blob: ffa9bf317d26b79a90a5b2d39e2b52b7b43ec6cc [file] [log] [blame]
Jerry Chuang8fc85982009-11-03 07:17:11 -02001/******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3 * Linux device driver for RTL8192U
4 *
5 * Based on the r8187 driver, which is:
6 * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * The full GNU General Public License is included in this distribution in the
21 * file called LICENSE.
22 *
23 * Contact Information:
24 * Jerry chuang <wlanfae@realtek.com>
25 */
26
27#ifndef CONFIG_FORCE_HARD_FLOAT
Xenia Ragiadakou27161412013-06-03 23:58:45 +030028double __floatsidf(int i)
29{
30 return i;
31}
32
33unsigned int __fixunsdfsi(double d)
34{
35 return d;
36}
37
38double __adddf3(double a, double b)
39{
40 return a+b;
41}
42
43double __addsf3(float a, float b)
44{
45 return a+b;
46}
47
48double __subdf3(double a, double b)
49{
50 return a-b;
51}
52
53double __extendsfdf2(float a)
54{
55 return a;
56}
Jerry Chuang8fc85982009-11-03 07:17:11 -020057#endif
58
59#undef LOOP_TEST
60#undef DUMP_RX
61#undef DUMP_TX
62#undef DEBUG_TX_DESC2
63#undef RX_DONT_PASS_UL
64#undef DEBUG_EPROM
65#undef DEBUG_RX_VERBOSE
66#undef DUMMY_RX
67#undef DEBUG_ZERO_RX
68#undef DEBUG_RX_SKB
69#undef DEBUG_TX_FRAG
70#undef DEBUG_RX_FRAG
71#undef DEBUG_TX_FILLDESC
72#undef DEBUG_TX
73#undef DEBUG_IRQ
74#undef DEBUG_RX
75#undef DEBUG_RXALLOC
76#undef DEBUG_REGISTERS
77#undef DEBUG_RING
78#undef DEBUG_IRQ_TASKLET
79#undef DEBUG_TX_ALLOC
80#undef DEBUG_TX_DESC
81
82#define CONFIG_RTL8192_IO_MAP
83
84#include <asm/uaccess.h>
85#include "r8192U_hw.h"
86#include "r8192U.h"
87#include "r8190_rtl8256.h" /* RTL8225 Radio frontend */
88#include "r8180_93cx6.h" /* Card EEPROM */
89#include "r8192U_wx.h"
90#include "r819xU_phy.h" //added by WB 4.30.2008
91#include "r819xU_phyreg.h"
92#include "r819xU_cmdpkt.h"
93#include "r8192U_dm.h"
Jerry Chuang8fc85982009-11-03 07:17:11 -020094#include <linux/usb.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090095#include <linux/slab.h>
David Howells0541f9d2013-04-08 15:17:33 +010096#include <linux/proc_fs.h>
97#include <linux/seq_file.h>
Jerry Chuang8fc85982009-11-03 07:17:11 -020098// FIXME: check if 2.6.7 is ok
Jerry Chuang8fc85982009-11-03 07:17:11 -020099
100#ifdef CONFIG_RTL8192_PM
101#include "r8192_pm.h"
102#endif
103
Jerry Chuang8fc85982009-11-03 07:17:11 -0200104#include "dot11d.h"
Jerry Chuang8fc85982009-11-03 07:17:11 -0200105//set here to open your trace code. //WB
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300106u32 rt_global_debug_component = COMP_DOWN |
Jerry Chuang8fc85982009-11-03 07:17:11 -0200107 COMP_SEC |
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300108 COMP_ERR; //always open err flags on
Jerry Chuang8fc85982009-11-03 07:17:11 -0200109
110#define TOTAL_CAM_ENTRY 32
111#define CAM_CONTENT_COUNT 8
112
Németh Mártona4577322010-01-10 00:18:34 +0100113static const struct usb_device_id rtl8192_usb_id_tbl[] = {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200114 /* Realtek */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200115 {USB_DEVICE(0x0bda, 0x8709)},
116 /* Corega */
117 {USB_DEVICE(0x07aa, 0x0043)},
118 /* Belkin */
119 {USB_DEVICE(0x050d, 0x805E)},
120 /* Sitecom */
121 {USB_DEVICE(0x0df6, 0x0031)},
122 /* EnGenius */
123 {USB_DEVICE(0x1740, 0x9201)},
124 /* Dlink */
125 {USB_DEVICE(0x2001, 0x3301)},
126 /* Zinwell */
127 {USB_DEVICE(0x5a57, 0x0290)},
Ben Hutchingse10ac152010-06-25 01:35:49 +0100128 /* LG */
129 {USB_DEVICE(0x043e, 0x7a01)},
Jerry Chuang8fc85982009-11-03 07:17:11 -0200130 {}
131};
132
133MODULE_LICENSE("GPL");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200134MODULE_VERSION("V 1.1");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200135MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl);
136MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards");
137
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300138static char *ifname = "wlan%d";
Jerry Chuang8fc85982009-11-03 07:17:11 -0200139static int hwwep = 1; //default use hw. set 0 to use software security
140static int channels = 0x3fff;
141
142
143
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300144module_param(ifname, charp, S_IRUGO|S_IWUSR);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300145module_param(hwwep, int, S_IRUGO|S_IWUSR);
146module_param(channels, int, S_IRUGO|S_IWUSR);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200147
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300148MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default");
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300149MODULE_PARM_DESC(hwwep, " Try to use hardware security support. ");
150MODULE_PARM_DESC(channels, " Channel bitmask for specific locales. NYI");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200151
Bill Pemberton25794522012-11-19 13:22:04 -0500152static int rtl8192_usb_probe(struct usb_interface *intf,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300153 const struct usb_device_id *id);
Bill Pembertona4a557e2012-11-19 13:26:46 -0500154static void rtl8192_usb_disconnect(struct usb_interface *intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200155
156
157static struct usb_driver rtl8192_usb_driver = {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200158 .name = RTL819xU_MODULE_NAME, /* Driver name */
159 .id_table = rtl8192_usb_id_tbl, /* PCI_ID table */
160 .probe = rtl8192_usb_probe, /* probe fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200161 .disconnect = rtl8192_usb_disconnect, /* remove fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200162#ifdef CONFIG_RTL8192_PM
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200163 .suspend = rtl8192_suspend, /* PM suspend fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200164 .resume = rtl8192_resume, /* PM resume fn */
165#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200166 .suspend = NULL, /* PM suspend fn */
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100167 .resume = NULL, /* PM resume fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200168#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -0200169};
170
Jerry Chuang8fc85982009-11-03 07:17:11 -0200171
Jennifer Naumann0db7a342012-12-05 21:40:19 +0100172typedef struct _CHANNEL_LIST {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200173 u8 Channel[32];
174 u8 Len;
Xenia Ragiadakou972ff922013-05-23 05:14:47 +0300175} CHANNEL_LIST, *PCHANNEL_LIST;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200176
177static CHANNEL_LIST ChannelPlan[] = {
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100178 {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,149,153,157,161,165},24}, //FCC
179 {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC
180 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //ETSI
Jerry Chuang8fc85982009-11-03 07:17:11 -0200181 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Spain. Change to ETSI.
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100182 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //France. Change to ETSI.
Jerry Chuang8fc85982009-11-03 07:17:11 -0200183 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, //MKK //MKK
184 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1
185 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Israel.
186 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, // For 11a , TELEC
187 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22}, //MIC
188 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14} //For Global Domain. 1-11:active scan, 12-14 passive scan. //+YJ, 080626
189};
190
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300191static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200192{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300193 int i, max_chan = -1, min_chan = -1;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300194 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300195 switch (channel_plan) {
Patrik Karlinf00c4932013-01-09 09:39:44 +0100196 case COUNTRY_CODE_FCC:
197 case COUNTRY_CODE_IC:
198 case COUNTRY_CODE_ETSI:
199 case COUNTRY_CODE_SPAIN:
200 case COUNTRY_CODE_FRANCE:
201 case COUNTRY_CODE_MKK:
202 case COUNTRY_CODE_MKK1:
203 case COUNTRY_CODE_ISRAEL:
204 case COUNTRY_CODE_TELEC:
205 case COUNTRY_CODE_MIC:
206 Dot11d_Init(ieee);
207 ieee->bGlobalDomain = false;
208 //actually 8225 & 8256 rf chips only support B,G,24N mode
209 if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256)) {
210 min_chan = 1;
211 max_chan = 14;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300212 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +0300213 RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __func__);
Patrik Karlinf00c4932013-01-09 09:39:44 +0100214 }
215 if (ChannelPlan[channel_plan].Len != 0) {
216 // Clear old channel map
217 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
218 // Set new channel map
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300219 for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
Patrik Karlinf00c4932013-01-09 09:39:44 +0100220 if (ChannelPlan[channel_plan].Channel[i] < min_chan || ChannelPlan[channel_plan].Channel[i] > max_chan)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200221 break;
Patrik Karlinf00c4932013-01-09 09:39:44 +0100222 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200223 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200224 }
Patrik Karlinf00c4932013-01-09 09:39:44 +0100225 break;
226
227 case COUNTRY_CODE_GLOBAL_DOMAIN:
228 GET_DOT11D_INFO(ieee)->bEnabled = 0;//this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain settings.
229 Dot11d_Reset(ieee);
230 ieee->bGlobalDomain = true;
231 break;
232
233 default:
234 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200235 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200236}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200237
Jerry Chuang8fc85982009-11-03 07:17:11 -0200238
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100239#define rx_hal_is_cck_rate(_pdrvinfo)\
Jerry Chuang8fc85982009-11-03 07:17:11 -0200240 (_pdrvinfo->RxRate == DESC90_RATE1M ||\
241 _pdrvinfo->RxRate == DESC90_RATE2M ||\
242 _pdrvinfo->RxRate == DESC90_RATE5_5M ||\
243 _pdrvinfo->RxRate == DESC90_RATE11M) &&\
244 !_pdrvinfo->RxHT\
245
246
247void CamResetAllEntry(struct net_device *dev)
248{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200249 u32 ulcommand = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200250 //2004/02/11 In static WEP, OID_ADD_KEY or OID_ADD_WEP are set before STA associate to AP.
251 // However, ResetKey is called on OID_802_11_INFRASTRUCTURE_MODE and MlmeAssociateRequest
252 // In this condition, Cam can not be reset because upper layer will not set this static key again.
Jerry Chuang8fc85982009-11-03 07:17:11 -0200253 ulcommand |= BIT31|BIT30;
254 write_nic_dword(dev, RWCAM, ulcommand);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200255
256}
257
258
259void write_cam(struct net_device *dev, u8 addr, u32 data)
260{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200261 write_nic_dword(dev, WCAMI, data);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300262 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200263}
264
265u32 read_cam(struct net_device *dev, u8 addr)
266{
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300267 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff));
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200268 return read_nic_dword(dev, 0xa8);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200269}
270
271void write_nic_byte_E(struct net_device *dev, int indx, u8 data)
272{
273 int status;
274 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
275 struct usb_device *udev = priv->udev;
276
277 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300278 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
279 indx|0xfe00, 0, &data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200280
281 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300282 netdev_err(dev, "write_nic_byte_E TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200283}
284
285u8 read_nic_byte_E(struct net_device *dev, int indx)
286{
287 int status;
288 u8 data;
289 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
290 struct usb_device *udev = priv->udev;
291
292 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300293 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
294 indx|0xfe00, 0, &data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200295
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200296 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300297 netdev_err(dev, "read_nic_byte_E TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200298
299 return data;
300}
301//as 92U has extend page from 4 to 16, so modify functions below.
302void write_nic_byte(struct net_device *dev, int indx, u8 data)
303{
304 int status;
305
306 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
307 struct usb_device *udev = priv->udev;
308
309 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300310 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
311 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200312
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200313 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300314 netdev_err(dev, "write_nic_byte TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200315
316
317}
318
319
320void write_nic_word(struct net_device *dev, int indx, u16 data)
321{
322
323 int status;
324
325 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
326 struct usb_device *udev = priv->udev;
327
328 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300329 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
330 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200331
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200332 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300333 netdev_err(dev, "write_nic_word TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200334
335}
336
337
338void write_nic_dword(struct net_device *dev, int indx, u32 data)
339{
340
341 int status;
342
343 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
344 struct usb_device *udev = priv->udev;
345
346 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300347 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
348 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200349
350
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200351 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300352 netdev_err(dev, "write_nic_dword TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200353
354}
355
356
357
358u8 read_nic_byte(struct net_device *dev, int indx)
359{
360 u8 data;
361 int status;
362 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
363 struct usb_device *udev = priv->udev;
364
365 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300366 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
367 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200368
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200369 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300370 netdev_err(dev, "read_nic_byte TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200371
372 return data;
373}
374
375
376
377u16 read_nic_word(struct net_device *dev, int indx)
378{
379 u16 data;
380 int status;
381 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
382 struct usb_device *udev = priv->udev;
383
384 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300385 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
386 (indx&0xff)|0xff00, (indx>>8)&0x0f,
387 &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200388
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200389 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300390 netdev_err(dev, "read_nic_word TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200391
392 return data;
393}
394
395u16 read_nic_word_E(struct net_device *dev, int indx)
396{
397 u16 data;
398 int status;
399 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
400 struct usb_device *udev = priv->udev;
401
402 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300403 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
404 indx|0xfe00, 0, &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200405
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200406 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300407 netdev_err(dev, "read_nic_word TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200408
409 return data;
410}
411
412u32 read_nic_dword(struct net_device *dev, int indx)
413{
414 u32 data;
415 int status;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200416
417 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
418 struct usb_device *udev = priv->udev;
419
420 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300421 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
422 (indx&0xff)|0xff00, (indx>>8)&0x0f,
423 &data, 4, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200424
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200425 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300426 netdev_err(dev, "read_nic_dword TimeOut! status:%d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200427
428 return data;
429}
430
Mike Gilks616f58f2010-06-03 18:29:23 +0800431/* u8 read_phy_cck(struct net_device *dev, u8 adr); */
432/* u8 read_phy_ofdm(struct net_device *dev, u8 adr); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200433/* this might still called in what was the PHY rtl8185/rtl8192 common code
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300434 * plans are to possibility turn it again in one common code...
Jerry Chuang8fc85982009-11-03 07:17:11 -0200435 */
436inline void force_pci_posting(struct net_device *dev)
437{
438}
439
Jerry Chuang8fc85982009-11-03 07:17:11 -0200440static struct net_device_stats *rtl8192_stats(struct net_device *dev);
441void rtl8192_commit(struct net_device *dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200442void rtl8192_restart(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200443void watch_dog_timer_callback(unsigned long data);
444
445/****************************************************************************
Mike Gilks616f58f2010-06-03 18:29:23 +0800446 * -----------------------------PROCFS STUFF-------------------------
447*****************************************************************************
448 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200449
Mike Gilks616f58f2010-06-03 18:29:23 +0800450static struct proc_dir_entry *rtl8192_proc;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200451
David Howells0541f9d2013-04-08 15:17:33 +0100452static int proc_get_stats_ap(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200453{
David Howells0541f9d2013-04-08 15:17:33 +0100454 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200455 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
456 struct ieee80211_device *ieee = priv->ieee80211;
457 struct ieee80211_network *target;
458
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200459 list_for_each_entry(target, &ieee->network_list, list) {
David Howells0541f9d2013-04-08 15:17:33 +0100460 const char *wpa = "non_WPA";
Mike Gilks616f58f2010-06-03 18:29:23 +0800461 if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0)
David Howells0541f9d2013-04-08 15:17:33 +0100462 wpa = "WPA";
463
464 seq_printf(m, "%s %s\n", target->ssid, wpa);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200465 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200466
David Howells0541f9d2013-04-08 15:17:33 +0100467 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200468}
469
David Howells0541f9d2013-04-08 15:17:33 +0100470static int proc_get_registers(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200471{
David Howells0541f9d2013-04-08 15:17:33 +0100472 struct net_device *dev = m->private;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300473 int i, n, max = 0xff;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200474
David Howells0541f9d2013-04-08 15:17:33 +0100475 seq_puts(m, "\n####################page 0##################\n ");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200476
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300477 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300478 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200479
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300480 for (i = 0; i < 16 && n <= max; i++, n++)
481 seq_printf(m, "%2x ", read_nic_byte(dev, 0x000|n));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200482 }
David Howells0541f9d2013-04-08 15:17:33 +0100483
484 seq_puts(m, "\n####################page 1##################\n ");
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300485 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300486 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200487
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300488 for (i = 0; i < 16 && n <= max; i++, n++)
489 seq_printf(m, "%2x ", read_nic_byte(dev, 0x100|n));
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200490 }
David Howells0541f9d2013-04-08 15:17:33 +0100491
492 seq_puts(m, "\n####################page 3##################\n ");
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300493 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300494 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200495
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300496 for (i = 0; i < 16 && n <= max; i++, n++)
497 seq_printf(m, "%2x ", read_nic_byte(dev, 0x300|n));
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200498 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200499
David Howells0541f9d2013-04-08 15:17:33 +0100500 seq_putc(m, '\n');
501 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200502}
503
David Howells0541f9d2013-04-08 15:17:33 +0100504static int proc_get_stats_tx(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200505{
David Howells0541f9d2013-04-08 15:17:33 +0100506 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200507 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
508
David Howells0541f9d2013-04-08 15:17:33 +0100509 seq_printf(m,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300510 "TX VI priority ok int: %lu\n"
511 "TX VI priority error int: %lu\n"
512 "TX VO priority ok int: %lu\n"
513 "TX VO priority error int: %lu\n"
514 "TX BE priority ok int: %lu\n"
515 "TX BE priority error int: %lu\n"
516 "TX BK priority ok int: %lu\n"
517 "TX BK priority error int: %lu\n"
518 "TX MANAGE priority ok int: %lu\n"
519 "TX MANAGE priority error int: %lu\n"
520 "TX BEACON priority ok int: %lu\n"
521 "TX BEACON priority error int: %lu\n"
522 "TX queue resume: %lu\n"
523 "TX queue stopped?: %d\n"
524 "TX fifo overflow: %lu\n"
525 "TX VI queue: %d\n"
526 "TX VO queue: %d\n"
527 "TX BE queue: %d\n"
528 "TX BK queue: %d\n"
529 "TX VI dropped: %lu\n"
530 "TX VO dropped: %lu\n"
531 "TX BE dropped: %lu\n"
532 "TX BK dropped: %lu\n"
533 "TX total data packets %lu\n",
534 priv->stats.txviokint,
535 priv->stats.txvierr,
536 priv->stats.txvookint,
537 priv->stats.txvoerr,
538 priv->stats.txbeokint,
539 priv->stats.txbeerr,
540 priv->stats.txbkokint,
541 priv->stats.txbkerr,
542 priv->stats.txmanageokint,
543 priv->stats.txmanageerr,
544 priv->stats.txbeaconokint,
545 priv->stats.txbeaconerr,
546 priv->stats.txresumed,
547 netif_queue_stopped(dev),
548 priv->stats.txoverflow,
549 atomic_read(&(priv->tx_pending[VI_PRIORITY])),
550 atomic_read(&(priv->tx_pending[VO_PRIORITY])),
551 atomic_read(&(priv->tx_pending[BE_PRIORITY])),
552 atomic_read(&(priv->tx_pending[BK_PRIORITY])),
553 priv->stats.txvidrop,
554 priv->stats.txvodrop,
555 priv->stats.txbedrop,
556 priv->stats.txbkdrop,
557 priv->stats.txdatapkt
Jerry Chuang8fc85982009-11-03 07:17:11 -0200558 );
559
David Howells0541f9d2013-04-08 15:17:33 +0100560 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200561}
562
David Howells0541f9d2013-04-08 15:17:33 +0100563static int proc_get_stats_rx(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200564{
David Howells0541f9d2013-04-08 15:17:33 +0100565 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200566 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
567
David Howells0541f9d2013-04-08 15:17:33 +0100568 seq_printf(m,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300569 "RX packets: %lu\n"
570 "RX urb status error: %lu\n"
571 "RX invalid urb error: %lu\n",
572 priv->stats.rxoktotal,
573 priv->stats.rxstaterr,
574 priv->stats.rxurberr);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200575
David Howells0541f9d2013-04-08 15:17:33 +0100576 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200577}
David Howells0541f9d2013-04-08 15:17:33 +0100578
Jerry Chuang8fc85982009-11-03 07:17:11 -0200579void rtl8192_proc_module_init(void)
580{
581 RT_TRACE(COMP_INIT, "Initializing proc filesystem");
Al Viroe55d92b2011-07-24 02:07:46 -0400582 rtl8192_proc = proc_mkdir(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200583}
584
585
586void rtl8192_proc_module_remove(void)
587{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200588 remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200589}
590
David Howells0541f9d2013-04-08 15:17:33 +0100591/*
592 * seq_file wrappers for procfile show routines.
593 */
594static int rtl8192_proc_open(struct inode *inode, struct file *file)
595{
David Howells4a520d22013-04-12 14:06:01 +0100596 struct net_device *dev = proc_get_parent_data(inode);
David Howells0541f9d2013-04-08 15:17:33 +0100597 int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
598
599 return single_open(file, show, dev);
600}
601
602static const struct file_operations rtl8192_proc_fops = {
603 .open = rtl8192_proc_open,
604 .read = seq_read,
605 .llseek = seq_lseek,
Al Virobae301d2013-05-05 00:15:43 -0400606 .release = single_release,
David Howells0541f9d2013-04-08 15:17:33 +0100607};
608
609/*
610 * Table of proc files we need to create.
611 */
612struct rtl8192_proc_file {
613 char name[12];
614 int (*show)(struct seq_file *, void *);
615};
616
617static const struct rtl8192_proc_file rtl8192_proc_files[] = {
618 { "stats-rx", &proc_get_stats_rx },
619 { "stats-tx", &proc_get_stats_tx },
620 { "stats-ap", &proc_get_stats_ap },
621 { "registers", &proc_get_registers },
622 { "" }
623};
624
625void rtl8192_proc_init_one(struct net_device *dev)
626{
627 const struct rtl8192_proc_file *f;
David Howellscc87e0f2013-04-12 03:02:22 +0100628 struct proc_dir_entry *dir;
David Howells0541f9d2013-04-08 15:17:33 +0100629
630 if (rtl8192_proc) {
David Howellscc87e0f2013-04-12 03:02:22 +0100631 dir = proc_mkdir_data(dev->name, 0, rtl8192_proc, dev);
632 if (!dir) {
David Howells0541f9d2013-04-08 15:17:33 +0100633 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
634 dev->name);
635 return;
636 }
David Howells0541f9d2013-04-08 15:17:33 +0100637
638 for (f = rtl8192_proc_files; f->name[0]; f++) {
David Howellscc87e0f2013-04-12 03:02:22 +0100639 if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir,
640 &rtl8192_proc_fops, f->show)) {
David Howells0541f9d2013-04-08 15:17:33 +0100641 RT_TRACE(COMP_ERR, "Unable to initialize "
642 "/proc/net/rtl8192/%s/%s\n",
643 dev->name, f->name);
644 return;
645 }
646 }
647 }
648}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200649
650void rtl8192_proc_remove_one(struct net_device *dev)
651{
David Howellscc87e0f2013-04-12 03:02:22 +0100652 remove_proc_subtree(dev->name, rtl8192_proc);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200653}
654
Jerry Chuang8fc85982009-11-03 07:17:11 -0200655/****************************************************************************
656 -----------------------------MISC STUFF-------------------------
657*****************************************************************************/
658
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300659short check_nic_enough_desc(struct net_device *dev, int queue_index)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200660{
661 struct r8192_priv *priv = ieee80211_priv(dev);
662 int used = atomic_read(&priv->tx_pending[queue_index]);
663
664 return (used < MAX_TX_URB);
665}
666
667void tx_timeout(struct net_device *dev)
668{
669 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200670
Jerry Chuang8fc85982009-11-03 07:17:11 -0200671 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200672}
673
674
675/* this is only for debug */
676void dump_eprom(struct net_device *dev)
677{
678 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300679 for (i = 0; i < 63; i++)
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300680 RT_TRACE(COMP_EPROM, "EEPROM addr %x : %x", i, eprom_read(dev, i));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200681}
682
Jerry Chuang8fc85982009-11-03 07:17:11 -0200683
684/****************************************************************************
685 ------------------------------HW STUFF---------------------------
686*****************************************************************************/
687
Jerry Chuang8fc85982009-11-03 07:17:11 -0200688
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300689void rtl8192_set_mode(struct net_device *dev, int mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200690{
691 u8 ecmd;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300692 ecmd = read_nic_byte(dev, EPROM_CMD);
693 ecmd = ecmd & ~EPROM_CMD_OPERATING_MODE_MASK;
694 ecmd = ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
695 ecmd = ecmd & ~(1<<EPROM_CS_SHIFT);
696 ecmd = ecmd & ~(1<<EPROM_CK_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200697 write_nic_byte(dev, EPROM_CMD, ecmd);
698}
699
700
701void rtl8192_update_msr(struct net_device *dev)
702{
703 struct r8192_priv *priv = ieee80211_priv(dev);
704 u8 msr;
705
706 msr = read_nic_byte(dev, MSR);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300707 msr &= ~MSR_LINK_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200708
709 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
710 * msr must be updated if the state is ASSOCIATING.
711 * this is intentional and make sense for ad-hoc and
712 * master (see the create BSS/IBSS func)
713 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300714 if (priv->ieee80211->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200715
716 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
717 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
718 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
719 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
720 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
721 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
722
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300723 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200724 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300725 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200726
727 write_nic_byte(dev, MSR, msr);
728}
729
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300730void rtl8192_set_chan(struct net_device *dev, short ch)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200731{
732 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +0300733 RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __func__, ch);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300734 priv->chan = ch;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200735
736 /* this hack should avoid frame TX during channel setting*/
737
Jerry Chuang8fc85982009-11-03 07:17:11 -0200738#ifndef LOOP_TEST
Jerry Chuang8fc85982009-11-03 07:17:11 -0200739 //need to implement rf set channel here WB
740
741 if (priv->rf_set_chan)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300742 priv->rf_set_chan(dev, priv->chan);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200743 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200744#endif
745}
746
Jerry Chuang8fc85982009-11-03 07:17:11 -0200747static void rtl8192_rx_isr(struct urb *urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200748
749u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
750{
751
752#ifdef USB_RX_AGGREGATION_SUPPORT
753 if (pstats->bisrxaggrsubframe)
754 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
755 + pstats->RxBufShift + 8);
756 else
757#endif
758 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300759 + pstats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200760
761}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300762static int rtl8192_rx_initiate(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200763{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200764 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
765 struct urb *entry;
766 struct sk_buff *skb;
767 struct rtl8192_rx_info *info;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200768
769 /* nomal packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200770 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB) {
771 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
772 if (!skb)
773 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200774 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200775 if (!entry) {
776 kfree_skb(skb);
777 break;
778 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200779 usb_fill_bulk_urb(entry, priv->udev,
780 usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb),
781 RX_URB_SIZE, rtl8192_rx_isr, skb);
782 info = (struct rtl8192_rx_info *) skb->cb;
783 info->urb = entry;
784 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200785 info->out_pipe = 3; //denote rx normal packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200786 skb_queue_tail(&priv->rx_queue, skb);
787 usb_submit_urb(entry, GFP_KERNEL);
788 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200789
790 /* command packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200791 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300792 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200793 if (!skb)
794 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200795 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200796 if (!entry) {
797 kfree_skb(skb);
798 break;
799 }
800 usb_fill_bulk_urb(entry, priv->udev,
801 usb_rcvbulkpipe(priv->udev, 9), skb_tail_pointer(skb),
802 RX_URB_SIZE, rtl8192_rx_isr, skb);
803 info = (struct rtl8192_rx_info *) skb->cb;
804 info->urb = entry;
805 info->dev = dev;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300806 info->out_pipe = 9; //denote rx cmd packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200807 skb_queue_tail(&priv->rx_queue, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200808 usb_submit_urb(entry, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200809 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200810
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200811 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200812}
813
814void rtl8192_set_rxconf(struct net_device *dev)
815{
816 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
817 u32 rxconf;
818
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300819 rxconf = read_nic_dword(dev, RCR);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300820 rxconf = rxconf & ~MAC_FILTER_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200821 rxconf = rxconf | RCR_AMF;
822 rxconf = rxconf | RCR_ADF;
823 rxconf = rxconf | RCR_AB;
824 rxconf = rxconf | RCR_AM;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200825
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300826 if (dev->flags & IFF_PROMISC)
827 DMESG("NIC in promisc mode");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200828
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300829 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300830 dev->flags & IFF_PROMISC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200831 rxconf = rxconf | RCR_AAP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300832 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200833 rxconf = rxconf | RCR_APM;
834 rxconf = rxconf | RCR_CBSSID;
835 }
836
837
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300838 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200839 rxconf = rxconf | RCR_AICV;
840 rxconf = rxconf | RCR_APWRMGT;
841 }
842
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300843 if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200844 rxconf = rxconf | RCR_ACRC32;
845
846
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300847 rxconf = rxconf & ~RX_FIFO_THRESHOLD_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200848 rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE<<RX_FIFO_THRESHOLD_SHIFT);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300849 rxconf = rxconf & ~MAX_RX_DMA_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200850 rxconf = rxconf | ((u32)7<<RCR_MXDMA_OFFSET);
851
Jerry Chuang8fc85982009-11-03 07:17:11 -0200852 rxconf = rxconf | RCR_ONLYERLPKT;
853
Jerry Chuang8fc85982009-11-03 07:17:11 -0200854 write_nic_dword(dev, RCR, rxconf);
855
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300856#ifdef DEBUG_RX
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300857 DMESG("rxconf: %x %x", rxconf, read_nic_dword(dev, RCR));
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300858#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -0200859}
860//wait to be removed
861void rtl8192_rx_enable(struct net_device *dev)
862{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200863 rtl8192_rx_initiate(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200864}
865
866
867void rtl8192_tx_enable(struct net_device *dev)
868{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200869}
870
Jerry Chuang8fc85982009-11-03 07:17:11 -0200871
872
873void rtl8192_rtx_disable(struct net_device *dev)
874{
875 u8 cmd;
876 struct r8192_priv *priv = ieee80211_priv(dev);
877 struct sk_buff *skb;
878 struct rtl8192_rx_info *info;
879
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300880 cmd = read_nic_byte(dev, CMDR);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300881 write_nic_byte(dev, CMDR, cmd & ~(CR_TE|CR_RE));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200882 force_pci_posting(dev);
883 mdelay(10);
884
885 while ((skb = __skb_dequeue(&priv->rx_queue))) {
886 info = (struct rtl8192_rx_info *) skb->cb;
887 if (!info->urb)
888 continue;
889
890 usb_kill_urb(info->urb);
891 kfree_skb(skb);
892 }
893
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300894 if (skb_queue_len(&priv->skb_queue))
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300895 netdev_warn(dev, "skb_queue not empty\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200896
897 skb_queue_purge(&priv->skb_queue);
898 return;
899}
900
901
902int alloc_tx_beacon_desc_ring(struct net_device *dev, int count)
903{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200904 return 0;
905}
906
Jerry Chuang8fc85982009-11-03 07:17:11 -0200907inline u16 ieeerate2rtlrate(int rate)
908{
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300909 switch (rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200910 case 10:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300911 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200912 case 20:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300913 return 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200914 case 55:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300915 return 2;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200916 case 110:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300917 return 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200918 case 60:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300919 return 4;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200920 case 90:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300921 return 5;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200922 case 120:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300923 return 6;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200924 case 180:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300925 return 7;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200926 case 240:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300927 return 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200928 case 360:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300929 return 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200930 case 480:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300931 return 10;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200932 case 540:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300933 return 11;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200934 default:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300935 return 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200936
937 }
938}
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300939static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
Jerry Chuang8fc85982009-11-03 07:17:11 -0200940inline u16 rtl8192_rate2rate(short rate)
941{
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300942 if (rate > 11) return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200943 return rtl_rate[rate];
944}
945
946
Justin P. Mattock589b3d02012-04-30 07:41:36 -0700947/* The prototype of rx_isr has changed since one version of Linux Kernel */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200948static void rtl8192_rx_isr(struct urb *urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200949{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200950 struct sk_buff *skb = (struct sk_buff *) urb->context;
951 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
952 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200953 struct r8192_priv *priv = ieee80211_priv(dev);
954 int out_pipe = info->out_pipe;
955 int err;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300956 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200957 return;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200958 if (unlikely(urb->status)) {
959 info->urb = NULL;
960 priv->stats.rxstaterr++;
961 priv->ieee80211->stats.rx_errors++;
962 usb_free_urb(urb);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200963 return;
964 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200965 skb_unlink(skb, &priv->rx_queue);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200966 skb_put(skb, urb->actual_length);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200967
968 skb_queue_tail(&priv->skb_queue, skb);
969 tasklet_schedule(&priv->irq_rx_tasklet);
970
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200971 skb = dev_alloc_skb(RX_URB_SIZE);
972 if (unlikely(!skb)) {
973 usb_free_urb(urb);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300974 netdev_err(dev, "%s(): can't alloc skb\n", __func__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200975 /* TODO check rx queue length and refill *somewhere* */
976 return;
977 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200978
979 usb_fill_bulk_urb(urb, priv->udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300980 usb_rcvbulkpipe(priv->udev, out_pipe), skb_tail_pointer(skb),
981 RX_URB_SIZE, rtl8192_rx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200982
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200983 info = (struct rtl8192_rx_info *) skb->cb;
984 info->urb = urb;
985 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200986 info->out_pipe = out_pipe;
987
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200988 urb->transfer_buffer = skb_tail_pointer(skb);
989 urb->context = skb;
990 skb_queue_tail(&priv->rx_queue, skb);
991 err = usb_submit_urb(urb, GFP_ATOMIC);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300992 if (err && err != EPERM)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300993 netdev_err(dev, "can not submit rxurb, err is %x, URB status is %x\n", err, urb->status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200994}
995
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +0300996u32 rtl819xusb_rx_command_packet(struct net_device *dev,
997 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200998{
999 u32 status;
1000
Jerry Chuang8fc85982009-11-03 07:17:11 -02001001 status = cmpk_message_handle_rx(dev, pstats);
1002 if (status)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001003 DMESG("rxcommandpackethandle819xusb: It is a command packet\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001004
Jerry Chuang8fc85982009-11-03 07:17:11 -02001005 return status;
1006}
1007
Jerry Chuang8fc85982009-11-03 07:17:11 -02001008
1009void rtl8192_data_hard_stop(struct net_device *dev)
1010{
1011 //FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001012}
1013
1014
1015void rtl8192_data_hard_resume(struct net_device *dev)
1016{
1017 // FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001018}
1019
1020/* this function TX data frames when the ieee80211 stack requires this.
1021 * It checks also if we need to stop the ieee tx queue, eventually do it
1022 */
1023void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
1024{
1025 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1026 int ret;
1027 unsigned long flags;
1028 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1029 u8 queue_index = tcb_desc->queue_index;
1030
1031 /* shall not be referred by command packet */
1032 assert(queue_index != TXCMD_QUEUE);
1033
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001034 spin_lock_irqsave(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001035
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001036 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001037 tcb_desc->bTxEnableFwCalcDur = 1;
1038 skb_push(skb, priv->ieee80211->tx_headroom);
1039 ret = rtl8192_tx(dev, skb);
1040
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001041 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001042
Jerry Chuang8fc85982009-11-03 07:17:11 -02001043 return;
1044}
1045
1046/* This is a rough attempt to TX a frame
1047 * This is called by the ieee 80211 stack to TX management frames.
1048 * If the ring is full packet are dropped (for data frame the queue
1049 * is stopped before this can happen).
1050 */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001051int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001052{
1053 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1054 int ret;
1055 unsigned long flags;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001056 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1057 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001058
1059
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001060 spin_lock_irqsave(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001061
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001062 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001063 if (queue_index == TXCMD_QUEUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001064 skb_push(skb, USB_HWDESC_HEADER_LEN);
1065 rtl819xU_tx_cmd(dev, skb);
1066 ret = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001067 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001068 return ret;
1069 } else {
1070 skb_push(skb, priv->ieee80211->tx_headroom);
1071 ret = rtl8192_tx(dev, skb);
1072 }
1073
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001074 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001075
1076 return ret;
1077}
1078
1079
1080void rtl8192_try_wake_queue(struct net_device *dev, int pri);
1081
1082#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1083u16 DrvAggr_PaddingAdd(struct net_device *dev, struct sk_buff *skb)
1084{
1085 u16 PaddingNum = 256 - ((skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES) % 256);
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03001086 return PaddingNum & 0xff;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001087}
1088
1089u8 MRateToHwRate8190Pci(u8 rate);
1090u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc);
1091u8 MapHwQueueToFirmwareQueue(u8 QueueID);
1092struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv_agg_txb *pSendList)
1093{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001094 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001095 struct r8192_priv *priv = ieee80211_priv(dev);
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001096 cb_desc *tcb_desc = NULL;
1097 u8 i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001098 u32 TotalLength;
1099 struct sk_buff *skb;
1100 struct sk_buff *agg_skb;
1101 tx_desc_819x_usb_aggr_subframe *tx_agg_desc = NULL;
1102 tx_fwinfo_819x_usb *tx_fwinfo = NULL;
1103
1104 //
1105 // Local variable initialization.
1106 //
1107 /* first skb initialization */
1108 skb = pSendList->tx_agg_frames[0];
1109 TotalLength = skb->len;
1110
1111 /* Get the total aggregation length including the padding space and
1112 * sub frame header.
1113 */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001114 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001115 TotalLength += DrvAggr_PaddingAdd(dev, skb);
1116 skb = pSendList->tx_agg_frames[i];
1117 TotalLength += (skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1118 }
1119
1120 /* allocate skb to contain the aggregated packets */
1121 agg_skb = dev_alloc_skb(TotalLength + ieee->tx_headroom);
1122 memset(agg_skb->data, 0, agg_skb->len);
1123 skb_reserve(agg_skb, ieee->tx_headroom);
1124
Jerry Chuang8fc85982009-11-03 07:17:11 -02001125 /* reserve info for first subframe Tx descriptor to be set in the tx function */
1126 skb = pSendList->tx_agg_frames[0];
1127 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1128 tcb_desc->drv_agg_enable = 1;
1129 tcb_desc->pkt_size = skb->len;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001130 tcb_desc->DrvAggrNum = pSendList->nr_drv_agg_frames;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001131 netdev_dbg(dev, "DrvAggNum = %d\n", tcb_desc->DrvAggrNum);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001132 memcpy(agg_skb->cb, skb->cb, sizeof(skb->cb));
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001133 memcpy(skb_put(agg_skb, skb->len), skb->data, skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001134
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001135 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001136 /* push the next sub frame to be 256 byte aline */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001137 skb_put(agg_skb, DrvAggr_PaddingAdd(dev, skb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001138
1139 /* Subframe drv Tx descriptor and firmware info setting */
1140 skb = pSendList->tx_agg_frames[i];
1141 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1142 tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)agg_skb->tail;
1143 tx_fwinfo = (tx_fwinfo_819x_usb *)(agg_skb->tail + sizeof(tx_desc_819x_usb_aggr_subframe));
1144
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001145 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001146 /* DWORD 0 */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001147 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001148 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1149 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1150 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001151 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001152 tx_fwinfo->AllowAggregation = 1;
1153 /* DWORD 1 */
1154 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1155 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1156 } else {
1157 tx_fwinfo->AllowAggregation = 0;
1158 /* DWORD 1 */
1159 tx_fwinfo->RxMF = 0;
1160 tx_fwinfo->RxAMD = 0;
1161 }
1162
1163 /* Protection mode related */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001164 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1165 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1166 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1167 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001168 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001169 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->RTSSC) : 0;
1170 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1) ? ((tcb_desc->bRTSBW) ? 1 : 0) : 0;
1171 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) :
1172 (tcb_desc->bRTSUseShortGI ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001173
1174 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001175 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001176 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001177 tx_fwinfo->TxBandwidth = 1;
1178 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1179 } else {
1180 tx_fwinfo->TxBandwidth = 0;
1181 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1182 }
1183 } else {
1184 tx_fwinfo->TxBandwidth = 0;
1185 tx_fwinfo->TxSubCarrier = 0;
1186 }
1187
1188 /* Fill Tx descriptor */
1189 memset(tx_agg_desc, 0, sizeof(tx_desc_819x_usb_aggr_subframe));
1190 /* DWORD 0 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001191 tx_agg_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001192 /* already raw data, need not to subtract header length */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001193 tx_agg_desc->PktSize = skb->len & 0xffff;
1194
1195 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001196 tx_agg_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001197 tx_agg_desc->RATid = tcb_desc->RATRIndex;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001198 tx_agg_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001199 tx_agg_desc->SecType = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001200
1201 if (tcb_desc->bHwSec) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001202 switch (priv->ieee80211->pairwise_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001203 case KEY_TYPE_WEP40:
1204 case KEY_TYPE_WEP104:
1205 tx_agg_desc->SecType = 0x1;
1206 tx_agg_desc->NoEnc = 0;
1207 break;
1208 case KEY_TYPE_TKIP:
1209 tx_agg_desc->SecType = 0x2;
1210 tx_agg_desc->NoEnc = 0;
1211 break;
1212 case KEY_TYPE_CCMP:
1213 tx_agg_desc->SecType = 0x3;
1214 tx_agg_desc->NoEnc = 0;
1215 break;
1216 case KEY_TYPE_NA:
1217 tx_agg_desc->SecType = 0x0;
1218 tx_agg_desc->NoEnc = 1;
1219 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001220 }
1221 }
1222
1223 tx_agg_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1224 tx_agg_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1225
1226 tx_agg_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1227 tx_agg_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1228
1229 tx_agg_desc->OWN = 1;
1230
1231 //DWORD 2
1232 /* According windows driver, it seems that there no need to fill this field */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001233
1234 /* to fill next packet */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001235 skb_put(agg_skb, TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1236 memcpy(skb_put(agg_skb, skb->len), skb->data, skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001237 }
1238
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001239 for (i = 0; i < pSendList->nr_drv_agg_frames; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001240 dev_kfree_skb_any(pSendList->tx_agg_frames[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001241
1242 return agg_skb;
1243}
1244
1245/* NOTE:
1246 This function return a list of PTCB which is proper to be aggregate with the input TCB.
1247 If no proper TCB is found to do aggregation, SendList will only contain the input TCB.
1248*/
1249u8 DrvAggr_GetAggregatibleList(struct net_device *dev, struct sk_buff *skb,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001250 struct ieee80211_drv_agg_txb *pSendList)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001251{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001252 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001253 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1254 u16 nMaxAggrNum = pHTInfo->UsbTxAggrNum;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001255 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001256 u8 QueueID = tcb_desc->queue_index;
1257
1258 do {
1259 pSendList->tx_agg_frames[pSendList->nr_drv_agg_frames++] = skb;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001260 if (pSendList->nr_drv_agg_frames >= nMaxAggrNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001261 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001262
Xenia Ragiadakou53c7f3c2013-05-22 18:22:35 +03001263 } while ((skb = skb_dequeue(&ieee->skb_drv_aggQ[QueueID])));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001264
1265 RT_TRACE(COMP_AMSDU, "DrvAggr_GetAggregatibleList, nAggrTcbNum = %d \n", pSendList->nr_drv_agg_frames);
1266 return pSendList->nr_drv_agg_frames;
1267}
1268#endif
1269
Jerry Chuang8fc85982009-11-03 07:17:11 -02001270static void rtl8192_tx_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001271{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001272 struct sk_buff *skb = (struct sk_buff *)tx_urb->context;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001273 struct net_device *dev = NULL;
1274 struct r8192_priv *priv = NULL;
1275 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1276 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001277
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001278 memcpy(&dev, (struct net_device *)(skb->cb), sizeof(struct net_device *));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001279 priv = ieee80211_priv(dev);
1280
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001281 if (tcb_desc->queue_index != TXCMD_QUEUE) {
1282 if (tx_urb->status == 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001283 dev->trans_start = jiffies;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001284 priv->stats.txoktotal++;
1285 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
1286 priv->stats.txbytesunicast += (skb->len - priv->ieee80211->tx_headroom);
1287 } else {
1288 priv->ieee80211->stats.tx_errors++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001289 /* TODO */
1290 }
1291 }
1292
1293 /* free skb and tx_urb */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001294 if (skb != NULL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001295 dev_kfree_skb_any(skb);
1296 usb_free_urb(tx_urb);
1297 atomic_dec(&priv->tx_pending[queue_index]);
1298 }
1299
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001300 //
1301 // Handle HW Beacon:
1302 // We had transfer our beacon frame to host controller at this moment.
1303 //
1304 //
1305 // Caution:
1306 // Handling the wait queue of command packets.
1307 // For Tx command packets, we must not do TCB fragment because it is not handled right now.
1308 // We must cut the packets to match the size of TX_CMD_PKT before we send it.
1309 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02001310
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001311 /* Handle MPDU in wait queue. */
1312 if (queue_index != BEACON_QUEUE) {
1313 /* Don't send data frame during scanning.*/
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001314 if ((skb_queue_len(&priv->ieee80211->skb_waitQ[queue_index]) != 0) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001315 (!(priv->ieee80211->queue_stop))) {
1316 if (NULL != (skb = skb_dequeue(&(priv->ieee80211->skb_waitQ[queue_index]))))
1317 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001318
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001319 return; //modified by david to avoid further processing AMSDU
Jerry Chuang8fc85982009-11-03 07:17:11 -02001320 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001321#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001322 else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index]) != 0) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001323 (!(priv->ieee80211->queue_stop))) {
1324 // Tx Driver Aggregation process
1325 /* The driver will aggregation the packets according to the following stats
1326 * 1. check whether there's tx irq available, for it's a completion return
1327 * function, it should contain enough tx irq;
1328 * 2. check packet type;
1329 * 3. initialize sendlist, check whether the to-be send packet no greater than 1
1330 * 4. aggregates the packets, and fill firmware info and tx desc into it, etc.
1331 * 5. check whether the packet could be sent, otherwise just insert into wait head
1332 * */
1333 skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]);
1334 if (!check_nic_enough_desc(dev, queue_index)) {
1335 skb_queue_head(&(priv->ieee80211->skb_drv_aggQ[queue_index]), skb);
1336 return;
1337 }
1338
1339 /*TODO*/
1340 {
1341 struct ieee80211_drv_agg_txb SendList;
1342
1343 memset(&SendList, 0, sizeof(struct ieee80211_drv_agg_txb));
1344 if (DrvAggr_GetAggregatibleList(dev, skb, &SendList) > 1) {
1345 skb = DrvAggr_Aggregation(dev, &SendList);
1346
1347 }
1348 }
1349 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1350 }
1351#endif
1352 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001353
Jerry Chuang8fc85982009-11-03 07:17:11 -02001354}
1355
1356void rtl8192_beacon_stop(struct net_device *dev)
1357{
1358 u8 msr, msrm, msr2;
1359 struct r8192_priv *priv = ieee80211_priv(dev);
1360
1361 msr = read_nic_byte(dev, MSR);
1362 msrm = msr & MSR_LINK_MASK;
1363 msr2 = msr & ~MSR_LINK_MASK;
1364
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001365 if (NIC_8192U == priv->card_8192)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001366 usb_kill_urb(priv->rx_urb[MAX_RX_URB]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001367 if ((msrm == (MSR_LINK_ADHOC<<MSR_LINK_SHIFT) ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001368 (msrm == (MSR_LINK_MASTER<<MSR_LINK_SHIFT)))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001369 write_nic_byte(dev, MSR, msr2 | MSR_LINK_NONE);
1370 write_nic_byte(dev, MSR, msr);
1371 }
1372}
1373
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001374void rtl8192_config_rate(struct net_device *dev, u16 *rate_config)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001375{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001376 struct r8192_priv *priv = ieee80211_priv(dev);
1377 struct ieee80211_network *net;
1378 u8 i = 0, basic_rate = 0;
1379 net = & priv->ieee80211->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001380
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001381 for (i = 0; i < net->rates_len; i++) {
1382 basic_rate = net->rates[i]&0x7f;
1383 switch (basic_rate) {
1384 case MGN_1M: *rate_config |= RRSR_1M; break;
1385 case MGN_2M: *rate_config |= RRSR_2M; break;
1386 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1387 case MGN_11M: *rate_config |= RRSR_11M; break;
1388 case MGN_6M: *rate_config |= RRSR_6M; break;
1389 case MGN_9M: *rate_config |= RRSR_9M; break;
1390 case MGN_12M: *rate_config |= RRSR_12M; break;
1391 case MGN_18M: *rate_config |= RRSR_18M; break;
1392 case MGN_24M: *rate_config |= RRSR_24M; break;
1393 case MGN_36M: *rate_config |= RRSR_36M; break;
1394 case MGN_48M: *rate_config |= RRSR_48M; break;
1395 case MGN_54M: *rate_config |= RRSR_54M; break;
1396 }
1397 }
1398 for (i = 0; i < net->rates_ex_len; i++) {
1399 basic_rate = net->rates_ex[i]&0x7f;
1400 switch (basic_rate) {
1401 case MGN_1M: *rate_config |= RRSR_1M; break;
1402 case MGN_2M: *rate_config |= RRSR_2M; break;
1403 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1404 case MGN_11M: *rate_config |= RRSR_11M; break;
1405 case MGN_6M: *rate_config |= RRSR_6M; break;
1406 case MGN_9M: *rate_config |= RRSR_9M; break;
1407 case MGN_12M: *rate_config |= RRSR_12M; break;
1408 case MGN_18M: *rate_config |= RRSR_18M; break;
1409 case MGN_24M: *rate_config |= RRSR_24M; break;
1410 case MGN_36M: *rate_config |= RRSR_36M; break;
1411 case MGN_48M: *rate_config |= RRSR_48M; break;
1412 case MGN_54M: *rate_config |= RRSR_54M; break;
1413 }
1414 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001415}
1416
1417
1418#define SHORT_SLOT_TIME 9
1419#define NON_SHORT_SLOT_TIME 20
1420
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001421void rtl8192_update_cap(struct net_device *dev, u16 cap)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001422{
1423 u32 tmp = 0;
1424 struct r8192_priv *priv = ieee80211_priv(dev);
1425 struct ieee80211_network *net = &priv->ieee80211->current_network;
1426 priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
1427 tmp = priv->basic_rate;
1428 if (priv->short_preamble)
1429 tmp |= BRSR_AckShortPmb;
1430 write_nic_dword(dev, RRSR, tmp);
1431
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001432 if (net->mode & (IEEE_G|IEEE_N_24G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001433 u8 slot_time = 0;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001434 if ((cap & WLAN_CAPABILITY_SHORT_SLOT) && (!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime)) //short slot time
Jerry Chuang8fc85982009-11-03 07:17:11 -02001435 slot_time = SHORT_SLOT_TIME;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001436 else //long slot time
1437 slot_time = NON_SHORT_SLOT_TIME;
1438 priv->slot_time = slot_time;
1439 write_nic_byte(dev, SLOT_TIME, slot_time);
1440 }
1441
1442}
1443void rtl8192_net_update(struct net_device *dev)
1444{
1445
1446 struct r8192_priv *priv = ieee80211_priv(dev);
1447 struct ieee80211_network *net;
1448 u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
1449 u16 rate_config = 0;
1450 net = & priv->ieee80211->current_network;
1451
1452 rtl8192_config_rate(dev, &rate_config);
1453 priv->basic_rate = rate_config &= 0x15f;
1454
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001455 write_nic_dword(dev, BSSIDR, ((u32 *)net->bssid)[0]);
1456 write_nic_word(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001457
1458 rtl8192_update_msr(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001459 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001460 write_nic_word(dev, ATIMWND, 2);
1461 write_nic_word(dev, BCN_DMATIME, 1023);
1462 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
1463 write_nic_word(dev, BCN_DRV_EARLY_INT, 1);
1464 write_nic_byte(dev, BCN_ERR_THRESH, 100);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001465 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001466 // TODO: BcnIFS may required to be changed on ASIC
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001467 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001468
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001469 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001470 }
1471
1472
1473
1474}
1475
1476//temporary hw beacon is not used any more.
1477//open it when necessary
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001478void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001479{
1480
Jerry Chuang8fc85982009-11-03 07:17:11 -02001481}
Jerry Chuang8fc85982009-11-03 07:17:11 -02001482inline u8 rtl8192_IsWirelessBMode(u16 rate)
1483{
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03001484 if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220))
Jerry Chuang8fc85982009-11-03 07:17:11 -02001485 return 1;
1486 else return 0;
1487}
1488
1489u16 N_DBPSOfRate(u16 DataRate);
1490
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03001491u16 ComputeTxTime(u16 FrameLength, u16 DataRate, u8 bManagementFrame,
1492 u8 bShortPreamble)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001493{
1494 u16 FrameTime;
1495 u16 N_DBPS;
1496 u16 Ceiling;
1497
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001498 if (rtl8192_IsWirelessBMode(DataRate)) {
1499 if (bManagementFrame || !bShortPreamble || DataRate == 10) // long preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001500 FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001501 else // Short preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001502 FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03001503 if ((FrameLength*8 % (DataRate/10)) != 0) //Get the Ceilling
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001504 FrameTime ++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001505 } else { //802.11g DSSS-OFDM PLCP length field calculation.
1506 N_DBPS = N_DBPSOfRate(DataRate);
1507 Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001508 + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001509 FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
1510 }
1511 return FrameTime;
1512}
1513
1514u16 N_DBPSOfRate(u16 DataRate)
1515{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001516 u16 N_DBPS = 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001517
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001518 switch (DataRate) {
1519 case 60:
1520 N_DBPS = 24;
1521 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001522
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001523 case 90:
1524 N_DBPS = 36;
1525 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001526
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001527 case 120:
1528 N_DBPS = 48;
1529 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001530
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001531 case 180:
1532 N_DBPS = 72;
1533 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001534
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001535 case 240:
1536 N_DBPS = 96;
1537 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001538
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001539 case 360:
1540 N_DBPS = 144;
1541 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001542
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001543 case 480:
1544 N_DBPS = 192;
1545 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001546
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001547 case 540:
1548 N_DBPS = 216;
1549 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001550
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001551 default:
1552 break;
1553 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001554
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001555 return N_DBPS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001556}
1557
1558void rtl819xU_cmd_isr(struct urb *tx_cmd_urb, struct pt_regs *regs)
1559{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001560 usb_free_urb(tx_cmd_urb);
1561}
1562
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001563unsigned int txqueue2outpipe(struct r8192_priv *priv, unsigned int tx_queue)
1564{
1565 if (tx_queue >= 9) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03001566 RT_TRACE(COMP_ERR, "%s():Unknown queue ID!!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001567 return 0x04;
1568 }
1569 return priv->txqueue_to_outpipemap[tx_queue];
1570}
1571
1572short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
1573{
1574 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001575 int status;
1576 struct urb *tx_urb;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001577 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001578 tx_desc_cmd_819x_usb *pdesc = (tx_desc_cmd_819x_usb *)skb->data;
1579 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1580 u8 queue_index = tcb_desc->queue_index;
1581
Jerry Chuang8fc85982009-11-03 07:17:11 -02001582 atomic_inc(&priv->tx_pending[queue_index]);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001583 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001584 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001585 dev_kfree_skb(skb);
1586 return -ENOMEM;
1587 }
1588
1589 memset(pdesc, 0, USB_HWDESC_HEADER_LEN);
1590 /* Tx descriptor ought to be set according to the skb->cb */
1591 pdesc->FirstSeg = 1;//bFirstSeg;
1592 pdesc->LastSeg = 1;//bLastSeg;
1593 pdesc->CmdInit = tcb_desc->bCmdOrInit;
1594 pdesc->TxBufferSize = tcb_desc->txbuf_size;
1595 pdesc->OWN = 1;
1596 pdesc->LINIP = tcb_desc->bLastIniPkt;
1597
1598 //----------------------------------------------------------------------------
1599 // Fill up USB_OUT_CONTEXT.
1600 //----------------------------------------------------------------------------
1601 // Get index to out pipe from specified QueueID.
1602#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001603 idx_pipe = txqueue2outpipe(priv, queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001604#else
1605 idx_pipe = 0x04;
1606#endif
1607#ifdef JOHN_DUMP_TXDESC
1608 int i;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001609 printk("<Tx descriptor>--rate %x---", rate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001610 for (i = 0; i < 8; i++)
1611 printk("%8x ", tx[i]);
1612 printk("\n");
1613#endif
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03001614 usb_fill_bulk_urb(tx_urb, priv->udev, usb_sndbulkpipe(priv->udev, idx_pipe),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001615 skb->data, skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001616
Jerry Chuang8fc85982009-11-03 07:17:11 -02001617 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001618
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001619 if (!status) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001620 return 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001621 } else {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001622 DMESGE("Error TX CMD URB, error %d", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001623 return -1;
1624 }
1625}
1626
1627/*
1628 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1629 * in TxFwInfo data structure
1630 * 2006.10.30 by Emily
1631 *
1632 * \param QUEUEID Software Queue
1633*/
1634u8 MapHwQueueToFirmwareQueue(u8 QueueID)
1635{
1636 u8 QueueSelect = 0x0; //defualt set to
1637
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001638 switch (QueueID) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001639 case BE_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001640 QueueSelect = QSLT_BE;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001641 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001642
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001643 case BK_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001644 QueueSelect = QSLT_BK;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001645 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001646
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001647 case VO_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001648 QueueSelect = QSLT_VO;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001649 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001650
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001651 case VI_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001652 QueueSelect = QSLT_VI;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001653 break;
1654 case MGNT_QUEUE:
1655 QueueSelect = QSLT_MGNT;
1656 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001657
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001658 case BEACON_QUEUE:
1659 QueueSelect = QSLT_BEACON;
1660 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001661
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001662 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
1663 // TODO: Remove Assertions
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001664 case TXCMD_QUEUE:
1665 QueueSelect = QSLT_CMD;
1666 break;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001667 case HIGH_QUEUE:
1668 QueueSelect = QSLT_HIGH;
1669 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001670
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001671 default:
1672 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
1673 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001674 }
1675 return QueueSelect;
1676}
1677
1678u8 MRateToHwRate8190Pci(u8 rate)
1679{
1680 u8 ret = DESC90_RATE1M;
1681
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001682 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001683 case MGN_1M: ret = DESC90_RATE1M; break;
1684 case MGN_2M: ret = DESC90_RATE2M; break;
1685 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1686 case MGN_11M: ret = DESC90_RATE11M; break;
1687 case MGN_6M: ret = DESC90_RATE6M; break;
1688 case MGN_9M: ret = DESC90_RATE9M; break;
1689 case MGN_12M: ret = DESC90_RATE12M; break;
1690 case MGN_18M: ret = DESC90_RATE18M; break;
1691 case MGN_24M: ret = DESC90_RATE24M; break;
1692 case MGN_36M: ret = DESC90_RATE36M; break;
1693 case MGN_48M: ret = DESC90_RATE48M; break;
1694 case MGN_54M: ret = DESC90_RATE54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001695
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001696 // HT rate since here
1697 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1698 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1699 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1700 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1701 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1702 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1703 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1704 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1705 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1706 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1707 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1708 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1709 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1710 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1711 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1712 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1713 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001714
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001715 default: break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001716 }
1717 return ret;
1718}
1719
1720
1721u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
1722{
1723 u8 tmp_Short;
1724
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001725 tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) : ((tcb_desc->bUseShortPreamble) ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001726
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03001727 if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001728 tmp_Short = 0;
1729
1730 return tmp_Short;
1731}
1732
Jerry Chuang8fc85982009-11-03 07:17:11 -02001733static void tx_zero_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001734{
1735 return;
1736}
1737
1738/*
1739 * The tx procedure is just as following,
1740 * skb->cb will contain all the following information,
1741 * priority, morefrag, rate, &dev.
1742 * */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001743short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001744{
1745 struct r8192_priv *priv = ieee80211_priv(dev);
1746 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1747 tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data;
1748 tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
1749 struct usb_device *udev = priv->udev;
1750 int pend;
1751 int status;
1752 struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001753 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001754 pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]);
1755 /* we are locked here so the two atomic_read and inc are executed
1756 * without interleaves
1757 * !!! For debug purpose
1758 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001759 if (pend > MAX_TX_URB) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001760 netdev_dbg(dev, "To discard skb packet!\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001761 dev_kfree_skb_any(skb);
1762 return -1;
1763 }
1764
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001765 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001766 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001767 dev_kfree_skb_any(skb);
1768 return -ENOMEM;
1769 }
1770
1771 /* Fill Tx firmware info */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001772 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001773 /* DWORD 0 */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001774 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001775 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1776 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1777 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001778 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001779 tx_fwinfo->AllowAggregation = 1;
1780 /* DWORD 1 */
1781 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1782 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1783 } else {
1784 tx_fwinfo->AllowAggregation = 0;
1785 /* DWORD 1 */
1786 tx_fwinfo->RxMF = 0;
1787 tx_fwinfo->RxAMD = 0;
1788 }
1789
1790 /* Protection mode related */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001791 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1792 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1793 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1794 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001795 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001796 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->RTSSC) : 0;
1797 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1) ? ((tcb_desc->bRTSBW) ? 1 : 0) : 0;
1798 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) :
1799 (tcb_desc->bRTSUseShortGI ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001800
1801 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001802 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001803 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001804 tx_fwinfo->TxBandwidth = 1;
1805 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1806 } else {
1807 tx_fwinfo->TxBandwidth = 0;
1808 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1809 }
1810 } else {
1811 tx_fwinfo->TxBandwidth = 0;
1812 tx_fwinfo->TxSubCarrier = 0;
1813 }
1814
1815#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1816 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001817 tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001818#endif
1819 /* Fill Tx descriptor */
1820 memset(tx_desc, 0, sizeof(tx_desc_819x_usb));
1821 /* DWORD 0 */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001822 tx_desc->LINIP = 0;
1823 tx_desc->CmdInit = 1;
1824 tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001825
1826#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001827 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001828 tx_desc->PktSize = tcb_desc->pkt_size;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001829 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02001830#endif
1831 {
1832 tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff;
1833 }
1834
1835 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001836 tx_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001837 tx_desc->RATid = tcb_desc->RATRIndex;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001838 tx_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001839 tx_desc->SecType = 0x0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001840 if (tcb_desc->bHwSec) {
1841 switch (priv->ieee80211->pairwise_key_type) {
1842 case KEY_TYPE_WEP40:
1843 case KEY_TYPE_WEP104:
1844 tx_desc->SecType = 0x1;
1845 tx_desc->NoEnc = 0;
1846 break;
1847 case KEY_TYPE_TKIP:
1848 tx_desc->SecType = 0x2;
1849 tx_desc->NoEnc = 0;
1850 break;
1851 case KEY_TYPE_CCMP:
1852 tx_desc->SecType = 0x3;
1853 tx_desc->NoEnc = 0;
1854 break;
1855 case KEY_TYPE_NA:
1856 tx_desc->SecType = 0x0;
1857 tx_desc->NoEnc = 1;
1858 break;
1859 }
1860 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001861
1862 tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1863 tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1864
1865 tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1866 tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1867
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001868 /* Fill fields that are required to be initialized in all of the descriptors */
1869 //DWORD 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001870 tx_desc->FirstSeg = 1;
1871 tx_desc->LastSeg = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001872 tx_desc->OWN = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001873
1874#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1875 if (tcb_desc->drv_agg_enable) {
1876 tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb);
1877 } else
1878#endif
1879 {
1880 //DWORD 2
1881 tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN);
1882 }
1883 /* Get index to out pipe from specified QueueID */
1884#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001885 idx_pipe = txqueue2outpipe(priv, tcb_desc->queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001886#else
1887 idx_pipe = 0x5;
1888#endif
1889
Jerry Chuang8fc85982009-11-03 07:17:11 -02001890 /* To submit bulk urb */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001891 usb_fill_bulk_urb(tx_urb, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001892 usb_sndbulkpipe(udev, idx_pipe), skb->data,
1893 skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001894
Jerry Chuang8fc85982009-11-03 07:17:11 -02001895 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001896 if (!status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001897 //we need to send 0 byte packet whenever 512N bytes/64N(HIGN SPEED/NORMAL SPEED) bytes packet has been transmitted. Otherwise, it will be halt to wait for another packet. WB. 2008.08.27
Jerry Chuang8fc85982009-11-03 07:17:11 -02001898 bool bSend0Byte = false;
1899 u8 zero = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001900 if (udev->speed == USB_SPEED_HIGH) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001901 if (skb->len > 0 && skb->len % 512 == 0)
1902 bSend0Byte = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001903 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001904 if (skb->len > 0 && skb->len % 64 == 0)
1905 bSend0Byte = true;
1906 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001907 if (bSend0Byte) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001908 tx_urb_zero = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001909 if (!tx_urb_zero) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001910 RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
1911 return -ENOMEM;
1912 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001913 usb_fill_bulk_urb(tx_urb_zero, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001914 usb_sndbulkpipe(udev, idx_pipe), &zero,
1915 0, tx_zero_isr, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001916 status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001917 if (status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001918 RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
1919 return -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001920 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001921 }
1922 dev->trans_start = jiffies;
1923 atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
1924 return 0;
Patrik Karlin29b48ae2013-01-09 09:40:23 +01001925 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001926 RT_TRACE(COMP_ERR, "Error TX URB %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001927 status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001928 return -1;
1929 }
1930}
1931
1932short rtl8192_usb_initendpoints(struct net_device *dev)
1933{
1934 struct r8192_priv *priv = ieee80211_priv(dev);
1935
Julia Lawall32414872010-05-11 20:26:57 +02001936 priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB+1),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001937 GFP_KERNEL);
David Chosrovab8345172010-12-01 13:42:16 +01001938 if (priv->rx_urb == NULL)
1939 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001940
1941#ifndef JACKSON_NEW_RX
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001942 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001943
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001944 priv->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001945
1946 priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL);
1947
1948 priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE;
1949 }
1950#endif
1951
1952#ifdef THOMAS_BEACON
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001953 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001954 long align = 0;
1955 void *oldaddr, *newaddr;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001956
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001957 priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
1958 priv->oldaddr = kmalloc(16, GFP_KERNEL);
1959 oldaddr = priv->oldaddr;
1960 align = ((long)oldaddr) & 3;
1961 if (align) {
1962 newaddr = oldaddr + 4 - align;
1963 priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align;
1964 } else {
1965 newaddr = oldaddr;
1966 priv->rx_urb[16]->transfer_buffer_length = 16;
1967 }
1968 priv->rx_urb[16]->transfer_buffer = newaddr;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001969 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001970#endif
1971
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001972 memset(priv->rx_urb, 0, sizeof(struct urb *) * MAX_RX_URB);
Julia Lawall7a6cb0d2010-05-13 22:00:05 +02001973 priv->pp_rxskb = kcalloc(MAX_RX_URB, sizeof(struct sk_buff *),
Julia Lawall32414872010-05-11 20:26:57 +02001974 GFP_KERNEL);
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001975 if (!priv->pp_rxskb) {
1976 kfree(priv->rx_urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001977
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001978 priv->pp_rxskb = NULL;
1979 priv->rx_urb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001980
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001981 DMESGE("Endpoint Alloc Failure");
1982 return -ENOMEM;
1983 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001984
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001985 netdev_dbg(dev, "End of initendpoints\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001986 return 0;
1987
1988}
1989#ifdef THOMAS_BEACON
1990void rtl8192_usb_deleteendpoints(struct net_device *dev)
1991{
1992 int i;
1993 struct r8192_priv *priv = ieee80211_priv(dev);
1994
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001995 if (priv->rx_urb) {
1996 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001997 usb_kill_urb(priv->rx_urb[i]);
1998 usb_free_urb(priv->rx_urb[i]);
1999 }
2000 kfree(priv->rx_urb);
2001 priv->rx_urb = NULL;
2002 }
Ilia Mirkine72714f2011-03-13 00:29:07 -05002003 kfree(priv->oldaddr);
2004 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002005 if (priv->pp_rxskb) {
2006 kfree(priv->pp_rxskb);
2007 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002008 }
2009}
2010#else
2011void rtl8192_usb_deleteendpoints(struct net_device *dev)
2012{
2013 int i;
2014 struct r8192_priv *priv = ieee80211_priv(dev);
2015
2016#ifndef JACKSON_NEW_RX
2017
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002018 if (priv->rx_urb) {
2019 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002020 usb_kill_urb(priv->rx_urb[i]);
2021 kfree(priv->rx_urb[i]->transfer_buffer);
2022 usb_free_urb(priv->rx_urb[i]);
2023 }
2024 kfree(priv->rx_urb);
2025 priv->rx_urb = NULL;
2026
2027 }
2028#else
Ilia Mirkine72714f2011-03-13 00:29:07 -05002029 kfree(priv->rx_urb);
2030 priv->rx_urb = NULL;
2031 kfree(priv->oldaddr);
2032 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002033 if (priv->pp_rxskb) {
2034 kfree(priv->pp_rxskb);
2035 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002036
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002037 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002038
2039#endif
2040}
2041#endif
2042
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002043extern void rtl8192_update_ratr_table(struct net_device *dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002044void rtl8192_link_change(struct net_device *dev)
2045{
Jerry Chuang8fc85982009-11-03 07:17:11 -02002046 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002047 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002048 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002049 rtl8192_net_update(dev);
2050 rtl8192_update_ratr_table(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002051 //add this as in pure N mode, wep encryption will use software way, but there is no chance to set this as wep will not set group key in wext. WB.2008.07.08
2052 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002053 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002054 }
2055 /*update timing params*/
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002056 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002057 u32 reg = 0;
2058 reg = read_nic_dword(dev, RCR);
2059 if (priv->ieee80211->state == IEEE80211_LINKED)
2060 priv->ReceiveConfig = reg |= RCR_CBSSID;
2061 else
2062 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
2063 write_nic_dword(dev, RCR, reg);
2064 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002065}
2066
2067static struct ieee80211_qos_parameters def_qos_parameters = {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002068 {3, 3, 3, 3},/* cw_min */
2069 {7, 7, 7, 7},/* cw_max */
2070 {2, 2, 2, 2},/* aifs */
2071 {0, 0, 0, 0},/* flags */
2072 {0, 0, 0, 0} /* tx_op_limit */
Jerry Chuang8fc85982009-11-03 07:17:11 -02002073};
2074
2075
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002076void rtl8192_update_beacon(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002077{
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002078 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
2079 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002080 struct ieee80211_device *ieee = priv->ieee80211;
2081 struct ieee80211_network *net = &ieee->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002082
2083 if (ieee->pHTInfo->bCurrentHTSupport)
2084 HTUpdateSelfAndPeerSetting(ieee, net);
2085 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
2086 rtl8192_update_cap(dev, net->capability);
2087}
2088/*
2089* background support to run QoS activate functionality
2090*/
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002091int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, EDCAPARA_VO};
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002092void rtl8192_qos_activate(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002093{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002094 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
2095 struct net_device *dev = priv->ieee80211->dev;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002096 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2097 u8 mode = priv->ieee80211->current_network.mode;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002098 u8 u1bAIFS;
2099 u32 u4bAcParam;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002100 int i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002101
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002102 if (priv == NULL)
2103 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002104
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002105 mutex_lock(&priv->mutex);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002106 if (priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002107 goto success;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002108 RT_TRACE(COMP_QOS, "qos active process with associate response received\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002109 /* It better set slot time at first */
2110 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2111 /* update the ac parameter to related registers */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002112 for (i = 0; i < QOS_QUEUE_NUM; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002113 //Mode G/A: slotTimeTimer = 9; Mode B: 20
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002114 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002115 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002116 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2117 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2118 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002119
2120 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002121 }
2122
2123success:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002124 mutex_unlock(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002125}
2126
2127static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002128 int active_network,
2129 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002130{
2131 int ret = 0;
2132 u32 size = sizeof(struct ieee80211_qos_parameters);
2133
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002134 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002135 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002136
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002137 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2138 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002139
2140 if (network->flags & NETWORK_HAS_QOS_MASK) {
2141 if (active_network &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002142 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
Jerry Chuang8fc85982009-11-03 07:17:11 -02002143 network->qos_data.active = network->qos_data.supported;
2144
2145 if ((network->qos_data.active == 1) && (active_network == 1) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002146 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2147 (network->qos_data.old_param_count !=
2148 network->qos_data.param_count)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002149 network->qos_data.old_param_count =
2150 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002151 queue_work(priv->priv_wq, &priv->qos_activate);
Xenia Ragiadakoue6367212013-05-23 05:14:46 +03002152 RT_TRACE(COMP_QOS, "QoS parameters change call "
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002153 "qos_activate\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002154 }
2155 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002156 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002157 &def_qos_parameters, size);
2158
2159 if ((network->qos_data.active == 1) && (active_network == 1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002160 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002161 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2162 }
2163 network->qos_data.active = 0;
2164 network->qos_data.supported = 0;
2165 }
2166
2167 return 0;
2168}
2169
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002170/* handle and manage frame from beacon and probe response */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002171static int rtl8192_handle_beacon(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002172 struct ieee80211_beacon *beacon,
2173 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002174{
2175 struct r8192_priv *priv = ieee80211_priv(dev);
2176
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002177 rtl8192_qos_handle_probe_response(priv, 1, network);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002178 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002179 return 0;
2180
2181}
2182
2183/*
2184* handling the beaconing responses. if we get different QoS setting
2185* off the network from the associated setting, adjust the QoS
2186* setting
2187*/
2188static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002189 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002190{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002191 int ret = 0;
2192 unsigned long flags;
2193 u32 size = sizeof(struct ieee80211_qos_parameters);
2194 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002195
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002196 if ((priv == NULL) || (network == NULL))
2197 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002198
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002199 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002200 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002201
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002202 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2203 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002204
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002205 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002206 if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002207 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002208 &network->qos_data.parameters,
2209 sizeof(struct ieee80211_qos_parameters));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002210 priv->ieee80211->current_network.qos_data.active = 1;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002211 set_qos_param = 1;
2212 /* update qos parameter for current network */
2213 priv->ieee80211->current_network.qos_data.old_param_count =
2214 priv->ieee80211->current_network.qos_data.param_count;
2215 priv->ieee80211->current_network.qos_data.param_count =
2216 network->qos_data.param_count;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002217 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002218 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002219 &def_qos_parameters, size);
2220 priv->ieee80211->current_network.qos_data.active = 0;
2221 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002222 set_qos_param = 1;
2223 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002224
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002225 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002226
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002227 RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n", __func__, network->flags, priv->ieee80211->current_network.qos_data.active);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002228 if (set_qos_param == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002229 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002230
2231
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002232 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002233}
2234
2235
2236static int rtl8192_handle_assoc_response(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002237 struct ieee80211_assoc_response_frame *resp,
2238 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002239{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002240 struct r8192_priv *priv = ieee80211_priv(dev);
2241 rtl8192_qos_association_resp(priv, network);
2242 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002243}
2244
2245
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002246void rtl8192_update_ratr_table(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002247{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002248 struct r8192_priv *priv = ieee80211_priv(dev);
2249 struct ieee80211_device *ieee = priv->ieee80211;
2250 u8 *pMcsRate = ieee->dot11HTOperationalRateSet;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002251 u32 ratr_value = 0;
2252 u8 rate_index = 0;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002253 rtl8192_config_rate(dev, (u16 *)(&ratr_value));
2254 ratr_value |= (*(u16 *)(pMcsRate)) << 12;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002255 switch (ieee->mode) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002256 case IEEE_A:
2257 ratr_value &= 0x00000FF0;
2258 break;
2259 case IEEE_B:
2260 ratr_value &= 0x0000000F;
2261 break;
2262 case IEEE_G:
2263 ratr_value &= 0x00000FF7;
2264 break;
2265 case IEEE_N_24G:
2266 case IEEE_N_5G:
2267 if (ieee->pHTInfo->PeerMimoPs == 0) {//MIMO_PS_STATIC
2268 ratr_value &= 0x0007F007;
2269 } else {
2270 if (priv->rf_type == RF_1T2R)
2271 ratr_value &= 0x000FF007;
2272 else
2273 ratr_value &= 0x0F81F007;
2274 }
2275 break;
2276 default:
2277 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002278 }
2279 ratr_value &= 0x0FFFFFFF;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002280 if (ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002281 ratr_value |= 0x80000000;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002282 else if (!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002283 ratr_value |= 0x80000000;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002284 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2285 write_nic_byte(dev, UFWP, 1);
2286}
2287
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002288static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04};
Jerry Chuang8fc85982009-11-03 07:17:11 -02002289static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002290bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002291{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002292 struct r8192_priv *priv = ieee80211_priv(dev);
2293 struct ieee80211_device *ieee = priv->ieee80211;
2294 struct ieee80211_network *network = &ieee->current_network;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002295 int wpa_ie_len = ieee->wpa_ie_len;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002296 struct ieee80211_crypt_data *crypt;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002297 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002298
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002299 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002300 //we use connecting AP's capability instead of only security config on our driver to distinguish whether it should use N mode or G mode
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002301 encrypt = (network->capability & WLAN_CAPABILITY_PRIVACY) || (ieee->host_encrypt && crypt && crypt->ops && (0 == strcmp(crypt->ops->name, "WEP")));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002302
2303 /* simply judge */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002304 if (encrypt && (wpa_ie_len == 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002305 /* wep encryption, no N mode setting */
2306 return false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002307 } else if ((wpa_ie_len != 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002308 /* parse pairwise key type */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002309 if (((ieee->wpa_ie[0] == 0xdd) && (!memcmp(&(ieee->wpa_ie[14]), ccmp_ie, 4))) || ((ieee->wpa_ie[0] == 0x30) && (!memcmp(&ieee->wpa_ie[10], ccmp_rsn_ie, 4))))
Jerry Chuang8fc85982009-11-03 07:17:11 -02002310 return true;
2311 else
2312 return false;
2313 } else {
2314 return true;
2315 }
2316
Jerry Chuang8fc85982009-11-03 07:17:11 -02002317 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002318}
2319
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002320bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002321{
2322 bool Reval;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002323 struct r8192_priv *priv = ieee80211_priv(dev);
2324 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002325
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002326 if (ieee->bHalfWirelessN24GMode == true)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002327 Reval = true;
2328 else
2329 Reval = false;
2330
2331 return Reval;
2332}
2333
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002334void rtl8192_refresh_supportrate(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002335{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002336 struct ieee80211_device *ieee = priv->ieee80211;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002337 //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002338 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002339 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002340 else
2341 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2342 return;
2343}
2344
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002345u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002346{
2347 struct r8192_priv *priv = ieee80211_priv(dev);
2348 u8 ret = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002349 switch (priv->rf_chip) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002350 case RF_8225:
2351 case RF_8256:
2352 case RF_PSEUDO_11N:
2353 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2354 break;
2355 case RF_8258:
2356 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2357 break;
2358 default:
2359 ret = WIRELESS_MODE_B;
2360 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002361 }
2362 return ret;
2363}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002364void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002365{
2366 struct r8192_priv *priv = ieee80211_priv(dev);
2367 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2368
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002369 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode) == 0)) {
2370 if (bSupportMode & WIRELESS_MODE_N_24G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002371 wireless_mode = WIRELESS_MODE_N_24G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002372 } else if (bSupportMode & WIRELESS_MODE_N_5G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002373 wireless_mode = WIRELESS_MODE_N_5G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002374 } else if ((bSupportMode & WIRELESS_MODE_A)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002375 wireless_mode = WIRELESS_MODE_A;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002376 } else if ((bSupportMode & WIRELESS_MODE_G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002377 wireless_mode = WIRELESS_MODE_G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002378 } else if ((bSupportMode & WIRELESS_MODE_B)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002379 wireless_mode = WIRELESS_MODE_B;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002380 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002381 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __func__, bSupportMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002382 wireless_mode = WIRELESS_MODE_B;
2383 }
2384 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002385#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we should wait for FPGA
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03002386 ActUpdateChannelAccessSetting(pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002387#endif
2388 priv->ieee80211->mode = wireless_mode;
2389
2390 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2391 priv->ieee80211->pHTInfo->bEnableHT = 1;
2392 else
2393 priv->ieee80211->pHTInfo->bEnableHT = 0;
2394 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2395 rtl8192_refresh_supportrate(priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002396
2397}
2398//init priv variables here. only non_zero value should be initialized here.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002399static void rtl8192_init_priv_variable(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002400{
2401 struct r8192_priv *priv = ieee80211_priv(dev);
2402 u8 i;
2403 priv->card_8192 = NIC_8192U;
2404 priv->chan = 1; //set to channel 1
2405 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2406 priv->ieee80211->iw_mode = IW_MODE_INFRA;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002407 priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002408 priv->retry_rts = DEFAULT_RETRY_RTS;
2409 priv->retry_data = DEFAULT_RETRY_DATA;
2410 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2411 priv->ieee80211->rate = 110; //11 mbps
2412 priv->ieee80211->short_slot = 1;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002413 priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002414 priv->CckPwEnl = 6;
2415 //for silent reset
2416 priv->IrpPendingCount = 1;
2417 priv->ResetProgress = RESET_TYPE_NORESET;
2418 priv->bForcedSilentReset = 0;
2419 priv->bDisableNormalResetCheck = false;
2420 priv->force_reset = false;
2421
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002422 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002423 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2424 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2425 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2426 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2427 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002428 IEEE_SOFTMAC_BEACONS;//added by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002429
2430 priv->ieee80211->active_scan = 1;
2431 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2432 priv->ieee80211->host_encrypt = 1;
2433 priv->ieee80211->host_decrypt = 1;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002434 priv->ieee80211->start_send_beacons = NULL; //-by amy 080604
2435 priv->ieee80211->stop_send_beacons = NULL; //-by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002436 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2437 priv->ieee80211->set_chan = rtl8192_set_chan;
2438 priv->ieee80211->link_change = rtl8192_link_change;
2439 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2440 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2441 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2442 priv->ieee80211->init_wmmparam_flag = 0;
2443 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2444 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2445 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
2446 priv->ieee80211->qos_support = 1;
2447
2448 //added by WB
Jerry Chuang8fc85982009-11-03 07:17:11 -02002449 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2450 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2451 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2452 //added by david
2453 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
2454 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
2455 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2456 //added by amy
2457 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
2458 priv->card_type = USB;
2459#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002460 if (Adapter->bInHctTest) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002461 pHalData->ShortRetryLimit = 7;
2462 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002463 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002464#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002465 priv->ShortRetryLimit = 0x30;
2466 priv->LongRetryLimit = 0x30;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002467 priv->EarlyRxThreshold = 7;
2468 priv->enable_gpio0 = 0;
2469 priv->TransmitConfig =
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002470 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002471 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
2472 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002473 (false ? TCR_SAT : 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
Jerry Chuang8fc85982009-11-03 07:17:11 -02002474#ifdef TO_DO_LIST
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002475 if (Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002476 pHalData->ReceiveConfig = pHalData->CSMethod |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002477 RCR_AMF | RCR_ADF | //accept management/data
Jerry Chuang8fc85982009-11-03 07:17:11 -02002478 //guangan200710
2479 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2480 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002481 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002482 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2483 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002484 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002485 else
2486
2487#endif
2488 priv->ReceiveConfig =
2489 RCR_AMF | RCR_ADF | //accept management/data
2490 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2491 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Jerry Chuang8fc85982009-11-03 07:17:11 -02002492 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2493 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002494 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002495
2496 priv->AcmControl = 0;
Devendra Nagab7553422012-08-26 11:06:33 +05302497 priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002498
2499 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002500 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002501 skb_queue_head_init(&priv->skb_queue);
2502
2503 /* Tx related queue */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002504 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002505 skb_queue_head_init(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002506 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002507 skb_queue_head_init(&priv->ieee80211->skb_aggQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002508 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002509 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002510 priv->rf_set_chan = rtl8192_phy_SwChnl;
2511}
2512
2513//init lock here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002514static void rtl8192_init_priv_lock(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002515{
2516 spin_lock_init(&priv->tx_lock);
2517 spin_lock_init(&priv->irq_lock);//added by thomas
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002518 sema_init(&priv->wx_sem, 1);
2519 sema_init(&priv->rf_sem, 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002520 mutex_init(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002521}
2522
Jerry Chuang8fc85982009-11-03 07:17:11 -02002523extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002524
2525void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
2526//init tasklet and wait_queue here. only 2.6 above kernel is considered
2527#define DRV_NAME "wlan0"
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002528static void rtl8192_init_priv_task(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002529{
2530 struct r8192_priv *priv = ieee80211_priv(dev);
2531
Jerry Chuang8fc85982009-11-03 07:17:11 -02002532 priv->priv_wq = create_workqueue(DRV_NAME);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002533
Jerry Chuang8fc85982009-11-03 07:17:11 -02002534 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2535
Jerry Chuang8fc85982009-11-03 07:17:11 -02002536 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2537 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002538 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2539 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2540 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002541 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002542
2543 tasklet_init(&priv->irq_rx_tasklet,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002544 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2545 (unsigned long)priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002546}
2547
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002548static void rtl8192_get_eeprom_size(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002549{
2550 u16 curCR = 0;
2551 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002552 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002553 curCR = read_nic_word_E(dev, EPROM_CMD);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002554 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
2555 //whether need I consider BIT5?
2556 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002557 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __func__, priv->epromtype);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002558}
2559
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002560//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002561static inline u16 endian_swap(u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002562{
2563 u16 tmp = *data;
2564 *data = (tmp >> 8) | (tmp << 8);
2565 return *data;
2566}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002567static void rtl8192_read_eeprom_info(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002568{
2569 u16 wEPROM_ID = 0;
2570 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
2571 u8 bLoad_From_EEPOM = false;
2572 struct r8192_priv *priv = ieee80211_priv(dev);
2573 u16 tmpValue = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002574 int i;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002575 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002576 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
2577 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
2578
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002579 if (wEPROM_ID != RTL8190_EEPROM_ID) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002580 RT_TRACE(COMP_ERR, "EEPROM ID is invalid(is 0x%x(should be 0x%x)\n", wEPROM_ID, RTL8190_EEPROM_ID);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002581 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002582 bLoad_From_EEPOM = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002583 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002584
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002585 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002586 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
2587 priv->eeprom_vid = endian_swap(&tmpValue);
2588 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
2589 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002590 priv->eeprom_ChannelPlan = ((tmpValue&0xff00)>>8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002591 priv->btxpowerdata_readfromEEPORM = true;
2592 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002593 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002594 priv->eeprom_vid = 0;
2595 priv->eeprom_pid = 0;
2596 priv->card_8192_version = VERSION_819xU_B;
2597 priv->eeprom_ChannelPlan = 0;
2598 priv->eeprom_CustomerID = 0;
2599 }
2600 RT_TRACE(COMP_EPROM, "vid:0x%4x, pid:0x%4x, CustomID:0x%2x, ChanPlan:0x%x\n", priv->eeprom_vid, priv->eeprom_pid, priv->eeprom_CustomerID, priv->eeprom_ChannelPlan);
2601 //set channelplan from eeprom
2602 priv->ChannelPlan = priv->eeprom_ChannelPlan;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002603 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002604 int i;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002605 for (i = 0; i < 6; i += 2) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002606 u16 tmp = 0;
2607 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002608 *(u16 *)(&dev->dev_addr[i]) = tmp;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002609 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002610 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002611 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2612 //should I set IDR0 here?
2613 }
Joe Perches0ee9f672009-12-06 11:34:52 -08002614 RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002615 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
2616 priv->rf_chip = RF_8256;
2617
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002618 if (priv->card_8192_version == (u8)VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002619 //read Tx power gain offset of legacy OFDM to HT rate
2620 if (bLoad_From_EEPOM)
2621 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
2622 else
2623 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
2624 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
2625 //read ThermalMeter from EEPROM
2626 if (bLoad_From_EEPOM)
2627 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
2628 else
2629 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2630 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
2631 //vivi, for tx power track
2632 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2633 //read antenna tx power offset of B/C/D to A from EEPROM
2634 if (bLoad_From_EEPOM)
2635 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
2636 else
2637 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
2638 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
2639 // Read CrystalCap from EEPROM
2640 if (bLoad_From_EEPOM)
2641 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
2642 else
2643 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
2644 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
2645 //get per-channel Tx power level
2646 if (bLoad_From_EEPOM)
2647 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
2648 else
2649 priv->EEPROM_Def_Ver = 1;
2650 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002651 if (priv->EEPROM_Def_Ver == 0) { //old eeprom definition
Jerry Chuang8fc85982009-11-03 07:17:11 -02002652 int i;
2653 if (bLoad_From_EEPOM)
2654 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
2655 else
2656 priv->EEPROMTxPowerLevelCCK = 0x10;
2657 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002658 for (i = 0; i < 3; i++) {
2659 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002660 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
2661 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
2662 tmpValue = tmpValue & 0x00ff;
2663 else
2664 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002665 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002666 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002667 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002668 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
2669 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
2670 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002671 } else if (priv->EEPROM_Def_Ver == 1) {
2672 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002673 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
2674 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002675 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002676 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002677 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002678 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
2679
2680 if (bLoad_From_EEPOM)
2681 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
2682 else
2683 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002684 *((u16 *)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002685 if (bLoad_From_EEPOM)
2686 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
2687 else
2688 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002689 *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002690 if (bLoad_From_EEPOM)
2691 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
2692 else
2693 tmpValue = 0x10;
2694 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
2695 }//endif EEPROM_Def_Ver == 1
2696
2697 //update HAL variables
2698 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002699 for (i = 0; i < 14; i++) {
2700 if (i <= 3)
2701 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
2702 else if (i >= 4 && i <= 9)
2703 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
2704 else
2705 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
2706 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002707
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002708 for (i = 0; i < 14; i++) {
2709 if (priv->EEPROM_Def_Ver == 0) {
2710 if (i <= 3)
2711 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2712 else if (i >= 4 && i <= 9)
2713 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
2714 else
2715 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2716 } else if (priv->EEPROM_Def_Ver == 1) {
2717 if (i <= 3)
2718 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
2719 else if (i >= 4 && i <= 9)
2720 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
2721 else
2722 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002723 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002724 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002725 priv->TxPowerDiff = priv->EEPROMPwDiff;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002726 // Antenna B gain offset to antenna A, bit0~3
Jerry Chuang8fc85982009-11-03 07:17:11 -02002727 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
2728 // Antenna C gain offset to antenna A, bit4~7
2729 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
2730 // CrystalCap, bit12~15
2731 priv->CrystalCap = priv->EEPROMCrystalCap;
2732 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
2733 // 92U does not enable TX power tracking.
2734 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
2735 }//end if VersionID == VERSION_819xU_A
2736
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002737 //added by vivi, for dlink led, 20080416
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002738 switch (priv->eeprom_CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002739 case EEPROM_CID_RUNTOP:
2740 priv->CustomerID = RT_CID_819x_RUNTOP;
2741 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002742
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002743 case EEPROM_CID_DLINK:
2744 priv->CustomerID = RT_CID_DLINK;
2745 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002746
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002747 default:
2748 priv->CustomerID = RT_CID_DEFAULT;
2749 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002750
2751 }
2752
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002753 switch (priv->CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002754 case RT_CID_819x_RUNTOP:
2755 priv->LedStrategy = SW_LED_MODE2;
2756 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002757
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002758 case RT_CID_DLINK:
2759 priv->LedStrategy = SW_LED_MODE4;
2760 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002761
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002762 default:
2763 priv->LedStrategy = SW_LED_MODE0;
2764 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002765
2766 }
2767
2768
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002769 if (priv->rf_type == RF_1T2R) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002770 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002771 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002772 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
2773 }
2774
2775 // 2008/01/16 MH We can only know RF type in the function. So we have to init
2776 // DIG RATR table again.
2777 init_rate_adaptive(dev);
2778 //we need init DIG RATR table here again.
2779
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002780 RT_TRACE(COMP_EPROM, "<===========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002781 return;
2782}
2783
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002784short rtl8192_get_channel_map(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002785{
2786 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002787 if (priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03002788 netdev_err(dev, "rtl8180_init: Error channel plan! Set to default.\n");
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002789 priv->ChannelPlan = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002790 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002791 RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002792
2793 rtl819x_set_channel_map(priv->ChannelPlan, priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002794 return 0;
2795}
2796
2797short rtl8192_init(struct net_device *dev)
2798{
2799
2800 struct r8192_priv *priv = ieee80211_priv(dev);
2801
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002802 memset(&(priv->stats), 0, sizeof(struct Stats));
2803 memset(priv->txqueue_to_outpipemap, 0, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002804#ifdef PIPE12
2805 {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002806 int i = 0;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002807 u8 queuetopipe[] = {3, 2, 1, 0, 4, 8, 7, 6, 5};
2808 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002809 }
2810#else
2811 {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002812 u8 queuetopipe[] = {3, 2, 1, 0, 4, 4, 0, 4, 4};
2813 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002814 }
2815#endif
2816 rtl8192_init_priv_variable(dev);
2817 rtl8192_init_priv_lock(priv);
2818 rtl8192_init_priv_task(dev);
2819 rtl8192_get_eeprom_size(dev);
2820 rtl8192_read_eeprom_info(dev);
2821 rtl8192_get_channel_map(dev);
2822 init_hal_dm(dev);
2823 init_timer(&priv->watch_dog_timer);
2824 priv->watch_dog_timer.data = (unsigned long)dev;
2825 priv->watch_dog_timer.function = watch_dog_timer_callback;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002826 if (rtl8192_usb_initendpoints(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002827 DMESG("Endopoints initialization failed");
2828 return -ENOMEM;
2829 }
2830
Jerry Chuang8fc85982009-11-03 07:17:11 -02002831#ifdef DEBUG_EPROM
2832 dump_eprom(dev);
2833#endif
2834 return 0;
2835}
2836
2837/******************************************************************************
2838 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
2839 * not to do all the hw config as its name says
2840 * input: net_device dev
2841 * output: none
2842 * return: none
2843 * notice: This part need to modified according to the rate set we filtered
2844 * ****************************************************************************/
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002845void rtl8192_hwconfig(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002846{
2847 u32 regRATR = 0, regRRSR = 0;
2848 u8 regBwOpMode = 0, regTmp = 0;
2849 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002850 u32 ratr_value = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002851
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002852 // Set RRSR, RATR, and BW_OPMODE registers
Jerry Chuang8fc85982009-11-03 07:17:11 -02002853 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002854 switch (priv->ieee80211->mode) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002855 case WIRELESS_MODE_B:
2856 regBwOpMode = BW_OPMODE_20MHZ;
2857 regRATR = RATE_ALL_CCK;
2858 regRRSR = RATE_ALL_CCK;
2859 break;
2860 case WIRELESS_MODE_A:
2861 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
2862 regRATR = RATE_ALL_OFDM_AG;
2863 regRRSR = RATE_ALL_OFDM_AG;
2864 break;
2865 case WIRELESS_MODE_G:
2866 regBwOpMode = BW_OPMODE_20MHZ;
2867 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2868 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2869 break;
2870 case WIRELESS_MODE_AUTO:
2871#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002872 if (Adapter->bInHctTest) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002873 regBwOpMode = BW_OPMODE_20MHZ;
2874 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2875 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002876 }
2877 else
2878#endif
2879 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002880 regBwOpMode = BW_OPMODE_20MHZ;
2881 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2882 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002883 }
2884 break;
2885 case WIRELESS_MODE_N_24G:
2886 // It support CCK rate by default.
2887 // CCK rate will be filtered out only when associated AP does not support it.
2888 regBwOpMode = BW_OPMODE_20MHZ;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002889 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2890 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002891 break;
2892 case WIRELESS_MODE_N_5G:
2893 regBwOpMode = BW_OPMODE_5G;
2894 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2895 regRRSR = RATE_ALL_OFDM_AG;
2896 break;
2897 }
2898
2899 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002900 ratr_value = regRATR;
2901 if (priv->rf_type == RF_1T2R)
2902 ratr_value &= ~(RATE_ALL_OFDM_2SS);
2903 write_nic_dword(dev, RATR0, ratr_value);
2904 write_nic_byte(dev, UFWP, 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002905 regTmp = read_nic_byte(dev, 0x313);
2906 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
2907 write_nic_dword(dev, RRSR, regRRSR);
2908
2909 //
2910 // Set Retry Limit here
2911 //
2912 write_nic_word(dev, RETRY_LIMIT,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002913 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
2914 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002915 // Set Contention Window here
2916
2917 // Set Tx AGC
2918
2919 // Set Tx Antenna including Feedback control
2920
2921 // Set Auto Rate fallback control
2922
2923
2924}
2925
2926
2927//InitializeAdapter and PhyCfg
2928bool rtl8192_adapter_start(struct net_device *dev)
2929{
2930 struct r8192_priv *priv = ieee80211_priv(dev);
2931 u32 dwRegRead = 0;
2932 bool init_status = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002933 u8 SECR_value = 0x0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002934 RT_TRACE(COMP_INIT, "====>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002935 priv->Rf_Mode = RF_OP_By_SW_3wire;
2936 //for ASIC power on sequence
2937 write_nic_byte_E(dev, 0x5f, 0x80);
2938 mdelay(50);
2939 write_nic_byte_E(dev, 0x5f, 0xf0);
2940 write_nic_byte_E(dev, 0x5d, 0x00);
2941 write_nic_byte_E(dev, 0x5e, 0x80);
2942 write_nic_byte(dev, 0x17, 0x37);
2943 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002944 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
2945 //config CPUReset Register
2946 //Firmware Reset or not?
2947 dwRegRead = read_nic_dword(dev, CPU_GEN);
2948 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
2949 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
2950 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
2951 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
2952 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002953 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __func__, priv->pFirmware->firmware_status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002954
2955 write_nic_dword(dev, CPU_GEN, dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002956 //config BB.
2957 rtl8192_BBConfig(dev);
2958
Jerry Chuang8fc85982009-11-03 07:17:11 -02002959 //Loopback mode or not
2960 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002961
2962 dwRegRead = read_nic_dword(dev, CPU_GEN);
2963 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
2964 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
2965 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
2966 dwRegRead |= CPU_CCK_LOOPBACK;
2967 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002968 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __func__, priv->LoopbackMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002969
2970 write_nic_dword(dev, CPU_GEN, dwRegRead);
2971
2972 //after reset cpu, we need wait for a seconds to write in register.
2973 udelay(500);
2974
2975 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
2976 write_nic_byte_E(dev, 0x5f, (read_nic_byte_E(dev, 0x5f)|0x20));
2977
2978 //Set Hardware
2979 rtl8192_hwconfig(dev);
2980
2981 //turn on Tx/Rx
2982 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
2983
2984 //set IDR0 here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002985 write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
2986 write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002987
2988 //set RCR
2989 write_nic_dword(dev, RCR, priv->ReceiveConfig);
2990
2991 //Initialize Number of Reserved Pages in Firmware Queue
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002992 write_nic_dword(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << RSVD_FW_QUEUE_PAGE_BK_SHIFT |
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002993 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT |
2994 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT |
2995 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002996 write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT |
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002997 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002998 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002999 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003000 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
3001
3002 //Set AckTimeout
3003 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
3004 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
3005
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003006 if (priv->ResetProgress == RESET_TYPE_NORESET)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003007 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003008 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003009 CamResetAllEntry(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003010 SECR_value |= SCR_TxEncEnable;
3011 SECR_value |= SCR_RxDecEnable;
3012 SECR_value |= SCR_NoSKMC;
3013 write_nic_byte(dev, SECR, SECR_value);
3014 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003015
3016 //Beacon related
3017 write_nic_word(dev, ATIMWND, 2);
3018 write_nic_word(dev, BCN_INTERVAL, 100);
3019
Jerry Chuang8fc85982009-11-03 07:17:11 -02003020#define DEFAULT_EDCA 0x005e4332
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003021 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003022 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003023 for (i = 0; i < QOS_QUEUE_NUM; i++)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003024 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003025 }
3026#ifdef USB_RX_AGGREGATION_SUPPORT
3027 //3 For usb rx firmware aggregation control
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003028 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003029 u32 ulValue;
3030 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
3031 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003032 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003033 /*
3034 * If usb rx firmware aggregation is enabled,
3035 * when anyone of three threshold conditions above is reached,
3036 * firmware will send aggregated packet to driver.
3037 */
3038 write_nic_dword(dev, 0x1a8, ulValue);
3039 priv->bCurrentRxAggrEnable = true;
3040 }
3041#endif
3042
3043 rtl8192_phy_configmac(dev);
3044
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003045 if (priv->card_8192_version == (u8) VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003046 rtl8192_phy_getTxPower(dev);
3047 rtl8192_phy_setTxPower(dev, priv->chan);
3048 }
3049
3050 //Firmware download
3051 init_status = init_firmware(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003052 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003053 RT_TRACE(COMP_ERR, "ERR!!! %s(): Firmware download is failed\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003054 return init_status;
3055 }
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003056 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003057 //
3058#ifdef TO_DO_LIST
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003059 if (Adapter->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003060 if (pMgntInfo->RegRfOff == TRUE) { // User disable RF via registry.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003061 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
3062 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003063 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003064 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003065 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003066 } else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { // H/W or S/W RF OFF before sleep.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003067 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
3068 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003069 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003070 pHalData->eRFPowerState = eRfOn;
3071 pMgntInfo->RfOffReason = 0;
3072 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
3073 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003074 } else {
3075 if (pHalData->eRFPowerState == eRfOff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003076 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003077 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003078 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003079 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3080 }
3081 }
3082#endif
3083 //config RF.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003084 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003085 rtl8192_phy_RFConfig(dev);
3086 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003087 }
3088
3089
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003090 if (priv->ieee80211->FwRWRF)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003091 // We can force firmware to do RF-R/W
3092 priv->Rf_Mode = RF_OP_By_FW;
3093 else
3094 priv->Rf_Mode = RF_OP_By_SW_3wire;
3095
3096
3097 rtl8192_phy_updateInitGain(dev);
3098 /*--set CCK and OFDM Block "ON"--*/
3099 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3100 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3101
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003102 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003103 //if D or C cut
3104 u8 tmpvalue = read_nic_byte(dev, 0x301);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003105 if (tmpvalue == 0x03) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003106 priv->bDcut = TRUE;
3107 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003108 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003109 priv->bDcut = FALSE;
3110 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
3111 }
3112 dm_initialize_txpower_tracking(dev);
3113
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003114 if (priv->bDcut == TRUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003115 u32 i, TempCCk;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003116 u32 tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003117 for (i = 0; i < TxBBGainTableLength; i++) {
3118 if (tmpRegA == priv->txbbgain_table[i].txbbgain_value) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003119 priv->rfa_txpowertrackingindex = (u8)i;
3120 priv->rfa_txpowertrackingindex_real = (u8)i;
3121 priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003122 break;
3123 }
3124 }
3125
3126 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3127
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003128 for (i = 0; i < CCKTxBBGainTableLength; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003129
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003130 if (TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0]) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003131 priv->cck_present_attentuation_20Mdefault = (u8) i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003132 break;
3133 }
3134 }
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003135 priv->cck_present_attentuation_40Mdefault = 0;
3136 priv->cck_present_attentuation_difference = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003137 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
3138
Jerry Chuang8fc85982009-11-03 07:17:11 -02003139 }
3140 }
3141 write_nic_byte(dev, 0x87, 0x0);
3142
3143
Jerry Chuang8fc85982009-11-03 07:17:11 -02003144 return init_status;
3145}
3146
3147/* this configures registers for beacon tx and enables it via
3148 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3149 * be used to stop beacon transmission
3150 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003151/***************************************************************************
3152 -------------------------------NET STUFF---------------------------
3153***************************************************************************/
3154
3155static struct net_device_stats *rtl8192_stats(struct net_device *dev)
3156{
3157 struct r8192_priv *priv = ieee80211_priv(dev);
3158
3159 return &priv->ieee80211->stats;
3160}
3161
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003162bool HalTxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003163{
3164 struct r8192_priv *priv = ieee80211_priv(dev);
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003165 u16 RegTxCounter = read_nic_word(dev, 0x128);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003166 bool bStuck = FALSE;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003167 RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", __func__, RegTxCounter, priv->TxCounter);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003168 if (priv->TxCounter == RegTxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003169 bStuck = TRUE;
3170
3171 priv->TxCounter = RegTxCounter;
3172
3173 return bStuck;
3174}
3175
3176/*
3177* <Assumption: RT_TX_SPINLOCK is acquired.>
3178* First added: 2006.11.19 by emily
3179*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003180RESET_TYPE TxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003181{
3182 struct r8192_priv *priv = ieee80211_priv(dev);
3183 u8 QueueID;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003184 bool bCheckFwTxCnt = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003185
3186 //
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003187 // Decide such threshold according to current power save mode
Jerry Chuang8fc85982009-11-03 07:17:11 -02003188 //
3189
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003190 for (QueueID = 0; QueueID <= BEACON_QUEUE; QueueID ++) {
3191 if (QueueID == TXCMD_QUEUE)
3192 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003193#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003194 if ((skb_queue_len(&priv->ieee80211->skb_waitQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_aggQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_drv_aggQ[QueueID]) == 0))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003195#else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003196 if ((skb_queue_len(&priv->ieee80211->skb_waitQ[QueueID]) == 0) && (skb_queue_len(&priv->ieee80211->skb_aggQ[QueueID]) == 0))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003197#endif
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003198 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003199
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003200 bCheckFwTxCnt = true;
3201 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003202 if (bCheckFwTxCnt) {
3203 if (HalTxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003204 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
3205 return RESET_TYPE_SILENT;
3206 }
3207 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003208 return RESET_TYPE_NORESET;
3209}
3210
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003211bool HalRxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003212{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003213 u16 RegRxCounter = read_nic_word(dev, 0x130);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003214 struct r8192_priv *priv = ieee80211_priv(dev);
3215 bool bStuck = FALSE;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003216 static u8 rx_chk_cnt;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003217 RT_TRACE(COMP_RESET, "%s(): RegRxCounter is %d,RxCounter is %d\n", __func__, RegRxCounter, priv->RxCounter);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003218 // If rssi is small, we should check rx for long time because of bad rx.
3219 // or maybe it will continuous silent reset every 2 seconds.
3220 rx_chk_cnt++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003221 if (priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003222 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003223 } else if (priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003224 ((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_40M) ||
3225 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_20M))) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003226 if (rx_chk_cnt < 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003227 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003228 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003229 rx_chk_cnt = 0;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003230 } else if (((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_40M) ||
3231 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_20M)) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003232 priv->undecorated_smoothed_pwdb >= VeryLowRSSI) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003233 if (rx_chk_cnt < 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003234 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003235 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003236 rx_chk_cnt = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003237 } else {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003238 if (rx_chk_cnt < 8)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003239 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003240 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003241 rx_chk_cnt = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003242 }
3243
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003244 if (priv->RxCounter == RegRxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003245 bStuck = TRUE;
3246
3247 priv->RxCounter = RegRxCounter;
3248
3249 return bStuck;
3250}
3251
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003252RESET_TYPE RxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003253{
3254 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003255 bool bRxCheck = FALSE;
3256
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003257 if (priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003258 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003259
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003260 if (bRxCheck) {
3261 if (HalRxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003262 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
3263 return RESET_TYPE_SILENT;
3264 }
3265 }
3266 return RESET_TYPE_NORESET;
3267}
3268
3269
3270/**
3271* This function is called by Checkforhang to check whether we should ask OS to reset driver
3272*
3273* \param pAdapter The adapter context for this miniport
3274*
3275* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
3276* to judge whether there is tx stuck.
3277* Note: This function may be required to be rewrite for Vista OS.
3278* <<<Assumption: Tx spinlock has been acquired >>>
3279*
3280* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
3281*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003282RESET_TYPE rtl819x_ifcheck_resetornot(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003283{
3284 struct r8192_priv *priv = ieee80211_priv(dev);
3285 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
3286 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003287 RT_RF_POWER_STATE rfState;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003288
3289 rfState = priv->ieee80211->eRFPowerState;
3290
3291 TxResetType = TxCheckStuck(dev);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003292 if (rfState != eRfOff ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003293 (priv->ieee80211->iw_mode != IW_MODE_ADHOC)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003294 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
3295 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
3296 // if driver is in firmware download failure status, driver should initialize RF in the following
3297 // silent reset procedure Emily, 2008.01.21
3298
3299 // Driver should not check RX stuck in IBSS mode because it is required to
3300 // set Check BSSID in order to send beacon, however, if check BSSID is
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003301 // set, STA cannot hear any packet at all. Emily, 2008.04.12
Jerry Chuang8fc85982009-11-03 07:17:11 -02003302 RxResetType = RxCheckStuck(dev);
3303 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003304 if (TxResetType == RESET_TYPE_NORMAL || RxResetType == RESET_TYPE_NORMAL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003305 return RESET_TYPE_NORMAL;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003306 } else if (TxResetType == RESET_TYPE_SILENT || RxResetType == RESET_TYPE_SILENT) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003307 RT_TRACE(COMP_RESET, "%s():silent reset\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003308 return RESET_TYPE_SILENT;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003309 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003310 return RESET_TYPE_NORESET;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003311 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003312
3313}
3314
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003315void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003316int _rtl8192_up(struct net_device *dev);
3317int rtl8192_close(struct net_device *dev);
3318
3319
3320
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003321void CamRestoreAllEntry(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003322{
3323 u8 EntryId = 0;
3324 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003325 u8 *MacAddr = priv->ieee80211->current_network.bssid;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003326
3327 static u8 CAM_CONST_ADDR[4][6] = {
3328 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3329 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
3330 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03003331 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003332 static u8 CAM_CONST_BROAD[] = {
3333 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003334
3335 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
3336
3337
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003338 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40) ||
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003339 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003340
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003341 for (EntryId = 0; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003342 MacAddr = CAM_CONST_ADDR[EntryId];
3343 setKey(dev, EntryId, EntryId,
3344 priv->ieee80211->pairwise_key_type,
3345 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003346 }
3347
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003348 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003349
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003350 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3351 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3352 (u8 *)dev->dev_addr, 0, NULL);
3353 else
3354 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3355 MacAddr, 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003356 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003357
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003358 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3359 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3360 (u8 *)dev->dev_addr, 0, NULL);
3361 else
3362 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3363 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003364 }
3365
3366
3367
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003368 if (priv->ieee80211->group_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003369 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003370 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003371 setKey(dev, EntryId, EntryId,
3372 priv->ieee80211->group_key_type,
3373 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003374 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003375 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003376 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3377 CAM_CONST_ADDR[0], 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003378 } else if (priv->ieee80211->group_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003379 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003380 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003381 setKey(dev, EntryId, EntryId,
3382 priv->ieee80211->group_key_type,
3383 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003384 }
3385
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003386 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003387 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3388 CAM_CONST_ADDR[0], 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003389 }
3390}
3391//////////////////////////////////////////////////////////////
3392// This function is used to fix Tx/Rx stop bug temporarily.
3393// This function will do "system reset" to NIC when Tx or Rx is stuck.
3394// The method checking Tx/Rx stuck of this function is supported by FW,
3395// which reports Tx and Rx counter to register 0x128 and 0x130.
3396//////////////////////////////////////////////////////////////
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003397void rtl819x_ifsilentreset(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003398{
Jerry Chuang8fc85982009-11-03 07:17:11 -02003399 struct r8192_priv *priv = ieee80211_priv(dev);
3400 u8 reset_times = 0;
3401 int reset_status = 0;
3402 struct ieee80211_device *ieee = priv->ieee80211;
3403
3404
3405 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
3406 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
3407
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003408 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003409RESET_START:
3410
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003411 RT_TRACE(COMP_RESET, "=========>Reset progress!! \n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003412
3413 // Set the variable for reset.
3414 priv->ResetProgress = RESET_TYPE_SILENT;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003415 down(&priv->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003416 if (priv->up == 0) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003417 RT_TRACE(COMP_ERR, "%s():the driver is not up! return\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003418 up(&priv->wx_sem);
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003419 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003420 }
3421 priv->up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003422 RT_TRACE(COMP_RESET, "%s():======>start to down the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003423
3424 rtl8192_rtx_disable(dev);
3425 rtl8192_cancel_deferred_work(priv);
3426 deinit_hal_dm(dev);
3427 del_timer_sync(&priv->watch_dog_timer);
3428
3429 ieee->sync_scan_hurryup = 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003430 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003431 down(&ieee->wx_sem);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003432 netdev_dbg(dev, "ieee->state is IEEE80211_LINKED\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003433 ieee80211_stop_send_beacons(priv->ieee80211);
3434 del_timer_sync(&ieee->associate_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003435 cancel_delayed_work(&ieee->associate_retry_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003436 ieee80211_stop_scan(ieee);
3437 netif_carrier_off(dev);
3438 up(&ieee->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003439 } else {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003440 netdev_dbg(dev, "ieee->state is NOT LINKED\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003441 ieee80211_softmac_stop_protocol(priv->ieee80211);
3442 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003443 up(&priv->wx_sem);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003444 RT_TRACE(COMP_RESET, "%s():<==========down process is finished\n", __func__);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003445 RT_TRACE(COMP_RESET, "%s():===========>start up the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003446 reset_status = _rtl8192_up(dev);
3447
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003448 RT_TRACE(COMP_RESET, "%s():<===========up process is finished\n", __func__);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003449 if (reset_status == -EAGAIN) {
3450 if (reset_times < 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003451 reset_times++;
3452 goto RESET_START;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003453 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003454 RT_TRACE(COMP_ERR, " ERR!!! %s(): Reset Failed!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003455 }
3456 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003457 ieee->is_silent_reset = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003458 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003459 if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003460 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3461
Jerry Chuang8fc85982009-11-03 07:17:11 -02003462 queue_work(ieee->wq, &ieee->associate_complete_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003463
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003464 } else if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003465 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3466 ieee->link_change(ieee->dev);
3467
Jerry Chuang8fc85982009-11-03 07:17:11 -02003468 ieee80211_start_send_beacons(ieee);
3469
3470 if (ieee->data_hard_resume)
3471 ieee->data_hard_resume(ieee->dev);
3472 netif_carrier_on(ieee->dev);
3473 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003474
3475 CamRestoreAllEntry(dev);
3476
3477 priv->ResetProgress = RESET_TYPE_NORESET;
3478 priv->reset_count++;
3479
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003480 priv->bForcedSilentReset = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003481 priv->bResetInProgress = false;
3482
3483 // For test --> force write UFWP.
3484 write_nic_byte(dev, UFWP, 1);
3485 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003486 }
3487}
3488
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003489void CAM_read_entry(struct net_device *dev, u32 iIndex)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003490{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003491 u32 target_command = 0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003492 u32 target_content = 0;
3493 u8 entry_i = 0;
3494 u32 ulStatus;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003495 s32 i = 100;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003496 for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003497 // polling bit, and No Write enable, and address
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003498 target_command = entry_i+CAM_CONTENT_COUNT*iIndex;
3499 target_command = target_command | BIT31;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003500
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003501 //Check polling bit is clear
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003502 while ((i--) >= 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003503 ulStatus = read_nic_dword(dev, RWCAM);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003504 if (ulStatus & BIT31)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003505 continue;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003506 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003507 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003508 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003509 write_nic_dword(dev, RWCAM, target_command);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003510 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x \n", target_command);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003511 target_content = read_nic_dword(dev, RCAMO);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003512 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n", target_content);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003513 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003514 printk("\n");
3515}
3516
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003517void rtl819x_update_rxcounts(struct r8192_priv *priv, u32 *TotalRxBcnNum,
3518 u32 *TotalRxDataNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003519{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003520 u16 SlotIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003521 u8 i;
3522
3523 *TotalRxBcnNum = 0;
3524 *TotalRxDataNum = 0;
3525
3526 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
3527 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
3528 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003529 for (i = 0; i < priv->ieee80211->LinkDetectInfo.SlotNum; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003530 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
3531 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
3532 }
3533}
3534
3535
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003536extern void rtl819x_watchdog_wqcallback(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003537{
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003538 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003539 struct r8192_priv *priv = container_of(dwork, struct r8192_priv, watch_dog_wq);
3540 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003541 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003542 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003543 static u8 check_reset_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003544 bool bBusyTraffic = false;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003545 u32 TotalRxBcnNum = 0;
3546 u32 TotalRxDataNum = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003547
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003548 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003549 return;
3550 hal_dm_watchdog(dev);
3551
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003552 //to get busy traffic condition
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003553 if (ieee->state == IEEE80211_LINKED) {
3554 if (ieee->LinkDetectInfo.NumRxOkInPeriod > 666 ||
3555 ieee->LinkDetectInfo.NumTxOkInPeriod > 666 ) {
3556 bBusyTraffic = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003557 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003558 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
3559 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
3560 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
3561 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003562 //added by amy for AP roaming
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003563 if (priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003564
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003565 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
3566 if ((TotalRxBcnNum+TotalRxDataNum) == 0) {
3567#ifdef TODO
3568 if (rfState == eRfOff)
3569 RT_TRACE(COMP_ERR, "========>%s()\n", __func__);
3570#endif
3571 netdev_dbg(dev, "===>%s(): AP is power off, connect another one\n", __func__);
3572 priv->ieee80211->state = IEEE80211_ASSOCIATING;
3573 notify_wx_assoc_event(priv->ieee80211);
3574 RemovePeerTS(priv->ieee80211, priv->ieee80211->current_network.bssid);
3575 priv->ieee80211->link_change(dev);
3576 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003577
Jerry Chuang8fc85982009-11-03 07:17:11 -02003578 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003579 }
3580 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod = 0;
3581 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003582 //check if reset the driver
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003583 if (check_reset_cnt++ >= 3) {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003584 ResetType = rtl819x_ifcheck_resetornot(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003585 check_reset_cnt = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003586 }
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003587 if ((priv->force_reset) || (priv->ResetProgress == RESET_TYPE_NORESET &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003588 (priv->bForcedSilentReset ||
3589 (!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_SILENT)))) { // This is control by OID set in Pomelo
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003590 RT_TRACE(COMP_RESET, "%s():priv->force_reset is %d,priv->ResetProgress is %d, priv->bForcedSilentReset is %d,priv->bDisableNormalResetCheck is %d,ResetType is %d\n", __func__, priv->force_reset, priv->ResetProgress, priv->bForcedSilentReset, priv->bDisableNormalResetCheck, ResetType);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003591 rtl819x_ifsilentreset(dev);
3592 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003593 priv->force_reset = false;
3594 priv->bForcedSilentReset = false;
3595 priv->bResetInProgress = false;
3596 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
3597
3598}
3599
3600void watch_dog_timer_callback(unsigned long data)
3601{
3602 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003603 queue_delayed_work(priv->priv_wq, &priv->watch_dog_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003604 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
Jerry Chuang8fc85982009-11-03 07:17:11 -02003605}
3606int _rtl8192_up(struct net_device *dev)
3607{
3608 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003609 int init_status = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003610 priv->up = 1;
3611 priv->ieee80211->ieee_up = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003612 RT_TRACE(COMP_INIT, "Bringing up iface");
3613 init_status = rtl8192_adapter_start(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003614 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003615 RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization failed!\n", __func__);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003616 priv->up = priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003617 return -EAGAIN;
3618 }
3619 RT_TRACE(COMP_INIT, "start adapter finished\n");
3620 rtl8192_rx_enable(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003621 if (priv->ieee80211->state != IEEE80211_LINKED)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003622 ieee80211_softmac_start_protocol(priv->ieee80211);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003623 ieee80211_reset_queue(priv->ieee80211);
3624 watch_dog_timer_callback((unsigned long) dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003625 if (!netif_queue_stopped(dev))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003626 netif_start_queue(dev);
3627 else
3628 netif_wake_queue(dev);
3629
3630 return 0;
3631}
3632
3633
3634int rtl8192_open(struct net_device *dev)
3635{
3636 struct r8192_priv *priv = ieee80211_priv(dev);
3637 int ret;
3638 down(&priv->wx_sem);
3639 ret = rtl8192_up(dev);
3640 up(&priv->wx_sem);
3641 return ret;
3642
3643}
3644
3645
3646int rtl8192_up(struct net_device *dev)
3647{
3648 struct r8192_priv *priv = ieee80211_priv(dev);
3649
3650 if (priv->up == 1) return -1;
3651
3652 return _rtl8192_up(dev);
3653}
3654
3655
3656int rtl8192_close(struct net_device *dev)
3657{
3658 struct r8192_priv *priv = ieee80211_priv(dev);
3659 int ret;
3660
3661 down(&priv->wx_sem);
3662
3663 ret = rtl8192_down(dev);
3664
3665 up(&priv->wx_sem);
3666
3667 return ret;
3668
3669}
3670
3671int rtl8192_down(struct net_device *dev)
3672{
3673 struct r8192_priv *priv = ieee80211_priv(dev);
3674 int i;
3675
3676 if (priv->up == 0) return -1;
3677
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003678 priv->up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003679 priv->ieee80211->ieee_up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003680 RT_TRACE(COMP_DOWN, "==========>%s()\n", __func__);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003681 /* FIXME */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003682 if (!netif_queue_stopped(dev))
3683 netif_stop_queue(dev);
3684
3685 rtl8192_rtx_disable(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003686
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003687 /* Tx related queue release */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003688 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003689 skb_queue_purge(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003690 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003691 skb_queue_purge(&priv->ieee80211->skb_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003692
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003693 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003694 skb_queue_purge(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003695
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003696 //as cancel_delayed_work will del work->timer, so if work is not defined as struct delayed_work, it will corrupt
Jerry Chuang8fc85982009-11-03 07:17:11 -02003697 rtl8192_cancel_deferred_work(priv);
3698 deinit_hal_dm(dev);
3699 del_timer_sync(&priv->watch_dog_timer);
3700
3701
3702 ieee80211_softmac_stop_protocol(priv->ieee80211);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003703 memset(&priv->ieee80211->current_network, 0, offsetof(struct ieee80211_network, list));
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003704 RT_TRACE(COMP_DOWN, "<==========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003705
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003706 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003707}
3708
3709
3710void rtl8192_commit(struct net_device *dev)
3711{
3712 struct r8192_priv *priv = ieee80211_priv(dev);
3713 int reset_status = 0;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003714 if (priv->up == 0) return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003715 priv->up = 0;
3716
3717 rtl8192_cancel_deferred_work(priv);
3718 del_timer_sync(&priv->watch_dog_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003719
3720 ieee80211_softmac_stop_protocol(priv->ieee80211);
3721
Jerry Chuang8fc85982009-11-03 07:17:11 -02003722 rtl8192_rtx_disable(dev);
3723 reset_status = _rtl8192_up(dev);
3724
3725}
3726
Jerry Chuang8fc85982009-11-03 07:17:11 -02003727void rtl8192_restart(struct work_struct *work)
3728{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003729 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
3730 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003731
3732 down(&priv->wx_sem);
3733
3734 rtl8192_commit(dev);
3735
3736 up(&priv->wx_sem);
3737}
3738
3739static void r8192_set_multicast(struct net_device *dev)
3740{
3741 struct r8192_priv *priv = ieee80211_priv(dev);
3742 short promisc;
3743
Jerry Chuang8fc85982009-11-03 07:17:11 -02003744 /* FIXME FIXME */
3745
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003746 promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003747
3748 if (promisc != priv->promisc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003749
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003750 priv->promisc = promisc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003751}
3752
3753
3754int r8192_set_mac_adr(struct net_device *dev, void *mac)
3755{
3756 struct r8192_priv *priv = ieee80211_priv(dev);
3757 struct sockaddr *addr = mac;
3758
3759 down(&priv->wx_sem);
3760
3761 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
3762
Jerry Chuang8fc85982009-11-03 07:17:11 -02003763 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003764 up(&priv->wx_sem);
3765
3766 return 0;
3767}
3768
3769/* based on ipw2200 driver */
3770int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3771{
3772 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3773 struct iwreq *wrq = (struct iwreq *)rq;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003774 int ret = -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003775 struct ieee80211_device *ieee = priv->ieee80211;
3776 u32 key[4];
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003777 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003778 struct iw_point *p = &wrq->u.data;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03003779 struct ieee_param *ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003780
3781 down(&priv->wx_sem);
3782
3783
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003784 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
3785 ret = -EINVAL;
3786 goto out;
3787 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003788
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003789 ipw = kmalloc(p->length, GFP_KERNEL);
3790 if (ipw == NULL) {
3791 ret = -ENOMEM;
3792 goto out;
3793 }
3794 if (copy_from_user(ipw, p->pointer, p->length)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003795 kfree(ipw);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003796 ret = -EFAULT;
3797 goto out;
3798 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003799
3800 switch (cmd) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003801 case RTL_IOCTL_WPA_SUPPLICANT:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003802 //parse here for HW security
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003803 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) {
3804 if (ipw->u.crypt.set_tx) {
3805 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003806 ieee->pairwise_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003807 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003808 ieee->pairwise_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003809 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003810 if (ipw->u.crypt.key_len == 13)
3811 ieee->pairwise_key_type = KEY_TYPE_WEP104;
3812 else if (ipw->u.crypt.key_len == 5)
3813 ieee->pairwise_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003814 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003815 ieee->pairwise_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003816 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003817
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003818 if (ieee->pairwise_key_type) {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003819 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003820 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003821 //we fill both index entry and 4th entry for pairwise key as in IPW interface, adhoc will only get here, so we need index entry for its default key serching!
3822 //added by WB.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003823 setKey(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8 *)ieee->ap_mac_addr, 0, key);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003824 if (ieee->auth_mode != 2)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003825 setKey(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8 *)ieee->ap_mac_addr, 0, key);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003826 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003827 } else {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003828 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003829 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003830 ieee->group_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003831 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003832 ieee->group_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003833 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003834 if (ipw->u.crypt.key_len == 13)
3835 ieee->group_key_type = KEY_TYPE_WEP104;
3836 else if (ipw->u.crypt.key_len == 5)
3837 ieee->group_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003838 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003839 ieee->group_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003840 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003841
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003842 if (ieee->group_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003843 setKey(dev, ipw->u.crypt.idx,
3844 ipw->u.crypt.idx, //KeyIndex
3845 ieee->group_key_type, //KeyType
3846 broadcast_addr, //MacAddr
3847 0, //DefaultKey
3848 key); //KeyContent
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003849 }
3850 }
3851 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003852#ifdef JOHN_HWSEC_DEBUG
3853 //john's test 0711
3854 printk("@@ wrq->u pointer = ");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003855 for (i = 0; i < wrq->u.data.length; i++) {
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003856 if (i%10 == 0) printk("\n");
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003857 printk("%8x|", ((u32 *)wrq->u.data.pointer)[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003858 }
3859 printk("\n");
3860#endif /*JOHN_HWSEC_DEBUG*/
3861 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
3862 break;
3863
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003864 default:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003865 ret = -EOPNOTSUPP;
3866 break;
3867 }
3868 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003869 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003870out:
3871 up(&priv->wx_sem);
3872 return ret;
3873}
3874
3875u8 HwRateToMRate90(bool bIsHT, u8 rate)
3876{
3877 u8 ret_rate = 0xff;
3878
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003879 if (!bIsHT) {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003880 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003881 case DESC90_RATE1M: ret_rate = MGN_1M; break;
3882 case DESC90_RATE2M: ret_rate = MGN_2M; break;
3883 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
3884 case DESC90_RATE11M: ret_rate = MGN_11M; break;
3885 case DESC90_RATE6M: ret_rate = MGN_6M; break;
3886 case DESC90_RATE9M: ret_rate = MGN_9M; break;
3887 case DESC90_RATE12M: ret_rate = MGN_12M; break;
3888 case DESC90_RATE18M: ret_rate = MGN_18M; break;
3889 case DESC90_RATE24M: ret_rate = MGN_24M; break;
3890 case DESC90_RATE36M: ret_rate = MGN_36M; break;
3891 case DESC90_RATE48M: ret_rate = MGN_48M; break;
3892 case DESC90_RATE54M: ret_rate = MGN_54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003893
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003894 default:
3895 ret_rate = 0xff;
3896 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
3897 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003898 }
3899
3900 } else {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003901 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003902 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
3903 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
3904 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
3905 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
3906 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
3907 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
3908 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
3909 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
3910 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
3911 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
3912 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
3913 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
3914 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
3915 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
3916 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
3917 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
3918 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003919
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003920 default:
3921 ret_rate = 0xff;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003922 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003923 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003924 }
3925 }
3926
3927 return ret_rate;
3928}
3929
3930/**
3931 * Function: UpdateRxPktTimeStamp
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003932 * Overview: Record the TSF time stamp when receiving a packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02003933 *
3934 * Input:
3935 * PADAPTER Adapter
3936 * PRT_RFD pRfd,
3937 *
3938 * Output:
3939 * PRT_RFD pRfd
3940 * (pRfd->Status.TimeStampHigh is updated)
3941 * (pRfd->Status.TimeStampLow is updated)
3942 * Return:
3943 * None
3944 */
Xenia Ragiadakoue6367212013-05-23 05:14:46 +03003945void UpdateRxPktTimeStamp8190(struct net_device *dev, struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003946{
3947 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3948
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003949 if (stats->bIsAMPDU && !stats->bFirstMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003950 stats->mac_time[0] = priv->LastRxDescTSFLow;
3951 stats->mac_time[1] = priv->LastRxDescTSFHigh;
3952 } else {
3953 priv->LastRxDescTSFLow = stats->mac_time[0];
3954 priv->LastRxDescTSFHigh = stats->mac_time[1];
3955 }
3956}
3957
3958//by amy 080606
3959
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003960long rtl819x_translate_todbm(u8 signal_strength_index)// 0-100 index.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003961{
3962 long signal_power; // in dBm.
3963
3964 // Translate to dBm (x=0.5y-95).
3965 signal_power = (long)((signal_strength_index + 1) >> 1);
3966 signal_power -= 95;
3967
3968 return signal_power;
3969}
3970
3971
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003972/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
Jerry Chuang8fc85982009-11-03 07:17:11 -02003973 be a local static. Otherwise, it may increase when we return from S3/S4. The
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003974 value will be kept in memory or disk. Declare the value in the adaptor
3975 and it will be reinitialized when returned from S3/S4. */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003976void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer, struct ieee80211_rx_stats *pprevious_stats, struct ieee80211_rx_stats *pcurrent_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003977{
3978 bool bcheck = false;
3979 u8 rfpath;
3980 u32 nspatial_stream, tmp_val;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003981 static u32 slide_rssi_index, slide_rssi_statistics;
3982 static u32 slide_evm_index, slide_evm_statistics;
3983 static u32 last_rssi, last_evm;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003984
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003985 static u32 slide_beacon_adc_pwdb_index, slide_beacon_adc_pwdb_statistics;
3986 static u32 last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003987
3988 struct ieee80211_hdr_3addr *hdr;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003989 u16 sc;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003990 unsigned int frag, seq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003991 hdr = (struct ieee80211_hdr_3addr *)buffer;
3992 sc = le16_to_cpu(hdr->seq_ctl);
3993 frag = WLAN_GET_SEQ_FRAG(sc);
3994 seq = WLAN_GET_SEQ_SEQ(sc);
3995 //cosa add 04292008 to record the sequence number
3996 pcurrent_stats->Seq_Num = seq;
3997 //
3998 // Check whether we should take the previous packet into accounting
3999 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004000 if (!pprevious_stats->bIsAMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004001 // if previous packet is not aggregated packet
4002 bcheck = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004003 }
4004
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004005 if (slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004006 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
4007 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
4008 priv->stats.slide_rssi_total -= last_rssi;
4009 }
4010 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
4011
4012 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004013 if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004014 slide_rssi_index = 0;
4015
4016 // <1> Showed on UI for user, in dbm
4017 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
4018 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
4019 pcurrent_stats->rssi = priv->stats.signal_strength;
4020 //
4021 // If the previous packet does not match the criteria, neglect it
4022 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004023 if (!pprevious_stats->bPacketMatchBSSID) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004024 if (!pprevious_stats->bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004025 return;
4026 }
4027
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004028 if (!bcheck)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004029 return;
4030
4031
4032 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
4033
4034 //
4035 // Check RSSI
4036 //
4037 priv->stats.num_process_phyinfo++;
4038
4039 /* record the general signal strength to the sliding window. */
4040
4041
4042 // <2> Showed on UI for engineering
4043 // hardware does not provide rssi information for each rf path in CCK
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004044 if (!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA)) {
4045 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004046 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
4047 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004048
4049 //Fixed by Jacken 2008-03-20
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004050 if (priv->stats.rx_rssi_percentage[rfpath] == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004051 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004052 if (pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath]) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004053 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004054 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004055 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004056 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004057 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004058 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004059 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004060 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004061 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004062 RT_TRACE(COMP_DBG, "priv->stats.rx_rssi_percentage[rfPath] = %d \n", priv->stats.rx_rssi_percentage[rfpath]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004063 }
4064 }
4065
4066
4067 //
4068 // Check PWDB.
4069 //
4070 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004071 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004072 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004073
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004074 if (pprevious_stats->bPacketBeacon) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004075 /* record the beacon pwdb to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004076 if (slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004077 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
4078 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
4079 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004080 }
4081 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
4082 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004083 slide_beacon_adc_pwdb_index++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004084 if (slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004085 slide_beacon_adc_pwdb_index = 0;
4086 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004087 if (pprevious_stats->RxPWDBAll >= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004088 pprevious_stats->RxPWDBAll -= 3;
4089 }
4090
4091 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004092 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004093 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004094
4095
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004096 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004097 if (priv->undecorated_smoothed_pwdb < 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004098 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004099 if (pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004100 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004101 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4102 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004103 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004104 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004105 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004106 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4107 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004108 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004109
4110 }
4111
4112 //
4113 // Check EVM
4114 //
4115 /* record the general EVM to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004116 if (pprevious_stats->SignalQuality) {
4117 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4118 if (slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004119 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
4120 last_evm = priv->stats.slide_evm[slide_evm_index];
4121 priv->stats.slide_evm_total -= last_evm;
4122 }
4123
4124 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
4125
4126 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004127 if (slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004128 slide_evm_index = 0;
4129
4130 // <1> Showed on UI for user, in percentage.
4131 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
4132 priv->stats.signal_quality = tmp_val;
4133 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
4134 priv->stats.last_signal_strength_inpercent = tmp_val;
4135 }
4136
4137 // <2> Showed on UI for engineering
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004138 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4139 for (nspatial_stream = 0; nspatial_stream < 2; nspatial_stream++) { // 2 spatial stream
4140 if (pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004141 if (priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004142 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
Jerry Chuang8fc85982009-11-03 07:17:11 -02004143 priv->stats.rx_evm_percentage[nspatial_stream] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004144 ((priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004145 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004146 }
4147 }
4148 }
4149 }
4150
4151
4152}
4153
4154/*-----------------------------------------------------------------------------
4155 * Function: rtl819x_query_rxpwrpercentage()
4156 *
4157 * Overview:
4158 *
4159 * Input: char antpower
4160 *
4161 * Output: NONE
4162 *
4163 * Return: 0-100 percentage
4164 *
4165 * Revised History:
4166 * When Who Remark
4167 * 05/26/2008 amy Create Version 0 porting from windows code.
4168 *
4169 *---------------------------------------------------------------------------*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004170static u8 rtl819x_query_rxpwrpercentage(char antpower)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004171{
4172 if ((antpower <= -100) || (antpower >= 20))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004173 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004174 else if (antpower >= 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004175 return 100;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004176 else
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004177 return 100 + antpower;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004178
4179} /* QueryRxPwrPercentage */
4180
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004181static u8 rtl819x_evm_dbtopercentage(char value)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004182{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004183 char ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004184
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004185 ret_val = value;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004186
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004187 if (ret_val >= 0)
4188 ret_val = 0;
4189 if (ret_val <= -33)
4190 ret_val = -33;
4191 ret_val = 0 - ret_val;
4192 ret_val *= 3;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004193 if (ret_val == 99)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004194 ret_val = 100;
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004195 return ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004196}
4197//
4198// Description:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004199// We want good-looking for signal strength/quality
Jerry Chuang8fc85982009-11-03 07:17:11 -02004200// 2007/7/19 01:09, by cosa.
4201//
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004202long rtl819x_signal_scale_mapping(long currsig)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004203{
4204 long retsig;
4205
4206 // Step 1. Scale mapping.
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004207 if (currsig >= 61 && currsig <= 100)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004208 retsig = 90 + ((currsig - 60) / 4);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004209 else if (currsig >= 41 && currsig <= 60)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004210 retsig = 78 + ((currsig - 40) / 2);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004211 else if (currsig >= 31 && currsig <= 40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004212 retsig = 66 + (currsig - 30);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004213 else if (currsig >= 21 && currsig <= 30)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004214 retsig = 54 + (currsig - 20);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004215 else if (currsig >= 5 && currsig <= 20)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004216 retsig = 42 + (((currsig - 5) * 2) / 3);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004217 else if (currsig == 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004218 retsig = 36;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004219 else if (currsig == 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004220 retsig = 27;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004221 else if (currsig == 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004222 retsig = 18;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004223 else if (currsig == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004224 retsig = 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004225 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004226 retsig = currsig;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004227
4228 return retsig;
4229}
4230
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004231static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
4232 struct ieee80211_rx_stats *pstats,
4233 rx_drvinfo_819x_usb *pdrvinfo,
4234 struct ieee80211_rx_stats *precord_stats,
4235 bool bpacket_match_bssid,
4236 bool bpacket_toself,
4237 bool bPacketBeacon,
4238 bool bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004239{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004240 phy_sts_ofdm_819xusb_t *pofdm_buf;
4241 phy_sts_cck_819xusb_t *pcck_buf;
4242 phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004243 u8 *prxpkt;
4244 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004245 char rx_pwr[4], rx_pwr_all = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004246 char rx_snrX, rx_evmX;
4247 u8 evm, pwdb_all;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004248 u32 RSSI, total_rssi = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004249 u8 is_cck_rate = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004250 u8 rf_rx_num = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004251 u8 sq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004252
4253
4254 priv->stats.numqry_phystatus++;
4255
4256 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4257
4258 // Record it for next packet processing
4259 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4260 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4261 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004262 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004263 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4264 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4265
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004266 prxpkt = (u8 *)pdrvinfo;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004267
4268 /* Move pointer to the 16th bytes. Phy status start address. */
4269 prxpkt += sizeof(rx_drvinfo_819x_usb);
4270
4271 /* Initial the cck and ofdm buffer pointer */
4272 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
4273 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
4274
4275 pstats->RxMIMOSignalQuality[0] = -1;
4276 pstats->RxMIMOSignalQuality[1] = -1;
4277 precord_stats->RxMIMOSignalQuality[0] = -1;
4278 precord_stats->RxMIMOSignalQuality[1] = -1;
4279
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004280 if (is_cck_rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004281 //
4282 // (1)Hardware does not provide RSSI for CCK
4283 //
4284
4285 //
4286 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4287 //
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004288 u8 report;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004289
4290 priv->stats.numqry_phystatusCCK++;
4291
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004292 if (!priv->bCckHighPower) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004293 report = pcck_buf->cck_agc_rpt & 0xc0;
4294 report = report>>6;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004295 switch (report) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004296 //Fixed by Jacken from Bryant 2008-03-20
4297 //Original value is -38 , -26 , -14 , -2
4298 //Fixed value is -35 , -23 , -11 , 6
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004299 case 0x3:
4300 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4301 break;
4302 case 0x2:
4303 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4304 break;
4305 case 0x1:
4306 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4307 break;
4308 case 0x0:
4309 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
4310 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004311 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004312 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004313 report = pcck_buf->cck_agc_rpt & 0x60;
4314 report = report>>5;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004315 switch (report) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004316 case 0x3:
4317 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4318 break;
4319 case 0x2:
4320 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4321 break;
4322 case 0x1:
4323 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4324 break;
4325 case 0x0:
4326 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4327 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004328 }
4329 }
4330
4331 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4332 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4333 pstats->RecvSignalPower = pwdb_all;
4334
4335 //
4336 // (3) Get Signal Quality (EVM)
4337 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02004338
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004339 if (pstats->RxPWDBAll > 40) {
4340 sq = 100;
4341 } else {
4342 sq = pcck_buf->sq_rpt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004343
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004344 if (pcck_buf->sq_rpt > 64)
4345 sq = 0;
4346 else if (pcck_buf->sq_rpt < 20)
4347 sq = 100;
4348 else
4349 sq = ((64-sq) * 100) / 44;
4350 }
4351 pstats->SignalQuality = precord_stats->SignalQuality = sq;
4352 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
4353 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004354
4355 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004356 priv->stats.numqry_phystatusHT++;
4357 //
4358 // (1)Get RSSI for HT rate
4359 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004360 for (i = RF90_PATH_A; i < priv->NumTotalRFPath; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004361 // 2008/01/30 MH we will judge RF RX path now.
4362 if (priv->brfpath_rxenable[i])
4363 rf_rx_num++;
4364 else
4365 continue;
4366
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004367 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004368 continue;
4369
4370 //Fixed by Jacken from Bryant 2008-03-20
4371 //Original value is 106
4372 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
4373
4374 //Get Rx snr value in DB
4375 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
4376 rx_snrX = (char)(tmp_rxsnr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004377 rx_snrX /= 2;
4378 priv->stats.rxSNRdB[i] = (long)rx_snrX;
4379
4380 /* Translate DBM to percentage. */
4381 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
4382 total_rssi += RSSI;
4383
4384 /* Record Signal Strength for next packet */
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004385 pstats->RxMIMOSignalStrength[i] = (u8) RSSI;
4386 precord_stats->RxMIMOSignalStrength[i] = (u8) RSSI;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004387 }
4388
4389
4390 //
4391 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4392 //
4393 //Fixed by Jacken from Bryant 2008-03-20
4394 //Original value is 106
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004395 rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1)& 0x7f) -106;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004396 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4397
4398 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4399 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
4400
4401 //
4402 // (3)EVM of HT rate
4403 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004404 if (pdrvinfo->RxHT && pdrvinfo->RxRate >= DESC90_RATEMCS8 &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004405 pdrvinfo->RxRate <= DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004406 max_spatial_stream = 2; //both spatial stream make sense
4407 else
4408 max_spatial_stream = 1; //only spatial stream 1 makes sense
4409
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004410 for (i = 0; i < max_spatial_stream; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004411 tmp_rxevm = pofdm_buf->rxevm_X[i];
4412 rx_evmX = (char)(tmp_rxevm);
4413
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004414 // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004415 // will set the most significant bit to "zero" when doing shifting operation which may change a negative
Jerry Chuang8fc85982009-11-03 07:17:11 -02004416 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
4417 rx_evmX /= 2; //dbm
4418
4419 evm = rtl819x_evm_dbtopercentage(rx_evmX);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004420 if (i == 0) // Fill value in RFD, Get the first spatial stream only
4421 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
4422 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004423 }
4424
4425
4426 /* record rx statistics for debug */
4427 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
4428 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004429 if (pdrvinfo->BW) //40M channel
Jerry Chuang8fc85982009-11-03 07:17:11 -02004430 priv->stats.received_bwtype[1+prxsc->rxsc]++;
4431 else //20M channel
4432 priv->stats.received_bwtype[0]++;
4433 }
4434
4435 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
4436 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004437 if (is_cck_rate) {
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004438 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004439 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004440 // We can judge RX path number now.
4441 if (rf_rx_num != 0)
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004442 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi /= rf_rx_num)));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004443 }
4444} /* QueryRxPhyStatus8190Pci */
4445
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004446void rtl8192_record_rxdesc_forlateruse(struct ieee80211_rx_stats *psrc_stats,
4447 struct ieee80211_rx_stats *ptarget_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004448{
4449 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
4450 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
4451 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
4452}
4453
4454
4455void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004456 struct ieee80211_rx_stats *pstats,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004457 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004458{
4459 // TODO: We must only check packet for current MAC address. Not finish
4460 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004461 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004462 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4463 bool bpacket_match_bssid, bpacket_toself;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004464 bool bPacketBeacon = FALSE, bToSelfBA = FALSE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004465 static struct ieee80211_rx_stats previous_stats;
4466 struct ieee80211_hdr_3addr *hdr;//by amy
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004467 u16 fc, type;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004468
4469 // Get Signal Quality for only RX data queue (but not command queue)
4470
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004471 u8 *tmp_buf;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004472 u8 *praddr;
4473
4474 /* Get MAC frame start address. */
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004475 tmp_buf = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004476
4477 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
4478 fc = le16_to_cpu(hdr->frame_ctl);
4479 type = WLAN_FC_GET_TYPE(fc);
4480 praddr = hdr->addr1;
4481
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004482 /* Check if the received packet is acceptable. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004483 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004484 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
4485 && (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004486 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
4487
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004488 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON)
4489 bPacketBeacon = true;
4490 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK) {
4491 if ((eqMacAddr(praddr, dev->dev_addr)))
4492 bToSelfBA = true;
4493 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004494
Jerry Chuang8fc85982009-11-03 07:17:11 -02004495
4496
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004497 if (bpacket_match_bssid)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004498 priv->stats.numpacket_matchbssid++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004499 if (bpacket_toself)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004500 priv->stats.numpacket_toself++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004501 //
4502 // Process PHY information for previous packet (RSSI/PWDB/EVM)
4503 //
4504 // Because phy information is contained in the last packet of AMPDU only, so driver
4505 // should process phy information of previous packet
4506 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004507 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid, bpacket_toself, bPacketBeacon, bToSelfBA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004508 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
4509
4510}
4511
4512/**
4513* Function: UpdateReceivedRateHistogramStatistics
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004514* Overview: Record the received data rate
Jerry Chuang8fc85982009-11-03 07:17:11 -02004515*
4516* Input:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004517* struct net_device *dev
Jerry Chuang8fc85982009-11-03 07:17:11 -02004518* struct ieee80211_rx_stats *stats
4519*
4520* Output:
4521*
4522* (priv->stats.ReceivedRateHistogram[] is updated)
4523* Return:
4524* None
4525*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004526void UpdateReceivedRateHistogramStatistics8190(struct net_device *dev,
4527 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004528{
4529 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004530 u32 rcvType = 1; //0: Total, 1:OK, 2:CRC, 3:ICV
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004531 u32 rateIndex;
4532 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02004533
4534
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004535 if (stats->bCRC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004536 rcvType = 2;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004537 else if (stats->bICV)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004538 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004539
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004540 if (stats->bShortPreamble)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004541 preamble_guardinterval = 1;// short
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004542 else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004543 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02004544
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004545 switch (stats->rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004546 //
4547 // CCK rate
4548 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004549 case MGN_1M: rateIndex = 0; break;
4550 case MGN_2M: rateIndex = 1; break;
4551 case MGN_5_5M: rateIndex = 2; break;
4552 case MGN_11M: rateIndex = 3; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004553 //
4554 // Legacy OFDM rate
4555 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004556 case MGN_6M: rateIndex = 4; break;
4557 case MGN_9M: rateIndex = 5; break;
4558 case MGN_12M: rateIndex = 6; break;
4559 case MGN_18M: rateIndex = 7; break;
4560 case MGN_24M: rateIndex = 8; break;
4561 case MGN_36M: rateIndex = 9; break;
4562 case MGN_48M: rateIndex = 10; break;
4563 case MGN_54M: rateIndex = 11; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004564 //
4565 // 11n High throughput rate
4566 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004567 case MGN_MCS0: rateIndex = 12; break;
4568 case MGN_MCS1: rateIndex = 13; break;
4569 case MGN_MCS2: rateIndex = 14; break;
4570 case MGN_MCS3: rateIndex = 15; break;
4571 case MGN_MCS4: rateIndex = 16; break;
4572 case MGN_MCS5: rateIndex = 17; break;
4573 case MGN_MCS6: rateIndex = 18; break;
4574 case MGN_MCS7: rateIndex = 19; break;
4575 case MGN_MCS8: rateIndex = 20; break;
4576 case MGN_MCS9: rateIndex = 21; break;
4577 case MGN_MCS10: rateIndex = 22; break;
4578 case MGN_MCS11: rateIndex = 23; break;
4579 case MGN_MCS12: rateIndex = 24; break;
4580 case MGN_MCS13: rateIndex = 25; break;
4581 case MGN_MCS14: rateIndex = 26; break;
4582 case MGN_MCS15: rateIndex = 27; break;
4583 default: rateIndex = 28; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004584 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004585 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
4586 priv->stats.received_rate_histogram[0][rateIndex]++; //total
4587 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004588}
4589
4590
4591void query_rxdesc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats, bool bIsRxAggrSubframe)
4592{
4593 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004594 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004595 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004596 rx_drvinfo_819x_usb *driver_info = NULL;
4597
4598 //
4599 //Get Rx Descriptor Information
4600 //
4601#ifdef USB_RX_AGGREGATION_SUPPORT
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004602 if (bIsRxAggrSubframe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004603 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004604 stats->Length = desc->Length;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004605 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
4606 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
4607 stats->bICV = desc->ICV;
4608 stats->bCRC = desc->CRC32;
4609 stats->bHwError = stats->bCRC|stats->bICV;
4610 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
4611 } else
4612#endif
4613 {
4614 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
4615
4616 stats->Length = desc->Length;
4617 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004618 stats->RxBufShift = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004619 stats->bICV = desc->ICV;
4620 stats->bCRC = desc->CRC32;
4621 stats->bHwError = stats->bCRC|stats->bICV;
4622 //RTL8190 set this bit to indicate that Hw does not decrypt packet
4623 stats->Decrypted = !desc->SWDec;
4624 }
4625
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004626 if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004627 stats->bHwError = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004628 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004629 stats->bHwError = stats->bCRC|stats->bICV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004630
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004631 if (stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004632 stats->bHwError |= 1;
4633 //
4634 //Get Driver Info
4635 //
4636 // TODO: Need to verify it on FGPA platform
4637 //Driver info are written to the RxBuffer following rx desc
4638 if (stats->RxDrvInfoSize != 0) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004639 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004640 stats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004641 /* unit: 0.5M */
4642 /* TODO */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004643 if (!stats->bHwError) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004644 u8 ret_rate;
4645 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004646 if (ret_rate == 0xff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004647 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
4648 // Special Error Handling here, 2008.05.16, by Emily
4649
4650 stats->bHwError = 1;
4651 stats->rate = MGN_1M; //Set 1M rate by default
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004652 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004653 stats->rate = ret_rate;
4654 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004655 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004656 stats->rate = 0x02;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004657 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004658
4659 stats->bShortPreamble = driver_info->SPLCP;
4660
4661
4662 UpdateReceivedRateHistogramStatistics8190(dev, stats);
4663
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004664 stats->bIsAMPDU = (driver_info->PartAggr == 1);
4665 stats->bFirstMPDU = (driver_info->PartAggr == 1) && (driver_info->FirstAGGR == 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004666 stats->TimeStampLow = driver_info->TSFL;
4667 // xiong mask it, 070514
Jerry Chuang8fc85982009-11-03 07:17:11 -02004668
4669 UpdateRxPktTimeStamp8190(dev, stats);
4670
4671 //
4672 // Rx A-MPDU
4673 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004674 if (driver_info->FirstAGGR == 1 || driver_info->PartAggr == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004675 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004676 driver_info->FirstAGGR, driver_info->PartAggr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004677
4678 }
4679
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004680 skb_pull(skb, sizeof(rx_desc_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004681 //
4682 // Get Total offset of MPDU Frame Body
4683 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004684 if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004685 stats->bShift = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004686 skb_pull(skb, stats->RxBufShift + stats->RxDrvInfoSize);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004687 }
4688
4689#ifdef USB_RX_AGGREGATION_SUPPORT
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004690 /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004691 if (bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004692 skb_pull(skb, 8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004693#endif
4694 /* for debug 2008.5.29 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004695
4696 //added by vivi, for MP, 20080108
4697 stats->RxIs40MHzPacket = driver_info->BW;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004698 if (stats->RxDrvInfoSize != 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004699 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
4700
4701}
4702
4703u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
4704{
4705#ifdef USB_RX_AGGREGATION_SUPPORT
4706 if (bIsRxAggrSubframe)
4707 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
4708 + Status->RxBufShift + 8);
4709 else
4710#endif
4711 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004712 + Status->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004713}
4714
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004715void rtl8192_rx_nomal(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004716{
4717 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004718 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004719 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4720 struct ieee80211_rx_stats stats = {
4721 .signal = 0,
4722 .noise = -98,
4723 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004724 .freq = IEEE80211_24GHZ_BAND,
4725 };
4726 u32 rx_pkt_len = 0;
4727 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
4728 bool unicast_packet = false;
4729#ifdef USB_RX_AGGREGATION_SUPPORT
4730 struct sk_buff *agg_skb = NULL;
4731 u32 TotalLength = 0;
4732 u32 TempDWord = 0;
4733 u32 PacketLength = 0;
4734 u32 PacketOccupiedLendth = 0;
4735 u8 TempByte = 0;
4736 u32 PacketShiftBytes = 0;
4737 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
4738 u8 PaddingBytes = 0;
4739 //add just for testing
4740 u8 testing;
4741
4742#endif
4743
4744 /* 20 is for ps-poll */
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004745 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004746#ifdef USB_RX_AGGREGATION_SUPPORT
4747 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
4748#endif
4749 /* first packet should not contain Rx aggregation header */
4750 query_rxdesc_status(skb, &stats, false);
4751 /* TODO */
4752 /* hardware related info */
4753#ifdef USB_RX_AGGREGATION_SUPPORT
4754 if (TempByte & BIT0) {
4755 agg_skb = skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004756 TotalLength = stats.Length - 4; /*sCrcLng*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02004757 /* though the head pointer has passed this position */
4758 TempDWord = *(u32 *)(agg_skb->data - 4);
4759 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
4760 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004761 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004762 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
4763 }
4764#endif
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004765 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004766 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4767
4768 rx_pkt_len = skb->len;
4769 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4770 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004771 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004772 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004773 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004774 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004775 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004776 /* unicast packet */
4777 unicast_packet = true;
4778 }
4779
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004780 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004781 dev_kfree_skb_any(skb);
4782 } else {
4783 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004784 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004785 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004786 }
4787#ifdef USB_RX_AGGREGATION_SUPPORT
4788 testing = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004789 if (TotalLength > 0) {
4790 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
4791 if ((PacketOccupiedLendth & 0xFF) != 0)
4792 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
4793 PacketOccupiedLendth -= 8;
4794 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
4795 if (agg_skb->len > TempDWord)
4796 skb_pull(agg_skb, TempDWord);
4797 else
4798 agg_skb->len = 0;
4799
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004800 while (agg_skb->len >= GetRxPacketShiftBytes819xUsb(&stats, true)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004801 u8 tmpCRC = 0, tmpICV = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004802 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
4803 tmpCRC = RxDescr->CRC32;
4804 tmpICV = RxDescr->ICV;
4805 memcpy(agg_skb->data, &agg_skb->data[44], 2);
4806 RxDescr->CRC32 = tmpCRC;
4807 RxDescr->ICV = tmpICV;
4808
4809 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
4810 stats.signal = 0;
4811 stats.noise = -98;
4812 stats.rate = 0;
4813 stats.freq = IEEE80211_24GHZ_BAND;
4814 query_rxdesc_status(agg_skb, &stats, true);
4815 PacketLength = stats.Length;
4816
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004817 if (PacketLength > agg_skb->len)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004818 break;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004819 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004820 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004821 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004822 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4823
4824 rx_pkt_len = skb->len;
4825 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4826 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004827 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004828 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004829 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004830 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004831 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004832 /* unicast packet */
4833 unicast_packet = true;
4834 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004835 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004836 dev_kfree_skb_any(skb);
4837 } else {
4838 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004839 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004840 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004841 }
4842 /* should trim the packet which has been copied to target skb */
4843 skb_pull(agg_skb, PacketLength);
4844 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
4845 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
4846 if ((PacketOccupiedLendth & 0xFF) != 0) {
4847 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
4848 if (agg_skb->len > PaddingBytes)
4849 skb_pull(agg_skb, PaddingBytes);
4850 else
4851 agg_skb->len = 0;
4852 }
4853 }
4854 dev_kfree_skb(agg_skb);
4855 }
4856#endif
4857 } else {
4858 priv->stats.rxurberr++;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03004859 netdev_dbg(dev, "actual_length: %d\n", skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004860 dev_kfree_skb_any(skb);
4861 }
4862
4863}
4864
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004865void rtl819xusb_process_received_packet(struct net_device *dev,
4866 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004867{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004868 u8 *frame;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004869 u16 frame_len = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004870 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004871
4872 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
4873 //porting by amy 080508
4874 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
4875 frame = pstats->virtual_address;
4876 frame_len = pstats->packetlength;
4877#ifdef TODO // by amy about HCT
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004878 if (!Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004879 CountRxErrStatistics(Adapter, pRfd);
4880#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004881#ifdef ENABLE_PS //by amy for adding ps function in future
4882 RT_RF_POWER_STATE rtState;
4883 // When RF is off, we should not count the packet for hw/sw synchronize
4884 // reason, ie. there may be a duration while sw switch is changed and hw
4885 // switch is being changed. 2006.12.04, by shien chang.
4886 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8 *)(&rtState));
4887 if (rtState == eRfOff)
4888 return;
4889#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -02004890 priv->stats.rxframgment++;
4891
Jerry Chuang8fc85982009-11-03 07:17:11 -02004892#ifdef TODO
4893 RmMonitorSignalStrength(Adapter, pRfd);
4894#endif
4895 /* 2007/01/16 MH Add RX command packet handle here. */
4896 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
4897 if (rtl819xusb_rx_command_packet(dev, pstats))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004898 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004899
4900#ifdef SW_CRC_CHECK
4901 SwCrcCheck();
4902#endif
4903
4904
4905}
4906
4907void query_rx_cmdpkt_desc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats)
4908{
Jerry Chuang8fc85982009-11-03 07:17:11 -02004909 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004910
4911 //
4912 //Get Rx Descriptor Information
4913 //
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004914 stats->virtual_address = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004915 stats->Length = desc->Length;
4916 stats->RxDrvInfoSize = 0;
4917 stats->RxBufShift = 0;
4918 stats->packetlength = stats->Length-scrclng;
4919 stats->fraglength = stats->packetlength;
4920 stats->fragoffset = 0;
4921 stats->ntotalfrag = 1;
4922}
4923
4924
4925void rtl8192_rx_cmd(struct sk_buff *skb)
4926{
4927 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
4928 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004929 /* TODO */
4930 struct ieee80211_rx_stats stats = {
4931 .signal = 0,
4932 .noise = -98,
4933 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004934 .freq = IEEE80211_24GHZ_BAND,
4935 };
4936
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004937 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004938
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004939 query_rx_cmdpkt_desc_status(skb, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004940 // this is to be done by amy 080508 prfd->queue_id = 1;
4941
4942
4943 //
4944 // Process the command packet received.
4945 //
4946
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004947 rtl819xusb_process_received_packet(dev, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004948
4949 dev_kfree_skb_any(skb);
4950 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004951}
4952
4953void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
4954{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004955 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004956 struct rtl8192_rx_info *info;
4957
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004958 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004959 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004960 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004961 /* Nomal packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004962 case 3:
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004963 priv->IrpPendingCount--;
4964 rtl8192_rx_nomal(skb);
4965 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004966
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004967 /* Command packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004968 case 9:
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004969 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004970 info->out_pipe);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004971
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004972 rtl8192_rx_cmd(skb);
4973 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004974
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004975 default: /* should never get here! */
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004976 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004977 info->out_pipe);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004978 dev_kfree_skb(skb);
4979 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004980
4981 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004982 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004983}
4984
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02004985static const struct net_device_ops rtl8192_netdev_ops = {
4986 .ndo_open = rtl8192_open,
4987 .ndo_stop = rtl8192_close,
4988 .ndo_get_stats = rtl8192_stats,
4989 .ndo_tx_timeout = tx_timeout,
4990 .ndo_do_ioctl = rtl8192_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00004991 .ndo_set_rx_mode = r8192_set_multicast,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02004992 .ndo_set_mac_address = r8192_set_mac_adr,
4993 .ndo_validate_addr = eth_validate_addr,
4994 .ndo_change_mtu = eth_change_mtu,
4995 .ndo_start_xmit = ieee80211_xmit,
4996};
Jerry Chuang8fc85982009-11-03 07:17:11 -02004997
4998
4999/****************************************************************************
5000 ---------------------------- USB_STUFF---------------------------
5001*****************************************************************************/
5002
Bill Pemberton25794522012-11-19 13:22:04 -05005003static int rtl8192_usb_probe(struct usb_interface *intf,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005004 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005005{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005006 struct net_device *dev = NULL;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005007 struct r8192_priv *priv = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005008 struct usb_device *udev = interface_to_usbdev(intf);
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005009 int ret;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005010 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005011
5012 dev = alloc_ieee80211(sizeof(struct r8192_priv));
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005013 if (dev == NULL)
5014 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005015
Jerry Chuang8fc85982009-11-03 07:17:11 -02005016 usb_set_intfdata(intf, dev);
5017 SET_NETDEV_DEV(dev, &intf->dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005018 priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005019 priv->ieee80211 = netdev_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005020 priv->udev = udev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005021
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005022 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005023
Jerry Chuang8fc85982009-11-03 07:17:11 -02005024#if WIRELESS_EXT >= 12
5025#if WIRELESS_EXT < 17
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005026 dev->get_wireless_stats = r8192_get_wireless_stats;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005027#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005028 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005029#endif
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005030 dev->type = ARPHRD_ETHER;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005031
5032 dev->watchdog_timeo = HZ*3; //modified by john, 0805
5033
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005034 if (dev_alloc_name(dev, ifname) < 0) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005035 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005036 ifname = "wlan%d";
5037 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005038 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005039
5040 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005041 if (rtl8192_init(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005042 RT_TRACE(COMP_ERR, "Initialization failed");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005043 ret = -ENODEV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005044 goto fail;
5045 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005046 netif_carrier_off(dev);
5047 netif_stop_queue(dev);
5048
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005049 ret = register_netdev(dev);
5050 if (ret)
5051 goto fail2;
5052
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005053 RT_TRACE(COMP_INIT, "dev name=======> %s\n", dev->name);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005054 rtl8192_proc_init_one(dev);
5055
5056
5057 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005058 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005059
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005060fail2:
5061 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005062 kfree(priv->pFirmware);
5063 priv->pFirmware = NULL;
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005064 rtl8192_usb_deleteendpoints(dev);
5065 destroy_workqueue(priv->priv_wq);
5066 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005067fail:
5068 free_ieee80211(dev);
5069
5070 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005071 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005072}
5073
5074//detach all the work and timer structure declared or inititialize in r8192U_init function.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005075void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005076{
5077
Jerry Chuang8fc85982009-11-03 07:17:11 -02005078 cancel_work_sync(&priv->reset_wq);
5079 cancel_delayed_work(&priv->watch_dog_wq);
5080 cancel_delayed_work(&priv->update_beacon_wq);
5081 cancel_work_sync(&priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005082}
5083
5084
Bill Pembertona4a557e2012-11-19 13:26:46 -05005085static void rtl8192_usb_disconnect(struct usb_interface *intf)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005086{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005087 struct net_device *dev = usb_get_intfdata(intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005088
5089 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005090 if (dev) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005091
5092 unregister_netdev(dev);
5093
5094 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
5095 rtl8192_proc_remove_one(dev);
5096
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005097 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005098 kfree(priv->pFirmware);
5099 priv->pFirmware = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005100 rtl8192_usb_deleteendpoints(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005101 destroy_workqueue(priv->priv_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005102 mdelay(10);
5103
5104 }
5105 free_ieee80211(dev);
5106 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
5107}
5108
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005109/* fun with the built-in ieee80211 stack... */
5110extern int ieee80211_debug_init(void);
5111extern void ieee80211_debug_exit(void);
5112extern int ieee80211_crypto_init(void);
5113extern void ieee80211_crypto_deinit(void);
5114extern int ieee80211_crypto_tkip_init(void);
5115extern void ieee80211_crypto_tkip_exit(void);
5116extern int ieee80211_crypto_ccmp_init(void);
5117extern void ieee80211_crypto_ccmp_exit(void);
5118extern int ieee80211_crypto_wep_init(void);
5119extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005120
5121static int __init rtl8192_usb_module_init(void)
5122{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005123 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005124
5125#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005126 ret = ieee80211_debug_init();
5127 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005128 pr_err("ieee80211_debug_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005129 return ret;
5130 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005131#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005132 ret = ieee80211_crypto_init();
5133 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005134 pr_err("ieee80211_crypto_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005135 return ret;
5136 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005137
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005138 ret = ieee80211_crypto_tkip_init();
5139 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005140 pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005141 return ret;
5142 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005143
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005144 ret = ieee80211_crypto_ccmp_init();
5145 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005146 pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005147 return ret;
5148 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005149
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005150 ret = ieee80211_crypto_wep_init();
5151 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005152 pr_err("ieee80211_crypto_wep_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005153 return ret;
5154 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005155
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005156 pr_info("\nLinux kernel driver for RTL8192 based WLAN cards\n");
5157 pr_info("Copyright (c) 2007-2008, Realsil Wlan\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005158 RT_TRACE(COMP_INIT, "Initializing module");
5159 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
5160 rtl8192_proc_module_init();
5161 return usb_register(&rtl8192_usb_driver);
5162}
5163
5164
5165static void __exit rtl8192_usb_module_exit(void)
5166{
5167 usb_deregister(&rtl8192_usb_driver);
5168
5169 RT_TRACE(COMP_DOWN, "Exiting");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005170}
5171
5172
5173void rtl8192_try_wake_queue(struct net_device *dev, int pri)
5174{
5175 unsigned long flags;
5176 short enough_desc;
5177 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5178
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005179 spin_lock_irqsave(&priv->tx_lock, flags);
5180 enough_desc = check_nic_enough_desc(dev, pri);
5181 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005182
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005183 if (enough_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005184 ieee80211_wake_queue(priv->ieee80211);
5185}
5186
5187void EnableHWSecurityConfig8192(struct net_device *dev)
5188{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005189 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005190 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005191 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005192 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005193 if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->ieee80211->auth_mode != 2)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005194 SECR_value |= SCR_RxUseDK;
5195 SECR_value |= SCR_TxUseDK;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005196 } else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005197 SECR_value |= SCR_RxUseDK;
5198 SECR_value |= SCR_TxUseDK;
5199 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005200 //add HWSec active enable here.
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005201 //default using hwsec. when peer AP is in N mode only and pairwise_key_type is none_aes(which HT_IOT_ACT_PURE_N_MODE indicates it), use software security. when peer AP is in b,g,n mode mixed and pairwise_key_type is none_aes, use g mode hw security. WB on 2008.7.4
Jerry Chuang8fc85982009-11-03 07:17:11 -02005202
5203 ieee->hwsec_active = 1;
5204
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005205 if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) { //add hwsec_support flag to totol control hw_sec on/off
Jerry Chuang8fc85982009-11-03 07:17:11 -02005206 ieee->hwsec_active = 0;
5207 SECR_value &= ~SCR_RxDecEnable;
5208 }
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03005209 RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __func__,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005210 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
5211 write_nic_byte(dev, SECR, SECR_value);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005212}
5213
5214
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03005215void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
5216 u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005217{
5218 u32 TargetCommand = 0;
5219 u32 TargetContent = 0;
5220 u16 usConfig = 0;
5221 u8 i;
5222 if (EntryNo >= TOTAL_CAM_ENTRY)
5223 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
5224
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005225 RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", dev, EntryNo, KeyIndex, KeyType, MacAddr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005226
5227 if (DefaultKey)
5228 usConfig |= BIT15 | (KeyType<<2);
5229 else
5230 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005231
5232
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005233 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005234 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
5235 TargetCommand |= BIT31|BIT16;
5236
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005237 if (i == 0) { //MAC|Config
Jerry Chuang8fc85982009-11-03 07:17:11 -02005238 TargetContent = (u32)(*(MacAddr+0)) << 16|
5239 (u32)(*(MacAddr+1)) << 24|
5240 (u32)usConfig;
5241
5242 write_nic_dword(dev, WCAMI, TargetContent);
5243 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005244 } else if (i == 1) { //MAC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005245 TargetContent = (u32)(*(MacAddr+2)) |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005246 (u32)(*(MacAddr+3)) << 8|
5247 (u32)(*(MacAddr+4)) << 16|
5248 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005249 write_nic_dword(dev, WCAMI, TargetContent);
5250 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005251 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005252 //Key Material
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005253 if (KeyContent != NULL) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005254 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)));
5255 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005256 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005257 }
5258 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005259
5260}
5261
5262/***************************************************************************
5263 ------------------- module init / exit stubs ----------------
5264****************************************************************************/
5265module_init(rtl8192_usb_module_init);
5266module_exit(rtl8192_usb_module_exit);