blob: f451bfc27a86742c6db849404c47a89620906341 [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
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>
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
62802.11 frame_contorl for data frames - 2 bytes
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 |
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
174 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
175
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;
Larry Fingerf38d2232011-08-25 11:48:28 -0500227 txb = kmalloc(sizeof(struct rtllib_txb) + (sizeof(u8 *) * nr_frags),
228 gfp_mask);
Larry Finger94a79942011-08-23 19:00:42 -0500229 if (!txb)
230 return NULL;
231
232 memset(txb, 0, sizeof(struct rtllib_txb));
233 txb->nr_frags = nr_frags;
234 txb->frag_size = txb_size;
235
236 for (i = 0; i < nr_frags; i++) {
Larry Finger94a79942011-08-23 19:00:42 -0500237 txb->fragments[i] = dev_alloc_skb(txb_size);
Larry Finger94a79942011-08-23 19:00:42 -0500238 if (unlikely(!txb->fragments[i])) {
239 i--;
240 break;
241 }
Larry Finger94a79942011-08-23 19:00:42 -0500242 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
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500253static int rtllib_classify(struct sk_buff *skb, u8 bIsAmsdu)
Larry Finger94a79942011-08-23 19:00:42 -0500254{
255 struct ethhdr *eth;
256 struct iphdr *ip;
257
258 eth = (struct ethhdr *)skb->data;
259 if (eth->h_proto != htons(ETH_P_IP))
260 return 0;
261
262 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA, skb->data, skb->len);
263 ip = ip_hdr(skb);
264 switch (ip->tos & 0xfc) {
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;
281 }
282}
283
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500284static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee,
285 struct sk_buff *skb,
286 struct cb_desc *tcb_desc)
Larry Finger94a79942011-08-23 19:00:42 -0500287{
Larry Finger7796d932011-07-18 20:22:19 -0500288 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
Larry Finger60554f22011-07-18 20:10:03 -0500289 struct tx_ts_record *pTxTs = NULL;
Larry Fingerf38d2232011-08-25 11:48:28 -0500290 struct rtllib_hdr_1addr* hdr = (struct rtllib_hdr_1addr *)skb->data;
Larry Finger94a79942011-08-23 19:00:42 -0500291
Larry Fingerf38d2232011-08-25 11:48:28 -0500292 if (rtllib_act_scanning(ieee, false))
Larry Finger94a79942011-08-23 19:00:42 -0500293 return;
294
Larry Fingerf38d2232011-08-25 11:48:28 -0500295 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
Larry Finger94a79942011-08-23 19:00:42 -0500296 return;
297 if (!IsQoSDataFrame(skb->data))
298 return;
Larry Fingerf38d2232011-08-25 11:48:28 -0500299 if (is_multicast_ether_addr(hdr->addr1) ||
300 is_broadcast_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;
Larry Fingerf38d2232011-08-25 11:48:28 -0500442 while (true) {
443 if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) {
Larry Finger94a79942011-08-23 19:00:42 -0500444 tcb_desc->bCTSEnable = true;
445 tcb_desc->rts_rate = MGN_24M;
446 tcb_desc->bRTSEnable = true;
447 break;
Larry Fingerf38d2232011-08-25 11:48:28 -0500448 } else if (pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS |
449 HT_IOT_ACT_PURE_N_MODE)) {
Larry Finger94a79942011-08-23 19:00:42 -0500450 tcb_desc->bRTSEnable = true;
451 tcb_desc->rts_rate = MGN_24M;
452 break;
453 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500454 if (ieee->current_network.buseprotection) {
Larry Finger94a79942011-08-23 19:00:42 -0500455 tcb_desc->bRTSEnable = true;
456 tcb_desc->bCTSEnable = true;
457 tcb_desc->rts_rate = MGN_24M;
458 break;
459 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500460 if (pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) {
Larry Finger94a79942011-08-23 19:00:42 -0500461 u8 HTOpMode = pHTInfo->CurrentOpMode;
Larry Fingerf38d2232011-08-25 11:48:28 -0500462 if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 ||
463 HTOpMode == 3)) ||
464 (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) {
Larry Finger94a79942011-08-23 19:00:42 -0500465 tcb_desc->rts_rate = MGN_24M;
466 tcb_desc->bRTSEnable = true;
467 break;
468 }
469 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500470 if (skb->len > ieee->rts) {
Larry Finger94a79942011-08-23 19:00:42 -0500471 tcb_desc->rts_rate = MGN_24M;
472 tcb_desc->bRTSEnable = true;
473 break;
474 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500475 if (tcb_desc->bAMPDUEnable) {
Larry Finger94a79942011-08-23 19:00:42 -0500476 tcb_desc->rts_rate = MGN_24M;
477 tcb_desc->bRTSEnable = false;
478 break;
479 }
480 goto NO_PROTECTION;
481 }
Larry Finger94a79942011-08-23 19:00:42 -0500482 }
483 if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
484 tcb_desc->bUseShortPreamble = true;
485 if (ieee->iw_mode == IW_MODE_MASTER)
486 goto NO_PROTECTION;
487 return;
488NO_PROTECTION:
489 tcb_desc->bRTSEnable = false;
490 tcb_desc->bCTSEnable = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500491 tcb_desc->rts_rate = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500492 tcb_desc->RTSSC = 0;
Larry Fingerf38d2232011-08-25 11:48:28 -0500493 tcb_desc->bRTSBW = false;
Larry Finger94a79942011-08-23 19:00:42 -0500494}
495
496
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500497static void rtllib_txrate_selectmode(struct rtllib_device *ieee,
498 struct cb_desc *tcb_desc)
Larry Finger94a79942011-08-23 19:00:42 -0500499{
Larry Finger94a79942011-08-23 19:00:42 -0500500 if (ieee->bTxDisableRateFallBack)
501 tcb_desc->bTxDisableRateFallBack = true;
502
503 if (ieee->bTxUseDriverAssingedRate)
504 tcb_desc->bTxUseDriverAssingedRate = true;
Larry Fingerf38d2232011-08-25 11:48:28 -0500505 if (!tcb_desc->bTxDisableRateFallBack ||
506 !tcb_desc->bTxUseDriverAssingedRate) {
507 if (ieee->iw_mode == IW_MODE_INFRA ||
508 ieee->iw_mode == IW_MODE_ADHOC)
Larry Finger94a79942011-08-23 19:00:42 -0500509 tcb_desc->RATRIndex = 0;
510 }
511}
512
Larry Fingerf38d2232011-08-25 11:48:28 -0500513u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb,
514 u8 *dst)
Larry Finger94a79942011-08-23 19:00:42 -0500515{
516 u16 seqnum = 0;
517
518 if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst))
519 return 0;
Larry Fingerf38d2232011-08-25 11:48:28 -0500520 if (IsQoSDataFrame(skb->data)) {
Larry Finger60554f22011-07-18 20:10:03 -0500521 struct tx_ts_record *pTS = NULL;
Larry Fingerf38d2232011-08-25 11:48:28 -0500522 if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
523 skb->priority, TX_DIR, true))
Larry Finger94a79942011-08-23 19:00:42 -0500524 return 0;
Larry Finger94a79942011-08-23 19:00:42 -0500525 seqnum = pTS->TxCurSeq;
526 pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
527 return seqnum;
528 }
529 return 0;
530}
531
532static int wme_downgrade_ac(struct sk_buff *skb)
533{
534 switch (skb->priority) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500535 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;
Larry Finger94a79942011-08-23 19:00:42 -0500549 }
550}
551
552int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
553{
Larry Fingerf38d2232011-08-25 11:48:28 -0500554 struct rtllib_device *ieee = (struct rtllib_device *)
555 netdev_priv_rsl(dev);
Larry Finger94a79942011-08-23 19:00:42 -0500556 struct rtllib_txb *txb = NULL;
557 struct rtllib_hdr_3addrqos *frag_hdr;
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;
564 struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */
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;
Sean MacLennan32c44cb2011-12-19 23:20:41 -0500571 struct lib80211_crypt_data *crypt = NULL;
Larry Finger3b83db42011-07-19 00:01:29 -0500572 struct cb_desc *tcb_desc;
Larry Finger94a79942011-08-23 19:00:42 -0500573 u8 bIsMulticast = false;
574 u8 IsAmsdu = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500575 bool bdhcp = false;
Larry Finger94a79942011-08-23 19:00:42 -0500576
Larry Finger94a79942011-08-23 19:00:42 -0500577 spin_lock_irqsave(&ieee->lock, flags);
578
579 /* If there is no driver handler to take the TXB, dont' bother
580 * creating it... */
Larry Fingerf38d2232011-08-25 11:48:28 -0500581 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)))) {
Larry Finger94a79942011-08-23 19:00:42 -0500585 printk(KERN_WARNING "%s: No xmit handler.\n",
586 ieee->dev->name);
587 goto success;
588 }
589
590
Larry Fingerf38d2232011-08-25 11:48:28 -0500591 if (likely(ieee->raw_tx == 0)) {
Larry Finger94a79942011-08-23 19:00:42 -0500592 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 }
597 /* Save source and destination addresses */
598 memcpy(dest, skb->data, ETH_ALEN);
599 memcpy(src, skb->data+ETH_ALEN, ETH_ALEN);
600
601 memset(skb->cb, 0, sizeof(skb->cb));
602 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
603
Larry Fingerf38d2232011-08-25 11:48:28 -0500604 if (ieee->iw_mode == IW_MODE_MONITOR) {
Larry Finger94a79942011-08-23 19:00:42 -0500605 txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
606 if (unlikely(!txb)) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500607 printk(KERN_WARNING "%s: Could not allocate "
608 "TXB\n",
Larry Finger94a79942011-08-23 19:00:42 -0500609 ieee->dev->name);
610 goto failed;
611 }
612
613 txb->encrypted = 0;
614 txb->payload_size = skb->len;
Larry Fingerf38d2232011-08-25 11:48:28 -0500615 memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
616 skb->len);
Larry Finger94a79942011-08-23 19:00:42 -0500617
618 goto success;
619 }
620
Larry Finger55dc4eb2011-08-25 11:48:13 -0500621 if (skb->len > 282) {
Larry Finger94a79942011-08-23 19:00:42 -0500622 if (ETH_P_IP == ether_type) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500623 const struct iphdr *ip = (struct iphdr *)
624 ((u8 *)skb->data+14);
Larry Finger94a79942011-08-23 19:00:42 -0500625 if (IPPROTO_UDP == ip->protocol) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500626 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))) {
Larry Finger94a79942011-08-23 19:00:42 -0500634 bdhcp = true;
635 ieee->LPSDelayCnt = 200;
636 }
637 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500638 } else if (ETH_P_ARP == ether_type) {
639 printk(KERN_INFO "=================>DHCP "
640 "Protocol start tx ARP pkt!!\n");
Larry Finger94a79942011-08-23 19:00:42 -0500641 bdhcp = true;
Larry Fingerf38d2232011-08-25 11:48:28 -0500642 ieee->LPSDelayCnt =
643 ieee->current_network.tim.tim_count;
Larry Finger94a79942011-08-23 19:00:42 -0500644 }
645 }
646
647 skb->priority = rtllib_classify(skb, IsAmsdu);
Sean MacLennan0ddcf5f2011-12-19 23:21:41 -0500648 crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
Larry Finger94a79942011-08-23 19:00:42 -0500649 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
650 ieee->host_encrypt && crypt && crypt->ops;
651 if (!encrypt && ieee->ieee802_1x &&
Larry Fingerf38d2232011-08-25 11:48:28 -0500652 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
Larry Finger94a79942011-08-23 19:00:42 -0500653 stats->tx_dropped++;
654 goto success;
655 }
Larry Finger94a79942011-08-23 19:00:42 -0500656 if (crypt && !encrypt && ether_type == ETH_P_PAE) {
657 struct eapol *eap = (struct eapol *)(skb->data +
Larry Fingerf38d2232011-08-25 11:48:28 -0500658 sizeof(struct ethhdr) - SNAP_SIZE -
659 sizeof(u16));
Larry Finger94a79942011-08-23 19:00:42 -0500660 RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
661 eap_get_type(eap->type));
662 }
Larry Finger94a79942011-08-23 19:00:42 -0500663
664 /* Advance the SKB to the start of the payload */
665 skb_pull(skb, sizeof(struct ethhdr));
666
Larry Fingerf38d2232011-08-25 11:48:28 -0500667 /* Determine total amount of storage required for TXB packets */
Larry Finger94a79942011-08-23 19:00:42 -0500668 bytes = skb->len + SNAP_SIZE + sizeof(u16);
669
670 if (encrypt)
671 fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP;
672 else
673 fc = RTLLIB_FTYPE_DATA;
674
675 if (qos_actived)
676 fc |= RTLLIB_STYPE_QOS_DATA;
677 else
678 fc |= RTLLIB_STYPE_DATA;
679
680 if (ieee->iw_mode == IW_MODE_INFRA) {
681 fc |= RTLLIB_FCTL_TODS;
682 /* To DS: Addr1 = BSSID, Addr2 = SA,
683 Addr3 = DA */
Larry Fingerf38d2232011-08-25 11:48:28 -0500684 memcpy(&header.addr1, ieee->current_network.bssid,
685 ETH_ALEN);
Larry Finger94a79942011-08-23 19:00:42 -0500686 memcpy(&header.addr2, &src, ETH_ALEN);
687 if (IsAmsdu)
Larry Fingerf38d2232011-08-25 11:48:28 -0500688 memcpy(&header.addr3,
689 ieee->current_network.bssid, ETH_ALEN);
Larry Finger94a79942011-08-23 19:00:42 -0500690 else
691 memcpy(&header.addr3, &dest, ETH_ALEN);
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);
Larry Fingerf38d2232011-08-25 11:48:28 -0500697 memcpy(&header.addr3, ieee->current_network.bssid,
698 ETH_ALEN);
Larry Finger94a79942011-08-23 19:00:42 -0500699 }
700
Larry Fingerf38d2232011-08-25 11:48:28 -0500701 bIsMulticast = is_broadcast_ether_addr(header.addr1) ||
702 is_multicast_ether_addr(header.addr1);
Larry Finger94a79942011-08-23 19:00:42 -0500703
Larry Fingerf38d2232011-08-25 11:48:28 -0500704 header.frame_ctl = cpu_to_le16(fc);
Larry Finger94a79942011-08-23 19:00:42 -0500705
706 /* Determine fragmentation size based on destination (multicast
707 * and broadcast are not fragmented) */
708 if (bIsMulticast) {
709 frag_size = MAX_FRAG_THRESHOLD;
710 qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
711 } else {
712 frag_size = ieee->fts;
713 qos_ctl = 0;
714 }
715
716 if (qos_actived) {
717 hdr_len = RTLLIB_3ADDR_LEN + 2;
718
Larry Fingerf38d2232011-08-25 11:48:28 -0500719 /* 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);
Larry Finger94a79942011-08-23 19:00:42 -0500729 } else {
730 hdr_len = RTLLIB_3ADDR_LEN;
731 }
732 /* Determine amount of payload per fragment. Regardless of if
Larry Fingerf38d2232011-08-25 11:48:28 -0500733 * 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. */
Larry Finger94a79942011-08-23 19:00:42 -0500736 bytes_per_frag = frag_size - hdr_len;
737 if (ieee->config &
Larry Fingerf38d2232011-08-25 11:48:28 -0500738 (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
Larry Finger94a79942011-08-23 19:00:42 -0500739 bytes_per_frag -= RTLLIB_FCS_LEN;
740
Larry Fingerf38d2232011-08-25 11:48:28 -0500741 /* Each fragment may need to have room for encryptiong
742 * pre/postfix */
Larry Finger94a79942011-08-23 19:00:42 -0500743 if (encrypt) {
Sean MacLennan32c44cb2011-12-19 23:20:41 -0500744 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;
Larry Finger94a79942011-08-23 19:00:42 -0500748 }
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
Larry Fingerf38d2232011-08-25 11:48:28 -0500758 /* 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);
Larry Finger94a79942011-08-23 19:00:42 -0500763 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
771 if (qos_actived)
Larry Finger94a79942011-08-23 19:00:42 -0500772 txb->queue_index = UP2AC(skb->priority);
Larry Fingerf38d2232011-08-25 11:48:28 -0500773 else
774 txb->queue_index = WME_AC_BE;
Larry Finger94a79942011-08-23 19:00:42 -0500775
776 for (i = 0; i < nr_frags; i++) {
777 skb_frag = txb->fragments[i];
Larry Fingerf38d2232011-08-25 11:48:28 -0500778 tcb_desc = (struct cb_desc *)(skb_frag->cb +
779 MAX_DEV_ADDR_SIZE);
780 if (qos_actived) {
Larry Finger94a79942011-08-23 19:00:42 -0500781 skb_frag->priority = skb->priority;
782 tcb_desc->queue_index = UP2AC(skb->priority);
783 } else {
784 skb_frag->priority = WME_AC_BE;
785 tcb_desc->queue_index = WME_AC_BE;
786 }
787 skb_reserve(skb_frag, ieee->tx_headroom);
788
Larry Fingerf38d2232011-08-25 11:48:28 -0500789 if (encrypt) {
Larry Finger94a79942011-08-23 19:00:42 -0500790 if (ieee->hwsec_active)
791 tcb_desc->bHwSec = 1;
792 else
793 tcb_desc->bHwSec = 0;
Larry Fingerf38d2232011-08-25 11:48:28 -0500794 skb_reserve(skb_frag,
Sean MacLennan32c44cb2011-12-19 23:20:41 -0500795 crypt->ops->extra_mpdu_prefix_len +
796 crypt->ops->extra_msdu_prefix_len);
Larry Finger94a79942011-08-23 19:00:42 -0500797 } else {
798 tcb_desc->bHwSec = 0;
799 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500800 frag_hdr = (struct rtllib_hdr_3addrqos *)
801 skb_put(skb_frag, hdr_len);
Larry Finger94a79942011-08-23 19:00:42 -0500802 memcpy(frag_hdr, &header, hdr_len);
803
Larry Fingerf38d2232011-08-25 11:48:28 -0500804 /* If this is not the last fragment, then add the
805 * MOREFRAGS bit to the frame control */
Larry Finger94a79942011-08-23 19:00:42 -0500806 if (i != nr_frags - 1) {
807 frag_hdr->frame_ctl = cpu_to_le16(
808 fc | RTLLIB_FCTL_MOREFRAGS);
809 bytes = bytes_per_frag;
810
811 } else {
Larry Fingerf38d2232011-08-25 11:48:28 -0500812 /* The last fragment has the remaining length */
Larry Finger94a79942011-08-23 19:00:42 -0500813 bytes = bytes_last_frag;
814 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500815 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);
Larry Finger94a79942011-08-23 19:00:42 -0500821 } else {
Larry Fingerf38d2232011-08-25 11:48:28 -0500822 frag_hdr->seq_ctl =
823 cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
Larry Finger94a79942011-08-23 19:00:42 -0500824 }
825 /* Put a SNAP header on the first fragment */
826 if (i == 0) {
827 rtllib_put_snap(
Larry Fingerf38d2232011-08-25 11:48:28 -0500828 skb_put(skb_frag, SNAP_SIZE +
829 sizeof(u16)), ether_type);
Larry Finger94a79942011-08-23 19:00:42 -0500830 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
Larry Fingerf38d2232011-08-25 11:48:28 -0500838 /* Encryption routine will move the header forward in
839 * order to insert the IV between the header and the
840 * payload */
Larry Finger94a79942011-08-23 19:00:42 -0500841 if (encrypt)
Larry Fingerf38d2232011-08-25 11:48:28 -0500842 rtllib_encrypt_fragment(ieee, skb_frag,
843 hdr_len);
Larry Finger94a79942011-08-23 19:00:42 -0500844 if (ieee->config &
Larry Fingerf38d2232011-08-25 11:48:28 -0500845 (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
Larry Finger94a79942011-08-23 19:00:42 -0500846 skb_put(skb_frag, 4);
847 }
848
849 if ((qos_actived) && (!bIsMulticast)) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500850 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]++;
Larry Finger94a79942011-08-23 19:00:42 -0500854 } else {
Larry Fingerf38d2232011-08-25 11:48:28 -0500855 if (ieee->seq_ctrl[0] == 0xFFF)
856 ieee->seq_ctrl[0] = 0;
857 else
858 ieee->seq_ctrl[0]++;
Larry Finger94a79942011-08-23 19:00:42 -0500859 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500860 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500861 if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) {
862 printk(KERN_WARNING "%s: skb too small (%d).\n",
863 ieee->dev->name, skb->len);
864 goto success;
865 }
866
867 txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
Larry Fingerf38d2232011-08-25 11:48:28 -0500868 if (!txb) {
Larry Finger94a79942011-08-23 19:00:42 -0500869 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;
Larry Fingerf38d2232011-08-25 11:48:28 -0500876 memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
877 skb->len);
Larry Finger94a79942011-08-23 19:00:42 -0500878 }
879
880 success:
Larry Fingerf38d2232011-08-25 11:48:28 -0500881 if (txb) {
882 struct cb_desc *tcb_desc = (struct cb_desc *)
883 (txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
Larry Finger94a79942011-08-23 19:00:42 -0500884 tcb_desc->bTxEnableFwCalcDur = 1;
885 tcb_desc->priority = skb->priority;
886
887 if (ether_type == ETH_P_PAE) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500888 if (ieee->pHTInfo->IOTAction &
889 HT_IOT_ACT_WA_IOT_Broadcom) {
890 tcb_desc->data_rate =
891 MgntQuery_TxRateExcludeCCKRates(ieee);
Larry Finger94a79942011-08-23 19:00:42 -0500892 tcb_desc->bTxDisableRateFallBack = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500893 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500894 tcb_desc->data_rate = ieee->basic_rate;
895 tcb_desc->bTxDisableRateFallBack = 1;
896 }
897
898
899 tcb_desc->RATRIndex = 7;
900 tcb_desc->bTxUseDriverAssingedRate = 1;
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;
Larry Finger94a79942011-08-23 19:00:42 -0500906 rtllib_txrate_selectmode(ieee, tcb_desc);
Larry Fingerf38d2232011-08-25 11:48:28 -0500907 if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
Larry Finger94a79942011-08-23 19:00:42 -0500908 tcb_desc->data_rate = ieee->basic_rate;
909 else
Larry Fingerf38d2232011-08-25 11:48:28 -0500910 tcb_desc->data_rate = CURRENT_RATE(ieee->mode,
911 ieee->rate, ieee->HTCurrentOperaRate);
Larry Finger94a79942011-08-23 19:00:42 -0500912
Larry Fingerf38d2232011-08-25 11:48:28 -0500913 if (bdhcp == true) {
914 if (ieee->pHTInfo->IOTAction &
915 HT_IOT_ACT_WA_IOT_Broadcom) {
916 tcb_desc->data_rate =
917 MgntQuery_TxRateExcludeCCKRates(ieee);
Larry Finger94a79942011-08-23 19:00:42 -0500918 tcb_desc->bTxDisableRateFallBack = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500919 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500920 tcb_desc->data_rate = MGN_1M;
921 tcb_desc->bTxDisableRateFallBack = 1;
922 }
923
924
925 tcb_desc->RATRIndex = 7;
926 tcb_desc->bTxUseDriverAssingedRate = 1;
927 tcb_desc->bdhcp = 1;
928 }
929
930 rtllib_qurey_ShortPreambleMode(ieee, tcb_desc);
Larry Fingerf38d2232011-08-25 11:48:28 -0500931 rtllib_tx_query_agg_cap(ieee, txb->fragments[0],
932 tcb_desc);
Larry Finger94a79942011-08-23 19:00:42 -0500933 rtllib_query_HTCapShortGI(ieee, tcb_desc);
934 rtllib_query_BandwidthMode(ieee, tcb_desc);
Larry Fingerf38d2232011-08-25 11:48:28 -0500935 rtllib_query_protectionmode(ieee, tcb_desc,
936 txb->fragments[0]);
Larry Finger94a79942011-08-23 19:00:42 -0500937 }
Larry Finger94a79942011-08-23 19:00:42 -0500938 }
939 spin_unlock_irqrestore(&ieee->lock, flags);
940 dev_kfree_skb_any(skb);
941 if (txb) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500942 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
Larry Finger94a79942011-08-23 19:00:42 -0500943 dev->stats.tx_packets++;
944 dev->stats.tx_bytes += txb->payload_size;
945 rtllib_softmac_xmit(txb, ieee);
Larry Fingerf38d2232011-08-25 11:48:28 -0500946 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500947 if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
948 stats->tx_packets++;
949 stats->tx_bytes += txb->payload_size;
950 return 0;
951 }
952 rtllib_txb_free(txb);
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}
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}
Sean MacLennan3b284992011-11-28 20:20:26 -0500970EXPORT_SYMBOL(rtllib_xmit);