Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[deliverable/linux.git] / drivers / staging / rtl8192e / rtllib_tx.c
CommitLineData
ecdfa446
GKH
1/******************************************************************************
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
559a4c31 28 Andrea Merello <andrea.merello@gmail.com>
ecdfa446
GKH
29
30 A special thanks goes to Realtek for their support !
31
32******************************************************************************/
33
34#include <linux/compiler.h>
ecdfa446
GKH
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>
ecdfa446
GKH
49#include <linux/wireless.h>
50#include <linux/etherdevice.h>
f38d223b 51#include <linux/uaccess.h>
ecdfa446
GKH
52#include <linux/if_vlan.h>
53
94a79942 54#include "rtllib.h"
ecdfa446 55
ecdfa446
GKH
56/*
57
58
59802.11 Data Frame
60
61
cd017123 62802.11 frame_control for data frames - 2 bytes
ecdfa446
GKH
63 ,-----------------------------------------------------------------------------------------.
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 |
f38d223b 69 | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | |
ecdfa446 70 '-----------------------------------------------------------------------------------------'
f38d223b
LF
71 /\
72 |
73802.11 Data Frame |
74 ,--------- 'ctrl' expands to >-----------'
75 |
ecdfa446
GKH
76 ,--'---,-------------------------------------------------------------.
77Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
78 |------|------|---------|---------|---------|------|---------|------|
79Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
f38d223b
LF
80 | | tion | (BSSID) | | | ence | data | |
81 `--------------------------------------------------| |------'
82Total: 28 non-data bytes `----.----'
83 |
ecdfa446
GKH
84 .- '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 |
f38d223b
LF
91 | DSAP | SSAP | | | | Packet |
92 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
93 `-----------------------------------------| |
94Total: 8 non-data bytes `----.----'
95 |
ecdfa446
GKH
96 .- '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 |
f38d223b 114 | MAC | MAC | | | |
ecdfa446
GKH
115 `-----------------------------------------'
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* |
f38d223b
LF
132* | ETHERNET HEADER ,-<-- PAYLOAD
133* | | 14 bytes from skb->data
ecdfa446 134* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
f38d223b 135* | | | |
ecdfa446
GKH
136* |,-Dest.--. ,--Src.---. | | |
137* | 6 bytes| | 6 bytes | | | |
f38d223b
LF
138* v | | | | | |
139* 0 | v 1 | v | v 2
ecdfa446 140* 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
f38d223b
LF
141* ^ | ^ | ^ |
142* | | | | | |
143* | | | | `T' <---- 2 bytes for Type
144* | | | |
ecdfa446
GKH
145* | | '---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
94a79942 156inline int rtllib_put_snap(u8 *data, u16 h_proto)
ecdfa446 157{
94a79942 158 struct rtllib_snap_hdr *snap;
ecdfa446
GKH
159 u8 *oui;
160
94a79942 161 snap = (struct rtllib_snap_hdr *)data;
ecdfa446
GKH
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
9326c5ca 174 *(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
ecdfa446
GKH
175
176 return SNAP_SIZE + sizeof(u16);
177}
178
f38d223b
LF
179int rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag,
180 int hdr_len)
ecdfa446 181{
32c44cb5 182 struct lib80211_crypt_data *crypt = NULL;
ecdfa446
GKH
183 int res;
184
0ddcf5fd 185 crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
94a79942 186
f38d223b
LF
187 if (!(crypt && crypt->ops)) {
188 printk(KERN_INFO "=========>%s(), crypt is null\n", __func__);
ecdfa446
GKH
189 return -1;
190 }
ecdfa446
GKH
191 /* To encrypt, frame format is:
192 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
193
ecdfa446
GKH
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
f38d223b
LF
215void rtllib_txb_free(struct rtllib_txb *txb)
216{
ecdfa446
GKH
217 if (unlikely(!txb))
218 return;
ecdfa446
GKH
219 kfree(txb);
220}
221
ec0dc6be
LF
222static struct rtllib_txb *rtllib_alloc_txb(int nr_frags, int txb_size,
223 gfp_t gfp_mask)
ecdfa446 224{
94a79942 225 struct rtllib_txb *txb;
ecdfa446 226 int i;
f38d223b
LF
227 txb = kmalloc(sizeof(struct rtllib_txb) + (sizeof(u8 *) * nr_frags),
228 gfp_mask);
ecdfa446
GKH
229 if (!txb)
230 return NULL;
231
94a79942 232 memset(txb, 0, sizeof(struct rtllib_txb));
ecdfa446 233 txb->nr_frags = nr_frags;
198e0d17 234 txb->frag_size = cpu_to_le16(txb_size);
ecdfa446
GKH
235
236 for (i = 0; i < nr_frags; i++) {
237 txb->fragments[i] = dev_alloc_skb(txb_size);
238 if (unlikely(!txb->fragments[i])) {
239 i--;
240 break;
241 }
242 memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb));
243 }
244 if (unlikely(i != nr_frags)) {
245 while (i >= 0)
246 dev_kfree_skb_any(txb->fragments[i--]);
247 kfree(txb);
248 return NULL;
249 }
250 return txb;
251}
252
ec0dc6be 253static int rtllib_classify(struct sk_buff *skb, u8 bIsAmsdu)
ecdfa446
GKH
254{
255 struct ethhdr *eth;
256 struct iphdr *ip;
94a79942 257
ecdfa446
GKH
258 eth = (struct ethhdr *)skb->data;
259 if (eth->h_proto != htons(ETH_P_IP))
260 return 0;
261
94a79942 262 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA, skb->data, skb->len);
ecdfa446 263 ip = ip_hdr(skb);
ecdfa446 264 switch (ip->tos & 0xfc) {
94a79942
LF
265 case 0x20:
266 return 2;
267 case 0x40:
268 return 1;
269 case 0x60:
270 return 3;
271 case 0x80:
272 return 4;
273 case 0xa0:
274 return 5;
275 case 0xc0:
276 return 6;
277 case 0xe0:
278 return 7;
279 default:
280 return 0;
ecdfa446
GKH
281 }
282}
283
ec0dc6be
LF
284static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee,
285 struct sk_buff *skb,
286 struct cb_desc *tcb_desc)
ecdfa446 287{
7796d93e 288 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
60554f2b 289 struct tx_ts_record *pTxTs = NULL;
4d0c8ee8 290 struct rtllib_hdr_1addr *hdr = (struct rtllib_hdr_1addr *)skb->data;
94a79942 291
f38d223b 292 if (rtllib_act_scanning(ieee, false))
94a79942 293 return;
ecdfa446 294
f38d223b 295 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
ecdfa446
GKH
296 return;
297 if (!IsQoSDataFrame(skb->data))
298 return;
14fc4235 299 if (is_multicast_ether_addr(hdr->addr1))
ecdfa446 300 return;
65a43784 301
f38d223b 302 if (tcb_desc->bdhcp || ieee->CntAfterLink < 2)
94a79942 303 return;
65a43784 304
94a79942
LF
305 if (pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION)
306 return;
65a43784 307
94a79942 308 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
ecdfa446 309 return;
f38d223b
LF
310 if (pHTInfo->bCurrentAMPDUEnable) {
311 if (!GetTs(ieee, (struct ts_common_info **)(&pTxTs), hdr->addr1,
312 skb->priority, TX_DIR, true)) {
313 printk(KERN_INFO "%s: can't get TS\n", __func__);
ecdfa446
GKH
314 return;
315 }
f38d223b
LF
316 if (pTxTs->TxAdmittedBARecord.bValid == false) {
317 if (ieee->wpa_ie_len && (ieee->pairwise_key_type ==
318 KEY_TYPE_NA)) {
94a79942 319 ;
f38d223b 320 } else if (tcb_desc->bdhcp == 1) {
94a79942 321 ;
f38d223b 322 } else if (!pTxTs->bDisable_AddBa) {
94a79942
LF
323 TsStartAddBaProcess(ieee, pTxTs);
324 }
ecdfa446 325 goto FORCED_AGG_SETTING;
94a79942 326 } else if (pTxTs->bUsingBa == false) {
f38d223b
LF
327 if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum,
328 (pTxTs->TxCurSeq+1)%4096))
ecdfa446
GKH
329 pTxTs->bUsingBa = true;
330 else
331 goto FORCED_AGG_SETTING;
332 }
94a79942 333 if (ieee->iw_mode == IW_MODE_INFRA) {
ecdfa446
GKH
334 tcb_desc->bAMPDUEnable = true;
335 tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
336 tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
337 }
338 }
339FORCED_AGG_SETTING:
94a79942 340 switch (pHTInfo->ForcedAMPDUMode) {
f38d223b
LF
341 case HT_AGG_AUTO:
342 break;
343
344 case HT_AGG_FORCE_ENABLE:
345 tcb_desc->bAMPDUEnable = true;
346 tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
347 tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
348 break;
349
350 case HT_AGG_FORCE_DISABLE:
351 tcb_desc->bAMPDUEnable = false;
352 tcb_desc->ampdu_density = 0;
353 tcb_desc->ampdu_factor = 0;
354 break;
ecdfa446 355 }
f38d223b 356 return;
ecdfa446
GKH
357}
358
ec0dc6be 359static void rtllib_qurey_ShortPreambleMode(struct rtllib_device *ieee,
f38d223b 360 struct cb_desc *tcb_desc)
ecdfa446
GKH
361{
362 tcb_desc->bUseShortPreamble = false;
363 if (tcb_desc->data_rate == 2)
ecdfa446 364 return;
f38d223b
LF
365 else if (ieee->current_network.capability &
366 WLAN_CAPABILITY_SHORT_PREAMBLE)
ecdfa446 367 tcb_desc->bUseShortPreamble = true;
ecdfa446
GKH
368 return;
369}
94a79942 370
ec0dc6be 371static void rtllib_query_HTCapShortGI(struct rtllib_device *ieee,
f38d223b 372 struct cb_desc *tcb_desc)
ecdfa446 373{
7796d93e 374 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
ecdfa446 375
94a79942 376 tcb_desc->bUseShortGI = false;
ecdfa446 377
f38d223b 378 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
ecdfa446
GKH
379 return;
380
f38d223b 381 if (pHTInfo->bForcedShortGI) {
ecdfa446
GKH
382 tcb_desc->bUseShortGI = true;
383 return;
384 }
385
f38d223b 386 if ((pHTInfo->bCurBW40MHz == true) && pHTInfo->bCurShortGI40MHz)
ecdfa446 387 tcb_desc->bUseShortGI = true;
f38d223b 388 else if ((pHTInfo->bCurBW40MHz == false) && pHTInfo->bCurShortGI20MHz)
ecdfa446
GKH
389 tcb_desc->bUseShortGI = true;
390}
391
ec0dc6be
LF
392static void rtllib_query_BandwidthMode(struct rtllib_device *ieee,
393 struct cb_desc *tcb_desc)
ecdfa446 394{
7796d93e 395 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
ecdfa446
GKH
396
397 tcb_desc->bPacketBW = false;
398
f38d223b 399 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
ecdfa446
GKH
400 return;
401
94a79942 402 if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
ecdfa446
GKH
403 return;
404
f38d223b 405 if ((tcb_desc->data_rate & 0x80) == 0)
ecdfa446 406 return;
f38d223b
LF
407 if (pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz &&
408 !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
ecdfa446
GKH
409 tcb_desc->bPacketBW = true;
410 return;
411}
94a79942 412
ec0dc6be
LF
413static void rtllib_query_protectionmode(struct rtllib_device *ieee,
414 struct cb_desc *tcb_desc,
415 struct sk_buff *skb)
ecdfa446 416{
ecdfa446 417 tcb_desc->bRTSSTBC = false;
94a79942
LF
418 tcb_desc->bRTSUseShortGI = false;
419 tcb_desc->bCTSEnable = false;
420 tcb_desc->RTSSC = 0;
421 tcb_desc->bRTSBW = false;
ecdfa446 422
94a79942 423 if (tcb_desc->bBroadcast || tcb_desc->bMulticast)
ecdfa446
GKH
424 return;
425
94a79942 426 if (is_broadcast_ether_addr(skb->data+16))
ecdfa446
GKH
427 return;
428
f38d223b
LF
429 if (ieee->mode < IEEE_N_24G) {
430 if (skb->len > ieee->rts) {
ecdfa446
GKH
431 tcb_desc->bRTSEnable = true;
432 tcb_desc->rts_rate = MGN_24M;
f38d223b 433 } else if (ieee->current_network.buseprotection) {
ecdfa446
GKH
434 tcb_desc->bRTSEnable = true;
435 tcb_desc->bCTSEnable = true;
436 tcb_desc->rts_rate = MGN_24M;
437 }
ecdfa446 438 return;
f38d223b 439 } else {
7796d93e 440 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
f38d223b
LF
441 while (true) {
442 if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) {
94a79942
LF
443 tcb_desc->bCTSEnable = true;
444 tcb_desc->rts_rate = MGN_24M;
445 tcb_desc->bRTSEnable = true;
446 break;
f38d223b
LF
447 } else if (pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS |
448 HT_IOT_ACT_PURE_N_MODE)) {
94a79942
LF
449 tcb_desc->bRTSEnable = true;
450 tcb_desc->rts_rate = MGN_24M;
451 break;
452 }
f38d223b 453 if (ieee->current_network.buseprotection) {
ecdfa446
GKH
454 tcb_desc->bRTSEnable = true;
455 tcb_desc->bCTSEnable = true;
456 tcb_desc->rts_rate = MGN_24M;
457 break;
458 }
f38d223b 459 if (pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) {
ecdfa446 460 u8 HTOpMode = pHTInfo->CurrentOpMode;
f38d223b
LF
461 if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 ||
462 HTOpMode == 3)) ||
463 (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) {
94a79942 464 tcb_desc->rts_rate = MGN_24M;
ecdfa446
GKH
465 tcb_desc->bRTSEnable = true;
466 break;
467 }
468 }
f38d223b 469 if (skb->len > ieee->rts) {
94a79942 470 tcb_desc->rts_rate = MGN_24M;
ecdfa446
GKH
471 tcb_desc->bRTSEnable = true;
472 break;
473 }
f38d223b 474 if (tcb_desc->bAMPDUEnable) {
94a79942 475 tcb_desc->rts_rate = MGN_24M;
ecdfa446
GKH
476 tcb_desc->bRTSEnable = false;
477 break;
478 }
ecdfa446
GKH
479 goto NO_PROTECTION;
480 }
ecdfa446
GKH
481 }
482 if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
483 tcb_desc->bUseShortPreamble = true;
94a79942 484 if (ieee->iw_mode == IW_MODE_MASTER)
ecdfa446
GKH
485 goto NO_PROTECTION;
486 return;
487NO_PROTECTION:
488 tcb_desc->bRTSEnable = false;
489 tcb_desc->bCTSEnable = false;
f38d223b 490 tcb_desc->rts_rate = 0;
ecdfa446 491 tcb_desc->RTSSC = 0;
f38d223b 492 tcb_desc->bRTSBW = false;
ecdfa446
GKH
493}
494
495
ec0dc6be
LF
496static void rtllib_txrate_selectmode(struct rtllib_device *ieee,
497 struct cb_desc *tcb_desc)
ecdfa446 498{
94a79942 499 if (ieee->bTxDisableRateFallBack)
ecdfa446
GKH
500 tcb_desc->bTxDisableRateFallBack = true;
501
94a79942 502 if (ieee->bTxUseDriverAssingedRate)
ecdfa446 503 tcb_desc->bTxUseDriverAssingedRate = true;
f38d223b
LF
504 if (!tcb_desc->bTxDisableRateFallBack ||
505 !tcb_desc->bTxUseDriverAssingedRate) {
506 if (ieee->iw_mode == IW_MODE_INFRA ||
507 ieee->iw_mode == IW_MODE_ADHOC)
ecdfa446
GKH
508 tcb_desc->RATRIndex = 0;
509 }
510}
511
f38d223b
LF
512u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb,
513 u8 *dst)
ecdfa446 514{
94a79942
LF
515 u16 seqnum = 0;
516
14fc4235 517 if (is_multicast_ether_addr(dst))
94a79942 518 return 0;
f38d223b 519 if (IsQoSDataFrame(skb->data)) {
60554f2b 520 struct tx_ts_record *pTS = NULL;
f38d223b
LF
521 if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
522 skb->priority, TX_DIR, true))
94a79942 523 return 0;
94a79942 524 seqnum = pTS->TxCurSeq;
ecdfa446 525 pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
94a79942
LF
526 return seqnum;
527 }
528 return 0;
529}
530
531static int wme_downgrade_ac(struct sk_buff *skb)
532{
533 switch (skb->priority) {
f38d223b
LF
534 case 6:
535 case 7:
536 skb->priority = 5; /* VO -> VI */
537 return 0;
538 case 4:
539 case 5:
540 skb->priority = 3; /* VI -> BE */
541 return 0;
542 case 0:
543 case 3:
544 skb->priority = 1; /* BE -> BK */
545 return 0;
546 default:
547 return -1;
ecdfa446
GKH
548 }
549}
550
94a79942 551int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
ecdfa446 552{
f38d223b
LF
553 struct rtllib_device *ieee = (struct rtllib_device *)
554 netdev_priv_rsl(dev);
94a79942
LF
555 struct rtllib_txb *txb = NULL;
556 struct rtllib_hdr_3addrqos *frag_hdr;
ecdfa446
GKH
557 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
558 unsigned long flags;
559 struct net_device_stats *stats = &ieee->stats;
560 int ether_type = 0, encrypt;
561 int bytes, fc, qos_ctl = 0, hdr_len;
562 struct sk_buff *skb_frag;
94a79942 563 struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */
ecdfa446
GKH
564 .duration_id = 0,
565 .seq_ctl = 0,
566 .qos_ctl = 0
567 };
568 u8 dest[ETH_ALEN], src[ETH_ALEN];
569 int qos_actived = ieee->current_network.qos_data.active;
32c44cb5 570 struct lib80211_crypt_data *crypt = NULL;
3b83db43 571 struct cb_desc *tcb_desc;
94a79942
LF
572 u8 bIsMulticast = false;
573 u8 IsAmsdu = false;
f38d223b 574 bool bdhcp = false;
ecdfa446
GKH
575
576 spin_lock_irqsave(&ieee->lock, flags);
577
cd017123 578 /* If there is no driver handler to take the TXB, don't bother
ecdfa446 579 * creating it... */
f38d223b
LF
580 if ((!ieee->hard_start_xmit && !(ieee->softmac_features &
581 IEEE_SOFTMAC_TX_QUEUE)) ||
582 ((!ieee->softmac_data_hard_start_xmit &&
583 (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
ecdfa446
GKH
584 printk(KERN_WARNING "%s: No xmit handler.\n",
585 ieee->dev->name);
586 goto success;
587 }
588
589
f38d223b 590 if (likely(ieee->raw_tx == 0)) {
ecdfa446
GKH
591 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
592 printk(KERN_WARNING "%s: skb too small (%d).\n",
593 ieee->dev->name, skb->len);
594 goto success;
595 }
94a79942
LF
596 /* Save source and destination addresses */
597 memcpy(dest, skb->data, ETH_ALEN);
598 memcpy(src, skb->data+ETH_ALEN, ETH_ALEN);
ecdfa446
GKH
599
600 memset(skb->cb, 0, sizeof(skb->cb));
601 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
602
f38d223b 603 if (ieee->iw_mode == IW_MODE_MONITOR) {
94a79942
LF
604 txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
605 if (unlikely(!txb)) {
f38d223b
LF
606 printk(KERN_WARNING "%s: Could not allocate "
607 "TXB\n",
94a79942
LF
608 ieee->dev->name);
609 goto failed;
610 }
ecdfa446 611
94a79942 612 txb->encrypted = 0;
198e0d17 613 txb->payload_size = cpu_to_le16(skb->len);
f38d223b
LF
614 memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
615 skb->len);
ecdfa446 616
ecdfa446
GKH
617 goto success;
618 }
ecdfa446 619
55dc4eb3 620 if (skb->len > 282) {
94a79942 621 if (ETH_P_IP == ether_type) {
f38d223b
LF
622 const struct iphdr *ip = (struct iphdr *)
623 ((u8 *)skb->data+14);
94a79942 624 if (IPPROTO_UDP == ip->protocol) {
f38d223b
LF
625 struct udphdr *udp;
626
627 udp = (struct udphdr *)((u8 *)ip +
628 (ip->ihl << 2));
629 if (((((u8 *)udp)[1] == 68) &&
630 (((u8 *)udp)[3] == 67)) ||
631 ((((u8 *)udp)[1] == 67) &&
632 (((u8 *)udp)[3] == 68))) {
65a43784 633 bdhcp = true;
94a79942 634 ieee->LPSDelayCnt = 200;
65a43784 635 }
636 }
f38d223b
LF
637 } else if (ETH_P_ARP == ether_type) {
638 printk(KERN_INFO "=================>DHCP "
639 "Protocol start tx ARP pkt!!\n");
94a79942 640 bdhcp = true;
f38d223b
LF
641 ieee->LPSDelayCnt =
642 ieee->current_network.tim.tim_count;
65a43784 643 }
94a79942 644 }
65a43784 645
94a79942 646 skb->priority = rtllib_classify(skb, IsAmsdu);
0ddcf5fd 647 crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
94a79942
LF
648 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
649 ieee->host_encrypt && crypt && crypt->ops;
650 if (!encrypt && ieee->ieee802_1x &&
f38d223b 651 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
94a79942
LF
652 stats->tx_dropped++;
653 goto success;
654 }
94a79942
LF
655 if (crypt && !encrypt && ether_type == ETH_P_PAE) {
656 struct eapol *eap = (struct eapol *)(skb->data +
f38d223b
LF
657 sizeof(struct ethhdr) - SNAP_SIZE -
658 sizeof(u16));
94a79942
LF
659 RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
660 eap_get_type(eap->type));
661 }
ecdfa446 662
94a79942
LF
663 /* Advance the SKB to the start of the payload */
664 skb_pull(skb, sizeof(struct ethhdr));
ecdfa446 665
f38d223b 666 /* Determine total amount of storage required for TXB packets */
94a79942 667 bytes = skb->len + SNAP_SIZE + sizeof(u16);
ecdfa446
GKH
668
669 if (encrypt)
94a79942 670 fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP;
ecdfa446 671 else
94a79942 672 fc = RTLLIB_FTYPE_DATA;
ecdfa446 673
94a79942
LF
674 if (qos_actived)
675 fc |= RTLLIB_STYPE_QOS_DATA;
ecdfa446 676 else
94a79942 677 fc |= RTLLIB_STYPE_DATA;
ecdfa446
GKH
678
679 if (ieee->iw_mode == IW_MODE_INFRA) {
94a79942 680 fc |= RTLLIB_FCTL_TODS;
ecdfa446
GKH
681 /* To DS: Addr1 = BSSID, Addr2 = SA,
682 Addr3 = DA */
f38d223b
LF
683 memcpy(&header.addr1, ieee->current_network.bssid,
684 ETH_ALEN);
ecdfa446 685 memcpy(&header.addr2, &src, ETH_ALEN);
94a79942 686 if (IsAmsdu)
f38d223b
LF
687 memcpy(&header.addr3,
688 ieee->current_network.bssid, ETH_ALEN);
94a79942
LF
689 else
690 memcpy(&header.addr3, &dest, ETH_ALEN);
ecdfa446
GKH
691 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
692 /* not From/To DS: Addr1 = DA, Addr2 = SA,
693 Addr3 = BSSID */
694 memcpy(&header.addr1, dest, ETH_ALEN);
695 memcpy(&header.addr2, src, ETH_ALEN);
f38d223b
LF
696 memcpy(&header.addr3, ieee->current_network.bssid,
697 ETH_ALEN);
ecdfa446
GKH
698 }
699
14fc4235 700 bIsMulticast = is_multicast_ether_addr(header.addr1);
94a79942 701
f38d223b 702 header.frame_ctl = cpu_to_le16(fc);
ecdfa446
GKH
703
704 /* Determine fragmentation size based on destination (multicast
705 * and broadcast are not fragmented) */
94a79942 706 if (bIsMulticast) {
ecdfa446
GKH
707 frag_size = MAX_FRAG_THRESHOLD;
708 qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
94a79942
LF
709 } else {
710 frag_size = ieee->fts;
ecdfa446
GKH
711 qos_ctl = 0;
712 }
713
94a79942
LF
714 if (qos_actived) {
715 hdr_len = RTLLIB_3ADDR_LEN + 2;
716
f38d223b
LF
717 /* in case we are a client verify acm is not set for this ac */
718 while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) {
719 printk(KERN_INFO "skb->priority = %x\n", skb->priority);
720 if (wme_downgrade_ac(skb))
721 break;
722 printk(KERN_INFO "converted skb->priority = %x\n",
723 skb->priority);
724 }
725 qos_ctl |= skb->priority;
726 header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID);
ecdfa446 727 } else {
94a79942 728 hdr_len = RTLLIB_3ADDR_LEN;
ecdfa446
GKH
729 }
730 /* Determine amount of payload per fragment. Regardless of if
f38d223b
LF
731 * this stack is providing the full 802.11 header, one will
732 * eventually be affixed to this fragment -- so we must account
733 * for it when determining the amount of payload space. */
ecdfa446
GKH
734 bytes_per_frag = frag_size - hdr_len;
735 if (ieee->config &
f38d223b 736 (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
94a79942 737 bytes_per_frag -= RTLLIB_FCS_LEN;
ecdfa446 738
cd017123 739 /* Each fragment may need to have room for encrypting
f38d223b 740 * pre/postfix */
94a79942 741 if (encrypt) {
32c44cb5
SM
742 bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
743 crypt->ops->extra_mpdu_postfix_len +
744 crypt->ops->extra_msdu_prefix_len +
745 crypt->ops->extra_msdu_postfix_len;
94a79942 746 }
ecdfa446
GKH
747 /* Number of fragments is the total bytes_per_frag /
748 * payload_per_fragment */
749 nr_frags = bytes / bytes_per_frag;
750 bytes_last_frag = bytes % bytes_per_frag;
751 if (bytes_last_frag)
752 nr_frags++;
753 else
754 bytes_last_frag = bytes_per_frag;
755
f38d223b
LF
756 /* When we allocate the TXB we allocate enough space for the
757 * reserve and full fragment bytes (bytes_per_frag doesn't
758 * include prefix, postfix, header, FCS, etc.) */
759 txb = rtllib_alloc_txb(nr_frags, frag_size +
760 ieee->tx_headroom, GFP_ATOMIC);
ecdfa446
GKH
761 if (unlikely(!txb)) {
762 printk(KERN_WARNING "%s: Could not allocate TXB\n",
763 ieee->dev->name);
764 goto failed;
765 }
766 txb->encrypted = encrypt;
198e0d17 767 txb->payload_size = cpu_to_le16(bytes);
ecdfa446 768
94a79942 769 if (qos_actived)
ecdfa446 770 txb->queue_index = UP2AC(skb->priority);
f38d223b
LF
771 else
772 txb->queue_index = WME_AC_BE;
ecdfa446 773
ecdfa446
GKH
774 for (i = 0; i < nr_frags; i++) {
775 skb_frag = txb->fragments[i];
f38d223b
LF
776 tcb_desc = (struct cb_desc *)(skb_frag->cb +
777 MAX_DEV_ADDR_SIZE);
778 if (qos_actived) {
94a79942 779 skb_frag->priority = skb->priority;
ecdfa446
GKH
780 tcb_desc->queue_index = UP2AC(skb->priority);
781 } else {
94a79942
LF
782 skb_frag->priority = WME_AC_BE;
783 tcb_desc->queue_index = WME_AC_BE;
ecdfa446
GKH
784 }
785 skb_reserve(skb_frag, ieee->tx_headroom);
786
f38d223b 787 if (encrypt) {
ecdfa446
GKH
788 if (ieee->hwsec_active)
789 tcb_desc->bHwSec = 1;
790 else
791 tcb_desc->bHwSec = 0;
f38d223b 792 skb_reserve(skb_frag,
32c44cb5
SM
793 crypt->ops->extra_mpdu_prefix_len +
794 crypt->ops->extra_msdu_prefix_len);
94a79942 795 } else {
ecdfa446
GKH
796 tcb_desc->bHwSec = 0;
797 }
f38d223b
LF
798 frag_hdr = (struct rtllib_hdr_3addrqos *)
799 skb_put(skb_frag, hdr_len);
ecdfa446
GKH
800 memcpy(frag_hdr, &header, hdr_len);
801
f38d223b
LF
802 /* If this is not the last fragment, then add the
803 * MOREFRAGS bit to the frame control */
ecdfa446
GKH
804 if (i != nr_frags - 1) {
805 frag_hdr->frame_ctl = cpu_to_le16(
94a79942 806 fc | RTLLIB_FCTL_MOREFRAGS);
ecdfa446
GKH
807 bytes = bytes_per_frag;
808
809 } else {
f38d223b 810 /* The last fragment has the remaining length */
ecdfa446
GKH
811 bytes = bytes_last_frag;
812 }
f38d223b
LF
813 if ((qos_actived) && (!bIsMulticast)) {
814 frag_hdr->seq_ctl =
198e0d17
RK
815 cpu_to_le16(rtllib_query_seqnum(ieee, skb_frag,
816 header.addr1));
f38d223b 817 frag_hdr->seq_ctl =
86005e16 818 cpu_to_le16(le16_to_cpu(frag_hdr->seq_ctl)<<4 | i);
ecdfa446 819 } else {
f38d223b
LF
820 frag_hdr->seq_ctl =
821 cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
ecdfa446 822 }
ecdfa446
GKH
823 /* Put a SNAP header on the first fragment */
824 if (i == 0) {
94a79942 825 rtllib_put_snap(
f38d223b
LF
826 skb_put(skb_frag, SNAP_SIZE +
827 sizeof(u16)), ether_type);
ecdfa446
GKH
828 bytes -= SNAP_SIZE + sizeof(u16);
829 }
830
831 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
832
833 /* Advance the SKB... */
834 skb_pull(skb, bytes);
835
f38d223b
LF
836 /* Encryption routine will move the header forward in
837 * order to insert the IV between the header and the
838 * payload */
ecdfa446 839 if (encrypt)
f38d223b
LF
840 rtllib_encrypt_fragment(ieee, skb_frag,
841 hdr_len);
ecdfa446 842 if (ieee->config &
f38d223b 843 (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
ecdfa446
GKH
844 skb_put(skb_frag, 4);
845 }
846
94a79942 847 if ((qos_actived) && (!bIsMulticast)) {
f38d223b
LF
848 if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
849 ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
850 else
851 ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
ecdfa446 852 } else {
f38d223b
LF
853 if (ieee->seq_ctrl[0] == 0xFFF)
854 ieee->seq_ctrl[0] = 0;
855 else
856 ieee->seq_ctrl[0]++;
ecdfa446 857 }
f38d223b 858 } else {
94a79942 859 if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) {
ecdfa446
GKH
860 printk(KERN_WARNING "%s: skb too small (%d).\n",
861 ieee->dev->name, skb->len);
862 goto success;
863 }
864
94a79942 865 txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
f38d223b 866 if (!txb) {
ecdfa446
GKH
867 printk(KERN_WARNING "%s: Could not allocate TXB\n",
868 ieee->dev->name);
869 goto failed;
870 }
871
872 txb->encrypted = 0;
198e0d17 873 txb->payload_size = cpu_to_le16(skb->len);
f38d223b
LF
874 memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
875 skb->len);
ecdfa446
GKH
876 }
877
878 success:
f38d223b
LF
879 if (txb) {
880 struct cb_desc *tcb_desc = (struct cb_desc *)
881 (txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
ecdfa446 882 tcb_desc->bTxEnableFwCalcDur = 1;
94a79942 883 tcb_desc->priority = skb->priority;
65a43784 884
94a79942 885 if (ether_type == ETH_P_PAE) {
f38d223b
LF
886 if (ieee->pHTInfo->IOTAction &
887 HT_IOT_ACT_WA_IOT_Broadcom) {
888 tcb_desc->data_rate =
889 MgntQuery_TxRateExcludeCCKRates(ieee);
94a79942 890 tcb_desc->bTxDisableRateFallBack = false;
f38d223b 891 } else {
94a79942 892 tcb_desc->data_rate = ieee->basic_rate;
65a43784 893 tcb_desc->bTxDisableRateFallBack = 1;
94a79942
LF
894 }
895
65a43784 896
897 tcb_desc->RATRIndex = 7;
898 tcb_desc->bTxUseDriverAssingedRate = 1;
94a79942
LF
899 } else {
900 if (is_multicast_ether_addr(header.addr1))
901 tcb_desc->bMulticast = 1;
902 if (is_broadcast_ether_addr(header.addr1))
903 tcb_desc->bBroadcast = 1;
94a79942 904 rtllib_txrate_selectmode(ieee, tcb_desc);
f38d223b 905 if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
94a79942
LF
906 tcb_desc->data_rate = ieee->basic_rate;
907 else
f38d223b
LF
908 tcb_desc->data_rate = CURRENT_RATE(ieee->mode,
909 ieee->rate, ieee->HTCurrentOperaRate);
910
4bb01423 911 if (bdhcp) {
f38d223b
LF
912 if (ieee->pHTInfo->IOTAction &
913 HT_IOT_ACT_WA_IOT_Broadcom) {
914 tcb_desc->data_rate =
915 MgntQuery_TxRateExcludeCCKRates(ieee);
94a79942 916 tcb_desc->bTxDisableRateFallBack = false;
f38d223b 917 } else {
94a79942
LF
918 tcb_desc->data_rate = MGN_1M;
919 tcb_desc->bTxDisableRateFallBack = 1;
920 }
65a43784 921
922
94a79942
LF
923 tcb_desc->RATRIndex = 7;
924 tcb_desc->bTxUseDriverAssingedRate = 1;
925 tcb_desc->bdhcp = 1;
926 }
927
928 rtllib_qurey_ShortPreambleMode(ieee, tcb_desc);
f38d223b
LF
929 rtllib_tx_query_agg_cap(ieee, txb->fragments[0],
930 tcb_desc);
94a79942
LF
931 rtllib_query_HTCapShortGI(ieee, tcb_desc);
932 rtllib_query_BandwidthMode(ieee, tcb_desc);
f38d223b
LF
933 rtllib_query_protectionmode(ieee, tcb_desc,
934 txb->fragments[0]);
94a79942 935 }
ecdfa446
GKH
936 }
937 spin_unlock_irqrestore(&ieee->lock, flags);
938 dev_kfree_skb_any(skb);
939 if (txb) {
f38d223b 940 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
94a79942 941 dev->stats.tx_packets++;
83efd529 942 dev->stats.tx_bytes += le16_to_cpu(txb->payload_size);
94a79942 943 rtllib_softmac_xmit(txb, ieee);
f38d223b 944 } else {
94a79942 945 if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
ecdfa446 946 stats->tx_packets++;
83efd529 947 stats->tx_bytes += le16_to_cpu(txb->payload_size);
ecdfa446
GKH
948 return 0;
949 }
94a79942 950 rtllib_txb_free(txb);
ecdfa446
GKH
951 }
952 }
953
954 return 0;
955
956 failed:
957 spin_unlock_irqrestore(&ieee->lock, flags);
958 netif_stop_queue(dev);
959 stats->tx_errors++;
960 return 1;
961
962}
94a79942
LF
963int rtllib_xmit(struct sk_buff *skb, struct net_device *dev)
964{
965 memset(skb->cb, 0, sizeof(skb->cb));
966 return rtllib_xmit_inter(skb, dev);
967}
3b28499c 968EXPORT_SYMBOL(rtllib_xmit);
This page took 0.492564 seconds and 5 git commands to generate.