| .. | .. |
|---|
| 23 | 23 | return 100 - ((bd->phy_stat0 >> 24) & 0xff); |
|---|
| 24 | 24 | } |
|---|
| 25 | 25 | |
|---|
| 26 | +struct wcn36xx_rate { |
|---|
| 27 | + u16 bitrate; |
|---|
| 28 | + u16 mcs_or_legacy_index; |
|---|
| 29 | + enum mac80211_rx_encoding encoding; |
|---|
| 30 | + enum mac80211_rx_encoding_flags encoding_flags; |
|---|
| 31 | + enum rate_info_bw bw; |
|---|
| 32 | +}; |
|---|
| 33 | + |
|---|
| 34 | +/* Buffer descriptor rx_ch field is limited to 5-bit (4+1), a mapping is used |
|---|
| 35 | + * for 11A Channels. |
|---|
| 36 | + */ |
|---|
| 37 | +static const u8 ab_rx_ch_map[] = { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, |
|---|
| 38 | + 108, 112, 116, 120, 124, 128, 132, 136, 140, |
|---|
| 39 | + 149, 153, 157, 161, 165, 144 }; |
|---|
| 40 | + |
|---|
| 41 | +static const struct wcn36xx_rate wcn36xx_rate_table[] = { |
|---|
| 42 | + /* 11b rates */ |
|---|
| 43 | + { 10, 0, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 44 | + { 20, 1, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 45 | + { 55, 2, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 46 | + { 110, 3, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 47 | + |
|---|
| 48 | + /* 11b SP (short preamble) */ |
|---|
| 49 | + { 10, 0, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 }, |
|---|
| 50 | + { 20, 1, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 }, |
|---|
| 51 | + { 55, 2, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 }, |
|---|
| 52 | + { 110, 3, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 }, |
|---|
| 53 | + |
|---|
| 54 | + /* 11ag */ |
|---|
| 55 | + { 60, 4, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 56 | + { 90, 5, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 57 | + { 120, 6, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 58 | + { 180, 7, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 59 | + { 240, 8, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 60 | + { 360, 9, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 61 | + { 480, 10, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 62 | + { 540, 11, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, |
|---|
| 63 | + |
|---|
| 64 | + /* 11n */ |
|---|
| 65 | + { 65, 0, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 66 | + { 130, 1, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 67 | + { 195, 2, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 68 | + { 260, 3, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 69 | + { 390, 4, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 70 | + { 520, 5, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 71 | + { 585, 6, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 72 | + { 650, 7, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 73 | + |
|---|
| 74 | + /* 11n SGI */ |
|---|
| 75 | + { 72, 0, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, |
|---|
| 76 | + { 144, 1, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, |
|---|
| 77 | + { 217, 2, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, |
|---|
| 78 | + { 289, 3, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, |
|---|
| 79 | + { 434, 4, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, |
|---|
| 80 | + { 578, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, |
|---|
| 81 | + { 650, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, |
|---|
| 82 | + { 722, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, |
|---|
| 83 | + |
|---|
| 84 | + /* 11n GF (greenfield) */ |
|---|
| 85 | + { 65, 0, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, |
|---|
| 86 | + { 130, 1, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, |
|---|
| 87 | + { 195, 2, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, |
|---|
| 88 | + { 260, 3, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, |
|---|
| 89 | + { 390, 4, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, |
|---|
| 90 | + { 520, 5, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, |
|---|
| 91 | + { 585, 6, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, |
|---|
| 92 | + { 650, 7, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, |
|---|
| 93 | + |
|---|
| 94 | + /* 11n CB (channel bonding) */ |
|---|
| 95 | + { 135, 0, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 96 | + { 270, 1, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 97 | + { 405, 2, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 98 | + { 540, 3, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 99 | + { 810, 4, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 100 | + { 1080, 5, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 101 | + { 1215, 6, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 102 | + { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 103 | + |
|---|
| 104 | + /* 11n CB + SGI */ |
|---|
| 105 | + { 150, 0, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 106 | + { 300, 1, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 107 | + { 450, 2, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 108 | + { 600, 3, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 109 | + { 900, 4, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 110 | + { 1200, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 111 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 112 | + { 1500, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 113 | + |
|---|
| 114 | + /* 11n GF + CB */ |
|---|
| 115 | + { 135, 0, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, |
|---|
| 116 | + { 270, 1, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, |
|---|
| 117 | + { 405, 2, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, |
|---|
| 118 | + { 540, 3, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, |
|---|
| 119 | + { 810, 4, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, |
|---|
| 120 | + { 1080, 5, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, |
|---|
| 121 | + { 1215, 6, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, |
|---|
| 122 | + { 1350, 7, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, |
|---|
| 123 | + |
|---|
| 124 | + /* 11ac reserved indices */ |
|---|
| 125 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 126 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 127 | + |
|---|
| 128 | + /* 11ac 20 MHz 800ns GI MCS 0-8 */ |
|---|
| 129 | + { 65, 0, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 130 | + { 130, 1, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 131 | + { 195, 2, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 132 | + { 260, 3, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 133 | + { 390, 4, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 134 | + { 520, 5, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 135 | + { 585, 6, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 136 | + { 650, 7, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 137 | + { 780, 8, RX_ENC_HT, 0, RATE_INFO_BW_20 }, |
|---|
| 138 | + |
|---|
| 139 | + /* 11ac reserved indices */ |
|---|
| 140 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 141 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 142 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 143 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 144 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 145 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 146 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 147 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 148 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 149 | + |
|---|
| 150 | + /* 11ac 20 MHz 400ns SGI MCS 6-8 */ |
|---|
| 151 | + { 655, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, |
|---|
| 152 | + { 722, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, |
|---|
| 153 | + { 866, 8, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, |
|---|
| 154 | + |
|---|
| 155 | + /* 11ac reserved indices */ |
|---|
| 156 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 157 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 158 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 159 | + |
|---|
| 160 | + /* 11ac 40 MHz 800ns GI MCS 0-9 */ |
|---|
| 161 | + { 135, 0, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 162 | + { 270, 1, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 163 | + { 405, 2, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 164 | + { 540, 3, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 165 | + { 810, 4, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 166 | + { 1080, 5, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 167 | + { 1215, 6, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 168 | + { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 169 | + { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 170 | + { 1620, 8, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 171 | + { 1800, 9, RX_ENC_HT, 0, RATE_INFO_BW_40 }, |
|---|
| 172 | + |
|---|
| 173 | + /* 11ac reserved indices */ |
|---|
| 174 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 175 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 176 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 177 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 178 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 179 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 180 | + |
|---|
| 181 | + /* 11ac 40 MHz 400ns SGI MCS 5-7 */ |
|---|
| 182 | + { 1200, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 183 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 184 | + { 1500, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 185 | + |
|---|
| 186 | + /* 11ac reserved index */ |
|---|
| 187 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 188 | + |
|---|
| 189 | + /* 11ac 40 MHz 400ns SGI MCS 5-7 */ |
|---|
| 190 | + { 1800, 8, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 191 | + { 2000, 9, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 192 | + |
|---|
| 193 | + /* 11ac reserved index */ |
|---|
| 194 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 195 | + |
|---|
| 196 | + /* 11ac 80 MHz 800ns GI MCS 0-7 */ |
|---|
| 197 | + { 292, 0, RX_ENC_HT, 0, RATE_INFO_BW_80}, |
|---|
| 198 | + { 585, 1, RX_ENC_HT, 0, RATE_INFO_BW_80}, |
|---|
| 199 | + { 877, 2, RX_ENC_HT, 0, RATE_INFO_BW_80}, |
|---|
| 200 | + { 1170, 3, RX_ENC_HT, 0, RATE_INFO_BW_80}, |
|---|
| 201 | + { 1755, 4, RX_ENC_HT, 0, RATE_INFO_BW_80}, |
|---|
| 202 | + { 2340, 5, RX_ENC_HT, 0, RATE_INFO_BW_80}, |
|---|
| 203 | + { 2632, 6, RX_ENC_HT, 0, RATE_INFO_BW_80}, |
|---|
| 204 | + { 2925, 7, RX_ENC_HT, 0, RATE_INFO_BW_80}, |
|---|
| 205 | + |
|---|
| 206 | + /* 11 ac reserved index */ |
|---|
| 207 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 208 | + |
|---|
| 209 | + /* 11ac 80 MHz 800 ns GI MCS 8-9 */ |
|---|
| 210 | + { 3510, 8, RX_ENC_HT, 0, RATE_INFO_BW_80}, |
|---|
| 211 | + { 3900, 9, RX_ENC_HT, 0, RATE_INFO_BW_80}, |
|---|
| 212 | + |
|---|
| 213 | + /* 11 ac reserved indices */ |
|---|
| 214 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 215 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 216 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 217 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 218 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 219 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 220 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 221 | + |
|---|
| 222 | + /* 11ac 80 MHz 400 ns SGI MCS 6-7 */ |
|---|
| 223 | + { 2925, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 }, |
|---|
| 224 | + { 3250, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 }, |
|---|
| 225 | + |
|---|
| 226 | + /* 11ac reserved index */ |
|---|
| 227 | + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, |
|---|
| 228 | + |
|---|
| 229 | + /* 11ac 80 MHz 400ns SGI MCS 8-9 */ |
|---|
| 230 | + { 3900, 8, RX_ENC_VHT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 }, |
|---|
| 231 | + { 4333, 9, RX_ENC_VHT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 }, |
|---|
| 232 | +}; |
|---|
| 233 | + |
|---|
| 26 | 234 | int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) |
|---|
| 27 | 235 | { |
|---|
| 28 | 236 | struct ieee80211_rx_status status; |
|---|
| 237 | + const struct wcn36xx_rate *rate; |
|---|
| 29 | 238 | struct ieee80211_hdr *hdr; |
|---|
| 30 | 239 | struct wcn36xx_rx_bd *bd; |
|---|
| 31 | 240 | u16 fc, sn; |
|---|
| .. | .. |
|---|
| 49 | 258 | fc = __le16_to_cpu(hdr->frame_control); |
|---|
| 50 | 259 | sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); |
|---|
| 51 | 260 | |
|---|
| 52 | | - /* When scanning associate beacons to this */ |
|---|
| 53 | | - if (ieee80211_is_beacon(hdr->frame_control) && wcn->scan_freq) { |
|---|
| 54 | | - status.freq = wcn->scan_freq; |
|---|
| 55 | | - status.band = wcn->scan_band; |
|---|
| 56 | | - } else { |
|---|
| 57 | | - status.freq = WCN36XX_CENTER_FREQ(wcn); |
|---|
| 58 | | - status.band = WCN36XX_BAND(wcn); |
|---|
| 59 | | - } |
|---|
| 60 | | - |
|---|
| 61 | 261 | status.mactime = 10; |
|---|
| 62 | 262 | status.signal = -get_rssi0(bd); |
|---|
| 63 | 263 | status.antenna = 1; |
|---|
| 64 | | - status.rate_idx = 1; |
|---|
| 65 | 264 | status.flag = 0; |
|---|
| 66 | 265 | status.rx_flags = 0; |
|---|
| 67 | 266 | status.flag |= RX_FLAG_IV_STRIPPED | |
|---|
| .. | .. |
|---|
| 69 | 268 | RX_FLAG_DECRYPTED; |
|---|
| 70 | 269 | |
|---|
| 71 | 270 | wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag); |
|---|
| 271 | + |
|---|
| 272 | + if (bd->scan_learn) { |
|---|
| 273 | + /* If packet originate from hardware scanning, extract the |
|---|
| 274 | + * band/channel from bd descriptor. |
|---|
| 275 | + */ |
|---|
| 276 | + u8 hwch = (bd->reserved0 << 4) + bd->rx_ch; |
|---|
| 277 | + |
|---|
| 278 | + if (bd->rf_band != 1 && hwch <= sizeof(ab_rx_ch_map) && hwch >= 1) { |
|---|
| 279 | + status.band = NL80211_BAND_5GHZ; |
|---|
| 280 | + status.freq = ieee80211_channel_to_frequency(ab_rx_ch_map[hwch - 1], |
|---|
| 281 | + status.band); |
|---|
| 282 | + } else { |
|---|
| 283 | + status.band = NL80211_BAND_2GHZ; |
|---|
| 284 | + status.freq = ieee80211_channel_to_frequency(hwch, status.band); |
|---|
| 285 | + } |
|---|
| 286 | + } else { |
|---|
| 287 | + status.band = WCN36XX_BAND(wcn); |
|---|
| 288 | + status.freq = WCN36XX_CENTER_FREQ(wcn); |
|---|
| 289 | + } |
|---|
| 290 | + |
|---|
| 291 | + if (bd->rate_id < ARRAY_SIZE(wcn36xx_rate_table)) { |
|---|
| 292 | + rate = &wcn36xx_rate_table[bd->rate_id]; |
|---|
| 293 | + status.encoding = rate->encoding; |
|---|
| 294 | + status.enc_flags = rate->encoding_flags; |
|---|
| 295 | + status.bw = rate->bw; |
|---|
| 296 | + status.rate_idx = rate->mcs_or_legacy_index; |
|---|
| 297 | + status.nss = 1; |
|---|
| 298 | + |
|---|
| 299 | + if (status.band == NL80211_BAND_5GHZ && |
|---|
| 300 | + status.encoding == RX_ENC_LEGACY && |
|---|
| 301 | + status.rate_idx >= 4) { |
|---|
| 302 | + /* no dsss rates in 5Ghz rates table */ |
|---|
| 303 | + status.rate_idx -= 4; |
|---|
| 304 | + } |
|---|
| 305 | + } else { |
|---|
| 306 | + status.encoding = 0; |
|---|
| 307 | + status.bw = 0; |
|---|
| 308 | + status.enc_flags = 0; |
|---|
| 309 | + status.rate_idx = 0; |
|---|
| 310 | + } |
|---|
| 311 | + |
|---|
| 312 | + if (ieee80211_is_beacon(hdr->frame_control) || |
|---|
| 313 | + ieee80211_is_probe_resp(hdr->frame_control)) |
|---|
| 314 | + status.boottime_ns = ktime_get_boottime_ns(); |
|---|
| 72 | 315 | |
|---|
| 73 | 316 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); |
|---|
| 74 | 317 | |
|---|
| .. | .. |
|---|
| 100 | 343 | bd->pdu.mpdu_header_off; |
|---|
| 101 | 344 | bd->pdu.mpdu_len = len; |
|---|
| 102 | 345 | bd->pdu.tid = tid; |
|---|
| 103 | | - bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS; |
|---|
| 104 | 346 | } |
|---|
| 105 | 347 | |
|---|
| 106 | 348 | static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, |
|---|
| .. | .. |
|---|
| 160 | 402 | bool bcast) |
|---|
| 161 | 403 | { |
|---|
| 162 | 404 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
|---|
| 405 | + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
|---|
| 163 | 406 | struct ieee80211_vif *vif = NULL; |
|---|
| 164 | 407 | struct wcn36xx_vif *__vif_priv = NULL; |
|---|
| 165 | | - bool is_data_qos; |
|---|
| 408 | + bool is_data_qos = ieee80211_is_data_qos(hdr->frame_control); |
|---|
| 409 | + u16 tid = 0; |
|---|
| 166 | 410 | |
|---|
| 167 | 411 | bd->bd_rate = WCN36XX_BD_RATE_DATA; |
|---|
| 168 | 412 | |
|---|
| .. | .. |
|---|
| 191 | 435 | bd->dpu_sign = __vif_priv->self_ucast_dpu_sign; |
|---|
| 192 | 436 | } |
|---|
| 193 | 437 | |
|---|
| 194 | | - if (ieee80211_is_nullfunc(hdr->frame_control) || |
|---|
| 195 | | - (sta_priv && !sta_priv->is_data_encrypted)) |
|---|
| 438 | + if (is_data_qos) { |
|---|
| 439 | + tid = ieee80211_get_tid(hdr); |
|---|
| 440 | + /* TID->QID is one-to-one mapping */ |
|---|
| 441 | + bd->queue_id = tid; |
|---|
| 442 | + bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS; |
|---|
| 443 | + } else { |
|---|
| 444 | + bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS; |
|---|
| 445 | + } |
|---|
| 446 | + |
|---|
| 447 | + if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT || |
|---|
| 448 | + (sta_priv && !sta_priv->is_data_encrypted)) { |
|---|
| 196 | 449 | bd->dpu_ne = 1; |
|---|
| 450 | + } |
|---|
| 451 | + |
|---|
| 452 | + if (ieee80211_is_any_nullfunc(hdr->frame_control)) { |
|---|
| 453 | + /* Don't use a regular queue for null packet (no ampdu) */ |
|---|
| 454 | + bd->queue_id = WCN36XX_TX_U_WQ_ID; |
|---|
| 455 | + bd->bd_rate = WCN36XX_BD_RATE_CTRL; |
|---|
| 456 | + if (ieee80211_is_qos_nullfunc(hdr->frame_control)) |
|---|
| 457 | + bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_HOST; |
|---|
| 458 | + } |
|---|
| 197 | 459 | |
|---|
| 198 | 460 | if (bcast) { |
|---|
| 199 | 461 | bd->ub = 1; |
|---|
| .. | .. |
|---|
| 201 | 463 | } |
|---|
| 202 | 464 | *vif_priv = __vif_priv; |
|---|
| 203 | 465 | |
|---|
| 204 | | - is_data_qos = ieee80211_is_data_qos(hdr->frame_control); |
|---|
| 205 | | - |
|---|
| 206 | 466 | wcn36xx_set_tx_pdu(bd, |
|---|
| 207 | 467 | is_data_qos ? |
|---|
| 208 | 468 | sizeof(struct ieee80211_qos_hdr) : |
|---|
| 209 | 469 | sizeof(struct ieee80211_hdr_3addr), |
|---|
| 210 | | - skb->len, sta_priv ? sta_priv->tid : 0); |
|---|
| 470 | + skb->len, tid); |
|---|
| 211 | 471 | |
|---|
| 212 | 472 | if (sta_priv && is_data_qos) |
|---|
| 213 | 473 | wcn36xx_tx_start_ampdu(wcn, sta_priv, skb); |
|---|
| .. | .. |
|---|
| 254 | 514 | bd->queue_id = WCN36XX_TX_U_WQ_ID; |
|---|
| 255 | 515 | *vif_priv = __vif_priv; |
|---|
| 256 | 516 | |
|---|
| 517 | + bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS; |
|---|
| 518 | + |
|---|
| 257 | 519 | wcn36xx_set_tx_pdu(bd, |
|---|
| 258 | 520 | ieee80211_is_data_qos(hdr->frame_control) ? |
|---|
| 259 | 521 | sizeof(struct ieee80211_qos_hdr) : |
|---|
| .. | .. |
|---|
| 268 | 530 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
|---|
| 269 | 531 | struct wcn36xx_vif *vif_priv = NULL; |
|---|
| 270 | 532 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
|---|
| 271 | | - unsigned long flags; |
|---|
| 272 | 533 | bool is_low = ieee80211_is_data(hdr->frame_control); |
|---|
| 273 | 534 | bool bcast = is_broadcast_ether_addr(hdr->addr1) || |
|---|
| 274 | 535 | is_multicast_ether_addr(hdr->addr1); |
|---|
| 536 | + bool ack_ind = (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) && |
|---|
| 537 | + !(info->flags & IEEE80211_TX_CTL_NO_ACK); |
|---|
| 275 | 538 | struct wcn36xx_tx_bd bd; |
|---|
| 276 | 539 | int ret; |
|---|
| 277 | 540 | |
|---|
| .. | .. |
|---|
| 287 | 550 | |
|---|
| 288 | 551 | bd.dpu_rf = WCN36XX_BMU_WQ_TX; |
|---|
| 289 | 552 | |
|---|
| 290 | | - bd.tx_comp = !!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS); |
|---|
| 291 | | - if (bd.tx_comp) { |
|---|
| 553 | + if (unlikely(ack_ind)) { |
|---|
| 292 | 554 | wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n"); |
|---|
| 293 | | - spin_lock_irqsave(&wcn->dxe_lock, flags); |
|---|
| 294 | | - if (wcn->tx_ack_skb) { |
|---|
| 295 | | - spin_unlock_irqrestore(&wcn->dxe_lock, flags); |
|---|
| 296 | | - wcn36xx_warn("tx_ack_skb already set\n"); |
|---|
| 297 | | - return -EINVAL; |
|---|
| 298 | | - } |
|---|
| 299 | | - |
|---|
| 300 | | - wcn->tx_ack_skb = skb; |
|---|
| 301 | | - spin_unlock_irqrestore(&wcn->dxe_lock, flags); |
|---|
| 302 | 555 | |
|---|
| 303 | 556 | /* Only one at a time is supported by fw. Stop the TX queues |
|---|
| 304 | 557 | * until the ack status gets back. |
|---|
| 305 | | - * |
|---|
| 306 | | - * TODO: Add watchdog in case FW does not answer |
|---|
| 307 | 558 | */ |
|---|
| 308 | 559 | ieee80211_stop_queues(wcn->hw); |
|---|
| 560 | + |
|---|
| 561 | + /* Request ack indication from the firmware */ |
|---|
| 562 | + bd.tx_comp = 1; |
|---|
| 309 | 563 | } |
|---|
| 310 | 564 | |
|---|
| 311 | 565 | /* Data frames served first*/ |
|---|
| .. | .. |
|---|
| 319 | 573 | bd.tx_bd_sign = 0xbdbdbdbd; |
|---|
| 320 | 574 | |
|---|
| 321 | 575 | ret = wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low); |
|---|
| 322 | | - if (ret && bd.tx_comp) { |
|---|
| 323 | | - /* If the skb has not been transmitted, |
|---|
| 324 | | - * don't keep a reference to it. |
|---|
| 325 | | - */ |
|---|
| 326 | | - spin_lock_irqsave(&wcn->dxe_lock, flags); |
|---|
| 327 | | - wcn->tx_ack_skb = NULL; |
|---|
| 328 | | - spin_unlock_irqrestore(&wcn->dxe_lock, flags); |
|---|
| 329 | | - |
|---|
| 576 | + if (unlikely(ret && ack_ind)) { |
|---|
| 577 | + /* If the skb has not been transmitted, resume TX queue */ |
|---|
| 330 | 578 | ieee80211_wake_queues(wcn->hw); |
|---|
| 331 | 579 | } |
|---|
| 332 | 580 | |
|---|