Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
0011  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
0013  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
0014  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 
0017 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0018 
0019 #include "txrx.h"
0020 
0021 static inline int get_rssi0(struct wcn36xx_rx_bd *bd)
0022 {
0023     return 100 - ((bd->phy_stat0 >> 24) & 0xff);
0024 }
0025 
0026 static inline int get_snr(struct wcn36xx_rx_bd *bd)
0027 {
0028     return ((bd->phy_stat1 >> 24) & 0xff);
0029 }
0030 
0031 struct wcn36xx_rate {
0032     u16 bitrate;
0033     u16 mcs_or_legacy_index;
0034     enum mac80211_rx_encoding encoding;
0035     enum mac80211_rx_encoding_flags encoding_flags;
0036     enum rate_info_bw bw;
0037 };
0038 
0039 /* Buffer descriptor rx_ch field is limited to 5-bit (4+1), a mapping is used
0040  * for 11A Channels.
0041  */
0042 static const u8 ab_rx_ch_map[] = { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104,
0043                    108, 112, 116, 120, 124, 128, 132, 136, 140,
0044                    149, 153, 157, 161, 165, 144 };
0045 
0046 static const struct wcn36xx_rate wcn36xx_rate_table[] = {
0047     /* 11b rates */
0048     {  10, 0, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0049     {  20, 1, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0050     {  55, 2, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0051     { 110, 3, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0052 
0053     /* 11b SP (short preamble) */
0054     {  10, 0, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 },
0055     {  20, 1, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 },
0056     {  55, 2, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 },
0057     { 110, 3, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 },
0058 
0059     /* 11ag */
0060     {  60, 4, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0061     {  90, 5, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0062     { 120, 6, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0063     { 180, 7, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0064     { 240, 8, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0065     { 360, 9, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0066     { 480, 10, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0067     { 540, 11, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
0068 
0069     /* 11n */
0070     {  65, 0, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0071     { 130, 1, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0072     { 195, 2, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0073     { 260, 3, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0074     { 390, 4, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0075     { 520, 5, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0076     { 585, 6, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0077     { 650, 7, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0078 
0079     /* 11n SGI */
0080     {  72, 0, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
0081     { 144, 1, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
0082     { 217, 2, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
0083     { 289, 3, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
0084     { 434, 4, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
0085     { 578, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
0086     { 650, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
0087     { 722, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
0088 
0089     /* 11n GF (greenfield) */
0090     {  65, 0, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
0091     { 130, 1, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
0092     { 195, 2, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
0093     { 260, 3, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
0094     { 390, 4, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
0095     { 520, 5, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
0096     { 585, 6, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
0097     { 650, 7, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 },
0098 
0099     /* 11n CB (channel bonding) */
0100     { 135, 0, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0101     { 270, 1, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0102     { 405, 2, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0103     { 540, 3, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0104     { 810, 4, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0105     { 1080, 5, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0106     { 1215, 6, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0107     { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0108 
0109     /* 11n CB + SGI */
0110     { 150, 0, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0111     { 300, 1, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0112     { 450, 2, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0113     { 600, 3, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0114     { 900, 4, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0115     { 1200, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0116     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0117     { 1500, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0118 
0119     /* 11n GF + CB */
0120     { 135, 0, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
0121     { 270, 1, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
0122     { 405, 2, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
0123     { 540, 3, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
0124     { 810, 4, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
0125     { 1080, 5, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
0126     { 1215, 6, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
0127     { 1350, 7, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 },
0128 
0129     /* 11ac reserved indices */
0130     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0131     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0132 
0133     /* 11ac 20 MHz 800ns GI MCS 0-8 */
0134     {   65, 0, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0135     {  130, 1, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0136     {  195, 2, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0137     {  260, 3, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0138     {  390, 4, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0139     {  520, 5, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0140     {  585, 6, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0141     {  650, 7, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0142     {  780, 8, RX_ENC_HT, 0, RATE_INFO_BW_20 },
0143 
0144     /* 11ac reserved indices */
0145     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0146     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0147     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0148     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0149     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0150     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0151     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0152     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0153     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0154 
0155     /* 11ac 20 MHz 400ns SGI MCS 6-8 */
0156     {  655, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
0157     {  722, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
0158     {  866, 8, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 },
0159 
0160     /* 11ac reserved indices */
0161     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0162     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0163     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0164 
0165     /* 11ac 40 MHz 800ns GI MCS 0-9 */
0166     {  135, 0, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0167     {  270, 1, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0168     {  405, 2, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0169     {  540, 3, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0170     {  810, 4, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0171     { 1080, 5, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0172     { 1215, 6, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0173     { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0174     { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0175     { 1620, 8, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0176     { 1800, 9, RX_ENC_HT, 0, RATE_INFO_BW_40 },
0177 
0178     /* 11ac reserved indices */
0179     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0180     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0181     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0182     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0183     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0184     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0185 
0186     /* 11ac 40 MHz 400ns SGI MCS 5-7 */
0187     { 1200, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0188     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0189     { 1500, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0190 
0191     /* 11ac reserved index */
0192     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0193 
0194     /* 11ac 40 MHz 400ns SGI MCS 5-7 */
0195     { 1800, 8, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0196     { 2000, 9, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0197 
0198     /* 11ac reserved index */
0199     { 1350, 6, RX_ENC_HT,  RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0200 
0201     /* 11ac 80 MHz 800ns GI MCS 0-7 */
0202     {  292, 0, RX_ENC_HT, 0, RATE_INFO_BW_80},
0203     {  585, 1, RX_ENC_HT, 0, RATE_INFO_BW_80},
0204     {  877, 2, RX_ENC_HT, 0, RATE_INFO_BW_80},
0205     { 1170, 3, RX_ENC_HT, 0, RATE_INFO_BW_80},
0206     { 1755, 4, RX_ENC_HT, 0, RATE_INFO_BW_80},
0207     { 2340, 5, RX_ENC_HT, 0, RATE_INFO_BW_80},
0208     { 2632, 6, RX_ENC_HT, 0, RATE_INFO_BW_80},
0209     { 2925, 7, RX_ENC_HT, 0, RATE_INFO_BW_80},
0210 
0211     /* 11 ac reserved index */
0212     { 1350, 6, RX_ENC_HT,  RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0213 
0214     /* 11ac 80 MHz 800 ns GI MCS 8-9 */
0215     { 3510, 8, RX_ENC_HT, 0, RATE_INFO_BW_80},
0216     { 3900, 9, RX_ENC_HT, 0, RATE_INFO_BW_80},
0217 
0218     /* 11 ac reserved indices */
0219     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0220     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0221     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0222     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0223     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0224     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0225     { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0226 
0227     /* 11ac 80 MHz 400 ns SGI MCS 6-7 */
0228     { 2925, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
0229     { 3250, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
0230 
0231     /* 11ac reserved index */
0232     { 1350, 6, RX_ENC_HT,  RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 },
0233 
0234     /* 11ac 80 MHz 400ns SGI MCS 8-9 */
0235     { 3900, 8, RX_ENC_VHT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
0236     { 4333, 9, RX_ENC_VHT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
0237 };
0238 
0239 static struct sk_buff *wcn36xx_unchain_msdu(struct sk_buff_head *amsdu)
0240 {
0241     struct sk_buff *skb, *first;
0242     int total_len = 0;
0243     int space;
0244 
0245     first = __skb_dequeue(amsdu);
0246 
0247     skb_queue_walk(amsdu, skb)
0248         total_len += skb->len;
0249 
0250     space = total_len - skb_tailroom(first);
0251     if (space > 0 && pskb_expand_head(first, 0, space, GFP_ATOMIC) < 0) {
0252         __skb_queue_head(amsdu, first);
0253         return NULL;
0254     }
0255 
0256     /* Walk list again, copying contents into msdu_head */
0257     while ((skb = __skb_dequeue(amsdu))) {
0258         skb_copy_from_linear_data(skb, skb_put(first, skb->len),
0259                       skb->len);
0260         dev_kfree_skb_irq(skb);
0261     }
0262 
0263     return first;
0264 }
0265 
0266 static void __skb_queue_purge_irq(struct sk_buff_head *list)
0267 {
0268     struct sk_buff *skb;
0269 
0270     while ((skb = __skb_dequeue(list)) != NULL)
0271         dev_kfree_skb_irq(skb);
0272 }
0273 
0274 static void wcn36xx_update_survey(struct wcn36xx *wcn, int rssi, int snr,
0275                   int band, int freq)
0276 {
0277     static struct ieee80211_channel *channel;
0278     struct ieee80211_supported_band *sband;
0279     int idx;
0280     int i;
0281 
0282     idx = 0;
0283     if (band == NL80211_BAND_5GHZ)
0284         idx = wcn->hw->wiphy->bands[NL80211_BAND_2GHZ]->n_channels;
0285 
0286     sband = wcn->hw->wiphy->bands[band];
0287     channel = sband->channels;
0288 
0289     for (i = 0; i < sband->n_channels; i++, channel++) {
0290         if (channel->center_freq == freq) {
0291             idx += i;
0292             break;
0293         }
0294     }
0295 
0296     spin_lock(&wcn->survey_lock);
0297     wcn->chan_survey[idx].rssi = rssi;
0298     wcn->chan_survey[idx].snr = snr;
0299     spin_unlock(&wcn->survey_lock);
0300 }
0301 
0302 int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
0303 {
0304     struct ieee80211_rx_status status;
0305     const struct wcn36xx_rate *rate;
0306     struct ieee80211_hdr *hdr;
0307     struct wcn36xx_rx_bd *bd;
0308     u16 fc, sn;
0309 
0310     /*
0311      * All fields must be 0, otherwise it can lead to
0312      * unexpected consequences.
0313      */
0314     memset(&status, 0, sizeof(status));
0315 
0316     bd = (struct wcn36xx_rx_bd *)skb->data;
0317     buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32));
0318     wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP,
0319              "BD   <<< ", (char *)bd,
0320              sizeof(struct wcn36xx_rx_bd));
0321 
0322     if (bd->pdu.mpdu_data_off <= bd->pdu.mpdu_header_off ||
0323         bd->pdu.mpdu_len < bd->pdu.mpdu_header_len)
0324         goto drop;
0325 
0326     if (bd->asf && !bd->esf) { /* chained A-MSDU chunks */
0327         /* Sanity check */
0328         if (bd->pdu.mpdu_data_off + bd->pdu.mpdu_len > WCN36XX_PKT_SIZE)
0329             goto drop;
0330 
0331         skb_put(skb, bd->pdu.mpdu_data_off + bd->pdu.mpdu_len);
0332         skb_pull(skb, bd->pdu.mpdu_data_off);
0333 
0334         /* Only set status for first chained BD (with mac header) */
0335         goto done;
0336     }
0337 
0338     if (bd->pdu.mpdu_header_off < sizeof(*bd) ||
0339         bd->pdu.mpdu_header_off + bd->pdu.mpdu_len > WCN36XX_PKT_SIZE)
0340         goto drop;
0341 
0342     skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len);
0343     skb_pull(skb, bd->pdu.mpdu_header_off);
0344 
0345     hdr = (struct ieee80211_hdr *) skb->data;
0346     fc = __le16_to_cpu(hdr->frame_control);
0347     sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl));
0348 
0349     status.mactime = 10;
0350     status.signal = -get_rssi0(bd);
0351     status.antenna = 1;
0352     status.flag = 0;
0353     status.rx_flags = 0;
0354     status.flag |= RX_FLAG_IV_STRIPPED |
0355                RX_FLAG_MMIC_STRIPPED |
0356                RX_FLAG_DECRYPTED;
0357 
0358     wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag);
0359 
0360     if (bd->scan_learn) {
0361         /* If packet originate from hardware scanning, extract the
0362          * band/channel from bd descriptor.
0363          */
0364         u8 hwch = (bd->reserved0 << 4) + bd->rx_ch;
0365 
0366         if (bd->rf_band != 1 && hwch <= sizeof(ab_rx_ch_map) && hwch >= 1) {
0367             status.band = NL80211_BAND_5GHZ;
0368             status.freq = ieee80211_channel_to_frequency(ab_rx_ch_map[hwch - 1],
0369                                      status.band);
0370         } else {
0371             status.band = NL80211_BAND_2GHZ;
0372             status.freq = ieee80211_channel_to_frequency(hwch, status.band);
0373         }
0374     } else {
0375         status.band = WCN36XX_BAND(wcn);
0376         status.freq = WCN36XX_CENTER_FREQ(wcn);
0377     }
0378 
0379     wcn36xx_update_survey(wcn, status.signal, get_snr(bd),
0380                   status.band, status.freq);
0381 
0382     if (bd->rate_id < ARRAY_SIZE(wcn36xx_rate_table)) {
0383         rate = &wcn36xx_rate_table[bd->rate_id];
0384         status.encoding = rate->encoding;
0385         status.enc_flags = rate->encoding_flags;
0386         status.bw = rate->bw;
0387         status.rate_idx = rate->mcs_or_legacy_index;
0388         status.nss = 1;
0389 
0390         if (status.band == NL80211_BAND_5GHZ &&
0391             status.encoding == RX_ENC_LEGACY &&
0392             status.rate_idx >= 4) {
0393             /* no dsss rates in 5Ghz rates table */
0394             status.rate_idx -= 4;
0395         }
0396     } else {
0397         status.encoding = 0;
0398         status.bw = 0;
0399         status.enc_flags = 0;
0400         status.rate_idx = 0;
0401     }
0402 
0403     if (ieee80211_is_beacon(hdr->frame_control) ||
0404         ieee80211_is_probe_resp(hdr->frame_control))
0405         status.boottime_ns = ktime_get_boottime_ns();
0406 
0407     memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
0408 
0409     if (ieee80211_is_beacon(hdr->frame_control)) {
0410         wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n",
0411                 skb, skb->len, fc, sn);
0412         wcn36xx_dbg_dump(WCN36XX_DBG_BEACON_DUMP, "SKB <<< ",
0413                  (char *)skb->data, skb->len);
0414     } else {
0415         wcn36xx_dbg(WCN36XX_DBG_RX, "rx skb %p len %d fc %04x sn %d\n",
0416                 skb, skb->len, fc, sn);
0417         wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, "SKB <<< ",
0418                  (char *)skb->data, skb->len);
0419     }
0420 
0421 done:
0422     /*  Chained AMSDU ? slow path */
0423     if (unlikely(bd->asf && !(bd->lsf && bd->esf))) {
0424         if (bd->esf && !skb_queue_empty(&wcn->amsdu)) {
0425             wcn36xx_err("Discarding non complete chain");
0426             __skb_queue_purge_irq(&wcn->amsdu);
0427         }
0428 
0429         __skb_queue_tail(&wcn->amsdu, skb);
0430 
0431         if (!bd->lsf)
0432             return 0; /* Not the last AMSDU, wait for more */
0433 
0434         skb = wcn36xx_unchain_msdu(&wcn->amsdu);
0435         if (!skb)
0436             goto drop;
0437     }
0438 
0439     ieee80211_rx_irqsafe(wcn->hw, skb);
0440 
0441     return 0;
0442 
0443 drop: /* drop everything */
0444     wcn36xx_err("Drop frame! skb:%p len:%u hoff:%u doff:%u asf=%u esf=%u lsf=%u\n",
0445             skb, bd->pdu.mpdu_len, bd->pdu.mpdu_header_off,
0446             bd->pdu.mpdu_data_off, bd->asf, bd->esf, bd->lsf);
0447 
0448     dev_kfree_skb_irq(skb);
0449     __skb_queue_purge_irq(&wcn->amsdu);
0450 
0451     return -EINVAL;
0452 }
0453 
0454 static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd,
0455                    u32 mpdu_header_len,
0456                    u32 len,
0457                    u16 tid)
0458 {
0459     bd->pdu.mpdu_header_len = mpdu_header_len;
0460     bd->pdu.mpdu_header_off = sizeof(*bd);
0461     bd->pdu.mpdu_data_off = bd->pdu.mpdu_header_len +
0462         bd->pdu.mpdu_header_off;
0463     bd->pdu.mpdu_len = len;
0464     bd->pdu.tid = tid;
0465 }
0466 
0467 static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn,
0468                           u8 *addr)
0469 {
0470     struct wcn36xx_vif *vif_priv = NULL;
0471     struct ieee80211_vif *vif = NULL;
0472     list_for_each_entry(vif_priv, &wcn->vif_list, list) {
0473             vif = wcn36xx_priv_to_vif(vif_priv);
0474             if (memcmp(vif->addr, addr, ETH_ALEN) == 0)
0475                 return vif_priv;
0476     }
0477     wcn36xx_warn("vif %pM not found\n", addr);
0478     return NULL;
0479 }
0480 
0481 static void wcn36xx_tx_start_ampdu(struct wcn36xx *wcn,
0482                    struct wcn36xx_sta *sta_priv,
0483                    struct sk_buff *skb)
0484 {
0485     struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
0486     struct ieee80211_sta *sta;
0487     u8 *qc, tid;
0488 
0489     if (!conf_is_ht(&wcn->hw->conf))
0490         return;
0491 
0492     sta = wcn36xx_priv_to_sta(sta_priv);
0493 
0494     if (WARN_ON(!ieee80211_is_data_qos(hdr->frame_control)))
0495         return;
0496 
0497     if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
0498         return;
0499 
0500     qc = ieee80211_get_qos_ctl(hdr);
0501     tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
0502 
0503     spin_lock(&sta_priv->ampdu_lock);
0504     if (sta_priv->ampdu_state[tid] != WCN36XX_AMPDU_NONE)
0505         goto out_unlock;
0506 
0507     if (sta_priv->non_agg_frame_ct++ >= WCN36XX_AMPDU_START_THRESH) {
0508         sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
0509         sta_priv->non_agg_frame_ct = 0;
0510         ieee80211_start_tx_ba_session(sta, tid, 0);
0511     }
0512 out_unlock:
0513     spin_unlock(&sta_priv->ampdu_lock);
0514 }
0515 
0516 static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
0517                 struct wcn36xx *wcn,
0518                 struct wcn36xx_vif **vif_priv,
0519                 struct wcn36xx_sta *sta_priv,
0520                 struct sk_buff *skb,
0521                 bool bcast)
0522 {
0523     struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
0524     struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
0525     struct ieee80211_vif *vif = NULL;
0526     struct wcn36xx_vif *__vif_priv = NULL;
0527     bool is_data_qos = ieee80211_is_data_qos(hdr->frame_control);
0528     u16 tid = 0;
0529 
0530     bd->bd_rate = WCN36XX_BD_RATE_DATA;
0531 
0532     /*
0533      * For not unicast frames mac80211 will not set sta pointer so use
0534      * self_sta_index instead.
0535      */
0536     if (sta_priv) {
0537         __vif_priv = sta_priv->vif;
0538         vif = wcn36xx_priv_to_vif(__vif_priv);
0539 
0540         bd->dpu_sign = sta_priv->ucast_dpu_sign;
0541         if (vif->type == NL80211_IFTYPE_STATION) {
0542             bd->sta_index = sta_priv->bss_sta_index;
0543             bd->dpu_desc_idx = sta_priv->bss_dpu_desc_index;
0544         } else if (vif->type == NL80211_IFTYPE_AP ||
0545                vif->type == NL80211_IFTYPE_ADHOC ||
0546                vif->type == NL80211_IFTYPE_MESH_POINT) {
0547             bd->sta_index = sta_priv->sta_index;
0548             bd->dpu_desc_idx = sta_priv->dpu_desc_index;
0549         }
0550     } else {
0551         __vif_priv = get_vif_by_addr(wcn, hdr->addr2);
0552         bd->sta_index = __vif_priv->self_sta_index;
0553         bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index;
0554         bd->dpu_sign = __vif_priv->self_ucast_dpu_sign;
0555     }
0556 
0557     if (is_data_qos) {
0558         tid = ieee80211_get_tid(hdr);
0559         /* TID->QID is one-to-one mapping */
0560         bd->queue_id = tid;
0561         bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS;
0562     } else {
0563         bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS;
0564     }
0565 
0566     if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT ||
0567         (sta_priv && !sta_priv->is_data_encrypted)) {
0568         bd->dpu_ne = 1;
0569     }
0570 
0571     if (ieee80211_is_any_nullfunc(hdr->frame_control)) {
0572         /* Don't use a regular queue for null packet (no ampdu) */
0573         bd->queue_id = WCN36XX_TX_U_WQ_ID;
0574         bd->bd_rate = WCN36XX_BD_RATE_CTRL;
0575         if (ieee80211_is_qos_nullfunc(hdr->frame_control))
0576             bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_HOST;
0577     }
0578 
0579     if (bcast) {
0580         bd->ub = 1;
0581         bd->ack_policy = 1;
0582     }
0583     *vif_priv = __vif_priv;
0584 
0585     wcn36xx_set_tx_pdu(bd,
0586                is_data_qos ?
0587                sizeof(struct ieee80211_qos_hdr) :
0588                sizeof(struct ieee80211_hdr_3addr),
0589                skb->len, tid);
0590 
0591     if (sta_priv && is_data_qos)
0592         wcn36xx_tx_start_ampdu(wcn, sta_priv, skb);
0593 }
0594 
0595 static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd,
0596                 struct wcn36xx *wcn,
0597                 struct wcn36xx_vif **vif_priv,
0598                 struct sk_buff *skb,
0599                 bool bcast)
0600 {
0601     struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
0602     struct wcn36xx_vif *__vif_priv =
0603         get_vif_by_addr(wcn, hdr->addr2);
0604     bd->sta_index = __vif_priv->self_sta_index;
0605     bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index;
0606     bd->dpu_ne = 1;
0607 
0608     /* default rate for unicast */
0609     if (ieee80211_is_mgmt(hdr->frame_control))
0610         bd->bd_rate = (WCN36XX_BAND(wcn) == NL80211_BAND_5GHZ) ?
0611             WCN36XX_BD_RATE_CTRL :
0612             WCN36XX_BD_RATE_MGMT;
0613     else if (ieee80211_is_ctl(hdr->frame_control))
0614         bd->bd_rate = WCN36XX_BD_RATE_CTRL;
0615     else
0616         wcn36xx_warn("frame control type unknown\n");
0617 
0618     /*
0619      * In joining state trick hardware that probe is sent as
0620      * unicast even if address is broadcast.
0621      */
0622     if (__vif_priv->is_joining &&
0623         ieee80211_is_probe_req(hdr->frame_control))
0624         bcast = false;
0625 
0626     if (bcast) {
0627         /* broadcast */
0628         bd->ub = 1;
0629         /* No ack needed not unicast */
0630         bd->ack_policy = 1;
0631         bd->queue_id = WCN36XX_TX_B_WQ_ID;
0632     } else
0633         bd->queue_id = WCN36XX_TX_U_WQ_ID;
0634     *vif_priv = __vif_priv;
0635 
0636     bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS;
0637 
0638     wcn36xx_set_tx_pdu(bd,
0639                ieee80211_is_data_qos(hdr->frame_control) ?
0640                sizeof(struct ieee80211_qos_hdr) :
0641                sizeof(struct ieee80211_hdr_3addr),
0642                skb->len, WCN36XX_TID);
0643 }
0644 
0645 int wcn36xx_start_tx(struct wcn36xx *wcn,
0646              struct wcn36xx_sta *sta_priv,
0647              struct sk_buff *skb)
0648 {
0649     struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
0650     struct wcn36xx_vif *vif_priv = NULL;
0651     struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
0652     bool is_low = ieee80211_is_data(hdr->frame_control);
0653     bool bcast = is_broadcast_ether_addr(hdr->addr1) ||
0654         is_multicast_ether_addr(hdr->addr1);
0655     bool ack_ind = (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) &&
0656                     !(info->flags & IEEE80211_TX_CTL_NO_ACK);
0657     struct wcn36xx_tx_bd bd;
0658     int ret;
0659 
0660     memset(&bd, 0, sizeof(bd));
0661 
0662     wcn36xx_dbg(WCN36XX_DBG_TX,
0663             "tx skb %p len %d fc %04x sn %d %s %s\n",
0664             skb, skb->len, __le16_to_cpu(hdr->frame_control),
0665             IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)),
0666             is_low ? "low" : "high", bcast ? "bcast" : "ucast");
0667 
0668     wcn36xx_dbg_dump(WCN36XX_DBG_TX_DUMP, "", skb->data, skb->len);
0669 
0670     bd.dpu_rf = WCN36XX_BMU_WQ_TX;
0671 
0672     if (unlikely(ack_ind)) {
0673         wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n");
0674 
0675         /* Only one at a time is supported by fw. Stop the TX queues
0676          * until the ack status gets back.
0677          */
0678         ieee80211_stop_queues(wcn->hw);
0679 
0680         /* Request ack indication from the firmware */
0681         bd.tx_comp = 1;
0682     }
0683 
0684     /* Data frames served first*/
0685     if (is_low)
0686         wcn36xx_set_tx_data(&bd, wcn, &vif_priv, sta_priv, skb, bcast);
0687     else
0688         /* MGMT and CTRL frames are handeld here*/
0689         wcn36xx_set_tx_mgmt(&bd, wcn, &vif_priv, skb, bcast);
0690 
0691     buff_to_be((u32 *)&bd, sizeof(bd)/sizeof(u32));
0692     bd.tx_bd_sign = 0xbdbdbdbd;
0693 
0694     ret = wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low);
0695     if (unlikely(ret && ack_ind)) {
0696         /* If the skb has not been transmitted, resume TX queue */
0697         ieee80211_wake_queues(wcn->hw);
0698     }
0699 
0700     return ret;
0701 }
0702 
0703 void wcn36xx_process_tx_rate(struct ani_global_class_a_stats_info *stats, struct rate_info *info)
0704 {
0705     /* tx_rate is in units of 500kbps; mac80211 wants them in 100kbps */
0706     if (stats->tx_rate_flags & HAL_TX_RATE_LEGACY)
0707         info->legacy = stats->tx_rate * 5;
0708 
0709     info->flags = 0;
0710     info->mcs = stats->mcs_index;
0711     info->nss = 1;
0712 
0713     if (stats->tx_rate_flags & (HAL_TX_RATE_HT20 | HAL_TX_RATE_HT40))
0714         info->flags |= RATE_INFO_FLAGS_MCS;
0715 
0716     if (stats->tx_rate_flags & (HAL_TX_RATE_VHT20 | HAL_TX_RATE_VHT40 | HAL_TX_RATE_VHT80))
0717         info->flags |= RATE_INFO_FLAGS_VHT_MCS;
0718 
0719     if (stats->tx_rate_flags & HAL_TX_RATE_SGI)
0720         info->flags |= RATE_INFO_FLAGS_SHORT_GI;
0721 
0722     if (stats->tx_rate_flags & (HAL_TX_RATE_HT20 | HAL_TX_RATE_VHT20))
0723         info->bw = RATE_INFO_BW_20;
0724 
0725     if (stats->tx_rate_flags & (HAL_TX_RATE_HT40 | HAL_TX_RATE_VHT40))
0726         info->bw = RATE_INFO_BW_40;
0727 
0728     if (stats->tx_rate_flags & HAL_TX_RATE_VHT80)
0729         info->bw = RATE_INFO_BW_80;
0730 }