ath10k: handle WMI debug print events
[cascardo/linux.git] / drivers / net / wireless / ath / ath10k / wmi.c
index c654137..f992570 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <linux/skbuff.h>
+#include <linux/ctype.h>
 
 #include "core.h"
 #include "htc.h"
@@ -875,6 +876,7 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
        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_channel *ch;
        struct ieee80211_hdr *hdr;
        u32 rx_status;
        u32 channel;
@@ -927,7 +929,25 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
        if (rx_status & WMI_RX_STATUS_ERR_MIC)
                status->flag |= RX_FLAG_MMIC_ERROR;
 
-       status->band = phy_mode_to_band(phy_mode);
+       /* HW can Rx CCK rates on 5GHz. In that case phy_mode is set to
+        * MODE_11B. This means phy_mode is not a reliable source for the band
+        * of mgmt rx. */
+
+       ch = ar->scan_channel;
+       if (!ch)
+               ch = ar->rx_channel;
+
+       if (ch) {
+               status->band = ch->band;
+
+               if (phy_mode == MODE_11B &&
+                   status->band == IEEE80211_BAND_5GHZ)
+                       ath10k_dbg(ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n");
+       } else {
+               ath10k_warn("using (unreliable) phy_mode to extract band for mgmt rx\n");
+               status->band = phy_mode_to_band(phy_mode);
+       }
+
        status->freq = ieee80211_channel_to_frequency(channel, status->band);
        status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR;
        status->rate_idx = get_rate_idx(rate, status->band);
@@ -937,7 +957,11 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
        hdr = (struct ieee80211_hdr *)skb->data;
        fc = le16_to_cpu(hdr->frame_control);
 
-       if (fc & IEEE80211_FCTL_PROTECTED) {
+       /* FW delivers WEP Shared Auth frame with Protected Bit set and
+        * encrypted payload. However in case of PMF it delivers decrypted
+        * frames with Protected Bit set. */
+       if (ieee80211_has_protected(hdr->frame_control) &&
+           !ieee80211_is_auth(hdr->frame_control)) {
                status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED |
                                RX_FLAG_MMIC_STRIPPED;
                hdr->frame_control = __cpu_to_le16(fc &
@@ -1653,9 +1677,37 @@ static void ath10k_wmi_event_profile_match(struct ath10k *ar,
 }
 
 static void ath10k_wmi_event_debug_print(struct ath10k *ar,
-                                 struct sk_buff *skb)
+                                        struct sk_buff *skb)
 {
-       ath10k_dbg(ATH10K_DBG_WMI, "WMI_DEBUG_PRINT_EVENTID\n");
+       char buf[101], c;
+       int i;
+
+       for (i = 0; i < sizeof(buf) - 1; i++) {
+               if (i >= skb->len)
+                       break;
+
+               c = skb->data[i];
+
+               if (c == '\0')
+                       break;
+
+               if (isascii(c) && isprint(c))
+                       buf[i] = c;
+               else
+                       buf[i] = '.';
+       }
+
+       if (i == sizeof(buf) - 1)
+               ath10k_warn("wmi debug print truncated: %d\n", skb->len);
+
+       /* for some reason the debug prints end with \n, remove that */
+       if (skb->data[i - 1] == '\n')
+               i--;
+
+       /* the last byte is always reserved for the null character */
+       buf[i] = '\0';
+
+       ath10k_dbg(ATH10K_DBG_WMI, "wmi event debug print '%s'\n", buf);
 }
 
 static void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb)
@@ -2991,7 +3043,7 @@ int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
        cmd = (struct wmi_vdev_up_cmd *)skb->data;
        cmd->vdev_id       = __cpu_to_le32(vdev_id);
        cmd->vdev_assoc_id = __cpu_to_le32(aid);
-       memcpy(&cmd->vdev_bssid.addr, bssid, 6);
+       memcpy(&cmd->vdev_bssid.addr, bssid, ETH_ALEN);
 
        ath10k_dbg(ATH10K_DBG_WMI,
                   "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n",
@@ -3159,7 +3211,7 @@ int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id,
        cmd->vdev_id     = __cpu_to_le32(vdev_id);
        cmd->param_id    = __cpu_to_le32(param_id);
        cmd->param_value = __cpu_to_le32(param_value);
-       memcpy(&cmd->peer_macaddr.addr, peer_addr, 6);
+       memcpy(&cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
 
        ath10k_dbg(ATH10K_DBG_WMI,
                   "wmi vdev %d peer 0x%pM set param %d value %d\n",