ath10k: adjust the RX packet pad offset at QCA99X0 4addr mode
authorYanbo Li <yanbol@qca.qualcomm.com>
Mon, 16 Nov 2015 20:22:02 +0000 (22:22 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Mon, 23 Nov 2015 15:12:18 +0000 (17:12 +0200)
The QCA99X0 4 addresses RX packets pad 2 bytes at the beginning of
MSDU instead the end of ieee80211 header to keep alignment. The currently RX
data path can't parse the header correctly in this case. This patch fixes it
for QCA99X0.

Signed-off-by: Yanbo Li <yanbol@qca.qualcomm.com>
[kvalo@qca.qualcomm.com: checkpatch fixes and naming changes]
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/hw.h

index dc4fc4e8d5eff6ac213a5c5f56421c779ddbf9e2..f128adbae4540c431a9882713c96e84dde7f870d 100644 (file)
@@ -58,6 +58,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
                .fw = {
                        .dir = QCA988X_HW_2_0_FW_DIR,
                        .fw = QCA988X_HW_2_0_FW_FILE,
@@ -75,6 +76,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
                .fw = {
                        .dir = QCA6174_HW_2_1_FW_DIR,
                        .fw = QCA6174_HW_2_1_FW_FILE,
@@ -92,6 +94,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
                .fw = {
                        .dir = QCA6174_HW_3_0_FW_DIR,
                        .fw = QCA6174_HW_3_0_FW_FILE,
@@ -109,6 +112,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
                .fw = {
                        /* uses same binaries as hw3.0 */
                        .dir = QCA6174_HW_3_0_FW_DIR,
@@ -128,6 +132,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .continuous_frag_desc = true,
                .channel_counters_freq_hz = 150000,
                .max_probe_resp_desc_thres = 24,
+               .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
                .fw = {
                        .dir = QCA99X0_HW_2_0_FW_DIR,
                        .fw = QCA99X0_HW_2_0_FW_FILE,
index c16f3484dc8a7313344585084257cfd39ea27c63..91a39878c873fd885fb4c7795aabc10aa625f260 100644 (file)
@@ -668,6 +668,9 @@ struct ath10k {
                 */
                u32 max_probe_resp_desc_thres;
 
+               /* The padding bytes's location is different on various chips */
+               enum ath10k_hw_4addr_pad hw_4addr_pad;
+
                struct ath10k_hw_params_fw {
                        const char *dir;
                        const char *fw;
index 396645b508e226ad884901a94eb06e6a35c3265e..b84727bcf2dad7f4c30a1c92ba0306f55a69e89d 100644 (file)
@@ -1114,7 +1114,20 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
         */
 
        /* pull decapped header and copy SA & DA */
-       hdr = (struct ieee80211_hdr *)msdu->data;
+       if ((ar->hw_params.hw_4addr_pad == ATH10K_HW_4ADDR_PAD_BEFORE) &&
+           ieee80211_has_a4(((struct ieee80211_hdr *)first_hdr)->frame_control)) {
+               /* The QCA99X0 4 address mode pad 2 bytes at the
+                * beginning of MSDU
+                */
+               hdr = (struct ieee80211_hdr *)(msdu->data + 2);
+               /* The skb length need be extended 2 as the 2 bytes at the tail
+                * be excluded due to the padding
+                */
+               skb_put(msdu, 2);
+       } else {
+               hdr = (struct ieee80211_hdr *)(msdu->data);
+       }
+
        hdr_len = ath10k_htt_rx_nwifi_hdrlen(ar, hdr);
        ether_addr_copy(da, ieee80211_get_DA(hdr));
        ether_addr_copy(sa, ieee80211_get_SA(hdr));
index 557d8d2d06aaeb8f41559d962ccfa09b718e2636..b99b691ccccc182f420f64de82a40bc02e80b228 100644 (file)
@@ -304,6 +304,11 @@ enum ath10k_hw_rate_cck {
        ATH10K_HW_RATE_CCK_SP_2M,
 };
 
+enum ath10k_hw_4addr_pad {
+       ATH10K_HW_4ADDR_PAD_AFTER,
+       ATH10K_HW_4ADDR_PAD_BEFORE,
+};
+
 /* Target specific defines for MAIN firmware */
 #define TARGET_NUM_VDEVS                       8
 #define TARGET_NUM_PEER_AST                    2