staging: line6/pcm.c: Removed trailing whitespace
[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
28 Andrea Merello <andreamrl@tiscali.it>
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
174 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
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
GKH
233 txb->nr_frags = nr_frags;
234 txb->frag_size = txb_size;
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;
f38d223b 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;
f38d223b
LF
299 if (is_multicast_ether_addr(hdr->addr1) ||
300 is_broadcast_ether_addr(hdr->addr1))
ecdfa446 301 return;
65a43784 302
f38d223b 303 if (tcb_desc->bdhcp || ieee->CntAfterLink < 2)
94a79942 304 return;
65a43784 305
94a79942
LF
306 if (pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION)
307 return;
65a43784 308
94a79942 309 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
ecdfa446 310 return;
f38d223b
LF
311 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__);
ecdfa446
GKH
315 return;
316 }
f38d223b
LF
317 if (pTxTs->TxAdmittedBARecord.bValid == false) {
318 if (ieee->wpa_ie_len && (ieee->pairwise_key_type ==
319 KEY_TYPE_NA)) {
94a79942 320 ;
f38d223b 321 } else if (tcb_desc->bdhcp == 1) {
94a79942 322 ;
f38d223b 323 } else if (!pTxTs->bDisable_AddBa) {
94a79942
LF
324 TsStartAddBaProcess(ieee, pTxTs);
325 }
ecdfa446 326 goto FORCED_AGG_SETTING;
94a79942 327 } else if (pTxTs->bUsingBa == false) {
f38d223b
LF
328 if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum,
329 (pTxTs->TxCurSeq+1)%4096))
ecdfa446
GKH
330 pTxTs->bUsingBa = true;
331 else
332 goto FORCED_AGG_SETTING;
333 }
94a79942 334 if (ieee->iw_mode == IW_MODE_INFRA) {
ecdfa446
GKH
335 tcb_desc->bAMPDUEnable = true;
336 tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
337 tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
338 }
339 }
340FORCED_AGG_SETTING:
94a79942 341 switch (pHTInfo->ForcedAMPDUMode) {
f38d223b
LF
342 case HT_AGG_AUTO:
343 break;
344
345 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;
350
351 case HT_AGG_FORCE_DISABLE:
352 tcb_desc->bAMPDUEnable = false;
353 tcb_desc->ampdu_density = 0;
354 tcb_desc->ampdu_factor = 0;
355 break;
ecdfa446 356 }
f38d223b 357 return;
ecdfa446
GKH
358}
359
ec0dc6be 360static void rtllib_qurey_ShortPreambleMode(struct rtllib_device *ieee,
f38d223b 361 struct cb_desc *tcb_desc)
ecdfa446
GKH
362{
363 tcb_desc->bUseShortPreamble = false;
364 if (tcb_desc->data_rate == 2)
ecdfa446 365 return;
f38d223b
LF
366 else if (ieee->current_network.capability &
367 WLAN_CAPABILITY_SHORT_PREAMBLE)
ecdfa446 368 tcb_desc->bUseShortPreamble = true;
ecdfa446
GKH
369 return;
370}
94a79942 371
ec0dc6be 372static void rtllib_query_HTCapShortGI(struct rtllib_device *ieee,
f38d223b 373 struct cb_desc *tcb_desc)
ecdfa446 374{
7796d93e 375 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
ecdfa446 376
94a79942 377 tcb_desc->bUseShortGI = false;
ecdfa446 378
f38d223b 379 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
ecdfa446
GKH
380 return;
381
f38d223b 382 if (pHTInfo->bForcedShortGI) {
ecdfa446
GKH
383 tcb_desc->bUseShortGI = true;
384 return;
385 }
386
f38d223b 387 if ((pHTInfo->bCurBW40MHz == true) && pHTInfo->bCurShortGI40MHz)
ecdfa446 388 tcb_desc->bUseShortGI = true;
f38d223b 389 else if ((pHTInfo->bCurBW40MHz == false) && pHTInfo->bCurShortGI20MHz)
ecdfa446
GKH
390 tcb_desc->bUseShortGI = true;
391}
392
ec0dc6be
LF
393static void rtllib_query_BandwidthMode(struct rtllib_device *ieee,
394 struct cb_desc *tcb_desc)
ecdfa446 395{
7796d93e 396 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
ecdfa446
GKH
397
398 tcb_desc->bPacketBW = false;
399
f38d223b 400 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
ecdfa446
GKH
401 return;
402
94a79942 403 if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
ecdfa446
GKH
404 return;
405
f38d223b 406 if ((tcb_desc->data_rate & 0x80) == 0)
ecdfa446 407 return;
f38d223b
LF
408 if (pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz &&
409 !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
ecdfa446
GKH
410 tcb_desc->bPacketBW = true;
411 return;
412}
94a79942 413
ec0dc6be
LF
414static void rtllib_query_protectionmode(struct rtllib_device *ieee,
415 struct cb_desc *tcb_desc,
416 struct sk_buff *skb)
ecdfa446 417{
ecdfa446 418 tcb_desc->bRTSSTBC = false;
94a79942
LF
419 tcb_desc->bRTSUseShortGI = false;
420 tcb_desc->bCTSEnable = false;
421 tcb_desc->RTSSC = 0;
422 tcb_desc->bRTSBW = false;
ecdfa446 423
94a79942 424 if (tcb_desc->bBroadcast || tcb_desc->bMulticast)
ecdfa446
GKH
425 return;
426
94a79942 427 if (is_broadcast_ether_addr(skb->data+16))
ecdfa446
GKH
428 return;
429
f38d223b
LF
430 if (ieee->mode < IEEE_N_24G) {
431 if (skb->len > ieee->rts) {
ecdfa446
GKH
432 tcb_desc->bRTSEnable = true;
433 tcb_desc->rts_rate = MGN_24M;
f38d223b 434 } else if (ieee->current_network.buseprotection) {
ecdfa446
GKH
435 tcb_desc->bRTSEnable = true;
436 tcb_desc->bCTSEnable = true;
437 tcb_desc->rts_rate = MGN_24M;
438 }
ecdfa446 439 return;
f38d223b 440 } else {
7796d93e 441 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
f38d223b
LF
442 while (true) {
443 if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) {
94a79942
LF
444 tcb_desc->bCTSEnable = true;
445 tcb_desc->rts_rate = MGN_24M;
446 tcb_desc->bRTSEnable = true;
447 break;
f38d223b
LF
448 } else if (pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS |
449 HT_IOT_ACT_PURE_N_MODE)) {
94a79942
LF
450 tcb_desc->bRTSEnable = true;
451 tcb_desc->rts_rate = MGN_24M;
452 break;
453 }
f38d223b 454 if (ieee->current_network.buseprotection) {
ecdfa446
GKH
455 tcb_desc->bRTSEnable = true;
456 tcb_desc->bCTSEnable = true;
457 tcb_desc->rts_rate = MGN_24M;
458 break;
459 }
f38d223b 460 if (pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) {
ecdfa446 461 u8 HTOpMode = pHTInfo->CurrentOpMode;
f38d223b
LF
462 if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 ||
463 HTOpMode == 3)) ||
464 (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) {
94a79942 465 tcb_desc->rts_rate = MGN_24M;
ecdfa446
GKH
466 tcb_desc->bRTSEnable = true;
467 break;
468 }
469 }
f38d223b 470 if (skb->len > ieee->rts) {
94a79942 471 tcb_desc->rts_rate = MGN_24M;
ecdfa446
GKH
472 tcb_desc->bRTSEnable = true;
473 break;
474 }
f38d223b 475 if (tcb_desc->bAMPDUEnable) {
94a79942 476 tcb_desc->rts_rate = MGN_24M;
ecdfa446
GKH
477 tcb_desc->bRTSEnable = false;
478 break;
479 }
ecdfa446
GKH
480 goto NO_PROTECTION;
481 }
ecdfa446
GKH
482 }
483 if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
484 tcb_desc->bUseShortPreamble = true;
94a79942 485 if (ieee->iw_mode == IW_MODE_MASTER)
ecdfa446
GKH
486 goto NO_PROTECTION;
487 return;
488NO_PROTECTION:
489 tcb_desc->bRTSEnable = false;
490 tcb_desc->bCTSEnable = false;
f38d223b 491 tcb_desc->rts_rate = 0;
ecdfa446 492 tcb_desc->RTSSC = 0;
f38d223b 493 tcb_desc->bRTSBW = false;
ecdfa446
GKH
494}
495
496
ec0dc6be
LF
497static void rtllib_txrate_selectmode(struct rtllib_device *ieee,
498 struct cb_desc *tcb_desc)
ecdfa446 499{
94a79942 500 if (ieee->bTxDisableRateFallBack)
ecdfa446
GKH
501 tcb_desc->bTxDisableRateFallBack = true;
502
94a79942 503 if (ieee->bTxUseDriverAssingedRate)
ecdfa446 504 tcb_desc->bTxUseDriverAssingedRate = true;
f38d223b
LF
505 if (!tcb_desc->bTxDisableRateFallBack ||
506 !tcb_desc->bTxUseDriverAssingedRate) {
507 if (ieee->iw_mode == IW_MODE_INFRA ||
508 ieee->iw_mode == IW_MODE_ADHOC)
ecdfa446
GKH
509 tcb_desc->RATRIndex = 0;
510 }
511}
512
f38d223b
LF
513u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb,
514 u8 *dst)
ecdfa446 515{
94a79942
LF
516 u16 seqnum = 0;
517
ecdfa446 518 if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst))
94a79942 519 return 0;
f38d223b 520 if (IsQoSDataFrame(skb->data)) {
60554f2b 521 struct tx_ts_record *pTS = NULL;
f38d223b
LF
522 if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
523 skb->priority, TX_DIR, true))
94a79942 524 return 0;
94a79942 525 seqnum = pTS->TxCurSeq;
ecdfa446 526 pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
94a79942
LF
527 return seqnum;
528 }
529 return 0;
530}
531
532static int wme_downgrade_ac(struct sk_buff *skb)
533{
534 switch (skb->priority) {
f38d223b
LF
535 case 6:
536 case 7:
537 skb->priority = 5; /* VO -> VI */
538 return 0;
539 case 4:
540 case 5:
541 skb->priority = 3; /* VI -> BE */
542 return 0;
543 case 0:
544 case 3:
545 skb->priority = 1; /* BE -> BK */
546 return 0;
547 default:
548 return -1;
ecdfa446
GKH
549 }
550}
551
94a79942 552int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
ecdfa446 553{
f38d223b
LF
554 struct rtllib_device *ieee = (struct rtllib_device *)
555 netdev_priv_rsl(dev);
94a79942
LF
556 struct rtllib_txb *txb = NULL;
557 struct rtllib_hdr_3addrqos *frag_hdr;
ecdfa446
GKH
558 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
559 unsigned long flags;
560 struct net_device_stats *stats = &ieee->stats;
561 int ether_type = 0, encrypt;
562 int bytes, fc, qos_ctl = 0, hdr_len;
563 struct sk_buff *skb_frag;
94a79942 564 struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */
ecdfa446
GKH
565 .duration_id = 0,
566 .seq_ctl = 0,
567 .qos_ctl = 0
568 };
569 u8 dest[ETH_ALEN], src[ETH_ALEN];
570 int qos_actived = ieee->current_network.qos_data.active;
32c44cb5 571 struct lib80211_crypt_data *crypt = NULL;
3b83db43 572 struct cb_desc *tcb_desc;
94a79942
LF
573 u8 bIsMulticast = false;
574 u8 IsAmsdu = false;
f38d223b 575 bool bdhcp = false;
ecdfa446
GKH
576
577 spin_lock_irqsave(&ieee->lock, flags);
578
cd017123 579 /* If there is no driver handler to take the TXB, don't bother
ecdfa446 580 * creating it... */
f38d223b
LF
581 if ((!ieee->hard_start_xmit && !(ieee->softmac_features &
582 IEEE_SOFTMAC_TX_QUEUE)) ||
583 ((!ieee->softmac_data_hard_start_xmit &&
584 (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
ecdfa446
GKH
585 printk(KERN_WARNING "%s: No xmit handler.\n",
586 ieee->dev->name);
587 goto success;
588 }
589
590
f38d223b 591 if (likely(ieee->raw_tx == 0)) {
ecdfa446
GKH
592 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
593 printk(KERN_WARNING "%s: skb too small (%d).\n",
594 ieee->dev->name, skb->len);
595 goto success;
596 }
94a79942
LF
597 /* Save source and destination addresses */
598 memcpy(dest, skb->data, ETH_ALEN);
599 memcpy(src, skb->data+ETH_ALEN, ETH_ALEN);
ecdfa446
GKH
600
601 memset(skb->cb, 0, sizeof(skb->cb));
602 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
603
f38d223b 604 if (ieee->iw_mode == IW_MODE_MONITOR) {
94a79942
LF
605 txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
606 if (unlikely(!txb)) {
f38d223b
LF
607 printk(KERN_WARNING "%s: Could not allocate "
608 "TXB\n",
94a79942
LF
609 ieee->dev->name);
610 goto failed;
611 }
ecdfa446 612
94a79942
LF
613 txb->encrypted = 0;
614 txb->payload_size = skb->len;
f38d223b
LF
615 memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
616 skb->len);
ecdfa446 617
ecdfa446
GKH
618 goto success;
619 }
ecdfa446 620
55dc4eb3 621 if (skb->len > 282) {
94a79942 622 if (ETH_P_IP == ether_type) {
f38d223b
LF
623 const struct iphdr *ip = (struct iphdr *)
624 ((u8 *)skb->data+14);
94a79942 625 if (IPPROTO_UDP == ip->protocol) {
f38d223b
LF
626 struct udphdr *udp;
627
628 udp = (struct udphdr *)((u8 *)ip +
629 (ip->ihl << 2));
630 if (((((u8 *)udp)[1] == 68) &&
631 (((u8 *)udp)[3] == 67)) ||
632 ((((u8 *)udp)[1] == 67) &&
633 (((u8 *)udp)[3] == 68))) {
65a43784 634 bdhcp = true;
94a79942 635 ieee->LPSDelayCnt = 200;
65a43784 636 }
637 }
f38d223b
LF
638 } else if (ETH_P_ARP == ether_type) {
639 printk(KERN_INFO "=================>DHCP "
640 "Protocol start tx ARP pkt!!\n");
94a79942 641 bdhcp = true;
f38d223b
LF
642 ieee->LPSDelayCnt =
643 ieee->current_network.tim.tim_count;
65a43784 644 }
94a79942 645 }
65a43784 646
94a79942 647 skb->priority = rtllib_classify(skb, IsAmsdu);
0ddcf5fd 648 crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
94a79942
LF
649 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
650 ieee->host_encrypt && crypt && crypt->ops;
651 if (!encrypt && ieee->ieee802_1x &&
f38d223b 652 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
94a79942
LF
653 stats->tx_dropped++;
654 goto success;
655 }
94a79942
LF
656 if (crypt && !encrypt && ether_type == ETH_P_PAE) {
657 struct eapol *eap = (struct eapol *)(skb->data +
f38d223b
LF
658 sizeof(struct ethhdr) - SNAP_SIZE -
659 sizeof(u16));
94a79942
LF
660 RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
661 eap_get_type(eap->type));
662 }
ecdfa446 663
94a79942
LF
664 /* Advance the SKB to the start of the payload */
665 skb_pull(skb, sizeof(struct ethhdr));
ecdfa446 666
f38d223b 667 /* Determine total amount of storage required for TXB packets */
94a79942 668 bytes = skb->len + SNAP_SIZE + sizeof(u16);
ecdfa446
GKH
669
670 if (encrypt)
94a79942 671 fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP;
ecdfa446 672 else
94a79942 673 fc = RTLLIB_FTYPE_DATA;
ecdfa446 674
94a79942
LF
675 if (qos_actived)
676 fc |= RTLLIB_STYPE_QOS_DATA;
ecdfa446 677 else
94a79942 678 fc |= RTLLIB_STYPE_DATA;
ecdfa446
GKH
679
680 if (ieee->iw_mode == IW_MODE_INFRA) {
94a79942 681 fc |= RTLLIB_FCTL_TODS;
ecdfa446
GKH
682 /* To DS: Addr1 = BSSID, Addr2 = SA,
683 Addr3 = DA */
f38d223b
LF
684 memcpy(&header.addr1, ieee->current_network.bssid,
685 ETH_ALEN);
ecdfa446 686 memcpy(&header.addr2, &src, ETH_ALEN);
94a79942 687 if (IsAmsdu)
f38d223b
LF
688 memcpy(&header.addr3,
689 ieee->current_network.bssid, ETH_ALEN);
94a79942
LF
690 else
691 memcpy(&header.addr3, &dest, ETH_ALEN);
ecdfa446
GKH
692 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
693 /* not From/To DS: Addr1 = DA, Addr2 = SA,
694 Addr3 = BSSID */
695 memcpy(&header.addr1, dest, ETH_ALEN);
696 memcpy(&header.addr2, src, ETH_ALEN);
f38d223b
LF
697 memcpy(&header.addr3, ieee->current_network.bssid,
698 ETH_ALEN);
ecdfa446
GKH
699 }
700
f38d223b
LF
701 bIsMulticast = is_broadcast_ether_addr(header.addr1) ||
702 is_multicast_ether_addr(header.addr1);
94a79942 703
f38d223b 704 header.frame_ctl = cpu_to_le16(fc);
ecdfa446
GKH
705
706 /* Determine fragmentation size based on destination (multicast
707 * and broadcast are not fragmented) */
94a79942 708 if (bIsMulticast) {
ecdfa446
GKH
709 frag_size = MAX_FRAG_THRESHOLD;
710 qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
94a79942
LF
711 } else {
712 frag_size = ieee->fts;
ecdfa446
GKH
713 qos_ctl = 0;
714 }
715
94a79942
LF
716 if (qos_actived) {
717 hdr_len = RTLLIB_3ADDR_LEN + 2;
718
f38d223b
LF
719 /* in case we are a client verify acm is not set for this ac */
720 while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) {
721 printk(KERN_INFO "skb->priority = %x\n", skb->priority);
722 if (wme_downgrade_ac(skb))
723 break;
724 printk(KERN_INFO "converted skb->priority = %x\n",
725 skb->priority);
726 }
727 qos_ctl |= skb->priority;
728 header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID);
ecdfa446 729 } else {
94a79942 730 hdr_len = RTLLIB_3ADDR_LEN;
ecdfa446
GKH
731 }
732 /* Determine amount of payload per fragment. Regardless of if
f38d223b
LF
733 * this stack is providing the full 802.11 header, one will
734 * eventually be affixed to this fragment -- so we must account
735 * for it when determining the amount of payload space. */
ecdfa446
GKH
736 bytes_per_frag = frag_size - hdr_len;
737 if (ieee->config &
f38d223b 738 (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
94a79942 739 bytes_per_frag -= RTLLIB_FCS_LEN;
ecdfa446 740
cd017123 741 /* Each fragment may need to have room for encrypting
f38d223b 742 * pre/postfix */
94a79942 743 if (encrypt) {
32c44cb5
SM
744 bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
745 crypt->ops->extra_mpdu_postfix_len +
746 crypt->ops->extra_msdu_prefix_len +
747 crypt->ops->extra_msdu_postfix_len;
94a79942 748 }
ecdfa446
GKH
749 /* Number of fragments is the total bytes_per_frag /
750 * payload_per_fragment */
751 nr_frags = bytes / bytes_per_frag;
752 bytes_last_frag = bytes % bytes_per_frag;
753 if (bytes_last_frag)
754 nr_frags++;
755 else
756 bytes_last_frag = bytes_per_frag;
757
f38d223b
LF
758 /* When we allocate the TXB we allocate enough space for the
759 * reserve and full fragment bytes (bytes_per_frag doesn't
760 * include prefix, postfix, header, FCS, etc.) */
761 txb = rtllib_alloc_txb(nr_frags, frag_size +
762 ieee->tx_headroom, GFP_ATOMIC);
ecdfa446
GKH
763 if (unlikely(!txb)) {
764 printk(KERN_WARNING "%s: Could not allocate TXB\n",
765 ieee->dev->name);
766 goto failed;
767 }
768 txb->encrypted = encrypt;
769 txb->payload_size = bytes;
770
94a79942 771 if (qos_actived)
ecdfa446 772 txb->queue_index = UP2AC(skb->priority);
f38d223b
LF
773 else
774 txb->queue_index = WME_AC_BE;
ecdfa446 775
ecdfa446
GKH
776 for (i = 0; i < nr_frags; i++) {
777 skb_frag = txb->fragments[i];
f38d223b
LF
778 tcb_desc = (struct cb_desc *)(skb_frag->cb +
779 MAX_DEV_ADDR_SIZE);
780 if (qos_actived) {
94a79942 781 skb_frag->priority = skb->priority;
ecdfa446
GKH
782 tcb_desc->queue_index = UP2AC(skb->priority);
783 } else {
94a79942
LF
784 skb_frag->priority = WME_AC_BE;
785 tcb_desc->queue_index = WME_AC_BE;
ecdfa446
GKH
786 }
787 skb_reserve(skb_frag, ieee->tx_headroom);
788
f38d223b 789 if (encrypt) {
ecdfa446
GKH
790 if (ieee->hwsec_active)
791 tcb_desc->bHwSec = 1;
792 else
793 tcb_desc->bHwSec = 0;
f38d223b 794 skb_reserve(skb_frag,
32c44cb5
SM
795 crypt->ops->extra_mpdu_prefix_len +
796 crypt->ops->extra_msdu_prefix_len);
94a79942 797 } else {
ecdfa446
GKH
798 tcb_desc->bHwSec = 0;
799 }
f38d223b
LF
800 frag_hdr = (struct rtllib_hdr_3addrqos *)
801 skb_put(skb_frag, hdr_len);
ecdfa446
GKH
802 memcpy(frag_hdr, &header, hdr_len);
803
f38d223b
LF
804 /* If this is not the last fragment, then add the
805 * MOREFRAGS bit to the frame control */
ecdfa446
GKH
806 if (i != nr_frags - 1) {
807 frag_hdr->frame_ctl = cpu_to_le16(
94a79942 808 fc | RTLLIB_FCTL_MOREFRAGS);
ecdfa446
GKH
809 bytes = bytes_per_frag;
810
811 } else {
f38d223b 812 /* The last fragment has the remaining length */
ecdfa446
GKH
813 bytes = bytes_last_frag;
814 }
f38d223b
LF
815 if ((qos_actived) && (!bIsMulticast)) {
816 frag_hdr->seq_ctl =
817 rtllib_query_seqnum(ieee, skb_frag,
818 header.addr1);
819 frag_hdr->seq_ctl =
820 cpu_to_le16(frag_hdr->seq_ctl<<4 | i);
ecdfa446 821 } else {
f38d223b
LF
822 frag_hdr->seq_ctl =
823 cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
ecdfa446 824 }
ecdfa446
GKH
825 /* Put a SNAP header on the first fragment */
826 if (i == 0) {
94a79942 827 rtllib_put_snap(
f38d223b
LF
828 skb_put(skb_frag, SNAP_SIZE +
829 sizeof(u16)), ether_type);
ecdfa446
GKH
830 bytes -= SNAP_SIZE + sizeof(u16);
831 }
832
833 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
834
835 /* Advance the SKB... */
836 skb_pull(skb, bytes);
837
f38d223b
LF
838 /* Encryption routine will move the header forward in
839 * order to insert the IV between the header and the
840 * payload */
ecdfa446 841 if (encrypt)
f38d223b
LF
842 rtllib_encrypt_fragment(ieee, skb_frag,
843 hdr_len);
ecdfa446 844 if (ieee->config &
f38d223b 845 (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
ecdfa446
GKH
846 skb_put(skb_frag, 4);
847 }
848
94a79942 849 if ((qos_actived) && (!bIsMulticast)) {
f38d223b
LF
850 if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
851 ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
852 else
853 ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
ecdfa446 854 } else {
f38d223b
LF
855 if (ieee->seq_ctrl[0] == 0xFFF)
856 ieee->seq_ctrl[0] = 0;
857 else
858 ieee->seq_ctrl[0]++;
ecdfa446 859 }
f38d223b 860 } else {
94a79942 861 if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) {
ecdfa446
GKH
862 printk(KERN_WARNING "%s: skb too small (%d).\n",
863 ieee->dev->name, skb->len);
864 goto success;
865 }
866
94a79942 867 txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
f38d223b 868 if (!txb) {
ecdfa446
GKH
869 printk(KERN_WARNING "%s: Could not allocate TXB\n",
870 ieee->dev->name);
871 goto failed;
872 }
873
874 txb->encrypted = 0;
875 txb->payload_size = skb->len;
f38d223b
LF
876 memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
877 skb->len);
ecdfa446
GKH
878 }
879
880 success:
f38d223b
LF
881 if (txb) {
882 struct cb_desc *tcb_desc = (struct cb_desc *)
883 (txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
ecdfa446 884 tcb_desc->bTxEnableFwCalcDur = 1;
94a79942 885 tcb_desc->priority = skb->priority;
65a43784 886
94a79942 887 if (ether_type == ETH_P_PAE) {
f38d223b
LF
888 if (ieee->pHTInfo->IOTAction &
889 HT_IOT_ACT_WA_IOT_Broadcom) {
890 tcb_desc->data_rate =
891 MgntQuery_TxRateExcludeCCKRates(ieee);
94a79942 892 tcb_desc->bTxDisableRateFallBack = false;
f38d223b 893 } else {
94a79942 894 tcb_desc->data_rate = ieee->basic_rate;
65a43784 895 tcb_desc->bTxDisableRateFallBack = 1;
94a79942
LF
896 }
897
65a43784 898
899 tcb_desc->RATRIndex = 7;
900 tcb_desc->bTxUseDriverAssingedRate = 1;
94a79942
LF
901 } else {
902 if (is_multicast_ether_addr(header.addr1))
903 tcb_desc->bMulticast = 1;
904 if (is_broadcast_ether_addr(header.addr1))
905 tcb_desc->bBroadcast = 1;
94a79942 906 rtllib_txrate_selectmode(ieee, tcb_desc);
f38d223b 907 if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
94a79942
LF
908 tcb_desc->data_rate = ieee->basic_rate;
909 else
f38d223b
LF
910 tcb_desc->data_rate = CURRENT_RATE(ieee->mode,
911 ieee->rate, ieee->HTCurrentOperaRate);
912
913 if (bdhcp == true) {
914 if (ieee->pHTInfo->IOTAction &
915 HT_IOT_ACT_WA_IOT_Broadcom) {
916 tcb_desc->data_rate =
917 MgntQuery_TxRateExcludeCCKRates(ieee);
94a79942 918 tcb_desc->bTxDisableRateFallBack = false;
f38d223b 919 } else {
94a79942
LF
920 tcb_desc->data_rate = MGN_1M;
921 tcb_desc->bTxDisableRateFallBack = 1;
922 }
65a43784 923
924
94a79942
LF
925 tcb_desc->RATRIndex = 7;
926 tcb_desc->bTxUseDriverAssingedRate = 1;
927 tcb_desc->bdhcp = 1;
928 }
929
930 rtllib_qurey_ShortPreambleMode(ieee, tcb_desc);
f38d223b
LF
931 rtllib_tx_query_agg_cap(ieee, txb->fragments[0],
932 tcb_desc);
94a79942
LF
933 rtllib_query_HTCapShortGI(ieee, tcb_desc);
934 rtllib_query_BandwidthMode(ieee, tcb_desc);
f38d223b
LF
935 rtllib_query_protectionmode(ieee, tcb_desc,
936 txb->fragments[0]);
94a79942 937 }
ecdfa446
GKH
938 }
939 spin_unlock_irqrestore(&ieee->lock, flags);
940 dev_kfree_skb_any(skb);
941 if (txb) {
f38d223b 942 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
94a79942
LF
943 dev->stats.tx_packets++;
944 dev->stats.tx_bytes += txb->payload_size;
945 rtllib_softmac_xmit(txb, ieee);
f38d223b 946 } else {
94a79942 947 if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
ecdfa446
GKH
948 stats->tx_packets++;
949 stats->tx_bytes += txb->payload_size;
950 return 0;
951 }
94a79942 952 rtllib_txb_free(txb);
ecdfa446
GKH
953 }
954 }
955
956 return 0;
957
958 failed:
959 spin_unlock_irqrestore(&ieee->lock, flags);
960 netif_stop_queue(dev);
961 stats->tx_errors++;
962 return 1;
963
964}
94a79942
LF
965int rtllib_xmit(struct sk_buff *skb, struct net_device *dev)
966{
967 memset(skb->cb, 0, sizeof(skb->cb));
968 return rtllib_xmit_inter(skb, dev);
969}
3b28499c 970EXPORT_SYMBOL(rtllib_xmit);
This page took 0.582812 seconds and 5 git commands to generate.