blob: 41bb8c21144c0dd317e3b41d54573f2fbe51917f [file] [log] [blame]
Larry Finger94a79942011-08-23 19:00:42 -05001/******************************************************************************
2
3 Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of version 2 of the GNU General Public License as
7 published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc., 59
16 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 The full GNU General Public License is included in this distribution in the
19 file called LICENSE.
20
21 Contact Information:
22 James P. Ketrenos <ipw2100-admin@linux.intel.com>
23 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24
25******************************************************************************
26
27 Few modifications for Realtek's Wi-Fi drivers by
Andrea Merello559a4c32013-08-26 13:53:30 +020028 Andrea Merello <andrea.merello@gmail.com>
Larry Finger94a79942011-08-23 19:00:42 -050029
30 A special thanks goes to Realtek for their support !
31
32******************************************************************************/
33
34#include <linux/compiler.h>
35#include <linux/errno.h>
36#include <linux/if_arp.h>
37#include <linux/in6.h>
38#include <linux/in.h>
39#include <linux/ip.h>
40#include <linux/kernel.h>
41#include <linux/module.h>
42#include <linux/netdevice.h>
43#include <linux/pci.h>
44#include <linux/proc_fs.h>
45#include <linux/skbuff.h>
46#include <linux/slab.h>
47#include <linux/tcp.h>
48#include <linux/types.h>
Larry Finger94a79942011-08-23 19:00:42 -050049#include <linux/wireless.h>
50#include <linux/etherdevice.h>
Larry Fingerf38d2232011-08-25 11:48:28 -050051#include <linux/uaccess.h>
Larry Finger94a79942011-08-23 19:00:42 -050052#include <linux/if_vlan.h>
53
54#include "rtllib.h"
55
Larry Finger94a79942011-08-23 19:00:42 -050056/*
57
58
59802.11 Data Frame
60
61
Justin P. Mattockcd017122012-04-23 07:36:52 -070062802.11 frame_control for data frames - 2 bytes
Larry Finger94a79942011-08-23 19:00:42 -050063 ,-----------------------------------------------------------------------------------------.
64bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e |
65 |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
66val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x |
67 |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
68desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep |
Larry Fingerf38d2232011-08-25 11:48:28 -050069 | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | |
Larry Finger94a79942011-08-23 19:00:42 -050070 '-----------------------------------------------------------------------------------------'
Larry Fingerf38d2232011-08-25 11:48:28 -050071 /\
72 |
73802.11 Data Frame |
74 ,--------- 'ctrl' expands to >-----------'
75 |
Larry Finger94a79942011-08-23 19:00:42 -050076 ,--'---,-------------------------------------------------------------.
77Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
78 |------|------|---------|---------|---------|------|---------|------|
79Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
Larry Fingerf38d2232011-08-25 11:48:28 -050080 | | tion | (BSSID) | | | ence | data | |
81 `--------------------------------------------------| |------'
82Total: 28 non-data bytes `----.----'
83 |
Larry Finger94a79942011-08-23 19:00:42 -050084 .- 'Frame data' expands to <---------------------------'
85 |
86 V
87 ,---------------------------------------------------.
88Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
89 |------|------|---------|----------|------|---------|
90Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
Larry Fingerf38d2232011-08-25 11:48:28 -050091 | DSAP | SSAP | | | | Packet |
92 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
93 `-----------------------------------------| |
94Total: 8 non-data bytes `----.----'
95 |
Larry Finger94a79942011-08-23 19:00:42 -050096 .- 'IP Packet' expands, if WEP enabled, to <--'
97 |
98 V
99 ,-----------------------.
100Bytes | 4 | 0-2296 | 4 |
101 |-----|-----------|-----|
102Desc. | IV | Encrypted | ICV |
103 | | IP Packet | |
104 `-----------------------'
105Total: 8 non-data bytes
106
107
108802.3 Ethernet Data Frame
109
110 ,-----------------------------------------.
111Bytes | 6 | 6 | 2 | Variable | 4 |
112 |-------|-------|------|-----------|------|
113Desc. | Dest. | Source| Type | IP Packet | fcs |
Larry Fingerf38d2232011-08-25 11:48:28 -0500114 | MAC | MAC | | | |
Larry Finger94a79942011-08-23 19:00:42 -0500115 `-----------------------------------------'
116Total: 18 non-data bytes
117
118In the event that fragmentation is required, the incoming payload is split into
119N parts of size ieee->fts. The first fragment contains the SNAP header and the
120remaining packets are just data.
121
122If encryption is enabled, each fragment payload size is reduced by enough space
123to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
124So if you have 1500 bytes of payload with ieee->fts set to 500 without
125encryption it will take 3 frames. With WEP it will take 4 frames as the
126payload of each frame is reduced to 492 bytes.
127
128* SKB visualization
129*
130* ,- skb->data
131* |
Larry Fingerf38d2232011-08-25 11:48:28 -0500132* | ETHERNET HEADER ,-<-- PAYLOAD
133* | | 14 bytes from skb->data
Larry Finger94a79942011-08-23 19:00:42 -0500134* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
Larry Fingerf38d2232011-08-25 11:48:28 -0500135* | | | |
Larry Finger94a79942011-08-23 19:00:42 -0500136* |,-Dest.--. ,--Src.---. | | |
137* | 6 bytes| | 6 bytes | | | |
Larry Fingerf38d2232011-08-25 11:48:28 -0500138* v | | | | | |
139* 0 | v 1 | v | v 2
Larry Finger94a79942011-08-23 19:00:42 -0500140* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
Larry Fingerf38d2232011-08-25 11:48:28 -0500141* ^ | ^ | ^ |
142* | | | | | |
143* | | | | `T' <---- 2 bytes for Type
144* | | | |
Larry Finger94a79942011-08-23 19:00:42 -0500145* | | '---SNAP--' <-------- 6 bytes for SNAP
146* | |
147* `-IV--' <-------------------- 4 bytes for IV (WEP)
148*
149* SNAP HEADER
150*
151*/
152
153static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
154static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
155
156inline int rtllib_put_snap(u8 *data, u16 h_proto)
157{
158 struct rtllib_snap_hdr *snap;
159 u8 *oui;
160
161 snap = (struct rtllib_snap_hdr *)data;
162 snap->dsap = 0xaa;
163 snap->ssap = 0xaa;
164 snap->ctrl = 0x03;
165
166 if (h_proto == 0x8137 || h_proto == 0x80f3)
167 oui = P802_1H_OUI;
168 else
169 oui = RFC1042_OUI;
170 snap->oui[0] = oui[0];
171 snap->oui[1] = oui[1];
172 snap->oui[2] = oui[2];
173
Sean MacLennan9326c5c2014-05-28 11:19:00 -0400174 *(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
Larry Finger94a79942011-08-23 19:00:42 -0500175
176 return SNAP_SIZE + sizeof(u16);
177}
178
Larry Fingerf38d2232011-08-25 11:48:28 -0500179int rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag,
180 int hdr_len)
Larry Finger94a79942011-08-23 19:00:42 -0500181{
Sean MacLennan32c44cb2011-12-19 23:20:41 -0500182 struct lib80211_crypt_data *crypt = NULL;
Larry Finger94a79942011-08-23 19:00:42 -0500183 int res;
184
Sean MacLennan0ddcf5f2011-12-19 23:21:41 -0500185 crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
Larry Finger94a79942011-08-23 19:00:42 -0500186
Larry Fingerf38d2232011-08-25 11:48:28 -0500187 if (!(crypt && crypt->ops)) {
188 printk(KERN_INFO "=========>%s(), crypt is null\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500189 return -1;
190 }
Larry Finger94a79942011-08-23 19:00:42 -0500191 /* To encrypt, frame format is:
192 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
193
194 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
195 * call both MSDU and MPDU encryption functions from here. */
196 atomic_inc(&crypt->refcnt);
197 res = 0;
198 if (crypt->ops->encrypt_msdu)
199 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
200 if (res == 0 && crypt->ops->encrypt_mpdu)
201 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
202
203 atomic_dec(&crypt->refcnt);
204 if (res < 0) {
205 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
206 ieee->dev->name, frag->len);
207 ieee->ieee_stats.tx_discards++;
208 return -1;
209 }
210
211 return 0;
212}
213
214
Larry Fingerf38d2232011-08-25 11:48:28 -0500215void rtllib_txb_free(struct rtllib_txb *txb)
216{
Larry Finger94a79942011-08-23 19:00:42 -0500217 if (unlikely(!txb))
218 return;
219 kfree(txb);
220}
221
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500222static struct rtllib_txb *rtllib_alloc_txb(int nr_frags, int txb_size,
223 gfp_t gfp_mask)
Larry Finger94a79942011-08-23 19:00:42 -0500224{
Larry Finger94a79942011-08-23 19:00:42 -0500225 struct rtllib_txb *txb;
226 int i;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400227
Larry Fingerf38d2232011-08-25 11:48:28 -0500228 txb = kmalloc(sizeof(struct rtllib_txb) + (sizeof(u8 *) * nr_frags),
229 gfp_mask);
Larry Finger94a79942011-08-23 19:00:42 -0500230 if (!txb)
231 return NULL;
232
233 memset(txb, 0, sizeof(struct rtllib_txb));
234 txb->nr_frags = nr_frags;
Rashika Kheria198e0d12013-11-02 23:39:22 +0530235 txb->frag_size = cpu_to_le16(txb_size);
Larry Finger94a79942011-08-23 19:00:42 -0500236
237 for (i = 0; i < nr_frags; i++) {
Larry Finger94a79942011-08-23 19:00:42 -0500238 txb->fragments[i] = dev_alloc_skb(txb_size);
Larry Finger94a79942011-08-23 19:00:42 -0500239 if (unlikely(!txb->fragments[i])) {
240 i--;
241 break;
242 }
Larry Finger94a79942011-08-23 19:00:42 -0500243 memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb));
244 }
245 if (unlikely(i != nr_frags)) {
246 while (i >= 0)
247 dev_kfree_skb_any(txb->fragments[i--]);
248 kfree(txb);
249 return NULL;
250 }
251 return txb;
252}
253
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500254static int rtllib_classify(struct sk_buff *skb, u8 bIsAmsdu)
Larry Finger94a79942011-08-23 19:00:42 -0500255{
256 struct ethhdr *eth;
257 struct iphdr *ip;
258
259 eth = (struct ethhdr *)skb->data;
260 if (eth->h_proto != htons(ETH_P_IP))
261 return 0;
262
263 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA, skb->data, skb->len);
264 ip = ip_hdr(skb);
265 switch (ip->tos & 0xfc) {
266 case 0x20:
267 return 2;
268 case 0x40:
269 return 1;
270 case 0x60:
271 return 3;
272 case 0x80:
273 return 4;
274 case 0xa0:
275 return 5;
276 case 0xc0:
277 return 6;
278 case 0xe0:
279 return 7;
280 default:
281 return 0;
282 }
283}
284
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500285static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee,
286 struct sk_buff *skb,
287 struct cb_desc *tcb_desc)
Larry Finger94a79942011-08-23 19:00:42 -0500288{
Larry Finger7796d932011-07-18 20:22:19 -0500289 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
Larry Finger60554f22011-07-18 20:10:03 -0500290 struct tx_ts_record *pTxTs = NULL;
Edgar Neukirchner4d0c8ee2012-10-31 15:48:58 +0100291 struct rtllib_hdr_1addr *hdr = (struct rtllib_hdr_1addr *)skb->data;
Larry Finger94a79942011-08-23 19:00:42 -0500292
Larry Fingerf38d2232011-08-25 11:48:28 -0500293 if (rtllib_act_scanning(ieee, false))
Larry Finger94a79942011-08-23 19:00:42 -0500294 return;
295
Larry Fingerf38d2232011-08-25 11:48:28 -0500296 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
Larry Finger94a79942011-08-23 19:00:42 -0500297 return;
298 if (!IsQoSDataFrame(skb->data))
299 return;
Joe Perches14fc4232012-05-08 10:11:56 -0700300 if (is_multicast_ether_addr(hdr->addr1))
Larry Finger94a79942011-08-23 19:00:42 -0500301 return;
Larry Finger94a79942011-08-23 19:00:42 -0500302
Larry Fingerf38d2232011-08-25 11:48:28 -0500303 if (tcb_desc->bdhcp || ieee->CntAfterLink < 2)
Larry Finger94a79942011-08-23 19:00:42 -0500304 return;
305
306 if (pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION)
307 return;
308
309 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
310 return;
Larry Fingerf38d2232011-08-25 11:48:28 -0500311 if (pHTInfo->bCurrentAMPDUEnable) {
312 if (!GetTs(ieee, (struct ts_common_info **)(&pTxTs), hdr->addr1,
313 skb->priority, TX_DIR, true)) {
314 printk(KERN_INFO "%s: can't get TS\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500315 return;
316 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500317 if (pTxTs->TxAdmittedBARecord.bValid == false) {
318 if (ieee->wpa_ie_len && (ieee->pairwise_key_type ==
319 KEY_TYPE_NA)) {
Larry Finger94a79942011-08-23 19:00:42 -0500320 ;
Larry Fingerf38d2232011-08-25 11:48:28 -0500321 } else if (tcb_desc->bdhcp == 1) {
Larry Finger94a79942011-08-23 19:00:42 -0500322 ;
Larry Fingerf38d2232011-08-25 11:48:28 -0500323 } else if (!pTxTs->bDisable_AddBa) {
Larry Finger94a79942011-08-23 19:00:42 -0500324 TsStartAddBaProcess(ieee, pTxTs);
325 }
326 goto FORCED_AGG_SETTING;
327 } else if (pTxTs->bUsingBa == false) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500328 if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum,
329 (pTxTs->TxCurSeq+1)%4096))
Larry Finger94a79942011-08-23 19:00:42 -0500330 pTxTs->bUsingBa = true;
331 else
332 goto FORCED_AGG_SETTING;
333 }
334 if (ieee->iw_mode == IW_MODE_INFRA) {
335 tcb_desc->bAMPDUEnable = true;
336 tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
337 tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
338 }
339 }
340FORCED_AGG_SETTING:
341 switch (pHTInfo->ForcedAMPDUMode) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500342 case HT_AGG_AUTO:
343 break;
Larry Finger94a79942011-08-23 19:00:42 -0500344
Larry Fingerf38d2232011-08-25 11:48:28 -0500345 case HT_AGG_FORCE_ENABLE:
346 tcb_desc->bAMPDUEnable = true;
347 tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
348 tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
349 break;
Larry Finger94a79942011-08-23 19:00:42 -0500350
Larry Fingerf38d2232011-08-25 11:48:28 -0500351 case HT_AGG_FORCE_DISABLE:
352 tcb_desc->bAMPDUEnable = false;
353 tcb_desc->ampdu_density = 0;
354 tcb_desc->ampdu_factor = 0;
355 break;
Larry Finger94a79942011-08-23 19:00:42 -0500356 }
357 return;
358}
359
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500360static void rtllib_qurey_ShortPreambleMode(struct rtllib_device *ieee,
Larry Fingerf38d2232011-08-25 11:48:28 -0500361 struct cb_desc *tcb_desc)
362{
363 tcb_desc->bUseShortPreamble = false;
364 if (tcb_desc->data_rate == 2)
365 return;
366 else if (ieee->current_network.capability &
367 WLAN_CAPABILITY_SHORT_PREAMBLE)
368 tcb_desc->bUseShortPreamble = true;
369 return;
370}
371
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500372static void rtllib_query_HTCapShortGI(struct rtllib_device *ieee,
Larry Fingerf38d2232011-08-25 11:48:28 -0500373 struct cb_desc *tcb_desc)
Larry Finger94a79942011-08-23 19:00:42 -0500374{
Larry Finger7796d932011-07-18 20:22:19 -0500375 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
Larry Finger94a79942011-08-23 19:00:42 -0500376
377 tcb_desc->bUseShortGI = false;
378
Larry Fingerf38d2232011-08-25 11:48:28 -0500379 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
Larry Finger94a79942011-08-23 19:00:42 -0500380 return;
381
Larry Fingerf38d2232011-08-25 11:48:28 -0500382 if (pHTInfo->bForcedShortGI) {
Larry Finger94a79942011-08-23 19:00:42 -0500383 tcb_desc->bUseShortGI = true;
384 return;
385 }
386
Larry Fingerf38d2232011-08-25 11:48:28 -0500387 if ((pHTInfo->bCurBW40MHz == true) && pHTInfo->bCurShortGI40MHz)
Larry Finger94a79942011-08-23 19:00:42 -0500388 tcb_desc->bUseShortGI = true;
Larry Fingerf38d2232011-08-25 11:48:28 -0500389 else if ((pHTInfo->bCurBW40MHz == false) && pHTInfo->bCurShortGI20MHz)
Larry Finger94a79942011-08-23 19:00:42 -0500390 tcb_desc->bUseShortGI = true;
391}
392
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500393static void rtllib_query_BandwidthMode(struct rtllib_device *ieee,
394 struct cb_desc *tcb_desc)
Larry Finger94a79942011-08-23 19:00:42 -0500395{
Larry Finger7796d932011-07-18 20:22:19 -0500396 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
Larry Finger94a79942011-08-23 19:00:42 -0500397
398 tcb_desc->bPacketBW = false;
399
Larry Fingerf38d2232011-08-25 11:48:28 -0500400 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
Larry Finger94a79942011-08-23 19:00:42 -0500401 return;
402
403 if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
404 return;
405
Larry Fingerf38d2232011-08-25 11:48:28 -0500406 if ((tcb_desc->data_rate & 0x80) == 0)
Larry Finger94a79942011-08-23 19:00:42 -0500407 return;
Larry Fingerf38d2232011-08-25 11:48:28 -0500408 if (pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz &&
409 !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
Larry Finger94a79942011-08-23 19:00:42 -0500410 tcb_desc->bPacketBW = true;
411 return;
412}
Larry Finger94a79942011-08-23 19:00:42 -0500413
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500414static void rtllib_query_protectionmode(struct rtllib_device *ieee,
415 struct cb_desc *tcb_desc,
416 struct sk_buff *skb)
Larry Finger94a79942011-08-23 19:00:42 -0500417{
418 tcb_desc->bRTSSTBC = false;
419 tcb_desc->bRTSUseShortGI = false;
420 tcb_desc->bCTSEnable = false;
421 tcb_desc->RTSSC = 0;
422 tcb_desc->bRTSBW = false;
423
424 if (tcb_desc->bBroadcast || tcb_desc->bMulticast)
425 return;
426
427 if (is_broadcast_ether_addr(skb->data+16))
428 return;
429
Larry Fingerf38d2232011-08-25 11:48:28 -0500430 if (ieee->mode < IEEE_N_24G) {
431 if (skb->len > ieee->rts) {
Larry Finger94a79942011-08-23 19:00:42 -0500432 tcb_desc->bRTSEnable = true;
433 tcb_desc->rts_rate = MGN_24M;
Larry Fingerf38d2232011-08-25 11:48:28 -0500434 } else if (ieee->current_network.buseprotection) {
Larry Finger94a79942011-08-23 19:00:42 -0500435 tcb_desc->bRTSEnable = true;
436 tcb_desc->bCTSEnable = true;
437 tcb_desc->rts_rate = MGN_24M;
438 }
439 return;
Larry Fingerf38d2232011-08-25 11:48:28 -0500440 } else {
Larry Finger7796d932011-07-18 20:22:19 -0500441 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400442
Larry Fingerf38d2232011-08-25 11:48:28 -0500443 while (true) {
444 if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) {
Larry Finger94a79942011-08-23 19:00:42 -0500445 tcb_desc->bCTSEnable = true;
446 tcb_desc->rts_rate = MGN_24M;
447 tcb_desc->bRTSEnable = true;
448 break;
Larry Fingerf38d2232011-08-25 11:48:28 -0500449 } else if (pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS |
450 HT_IOT_ACT_PURE_N_MODE)) {
Larry Finger94a79942011-08-23 19:00:42 -0500451 tcb_desc->bRTSEnable = true;
452 tcb_desc->rts_rate = MGN_24M;
453 break;
454 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500455 if (ieee->current_network.buseprotection) {
Larry Finger94a79942011-08-23 19:00:42 -0500456 tcb_desc->bRTSEnable = true;
457 tcb_desc->bCTSEnable = true;
458 tcb_desc->rts_rate = MGN_24M;
459 break;
460 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500461 if (pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) {
Larry Finger94a79942011-08-23 19:00:42 -0500462 u8 HTOpMode = pHTInfo->CurrentOpMode;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400463
Larry Fingerf38d2232011-08-25 11:48:28 -0500464 if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 ||
465 HTOpMode == 3)) ||
466 (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) {
Larry Finger94a79942011-08-23 19:00:42 -0500467 tcb_desc->rts_rate = MGN_24M;
468 tcb_desc->bRTSEnable = true;
469 break;
470 }
471 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500472 if (skb->len > ieee->rts) {
Larry Finger94a79942011-08-23 19:00:42 -0500473 tcb_desc->rts_rate = MGN_24M;
474 tcb_desc->bRTSEnable = true;
475 break;
476 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500477 if (tcb_desc->bAMPDUEnable) {
Larry Finger94a79942011-08-23 19:00:42 -0500478 tcb_desc->rts_rate = MGN_24M;
479 tcb_desc->bRTSEnable = false;
480 break;
481 }
482 goto NO_PROTECTION;
483 }
Larry Finger94a79942011-08-23 19:00:42 -0500484 }
485 if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
486 tcb_desc->bUseShortPreamble = true;
487 if (ieee->iw_mode == IW_MODE_MASTER)
488 goto NO_PROTECTION;
489 return;
490NO_PROTECTION:
491 tcb_desc->bRTSEnable = false;
492 tcb_desc->bCTSEnable = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500493 tcb_desc->rts_rate = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500494 tcb_desc->RTSSC = 0;
Larry Fingerf38d2232011-08-25 11:48:28 -0500495 tcb_desc->bRTSBW = false;
Larry Finger94a79942011-08-23 19:00:42 -0500496}
497
498
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500499static void rtllib_txrate_selectmode(struct rtllib_device *ieee,
500 struct cb_desc *tcb_desc)
Larry Finger94a79942011-08-23 19:00:42 -0500501{
Larry Finger94a79942011-08-23 19:00:42 -0500502 if (ieee->bTxDisableRateFallBack)
503 tcb_desc->bTxDisableRateFallBack = true;
504
505 if (ieee->bTxUseDriverAssingedRate)
506 tcb_desc->bTxUseDriverAssingedRate = true;
Larry Fingerf38d2232011-08-25 11:48:28 -0500507 if (!tcb_desc->bTxDisableRateFallBack ||
508 !tcb_desc->bTxUseDriverAssingedRate) {
509 if (ieee->iw_mode == IW_MODE_INFRA ||
510 ieee->iw_mode == IW_MODE_ADHOC)
Larry Finger94a79942011-08-23 19:00:42 -0500511 tcb_desc->RATRIndex = 0;
512 }
513}
514
Larry Fingerf38d2232011-08-25 11:48:28 -0500515u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb,
516 u8 *dst)
Larry Finger94a79942011-08-23 19:00:42 -0500517{
518 u16 seqnum = 0;
519
Joe Perches14fc4232012-05-08 10:11:56 -0700520 if (is_multicast_ether_addr(dst))
Larry Finger94a79942011-08-23 19:00:42 -0500521 return 0;
Larry Fingerf38d2232011-08-25 11:48:28 -0500522 if (IsQoSDataFrame(skb->data)) {
Larry Finger60554f22011-07-18 20:10:03 -0500523 struct tx_ts_record *pTS = NULL;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400524
Larry Fingerf38d2232011-08-25 11:48:28 -0500525 if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
526 skb->priority, TX_DIR, true))
Larry Finger94a79942011-08-23 19:00:42 -0500527 return 0;
Larry Finger94a79942011-08-23 19:00:42 -0500528 seqnum = pTS->TxCurSeq;
529 pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
530 return seqnum;
531 }
532 return 0;
533}
534
535static int wme_downgrade_ac(struct sk_buff *skb)
536{
537 switch (skb->priority) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500538 case 6:
539 case 7:
540 skb->priority = 5; /* VO -> VI */
541 return 0;
542 case 4:
543 case 5:
544 skb->priority = 3; /* VI -> BE */
545 return 0;
546 case 0:
547 case 3:
548 skb->priority = 1; /* BE -> BK */
549 return 0;
550 default:
551 return -1;
Larry Finger94a79942011-08-23 19:00:42 -0500552 }
553}
554
555int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
556{
Larry Fingerf38d2232011-08-25 11:48:28 -0500557 struct rtllib_device *ieee = (struct rtllib_device *)
558 netdev_priv_rsl(dev);
Larry Finger94a79942011-08-23 19:00:42 -0500559 struct rtllib_txb *txb = NULL;
560 struct rtllib_hdr_3addrqos *frag_hdr;
561 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
562 unsigned long flags;
563 struct net_device_stats *stats = &ieee->stats;
564 int ether_type = 0, encrypt;
565 int bytes, fc, qos_ctl = 0, hdr_len;
566 struct sk_buff *skb_frag;
567 struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */
568 .duration_id = 0,
569 .seq_ctl = 0,
570 .qos_ctl = 0
571 };
572 u8 dest[ETH_ALEN], src[ETH_ALEN];
573 int qos_actived = ieee->current_network.qos_data.active;
Sean MacLennan32c44cb2011-12-19 23:20:41 -0500574 struct lib80211_crypt_data *crypt = NULL;
Larry Finger3b83db42011-07-19 00:01:29 -0500575 struct cb_desc *tcb_desc;
Larry Finger94a79942011-08-23 19:00:42 -0500576 u8 bIsMulticast = false;
577 u8 IsAmsdu = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500578 bool bdhcp = false;
Larry Finger94a79942011-08-23 19:00:42 -0500579
Larry Finger94a79942011-08-23 19:00:42 -0500580 spin_lock_irqsave(&ieee->lock, flags);
581
Justin P. Mattockcd017122012-04-23 07:36:52 -0700582 /* If there is no driver handler to take the TXB, don't bother
Larry Finger94a79942011-08-23 19:00:42 -0500583 * creating it... */
Larry Fingerf38d2232011-08-25 11:48:28 -0500584 if ((!ieee->hard_start_xmit && !(ieee->softmac_features &
585 IEEE_SOFTMAC_TX_QUEUE)) ||
586 ((!ieee->softmac_data_hard_start_xmit &&
587 (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
Larry Finger94a79942011-08-23 19:00:42 -0500588 printk(KERN_WARNING "%s: No xmit handler.\n",
589 ieee->dev->name);
590 goto success;
591 }
592
593
Larry Fingerf38d2232011-08-25 11:48:28 -0500594 if (likely(ieee->raw_tx == 0)) {
Larry Finger94a79942011-08-23 19:00:42 -0500595 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
596 printk(KERN_WARNING "%s: skb too small (%d).\n",
597 ieee->dev->name, skb->len);
598 goto success;
599 }
600 /* Save source and destination addresses */
601 memcpy(dest, skb->data, ETH_ALEN);
602 memcpy(src, skb->data+ETH_ALEN, ETH_ALEN);
603
604 memset(skb->cb, 0, sizeof(skb->cb));
605 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
606
Larry Fingerf38d2232011-08-25 11:48:28 -0500607 if (ieee->iw_mode == IW_MODE_MONITOR) {
Larry Finger94a79942011-08-23 19:00:42 -0500608 txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
609 if (unlikely(!txb)) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500610 printk(KERN_WARNING "%s: Could not allocate "
611 "TXB\n",
Larry Finger94a79942011-08-23 19:00:42 -0500612 ieee->dev->name);
613 goto failed;
614 }
615
616 txb->encrypted = 0;
Rashika Kheria198e0d12013-11-02 23:39:22 +0530617 txb->payload_size = cpu_to_le16(skb->len);
Larry Fingerf38d2232011-08-25 11:48:28 -0500618 memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
619 skb->len);
Larry Finger94a79942011-08-23 19:00:42 -0500620
621 goto success;
622 }
623
Larry Finger55dc4eb2011-08-25 11:48:13 -0500624 if (skb->len > 282) {
Larry Finger94a79942011-08-23 19:00:42 -0500625 if (ETH_P_IP == ether_type) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500626 const struct iphdr *ip = (struct iphdr *)
627 ((u8 *)skb->data+14);
Larry Finger94a79942011-08-23 19:00:42 -0500628 if (IPPROTO_UDP == ip->protocol) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500629 struct udphdr *udp;
630
631 udp = (struct udphdr *)((u8 *)ip +
632 (ip->ihl << 2));
633 if (((((u8 *)udp)[1] == 68) &&
634 (((u8 *)udp)[3] == 67)) ||
635 ((((u8 *)udp)[1] == 67) &&
636 (((u8 *)udp)[3] == 68))) {
Larry Finger94a79942011-08-23 19:00:42 -0500637 bdhcp = true;
638 ieee->LPSDelayCnt = 200;
639 }
640 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500641 } else if (ETH_P_ARP == ether_type) {
642 printk(KERN_INFO "=================>DHCP "
643 "Protocol start tx ARP pkt!!\n");
Larry Finger94a79942011-08-23 19:00:42 -0500644 bdhcp = true;
Larry Fingerf38d2232011-08-25 11:48:28 -0500645 ieee->LPSDelayCnt =
646 ieee->current_network.tim.tim_count;
Larry Finger94a79942011-08-23 19:00:42 -0500647 }
648 }
649
650 skb->priority = rtllib_classify(skb, IsAmsdu);
Sean MacLennan0ddcf5f2011-12-19 23:21:41 -0500651 crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
Larry Finger94a79942011-08-23 19:00:42 -0500652 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
653 ieee->host_encrypt && crypt && crypt->ops;
654 if (!encrypt && ieee->ieee802_1x &&
Larry Fingerf38d2232011-08-25 11:48:28 -0500655 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
Larry Finger94a79942011-08-23 19:00:42 -0500656 stats->tx_dropped++;
657 goto success;
658 }
Larry Finger94a79942011-08-23 19:00:42 -0500659 if (crypt && !encrypt && ether_type == ETH_P_PAE) {
660 struct eapol *eap = (struct eapol *)(skb->data +
Larry Fingerf38d2232011-08-25 11:48:28 -0500661 sizeof(struct ethhdr) - SNAP_SIZE -
662 sizeof(u16));
Larry Finger94a79942011-08-23 19:00:42 -0500663 RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
664 eap_get_type(eap->type));
665 }
Larry Finger94a79942011-08-23 19:00:42 -0500666
667 /* Advance the SKB to the start of the payload */
668 skb_pull(skb, sizeof(struct ethhdr));
669
Larry Fingerf38d2232011-08-25 11:48:28 -0500670 /* Determine total amount of storage required for TXB packets */
Larry Finger94a79942011-08-23 19:00:42 -0500671 bytes = skb->len + SNAP_SIZE + sizeof(u16);
672
673 if (encrypt)
674 fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP;
675 else
676 fc = RTLLIB_FTYPE_DATA;
677
678 if (qos_actived)
679 fc |= RTLLIB_STYPE_QOS_DATA;
680 else
681 fc |= RTLLIB_STYPE_DATA;
682
683 if (ieee->iw_mode == IW_MODE_INFRA) {
684 fc |= RTLLIB_FCTL_TODS;
685 /* To DS: Addr1 = BSSID, Addr2 = SA,
686 Addr3 = DA */
Larry Fingerf38d2232011-08-25 11:48:28 -0500687 memcpy(&header.addr1, ieee->current_network.bssid,
688 ETH_ALEN);
Larry Finger94a79942011-08-23 19:00:42 -0500689 memcpy(&header.addr2, &src, ETH_ALEN);
690 if (IsAmsdu)
Larry Fingerf38d2232011-08-25 11:48:28 -0500691 memcpy(&header.addr3,
692 ieee->current_network.bssid, ETH_ALEN);
Larry Finger94a79942011-08-23 19:00:42 -0500693 else
694 memcpy(&header.addr3, &dest, ETH_ALEN);
695 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
696 /* not From/To DS: Addr1 = DA, Addr2 = SA,
697 Addr3 = BSSID */
698 memcpy(&header.addr1, dest, ETH_ALEN);
699 memcpy(&header.addr2, src, ETH_ALEN);
Larry Fingerf38d2232011-08-25 11:48:28 -0500700 memcpy(&header.addr3, ieee->current_network.bssid,
701 ETH_ALEN);
Larry Finger94a79942011-08-23 19:00:42 -0500702 }
703
Joe Perches14fc4232012-05-08 10:11:56 -0700704 bIsMulticast = is_multicast_ether_addr(header.addr1);
Larry Finger94a79942011-08-23 19:00:42 -0500705
Larry Fingerf38d2232011-08-25 11:48:28 -0500706 header.frame_ctl = cpu_to_le16(fc);
Larry Finger94a79942011-08-23 19:00:42 -0500707
708 /* Determine fragmentation size based on destination (multicast
709 * and broadcast are not fragmented) */
710 if (bIsMulticast) {
711 frag_size = MAX_FRAG_THRESHOLD;
712 qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
713 } else {
714 frag_size = ieee->fts;
715 qos_ctl = 0;
716 }
717
718 if (qos_actived) {
719 hdr_len = RTLLIB_3ADDR_LEN + 2;
720
Larry Fingerf38d2232011-08-25 11:48:28 -0500721 /* in case we are a client verify acm is not set for this ac */
722 while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) {
723 printk(KERN_INFO "skb->priority = %x\n", skb->priority);
724 if (wme_downgrade_ac(skb))
725 break;
726 printk(KERN_INFO "converted skb->priority = %x\n",
727 skb->priority);
728 }
729 qos_ctl |= skb->priority;
730 header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID);
Larry Finger94a79942011-08-23 19:00:42 -0500731 } else {
732 hdr_len = RTLLIB_3ADDR_LEN;
733 }
734 /* Determine amount of payload per fragment. Regardless of if
Larry Fingerf38d2232011-08-25 11:48:28 -0500735 * this stack is providing the full 802.11 header, one will
736 * eventually be affixed to this fragment -- so we must account
737 * for it when determining the amount of payload space. */
Larry Finger94a79942011-08-23 19:00:42 -0500738 bytes_per_frag = frag_size - hdr_len;
739 if (ieee->config &
Larry Fingerf38d2232011-08-25 11:48:28 -0500740 (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
Larry Finger94a79942011-08-23 19:00:42 -0500741 bytes_per_frag -= RTLLIB_FCS_LEN;
742
Justin P. Mattockcd017122012-04-23 07:36:52 -0700743 /* Each fragment may need to have room for encrypting
Larry Fingerf38d2232011-08-25 11:48:28 -0500744 * pre/postfix */
Larry Finger94a79942011-08-23 19:00:42 -0500745 if (encrypt) {
Sean MacLennan32c44cb2011-12-19 23:20:41 -0500746 bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
747 crypt->ops->extra_mpdu_postfix_len +
748 crypt->ops->extra_msdu_prefix_len +
749 crypt->ops->extra_msdu_postfix_len;
Larry Finger94a79942011-08-23 19:00:42 -0500750 }
751 /* Number of fragments is the total bytes_per_frag /
752 * payload_per_fragment */
753 nr_frags = bytes / bytes_per_frag;
754 bytes_last_frag = bytes % bytes_per_frag;
755 if (bytes_last_frag)
756 nr_frags++;
757 else
758 bytes_last_frag = bytes_per_frag;
759
Larry Fingerf38d2232011-08-25 11:48:28 -0500760 /* When we allocate the TXB we allocate enough space for the
761 * reserve and full fragment bytes (bytes_per_frag doesn't
762 * include prefix, postfix, header, FCS, etc.) */
763 txb = rtllib_alloc_txb(nr_frags, frag_size +
764 ieee->tx_headroom, GFP_ATOMIC);
Larry Finger94a79942011-08-23 19:00:42 -0500765 if (unlikely(!txb)) {
766 printk(KERN_WARNING "%s: Could not allocate TXB\n",
767 ieee->dev->name);
768 goto failed;
769 }
770 txb->encrypted = encrypt;
Rashika Kheria198e0d12013-11-02 23:39:22 +0530771 txb->payload_size = cpu_to_le16(bytes);
Larry Finger94a79942011-08-23 19:00:42 -0500772
773 if (qos_actived)
Larry Finger94a79942011-08-23 19:00:42 -0500774 txb->queue_index = UP2AC(skb->priority);
Larry Fingerf38d2232011-08-25 11:48:28 -0500775 else
776 txb->queue_index = WME_AC_BE;
Larry Finger94a79942011-08-23 19:00:42 -0500777
778 for (i = 0; i < nr_frags; i++) {
779 skb_frag = txb->fragments[i];
Larry Fingerf38d2232011-08-25 11:48:28 -0500780 tcb_desc = (struct cb_desc *)(skb_frag->cb +
781 MAX_DEV_ADDR_SIZE);
782 if (qos_actived) {
Larry Finger94a79942011-08-23 19:00:42 -0500783 skb_frag->priority = skb->priority;
784 tcb_desc->queue_index = UP2AC(skb->priority);
785 } else {
786 skb_frag->priority = WME_AC_BE;
787 tcb_desc->queue_index = WME_AC_BE;
788 }
789 skb_reserve(skb_frag, ieee->tx_headroom);
790
Larry Fingerf38d2232011-08-25 11:48:28 -0500791 if (encrypt) {
Larry Finger94a79942011-08-23 19:00:42 -0500792 if (ieee->hwsec_active)
793 tcb_desc->bHwSec = 1;
794 else
795 tcb_desc->bHwSec = 0;
Larry Fingerf38d2232011-08-25 11:48:28 -0500796 skb_reserve(skb_frag,
Sean MacLennan32c44cb2011-12-19 23:20:41 -0500797 crypt->ops->extra_mpdu_prefix_len +
798 crypt->ops->extra_msdu_prefix_len);
Larry Finger94a79942011-08-23 19:00:42 -0500799 } else {
800 tcb_desc->bHwSec = 0;
801 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500802 frag_hdr = (struct rtllib_hdr_3addrqos *)
803 skb_put(skb_frag, hdr_len);
Larry Finger94a79942011-08-23 19:00:42 -0500804 memcpy(frag_hdr, &header, hdr_len);
805
Larry Fingerf38d2232011-08-25 11:48:28 -0500806 /* If this is not the last fragment, then add the
807 * MOREFRAGS bit to the frame control */
Larry Finger94a79942011-08-23 19:00:42 -0500808 if (i != nr_frags - 1) {
809 frag_hdr->frame_ctl = cpu_to_le16(
810 fc | RTLLIB_FCTL_MOREFRAGS);
811 bytes = bytes_per_frag;
812
813 } else {
Larry Fingerf38d2232011-08-25 11:48:28 -0500814 /* The last fragment has the remaining length */
Larry Finger94a79942011-08-23 19:00:42 -0500815 bytes = bytes_last_frag;
816 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500817 if ((qos_actived) && (!bIsMulticast)) {
818 frag_hdr->seq_ctl =
Rashika Kheria198e0d12013-11-02 23:39:22 +0530819 cpu_to_le16(rtllib_query_seqnum(ieee, skb_frag,
820 header.addr1));
Larry Fingerf38d2232011-08-25 11:48:28 -0500821 frag_hdr->seq_ctl =
Rashika Kheria86005e12013-11-02 23:40:15 +0530822 cpu_to_le16(le16_to_cpu(frag_hdr->seq_ctl)<<4 | i);
Larry Finger94a79942011-08-23 19:00:42 -0500823 } else {
Larry Fingerf38d2232011-08-25 11:48:28 -0500824 frag_hdr->seq_ctl =
825 cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
Larry Finger94a79942011-08-23 19:00:42 -0500826 }
827 /* Put a SNAP header on the first fragment */
828 if (i == 0) {
829 rtllib_put_snap(
Larry Fingerf38d2232011-08-25 11:48:28 -0500830 skb_put(skb_frag, SNAP_SIZE +
831 sizeof(u16)), ether_type);
Larry Finger94a79942011-08-23 19:00:42 -0500832 bytes -= SNAP_SIZE + sizeof(u16);
833 }
834
835 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
836
837 /* Advance the SKB... */
838 skb_pull(skb, bytes);
839
Larry Fingerf38d2232011-08-25 11:48:28 -0500840 /* Encryption routine will move the header forward in
841 * order to insert the IV between the header and the
842 * payload */
Larry Finger94a79942011-08-23 19:00:42 -0500843 if (encrypt)
Larry Fingerf38d2232011-08-25 11:48:28 -0500844 rtllib_encrypt_fragment(ieee, skb_frag,
845 hdr_len);
Larry Finger94a79942011-08-23 19:00:42 -0500846 if (ieee->config &
Larry Fingerf38d2232011-08-25 11:48:28 -0500847 (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
Larry Finger94a79942011-08-23 19:00:42 -0500848 skb_put(skb_frag, 4);
849 }
850
851 if ((qos_actived) && (!bIsMulticast)) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500852 if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
853 ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
854 else
855 ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
Larry Finger94a79942011-08-23 19:00:42 -0500856 } else {
Larry Fingerf38d2232011-08-25 11:48:28 -0500857 if (ieee->seq_ctrl[0] == 0xFFF)
858 ieee->seq_ctrl[0] = 0;
859 else
860 ieee->seq_ctrl[0]++;
Larry Finger94a79942011-08-23 19:00:42 -0500861 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500862 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500863 if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) {
864 printk(KERN_WARNING "%s: skb too small (%d).\n",
865 ieee->dev->name, skb->len);
866 goto success;
867 }
868
869 txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
Larry Fingerf38d2232011-08-25 11:48:28 -0500870 if (!txb) {
Larry Finger94a79942011-08-23 19:00:42 -0500871 printk(KERN_WARNING "%s: Could not allocate TXB\n",
872 ieee->dev->name);
873 goto failed;
874 }
875
876 txb->encrypted = 0;
Rashika Kheria198e0d12013-11-02 23:39:22 +0530877 txb->payload_size = cpu_to_le16(skb->len);
Larry Fingerf38d2232011-08-25 11:48:28 -0500878 memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
879 skb->len);
Larry Finger94a79942011-08-23 19:00:42 -0500880 }
881
882 success:
Larry Fingerf38d2232011-08-25 11:48:28 -0500883 if (txb) {
884 struct cb_desc *tcb_desc = (struct cb_desc *)
885 (txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
Larry Finger94a79942011-08-23 19:00:42 -0500886 tcb_desc->bTxEnableFwCalcDur = 1;
887 tcb_desc->priority = skb->priority;
888
889 if (ether_type == ETH_P_PAE) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500890 if (ieee->pHTInfo->IOTAction &
891 HT_IOT_ACT_WA_IOT_Broadcom) {
892 tcb_desc->data_rate =
893 MgntQuery_TxRateExcludeCCKRates(ieee);
Larry Finger94a79942011-08-23 19:00:42 -0500894 tcb_desc->bTxDisableRateFallBack = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500895 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500896 tcb_desc->data_rate = ieee->basic_rate;
897 tcb_desc->bTxDisableRateFallBack = 1;
898 }
899
900
901 tcb_desc->RATRIndex = 7;
902 tcb_desc->bTxUseDriverAssingedRate = 1;
903 } else {
904 if (is_multicast_ether_addr(header.addr1))
905 tcb_desc->bMulticast = 1;
906 if (is_broadcast_ether_addr(header.addr1))
907 tcb_desc->bBroadcast = 1;
Larry Finger94a79942011-08-23 19:00:42 -0500908 rtllib_txrate_selectmode(ieee, tcb_desc);
Larry Fingerf38d2232011-08-25 11:48:28 -0500909 if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
Larry Finger94a79942011-08-23 19:00:42 -0500910 tcb_desc->data_rate = ieee->basic_rate;
911 else
Larry Fingerf38d2232011-08-25 11:48:28 -0500912 tcb_desc->data_rate = CURRENT_RATE(ieee->mode,
913 ieee->rate, ieee->HTCurrentOperaRate);
Larry Finger94a79942011-08-23 19:00:42 -0500914
Valentina Manea4bb01422013-10-25 11:28:10 +0300915 if (bdhcp) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500916 if (ieee->pHTInfo->IOTAction &
917 HT_IOT_ACT_WA_IOT_Broadcom) {
918 tcb_desc->data_rate =
919 MgntQuery_TxRateExcludeCCKRates(ieee);
Larry Finger94a79942011-08-23 19:00:42 -0500920 tcb_desc->bTxDisableRateFallBack = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500921 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500922 tcb_desc->data_rate = MGN_1M;
923 tcb_desc->bTxDisableRateFallBack = 1;
924 }
925
926
927 tcb_desc->RATRIndex = 7;
928 tcb_desc->bTxUseDriverAssingedRate = 1;
929 tcb_desc->bdhcp = 1;
930 }
931
932 rtllib_qurey_ShortPreambleMode(ieee, tcb_desc);
Larry Fingerf38d2232011-08-25 11:48:28 -0500933 rtllib_tx_query_agg_cap(ieee, txb->fragments[0],
934 tcb_desc);
Larry Finger94a79942011-08-23 19:00:42 -0500935 rtllib_query_HTCapShortGI(ieee, tcb_desc);
936 rtllib_query_BandwidthMode(ieee, tcb_desc);
Larry Fingerf38d2232011-08-25 11:48:28 -0500937 rtllib_query_protectionmode(ieee, tcb_desc,
938 txb->fragments[0]);
Larry Finger94a79942011-08-23 19:00:42 -0500939 }
Larry Finger94a79942011-08-23 19:00:42 -0500940 }
941 spin_unlock_irqrestore(&ieee->lock, flags);
942 dev_kfree_skb_any(skb);
943 if (txb) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500944 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
Larry Finger94a79942011-08-23 19:00:42 -0500945 dev->stats.tx_packets++;
Monam Agarwal83efd522014-03-07 02:39:44 +0530946 dev->stats.tx_bytes += le16_to_cpu(txb->payload_size);
Larry Finger94a79942011-08-23 19:00:42 -0500947 rtllib_softmac_xmit(txb, ieee);
Larry Fingerf38d2232011-08-25 11:48:28 -0500948 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500949 if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
950 stats->tx_packets++;
Monam Agarwal83efd522014-03-07 02:39:44 +0530951 stats->tx_bytes += le16_to_cpu(txb->payload_size);
Larry Finger94a79942011-08-23 19:00:42 -0500952 return 0;
953 }
954 rtllib_txb_free(txb);
955 }
956 }
957
958 return 0;
959
960 failed:
961 spin_unlock_irqrestore(&ieee->lock, flags);
962 netif_stop_queue(dev);
963 stats->tx_errors++;
964 return 1;
965
966}
967int rtllib_xmit(struct sk_buff *skb, struct net_device *dev)
968{
969 memset(skb->cb, 0, sizeof(skb->cb));
970 return rtllib_xmit_inter(skb, dev);
971}
Sean MacLennan3b284992011-11-28 20:20:26 -0500972EXPORT_SYMBOL(rtllib_xmit);