blob: 44e8006bc1af1f81a284261f87632ccac549c46c [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>
49#include <linux/version.h>
50#include <linux/wireless.h>
51#include <linux/etherdevice.h>
Larry Fingerf38d2232011-08-25 11:48:28 -050052#include <linux/uaccess.h>
Larry Finger94a79942011-08-23 19:00:42 -050053#include <linux/if_vlan.h>
54
55#include "rtllib.h"
56
Larry Finger94a79942011-08-23 19:00:42 -050057/*
58
59
60802.11 Data Frame
61
62
63802.11 frame_contorl for data frames - 2 bytes
64 ,-----------------------------------------------------------------------------------------.
65bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e |
66 |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
67val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x |
68 |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
69desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep |
Larry Fingerf38d2232011-08-25 11:48:28 -050070 | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | |
Larry Finger94a79942011-08-23 19:00:42 -050071 '-----------------------------------------------------------------------------------------'
Larry Fingerf38d2232011-08-25 11:48:28 -050072 /\
73 |
74802.11 Data Frame |
75 ,--------- 'ctrl' expands to >-----------'
76 |
Larry Finger94a79942011-08-23 19:00:42 -050077 ,--'---,-------------------------------------------------------------.
78Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
79 |------|------|---------|---------|---------|------|---------|------|
80Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
Larry Fingerf38d2232011-08-25 11:48:28 -050081 | | tion | (BSSID) | | | ence | data | |
82 `--------------------------------------------------| |------'
83Total: 28 non-data bytes `----.----'
84 |
Larry Finger94a79942011-08-23 19:00:42 -050085 .- 'Frame data' expands to <---------------------------'
86 |
87 V
88 ,---------------------------------------------------.
89Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
90 |------|------|---------|----------|------|---------|
91Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
Larry Fingerf38d2232011-08-25 11:48:28 -050092 | DSAP | SSAP | | | | Packet |
93 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
94 `-----------------------------------------| |
95Total: 8 non-data bytes `----.----'
96 |
Larry Finger94a79942011-08-23 19:00:42 -050097 .- 'IP Packet' expands, if WEP enabled, to <--'
98 |
99 V
100 ,-----------------------.
101Bytes | 4 | 0-2296 | 4 |
102 |-----|-----------|-----|
103Desc. | IV | Encrypted | ICV |
104 | | IP Packet | |
105 `-----------------------'
106Total: 8 non-data bytes
107
108
109802.3 Ethernet Data Frame
110
111 ,-----------------------------------------.
112Bytes | 6 | 6 | 2 | Variable | 4 |
113 |-------|-------|------|-----------|------|
114Desc. | Dest. | Source| Type | IP Packet | fcs |
Larry Fingerf38d2232011-08-25 11:48:28 -0500115 | MAC | MAC | | | |
Larry Finger94a79942011-08-23 19:00:42 -0500116 `-----------------------------------------'
117Total: 18 non-data bytes
118
119In the event that fragmentation is required, the incoming payload is split into
120N parts of size ieee->fts. The first fragment contains the SNAP header and the
121remaining packets are just data.
122
123If encryption is enabled, each fragment payload size is reduced by enough space
124to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
125So if you have 1500 bytes of payload with ieee->fts set to 500 without
126encryption it will take 3 frames. With WEP it will take 4 frames as the
127payload of each frame is reduced to 492 bytes.
128
129* SKB visualization
130*
131* ,- skb->data
132* |
Larry Fingerf38d2232011-08-25 11:48:28 -0500133* | ETHERNET HEADER ,-<-- PAYLOAD
134* | | 14 bytes from skb->data
Larry Finger94a79942011-08-23 19:00:42 -0500135* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
Larry Fingerf38d2232011-08-25 11:48:28 -0500136* | | | |
Larry Finger94a79942011-08-23 19:00:42 -0500137* |,-Dest.--. ,--Src.---. | | |
138* | 6 bytes| | 6 bytes | | | |
Larry Fingerf38d2232011-08-25 11:48:28 -0500139* v | | | | | |
140* 0 | v 1 | v | v 2
Larry Finger94a79942011-08-23 19:00:42 -0500141* 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 -0500142* ^ | ^ | ^ |
143* | | | | | |
144* | | | | `T' <---- 2 bytes for Type
145* | | | |
Larry Finger94a79942011-08-23 19:00:42 -0500146* | | '---SNAP--' <-------- 6 bytes for SNAP
147* | |
148* `-IV--' <-------------------- 4 bytes for IV (WEP)
149*
150* SNAP HEADER
151*
152*/
153
154static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
155static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
156
157inline int rtllib_put_snap(u8 *data, u16 h_proto)
158{
159 struct rtllib_snap_hdr *snap;
160 u8 *oui;
161
162 snap = (struct rtllib_snap_hdr *)data;
163 snap->dsap = 0xaa;
164 snap->ssap = 0xaa;
165 snap->ctrl = 0x03;
166
167 if (h_proto == 0x8137 || h_proto == 0x80f3)
168 oui = P802_1H_OUI;
169 else
170 oui = RFC1042_OUI;
171 snap->oui[0] = oui[0];
172 snap->oui[1] = oui[1];
173 snap->oui[2] = oui[2];
174
175 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
176
177 return SNAP_SIZE + sizeof(u16);
178}
179
Larry Fingerf38d2232011-08-25 11:48:28 -0500180int rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag,
181 int hdr_len)
Larry Finger94a79942011-08-23 19:00:42 -0500182{
Larry Fingerf38d2232011-08-25 11:48:28 -0500183 struct rtllib_crypt_data *crypt = NULL;
Larry Finger94a79942011-08-23 19:00:42 -0500184 int res;
185
186 crypt = ieee->crypt[ieee->tx_keyidx];
187
Larry Fingerf38d2232011-08-25 11:48:28 -0500188 if (!(crypt && crypt->ops)) {
189 printk(KERN_INFO "=========>%s(), crypt is null\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500190 return -1;
191 }
Larry Finger94a79942011-08-23 19:00:42 -0500192 /* To encrypt, frame format is:
193 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
194
195 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
196 * call both MSDU and MPDU encryption functions from here. */
197 atomic_inc(&crypt->refcnt);
198 res = 0;
199 if (crypt->ops->encrypt_msdu)
200 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
201 if (res == 0 && crypt->ops->encrypt_mpdu)
202 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
203
204 atomic_dec(&crypt->refcnt);
205 if (res < 0) {
206 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
207 ieee->dev->name, frag->len);
208 ieee->ieee_stats.tx_discards++;
209 return -1;
210 }
211
212 return 0;
213}
214
215
Larry Fingerf38d2232011-08-25 11:48:28 -0500216void rtllib_txb_free(struct rtllib_txb *txb)
217{
Larry Finger94a79942011-08-23 19:00:42 -0500218 if (unlikely(!txb))
219 return;
220 kfree(txb);
221}
222
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500223static struct rtllib_txb *rtllib_alloc_txb(int nr_frags, int txb_size,
224 gfp_t gfp_mask)
Larry Finger94a79942011-08-23 19:00:42 -0500225{
Larry Finger94a79942011-08-23 19:00:42 -0500226 struct rtllib_txb *txb;
227 int i;
Larry Fingerf38d2232011-08-25 11:48:28 -0500228 txb = kmalloc(sizeof(struct rtllib_txb) + (sizeof(u8 *) * nr_frags),
229 gfp_mask);
Larry Finger94a79942011-08-23 19:00:42 -0500230 if (!txb)
231 return NULL;
232
233 memset(txb, 0, sizeof(struct rtllib_txb));
234 txb->nr_frags = nr_frags;
235 txb->frag_size = txb_size;
236
237 for (i = 0; i < nr_frags; i++) {
Larry Finger94a79942011-08-23 19:00:42 -0500238 txb->fragments[i] = dev_alloc_skb(txb_size);
Larry Finger94a79942011-08-23 19:00:42 -0500239 if (unlikely(!txb->fragments[i])) {
240 i--;
241 break;
242 }
Larry Finger94a79942011-08-23 19:00:42 -0500243 memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb));
244 }
245 if (unlikely(i != nr_frags)) {
246 while (i >= 0)
247 dev_kfree_skb_any(txb->fragments[i--]);
248 kfree(txb);
249 return NULL;
250 }
251 return txb;
252}
253
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500254static int rtllib_classify(struct sk_buff *skb, u8 bIsAmsdu)
Larry Finger94a79942011-08-23 19:00:42 -0500255{
256 struct ethhdr *eth;
257 struct iphdr *ip;
258
259 eth = (struct ethhdr *)skb->data;
260 if (eth->h_proto != htons(ETH_P_IP))
261 return 0;
262
263 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA, skb->data, skb->len);
264 ip = ip_hdr(skb);
265 switch (ip->tos & 0xfc) {
266 case 0x20:
267 return 2;
268 case 0x40:
269 return 1;
270 case 0x60:
271 return 3;
272 case 0x80:
273 return 4;
274 case 0xa0:
275 return 5;
276 case 0xc0:
277 return 6;
278 case 0xe0:
279 return 7;
280 default:
281 return 0;
282 }
283}
284
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500285static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee,
286 struct sk_buff *skb,
287 struct cb_desc *tcb_desc)
Larry Finger94a79942011-08-23 19:00:42 -0500288{
Larry Finger7796d932011-07-18 20:22:19 -0500289 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
Larry Finger60554f22011-07-18 20:10:03 -0500290 struct tx_ts_record *pTxTs = NULL;
Larry Fingerf38d2232011-08-25 11:48:28 -0500291 struct rtllib_hdr_1addr* hdr = (struct rtllib_hdr_1addr *)skb->data;
Larry Finger94a79942011-08-23 19:00:42 -0500292
Larry Fingerf38d2232011-08-25 11:48:28 -0500293 if (rtllib_act_scanning(ieee, false))
Larry Finger94a79942011-08-23 19:00:42 -0500294 return;
295
Larry Fingerf38d2232011-08-25 11:48:28 -0500296 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
Larry Finger94a79942011-08-23 19:00:42 -0500297 return;
298 if (!IsQoSDataFrame(skb->data))
299 return;
Larry Fingerf38d2232011-08-25 11:48:28 -0500300 if (is_multicast_ether_addr(hdr->addr1) ||
301 is_broadcast_ether_addr(hdr->addr1))
Larry Finger94a79942011-08-23 19:00:42 -0500302 return;
Larry Finger94a79942011-08-23 19:00:42 -0500303
Larry Fingerf38d2232011-08-25 11:48:28 -0500304 if (tcb_desc->bdhcp || ieee->CntAfterLink < 2)
Larry Finger94a79942011-08-23 19:00:42 -0500305 return;
306
307 if (pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION)
308 return;
309
310 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
311 return;
Larry Fingerf38d2232011-08-25 11:48:28 -0500312 if (pHTInfo->bCurrentAMPDUEnable) {
313 if (!GetTs(ieee, (struct ts_common_info **)(&pTxTs), hdr->addr1,
314 skb->priority, TX_DIR, true)) {
315 printk(KERN_INFO "%s: can't get TS\n", __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500316 return;
317 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500318 if (pTxTs->TxAdmittedBARecord.bValid == false) {
319 if (ieee->wpa_ie_len && (ieee->pairwise_key_type ==
320 KEY_TYPE_NA)) {
Larry Finger94a79942011-08-23 19:00:42 -0500321 ;
Larry Fingerf38d2232011-08-25 11:48:28 -0500322 } else if (tcb_desc->bdhcp == 1) {
Larry Finger94a79942011-08-23 19:00:42 -0500323 ;
Larry Fingerf38d2232011-08-25 11:48:28 -0500324 } else if (!pTxTs->bDisable_AddBa) {
Larry Finger94a79942011-08-23 19:00:42 -0500325 TsStartAddBaProcess(ieee, pTxTs);
326 }
327 goto FORCED_AGG_SETTING;
328 } else if (pTxTs->bUsingBa == false) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500329 if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum,
330 (pTxTs->TxCurSeq+1)%4096))
Larry Finger94a79942011-08-23 19:00:42 -0500331 pTxTs->bUsingBa = true;
332 else
333 goto FORCED_AGG_SETTING;
334 }
335 if (ieee->iw_mode == IW_MODE_INFRA) {
336 tcb_desc->bAMPDUEnable = true;
337 tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
338 tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
339 }
340 }
341FORCED_AGG_SETTING:
342 switch (pHTInfo->ForcedAMPDUMode) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500343 case HT_AGG_AUTO:
344 break;
Larry Finger94a79942011-08-23 19:00:42 -0500345
Larry Fingerf38d2232011-08-25 11:48:28 -0500346 case HT_AGG_FORCE_ENABLE:
347 tcb_desc->bAMPDUEnable = true;
348 tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
349 tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
350 break;
Larry Finger94a79942011-08-23 19:00:42 -0500351
Larry Fingerf38d2232011-08-25 11:48:28 -0500352 case HT_AGG_FORCE_DISABLE:
353 tcb_desc->bAMPDUEnable = false;
354 tcb_desc->ampdu_density = 0;
355 tcb_desc->ampdu_factor = 0;
356 break;
Larry Finger94a79942011-08-23 19:00:42 -0500357 }
358 return;
359}
360
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500361static void rtllib_qurey_ShortPreambleMode(struct rtllib_device *ieee,
Larry Fingerf38d2232011-08-25 11:48:28 -0500362 struct cb_desc *tcb_desc)
363{
364 tcb_desc->bUseShortPreamble = false;
365 if (tcb_desc->data_rate == 2)
366 return;
367 else if (ieee->current_network.capability &
368 WLAN_CAPABILITY_SHORT_PREAMBLE)
369 tcb_desc->bUseShortPreamble = true;
370 return;
371}
372
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500373static void rtllib_query_HTCapShortGI(struct rtllib_device *ieee,
Larry Fingerf38d2232011-08-25 11:48:28 -0500374 struct cb_desc *tcb_desc)
Larry Finger94a79942011-08-23 19:00:42 -0500375{
Larry Finger7796d932011-07-18 20:22:19 -0500376 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
Larry Finger94a79942011-08-23 19:00:42 -0500377
378 tcb_desc->bUseShortGI = false;
379
Larry Fingerf38d2232011-08-25 11:48:28 -0500380 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
Larry Finger94a79942011-08-23 19:00:42 -0500381 return;
382
Larry Fingerf38d2232011-08-25 11:48:28 -0500383 if (pHTInfo->bForcedShortGI) {
Larry Finger94a79942011-08-23 19:00:42 -0500384 tcb_desc->bUseShortGI = true;
385 return;
386 }
387
Larry Fingerf38d2232011-08-25 11:48:28 -0500388 if ((pHTInfo->bCurBW40MHz == true) && pHTInfo->bCurShortGI40MHz)
Larry Finger94a79942011-08-23 19:00:42 -0500389 tcb_desc->bUseShortGI = true;
Larry Fingerf38d2232011-08-25 11:48:28 -0500390 else if ((pHTInfo->bCurBW40MHz == false) && pHTInfo->bCurShortGI20MHz)
Larry Finger94a79942011-08-23 19:00:42 -0500391 tcb_desc->bUseShortGI = true;
392}
393
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500394static void rtllib_query_BandwidthMode(struct rtllib_device *ieee,
395 struct cb_desc *tcb_desc)
Larry Finger94a79942011-08-23 19:00:42 -0500396{
Larry Finger7796d932011-07-18 20:22:19 -0500397 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
Larry Finger94a79942011-08-23 19:00:42 -0500398
399 tcb_desc->bPacketBW = false;
400
Larry Fingerf38d2232011-08-25 11:48:28 -0500401 if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
Larry Finger94a79942011-08-23 19:00:42 -0500402 return;
403
404 if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
405 return;
406
Larry Fingerf38d2232011-08-25 11:48:28 -0500407 if ((tcb_desc->data_rate & 0x80) == 0)
Larry Finger94a79942011-08-23 19:00:42 -0500408 return;
Larry Fingerf38d2232011-08-25 11:48:28 -0500409 if (pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz &&
410 !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
Larry Finger94a79942011-08-23 19:00:42 -0500411 tcb_desc->bPacketBW = true;
412 return;
413}
Larry Finger94a79942011-08-23 19:00:42 -0500414
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500415static void rtllib_query_protectionmode(struct rtllib_device *ieee,
416 struct cb_desc *tcb_desc,
417 struct sk_buff *skb)
Larry Finger94a79942011-08-23 19:00:42 -0500418{
419 tcb_desc->bRTSSTBC = false;
420 tcb_desc->bRTSUseShortGI = false;
421 tcb_desc->bCTSEnable = false;
422 tcb_desc->RTSSC = 0;
423 tcb_desc->bRTSBW = false;
424
425 if (tcb_desc->bBroadcast || tcb_desc->bMulticast)
426 return;
427
428 if (is_broadcast_ether_addr(skb->data+16))
429 return;
430
Larry Fingerf38d2232011-08-25 11:48:28 -0500431 if (ieee->mode < IEEE_N_24G) {
432 if (skb->len > ieee->rts) {
Larry Finger94a79942011-08-23 19:00:42 -0500433 tcb_desc->bRTSEnable = true;
434 tcb_desc->rts_rate = MGN_24M;
Larry Fingerf38d2232011-08-25 11:48:28 -0500435 } else if (ieee->current_network.buseprotection) {
Larry Finger94a79942011-08-23 19:00:42 -0500436 tcb_desc->bRTSEnable = true;
437 tcb_desc->bCTSEnable = true;
438 tcb_desc->rts_rate = MGN_24M;
439 }
440 return;
Larry Fingerf38d2232011-08-25 11:48:28 -0500441 } else {
Larry Finger7796d932011-07-18 20:22:19 -0500442 struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
Larry Fingerf38d2232011-08-25 11:48:28 -0500443 while (true) {
444 if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) {
Larry Finger94a79942011-08-23 19:00:42 -0500445 tcb_desc->bCTSEnable = true;
446 tcb_desc->rts_rate = MGN_24M;
447 tcb_desc->bRTSEnable = true;
448 break;
Larry Fingerf38d2232011-08-25 11:48:28 -0500449 } else if (pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS |
450 HT_IOT_ACT_PURE_N_MODE)) {
Larry Finger94a79942011-08-23 19:00:42 -0500451 tcb_desc->bRTSEnable = true;
452 tcb_desc->rts_rate = MGN_24M;
453 break;
454 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500455 if (ieee->current_network.buseprotection) {
Larry Finger94a79942011-08-23 19:00:42 -0500456 tcb_desc->bRTSEnable = true;
457 tcb_desc->bCTSEnable = true;
458 tcb_desc->rts_rate = MGN_24M;
459 break;
460 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500461 if (pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) {
Larry Finger94a79942011-08-23 19:00:42 -0500462 u8 HTOpMode = pHTInfo->CurrentOpMode;
Larry Fingerf38d2232011-08-25 11:48:28 -0500463 if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 ||
464 HTOpMode == 3)) ||
465 (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) {
Larry Finger94a79942011-08-23 19:00:42 -0500466 tcb_desc->rts_rate = MGN_24M;
467 tcb_desc->bRTSEnable = true;
468 break;
469 }
470 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500471 if (skb->len > ieee->rts) {
Larry Finger94a79942011-08-23 19:00:42 -0500472 tcb_desc->rts_rate = MGN_24M;
473 tcb_desc->bRTSEnable = true;
474 break;
475 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500476 if (tcb_desc->bAMPDUEnable) {
Larry Finger94a79942011-08-23 19:00:42 -0500477 tcb_desc->rts_rate = MGN_24M;
478 tcb_desc->bRTSEnable = false;
479 break;
480 }
481 goto NO_PROTECTION;
482 }
Larry Finger94a79942011-08-23 19:00:42 -0500483 }
484 if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
485 tcb_desc->bUseShortPreamble = true;
486 if (ieee->iw_mode == IW_MODE_MASTER)
487 goto NO_PROTECTION;
488 return;
489NO_PROTECTION:
490 tcb_desc->bRTSEnable = false;
491 tcb_desc->bCTSEnable = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500492 tcb_desc->rts_rate = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500493 tcb_desc->RTSSC = 0;
Larry Fingerf38d2232011-08-25 11:48:28 -0500494 tcb_desc->bRTSBW = false;
Larry Finger94a79942011-08-23 19:00:42 -0500495}
496
497
Larry Fingerec0dc6be2011-08-25 14:07:04 -0500498static void rtllib_txrate_selectmode(struct rtllib_device *ieee,
499 struct cb_desc *tcb_desc)
Larry Finger94a79942011-08-23 19:00:42 -0500500{
Larry Finger94a79942011-08-23 19:00:42 -0500501 if (ieee->bTxDisableRateFallBack)
502 tcb_desc->bTxDisableRateFallBack = true;
503
504 if (ieee->bTxUseDriverAssingedRate)
505 tcb_desc->bTxUseDriverAssingedRate = true;
Larry Fingerf38d2232011-08-25 11:48:28 -0500506 if (!tcb_desc->bTxDisableRateFallBack ||
507 !tcb_desc->bTxUseDriverAssingedRate) {
508 if (ieee->iw_mode == IW_MODE_INFRA ||
509 ieee->iw_mode == IW_MODE_ADHOC)
Larry Finger94a79942011-08-23 19:00:42 -0500510 tcb_desc->RATRIndex = 0;
511 }
512}
513
Larry Fingerf38d2232011-08-25 11:48:28 -0500514u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb,
515 u8 *dst)
Larry Finger94a79942011-08-23 19:00:42 -0500516{
517 u16 seqnum = 0;
518
519 if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst))
520 return 0;
Larry Fingerf38d2232011-08-25 11:48:28 -0500521 if (IsQoSDataFrame(skb->data)) {
Larry Finger60554f22011-07-18 20:10:03 -0500522 struct tx_ts_record *pTS = NULL;
Larry Fingerf38d2232011-08-25 11:48:28 -0500523 if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
524 skb->priority, TX_DIR, true))
Larry Finger94a79942011-08-23 19:00:42 -0500525 return 0;
Larry Finger94a79942011-08-23 19:00:42 -0500526 seqnum = pTS->TxCurSeq;
527 pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
528 return seqnum;
529 }
530 return 0;
531}
532
533static int wme_downgrade_ac(struct sk_buff *skb)
534{
535 switch (skb->priority) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500536 case 6:
537 case 7:
538 skb->priority = 5; /* VO -> VI */
539 return 0;
540 case 4:
541 case 5:
542 skb->priority = 3; /* VI -> BE */
543 return 0;
544 case 0:
545 case 3:
546 skb->priority = 1; /* BE -> BK */
547 return 0;
548 default:
549 return -1;
Larry Finger94a79942011-08-23 19:00:42 -0500550 }
551}
552
553int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
554{
Larry Fingerf38d2232011-08-25 11:48:28 -0500555 struct rtllib_device *ieee = (struct rtllib_device *)
556 netdev_priv_rsl(dev);
Larry Finger94a79942011-08-23 19:00:42 -0500557 struct rtllib_txb *txb = NULL;
558 struct rtllib_hdr_3addrqos *frag_hdr;
559 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
560 unsigned long flags;
561 struct net_device_stats *stats = &ieee->stats;
562 int ether_type = 0, encrypt;
563 int bytes, fc, qos_ctl = 0, hdr_len;
564 struct sk_buff *skb_frag;
565 struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */
566 .duration_id = 0,
567 .seq_ctl = 0,
568 .qos_ctl = 0
569 };
570 u8 dest[ETH_ALEN], src[ETH_ALEN];
571 int qos_actived = ieee->current_network.qos_data.active;
Larry Fingerf38d2232011-08-25 11:48:28 -0500572 struct rtllib_crypt_data *crypt = NULL;
Larry Finger3b83db42011-07-19 00:01:29 -0500573 struct cb_desc *tcb_desc;
Larry Finger94a79942011-08-23 19:00:42 -0500574 u8 bIsMulticast = false;
575 u8 IsAmsdu = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500576 bool bdhcp = false;
Larry Finger94a79942011-08-23 19:00:42 -0500577
Larry Finger94a79942011-08-23 19:00:42 -0500578 spin_lock_irqsave(&ieee->lock, flags);
579
580 /* If there is no driver handler to take the TXB, dont' bother
581 * creating it... */
Larry Fingerf38d2232011-08-25 11:48:28 -0500582 if ((!ieee->hard_start_xmit && !(ieee->softmac_features &
583 IEEE_SOFTMAC_TX_QUEUE)) ||
584 ((!ieee->softmac_data_hard_start_xmit &&
585 (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
Larry Finger94a79942011-08-23 19:00:42 -0500586 printk(KERN_WARNING "%s: No xmit handler.\n",
587 ieee->dev->name);
588 goto success;
589 }
590
591
Larry Fingerf38d2232011-08-25 11:48:28 -0500592 if (likely(ieee->raw_tx == 0)) {
Larry Finger94a79942011-08-23 19:00:42 -0500593 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
594 printk(KERN_WARNING "%s: skb too small (%d).\n",
595 ieee->dev->name, skb->len);
596 goto success;
597 }
598 /* Save source and destination addresses */
599 memcpy(dest, skb->data, ETH_ALEN);
600 memcpy(src, skb->data+ETH_ALEN, ETH_ALEN);
601
602 memset(skb->cb, 0, sizeof(skb->cb));
603 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
604
Larry Fingerf38d2232011-08-25 11:48:28 -0500605 if (ieee->iw_mode == IW_MODE_MONITOR) {
Larry Finger94a79942011-08-23 19:00:42 -0500606 txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
607 if (unlikely(!txb)) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500608 printk(KERN_WARNING "%s: Could not allocate "
609 "TXB\n",
Larry Finger94a79942011-08-23 19:00:42 -0500610 ieee->dev->name);
611 goto failed;
612 }
613
614 txb->encrypted = 0;
615 txb->payload_size = skb->len;
Larry Fingerf38d2232011-08-25 11:48:28 -0500616 memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
617 skb->len);
Larry Finger94a79942011-08-23 19:00:42 -0500618
619 goto success;
620 }
621
Larry Finger55dc4eb2011-08-25 11:48:13 -0500622 if (skb->len > 282) {
Larry Finger94a79942011-08-23 19:00:42 -0500623 if (ETH_P_IP == ether_type) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500624 const struct iphdr *ip = (struct iphdr *)
625 ((u8 *)skb->data+14);
Larry Finger94a79942011-08-23 19:00:42 -0500626 if (IPPROTO_UDP == ip->protocol) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500627 struct udphdr *udp;
628
629 udp = (struct udphdr *)((u8 *)ip +
630 (ip->ihl << 2));
631 if (((((u8 *)udp)[1] == 68) &&
632 (((u8 *)udp)[3] == 67)) ||
633 ((((u8 *)udp)[1] == 67) &&
634 (((u8 *)udp)[3] == 68))) {
Larry Finger94a79942011-08-23 19:00:42 -0500635 bdhcp = true;
636 ieee->LPSDelayCnt = 200;
637 }
638 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500639 } else if (ETH_P_ARP == ether_type) {
640 printk(KERN_INFO "=================>DHCP "
641 "Protocol start tx ARP pkt!!\n");
Larry Finger94a79942011-08-23 19:00:42 -0500642 bdhcp = true;
Larry Fingerf38d2232011-08-25 11:48:28 -0500643 ieee->LPSDelayCnt =
644 ieee->current_network.tim.tim_count;
Larry Finger94a79942011-08-23 19:00:42 -0500645 }
646 }
647
648 skb->priority = rtllib_classify(skb, IsAmsdu);
649 crypt = ieee->crypt[ieee->tx_keyidx];
650 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
651 ieee->host_encrypt && crypt && crypt->ops;
652 if (!encrypt && ieee->ieee802_1x &&
Larry Fingerf38d2232011-08-25 11:48:28 -0500653 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
Larry Finger94a79942011-08-23 19:00:42 -0500654 stats->tx_dropped++;
655 goto success;
656 }
Larry Finger94a79942011-08-23 19:00:42 -0500657 if (crypt && !encrypt && ether_type == ETH_P_PAE) {
658 struct eapol *eap = (struct eapol *)(skb->data +
Larry Fingerf38d2232011-08-25 11:48:28 -0500659 sizeof(struct ethhdr) - SNAP_SIZE -
660 sizeof(u16));
Larry Finger94a79942011-08-23 19:00:42 -0500661 RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
662 eap_get_type(eap->type));
663 }
Larry Finger94a79942011-08-23 19:00:42 -0500664
665 /* Advance the SKB to the start of the payload */
666 skb_pull(skb, sizeof(struct ethhdr));
667
Larry Fingerf38d2232011-08-25 11:48:28 -0500668 /* Determine total amount of storage required for TXB packets */
Larry Finger94a79942011-08-23 19:00:42 -0500669 bytes = skb->len + SNAP_SIZE + sizeof(u16);
670
671 if (encrypt)
672 fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP;
673 else
674 fc = RTLLIB_FTYPE_DATA;
675
676 if (qos_actived)
677 fc |= RTLLIB_STYPE_QOS_DATA;
678 else
679 fc |= RTLLIB_STYPE_DATA;
680
681 if (ieee->iw_mode == IW_MODE_INFRA) {
682 fc |= RTLLIB_FCTL_TODS;
683 /* To DS: Addr1 = BSSID, Addr2 = SA,
684 Addr3 = DA */
Larry Fingerf38d2232011-08-25 11:48:28 -0500685 memcpy(&header.addr1, ieee->current_network.bssid,
686 ETH_ALEN);
Larry Finger94a79942011-08-23 19:00:42 -0500687 memcpy(&header.addr2, &src, ETH_ALEN);
688 if (IsAmsdu)
Larry Fingerf38d2232011-08-25 11:48:28 -0500689 memcpy(&header.addr3,
690 ieee->current_network.bssid, ETH_ALEN);
Larry Finger94a79942011-08-23 19:00:42 -0500691 else
692 memcpy(&header.addr3, &dest, ETH_ALEN);
693 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
694 /* not From/To DS: Addr1 = DA, Addr2 = SA,
695 Addr3 = BSSID */
696 memcpy(&header.addr1, dest, ETH_ALEN);
697 memcpy(&header.addr2, src, ETH_ALEN);
Larry Fingerf38d2232011-08-25 11:48:28 -0500698 memcpy(&header.addr3, ieee->current_network.bssid,
699 ETH_ALEN);
Larry Finger94a79942011-08-23 19:00:42 -0500700 }
701
Larry Fingerf38d2232011-08-25 11:48:28 -0500702 bIsMulticast = is_broadcast_ether_addr(header.addr1) ||
703 is_multicast_ether_addr(header.addr1);
Larry Finger94a79942011-08-23 19:00:42 -0500704
Larry Fingerf38d2232011-08-25 11:48:28 -0500705 header.frame_ctl = cpu_to_le16(fc);
Larry Finger94a79942011-08-23 19:00:42 -0500706
707 /* Determine fragmentation size based on destination (multicast
708 * and broadcast are not fragmented) */
709 if (bIsMulticast) {
710 frag_size = MAX_FRAG_THRESHOLD;
711 qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
712 } else {
713 frag_size = ieee->fts;
714 qos_ctl = 0;
715 }
716
717 if (qos_actived) {
718 hdr_len = RTLLIB_3ADDR_LEN + 2;
719
Larry Fingerf38d2232011-08-25 11:48:28 -0500720 /* in case we are a client verify acm is not set for this ac */
721 while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) {
722 printk(KERN_INFO "skb->priority = %x\n", skb->priority);
723 if (wme_downgrade_ac(skb))
724 break;
725 printk(KERN_INFO "converted skb->priority = %x\n",
726 skb->priority);
727 }
728 qos_ctl |= skb->priority;
729 header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID);
Larry Finger94a79942011-08-23 19:00:42 -0500730 } else {
731 hdr_len = RTLLIB_3ADDR_LEN;
732 }
733 /* Determine amount of payload per fragment. Regardless of if
Larry Fingerf38d2232011-08-25 11:48:28 -0500734 * this stack is providing the full 802.11 header, one will
735 * eventually be affixed to this fragment -- so we must account
736 * for it when determining the amount of payload space. */
Larry Finger94a79942011-08-23 19:00:42 -0500737 bytes_per_frag = frag_size - hdr_len;
738 if (ieee->config &
Larry Fingerf38d2232011-08-25 11:48:28 -0500739 (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
Larry Finger94a79942011-08-23 19:00:42 -0500740 bytes_per_frag -= RTLLIB_FCS_LEN;
741
Larry Fingerf38d2232011-08-25 11:48:28 -0500742 /* Each fragment may need to have room for encryptiong
743 * pre/postfix */
Larry Finger94a79942011-08-23 19:00:42 -0500744 if (encrypt) {
745 bytes_per_frag -= crypt->ops->extra_prefix_len +
746 crypt->ops->extra_postfix_len;
747 }
748 /* Number of fragments is the total bytes_per_frag /
749 * payload_per_fragment */
750 nr_frags = bytes / bytes_per_frag;
751 bytes_last_frag = bytes % bytes_per_frag;
752 if (bytes_last_frag)
753 nr_frags++;
754 else
755 bytes_last_frag = bytes_per_frag;
756
Larry Fingerf38d2232011-08-25 11:48:28 -0500757 /* When we allocate the TXB we allocate enough space for the
758 * reserve and full fragment bytes (bytes_per_frag doesn't
759 * include prefix, postfix, header, FCS, etc.) */
760 txb = rtllib_alloc_txb(nr_frags, frag_size +
761 ieee->tx_headroom, GFP_ATOMIC);
Larry Finger94a79942011-08-23 19:00:42 -0500762 if (unlikely(!txb)) {
763 printk(KERN_WARNING "%s: Could not allocate TXB\n",
764 ieee->dev->name);
765 goto failed;
766 }
767 txb->encrypted = encrypt;
768 txb->payload_size = bytes;
769
770 if (qos_actived)
Larry Finger94a79942011-08-23 19:00:42 -0500771 txb->queue_index = UP2AC(skb->priority);
Larry Fingerf38d2232011-08-25 11:48:28 -0500772 else
773 txb->queue_index = WME_AC_BE;
Larry Finger94a79942011-08-23 19:00:42 -0500774
775 for (i = 0; i < nr_frags; i++) {
776 skb_frag = txb->fragments[i];
Larry Fingerf38d2232011-08-25 11:48:28 -0500777 tcb_desc = (struct cb_desc *)(skb_frag->cb +
778 MAX_DEV_ADDR_SIZE);
779 if (qos_actived) {
Larry Finger94a79942011-08-23 19:00:42 -0500780 skb_frag->priority = skb->priority;
781 tcb_desc->queue_index = UP2AC(skb->priority);
782 } else {
783 skb_frag->priority = WME_AC_BE;
784 tcb_desc->queue_index = WME_AC_BE;
785 }
786 skb_reserve(skb_frag, ieee->tx_headroom);
787
Larry Fingerf38d2232011-08-25 11:48:28 -0500788 if (encrypt) {
Larry Finger94a79942011-08-23 19:00:42 -0500789 if (ieee->hwsec_active)
790 tcb_desc->bHwSec = 1;
791 else
792 tcb_desc->bHwSec = 0;
Larry Fingerf38d2232011-08-25 11:48:28 -0500793 skb_reserve(skb_frag,
794 crypt->ops->extra_prefix_len);
Larry Finger94a79942011-08-23 19:00:42 -0500795 } else {
796 tcb_desc->bHwSec = 0;
797 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500798 frag_hdr = (struct rtllib_hdr_3addrqos *)
799 skb_put(skb_frag, hdr_len);
Larry Finger94a79942011-08-23 19:00:42 -0500800 memcpy(frag_hdr, &header, hdr_len);
801
Larry Fingerf38d2232011-08-25 11:48:28 -0500802 /* If this is not the last fragment, then add the
803 * MOREFRAGS bit to the frame control */
Larry Finger94a79942011-08-23 19:00:42 -0500804 if (i != nr_frags - 1) {
805 frag_hdr->frame_ctl = cpu_to_le16(
806 fc | RTLLIB_FCTL_MOREFRAGS);
807 bytes = bytes_per_frag;
808
809 } else {
Larry Fingerf38d2232011-08-25 11:48:28 -0500810 /* The last fragment has the remaining length */
Larry Finger94a79942011-08-23 19:00:42 -0500811 bytes = bytes_last_frag;
812 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500813 if ((qos_actived) && (!bIsMulticast)) {
814 frag_hdr->seq_ctl =
815 rtllib_query_seqnum(ieee, skb_frag,
816 header.addr1);
817 frag_hdr->seq_ctl =
818 cpu_to_le16(frag_hdr->seq_ctl<<4 | i);
Larry Finger94a79942011-08-23 19:00:42 -0500819 } else {
Larry Fingerf38d2232011-08-25 11:48:28 -0500820 frag_hdr->seq_ctl =
821 cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
Larry Finger94a79942011-08-23 19:00:42 -0500822 }
823 /* Put a SNAP header on the first fragment */
824 if (i == 0) {
825 rtllib_put_snap(
Larry Fingerf38d2232011-08-25 11:48:28 -0500826 skb_put(skb_frag, SNAP_SIZE +
827 sizeof(u16)), ether_type);
Larry Finger94a79942011-08-23 19:00:42 -0500828 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
Larry Fingerf38d2232011-08-25 11:48:28 -0500836 /* Encryption routine will move the header forward in
837 * order to insert the IV between the header and the
838 * payload */
Larry Finger94a79942011-08-23 19:00:42 -0500839 if (encrypt)
Larry Fingerf38d2232011-08-25 11:48:28 -0500840 rtllib_encrypt_fragment(ieee, skb_frag,
841 hdr_len);
Larry Finger94a79942011-08-23 19:00:42 -0500842 if (ieee->config &
Larry Fingerf38d2232011-08-25 11:48:28 -0500843 (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
Larry Finger94a79942011-08-23 19:00:42 -0500844 skb_put(skb_frag, 4);
845 }
846
847 if ((qos_actived) && (!bIsMulticast)) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500848 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]++;
Larry Finger94a79942011-08-23 19:00:42 -0500852 } else {
Larry Fingerf38d2232011-08-25 11:48:28 -0500853 if (ieee->seq_ctrl[0] == 0xFFF)
854 ieee->seq_ctrl[0] = 0;
855 else
856 ieee->seq_ctrl[0]++;
Larry Finger94a79942011-08-23 19:00:42 -0500857 }
Larry Fingerf38d2232011-08-25 11:48:28 -0500858 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500859 if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) {
860 printk(KERN_WARNING "%s: skb too small (%d).\n",
861 ieee->dev->name, skb->len);
862 goto success;
863 }
864
865 txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
Larry Fingerf38d2232011-08-25 11:48:28 -0500866 if (!txb) {
Larry Finger94a79942011-08-23 19:00:42 -0500867 printk(KERN_WARNING "%s: Could not allocate TXB\n",
868 ieee->dev->name);
869 goto failed;
870 }
871
872 txb->encrypted = 0;
873 txb->payload_size = skb->len;
Larry Fingerf38d2232011-08-25 11:48:28 -0500874 memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
875 skb->len);
Larry Finger94a79942011-08-23 19:00:42 -0500876 }
877
878 success:
Larry Fingerf38d2232011-08-25 11:48:28 -0500879 if (txb) {
880 struct cb_desc *tcb_desc = (struct cb_desc *)
881 (txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
Larry Finger94a79942011-08-23 19:00:42 -0500882 tcb_desc->bTxEnableFwCalcDur = 1;
883 tcb_desc->priority = skb->priority;
884
885 if (ether_type == ETH_P_PAE) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500886 if (ieee->pHTInfo->IOTAction &
887 HT_IOT_ACT_WA_IOT_Broadcom) {
888 tcb_desc->data_rate =
889 MgntQuery_TxRateExcludeCCKRates(ieee);
Larry Finger94a79942011-08-23 19:00:42 -0500890 tcb_desc->bTxDisableRateFallBack = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500891 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500892 tcb_desc->data_rate = ieee->basic_rate;
893 tcb_desc->bTxDisableRateFallBack = 1;
894 }
895
896
897 tcb_desc->RATRIndex = 7;
898 tcb_desc->bTxUseDriverAssingedRate = 1;
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;
Larry Finger94a79942011-08-23 19:00:42 -0500904 rtllib_txrate_selectmode(ieee, tcb_desc);
Larry Fingerf38d2232011-08-25 11:48:28 -0500905 if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
Larry Finger94a79942011-08-23 19:00:42 -0500906 tcb_desc->data_rate = ieee->basic_rate;
907 else
Larry Fingerf38d2232011-08-25 11:48:28 -0500908 tcb_desc->data_rate = CURRENT_RATE(ieee->mode,
909 ieee->rate, ieee->HTCurrentOperaRate);
Larry Finger94a79942011-08-23 19:00:42 -0500910
Larry Fingerf38d2232011-08-25 11:48:28 -0500911 if (bdhcp == true) {
912 if (ieee->pHTInfo->IOTAction &
913 HT_IOT_ACT_WA_IOT_Broadcom) {
914 tcb_desc->data_rate =
915 MgntQuery_TxRateExcludeCCKRates(ieee);
Larry Finger94a79942011-08-23 19:00:42 -0500916 tcb_desc->bTxDisableRateFallBack = false;
Larry Fingerf38d2232011-08-25 11:48:28 -0500917 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500918 tcb_desc->data_rate = MGN_1M;
919 tcb_desc->bTxDisableRateFallBack = 1;
920 }
921
922
923 tcb_desc->RATRIndex = 7;
924 tcb_desc->bTxUseDriverAssingedRate = 1;
925 tcb_desc->bdhcp = 1;
926 }
927
928 rtllib_qurey_ShortPreambleMode(ieee, tcb_desc);
Larry Fingerf38d2232011-08-25 11:48:28 -0500929 rtllib_tx_query_agg_cap(ieee, txb->fragments[0],
930 tcb_desc);
Larry Finger94a79942011-08-23 19:00:42 -0500931 rtllib_query_HTCapShortGI(ieee, tcb_desc);
932 rtllib_query_BandwidthMode(ieee, tcb_desc);
Larry Fingerf38d2232011-08-25 11:48:28 -0500933 rtllib_query_protectionmode(ieee, tcb_desc,
934 txb->fragments[0]);
Larry Finger94a79942011-08-23 19:00:42 -0500935 }
Larry Finger94a79942011-08-23 19:00:42 -0500936 }
937 spin_unlock_irqrestore(&ieee->lock, flags);
938 dev_kfree_skb_any(skb);
939 if (txb) {
Larry Fingerf38d2232011-08-25 11:48:28 -0500940 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
Larry Finger94a79942011-08-23 19:00:42 -0500941 dev->stats.tx_packets++;
942 dev->stats.tx_bytes += txb->payload_size;
943 rtllib_softmac_xmit(txb, ieee);
Larry Fingerf38d2232011-08-25 11:48:28 -0500944 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500945 if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
946 stats->tx_packets++;
947 stats->tx_bytes += txb->payload_size;
948 return 0;
949 }
950 rtllib_txb_free(txb);
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}
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}