blob: 2a9150daec523eb503dfed0055f6172a1216d619 [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:
Andrea Merello559a4c32013-08-26 13:53:30 +02006 * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
Jerry Chuang8fc85982009-11-03 07:17:11 -02007 * 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
Jerry Chuang8fc85982009-11-03 07:17:11 -0200100#include "dot11d.h"
Jerry Chuang8fc85982009-11-03 07:17:11 -0200101//set here to open your trace code. //WB
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300102u32 rt_global_debug_component = COMP_DOWN |
Jerry Chuang8fc85982009-11-03 07:17:11 -0200103 COMP_SEC |
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300104 COMP_ERR; //always open err flags on
Jerry Chuang8fc85982009-11-03 07:17:11 -0200105
106#define TOTAL_CAM_ENTRY 32
107#define CAM_CONTENT_COUNT 8
108
Németh Mártona4577322010-01-10 00:18:34 +0100109static const struct usb_device_id rtl8192_usb_id_tbl[] = {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200110 /* Realtek */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200111 {USB_DEVICE(0x0bda, 0x8709)},
112 /* Corega */
113 {USB_DEVICE(0x07aa, 0x0043)},
114 /* Belkin */
115 {USB_DEVICE(0x050d, 0x805E)},
116 /* Sitecom */
117 {USB_DEVICE(0x0df6, 0x0031)},
118 /* EnGenius */
119 {USB_DEVICE(0x1740, 0x9201)},
120 /* Dlink */
121 {USB_DEVICE(0x2001, 0x3301)},
122 /* Zinwell */
123 {USB_DEVICE(0x5a57, 0x0290)},
Ben Hutchingse10ac152010-06-25 01:35:49 +0100124 /* LG */
125 {USB_DEVICE(0x043e, 0x7a01)},
Jerry Chuang8fc85982009-11-03 07:17:11 -0200126 {}
127};
128
129MODULE_LICENSE("GPL");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200130MODULE_VERSION("V 1.1");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200131MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl);
132MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards");
133
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300134static char *ifname = "wlan%d";
Jerry Chuang8fc85982009-11-03 07:17:11 -0200135static int hwwep = 1; //default use hw. set 0 to use software security
136static int channels = 0x3fff;
137
138
139
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300140module_param(ifname, charp, S_IRUGO|S_IWUSR);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300141module_param(hwwep, int, S_IRUGO|S_IWUSR);
142module_param(channels, int, S_IRUGO|S_IWUSR);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200143
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300144MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default");
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300145MODULE_PARM_DESC(hwwep, " Try to use hardware security support. ");
146MODULE_PARM_DESC(channels, " Channel bitmask for specific locales. NYI");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200147
Bill Pemberton25794522012-11-19 13:22:04 -0500148static int rtl8192_usb_probe(struct usb_interface *intf,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300149 const struct usb_device_id *id);
Bill Pembertona4a557e2012-11-19 13:26:46 -0500150static void rtl8192_usb_disconnect(struct usb_interface *intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200151
152
153static struct usb_driver rtl8192_usb_driver = {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200154 .name = RTL819xU_MODULE_NAME, /* Driver name */
155 .id_table = rtl8192_usb_id_tbl, /* PCI_ID table */
156 .probe = rtl8192_usb_probe, /* probe fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200157 .disconnect = rtl8192_usb_disconnect, /* remove fn */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200158 .suspend = NULL, /* PM suspend fn */
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100159 .resume = NULL, /* PM resume fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200160};
161
Jerry Chuang8fc85982009-11-03 07:17:11 -0200162
Jennifer Naumann0db7a342012-12-05 21:40:19 +0100163typedef struct _CHANNEL_LIST {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200164 u8 Channel[32];
165 u8 Len;
Xenia Ragiadakou972ff922013-05-23 05:14:47 +0300166} CHANNEL_LIST, *PCHANNEL_LIST;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200167
168static CHANNEL_LIST ChannelPlan[] = {
Chaitanya Hazareyb6b07892014-06-05 13:25:56 -0700169 {{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
170 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, //IC
171 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, //ETSI
172 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, //Spain. Change to ETSI.
173 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, //France. Change to ETSI.
174 {{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
175 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22},//MKK1
176 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, //Israel.
177 {{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
178 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22}, //MIC
179 {{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
Jerry Chuang8fc85982009-11-03 07:17:11 -0200180};
181
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300182static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200183{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300184 int i, max_chan = -1, min_chan = -1;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300185 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300186 switch (channel_plan) {
Patrik Karlinf00c4932013-01-09 09:39:44 +0100187 case COUNTRY_CODE_FCC:
188 case COUNTRY_CODE_IC:
189 case COUNTRY_CODE_ETSI:
190 case COUNTRY_CODE_SPAIN:
191 case COUNTRY_CODE_FRANCE:
192 case COUNTRY_CODE_MKK:
193 case COUNTRY_CODE_MKK1:
194 case COUNTRY_CODE_ISRAEL:
195 case COUNTRY_CODE_TELEC:
Xenia Ragiadakou88e5a932013-06-04 23:32:31 +0300196 case COUNTRY_CODE_MIC:
Patrik Karlinf00c4932013-01-09 09:39:44 +0100197 Dot11d_Init(ieee);
198 ieee->bGlobalDomain = false;
199 //actually 8225 & 8256 rf chips only support B,G,24N mode
200 if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256)) {
201 min_chan = 1;
202 max_chan = 14;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300203 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +0300204 RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __func__);
Patrik Karlinf00c4932013-01-09 09:39:44 +0100205 }
206 if (ChannelPlan[channel_plan].Len != 0) {
207 // Clear old channel map
208 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
209 // Set new channel map
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300210 for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
Patrik Karlinf00c4932013-01-09 09:39:44 +0100211 if (ChannelPlan[channel_plan].Channel[i] < min_chan || ChannelPlan[channel_plan].Channel[i] > max_chan)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200212 break;
Patrik Karlinf00c4932013-01-09 09:39:44 +0100213 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200214 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200215 }
Patrik Karlinf00c4932013-01-09 09:39:44 +0100216 break;
217
218 case COUNTRY_CODE_GLOBAL_DOMAIN:
219 GET_DOT11D_INFO(ieee)->bEnabled = 0;//this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain settings.
220 Dot11d_Reset(ieee);
221 ieee->bGlobalDomain = true;
222 break;
Xenia Ragiadakou88e5a932013-06-04 23:32:31 +0300223
Patrik Karlinf00c4932013-01-09 09:39:44 +0100224 default:
225 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200226 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200227}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200228
Jerry Chuang8fc85982009-11-03 07:17:11 -0200229
Jerry Chuang8fc85982009-11-03 07:17:11 -0200230
231
Ana Reyf4c60742014-03-13 12:36:38 +0100232static void CamResetAllEntry(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200233{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200234 u32 ulcommand = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200235 //2004/02/11 In static WEP, OID_ADD_KEY or OID_ADD_WEP are set before STA associate to AP.
236 // However, ResetKey is called on OID_802_11_INFRASTRUCTURE_MODE and MlmeAssociateRequest
237 // 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 -0200238 ulcommand |= BIT31|BIT30;
239 write_nic_dword(dev, RWCAM, ulcommand);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200240
241}
242
243
244void write_cam(struct net_device *dev, u8 addr, u32 data)
245{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200246 write_nic_dword(dev, WCAMI, data);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300247 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200248}
249
250u32 read_cam(struct net_device *dev, u8 addr)
251{
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300252 u32 data;
253
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300254 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff));
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300255 read_nic_dword(dev, 0xa8, &data);
256 return data;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200257}
258
259void write_nic_byte_E(struct net_device *dev, int indx, u8 data)
260{
261 int status;
262 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
263 struct usb_device *udev = priv->udev;
264
265 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300266 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
267 indx|0xfe00, 0, &data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200268
269 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300270 netdev_err(dev, "write_nic_byte_E TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200271}
272
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300273int read_nic_byte_E(struct net_device *dev, int indx, u8 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200274{
275 int status;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200276 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
277 struct usb_device *udev = priv->udev;
278
279 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300280 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300281 indx|0xfe00, 0, data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200282
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300283 if (status < 0) {
284 netdev_err(dev, "%s failure status: %d\n", __func__, status);
285 return status;
286 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200287
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300288 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200289}
290//as 92U has extend page from 4 to 16, so modify functions below.
291void write_nic_byte(struct net_device *dev, int indx, u8 data)
292{
293 int status;
294
295 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
296 struct usb_device *udev = priv->udev;
297
298 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300299 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
300 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200301
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200302 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300303 netdev_err(dev, "write_nic_byte TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200304
305
306}
307
308
309void write_nic_word(struct net_device *dev, int indx, u16 data)
310{
311
312 int status;
313
314 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
315 struct usb_device *udev = priv->udev;
316
317 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300318 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
319 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200320
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200321 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300322 netdev_err(dev, "write_nic_word TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200323
324}
325
326
327void write_nic_dword(struct net_device *dev, int indx, u32 data)
328{
329
330 int status;
331
332 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
333 struct usb_device *udev = priv->udev;
334
335 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300336 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
337 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200338
339
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200340 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300341 netdev_err(dev, "write_nic_dword TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200342
343}
344
345
346
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300347int read_nic_byte(struct net_device *dev, int indx, u8 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200348{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200349 int status;
350 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
351 struct usb_device *udev = priv->udev;
352
353 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300354 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300355 (indx&0xff)|0xff00, (indx>>8)&0x0f, data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200356
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300357 if (status < 0) {
358 netdev_err(dev, "%s failure status: %d\n", __func__, status);
359 return status;
360 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200361
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300362 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200363}
364
365
366
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300367int read_nic_word(struct net_device *dev, int indx, u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200368{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200369 int status;
370 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
371 struct usb_device *udev = priv->udev;
372
373 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300374 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
375 (indx&0xff)|0xff00, (indx>>8)&0x0f,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300376 data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200377
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300378 if (status < 0) {
379 netdev_err(dev, "%s failure status: %d\n", __func__, status);
380 return status;
381 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200382
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300383 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200384}
385
Teodora Baluta46326d22013-10-16 01:59:17 +0300386static int read_nic_word_E(struct net_device *dev, int indx, u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200387{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200388 int status;
389 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
390 struct usb_device *udev = priv->udev;
391
392 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300393 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300394 indx|0xfe00, 0, data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200395
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300396 if (status < 0) {
397 netdev_err(dev, "%s failure status: %d\n", __func__, status);
398 return status;
399 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200400
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300401 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200402}
403
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300404int read_nic_dword(struct net_device *dev, int indx, u32 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200405{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200406 int status;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200407
408 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
409 struct usb_device *udev = priv->udev;
410
411 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300412 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
413 (indx&0xff)|0xff00, (indx>>8)&0x0f,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300414 data, 4, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200415
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300416 if (status < 0) {
417 netdev_err(dev, "%s failure status: %d\n", __func__, status);
418 return status;
419 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200420
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300421 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200422}
423
Mike Gilks616f58f2010-06-03 18:29:23 +0800424/* u8 read_phy_cck(struct net_device *dev, u8 adr); */
425/* u8 read_phy_ofdm(struct net_device *dev, u8 adr); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200426/* this might still called in what was the PHY rtl8185/rtl8192 common code
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300427 * plans are to possibility turn it again in one common code...
Jerry Chuang8fc85982009-11-03 07:17:11 -0200428 */
429inline void force_pci_posting(struct net_device *dev)
430{
431}
432
Jerry Chuang8fc85982009-11-03 07:17:11 -0200433static struct net_device_stats *rtl8192_stats(struct net_device *dev);
434void rtl8192_commit(struct net_device *dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200435void rtl8192_restart(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200436void watch_dog_timer_callback(unsigned long data);
437
438/****************************************************************************
Mike Gilks616f58f2010-06-03 18:29:23 +0800439 * -----------------------------PROCFS STUFF-------------------------
440*****************************************************************************
441 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200442
Mike Gilks616f58f2010-06-03 18:29:23 +0800443static struct proc_dir_entry *rtl8192_proc;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200444
David Howells0541f9d2013-04-08 15:17:33 +0100445static int proc_get_stats_ap(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200446{
David Howells0541f9d2013-04-08 15:17:33 +0100447 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200448 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
449 struct ieee80211_device *ieee = priv->ieee80211;
450 struct ieee80211_network *target;
451
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200452 list_for_each_entry(target, &ieee->network_list, list) {
David Howells0541f9d2013-04-08 15:17:33 +0100453 const char *wpa = "non_WPA";
Mike Gilks616f58f2010-06-03 18:29:23 +0800454 if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0)
David Howells0541f9d2013-04-08 15:17:33 +0100455 wpa = "WPA";
456
457 seq_printf(m, "%s %s\n", target->ssid, wpa);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200458 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200459
David Howells0541f9d2013-04-08 15:17:33 +0100460 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200461}
462
David Howells0541f9d2013-04-08 15:17:33 +0100463static int proc_get_registers(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200464{
David Howells0541f9d2013-04-08 15:17:33 +0100465 struct net_device *dev = m->private;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300466 int i, n, max = 0xff;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300467 u8 byte_rd;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200468
David Howells0541f9d2013-04-08 15:17:33 +0100469 seq_puts(m, "\n####################page 0##################\n ");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200470
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300471 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300472 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200473
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300474 for (i = 0; i < 16 && n <= max; i++, n++) {
475 read_nic_byte(dev, 0x000|n, &byte_rd);
476 seq_printf(m, "%2x ", byte_rd);
477 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200478 }
David Howells0541f9d2013-04-08 15:17:33 +0100479
480 seq_puts(m, "\n####################page 1##################\n ");
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300481 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300482 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200483
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300484 for (i = 0; i < 16 && n <= max; i++, n++) {
485 read_nic_byte(dev, 0x100|n, &byte_rd);
486 seq_printf(m, "%2x ", byte_rd);
487 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200488 }
David Howells0541f9d2013-04-08 15:17:33 +0100489
490 seq_puts(m, "\n####################page 3##################\n ");
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300491 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300492 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200493
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300494 for (i = 0; i < 16 && n <= max; i++, n++) {
495 read_nic_byte(dev, 0x300|n, &byte_rd);
496 seq_printf(m, "%2x ", byte_rd);
497 }
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
Teodora Baluta46326d22013-10-16 01:59:17 +0300579static void rtl8192_proc_module_init(void)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200580{
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
David Howells0541f9d2013-04-08 15:17:33 +0100585/*
586 * seq_file wrappers for procfile show routines.
587 */
588static int rtl8192_proc_open(struct inode *inode, struct file *file)
589{
David Howells4a520d22013-04-12 14:06:01 +0100590 struct net_device *dev = proc_get_parent_data(inode);
David Howells0541f9d2013-04-08 15:17:33 +0100591 int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
592
593 return single_open(file, show, dev);
594}
595
596static const struct file_operations rtl8192_proc_fops = {
597 .open = rtl8192_proc_open,
598 .read = seq_read,
599 .llseek = seq_lseek,
Al Virobae301d2013-05-05 00:15:43 -0400600 .release = single_release,
David Howells0541f9d2013-04-08 15:17:33 +0100601};
602
603/*
604 * Table of proc files we need to create.
605 */
606struct rtl8192_proc_file {
607 char name[12];
608 int (*show)(struct seq_file *, void *);
609};
610
611static const struct rtl8192_proc_file rtl8192_proc_files[] = {
612 { "stats-rx", &proc_get_stats_rx },
613 { "stats-tx", &proc_get_stats_tx },
614 { "stats-ap", &proc_get_stats_ap },
615 { "registers", &proc_get_registers },
616 { "" }
617};
618
Teodora Baluta46326d22013-10-16 01:59:17 +0300619static void rtl8192_proc_init_one(struct net_device *dev)
David Howells0541f9d2013-04-08 15:17:33 +0100620{
621 const struct rtl8192_proc_file *f;
David Howellscc87e0f2013-04-12 03:02:22 +0100622 struct proc_dir_entry *dir;
David Howells0541f9d2013-04-08 15:17:33 +0100623
624 if (rtl8192_proc) {
David Howellscc87e0f2013-04-12 03:02:22 +0100625 dir = proc_mkdir_data(dev->name, 0, rtl8192_proc, dev);
626 if (!dir) {
David Howells0541f9d2013-04-08 15:17:33 +0100627 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
628 dev->name);
629 return;
630 }
David Howells0541f9d2013-04-08 15:17:33 +0100631
632 for (f = rtl8192_proc_files; f->name[0]; f++) {
David Howellscc87e0f2013-04-12 03:02:22 +0100633 if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir,
634 &rtl8192_proc_fops, f->show)) {
David Howells0541f9d2013-04-08 15:17:33 +0100635 RT_TRACE(COMP_ERR, "Unable to initialize "
636 "/proc/net/rtl8192/%s/%s\n",
637 dev->name, f->name);
638 return;
639 }
640 }
641 }
642}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200643
Teodora Baluta46326d22013-10-16 01:59:17 +0300644static void rtl8192_proc_remove_one(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200645{
David Howellscc87e0f2013-04-12 03:02:22 +0100646 remove_proc_subtree(dev->name, rtl8192_proc);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200647}
648
Jerry Chuang8fc85982009-11-03 07:17:11 -0200649/****************************************************************************
650 -----------------------------MISC STUFF-------------------------
651*****************************************************************************/
652
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300653short check_nic_enough_desc(struct net_device *dev, int queue_index)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200654{
655 struct r8192_priv *priv = ieee80211_priv(dev);
656 int used = atomic_read(&priv->tx_pending[queue_index]);
657
658 return (used < MAX_TX_URB);
659}
660
Ana Reyf4c60742014-03-13 12:36:38 +0100661static void tx_timeout(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200662{
663 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200664
Jerry Chuang8fc85982009-11-03 07:17:11 -0200665 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200666}
667
668
669/* this is only for debug */
670void dump_eprom(struct net_device *dev)
671{
672 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300673 for (i = 0; i < 63; i++)
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300674 RT_TRACE(COMP_EPROM, "EEPROM addr %x : %x", i, eprom_read(dev, i));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200675}
676
Jerry Chuang8fc85982009-11-03 07:17:11 -0200677void rtl8192_update_msr(struct net_device *dev)
678{
679 struct r8192_priv *priv = ieee80211_priv(dev);
680 u8 msr;
681
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300682 read_nic_byte(dev, MSR, &msr);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300683 msr &= ~MSR_LINK_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200684
685 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
686 * msr must be updated if the state is ASSOCIATING.
687 * this is intentional and make sense for ad-hoc and
688 * master (see the create BSS/IBSS func)
689 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300690 if (priv->ieee80211->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200691
692 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
693 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
694 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
695 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
696 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
697 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
698
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300699 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200700 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300701 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200702
703 write_nic_byte(dev, MSR, msr);
704}
705
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300706void rtl8192_set_chan(struct net_device *dev, short ch)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200707{
708 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +0300709 RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __func__, ch);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300710 priv->chan = ch;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200711
712 /* this hack should avoid frame TX during channel setting*/
713
Jerry Chuang8fc85982009-11-03 07:17:11 -0200714#ifndef LOOP_TEST
Jerry Chuang8fc85982009-11-03 07:17:11 -0200715 //need to implement rf set channel here WB
716
717 if (priv->rf_set_chan)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300718 priv->rf_set_chan(dev, priv->chan);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200719 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200720#endif
721}
722
Jerry Chuang8fc85982009-11-03 07:17:11 -0200723static void rtl8192_rx_isr(struct urb *urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200724
Teodora Baluta46326d22013-10-16 01:59:17 +0300725static u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200726{
727
728#ifdef USB_RX_AGGREGATION_SUPPORT
729 if (pstats->bisrxaggrsubframe)
730 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
731 + pstats->RxBufShift + 8);
732 else
733#endif
734 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300735 + pstats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200736
737}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300738static int rtl8192_rx_initiate(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200739{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200740 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
741 struct urb *entry;
742 struct sk_buff *skb;
743 struct rtl8192_rx_info *info;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200744
745 /* nomal packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200746 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB) {
747 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
748 if (!skb)
749 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200750 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200751 if (!entry) {
752 kfree_skb(skb);
753 break;
754 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200755 usb_fill_bulk_urb(entry, priv->udev,
756 usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb),
757 RX_URB_SIZE, rtl8192_rx_isr, skb);
758 info = (struct rtl8192_rx_info *) skb->cb;
759 info->urb = entry;
760 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200761 info->out_pipe = 3; //denote rx normal packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200762 skb_queue_tail(&priv->rx_queue, skb);
763 usb_submit_urb(entry, GFP_KERNEL);
764 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200765
766 /* command packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200767 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300768 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200769 if (!skb)
770 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200771 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200772 if (!entry) {
773 kfree_skb(skb);
774 break;
775 }
776 usb_fill_bulk_urb(entry, priv->udev,
777 usb_rcvbulkpipe(priv->udev, 9), skb_tail_pointer(skb),
778 RX_URB_SIZE, rtl8192_rx_isr, skb);
779 info = (struct rtl8192_rx_info *) skb->cb;
780 info->urb = entry;
781 info->dev = dev;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300782 info->out_pipe = 9; //denote rx cmd packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200783 skb_queue_tail(&priv->rx_queue, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200784 usb_submit_urb(entry, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200785 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200786
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200787 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200788}
789
790void rtl8192_set_rxconf(struct net_device *dev)
791{
792 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
793 u32 rxconf;
794
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300795 read_nic_dword(dev, RCR, &rxconf);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300796 rxconf = rxconf & ~MAC_FILTER_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200797 rxconf = rxconf | RCR_AMF;
798 rxconf = rxconf | RCR_ADF;
799 rxconf = rxconf | RCR_AB;
800 rxconf = rxconf | RCR_AM;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200801
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300802 if (dev->flags & IFF_PROMISC)
803 DMESG("NIC in promisc mode");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200804
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300805 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300806 dev->flags & IFF_PROMISC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200807 rxconf = rxconf | RCR_AAP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300808 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200809 rxconf = rxconf | RCR_APM;
810 rxconf = rxconf | RCR_CBSSID;
811 }
812
813
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300814 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200815 rxconf = rxconf | RCR_AICV;
816 rxconf = rxconf | RCR_APWRMGT;
817 }
818
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300819 if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200820 rxconf = rxconf | RCR_ACRC32;
821
822
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300823 rxconf = rxconf & ~RX_FIFO_THRESHOLD_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200824 rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE<<RX_FIFO_THRESHOLD_SHIFT);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300825 rxconf = rxconf & ~MAX_RX_DMA_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200826 rxconf = rxconf | ((u32)7<<RCR_MXDMA_OFFSET);
827
Jerry Chuang8fc85982009-11-03 07:17:11 -0200828 rxconf = rxconf | RCR_ONLYERLPKT;
829
Jerry Chuang8fc85982009-11-03 07:17:11 -0200830 write_nic_dword(dev, RCR, rxconf);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200831}
832//wait to be removed
833void rtl8192_rx_enable(struct net_device *dev)
834{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200835 rtl8192_rx_initiate(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200836}
837
838
839void rtl8192_tx_enable(struct net_device *dev)
840{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200841}
842
Jerry Chuang8fc85982009-11-03 07:17:11 -0200843
844
845void rtl8192_rtx_disable(struct net_device *dev)
846{
847 u8 cmd;
848 struct r8192_priv *priv = ieee80211_priv(dev);
849 struct sk_buff *skb;
850 struct rtl8192_rx_info *info;
851
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300852 read_nic_byte(dev, CMDR, &cmd);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300853 write_nic_byte(dev, CMDR, cmd & ~(CR_TE|CR_RE));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200854 force_pci_posting(dev);
855 mdelay(10);
856
857 while ((skb = __skb_dequeue(&priv->rx_queue))) {
858 info = (struct rtl8192_rx_info *) skb->cb;
859 if (!info->urb)
860 continue;
861
862 usb_kill_urb(info->urb);
863 kfree_skb(skb);
864 }
865
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300866 if (skb_queue_len(&priv->skb_queue))
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300867 netdev_warn(dev, "skb_queue not empty\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200868
869 skb_queue_purge(&priv->skb_queue);
870 return;
871}
872
Jerry Chuang8fc85982009-11-03 07:17:11 -0200873inline u16 ieeerate2rtlrate(int rate)
874{
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300875 switch (rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200876 case 10:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300877 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200878 case 20:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300879 return 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200880 case 55:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300881 return 2;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200882 case 110:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300883 return 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200884 case 60:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300885 return 4;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200886 case 90:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300887 return 5;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200888 case 120:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300889 return 6;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200890 case 180:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300891 return 7;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200892 case 240:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300893 return 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200894 case 360:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300895 return 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200896 case 480:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300897 return 10;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200898 case 540:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300899 return 11;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200900 default:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300901 return 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200902
903 }
904}
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300905static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
Jerry Chuang8fc85982009-11-03 07:17:11 -0200906inline u16 rtl8192_rate2rate(short rate)
907{
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300908 if (rate > 11) return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200909 return rtl_rate[rate];
910}
911
912
Justin P. Mattock589b3d02012-04-30 07:41:36 -0700913/* The prototype of rx_isr has changed since one version of Linux Kernel */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200914static void rtl8192_rx_isr(struct urb *urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200915{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200916 struct sk_buff *skb = (struct sk_buff *) urb->context;
917 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
918 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200919 struct r8192_priv *priv = ieee80211_priv(dev);
920 int out_pipe = info->out_pipe;
921 int err;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300922 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200923 return;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200924 if (unlikely(urb->status)) {
925 info->urb = NULL;
926 priv->stats.rxstaterr++;
927 priv->ieee80211->stats.rx_errors++;
928 usb_free_urb(urb);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200929 return;
930 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200931 skb_unlink(skb, &priv->rx_queue);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200932 skb_put(skb, urb->actual_length);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200933
934 skb_queue_tail(&priv->skb_queue, skb);
935 tasklet_schedule(&priv->irq_rx_tasklet);
936
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200937 skb = dev_alloc_skb(RX_URB_SIZE);
938 if (unlikely(!skb)) {
939 usb_free_urb(urb);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300940 netdev_err(dev, "%s(): can't alloc skb\n", __func__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200941 /* TODO check rx queue length and refill *somewhere* */
942 return;
943 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200944
945 usb_fill_bulk_urb(urb, priv->udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300946 usb_rcvbulkpipe(priv->udev, out_pipe), skb_tail_pointer(skb),
947 RX_URB_SIZE, rtl8192_rx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200948
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200949 info = (struct rtl8192_rx_info *) skb->cb;
950 info->urb = urb;
951 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200952 info->out_pipe = out_pipe;
953
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200954 urb->transfer_buffer = skb_tail_pointer(skb);
955 urb->context = skb;
956 skb_queue_tail(&priv->rx_queue, skb);
957 err = usb_submit_urb(urb, GFP_ATOMIC);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300958 if (err && err != EPERM)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300959 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 -0200960}
961
Teodora Baluta46326d22013-10-16 01:59:17 +0300962static u32 rtl819xusb_rx_command_packet(struct net_device *dev,
963 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200964{
965 u32 status;
966
Jerry Chuang8fc85982009-11-03 07:17:11 -0200967 status = cmpk_message_handle_rx(dev, pstats);
968 if (status)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200969 DMESG("rxcommandpackethandle819xusb: It is a command packet\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200970
Jerry Chuang8fc85982009-11-03 07:17:11 -0200971 return status;
972}
973
Jerry Chuang8fc85982009-11-03 07:17:11 -0200974
Ana Reyf4c60742014-03-13 12:36:38 +0100975static void rtl8192_data_hard_stop(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200976{
977 //FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -0200978}
979
980
Ana Reyf4c60742014-03-13 12:36:38 +0100981static void rtl8192_data_hard_resume(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200982{
983 // FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -0200984}
985
986/* this function TX data frames when the ieee80211 stack requires this.
987 * It checks also if we need to stop the ieee tx queue, eventually do it
988 */
Ana Reyf4c60742014-03-13 12:36:38 +0100989static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200990{
991 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
992 int ret;
993 unsigned long flags;
994 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
995 u8 queue_index = tcb_desc->queue_index;
996
997 /* shall not be referred by command packet */
Xenia Ragiadakou4a8d1132013-06-09 14:38:43 +0300998 RTL8192U_ASSERT(queue_index != TXCMD_QUEUE);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200999
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001000 spin_lock_irqsave(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001001
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001002 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001003 tcb_desc->bTxEnableFwCalcDur = 1;
1004 skb_push(skb, priv->ieee80211->tx_headroom);
1005 ret = rtl8192_tx(dev, skb);
1006
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001007 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001008
Jerry Chuang8fc85982009-11-03 07:17:11 -02001009 return;
1010}
1011
1012/* This is a rough attempt to TX a frame
1013 * This is called by the ieee 80211 stack to TX management frames.
1014 * If the ring is full packet are dropped (for data frame the queue
1015 * is stopped before this can happen).
1016 */
Ana Reyf4c60742014-03-13 12:36:38 +01001017static int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001018{
1019 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1020 int ret;
1021 unsigned long flags;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001022 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1023 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001024
1025
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001026 spin_lock_irqsave(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001027
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001028 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001029 if (queue_index == TXCMD_QUEUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001030 skb_push(skb, USB_HWDESC_HEADER_LEN);
1031 rtl819xU_tx_cmd(dev, skb);
1032 ret = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001033 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001034 return ret;
1035 } else {
1036 skb_push(skb, priv->ieee80211->tx_headroom);
1037 ret = rtl8192_tx(dev, skb);
1038 }
1039
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001040 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001041
1042 return ret;
1043}
1044
1045
1046void rtl8192_try_wake_queue(struct net_device *dev, int pri);
1047
1048#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1049u16 DrvAggr_PaddingAdd(struct net_device *dev, struct sk_buff *skb)
1050{
1051 u16 PaddingNum = 256 - ((skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES) % 256);
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03001052 return PaddingNum & 0xff;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001053}
1054
1055u8 MRateToHwRate8190Pci(u8 rate);
1056u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc);
1057u8 MapHwQueueToFirmwareQueue(u8 QueueID);
1058struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv_agg_txb *pSendList)
1059{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001060 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001061 struct r8192_priv *priv = ieee80211_priv(dev);
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001062 cb_desc *tcb_desc = NULL;
1063 u8 i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001064 u32 TotalLength;
1065 struct sk_buff *skb;
1066 struct sk_buff *agg_skb;
1067 tx_desc_819x_usb_aggr_subframe *tx_agg_desc = NULL;
1068 tx_fwinfo_819x_usb *tx_fwinfo = NULL;
1069
1070 //
1071 // Local variable initialization.
1072 //
1073 /* first skb initialization */
1074 skb = pSendList->tx_agg_frames[0];
1075 TotalLength = skb->len;
1076
1077 /* Get the total aggregation length including the padding space and
1078 * sub frame header.
1079 */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001080 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001081 TotalLength += DrvAggr_PaddingAdd(dev, skb);
1082 skb = pSendList->tx_agg_frames[i];
1083 TotalLength += (skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1084 }
1085
1086 /* allocate skb to contain the aggregated packets */
1087 agg_skb = dev_alloc_skb(TotalLength + ieee->tx_headroom);
1088 memset(agg_skb->data, 0, agg_skb->len);
1089 skb_reserve(agg_skb, ieee->tx_headroom);
1090
Jerry Chuang8fc85982009-11-03 07:17:11 -02001091 /* reserve info for first subframe Tx descriptor to be set in the tx function */
1092 skb = pSendList->tx_agg_frames[0];
1093 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1094 tcb_desc->drv_agg_enable = 1;
1095 tcb_desc->pkt_size = skb->len;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001096 tcb_desc->DrvAggrNum = pSendList->nr_drv_agg_frames;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001097 netdev_dbg(dev, "DrvAggNum = %d\n", tcb_desc->DrvAggrNum);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001098 memcpy(agg_skb->cb, skb->cb, sizeof(skb->cb));
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001099 memcpy(skb_put(agg_skb, skb->len), skb->data, skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001100
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001101 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001102 /* push the next sub frame to be 256 byte aline */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001103 skb_put(agg_skb, DrvAggr_PaddingAdd(dev, skb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001104
1105 /* Subframe drv Tx descriptor and firmware info setting */
1106 skb = pSendList->tx_agg_frames[i];
1107 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Isaku Yamahataa267a602013-06-14 17:58:35 +09001108 tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)skb_tail_pointer(agg_skb);
1109 tx_fwinfo = (tx_fwinfo_819x_usb *)(skb_tail_pointer(agg_skb) + sizeof(tx_desc_819x_usb_aggr_subframe));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001110
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001111 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001112 /* DWORD 0 */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001113 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001114 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1115 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1116 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001117 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001118 tx_fwinfo->AllowAggregation = 1;
1119 /* DWORD 1 */
1120 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1121 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1122 } else {
1123 tx_fwinfo->AllowAggregation = 0;
1124 /* DWORD 1 */
1125 tx_fwinfo->RxMF = 0;
1126 tx_fwinfo->RxAMD = 0;
1127 }
1128
1129 /* Protection mode related */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001130 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1131 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1132 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1133 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001134 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001135 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->RTSSC) : 0;
1136 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1) ? ((tcb_desc->bRTSBW) ? 1 : 0) : 0;
1137 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) :
1138 (tcb_desc->bRTSUseShortGI ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001139
1140 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001141 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001142 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001143 tx_fwinfo->TxBandwidth = 1;
1144 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1145 } else {
1146 tx_fwinfo->TxBandwidth = 0;
1147 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1148 }
1149 } else {
1150 tx_fwinfo->TxBandwidth = 0;
1151 tx_fwinfo->TxSubCarrier = 0;
1152 }
1153
1154 /* Fill Tx descriptor */
1155 memset(tx_agg_desc, 0, sizeof(tx_desc_819x_usb_aggr_subframe));
1156 /* DWORD 0 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001157 tx_agg_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001158 /* already raw data, need not to subtract header length */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001159 tx_agg_desc->PktSize = skb->len & 0xffff;
1160
1161 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001162 tx_agg_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001163 tx_agg_desc->RATid = tcb_desc->RATRIndex;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001164 tx_agg_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001165 tx_agg_desc->SecType = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001166
1167 if (tcb_desc->bHwSec) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001168 switch (priv->ieee80211->pairwise_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001169 case KEY_TYPE_WEP40:
1170 case KEY_TYPE_WEP104:
1171 tx_agg_desc->SecType = 0x1;
1172 tx_agg_desc->NoEnc = 0;
1173 break;
1174 case KEY_TYPE_TKIP:
1175 tx_agg_desc->SecType = 0x2;
1176 tx_agg_desc->NoEnc = 0;
1177 break;
1178 case KEY_TYPE_CCMP:
1179 tx_agg_desc->SecType = 0x3;
1180 tx_agg_desc->NoEnc = 0;
1181 break;
1182 case KEY_TYPE_NA:
1183 tx_agg_desc->SecType = 0x0;
1184 tx_agg_desc->NoEnc = 1;
1185 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001186 }
1187 }
1188
1189 tx_agg_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1190 tx_agg_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1191
1192 tx_agg_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1193 tx_agg_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1194
1195 tx_agg_desc->OWN = 1;
1196
1197 //DWORD 2
1198 /* According windows driver, it seems that there no need to fill this field */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001199
1200 /* to fill next packet */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001201 skb_put(agg_skb, TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1202 memcpy(skb_put(agg_skb, skb->len), skb->data, skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001203 }
1204
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001205 for (i = 0; i < pSendList->nr_drv_agg_frames; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001206 dev_kfree_skb_any(pSendList->tx_agg_frames[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001207
1208 return agg_skb;
1209}
1210
1211/* NOTE:
1212 This function return a list of PTCB which is proper to be aggregate with the input TCB.
1213 If no proper TCB is found to do aggregation, SendList will only contain the input TCB.
1214*/
1215u8 DrvAggr_GetAggregatibleList(struct net_device *dev, struct sk_buff *skb,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001216 struct ieee80211_drv_agg_txb *pSendList)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001217{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001218 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001219 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1220 u16 nMaxAggrNum = pHTInfo->UsbTxAggrNum;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001221 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001222 u8 QueueID = tcb_desc->queue_index;
1223
1224 do {
1225 pSendList->tx_agg_frames[pSendList->nr_drv_agg_frames++] = skb;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001226 if (pSendList->nr_drv_agg_frames >= nMaxAggrNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001227 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001228
Xenia Ragiadakou53c7f3c2013-05-22 18:22:35 +03001229 } while ((skb = skb_dequeue(&ieee->skb_drv_aggQ[QueueID])));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001230
1231 RT_TRACE(COMP_AMSDU, "DrvAggr_GetAggregatibleList, nAggrTcbNum = %d \n", pSendList->nr_drv_agg_frames);
1232 return pSendList->nr_drv_agg_frames;
1233}
1234#endif
1235
Jerry Chuang8fc85982009-11-03 07:17:11 -02001236static void rtl8192_tx_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001237{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001238 struct sk_buff *skb = (struct sk_buff *)tx_urb->context;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001239 struct net_device *dev = NULL;
1240 struct r8192_priv *priv = NULL;
1241 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1242 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001243
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001244 memcpy(&dev, (struct net_device *)(skb->cb), sizeof(struct net_device *));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001245 priv = ieee80211_priv(dev);
1246
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001247 if (tcb_desc->queue_index != TXCMD_QUEUE) {
1248 if (tx_urb->status == 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001249 dev->trans_start = jiffies;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001250 priv->stats.txoktotal++;
1251 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
1252 priv->stats.txbytesunicast += (skb->len - priv->ieee80211->tx_headroom);
1253 } else {
1254 priv->ieee80211->stats.tx_errors++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001255 /* TODO */
1256 }
1257 }
1258
1259 /* free skb and tx_urb */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001260 if (skb != NULL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001261 dev_kfree_skb_any(skb);
1262 usb_free_urb(tx_urb);
1263 atomic_dec(&priv->tx_pending[queue_index]);
1264 }
1265
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001266 //
1267 // Handle HW Beacon:
1268 // We had transfer our beacon frame to host controller at this moment.
1269 //
1270 //
1271 // Caution:
1272 // Handling the wait queue of command packets.
1273 // For Tx command packets, we must not do TCB fragment because it is not handled right now.
1274 // We must cut the packets to match the size of TX_CMD_PKT before we send it.
1275 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02001276
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001277 /* Handle MPDU in wait queue. */
1278 if (queue_index != BEACON_QUEUE) {
1279 /* Don't send data frame during scanning.*/
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001280 if ((skb_queue_len(&priv->ieee80211->skb_waitQ[queue_index]) != 0) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001281 (!(priv->ieee80211->queue_stop))) {
Chi Pham09adb6e2014-03-10 22:31:52 +01001282 skb = skb_dequeue(&(priv->ieee80211->skb_waitQ[queue_index]));
1283 if (skb)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001284 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001285
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001286 return; //modified by david to avoid further processing AMSDU
Jerry Chuang8fc85982009-11-03 07:17:11 -02001287 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001288#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001289 else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index]) != 0) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001290 (!(priv->ieee80211->queue_stop))) {
1291 // Tx Driver Aggregation process
1292 /* The driver will aggregation the packets according to the following stats
1293 * 1. check whether there's tx irq available, for it's a completion return
1294 * function, it should contain enough tx irq;
1295 * 2. check packet type;
1296 * 3. initialize sendlist, check whether the to-be send packet no greater than 1
1297 * 4. aggregates the packets, and fill firmware info and tx desc into it, etc.
1298 * 5. check whether the packet could be sent, otherwise just insert into wait head
1299 * */
1300 skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]);
1301 if (!check_nic_enough_desc(dev, queue_index)) {
1302 skb_queue_head(&(priv->ieee80211->skb_drv_aggQ[queue_index]), skb);
1303 return;
1304 }
1305
1306 /*TODO*/
1307 {
1308 struct ieee80211_drv_agg_txb SendList;
1309
1310 memset(&SendList, 0, sizeof(struct ieee80211_drv_agg_txb));
1311 if (DrvAggr_GetAggregatibleList(dev, skb, &SendList) > 1) {
1312 skb = DrvAggr_Aggregation(dev, &SendList);
1313
1314 }
1315 }
1316 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1317 }
1318#endif
1319 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001320
Jerry Chuang8fc85982009-11-03 07:17:11 -02001321}
1322
Ana Reyf4c60742014-03-13 12:36:38 +01001323static void rtl8192_config_rate(struct net_device *dev, u16 *rate_config)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001324{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001325 struct r8192_priv *priv = ieee80211_priv(dev);
1326 struct ieee80211_network *net;
1327 u8 i = 0, basic_rate = 0;
Xenia Ragiadakou003a2d12013-06-04 23:32:29 +03001328 net = &priv->ieee80211->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001329
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001330 for (i = 0; i < net->rates_len; i++) {
1331 basic_rate = net->rates[i]&0x7f;
1332 switch (basic_rate) {
1333 case MGN_1M: *rate_config |= RRSR_1M; break;
1334 case MGN_2M: *rate_config |= RRSR_2M; break;
1335 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1336 case MGN_11M: *rate_config |= RRSR_11M; break;
1337 case MGN_6M: *rate_config |= RRSR_6M; break;
1338 case MGN_9M: *rate_config |= RRSR_9M; break;
1339 case MGN_12M: *rate_config |= RRSR_12M; break;
1340 case MGN_18M: *rate_config |= RRSR_18M; break;
1341 case MGN_24M: *rate_config |= RRSR_24M; break;
1342 case MGN_36M: *rate_config |= RRSR_36M; break;
1343 case MGN_48M: *rate_config |= RRSR_48M; break;
1344 case MGN_54M: *rate_config |= RRSR_54M; break;
1345 }
1346 }
1347 for (i = 0; i < net->rates_ex_len; i++) {
1348 basic_rate = net->rates_ex[i]&0x7f;
1349 switch (basic_rate) {
1350 case MGN_1M: *rate_config |= RRSR_1M; break;
1351 case MGN_2M: *rate_config |= RRSR_2M; break;
1352 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1353 case MGN_11M: *rate_config |= RRSR_11M; break;
1354 case MGN_6M: *rate_config |= RRSR_6M; break;
1355 case MGN_9M: *rate_config |= RRSR_9M; break;
1356 case MGN_12M: *rate_config |= RRSR_12M; break;
1357 case MGN_18M: *rate_config |= RRSR_18M; break;
1358 case MGN_24M: *rate_config |= RRSR_24M; break;
1359 case MGN_36M: *rate_config |= RRSR_36M; break;
1360 case MGN_48M: *rate_config |= RRSR_48M; break;
1361 case MGN_54M: *rate_config |= RRSR_54M; break;
1362 }
1363 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001364}
1365
1366
1367#define SHORT_SLOT_TIME 9
1368#define NON_SHORT_SLOT_TIME 20
1369
Ana Reyf4c60742014-03-13 12:36:38 +01001370static void rtl8192_update_cap(struct net_device *dev, u16 cap)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001371{
1372 u32 tmp = 0;
1373 struct r8192_priv *priv = ieee80211_priv(dev);
1374 struct ieee80211_network *net = &priv->ieee80211->current_network;
1375 priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
1376 tmp = priv->basic_rate;
1377 if (priv->short_preamble)
1378 tmp |= BRSR_AckShortPmb;
1379 write_nic_dword(dev, RRSR, tmp);
1380
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001381 if (net->mode & (IEEE_G|IEEE_N_24G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001382 u8 slot_time = 0;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001383 if ((cap & WLAN_CAPABILITY_SHORT_SLOT) && (!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime)) //short slot time
Jerry Chuang8fc85982009-11-03 07:17:11 -02001384 slot_time = SHORT_SLOT_TIME;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001385 else //long slot time
1386 slot_time = NON_SHORT_SLOT_TIME;
1387 priv->slot_time = slot_time;
1388 write_nic_byte(dev, SLOT_TIME, slot_time);
1389 }
1390
1391}
Ana Reyf4c60742014-03-13 12:36:38 +01001392static void rtl8192_net_update(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001393{
1394
1395 struct r8192_priv *priv = ieee80211_priv(dev);
1396 struct ieee80211_network *net;
1397 u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
1398 u16 rate_config = 0;
Xenia Ragiadakou003a2d12013-06-04 23:32:29 +03001399 net = &priv->ieee80211->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001400
1401 rtl8192_config_rate(dev, &rate_config);
1402 priv->basic_rate = rate_config &= 0x15f;
1403
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001404 write_nic_dword(dev, BSSIDR, ((u32 *)net->bssid)[0]);
1405 write_nic_word(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001406
1407 rtl8192_update_msr(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001408 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001409 write_nic_word(dev, ATIMWND, 2);
1410 write_nic_word(dev, BCN_DMATIME, 1023);
1411 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
1412 write_nic_word(dev, BCN_DRV_EARLY_INT, 1);
1413 write_nic_byte(dev, BCN_ERR_THRESH, 100);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001414 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001415 // TODO: BcnIFS may required to be changed on ASIC
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001416 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001417
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001418 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001419 }
1420
1421
1422
1423}
1424
1425//temporary hw beacon is not used any more.
1426//open it when necessary
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001427void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001428{
1429
Jerry Chuang8fc85982009-11-03 07:17:11 -02001430}
Jerry Chuang8fc85982009-11-03 07:17:11 -02001431inline u8 rtl8192_IsWirelessBMode(u16 rate)
1432{
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03001433 if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220))
Jerry Chuang8fc85982009-11-03 07:17:11 -02001434 return 1;
1435 else return 0;
1436}
1437
1438u16 N_DBPSOfRate(u16 DataRate);
1439
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03001440u16 ComputeTxTime(u16 FrameLength, u16 DataRate, u8 bManagementFrame,
1441 u8 bShortPreamble)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001442{
1443 u16 FrameTime;
1444 u16 N_DBPS;
1445 u16 Ceiling;
1446
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001447 if (rtl8192_IsWirelessBMode(DataRate)) {
1448 if (bManagementFrame || !bShortPreamble || DataRate == 10) // long preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001449 FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001450 else // Short preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001451 FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03001452 if ((FrameLength*8 % (DataRate/10)) != 0) //Get the Ceilling
Xenia Ragiadakou7d79ec62013-06-04 23:32:30 +03001453 FrameTime++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001454 } else { //802.11g DSSS-OFDM PLCP length field calculation.
1455 N_DBPS = N_DBPSOfRate(DataRate);
1456 Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001457 + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001458 FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
1459 }
1460 return FrameTime;
1461}
1462
1463u16 N_DBPSOfRate(u16 DataRate)
1464{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001465 u16 N_DBPS = 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001466
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001467 switch (DataRate) {
1468 case 60:
1469 N_DBPS = 24;
1470 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001471
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001472 case 90:
1473 N_DBPS = 36;
1474 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001475
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001476 case 120:
1477 N_DBPS = 48;
1478 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001479
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001480 case 180:
1481 N_DBPS = 72;
1482 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001483
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001484 case 240:
1485 N_DBPS = 96;
1486 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001487
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001488 case 360:
1489 N_DBPS = 144;
1490 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001491
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001492 case 480:
1493 N_DBPS = 192;
1494 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001495
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001496 case 540:
1497 N_DBPS = 216;
1498 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001499
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001500 default:
1501 break;
1502 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001503
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001504 return N_DBPS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001505}
1506
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001507unsigned int txqueue2outpipe(struct r8192_priv *priv, unsigned int tx_queue)
1508{
1509 if (tx_queue >= 9) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03001510 RT_TRACE(COMP_ERR, "%s():Unknown queue ID!!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001511 return 0x04;
1512 }
1513 return priv->txqueue_to_outpipemap[tx_queue];
1514}
1515
1516short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
1517{
1518 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001519 int status;
1520 struct urb *tx_urb;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001521 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001522 tx_desc_cmd_819x_usb *pdesc = (tx_desc_cmd_819x_usb *)skb->data;
1523 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1524 u8 queue_index = tcb_desc->queue_index;
1525
Jerry Chuang8fc85982009-11-03 07:17:11 -02001526 atomic_inc(&priv->tx_pending[queue_index]);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001527 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001528 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001529 dev_kfree_skb(skb);
1530 return -ENOMEM;
1531 }
1532
1533 memset(pdesc, 0, USB_HWDESC_HEADER_LEN);
1534 /* Tx descriptor ought to be set according to the skb->cb */
1535 pdesc->FirstSeg = 1;//bFirstSeg;
1536 pdesc->LastSeg = 1;//bLastSeg;
1537 pdesc->CmdInit = tcb_desc->bCmdOrInit;
1538 pdesc->TxBufferSize = tcb_desc->txbuf_size;
1539 pdesc->OWN = 1;
1540 pdesc->LINIP = tcb_desc->bLastIniPkt;
1541
1542 //----------------------------------------------------------------------------
1543 // Fill up USB_OUT_CONTEXT.
1544 //----------------------------------------------------------------------------
1545 // Get index to out pipe from specified QueueID.
1546#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001547 idx_pipe = txqueue2outpipe(priv, queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001548#else
1549 idx_pipe = 0x04;
1550#endif
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03001551 usb_fill_bulk_urb(tx_urb, priv->udev, usb_sndbulkpipe(priv->udev, idx_pipe),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001552 skb->data, skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001553
Jerry Chuang8fc85982009-11-03 07:17:11 -02001554 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001555
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001556 if (!status) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001557 return 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001558 } else {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001559 DMESGE("Error TX CMD URB, error %d", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001560 return -1;
1561 }
1562}
1563
1564/*
1565 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1566 * in TxFwInfo data structure
1567 * 2006.10.30 by Emily
1568 *
1569 * \param QUEUEID Software Queue
1570*/
Teodora Baluta46326d22013-10-16 01:59:17 +03001571static u8 MapHwQueueToFirmwareQueue(u8 QueueID)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001572{
1573 u8 QueueSelect = 0x0; //defualt set to
1574
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001575 switch (QueueID) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001576 case BE_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001577 QueueSelect = QSLT_BE;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001578 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001579
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001580 case BK_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001581 QueueSelect = QSLT_BK;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001582 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001583
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001584 case VO_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001585 QueueSelect = QSLT_VO;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001586 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001587
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001588 case VI_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001589 QueueSelect = QSLT_VI;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001590 break;
1591 case MGNT_QUEUE:
1592 QueueSelect = QSLT_MGNT;
1593 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001594
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001595 case BEACON_QUEUE:
1596 QueueSelect = QSLT_BEACON;
1597 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001598
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001599 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
1600 // TODO: Remove Assertions
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001601 case TXCMD_QUEUE:
1602 QueueSelect = QSLT_CMD;
1603 break;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001604 case HIGH_QUEUE:
1605 QueueSelect = QSLT_HIGH;
1606 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001607
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001608 default:
1609 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
1610 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001611 }
1612 return QueueSelect;
1613}
1614
Ana Reyf4c60742014-03-13 12:36:38 +01001615static u8 MRateToHwRate8190Pci(u8 rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001616{
1617 u8 ret = DESC90_RATE1M;
1618
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001619 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001620 case MGN_1M: ret = DESC90_RATE1M; break;
1621 case MGN_2M: ret = DESC90_RATE2M; break;
1622 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1623 case MGN_11M: ret = DESC90_RATE11M; break;
1624 case MGN_6M: ret = DESC90_RATE6M; break;
1625 case MGN_9M: ret = DESC90_RATE9M; break;
1626 case MGN_12M: ret = DESC90_RATE12M; break;
1627 case MGN_18M: ret = DESC90_RATE18M; break;
1628 case MGN_24M: ret = DESC90_RATE24M; break;
1629 case MGN_36M: ret = DESC90_RATE36M; break;
1630 case MGN_48M: ret = DESC90_RATE48M; break;
1631 case MGN_54M: ret = DESC90_RATE54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001632
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001633 // HT rate since here
1634 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1635 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1636 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1637 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1638 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1639 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1640 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1641 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1642 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1643 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1644 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1645 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1646 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1647 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1648 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1649 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1650 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001651
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001652 default: break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001653 }
1654 return ret;
1655}
1656
1657
Teodora Baluta46326d22013-10-16 01:59:17 +03001658static u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001659{
1660 u8 tmp_Short;
1661
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001662 tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) : ((tcb_desc->bUseShortPreamble) ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001663
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03001664 if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001665 tmp_Short = 0;
1666
1667 return tmp_Short;
1668}
1669
Jerry Chuang8fc85982009-11-03 07:17:11 -02001670static void tx_zero_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001671{
1672 return;
1673}
1674
1675/*
1676 * The tx procedure is just as following,
1677 * skb->cb will contain all the following information,
1678 * priority, morefrag, rate, &dev.
1679 * */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001680short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001681{
1682 struct r8192_priv *priv = ieee80211_priv(dev);
1683 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1684 tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data;
1685 tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
1686 struct usb_device *udev = priv->udev;
1687 int pend;
1688 int status;
1689 struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001690 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001691 pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]);
1692 /* we are locked here so the two atomic_read and inc are executed
1693 * without interleaves
1694 * !!! For debug purpose
1695 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001696 if (pend > MAX_TX_URB) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001697 netdev_dbg(dev, "To discard skb packet!\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001698 dev_kfree_skb_any(skb);
1699 return -1;
1700 }
1701
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001702 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001703 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001704 dev_kfree_skb_any(skb);
1705 return -ENOMEM;
1706 }
1707
1708 /* Fill Tx firmware info */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001709 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001710 /* DWORD 0 */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001711 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001712 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1713 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1714 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001715 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001716 tx_fwinfo->AllowAggregation = 1;
1717 /* DWORD 1 */
1718 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1719 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1720 } else {
1721 tx_fwinfo->AllowAggregation = 0;
1722 /* DWORD 1 */
1723 tx_fwinfo->RxMF = 0;
1724 tx_fwinfo->RxAMD = 0;
1725 }
1726
1727 /* Protection mode related */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001728 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1729 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1730 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1731 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001732 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001733 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->RTSSC) : 0;
1734 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1) ? ((tcb_desc->bRTSBW) ? 1 : 0) : 0;
1735 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) :
1736 (tcb_desc->bRTSUseShortGI ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001737
1738 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001739 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001740 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001741 tx_fwinfo->TxBandwidth = 1;
1742 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1743 } else {
1744 tx_fwinfo->TxBandwidth = 0;
1745 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1746 }
1747 } else {
1748 tx_fwinfo->TxBandwidth = 0;
1749 tx_fwinfo->TxSubCarrier = 0;
1750 }
1751
1752#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1753 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001754 tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001755#endif
1756 /* Fill Tx descriptor */
1757 memset(tx_desc, 0, sizeof(tx_desc_819x_usb));
1758 /* DWORD 0 */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001759 tx_desc->LINIP = 0;
1760 tx_desc->CmdInit = 1;
1761 tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001762
1763#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001764 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001765 tx_desc->PktSize = tcb_desc->pkt_size;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001766 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02001767#endif
1768 {
1769 tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff;
1770 }
1771
1772 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001773 tx_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001774 tx_desc->RATid = tcb_desc->RATRIndex;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001775 tx_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001776 tx_desc->SecType = 0x0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001777 if (tcb_desc->bHwSec) {
1778 switch (priv->ieee80211->pairwise_key_type) {
1779 case KEY_TYPE_WEP40:
1780 case KEY_TYPE_WEP104:
1781 tx_desc->SecType = 0x1;
1782 tx_desc->NoEnc = 0;
1783 break;
1784 case KEY_TYPE_TKIP:
1785 tx_desc->SecType = 0x2;
1786 tx_desc->NoEnc = 0;
1787 break;
1788 case KEY_TYPE_CCMP:
1789 tx_desc->SecType = 0x3;
1790 tx_desc->NoEnc = 0;
1791 break;
1792 case KEY_TYPE_NA:
1793 tx_desc->SecType = 0x0;
1794 tx_desc->NoEnc = 1;
1795 break;
1796 }
1797 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001798
1799 tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1800 tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1801
1802 tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1803 tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1804
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001805 /* Fill fields that are required to be initialized in all of the descriptors */
1806 //DWORD 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001807 tx_desc->FirstSeg = 1;
1808 tx_desc->LastSeg = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001809 tx_desc->OWN = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001810
1811#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1812 if (tcb_desc->drv_agg_enable) {
1813 tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb);
1814 } else
1815#endif
1816 {
1817 //DWORD 2
1818 tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN);
1819 }
1820 /* Get index to out pipe from specified QueueID */
1821#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001822 idx_pipe = txqueue2outpipe(priv, tcb_desc->queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001823#else
1824 idx_pipe = 0x5;
1825#endif
1826
Jerry Chuang8fc85982009-11-03 07:17:11 -02001827 /* To submit bulk urb */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001828 usb_fill_bulk_urb(tx_urb, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001829 usb_sndbulkpipe(udev, idx_pipe), skb->data,
1830 skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001831
Jerry Chuang8fc85982009-11-03 07:17:11 -02001832 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001833 if (!status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001834 //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 -02001835 bool bSend0Byte = false;
1836 u8 zero = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001837 if (udev->speed == USB_SPEED_HIGH) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001838 if (skb->len > 0 && skb->len % 512 == 0)
1839 bSend0Byte = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001840 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001841 if (skb->len > 0 && skb->len % 64 == 0)
1842 bSend0Byte = true;
1843 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001844 if (bSend0Byte) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001845 tx_urb_zero = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001846 if (!tx_urb_zero) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001847 RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
1848 return -ENOMEM;
1849 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001850 usb_fill_bulk_urb(tx_urb_zero, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001851 usb_sndbulkpipe(udev, idx_pipe), &zero,
1852 0, tx_zero_isr, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001853 status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001854 if (status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001855 RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
1856 return -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001857 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001858 }
1859 dev->trans_start = jiffies;
1860 atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
1861 return 0;
Patrik Karlin29b48ae2013-01-09 09:40:23 +01001862 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001863 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 +03001864 status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001865 return -1;
1866 }
1867}
1868
Teodora Baluta46326d22013-10-16 01:59:17 +03001869static short rtl8192_usb_initendpoints(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001870{
1871 struct r8192_priv *priv = ieee80211_priv(dev);
1872
Julia Lawall32414872010-05-11 20:26:57 +02001873 priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB+1),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001874 GFP_KERNEL);
David Chosrovab8345172010-12-01 13:42:16 +01001875 if (priv->rx_urb == NULL)
1876 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001877
1878#ifndef JACKSON_NEW_RX
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001879 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001880
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001881 priv->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001882
1883 priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL);
1884
1885 priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE;
1886 }
1887#endif
1888
1889#ifdef THOMAS_BEACON
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001890 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001891 long align = 0;
1892 void *oldaddr, *newaddr;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001893
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001894 priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
1895 priv->oldaddr = kmalloc(16, GFP_KERNEL);
1896 oldaddr = priv->oldaddr;
1897 align = ((long)oldaddr) & 3;
1898 if (align) {
1899 newaddr = oldaddr + 4 - align;
1900 priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align;
1901 } else {
1902 newaddr = oldaddr;
1903 priv->rx_urb[16]->transfer_buffer_length = 16;
1904 }
1905 priv->rx_urb[16]->transfer_buffer = newaddr;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001906 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001907#endif
1908
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001909 memset(priv->rx_urb, 0, sizeof(struct urb *) * MAX_RX_URB);
Julia Lawall7a6cb0d2010-05-13 22:00:05 +02001910 priv->pp_rxskb = kcalloc(MAX_RX_URB, sizeof(struct sk_buff *),
Julia Lawall32414872010-05-11 20:26:57 +02001911 GFP_KERNEL);
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001912 if (!priv->pp_rxskb) {
1913 kfree(priv->rx_urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001914
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001915 priv->pp_rxskb = NULL;
1916 priv->rx_urb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001917
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001918 DMESGE("Endpoint Alloc Failure");
1919 return -ENOMEM;
1920 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001921
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001922 netdev_dbg(dev, "End of initendpoints\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001923 return 0;
1924
1925}
1926#ifdef THOMAS_BEACON
Teodora Baluta46326d22013-10-16 01:59:17 +03001927static void rtl8192_usb_deleteendpoints(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001928{
1929 int i;
1930 struct r8192_priv *priv = ieee80211_priv(dev);
1931
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001932 if (priv->rx_urb) {
1933 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001934 usb_kill_urb(priv->rx_urb[i]);
1935 usb_free_urb(priv->rx_urb[i]);
1936 }
1937 kfree(priv->rx_urb);
1938 priv->rx_urb = NULL;
1939 }
Ilia Mirkine72714f2011-03-13 00:29:07 -05001940 kfree(priv->oldaddr);
1941 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001942 if (priv->pp_rxskb) {
1943 kfree(priv->pp_rxskb);
Sachin Kamat875d2a12013-10-09 15:58:30 +05301944 priv->pp_rxskb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001945 }
1946}
1947#else
1948void rtl8192_usb_deleteendpoints(struct net_device *dev)
1949{
1950 int i;
1951 struct r8192_priv *priv = ieee80211_priv(dev);
1952
1953#ifndef JACKSON_NEW_RX
1954
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001955 if (priv->rx_urb) {
1956 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001957 usb_kill_urb(priv->rx_urb[i]);
1958 kfree(priv->rx_urb[i]->transfer_buffer);
1959 usb_free_urb(priv->rx_urb[i]);
1960 }
1961 kfree(priv->rx_urb);
1962 priv->rx_urb = NULL;
1963
1964 }
1965#else
Ilia Mirkine72714f2011-03-13 00:29:07 -05001966 kfree(priv->rx_urb);
1967 priv->rx_urb = NULL;
1968 kfree(priv->oldaddr);
1969 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001970 if (priv->pp_rxskb) {
1971 kfree(priv->pp_rxskb);
1972 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001973
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001974 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001975
1976#endif
1977}
1978#endif
1979
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001980extern void rtl8192_update_ratr_table(struct net_device *dev);
Ana Reyf4c60742014-03-13 12:36:38 +01001981static void rtl8192_link_change(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001982{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001983 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001984 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001985 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001986 rtl8192_net_update(dev);
1987 rtl8192_update_ratr_table(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001988 //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
1989 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001990 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001991 }
1992 /*update timing params*/
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001993 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01001994 u32 reg = 0;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03001995 read_nic_dword(dev, RCR, &reg);
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01001996 if (priv->ieee80211->state == IEEE80211_LINKED)
1997 priv->ReceiveConfig = reg |= RCR_CBSSID;
1998 else
1999 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
2000 write_nic_dword(dev, RCR, reg);
2001 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002002}
2003
2004static struct ieee80211_qos_parameters def_qos_parameters = {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002005 {3, 3, 3, 3},/* cw_min */
2006 {7, 7, 7, 7},/* cw_max */
2007 {2, 2, 2, 2},/* aifs */
2008 {0, 0, 0, 0},/* flags */
2009 {0, 0, 0, 0} /* tx_op_limit */
Jerry Chuang8fc85982009-11-03 07:17:11 -02002010};
2011
2012
Ana Reyf4c60742014-03-13 12:36:38 +01002013static void rtl8192_update_beacon(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002014{
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002015 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
2016 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002017 struct ieee80211_device *ieee = priv->ieee80211;
2018 struct ieee80211_network *net = &ieee->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002019
2020 if (ieee->pHTInfo->bCurrentHTSupport)
2021 HTUpdateSelfAndPeerSetting(ieee, net);
2022 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
2023 rtl8192_update_cap(dev, net->capability);
2024}
2025/*
2026* background support to run QoS activate functionality
2027*/
Ana Reyf4c60742014-03-13 12:36:38 +01002028static int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, EDCAPARA_VO};
2029static void rtl8192_qos_activate(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002030{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002031 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
2032 struct net_device *dev = priv->ieee80211->dev;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002033 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2034 u8 mode = priv->ieee80211->current_network.mode;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002035 u8 u1bAIFS;
2036 u32 u4bAcParam;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002037 int i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002038
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002039 mutex_lock(&priv->mutex);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002040 if (priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002041 goto success;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002042 RT_TRACE(COMP_QOS, "qos active process with associate response received\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002043 /* It better set slot time at first */
2044 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2045 /* update the ac parameter to related registers */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002046 for (i = 0; i < QOS_QUEUE_NUM; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002047 //Mode G/A: slotTimeTimer = 9; Mode B: 20
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002048 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002049 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002050 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2051 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2052 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002053
2054 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002055 }
2056
2057success:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002058 mutex_unlock(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002059}
2060
2061static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002062 int active_network,
2063 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002064{
2065 int ret = 0;
2066 u32 size = sizeof(struct ieee80211_qos_parameters);
2067
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002068 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002069 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002070
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002071 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2072 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002073
2074 if (network->flags & NETWORK_HAS_QOS_MASK) {
2075 if (active_network &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002076 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
Jerry Chuang8fc85982009-11-03 07:17:11 -02002077 network->qos_data.active = network->qos_data.supported;
2078
2079 if ((network->qos_data.active == 1) && (active_network == 1) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002080 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2081 (network->qos_data.old_param_count !=
2082 network->qos_data.param_count)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002083 network->qos_data.old_param_count =
2084 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002085 queue_work(priv->priv_wq, &priv->qos_activate);
Xenia Ragiadakoue6367212013-05-23 05:14:46 +03002086 RT_TRACE(COMP_QOS, "QoS parameters change call "
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002087 "qos_activate\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002088 }
2089 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002090 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002091 &def_qos_parameters, size);
2092
2093 if ((network->qos_data.active == 1) && (active_network == 1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002094 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002095 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2096 }
2097 network->qos_data.active = 0;
2098 network->qos_data.supported = 0;
2099 }
2100
2101 return 0;
2102}
2103
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002104/* handle and manage frame from beacon and probe response */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002105static int rtl8192_handle_beacon(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002106 struct ieee80211_beacon *beacon,
2107 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002108{
2109 struct r8192_priv *priv = ieee80211_priv(dev);
2110
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002111 rtl8192_qos_handle_probe_response(priv, 1, network);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002112 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002113 return 0;
2114
2115}
2116
2117/*
2118* handling the beaconing responses. if we get different QoS setting
2119* off the network from the associated setting, adjust the QoS
2120* setting
2121*/
2122static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002123 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002124{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002125 int ret = 0;
2126 unsigned long flags;
2127 u32 size = sizeof(struct ieee80211_qos_parameters);
2128 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002129
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002130 if ((priv == NULL) || (network == NULL))
2131 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002132
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002133 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002134 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002135
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002136 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2137 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002138
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002139 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002140 if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002141 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002142 &network->qos_data.parameters,
2143 sizeof(struct ieee80211_qos_parameters));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002144 priv->ieee80211->current_network.qos_data.active = 1;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002145 set_qos_param = 1;
2146 /* update qos parameter for current network */
2147 priv->ieee80211->current_network.qos_data.old_param_count =
2148 priv->ieee80211->current_network.qos_data.param_count;
2149 priv->ieee80211->current_network.qos_data.param_count =
2150 network->qos_data.param_count;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002151 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002152 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002153 &def_qos_parameters, size);
2154 priv->ieee80211->current_network.qos_data.active = 0;
2155 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002156 set_qos_param = 1;
2157 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002158
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002159 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002160
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002161 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 -02002162 if (set_qos_param == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002163 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002164
2165
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002166 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002167}
2168
2169
2170static int rtl8192_handle_assoc_response(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002171 struct ieee80211_assoc_response_frame *resp,
2172 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002173{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002174 struct r8192_priv *priv = ieee80211_priv(dev);
2175 rtl8192_qos_association_resp(priv, network);
2176 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002177}
2178
2179
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002180void rtl8192_update_ratr_table(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002181{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002182 struct r8192_priv *priv = ieee80211_priv(dev);
2183 struct ieee80211_device *ieee = priv->ieee80211;
2184 u8 *pMcsRate = ieee->dot11HTOperationalRateSet;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002185 u32 ratr_value = 0;
2186 u8 rate_index = 0;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002187 rtl8192_config_rate(dev, (u16 *)(&ratr_value));
2188 ratr_value |= (*(u16 *)(pMcsRate)) << 12;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002189 switch (ieee->mode) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002190 case IEEE_A:
2191 ratr_value &= 0x00000FF0;
2192 break;
2193 case IEEE_B:
2194 ratr_value &= 0x0000000F;
2195 break;
2196 case IEEE_G:
2197 ratr_value &= 0x00000FF7;
2198 break;
2199 case IEEE_N_24G:
2200 case IEEE_N_5G:
2201 if (ieee->pHTInfo->PeerMimoPs == 0) {//MIMO_PS_STATIC
2202 ratr_value &= 0x0007F007;
2203 } else {
2204 if (priv->rf_type == RF_1T2R)
2205 ratr_value &= 0x000FF007;
2206 else
2207 ratr_value &= 0x0F81F007;
2208 }
2209 break;
2210 default:
2211 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002212 }
2213 ratr_value &= 0x0FFFFFFF;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002214 if (ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002215 ratr_value |= 0x80000000;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002216 else if (!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002217 ratr_value |= 0x80000000;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002218 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2219 write_nic_byte(dev, UFWP, 1);
2220}
2221
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002222static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04};
Jerry Chuang8fc85982009-11-03 07:17:11 -02002223static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
Teodora Baluta46326d22013-10-16 01:59:17 +03002224static bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002225{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002226 struct r8192_priv *priv = ieee80211_priv(dev);
2227 struct ieee80211_device *ieee = priv->ieee80211;
2228 struct ieee80211_network *network = &ieee->current_network;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002229 int wpa_ie_len = ieee->wpa_ie_len;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002230 struct ieee80211_crypt_data *crypt;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002231 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002232
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002233 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002234 //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 +03002235 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 -02002236
2237 /* simply judge */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002238 if (encrypt && (wpa_ie_len == 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002239 /* wep encryption, no N mode setting */
2240 return false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002241 } else if ((wpa_ie_len != 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002242 /* parse pairwise key type */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002243 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 -02002244 return true;
2245 else
2246 return false;
2247 } else {
2248 return true;
2249 }
2250
Jerry Chuang8fc85982009-11-03 07:17:11 -02002251 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002252}
2253
Ana Reyf4c60742014-03-13 12:36:38 +01002254static bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002255{
2256 bool Reval;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002257 struct r8192_priv *priv = ieee80211_priv(dev);
2258 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002259
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002260 if (ieee->bHalfWirelessN24GMode == true)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002261 Reval = true;
2262 else
2263 Reval = false;
2264
2265 return Reval;
2266}
2267
Ana Reyf4c60742014-03-13 12:36:38 +01002268static void rtl8192_refresh_supportrate(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002269{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002270 struct ieee80211_device *ieee = priv->ieee80211;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002271 //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002272 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002273 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002274 else
2275 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2276 return;
2277}
2278
Ana Reyf4c60742014-03-13 12:36:38 +01002279static u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002280{
2281 struct r8192_priv *priv = ieee80211_priv(dev);
2282 u8 ret = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002283 switch (priv->rf_chip) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002284 case RF_8225:
2285 case RF_8256:
2286 case RF_PSEUDO_11N:
2287 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2288 break;
2289 case RF_8258:
2290 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2291 break;
2292 default:
2293 ret = WIRELESS_MODE_B;
2294 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002295 }
2296 return ret;
2297}
Ana Reyf4c60742014-03-13 12:36:38 +01002298static void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002299{
2300 struct r8192_priv *priv = ieee80211_priv(dev);
2301 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2302
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002303 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode) == 0)) {
2304 if (bSupportMode & WIRELESS_MODE_N_24G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002305 wireless_mode = WIRELESS_MODE_N_24G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002306 } else if (bSupportMode & WIRELESS_MODE_N_5G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002307 wireless_mode = WIRELESS_MODE_N_5G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002308 } else if ((bSupportMode & WIRELESS_MODE_A)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002309 wireless_mode = WIRELESS_MODE_A;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002310 } else if ((bSupportMode & WIRELESS_MODE_G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002311 wireless_mode = WIRELESS_MODE_G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002312 } else if ((bSupportMode & WIRELESS_MODE_B)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002313 wireless_mode = WIRELESS_MODE_B;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002314 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002315 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __func__, bSupportMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002316 wireless_mode = WIRELESS_MODE_B;
2317 }
2318 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002319#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 +03002320 ActUpdateChannelAccessSetting(pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002321#endif
2322 priv->ieee80211->mode = wireless_mode;
2323
2324 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2325 priv->ieee80211->pHTInfo->bEnableHT = 1;
2326 else
2327 priv->ieee80211->pHTInfo->bEnableHT = 0;
2328 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2329 rtl8192_refresh_supportrate(priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002330
2331}
2332//init priv variables here. only non_zero value should be initialized here.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002333static void rtl8192_init_priv_variable(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002334{
2335 struct r8192_priv *priv = ieee80211_priv(dev);
2336 u8 i;
2337 priv->card_8192 = NIC_8192U;
2338 priv->chan = 1; //set to channel 1
2339 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2340 priv->ieee80211->iw_mode = IW_MODE_INFRA;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002341 priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002342 priv->retry_rts = DEFAULT_RETRY_RTS;
2343 priv->retry_data = DEFAULT_RETRY_DATA;
2344 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2345 priv->ieee80211->rate = 110; //11 mbps
2346 priv->ieee80211->short_slot = 1;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002347 priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002348 priv->CckPwEnl = 6;
2349 //for silent reset
2350 priv->IrpPendingCount = 1;
2351 priv->ResetProgress = RESET_TYPE_NORESET;
2352 priv->bForcedSilentReset = 0;
2353 priv->bDisableNormalResetCheck = false;
2354 priv->force_reset = false;
2355
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002356 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002357 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2358 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2359 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2360 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2361 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002362 IEEE_SOFTMAC_BEACONS;//added by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002363
2364 priv->ieee80211->active_scan = 1;
2365 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2366 priv->ieee80211->host_encrypt = 1;
2367 priv->ieee80211->host_decrypt = 1;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002368 priv->ieee80211->start_send_beacons = NULL; //-by amy 080604
2369 priv->ieee80211->stop_send_beacons = NULL; //-by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002370 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2371 priv->ieee80211->set_chan = rtl8192_set_chan;
2372 priv->ieee80211->link_change = rtl8192_link_change;
2373 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2374 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2375 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2376 priv->ieee80211->init_wmmparam_flag = 0;
2377 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2378 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2379 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
2380 priv->ieee80211->qos_support = 1;
2381
2382 //added by WB
Jerry Chuang8fc85982009-11-03 07:17:11 -02002383 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2384 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2385 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2386 //added by david
2387 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
2388 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
2389 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2390 //added by amy
2391 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
2392 priv->card_type = USB;
2393#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002394 if (Adapter->bInHctTest) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002395 pHalData->ShortRetryLimit = 7;
2396 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002397 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002398#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002399 priv->ShortRetryLimit = 0x30;
2400 priv->LongRetryLimit = 0x30;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002401 priv->EarlyRxThreshold = 7;
2402 priv->enable_gpio0 = 0;
2403 priv->TransmitConfig =
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002404 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002405 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
2406 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002407 (false ? TCR_SAT : 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
Jerry Chuang8fc85982009-11-03 07:17:11 -02002408#ifdef TO_DO_LIST
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002409 if (Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002410 pHalData->ReceiveConfig = pHalData->CSMethod |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002411 RCR_AMF | RCR_ADF | //accept management/data
Jerry Chuang8fc85982009-11-03 07:17:11 -02002412 //guangan200710
2413 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2414 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002415 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002416 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2417 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002418 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002419 else
2420
2421#endif
2422 priv->ReceiveConfig =
2423 RCR_AMF | RCR_ADF | //accept management/data
2424 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2425 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Jerry Chuang8fc85982009-11-03 07:17:11 -02002426 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2427 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002428 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002429
2430 priv->AcmControl = 0;
Devendra Nagab7553422012-08-26 11:06:33 +05302431 priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002432
2433 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002434 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002435 skb_queue_head_init(&priv->skb_queue);
2436
2437 /* Tx related queue */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002438 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002439 skb_queue_head_init(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002440 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002441 skb_queue_head_init(&priv->ieee80211->skb_aggQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002442 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002443 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002444 priv->rf_set_chan = rtl8192_phy_SwChnl;
2445}
2446
2447//init lock here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002448static void rtl8192_init_priv_lock(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002449{
2450 spin_lock_init(&priv->tx_lock);
2451 spin_lock_init(&priv->irq_lock);//added by thomas
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002452 sema_init(&priv->wx_sem, 1);
2453 sema_init(&priv->rf_sem, 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002454 mutex_init(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002455}
2456
Jerry Chuang8fc85982009-11-03 07:17:11 -02002457extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002458
2459void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
2460//init tasklet and wait_queue here. only 2.6 above kernel is considered
2461#define DRV_NAME "wlan0"
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002462static void rtl8192_init_priv_task(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002463{
2464 struct r8192_priv *priv = ieee80211_priv(dev);
2465
Jerry Chuang8fc85982009-11-03 07:17:11 -02002466 priv->priv_wq = create_workqueue(DRV_NAME);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002467
Jerry Chuang8fc85982009-11-03 07:17:11 -02002468 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2469
Jerry Chuang8fc85982009-11-03 07:17:11 -02002470 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2471 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002472 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2473 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2474 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002475 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002476
2477 tasklet_init(&priv->irq_rx_tasklet,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002478 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2479 (unsigned long)priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002480}
2481
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002482static void rtl8192_get_eeprom_size(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002483{
2484 u16 curCR = 0;
2485 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002486 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002487 read_nic_word_E(dev, EPROM_CMD, &curCR);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002488 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
2489 //whether need I consider BIT5?
2490 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002491 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __func__, priv->epromtype);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002492}
2493
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002494//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002495static inline u16 endian_swap(u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002496{
2497 u16 tmp = *data;
2498 *data = (tmp >> 8) | (tmp << 8);
2499 return *data;
2500}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002501static void rtl8192_read_eeprom_info(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002502{
2503 u16 wEPROM_ID = 0;
2504 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
2505 u8 bLoad_From_EEPOM = false;
2506 struct r8192_priv *priv = ieee80211_priv(dev);
2507 u16 tmpValue = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002508 int i;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002509 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002510 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
2511 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
2512
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002513 if (wEPROM_ID != RTL8190_EEPROM_ID) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002514 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 +03002515 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002516 bLoad_From_EEPOM = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002517 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002518
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002519 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002520 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
2521 priv->eeprom_vid = endian_swap(&tmpValue);
2522 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
2523 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002524 priv->eeprom_ChannelPlan = ((tmpValue&0xff00)>>8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002525 priv->btxpowerdata_readfromEEPORM = true;
2526 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002527 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002528 priv->eeprom_vid = 0;
2529 priv->eeprom_pid = 0;
2530 priv->card_8192_version = VERSION_819xU_B;
2531 priv->eeprom_ChannelPlan = 0;
2532 priv->eeprom_CustomerID = 0;
2533 }
2534 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);
2535 //set channelplan from eeprom
2536 priv->ChannelPlan = priv->eeprom_ChannelPlan;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002537 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002538 int i;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002539 for (i = 0; i < 6; i += 2) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002540 u16 tmp = 0;
2541 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002542 *(u16 *)(&dev->dev_addr[i]) = tmp;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002543 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002544 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002545 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2546 //should I set IDR0 here?
2547 }
Joe Perches0ee9f672009-12-06 11:34:52 -08002548 RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002549 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
2550 priv->rf_chip = RF_8256;
2551
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002552 if (priv->card_8192_version == (u8)VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002553 //read Tx power gain offset of legacy OFDM to HT rate
2554 if (bLoad_From_EEPOM)
2555 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
2556 else
2557 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
2558 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
2559 //read ThermalMeter from EEPROM
2560 if (bLoad_From_EEPOM)
2561 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
2562 else
2563 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2564 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
2565 //vivi, for tx power track
2566 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2567 //read antenna tx power offset of B/C/D to A from EEPROM
2568 if (bLoad_From_EEPOM)
2569 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
2570 else
2571 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
2572 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
2573 // Read CrystalCap from EEPROM
2574 if (bLoad_From_EEPOM)
2575 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
2576 else
2577 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
2578 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
2579 //get per-channel Tx power level
2580 if (bLoad_From_EEPOM)
2581 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
2582 else
2583 priv->EEPROM_Def_Ver = 1;
2584 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002585 if (priv->EEPROM_Def_Ver == 0) { //old eeprom definition
Jerry Chuang8fc85982009-11-03 07:17:11 -02002586 int i;
2587 if (bLoad_From_EEPOM)
2588 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
2589 else
2590 priv->EEPROMTxPowerLevelCCK = 0x10;
2591 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002592 for (i = 0; i < 3; i++) {
2593 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002594 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
2595 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
2596 tmpValue = tmpValue & 0x00ff;
2597 else
2598 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002599 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002600 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002601 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002602 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
2603 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
2604 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002605 } else if (priv->EEPROM_Def_Ver == 1) {
2606 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002607 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
2608 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002609 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002610 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002611 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002612 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
2613
2614 if (bLoad_From_EEPOM)
2615 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
2616 else
2617 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002618 *((u16 *)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002619 if (bLoad_From_EEPOM)
2620 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
2621 else
2622 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002623 *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002624 if (bLoad_From_EEPOM)
2625 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
2626 else
2627 tmpValue = 0x10;
2628 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
2629 }//endif EEPROM_Def_Ver == 1
2630
2631 //update HAL variables
2632 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002633 for (i = 0; i < 14; i++) {
2634 if (i <= 3)
2635 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
2636 else if (i >= 4 && i <= 9)
2637 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
2638 else
2639 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
2640 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002641
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002642 for (i = 0; i < 14; i++) {
2643 if (priv->EEPROM_Def_Ver == 0) {
2644 if (i <= 3)
2645 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2646 else if (i >= 4 && i <= 9)
2647 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
2648 else
2649 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2650 } else if (priv->EEPROM_Def_Ver == 1) {
2651 if (i <= 3)
2652 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
2653 else if (i >= 4 && i <= 9)
2654 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
2655 else
2656 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002657 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002658 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002659 priv->TxPowerDiff = priv->EEPROMPwDiff;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002660 // Antenna B gain offset to antenna A, bit0~3
Jerry Chuang8fc85982009-11-03 07:17:11 -02002661 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
2662 // Antenna C gain offset to antenna A, bit4~7
2663 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
2664 // CrystalCap, bit12~15
2665 priv->CrystalCap = priv->EEPROMCrystalCap;
2666 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
2667 // 92U does not enable TX power tracking.
2668 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
2669 }//end if VersionID == VERSION_819xU_A
2670
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002671 //added by vivi, for dlink led, 20080416
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002672 switch (priv->eeprom_CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002673 case EEPROM_CID_RUNTOP:
2674 priv->CustomerID = RT_CID_819x_RUNTOP;
2675 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002676
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002677 case EEPROM_CID_DLINK:
2678 priv->CustomerID = RT_CID_DLINK;
2679 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002680
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002681 default:
2682 priv->CustomerID = RT_CID_DEFAULT;
2683 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002684
2685 }
2686
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002687 switch (priv->CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002688 case RT_CID_819x_RUNTOP:
2689 priv->LedStrategy = SW_LED_MODE2;
2690 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002691
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002692 case RT_CID_DLINK:
2693 priv->LedStrategy = SW_LED_MODE4;
2694 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002695
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002696 default:
2697 priv->LedStrategy = SW_LED_MODE0;
2698 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002699
2700 }
2701
2702
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002703 if (priv->rf_type == RF_1T2R) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002704 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002705 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002706 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
2707 }
2708
2709 // 2008/01/16 MH We can only know RF type in the function. So we have to init
2710 // DIG RATR table again.
2711 init_rate_adaptive(dev);
2712 //we need init DIG RATR table here again.
2713
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002714 RT_TRACE(COMP_EPROM, "<===========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002715 return;
2716}
2717
Ana Reyf4c60742014-03-13 12:36:38 +01002718static short rtl8192_get_channel_map(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002719{
2720 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002721 if (priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03002722 netdev_err(dev, "rtl8180_init: Error channel plan! Set to default.\n");
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002723 priv->ChannelPlan = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002724 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002725 RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002726
2727 rtl819x_set_channel_map(priv->ChannelPlan, priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002728 return 0;
2729}
2730
Ana Reyf4c60742014-03-13 12:36:38 +01002731static short rtl8192_init(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002732{
2733
2734 struct r8192_priv *priv = ieee80211_priv(dev);
2735
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002736 memset(&(priv->stats), 0, sizeof(struct Stats));
2737 memset(priv->txqueue_to_outpipemap, 0, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002738#ifdef PIPE12
2739 {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002740 int i = 0;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002741 u8 queuetopipe[] = {3, 2, 1, 0, 4, 8, 7, 6, 5};
2742 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002743 }
2744#else
2745 {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002746 u8 queuetopipe[] = {3, 2, 1, 0, 4, 4, 0, 4, 4};
2747 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002748 }
2749#endif
2750 rtl8192_init_priv_variable(dev);
2751 rtl8192_init_priv_lock(priv);
2752 rtl8192_init_priv_task(dev);
2753 rtl8192_get_eeprom_size(dev);
2754 rtl8192_read_eeprom_info(dev);
2755 rtl8192_get_channel_map(dev);
2756 init_hal_dm(dev);
2757 init_timer(&priv->watch_dog_timer);
2758 priv->watch_dog_timer.data = (unsigned long)dev;
2759 priv->watch_dog_timer.function = watch_dog_timer_callback;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002760 if (rtl8192_usb_initendpoints(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002761 DMESG("Endopoints initialization failed");
2762 return -ENOMEM;
2763 }
2764
Jerry Chuang8fc85982009-11-03 07:17:11 -02002765#ifdef DEBUG_EPROM
2766 dump_eprom(dev);
2767#endif
2768 return 0;
2769}
2770
2771/******************************************************************************
2772 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
2773 * not to do all the hw config as its name says
2774 * input: net_device dev
2775 * output: none
2776 * return: none
2777 * notice: This part need to modified according to the rate set we filtered
2778 * ****************************************************************************/
Ana Reyf4c60742014-03-13 12:36:38 +01002779static void rtl8192_hwconfig(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002780{
2781 u32 regRATR = 0, regRRSR = 0;
2782 u8 regBwOpMode = 0, regTmp = 0;
2783 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002784 u32 ratr_value = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002785
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002786 // Set RRSR, RATR, and BW_OPMODE registers
Jerry Chuang8fc85982009-11-03 07:17:11 -02002787 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002788 switch (priv->ieee80211->mode) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002789 case WIRELESS_MODE_B:
2790 regBwOpMode = BW_OPMODE_20MHZ;
2791 regRATR = RATE_ALL_CCK;
2792 regRRSR = RATE_ALL_CCK;
2793 break;
2794 case WIRELESS_MODE_A:
2795 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
2796 regRATR = RATE_ALL_OFDM_AG;
2797 regRRSR = RATE_ALL_OFDM_AG;
2798 break;
2799 case WIRELESS_MODE_G:
2800 regBwOpMode = BW_OPMODE_20MHZ;
2801 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2802 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2803 break;
2804 case WIRELESS_MODE_AUTO:
2805#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002806 if (Adapter->bInHctTest) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002807 regBwOpMode = BW_OPMODE_20MHZ;
2808 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2809 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002810 }
2811 else
2812#endif
2813 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002814 regBwOpMode = BW_OPMODE_20MHZ;
2815 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2816 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002817 }
2818 break;
2819 case WIRELESS_MODE_N_24G:
2820 // It support CCK rate by default.
2821 // CCK rate will be filtered out only when associated AP does not support it.
2822 regBwOpMode = BW_OPMODE_20MHZ;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002823 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2824 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002825 break;
2826 case WIRELESS_MODE_N_5G:
2827 regBwOpMode = BW_OPMODE_5G;
2828 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2829 regRRSR = RATE_ALL_OFDM_AG;
2830 break;
2831 }
2832
2833 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002834 ratr_value = regRATR;
2835 if (priv->rf_type == RF_1T2R)
2836 ratr_value &= ~(RATE_ALL_OFDM_2SS);
2837 write_nic_dword(dev, RATR0, ratr_value);
2838 write_nic_byte(dev, UFWP, 1);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002839 read_nic_byte(dev, 0x313, &regTmp);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002840 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
2841 write_nic_dword(dev, RRSR, regRRSR);
2842
2843 //
2844 // Set Retry Limit here
2845 //
2846 write_nic_word(dev, RETRY_LIMIT,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002847 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
2848 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002849 // Set Contention Window here
2850
2851 // Set Tx AGC
2852
2853 // Set Tx Antenna including Feedback control
2854
2855 // Set Auto Rate fallback control
2856
2857
2858}
2859
2860
2861//InitializeAdapter and PhyCfg
Ana Reyf4c60742014-03-13 12:36:38 +01002862static bool rtl8192_adapter_start(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002863{
2864 struct r8192_priv *priv = ieee80211_priv(dev);
2865 u32 dwRegRead = 0;
2866 bool init_status = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002867 u8 SECR_value = 0x0;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002868 u8 tmp;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002869 RT_TRACE(COMP_INIT, "====>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002870 priv->Rf_Mode = RF_OP_By_SW_3wire;
2871 //for ASIC power on sequence
2872 write_nic_byte_E(dev, 0x5f, 0x80);
2873 mdelay(50);
2874 write_nic_byte_E(dev, 0x5f, 0xf0);
2875 write_nic_byte_E(dev, 0x5d, 0x00);
2876 write_nic_byte_E(dev, 0x5e, 0x80);
2877 write_nic_byte(dev, 0x17, 0x37);
2878 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002879 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
2880 //config CPUReset Register
2881 //Firmware Reset or not?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002882 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002883 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
2884 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
2885 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
2886 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
2887 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002888 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __func__, priv->pFirmware->firmware_status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002889
2890 write_nic_dword(dev, CPU_GEN, dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002891 //config BB.
2892 rtl8192_BBConfig(dev);
2893
Jerry Chuang8fc85982009-11-03 07:17:11 -02002894 //Loopback mode or not
2895 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002896
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002897 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002898 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
2899 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
2900 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
2901 dwRegRead |= CPU_CCK_LOOPBACK;
2902 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002903 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __func__, priv->LoopbackMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002904
2905 write_nic_dword(dev, CPU_GEN, dwRegRead);
2906
2907 //after reset cpu, we need wait for a seconds to write in register.
2908 udelay(500);
2909
2910 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002911 read_nic_byte_E(dev, 0x5f, &tmp);
2912 write_nic_byte_E(dev, 0x5f, tmp|0x20);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002913
2914 //Set Hardware
2915 rtl8192_hwconfig(dev);
2916
2917 //turn on Tx/Rx
2918 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
2919
2920 //set IDR0 here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002921 write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
2922 write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002923
2924 //set RCR
2925 write_nic_dword(dev, RCR, priv->ReceiveConfig);
2926
2927 //Initialize Number of Reserved Pages in Firmware Queue
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002928 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 +03002929 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT |
2930 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT |
2931 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002932 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 +03002933 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002934 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002935 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002936 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
2937
2938 //Set AckTimeout
2939 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
2940 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
2941
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002942 if (priv->ResetProgress == RESET_TYPE_NORESET)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002943 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002944 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002945 CamResetAllEntry(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002946 SECR_value |= SCR_TxEncEnable;
2947 SECR_value |= SCR_RxDecEnable;
2948 SECR_value |= SCR_NoSKMC;
2949 write_nic_byte(dev, SECR, SECR_value);
2950 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002951
2952 //Beacon related
2953 write_nic_word(dev, ATIMWND, 2);
2954 write_nic_word(dev, BCN_INTERVAL, 100);
2955
Jerry Chuang8fc85982009-11-03 07:17:11 -02002956#define DEFAULT_EDCA 0x005e4332
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002957 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002958 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002959 for (i = 0; i < QOS_QUEUE_NUM; i++)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002960 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002961 }
2962#ifdef USB_RX_AGGREGATION_SUPPORT
2963 //3 For usb rx firmware aggregation control
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002964 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002965 u32 ulValue;
2966 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
2967 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002968 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002969 /*
2970 * If usb rx firmware aggregation is enabled,
2971 * when anyone of three threshold conditions above is reached,
2972 * firmware will send aggregated packet to driver.
2973 */
2974 write_nic_dword(dev, 0x1a8, ulValue);
2975 priv->bCurrentRxAggrEnable = true;
2976 }
2977#endif
2978
2979 rtl8192_phy_configmac(dev);
2980
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002981 if (priv->card_8192_version == (u8) VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002982 rtl8192_phy_getTxPower(dev);
2983 rtl8192_phy_setTxPower(dev, priv->chan);
2984 }
2985
2986 //Firmware download
2987 init_status = init_firmware(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002988 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002989 RT_TRACE(COMP_ERR, "ERR!!! %s(): Firmware download is failed\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002990 return init_status;
2991 }
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002992 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002993 //
2994#ifdef TO_DO_LIST
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002995 if (Adapter->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002996 if (pMgntInfo->RegRfOff == TRUE) { // User disable RF via registry.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002997 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
2998 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07002999 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003000 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003001 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003002 } else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { // H/W or S/W RF OFF before sleep.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003003 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
3004 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003005 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003006 pHalData->eRFPowerState = eRfOn;
3007 pMgntInfo->RfOffReason = 0;
3008 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
3009 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003010 } else {
3011 if (pHalData->eRFPowerState == eRfOff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003012 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003013 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003014 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003015 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3016 }
3017 }
3018#endif
3019 //config RF.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003020 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003021 rtl8192_phy_RFConfig(dev);
3022 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003023 }
3024
3025
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003026 if (priv->ieee80211->FwRWRF)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003027 // We can force firmware to do RF-R/W
3028 priv->Rf_Mode = RF_OP_By_FW;
3029 else
3030 priv->Rf_Mode = RF_OP_By_SW_3wire;
3031
3032
3033 rtl8192_phy_updateInitGain(dev);
3034 /*--set CCK and OFDM Block "ON"--*/
3035 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3036 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3037
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003038 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003039 //if D or C cut
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003040 u8 tmpvalue;
3041 read_nic_byte(dev, 0x301, &tmpvalue);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003042 if (tmpvalue == 0x03) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003043 priv->bDcut = TRUE;
3044 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003045 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003046 priv->bDcut = FALSE;
3047 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
3048 }
3049 dm_initialize_txpower_tracking(dev);
3050
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003051 if (priv->bDcut == TRUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003052 u32 i, TempCCk;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003053 u32 tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003054 for (i = 0; i < TxBBGainTableLength; i++) {
3055 if (tmpRegA == priv->txbbgain_table[i].txbbgain_value) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003056 priv->rfa_txpowertrackingindex = (u8)i;
3057 priv->rfa_txpowertrackingindex_real = (u8)i;
3058 priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003059 break;
3060 }
3061 }
3062
3063 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3064
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003065 for (i = 0; i < CCKTxBBGainTableLength; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003066
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003067 if (TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0]) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003068 priv->cck_present_attentuation_20Mdefault = (u8) i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003069 break;
3070 }
3071 }
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003072 priv->cck_present_attentuation_40Mdefault = 0;
3073 priv->cck_present_attentuation_difference = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003074 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
3075
Jerry Chuang8fc85982009-11-03 07:17:11 -02003076 }
3077 }
3078 write_nic_byte(dev, 0x87, 0x0);
3079
3080
Jerry Chuang8fc85982009-11-03 07:17:11 -02003081 return init_status;
3082}
3083
3084/* this configures registers for beacon tx and enables it via
3085 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3086 * be used to stop beacon transmission
3087 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003088/***************************************************************************
3089 -------------------------------NET STUFF---------------------------
3090***************************************************************************/
3091
3092static struct net_device_stats *rtl8192_stats(struct net_device *dev)
3093{
3094 struct r8192_priv *priv = ieee80211_priv(dev);
3095
3096 return &priv->ieee80211->stats;
3097}
3098
Teodora Baluta46326d22013-10-16 01:59:17 +03003099static bool HalTxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003100{
3101 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003102 u16 RegTxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003103 bool bStuck = FALSE;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003104 read_nic_word(dev, 0x128, &RegTxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003105 RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", __func__, RegTxCounter, priv->TxCounter);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003106 if (priv->TxCounter == RegTxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003107 bStuck = TRUE;
3108
3109 priv->TxCounter = RegTxCounter;
3110
3111 return bStuck;
3112}
3113
3114/*
3115* <Assumption: RT_TX_SPINLOCK is acquired.>
3116* First added: 2006.11.19 by emily
3117*/
Ana Reyf4c60742014-03-13 12:36:38 +01003118static RESET_TYPE TxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003119{
3120 struct r8192_priv *priv = ieee80211_priv(dev);
3121 u8 QueueID;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003122 bool bCheckFwTxCnt = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003123
3124 //
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003125 // Decide such threshold according to current power save mode
Jerry Chuang8fc85982009-11-03 07:17:11 -02003126 //
3127
Xenia Ragiadakou7d79ec62013-06-04 23:32:30 +03003128 for (QueueID = 0; QueueID <= BEACON_QUEUE; QueueID++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003129 if (QueueID == TXCMD_QUEUE)
3130 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003131#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003132 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 -02003133#else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003134 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 -02003135#endif
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003136 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003137
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003138 bCheckFwTxCnt = true;
3139 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003140 if (bCheckFwTxCnt) {
3141 if (HalTxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003142 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
3143 return RESET_TYPE_SILENT;
3144 }
3145 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003146 return RESET_TYPE_NORESET;
3147}
3148
Teodora Baluta46326d22013-10-16 01:59:17 +03003149static bool HalRxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003150{
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003151 u16 RegRxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003152 struct r8192_priv *priv = ieee80211_priv(dev);
3153 bool bStuck = FALSE;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003154 static u8 rx_chk_cnt;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003155 read_nic_word(dev, 0x130, &RegRxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003156 RT_TRACE(COMP_RESET, "%s(): RegRxCounter is %d,RxCounter is %d\n", __func__, RegRxCounter, priv->RxCounter);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003157 // If rssi is small, we should check rx for long time because of bad rx.
3158 // or maybe it will continuous silent reset every 2 seconds.
3159 rx_chk_cnt++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003160 if (priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003161 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003162 } else if (priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003163 ((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_40M) ||
3164 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_20M))) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003165 if (rx_chk_cnt < 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003166 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003167 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003168 rx_chk_cnt = 0;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003169 } else if (((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_40M) ||
3170 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_20M)) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003171 priv->undecorated_smoothed_pwdb >= VeryLowRSSI) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003172 if (rx_chk_cnt < 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003173 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003174 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003175 rx_chk_cnt = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003176 } else {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003177 if (rx_chk_cnt < 8)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003178 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003179 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003180 rx_chk_cnt = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003181 }
3182
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003183 if (priv->RxCounter == RegRxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003184 bStuck = TRUE;
3185
3186 priv->RxCounter = RegRxCounter;
3187
3188 return bStuck;
3189}
3190
Teodora Baluta46326d22013-10-16 01:59:17 +03003191static RESET_TYPE RxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003192{
3193 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003194 bool bRxCheck = FALSE;
3195
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003196 if (priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003197 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003198
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003199 if (bRxCheck) {
3200 if (HalRxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003201 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
3202 return RESET_TYPE_SILENT;
3203 }
3204 }
3205 return RESET_TYPE_NORESET;
3206}
3207
3208
3209/**
3210* This function is called by Checkforhang to check whether we should ask OS to reset driver
3211*
3212* \param pAdapter The adapter context for this miniport
3213*
3214* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
3215* to judge whether there is tx stuck.
3216* Note: This function may be required to be rewrite for Vista OS.
3217* <<<Assumption: Tx spinlock has been acquired >>>
3218*
3219* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
3220*/
Ana Reyf4c60742014-03-13 12:36:38 +01003221static RESET_TYPE rtl819x_ifcheck_resetornot(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003222{
3223 struct r8192_priv *priv = ieee80211_priv(dev);
3224 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
3225 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003226 RT_RF_POWER_STATE rfState;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003227
3228 rfState = priv->ieee80211->eRFPowerState;
3229
3230 TxResetType = TxCheckStuck(dev);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003231 if (rfState != eRfOff ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003232 (priv->ieee80211->iw_mode != IW_MODE_ADHOC)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003233 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
3234 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
3235 // if driver is in firmware download failure status, driver should initialize RF in the following
3236 // silent reset procedure Emily, 2008.01.21
3237
3238 // Driver should not check RX stuck in IBSS mode because it is required to
3239 // set Check BSSID in order to send beacon, however, if check BSSID is
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003240 // set, STA cannot hear any packet at all. Emily, 2008.04.12
Jerry Chuang8fc85982009-11-03 07:17:11 -02003241 RxResetType = RxCheckStuck(dev);
3242 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003243 if (TxResetType == RESET_TYPE_NORMAL || RxResetType == RESET_TYPE_NORMAL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003244 return RESET_TYPE_NORMAL;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003245 } else if (TxResetType == RESET_TYPE_SILENT || RxResetType == RESET_TYPE_SILENT) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003246 RT_TRACE(COMP_RESET, "%s():silent reset\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003247 return RESET_TYPE_SILENT;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003248 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003249 return RESET_TYPE_NORESET;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003250 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003251
3252}
3253
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003254void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003255int _rtl8192_up(struct net_device *dev);
3256int rtl8192_close(struct net_device *dev);
3257
3258
3259
Ana Reyf4c60742014-03-13 12:36:38 +01003260static void CamRestoreAllEntry(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003261{
3262 u8 EntryId = 0;
3263 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003264 u8 *MacAddr = priv->ieee80211->current_network.bssid;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003265
3266 static u8 CAM_CONST_ADDR[4][6] = {
3267 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3268 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
3269 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03003270 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003271 static u8 CAM_CONST_BROAD[] = {
3272 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003273
3274 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
3275
3276
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003277 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40) ||
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003278 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003279
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003280 for (EntryId = 0; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003281 MacAddr = CAM_CONST_ADDR[EntryId];
3282 setKey(dev, EntryId, EntryId,
3283 priv->ieee80211->pairwise_key_type,
3284 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003285 }
3286
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003287 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003288
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003289 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3290 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3291 (u8 *)dev->dev_addr, 0, NULL);
3292 else
3293 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3294 MacAddr, 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003295 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003296
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003297 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3298 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3299 (u8 *)dev->dev_addr, 0, NULL);
3300 else
3301 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3302 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003303 }
3304
3305
3306
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003307 if (priv->ieee80211->group_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003308 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003309 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003310 setKey(dev, EntryId, EntryId,
3311 priv->ieee80211->group_key_type,
3312 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003313 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003314 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003315 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3316 CAM_CONST_ADDR[0], 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003317 } else if (priv->ieee80211->group_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003318 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003319 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003320 setKey(dev, EntryId, EntryId,
3321 priv->ieee80211->group_key_type,
3322 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003323 }
3324
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003325 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003326 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3327 CAM_CONST_ADDR[0], 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003328 }
3329}
3330//////////////////////////////////////////////////////////////
3331// This function is used to fix Tx/Rx stop bug temporarily.
3332// This function will do "system reset" to NIC when Tx or Rx is stuck.
3333// The method checking Tx/Rx stuck of this function is supported by FW,
3334// which reports Tx and Rx counter to register 0x128 and 0x130.
3335//////////////////////////////////////////////////////////////
Ana Reyf4c60742014-03-13 12:36:38 +01003336static void rtl819x_ifsilentreset(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003337{
Jerry Chuang8fc85982009-11-03 07:17:11 -02003338 struct r8192_priv *priv = ieee80211_priv(dev);
3339 u8 reset_times = 0;
3340 int reset_status = 0;
3341 struct ieee80211_device *ieee = priv->ieee80211;
3342
3343
3344 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
3345 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
3346
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003347 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003348RESET_START:
3349
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003350 RT_TRACE(COMP_RESET, "=========>Reset progress!! \n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003351
3352 // Set the variable for reset.
3353 priv->ResetProgress = RESET_TYPE_SILENT;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003354 down(&priv->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003355 if (priv->up == 0) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003356 RT_TRACE(COMP_ERR, "%s():the driver is not up! return\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003357 up(&priv->wx_sem);
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003358 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003359 }
3360 priv->up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003361 RT_TRACE(COMP_RESET, "%s():======>start to down the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003362
3363 rtl8192_rtx_disable(dev);
3364 rtl8192_cancel_deferred_work(priv);
3365 deinit_hal_dm(dev);
3366 del_timer_sync(&priv->watch_dog_timer);
3367
3368 ieee->sync_scan_hurryup = 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003369 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003370 down(&ieee->wx_sem);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003371 netdev_dbg(dev, "ieee->state is IEEE80211_LINKED\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003372 ieee80211_stop_send_beacons(priv->ieee80211);
3373 del_timer_sync(&ieee->associate_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003374 cancel_delayed_work(&ieee->associate_retry_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003375 ieee80211_stop_scan(ieee);
3376 netif_carrier_off(dev);
3377 up(&ieee->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003378 } else {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003379 netdev_dbg(dev, "ieee->state is NOT LINKED\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003380 ieee80211_softmac_stop_protocol(priv->ieee80211);
3381 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003382 up(&priv->wx_sem);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003383 RT_TRACE(COMP_RESET, "%s():<==========down process is finished\n", __func__);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003384 RT_TRACE(COMP_RESET, "%s():===========>start up the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003385 reset_status = _rtl8192_up(dev);
3386
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003387 RT_TRACE(COMP_RESET, "%s():<===========up process is finished\n", __func__);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003388 if (reset_status == -EAGAIN) {
3389 if (reset_times < 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003390 reset_times++;
3391 goto RESET_START;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003392 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003393 RT_TRACE(COMP_ERR, " ERR!!! %s(): Reset Failed!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003394 }
3395 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003396 ieee->is_silent_reset = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003397 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003398 if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003399 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3400
Jerry Chuang8fc85982009-11-03 07:17:11 -02003401 queue_work(ieee->wq, &ieee->associate_complete_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003402
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003403 } else if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003404 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3405 ieee->link_change(ieee->dev);
3406
Jerry Chuang8fc85982009-11-03 07:17:11 -02003407 ieee80211_start_send_beacons(ieee);
3408
3409 if (ieee->data_hard_resume)
3410 ieee->data_hard_resume(ieee->dev);
3411 netif_carrier_on(ieee->dev);
3412 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003413
3414 CamRestoreAllEntry(dev);
3415
3416 priv->ResetProgress = RESET_TYPE_NORESET;
3417 priv->reset_count++;
3418
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003419 priv->bForcedSilentReset = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003420 priv->bResetInProgress = false;
3421
3422 // For test --> force write UFWP.
3423 write_nic_byte(dev, UFWP, 1);
3424 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003425 }
3426}
3427
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003428void CAM_read_entry(struct net_device *dev, u32 iIndex)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003429{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003430 u32 target_command = 0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003431 u32 target_content = 0;
3432 u8 entry_i = 0;
3433 u32 ulStatus;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003434 s32 i = 100;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003435 for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003436 // polling bit, and No Write enable, and address
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003437 target_command = entry_i+CAM_CONTENT_COUNT*iIndex;
3438 target_command = target_command | BIT31;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003439
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003440 //Check polling bit is clear
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003441 while ((i--) >= 0) {
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003442 read_nic_dword(dev, RWCAM, &ulStatus);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003443 if (ulStatus & BIT31)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003444 continue;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003445 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003446 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003447 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003448 write_nic_dword(dev, RWCAM, target_command);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003449 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x \n", target_command);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003450 read_nic_dword(dev, RCAMO, &target_content);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003451 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n", target_content);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003452 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003453 printk("\n");
3454}
3455
Ana Reyf4c60742014-03-13 12:36:38 +01003456static void rtl819x_update_rxcounts(struct r8192_priv *priv, u32 *TotalRxBcnNum,
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003457 u32 *TotalRxDataNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003458{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003459 u16 SlotIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003460 u8 i;
3461
3462 *TotalRxBcnNum = 0;
3463 *TotalRxDataNum = 0;
3464
3465 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
3466 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
3467 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003468 for (i = 0; i < priv->ieee80211->LinkDetectInfo.SlotNum; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003469 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
3470 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
3471 }
3472}
3473
3474
Himangi Saraogid16e05f2014-03-09 04:21:41 +05303475void rtl819x_watchdog_wqcallback(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003476{
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003477 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003478 struct r8192_priv *priv = container_of(dwork, struct r8192_priv, watch_dog_wq);
3479 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003480 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003481 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003482 static u8 check_reset_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003483 bool bBusyTraffic = false;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003484 u32 TotalRxBcnNum = 0;
3485 u32 TotalRxDataNum = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003486
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003487 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003488 return;
3489 hal_dm_watchdog(dev);
3490
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003491 //to get busy traffic condition
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003492 if (ieee->state == IEEE80211_LINKED) {
3493 if (ieee->LinkDetectInfo.NumRxOkInPeriod > 666 ||
3494 ieee->LinkDetectInfo.NumTxOkInPeriod > 666 ) {
3495 bBusyTraffic = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003496 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003497 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
3498 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
3499 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
3500 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003501 //added by amy for AP roaming
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003502 if (priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003503
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003504 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
3505 if ((TotalRxBcnNum+TotalRxDataNum) == 0) {
3506#ifdef TODO
3507 if (rfState == eRfOff)
3508 RT_TRACE(COMP_ERR, "========>%s()\n", __func__);
3509#endif
3510 netdev_dbg(dev, "===>%s(): AP is power off, connect another one\n", __func__);
3511 priv->ieee80211->state = IEEE80211_ASSOCIATING;
3512 notify_wx_assoc_event(priv->ieee80211);
3513 RemovePeerTS(priv->ieee80211, priv->ieee80211->current_network.bssid);
3514 priv->ieee80211->link_change(dev);
3515 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003516
Jerry Chuang8fc85982009-11-03 07:17:11 -02003517 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003518 }
3519 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod = 0;
3520 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003521 //check if reset the driver
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003522 if (check_reset_cnt++ >= 3) {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003523 ResetType = rtl819x_ifcheck_resetornot(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003524 check_reset_cnt = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003525 }
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003526 if ((priv->force_reset) || (priv->ResetProgress == RESET_TYPE_NORESET &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003527 (priv->bForcedSilentReset ||
3528 (!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_SILENT)))) { // This is control by OID set in Pomelo
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003529 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 -02003530 rtl819x_ifsilentreset(dev);
3531 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003532 priv->force_reset = false;
3533 priv->bForcedSilentReset = false;
3534 priv->bResetInProgress = false;
3535 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
3536
3537}
3538
3539void watch_dog_timer_callback(unsigned long data)
3540{
3541 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003542 queue_delayed_work(priv->priv_wq, &priv->watch_dog_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003543 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
Jerry Chuang8fc85982009-11-03 07:17:11 -02003544}
3545int _rtl8192_up(struct net_device *dev)
3546{
3547 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003548 int init_status = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003549 priv->up = 1;
3550 priv->ieee80211->ieee_up = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003551 RT_TRACE(COMP_INIT, "Bringing up iface");
3552 init_status = rtl8192_adapter_start(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003553 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003554 RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization failed!\n", __func__);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003555 priv->up = priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003556 return -EAGAIN;
3557 }
3558 RT_TRACE(COMP_INIT, "start adapter finished\n");
3559 rtl8192_rx_enable(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003560 if (priv->ieee80211->state != IEEE80211_LINKED)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003561 ieee80211_softmac_start_protocol(priv->ieee80211);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003562 ieee80211_reset_queue(priv->ieee80211);
3563 watch_dog_timer_callback((unsigned long) dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003564 if (!netif_queue_stopped(dev))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003565 netif_start_queue(dev);
3566 else
3567 netif_wake_queue(dev);
3568
3569 return 0;
3570}
3571
3572
Ana Reyf4c60742014-03-13 12:36:38 +01003573static int rtl8192_open(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003574{
3575 struct r8192_priv *priv = ieee80211_priv(dev);
3576 int ret;
3577 down(&priv->wx_sem);
3578 ret = rtl8192_up(dev);
3579 up(&priv->wx_sem);
3580 return ret;
3581
3582}
3583
3584
3585int rtl8192_up(struct net_device *dev)
3586{
3587 struct r8192_priv *priv = ieee80211_priv(dev);
3588
3589 if (priv->up == 1) return -1;
3590
3591 return _rtl8192_up(dev);
3592}
3593
3594
3595int rtl8192_close(struct net_device *dev)
3596{
3597 struct r8192_priv *priv = ieee80211_priv(dev);
3598 int ret;
3599
3600 down(&priv->wx_sem);
3601
3602 ret = rtl8192_down(dev);
3603
3604 up(&priv->wx_sem);
3605
3606 return ret;
3607
3608}
3609
3610int rtl8192_down(struct net_device *dev)
3611{
3612 struct r8192_priv *priv = ieee80211_priv(dev);
3613 int i;
3614
3615 if (priv->up == 0) return -1;
3616
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003617 priv->up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003618 priv->ieee80211->ieee_up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003619 RT_TRACE(COMP_DOWN, "==========>%s()\n", __func__);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003620 /* FIXME */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003621 if (!netif_queue_stopped(dev))
3622 netif_stop_queue(dev);
3623
3624 rtl8192_rtx_disable(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003625
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003626 /* Tx related queue release */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003627 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003628 skb_queue_purge(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003629 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003630 skb_queue_purge(&priv->ieee80211->skb_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003631
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003632 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003633 skb_queue_purge(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003634
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003635 //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 -02003636 rtl8192_cancel_deferred_work(priv);
3637 deinit_hal_dm(dev);
3638 del_timer_sync(&priv->watch_dog_timer);
3639
3640
3641 ieee80211_softmac_stop_protocol(priv->ieee80211);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003642 memset(&priv->ieee80211->current_network, 0, offsetof(struct ieee80211_network, list));
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003643 RT_TRACE(COMP_DOWN, "<==========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003644
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003645 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003646}
3647
3648
3649void rtl8192_commit(struct net_device *dev)
3650{
3651 struct r8192_priv *priv = ieee80211_priv(dev);
3652 int reset_status = 0;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003653 if (priv->up == 0) return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003654 priv->up = 0;
3655
3656 rtl8192_cancel_deferred_work(priv);
3657 del_timer_sync(&priv->watch_dog_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003658
3659 ieee80211_softmac_stop_protocol(priv->ieee80211);
3660
Jerry Chuang8fc85982009-11-03 07:17:11 -02003661 rtl8192_rtx_disable(dev);
3662 reset_status = _rtl8192_up(dev);
3663
3664}
3665
Jerry Chuang8fc85982009-11-03 07:17:11 -02003666void rtl8192_restart(struct work_struct *work)
3667{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003668 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
3669 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003670
3671 down(&priv->wx_sem);
3672
3673 rtl8192_commit(dev);
3674
3675 up(&priv->wx_sem);
3676}
3677
3678static void r8192_set_multicast(struct net_device *dev)
3679{
3680 struct r8192_priv *priv = ieee80211_priv(dev);
3681 short promisc;
3682
Jerry Chuang8fc85982009-11-03 07:17:11 -02003683 /* FIXME FIXME */
3684
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003685 promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003686
3687 if (promisc != priv->promisc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003688
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003689 priv->promisc = promisc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003690}
3691
3692
Ana Reyf4c60742014-03-13 12:36:38 +01003693static int r8192_set_mac_adr(struct net_device *dev, void *mac)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003694{
3695 struct r8192_priv *priv = ieee80211_priv(dev);
3696 struct sockaddr *addr = mac;
3697
3698 down(&priv->wx_sem);
3699
3700 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
3701
Jerry Chuang8fc85982009-11-03 07:17:11 -02003702 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003703 up(&priv->wx_sem);
3704
3705 return 0;
3706}
3707
3708/* based on ipw2200 driver */
Ana Reyf4c60742014-03-13 12:36:38 +01003709static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003710{
3711 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3712 struct iwreq *wrq = (struct iwreq *)rq;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003713 int ret = -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003714 struct ieee80211_device *ieee = priv->ieee80211;
3715 u32 key[4];
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003716 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003717 struct iw_point *p = &wrq->u.data;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03003718 struct ieee_param *ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003719
3720 down(&priv->wx_sem);
3721
3722
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003723 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
3724 ret = -EINVAL;
3725 goto out;
3726 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003727
Teodora Baluta38272d22013-10-25 11:27:09 +03003728 ipw = memdup_user(p->pointer, p->length);
3729 if (IS_ERR(ipw)) {
3730 ret = PTR_ERR(ipw);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003731 goto out;
3732 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003733
3734 switch (cmd) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003735 case RTL_IOCTL_WPA_SUPPLICANT:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003736 //parse here for HW security
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003737 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) {
3738 if (ipw->u.crypt.set_tx) {
3739 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003740 ieee->pairwise_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003741 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003742 ieee->pairwise_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003743 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003744 if (ipw->u.crypt.key_len == 13)
3745 ieee->pairwise_key_type = KEY_TYPE_WEP104;
3746 else if (ipw->u.crypt.key_len == 5)
3747 ieee->pairwise_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003748 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003749 ieee->pairwise_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003750 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003751
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003752 if (ieee->pairwise_key_type) {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003753 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003754 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003755 //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!
3756 //added by WB.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003757 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 +01003758 if (ieee->auth_mode != 2)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003759 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 -02003760 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003761 } else {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003762 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003763 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003764 ieee->group_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003765 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003766 ieee->group_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003767 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003768 if (ipw->u.crypt.key_len == 13)
3769 ieee->group_key_type = KEY_TYPE_WEP104;
3770 else if (ipw->u.crypt.key_len == 5)
3771 ieee->group_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003772 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003773 ieee->group_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003774 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003775
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003776 if (ieee->group_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003777 setKey(dev, ipw->u.crypt.idx,
3778 ipw->u.crypt.idx, //KeyIndex
3779 ieee->group_key_type, //KeyType
3780 broadcast_addr, //MacAddr
3781 0, //DefaultKey
3782 key); //KeyContent
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003783 }
3784 }
3785 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003786 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
3787 break;
3788
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003789 default:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003790 ret = -EOPNOTSUPP;
3791 break;
3792 }
3793 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003794 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003795out:
3796 up(&priv->wx_sem);
3797 return ret;
3798}
3799
Ana Reyf4c60742014-03-13 12:36:38 +01003800static u8 HwRateToMRate90(bool bIsHT, u8 rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003801{
3802 u8 ret_rate = 0xff;
3803
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003804 if (!bIsHT) {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003805 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003806 case DESC90_RATE1M: ret_rate = MGN_1M; break;
3807 case DESC90_RATE2M: ret_rate = MGN_2M; break;
3808 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
3809 case DESC90_RATE11M: ret_rate = MGN_11M; break;
3810 case DESC90_RATE6M: ret_rate = MGN_6M; break;
3811 case DESC90_RATE9M: ret_rate = MGN_9M; break;
3812 case DESC90_RATE12M: ret_rate = MGN_12M; break;
3813 case DESC90_RATE18M: ret_rate = MGN_18M; break;
3814 case DESC90_RATE24M: ret_rate = MGN_24M; break;
3815 case DESC90_RATE36M: ret_rate = MGN_36M; break;
3816 case DESC90_RATE48M: ret_rate = MGN_48M; break;
3817 case DESC90_RATE54M: ret_rate = MGN_54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003818
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003819 default:
3820 ret_rate = 0xff;
3821 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
3822 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003823 }
3824
3825 } else {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003826 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003827 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
3828 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
3829 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
3830 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
3831 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
3832 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
3833 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
3834 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
3835 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
3836 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
3837 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
3838 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
3839 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
3840 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
3841 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
3842 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
3843 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003844
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003845 default:
3846 ret_rate = 0xff;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003847 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003848 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003849 }
3850 }
3851
3852 return ret_rate;
3853}
3854
3855/**
3856 * Function: UpdateRxPktTimeStamp
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003857 * Overview: Record the TSF time stamp when receiving a packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02003858 *
3859 * Input:
3860 * PADAPTER Adapter
3861 * PRT_RFD pRfd,
3862 *
3863 * Output:
3864 * PRT_RFD pRfd
3865 * (pRfd->Status.TimeStampHigh is updated)
3866 * (pRfd->Status.TimeStampLow is updated)
3867 * Return:
3868 * None
3869 */
Teodora Baluta46326d22013-10-16 01:59:17 +03003870static void UpdateRxPktTimeStamp8190(struct net_device *dev,
3871 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003872{
3873 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3874
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003875 if (stats->bIsAMPDU && !stats->bFirstMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003876 stats->mac_time[0] = priv->LastRxDescTSFLow;
3877 stats->mac_time[1] = priv->LastRxDescTSFHigh;
3878 } else {
3879 priv->LastRxDescTSFLow = stats->mac_time[0];
3880 priv->LastRxDescTSFHigh = stats->mac_time[1];
3881 }
3882}
3883
3884//by amy 080606
3885
Ana Reyf4c60742014-03-13 12:36:38 +01003886static long rtl819x_translate_todbm(u8 signal_strength_index)// 0-100 index.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003887{
3888 long signal_power; // in dBm.
3889
3890 // Translate to dBm (x=0.5y-95).
3891 signal_power = (long)((signal_strength_index + 1) >> 1);
3892 signal_power -= 95;
3893
3894 return signal_power;
3895}
3896
3897
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003898/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
Jerry Chuang8fc85982009-11-03 07:17:11 -02003899 be a local static. Otherwise, it may increase when we return from S3/S4. The
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003900 value will be kept in memory or disk. Declare the value in the adaptor
3901 and it will be reinitialized when returned from S3/S4. */
Ana Reyf4c60742014-03-13 12:36:38 +01003902static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
3903 struct ieee80211_rx_stats *pprevious_stats,
3904 struct ieee80211_rx_stats *pcurrent_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003905{
3906 bool bcheck = false;
3907 u8 rfpath;
3908 u32 nspatial_stream, tmp_val;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003909 static u32 slide_rssi_index, slide_rssi_statistics;
3910 static u32 slide_evm_index, slide_evm_statistics;
3911 static u32 last_rssi, last_evm;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003912
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003913 static u32 slide_beacon_adc_pwdb_index, slide_beacon_adc_pwdb_statistics;
3914 static u32 last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003915
3916 struct ieee80211_hdr_3addr *hdr;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003917 u16 sc;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003918 unsigned int frag, seq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003919 hdr = (struct ieee80211_hdr_3addr *)buffer;
3920 sc = le16_to_cpu(hdr->seq_ctl);
3921 frag = WLAN_GET_SEQ_FRAG(sc);
3922 seq = WLAN_GET_SEQ_SEQ(sc);
3923 //cosa add 04292008 to record the sequence number
3924 pcurrent_stats->Seq_Num = seq;
3925 //
3926 // Check whether we should take the previous packet into accounting
3927 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003928 if (!pprevious_stats->bIsAMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003929 // if previous packet is not aggregated packet
3930 bcheck = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003931 }
3932
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003933 if (slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003934 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
3935 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
3936 priv->stats.slide_rssi_total -= last_rssi;
3937 }
3938 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
3939
3940 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003941 if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003942 slide_rssi_index = 0;
3943
3944 // <1> Showed on UI for user, in dbm
3945 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
3946 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
3947 pcurrent_stats->rssi = priv->stats.signal_strength;
3948 //
3949 // If the previous packet does not match the criteria, neglect it
3950 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003951 if (!pprevious_stats->bPacketMatchBSSID) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003952 if (!pprevious_stats->bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003953 return;
3954 }
3955
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003956 if (!bcheck)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003957 return;
3958
3959
3960 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
3961
3962 //
3963 // Check RSSI
3964 //
3965 priv->stats.num_process_phyinfo++;
3966
3967 /* record the general signal strength to the sliding window. */
3968
3969
3970 // <2> Showed on UI for engineering
3971 // hardware does not provide rssi information for each rf path in CCK
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003972 if (!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA)) {
3973 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003974 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
3975 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003976
3977 //Fixed by Jacken 2008-03-20
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003978 if (priv->stats.rx_rssi_percentage[rfpath] == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003979 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003980 if (pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath]) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003981 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003982 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003983 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003984 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003985 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003986 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003987 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003988 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003989 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003990 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 -02003991 }
3992 }
3993
3994
3995 //
3996 // Check PWDB.
3997 //
3998 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003999 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004000 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004001
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004002 if (pprevious_stats->bPacketBeacon) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004003 /* record the beacon pwdb to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004004 if (slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004005 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
4006 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
4007 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004008 }
4009 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
4010 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004011 slide_beacon_adc_pwdb_index++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004012 if (slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004013 slide_beacon_adc_pwdb_index = 0;
4014 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004015 if (pprevious_stats->RxPWDBAll >= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004016 pprevious_stats->RxPWDBAll -= 3;
4017 }
4018
4019 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004020 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004021 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004022
4023
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004024 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004025 if (priv->undecorated_smoothed_pwdb < 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004026 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004027 if (pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004028 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004029 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4030 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004031 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004032 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004033 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004034 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4035 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004036 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004037
4038 }
4039
4040 //
4041 // Check EVM
4042 //
4043 /* record the general EVM to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004044 if (pprevious_stats->SignalQuality) {
4045 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4046 if (slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004047 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
4048 last_evm = priv->stats.slide_evm[slide_evm_index];
4049 priv->stats.slide_evm_total -= last_evm;
4050 }
4051
4052 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
4053
4054 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004055 if (slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004056 slide_evm_index = 0;
4057
4058 // <1> Showed on UI for user, in percentage.
4059 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
4060 priv->stats.signal_quality = tmp_val;
4061 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
4062 priv->stats.last_signal_strength_inpercent = tmp_val;
4063 }
4064
4065 // <2> Showed on UI for engineering
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004066 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4067 for (nspatial_stream = 0; nspatial_stream < 2; nspatial_stream++) { // 2 spatial stream
4068 if (pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004069 if (priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004070 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
Jerry Chuang8fc85982009-11-03 07:17:11 -02004071 priv->stats.rx_evm_percentage[nspatial_stream] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004072 ((priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004073 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004074 }
4075 }
4076 }
4077 }
4078
4079
4080}
4081
4082/*-----------------------------------------------------------------------------
4083 * Function: rtl819x_query_rxpwrpercentage()
4084 *
4085 * Overview:
4086 *
4087 * Input: char antpower
4088 *
4089 * Output: NONE
4090 *
4091 * Return: 0-100 percentage
4092 *
4093 * Revised History:
4094 * When Who Remark
4095 * 05/26/2008 amy Create Version 0 porting from windows code.
4096 *
4097 *---------------------------------------------------------------------------*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004098static u8 rtl819x_query_rxpwrpercentage(char antpower)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004099{
4100 if ((antpower <= -100) || (antpower >= 20))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004101 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004102 else if (antpower >= 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004103 return 100;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004104 else
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004105 return 100 + antpower;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004106
4107} /* QueryRxPwrPercentage */
4108
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004109static u8 rtl819x_evm_dbtopercentage(char value)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004110{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004111 char ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004112
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004113 ret_val = value;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004114
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004115 if (ret_val >= 0)
4116 ret_val = 0;
4117 if (ret_val <= -33)
4118 ret_val = -33;
4119 ret_val = 0 - ret_val;
4120 ret_val *= 3;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004121 if (ret_val == 99)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004122 ret_val = 100;
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004123 return ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004124}
4125//
4126// Description:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004127// We want good-looking for signal strength/quality
Jerry Chuang8fc85982009-11-03 07:17:11 -02004128// 2007/7/19 01:09, by cosa.
4129//
Teodora Baluta46326d22013-10-16 01:59:17 +03004130static long rtl819x_signal_scale_mapping(long currsig)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004131{
4132 long retsig;
4133
4134 // Step 1. Scale mapping.
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004135 if (currsig >= 61 && currsig <= 100)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004136 retsig = 90 + ((currsig - 60) / 4);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004137 else if (currsig >= 41 && currsig <= 60)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004138 retsig = 78 + ((currsig - 40) / 2);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004139 else if (currsig >= 31 && currsig <= 40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004140 retsig = 66 + (currsig - 30);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004141 else if (currsig >= 21 && currsig <= 30)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004142 retsig = 54 + (currsig - 20);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004143 else if (currsig >= 5 && currsig <= 20)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004144 retsig = 42 + (((currsig - 5) * 2) / 3);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004145 else if (currsig == 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004146 retsig = 36;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004147 else if (currsig == 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004148 retsig = 27;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004149 else if (currsig == 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004150 retsig = 18;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004151 else if (currsig == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004152 retsig = 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004153 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004154 retsig = currsig;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004155
4156 return retsig;
4157}
4158
Xenia Ragiadakouf2c3d802013-06-04 23:32:32 +03004159static inline bool rx_hal_is_cck_rate(struct rx_drvinfo_819x_usb *pdrvinfo)
4160{
4161 if (pdrvinfo->RxHT)
4162 return false;
4163
4164 switch (pdrvinfo->RxRate) {
4165 case DESC90_RATE1M:
4166 case DESC90_RATE2M:
4167 case DESC90_RATE5_5M:
4168 case DESC90_RATE11M:
4169 return true;
4170 default:
4171 return false;
4172 }
4173}
4174
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004175static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
4176 struct ieee80211_rx_stats *pstats,
4177 rx_drvinfo_819x_usb *pdrvinfo,
4178 struct ieee80211_rx_stats *precord_stats,
4179 bool bpacket_match_bssid,
4180 bool bpacket_toself,
4181 bool bPacketBeacon,
4182 bool bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004183{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004184 phy_sts_ofdm_819xusb_t *pofdm_buf;
4185 phy_sts_cck_819xusb_t *pcck_buf;
4186 phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004187 u8 *prxpkt;
4188 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004189 char rx_pwr[4], rx_pwr_all = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004190 char rx_snrX, rx_evmX;
4191 u8 evm, pwdb_all;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004192 u32 RSSI, total_rssi = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004193 u8 is_cck_rate = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004194 u8 rf_rx_num = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004195 u8 sq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004196
4197
4198 priv->stats.numqry_phystatus++;
4199
4200 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4201
4202 // Record it for next packet processing
4203 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4204 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4205 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004206 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004207 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4208 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4209
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004210 prxpkt = (u8 *)pdrvinfo;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004211
4212 /* Move pointer to the 16th bytes. Phy status start address. */
4213 prxpkt += sizeof(rx_drvinfo_819x_usb);
4214
4215 /* Initial the cck and ofdm buffer pointer */
4216 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
4217 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
4218
4219 pstats->RxMIMOSignalQuality[0] = -1;
4220 pstats->RxMIMOSignalQuality[1] = -1;
4221 precord_stats->RxMIMOSignalQuality[0] = -1;
4222 precord_stats->RxMIMOSignalQuality[1] = -1;
4223
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004224 if (is_cck_rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004225 //
4226 // (1)Hardware does not provide RSSI for CCK
4227 //
4228
4229 //
4230 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4231 //
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004232 u8 report;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004233
4234 priv->stats.numqry_phystatusCCK++;
4235
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004236 if (!priv->bCckHighPower) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004237 report = pcck_buf->cck_agc_rpt & 0xc0;
4238 report = report>>6;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004239 switch (report) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004240 //Fixed by Jacken from Bryant 2008-03-20
4241 //Original value is -38 , -26 , -14 , -2
4242 //Fixed value is -35 , -23 , -11 , 6
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004243 case 0x3:
4244 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4245 break;
4246 case 0x2:
4247 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4248 break;
4249 case 0x1:
4250 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4251 break;
4252 case 0x0:
4253 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
4254 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004255 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004256 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004257 report = pcck_buf->cck_agc_rpt & 0x60;
4258 report = report>>5;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004259 switch (report) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004260 case 0x3:
4261 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4262 break;
4263 case 0x2:
4264 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4265 break;
4266 case 0x1:
4267 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4268 break;
4269 case 0x0:
4270 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4271 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004272 }
4273 }
4274
4275 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4276 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4277 pstats->RecvSignalPower = pwdb_all;
4278
4279 //
4280 // (3) Get Signal Quality (EVM)
4281 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02004282
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004283 if (pstats->RxPWDBAll > 40) {
4284 sq = 100;
4285 } else {
4286 sq = pcck_buf->sq_rpt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004287
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004288 if (pcck_buf->sq_rpt > 64)
4289 sq = 0;
4290 else if (pcck_buf->sq_rpt < 20)
4291 sq = 100;
4292 else
4293 sq = ((64-sq) * 100) / 44;
4294 }
4295 pstats->SignalQuality = precord_stats->SignalQuality = sq;
4296 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
4297 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004298
4299 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004300 priv->stats.numqry_phystatusHT++;
4301 //
4302 // (1)Get RSSI for HT rate
4303 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004304 for (i = RF90_PATH_A; i < priv->NumTotalRFPath; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004305 // 2008/01/30 MH we will judge RF RX path now.
4306 if (priv->brfpath_rxenable[i])
4307 rf_rx_num++;
4308 else
4309 continue;
4310
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004311 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004312 continue;
4313
4314 //Fixed by Jacken from Bryant 2008-03-20
4315 //Original value is 106
4316 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
4317
4318 //Get Rx snr value in DB
4319 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
4320 rx_snrX = (char)(tmp_rxsnr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004321 rx_snrX /= 2;
4322 priv->stats.rxSNRdB[i] = (long)rx_snrX;
4323
4324 /* Translate DBM to percentage. */
4325 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
4326 total_rssi += RSSI;
4327
4328 /* Record Signal Strength for next packet */
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004329 pstats->RxMIMOSignalStrength[i] = (u8) RSSI;
4330 precord_stats->RxMIMOSignalStrength[i] = (u8) RSSI;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004331 }
4332
4333
4334 //
4335 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4336 //
4337 //Fixed by Jacken from Bryant 2008-03-20
4338 //Original value is 106
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004339 rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1)& 0x7f) -106;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004340 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4341
4342 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4343 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
4344
4345 //
4346 // (3)EVM of HT rate
4347 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004348 if (pdrvinfo->RxHT && pdrvinfo->RxRate >= DESC90_RATEMCS8 &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004349 pdrvinfo->RxRate <= DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004350 max_spatial_stream = 2; //both spatial stream make sense
4351 else
4352 max_spatial_stream = 1; //only spatial stream 1 makes sense
4353
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004354 for (i = 0; i < max_spatial_stream; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004355 tmp_rxevm = pofdm_buf->rxevm_X[i];
4356 rx_evmX = (char)(tmp_rxevm);
4357
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004358 // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004359 // will set the most significant bit to "zero" when doing shifting operation which may change a negative
Jerry Chuang8fc85982009-11-03 07:17:11 -02004360 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
4361 rx_evmX /= 2; //dbm
4362
4363 evm = rtl819x_evm_dbtopercentage(rx_evmX);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004364 if (i == 0) // Fill value in RFD, Get the first spatial stream only
4365 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
4366 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004367 }
4368
4369
4370 /* record rx statistics for debug */
4371 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
4372 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004373 if (pdrvinfo->BW) //40M channel
Jerry Chuang8fc85982009-11-03 07:17:11 -02004374 priv->stats.received_bwtype[1+prxsc->rxsc]++;
4375 else //20M channel
4376 priv->stats.received_bwtype[0]++;
4377 }
4378
4379 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
4380 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004381 if (is_cck_rate) {
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004382 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004383 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004384 // We can judge RX path number now.
4385 if (rf_rx_num != 0)
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004386 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi /= rf_rx_num)));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004387 }
4388} /* QueryRxPhyStatus8190Pci */
4389
Ana Reyf4c60742014-03-13 12:36:38 +01004390static void rtl8192_record_rxdesc_forlateruse(struct ieee80211_rx_stats *psrc_stats,
4391 struct ieee80211_rx_stats *ptarget_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004392{
4393 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
4394 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
4395 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
4396}
4397
4398
Teodora Baluta46326d22013-10-16 01:59:17 +03004399static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
4400 struct ieee80211_rx_stats *pstats,
4401 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004402{
4403 // TODO: We must only check packet for current MAC address. Not finish
4404 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004405 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004406 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4407 bool bpacket_match_bssid, bpacket_toself;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004408 bool bPacketBeacon = FALSE, bToSelfBA = FALSE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004409 static struct ieee80211_rx_stats previous_stats;
4410 struct ieee80211_hdr_3addr *hdr;//by amy
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004411 u16 fc, type;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004412
4413 // Get Signal Quality for only RX data queue (but not command queue)
4414
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004415 u8 *tmp_buf;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004416 u8 *praddr;
4417
4418 /* Get MAC frame start address. */
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004419 tmp_buf = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004420
4421 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
4422 fc = le16_to_cpu(hdr->frame_ctl);
4423 type = WLAN_FC_GET_TYPE(fc);
4424 praddr = hdr->addr1;
4425
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004426 /* Check if the received packet is acceptable. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004427 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004428 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
4429 && (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004430 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
4431
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004432 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON)
4433 bPacketBeacon = true;
4434 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK) {
4435 if ((eqMacAddr(praddr, dev->dev_addr)))
4436 bToSelfBA = true;
4437 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004438
Jerry Chuang8fc85982009-11-03 07:17:11 -02004439
4440
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004441 if (bpacket_match_bssid)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004442 priv->stats.numpacket_matchbssid++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004443 if (bpacket_toself)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004444 priv->stats.numpacket_toself++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004445 //
4446 // Process PHY information for previous packet (RSSI/PWDB/EVM)
4447 //
4448 // Because phy information is contained in the last packet of AMPDU only, so driver
4449 // should process phy information of previous packet
4450 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004451 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid, bpacket_toself, bPacketBeacon, bToSelfBA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004452 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
4453
4454}
4455
4456/**
4457* Function: UpdateReceivedRateHistogramStatistics
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004458* Overview: Record the received data rate
Jerry Chuang8fc85982009-11-03 07:17:11 -02004459*
4460* Input:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004461* struct net_device *dev
Jerry Chuang8fc85982009-11-03 07:17:11 -02004462* struct ieee80211_rx_stats *stats
4463*
4464* Output:
4465*
4466* (priv->stats.ReceivedRateHistogram[] is updated)
4467* Return:
4468* None
4469*/
Teodora Baluta46326d22013-10-16 01:59:17 +03004470static void
4471UpdateReceivedRateHistogramStatistics8190(struct net_device *dev,
4472 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004473{
4474 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004475 u32 rcvType = 1; //0: Total, 1:OK, 2:CRC, 3:ICV
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004476 u32 rateIndex;
4477 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02004478
4479
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004480 if (stats->bCRC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004481 rcvType = 2;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004482 else if (stats->bICV)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004483 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004484
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004485 if (stats->bShortPreamble)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004486 preamble_guardinterval = 1;// short
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004487 else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004488 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02004489
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004490 switch (stats->rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004491 //
4492 // CCK rate
4493 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004494 case MGN_1M: rateIndex = 0; break;
4495 case MGN_2M: rateIndex = 1; break;
4496 case MGN_5_5M: rateIndex = 2; break;
4497 case MGN_11M: rateIndex = 3; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004498 //
4499 // Legacy OFDM rate
4500 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004501 case MGN_6M: rateIndex = 4; break;
4502 case MGN_9M: rateIndex = 5; break;
4503 case MGN_12M: rateIndex = 6; break;
4504 case MGN_18M: rateIndex = 7; break;
4505 case MGN_24M: rateIndex = 8; break;
4506 case MGN_36M: rateIndex = 9; break;
4507 case MGN_48M: rateIndex = 10; break;
4508 case MGN_54M: rateIndex = 11; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004509 //
4510 // 11n High throughput rate
4511 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004512 case MGN_MCS0: rateIndex = 12; break;
4513 case MGN_MCS1: rateIndex = 13; break;
4514 case MGN_MCS2: rateIndex = 14; break;
4515 case MGN_MCS3: rateIndex = 15; break;
4516 case MGN_MCS4: rateIndex = 16; break;
4517 case MGN_MCS5: rateIndex = 17; break;
4518 case MGN_MCS6: rateIndex = 18; break;
4519 case MGN_MCS7: rateIndex = 19; break;
4520 case MGN_MCS8: rateIndex = 20; break;
4521 case MGN_MCS9: rateIndex = 21; break;
4522 case MGN_MCS10: rateIndex = 22; break;
4523 case MGN_MCS11: rateIndex = 23; break;
4524 case MGN_MCS12: rateIndex = 24; break;
4525 case MGN_MCS13: rateIndex = 25; break;
4526 case MGN_MCS14: rateIndex = 26; break;
4527 case MGN_MCS15: rateIndex = 27; break;
4528 default: rateIndex = 28; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004529 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004530 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
4531 priv->stats.received_rate_histogram[0][rateIndex]++; //total
4532 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004533}
4534
4535
Teodora Baluta46326d22013-10-16 01:59:17 +03004536static void query_rxdesc_status(struct sk_buff *skb,
4537 struct ieee80211_rx_stats *stats,
4538 bool bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004539{
4540 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004541 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004542 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004543 rx_drvinfo_819x_usb *driver_info = NULL;
4544
4545 //
4546 //Get Rx Descriptor Information
4547 //
4548#ifdef USB_RX_AGGREGATION_SUPPORT
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004549 if (bIsRxAggrSubframe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004550 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004551 stats->Length = desc->Length;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004552 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
4553 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
4554 stats->bICV = desc->ICV;
4555 stats->bCRC = desc->CRC32;
4556 stats->bHwError = stats->bCRC|stats->bICV;
4557 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
4558 } else
4559#endif
4560 {
4561 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
4562
4563 stats->Length = desc->Length;
4564 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004565 stats->RxBufShift = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004566 stats->bICV = desc->ICV;
4567 stats->bCRC = desc->CRC32;
4568 stats->bHwError = stats->bCRC|stats->bICV;
4569 //RTL8190 set this bit to indicate that Hw does not decrypt packet
4570 stats->Decrypted = !desc->SWDec;
4571 }
4572
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004573 if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004574 stats->bHwError = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004575 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004576 stats->bHwError = stats->bCRC|stats->bICV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004577
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004578 if (stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004579 stats->bHwError |= 1;
4580 //
4581 //Get Driver Info
4582 //
4583 // TODO: Need to verify it on FGPA platform
4584 //Driver info are written to the RxBuffer following rx desc
4585 if (stats->RxDrvInfoSize != 0) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004586 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004587 stats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004588 /* unit: 0.5M */
4589 /* TODO */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004590 if (!stats->bHwError) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004591 u8 ret_rate;
4592 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004593 if (ret_rate == 0xff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004594 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
4595 // Special Error Handling here, 2008.05.16, by Emily
4596
4597 stats->bHwError = 1;
4598 stats->rate = MGN_1M; //Set 1M rate by default
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004599 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004600 stats->rate = ret_rate;
4601 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004602 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004603 stats->rate = 0x02;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004604 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004605
4606 stats->bShortPreamble = driver_info->SPLCP;
4607
4608
4609 UpdateReceivedRateHistogramStatistics8190(dev, stats);
4610
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004611 stats->bIsAMPDU = (driver_info->PartAggr == 1);
4612 stats->bFirstMPDU = (driver_info->PartAggr == 1) && (driver_info->FirstAGGR == 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004613 stats->TimeStampLow = driver_info->TSFL;
4614 // xiong mask it, 070514
Jerry Chuang8fc85982009-11-03 07:17:11 -02004615
4616 UpdateRxPktTimeStamp8190(dev, stats);
4617
4618 //
4619 // Rx A-MPDU
4620 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004621 if (driver_info->FirstAGGR == 1 || driver_info->PartAggr == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004622 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004623 driver_info->FirstAGGR, driver_info->PartAggr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004624
4625 }
4626
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004627 skb_pull(skb, sizeof(rx_desc_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004628 //
4629 // Get Total offset of MPDU Frame Body
4630 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004631 if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004632 stats->bShift = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004633 skb_pull(skb, stats->RxBufShift + stats->RxDrvInfoSize);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004634 }
4635
4636#ifdef USB_RX_AGGREGATION_SUPPORT
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004637 /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004638 if (bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004639 skb_pull(skb, 8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004640#endif
4641 /* for debug 2008.5.29 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004642
4643 //added by vivi, for MP, 20080108
4644 stats->RxIs40MHzPacket = driver_info->BW;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004645 if (stats->RxDrvInfoSize != 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004646 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
4647
4648}
4649
4650u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
4651{
4652#ifdef USB_RX_AGGREGATION_SUPPORT
4653 if (bIsRxAggrSubframe)
4654 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
4655 + Status->RxBufShift + 8);
4656 else
4657#endif
4658 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004659 + Status->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004660}
4661
Ana Reyf4c60742014-03-13 12:36:38 +01004662static void rtl8192_rx_nomal(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004663{
4664 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004665 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004666 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4667 struct ieee80211_rx_stats stats = {
4668 .signal = 0,
4669 .noise = -98,
4670 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004671 .freq = IEEE80211_24GHZ_BAND,
4672 };
4673 u32 rx_pkt_len = 0;
4674 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
4675 bool unicast_packet = false;
4676#ifdef USB_RX_AGGREGATION_SUPPORT
4677 struct sk_buff *agg_skb = NULL;
4678 u32 TotalLength = 0;
4679 u32 TempDWord = 0;
4680 u32 PacketLength = 0;
4681 u32 PacketOccupiedLendth = 0;
4682 u8 TempByte = 0;
4683 u32 PacketShiftBytes = 0;
4684 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
4685 u8 PaddingBytes = 0;
4686 //add just for testing
4687 u8 testing;
4688
4689#endif
4690
4691 /* 20 is for ps-poll */
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004692 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004693#ifdef USB_RX_AGGREGATION_SUPPORT
4694 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
4695#endif
4696 /* first packet should not contain Rx aggregation header */
4697 query_rxdesc_status(skb, &stats, false);
4698 /* TODO */
4699 /* hardware related info */
4700#ifdef USB_RX_AGGREGATION_SUPPORT
4701 if (TempByte & BIT0) {
4702 agg_skb = skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004703 TotalLength = stats.Length - 4; /*sCrcLng*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02004704 /* though the head pointer has passed this position */
4705 TempDWord = *(u32 *)(agg_skb->data - 4);
4706 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
4707 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004708 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004709 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
4710 }
4711#endif
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004712 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004713 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4714
4715 rx_pkt_len = skb->len;
4716 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4717 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004718 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004719 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004720 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004721 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004722 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004723 /* unicast packet */
4724 unicast_packet = true;
4725 }
4726
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004727 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004728 dev_kfree_skb_any(skb);
4729 } else {
4730 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004731 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004732 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004733 }
4734#ifdef USB_RX_AGGREGATION_SUPPORT
4735 testing = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004736 if (TotalLength > 0) {
4737 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
4738 if ((PacketOccupiedLendth & 0xFF) != 0)
4739 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
4740 PacketOccupiedLendth -= 8;
4741 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
4742 if (agg_skb->len > TempDWord)
4743 skb_pull(agg_skb, TempDWord);
4744 else
4745 agg_skb->len = 0;
4746
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004747 while (agg_skb->len >= GetRxPacketShiftBytes819xUsb(&stats, true)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004748 u8 tmpCRC = 0, tmpICV = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004749 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
4750 tmpCRC = RxDescr->CRC32;
4751 tmpICV = RxDescr->ICV;
4752 memcpy(agg_skb->data, &agg_skb->data[44], 2);
4753 RxDescr->CRC32 = tmpCRC;
4754 RxDescr->ICV = tmpICV;
4755
4756 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
4757 stats.signal = 0;
4758 stats.noise = -98;
4759 stats.rate = 0;
4760 stats.freq = IEEE80211_24GHZ_BAND;
4761 query_rxdesc_status(agg_skb, &stats, true);
4762 PacketLength = stats.Length;
4763
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004764 if (PacketLength > agg_skb->len)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004765 break;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004766 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004767 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004768 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004769 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4770
4771 rx_pkt_len = skb->len;
4772 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4773 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004774 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004775 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004776 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004777 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004778 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004779 /* unicast packet */
4780 unicast_packet = true;
4781 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004782 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004783 dev_kfree_skb_any(skb);
4784 } else {
4785 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004786 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004787 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004788 }
4789 /* should trim the packet which has been copied to target skb */
4790 skb_pull(agg_skb, PacketLength);
4791 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
4792 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
4793 if ((PacketOccupiedLendth & 0xFF) != 0) {
4794 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
4795 if (agg_skb->len > PaddingBytes)
4796 skb_pull(agg_skb, PaddingBytes);
4797 else
4798 agg_skb->len = 0;
4799 }
4800 }
4801 dev_kfree_skb(agg_skb);
4802 }
4803#endif
4804 } else {
4805 priv->stats.rxurberr++;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03004806 netdev_dbg(dev, "actual_length: %d\n", skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004807 dev_kfree_skb_any(skb);
4808 }
4809
4810}
4811
Ana Reyf4c60742014-03-13 12:36:38 +01004812static void rtl819xusb_process_received_packet(struct net_device *dev,
4813 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004814{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004815 u8 *frame;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004816 u16 frame_len = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004817 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004818
4819 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
4820 //porting by amy 080508
4821 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
4822 frame = pstats->virtual_address;
4823 frame_len = pstats->packetlength;
4824#ifdef TODO // by amy about HCT
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004825 if (!Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004826 CountRxErrStatistics(Adapter, pRfd);
4827#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004828#ifdef ENABLE_PS //by amy for adding ps function in future
4829 RT_RF_POWER_STATE rtState;
4830 // When RF is off, we should not count the packet for hw/sw synchronize
4831 // reason, ie. there may be a duration while sw switch is changed and hw
4832 // switch is being changed. 2006.12.04, by shien chang.
4833 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8 *)(&rtState));
4834 if (rtState == eRfOff)
4835 return;
4836#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -02004837 priv->stats.rxframgment++;
4838
Jerry Chuang8fc85982009-11-03 07:17:11 -02004839#ifdef TODO
4840 RmMonitorSignalStrength(Adapter, pRfd);
4841#endif
4842 /* 2007/01/16 MH Add RX command packet handle here. */
4843 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
4844 if (rtl819xusb_rx_command_packet(dev, pstats))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004845 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004846
4847#ifdef SW_CRC_CHECK
4848 SwCrcCheck();
4849#endif
4850
4851
4852}
4853
Teodora Baluta46326d22013-10-16 01:59:17 +03004854static void query_rx_cmdpkt_desc_status(struct sk_buff *skb,
4855 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004856{
Jerry Chuang8fc85982009-11-03 07:17:11 -02004857 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004858
4859 //
4860 //Get Rx Descriptor Information
4861 //
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004862 stats->virtual_address = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004863 stats->Length = desc->Length;
4864 stats->RxDrvInfoSize = 0;
4865 stats->RxBufShift = 0;
4866 stats->packetlength = stats->Length-scrclng;
4867 stats->fraglength = stats->packetlength;
4868 stats->fragoffset = 0;
4869 stats->ntotalfrag = 1;
4870}
4871
4872
Ana Reyf4c60742014-03-13 12:36:38 +01004873static void rtl8192_rx_cmd(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004874{
4875 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
4876 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004877 /* TODO */
4878 struct ieee80211_rx_stats stats = {
4879 .signal = 0,
4880 .noise = -98,
4881 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004882 .freq = IEEE80211_24GHZ_BAND,
4883 };
4884
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004885 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004886
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004887 query_rx_cmdpkt_desc_status(skb, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004888 // this is to be done by amy 080508 prfd->queue_id = 1;
4889
4890
4891 //
4892 // Process the command packet received.
4893 //
4894
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004895 rtl819xusb_process_received_packet(dev, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004896
4897 dev_kfree_skb_any(skb);
4898 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004899}
4900
4901void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
4902{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004903 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004904 struct rtl8192_rx_info *info;
4905
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004906 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004907 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004908 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004909 /* Nomal packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004910 case 3:
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004911 priv->IrpPendingCount--;
4912 rtl8192_rx_nomal(skb);
4913 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004914
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004915 /* Command packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004916 case 9:
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004917 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004918 info->out_pipe);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004919
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004920 rtl8192_rx_cmd(skb);
4921 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004922
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004923 default: /* should never get here! */
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004924 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004925 info->out_pipe);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004926 dev_kfree_skb(skb);
4927 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004928
4929 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004930 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004931}
4932
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02004933static const struct net_device_ops rtl8192_netdev_ops = {
4934 .ndo_open = rtl8192_open,
4935 .ndo_stop = rtl8192_close,
4936 .ndo_get_stats = rtl8192_stats,
4937 .ndo_tx_timeout = tx_timeout,
4938 .ndo_do_ioctl = rtl8192_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00004939 .ndo_set_rx_mode = r8192_set_multicast,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02004940 .ndo_set_mac_address = r8192_set_mac_adr,
4941 .ndo_validate_addr = eth_validate_addr,
4942 .ndo_change_mtu = eth_change_mtu,
4943 .ndo_start_xmit = ieee80211_xmit,
4944};
Jerry Chuang8fc85982009-11-03 07:17:11 -02004945
4946
4947/****************************************************************************
4948 ---------------------------- USB_STUFF---------------------------
4949*****************************************************************************/
4950
Bill Pemberton25794522012-11-19 13:22:04 -05004951static int rtl8192_usb_probe(struct usb_interface *intf,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004952 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004953{
Jerry Chuang8fc85982009-11-03 07:17:11 -02004954 struct net_device *dev = NULL;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004955 struct r8192_priv *priv = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004956 struct usb_device *udev = interface_to_usbdev(intf);
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04004957 int ret;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004958 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02004959
4960 dev = alloc_ieee80211(sizeof(struct r8192_priv));
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04004961 if (dev == NULL)
4962 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004963
Jerry Chuang8fc85982009-11-03 07:17:11 -02004964 usb_set_intfdata(intf, dev);
4965 SET_NETDEV_DEV(dev, &intf->dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004966 priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004967 priv->ieee80211 = netdev_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004968 priv->udev = udev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004969
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004970 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004971
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004972 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Joel Pelaez Jorgee6c1ef62014-05-23 14:27:43 -05004973
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004974 dev->type = ARPHRD_ETHER;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004975
4976 dev->watchdog_timeo = HZ*3; //modified by john, 0805
4977
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004978 if (dev_alloc_name(dev, ifname) < 0) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004979 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02004980 ifname = "wlan%d";
4981 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004982 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004983
4984 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004985 if (rtl8192_init(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004986 RT_TRACE(COMP_ERR, "Initialization failed");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04004987 ret = -ENODEV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004988 goto fail;
4989 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004990 netif_carrier_off(dev);
4991 netif_stop_queue(dev);
4992
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04004993 ret = register_netdev(dev);
4994 if (ret)
4995 goto fail2;
4996
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004997 RT_TRACE(COMP_INIT, "dev name=======> %s\n", dev->name);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004998 rtl8192_proc_init_one(dev);
4999
5000
5001 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005002 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005003
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005004fail2:
5005 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005006 kfree(priv->pFirmware);
5007 priv->pFirmware = NULL;
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005008 rtl8192_usb_deleteendpoints(dev);
5009 destroy_workqueue(priv->priv_wq);
5010 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005011fail:
5012 free_ieee80211(dev);
5013
5014 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005015 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005016}
5017
5018//detach all the work and timer structure declared or inititialize in r8192U_init function.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005019void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005020{
5021
Jerry Chuang8fc85982009-11-03 07:17:11 -02005022 cancel_work_sync(&priv->reset_wq);
5023 cancel_delayed_work(&priv->watch_dog_wq);
5024 cancel_delayed_work(&priv->update_beacon_wq);
5025 cancel_work_sync(&priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005026}
5027
5028
Bill Pembertona4a557e2012-11-19 13:26:46 -05005029static void rtl8192_usb_disconnect(struct usb_interface *intf)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005030{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005031 struct net_device *dev = usb_get_intfdata(intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005032
5033 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005034 if (dev) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005035
5036 unregister_netdev(dev);
5037
5038 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
5039 rtl8192_proc_remove_one(dev);
5040
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005041 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005042 kfree(priv->pFirmware);
5043 priv->pFirmware = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005044 rtl8192_usb_deleteendpoints(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005045 destroy_workqueue(priv->priv_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005046 mdelay(10);
5047
5048 }
5049 free_ieee80211(dev);
5050 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
5051}
5052
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005053/* fun with the built-in ieee80211 stack... */
5054extern int ieee80211_debug_init(void);
5055extern void ieee80211_debug_exit(void);
5056extern int ieee80211_crypto_init(void);
5057extern void ieee80211_crypto_deinit(void);
5058extern int ieee80211_crypto_tkip_init(void);
5059extern void ieee80211_crypto_tkip_exit(void);
5060extern int ieee80211_crypto_ccmp_init(void);
5061extern void ieee80211_crypto_ccmp_exit(void);
5062extern int ieee80211_crypto_wep_init(void);
5063extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005064
5065static int __init rtl8192_usb_module_init(void)
5066{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005067 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005068
5069#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005070 ret = ieee80211_debug_init();
5071 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005072 pr_err("ieee80211_debug_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005073 return ret;
5074 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005075#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005076 ret = ieee80211_crypto_init();
5077 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005078 pr_err("ieee80211_crypto_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005079 return ret;
5080 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005081
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005082 ret = ieee80211_crypto_tkip_init();
5083 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005084 pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005085 return ret;
5086 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005087
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005088 ret = ieee80211_crypto_ccmp_init();
5089 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005090 pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005091 return ret;
5092 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005093
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005094 ret = ieee80211_crypto_wep_init();
5095 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005096 pr_err("ieee80211_crypto_wep_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005097 return ret;
5098 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005099
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005100 pr_info("\nLinux kernel driver for RTL8192 based WLAN cards\n");
5101 pr_info("Copyright (c) 2007-2008, Realsil Wlan\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005102 RT_TRACE(COMP_INIT, "Initializing module");
5103 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
5104 rtl8192_proc_module_init();
5105 return usb_register(&rtl8192_usb_driver);
5106}
5107
5108
5109static void __exit rtl8192_usb_module_exit(void)
5110{
5111 usb_deregister(&rtl8192_usb_driver);
5112
5113 RT_TRACE(COMP_DOWN, "Exiting");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005114}
5115
5116
5117void rtl8192_try_wake_queue(struct net_device *dev, int pri)
5118{
5119 unsigned long flags;
5120 short enough_desc;
5121 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5122
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005123 spin_lock_irqsave(&priv->tx_lock, flags);
5124 enough_desc = check_nic_enough_desc(dev, pri);
5125 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005126
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005127 if (enough_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005128 ieee80211_wake_queue(priv->ieee80211);
5129}
5130
5131void EnableHWSecurityConfig8192(struct net_device *dev)
5132{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005133 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005134 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005135 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005136 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005137 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 -02005138 SECR_value |= SCR_RxUseDK;
5139 SECR_value |= SCR_TxUseDK;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005140 } 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 -02005141 SECR_value |= SCR_RxUseDK;
5142 SECR_value |= SCR_TxUseDK;
5143 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005144 //add HWSec active enable here.
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005145 //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 -02005146
5147 ieee->hwsec_active = 1;
5148
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005149 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 -02005150 ieee->hwsec_active = 0;
5151 SECR_value &= ~SCR_RxDecEnable;
5152 }
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03005153 RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __func__,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005154 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
5155 write_nic_byte(dev, SECR, SECR_value);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005156}
5157
5158
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03005159void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
5160 u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005161{
5162 u32 TargetCommand = 0;
5163 u32 TargetContent = 0;
5164 u16 usConfig = 0;
5165 u8 i;
5166 if (EntryNo >= TOTAL_CAM_ENTRY)
5167 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
5168
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005169 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 -02005170
5171 if (DefaultKey)
5172 usConfig |= BIT15 | (KeyType<<2);
5173 else
5174 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005175
5176
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005177 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005178 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
5179 TargetCommand |= BIT31|BIT16;
5180
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005181 if (i == 0) { //MAC|Config
Jerry Chuang8fc85982009-11-03 07:17:11 -02005182 TargetContent = (u32)(*(MacAddr+0)) << 16|
5183 (u32)(*(MacAddr+1)) << 24|
5184 (u32)usConfig;
5185
5186 write_nic_dword(dev, WCAMI, TargetContent);
5187 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005188 } else if (i == 1) { //MAC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005189 TargetContent = (u32)(*(MacAddr+2)) |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005190 (u32)(*(MacAddr+3)) << 8|
5191 (u32)(*(MacAddr+4)) << 16|
5192 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005193 write_nic_dword(dev, WCAMI, TargetContent);
5194 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005195 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005196 //Key Material
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005197 if (KeyContent != NULL) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005198 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)));
5199 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005200 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005201 }
5202 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005203
5204}
5205
5206/***************************************************************************
5207 ------------------- module init / exit stubs ----------------
5208****************************************************************************/
5209module_init(rtl8192_usb_module_init);
5210module_exit(rtl8192_usb_module_exit);