blob: 1bb6143cdf0f18aec8a9ae5906b74e94b1d68b88 [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
100#ifdef CONFIG_RTL8192_PM
101#include "r8192_pm.h"
102#endif
103
Jerry Chuang8fc85982009-11-03 07:17:11 -0200104#include "dot11d.h"
Jerry Chuang8fc85982009-11-03 07:17:11 -0200105//set here to open your trace code. //WB
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300106u32 rt_global_debug_component = COMP_DOWN |
Jerry Chuang8fc85982009-11-03 07:17:11 -0200107 COMP_SEC |
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300108 COMP_ERR; //always open err flags on
Jerry Chuang8fc85982009-11-03 07:17:11 -0200109
110#define TOTAL_CAM_ENTRY 32
111#define CAM_CONTENT_COUNT 8
112
Németh Mártona4577322010-01-10 00:18:34 +0100113static const struct usb_device_id rtl8192_usb_id_tbl[] = {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200114 /* Realtek */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200115 {USB_DEVICE(0x0bda, 0x8709)},
116 /* Corega */
117 {USB_DEVICE(0x07aa, 0x0043)},
118 /* Belkin */
119 {USB_DEVICE(0x050d, 0x805E)},
120 /* Sitecom */
121 {USB_DEVICE(0x0df6, 0x0031)},
122 /* EnGenius */
123 {USB_DEVICE(0x1740, 0x9201)},
124 /* Dlink */
125 {USB_DEVICE(0x2001, 0x3301)},
126 /* Zinwell */
127 {USB_DEVICE(0x5a57, 0x0290)},
Ben Hutchingse10ac152010-06-25 01:35:49 +0100128 /* LG */
129 {USB_DEVICE(0x043e, 0x7a01)},
Jerry Chuang8fc85982009-11-03 07:17:11 -0200130 {}
131};
132
133MODULE_LICENSE("GPL");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200134MODULE_VERSION("V 1.1");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200135MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl);
136MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards");
137
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300138static char *ifname = "wlan%d";
Jerry Chuang8fc85982009-11-03 07:17:11 -0200139static int hwwep = 1; //default use hw. set 0 to use software security
140static int channels = 0x3fff;
141
142
143
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300144module_param(ifname, charp, S_IRUGO|S_IWUSR);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300145module_param(hwwep, int, S_IRUGO|S_IWUSR);
146module_param(channels, int, S_IRUGO|S_IWUSR);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200147
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300148MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default");
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300149MODULE_PARM_DESC(hwwep, " Try to use hardware security support. ");
150MODULE_PARM_DESC(channels, " Channel bitmask for specific locales. NYI");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200151
Bill Pemberton25794522012-11-19 13:22:04 -0500152static int rtl8192_usb_probe(struct usb_interface *intf,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300153 const struct usb_device_id *id);
Bill Pembertona4a557e2012-11-19 13:26:46 -0500154static void rtl8192_usb_disconnect(struct usb_interface *intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200155
156
157static struct usb_driver rtl8192_usb_driver = {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200158 .name = RTL819xU_MODULE_NAME, /* Driver name */
159 .id_table = rtl8192_usb_id_tbl, /* PCI_ID table */
160 .probe = rtl8192_usb_probe, /* probe fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200161 .disconnect = rtl8192_usb_disconnect, /* remove fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200162#ifdef CONFIG_RTL8192_PM
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200163 .suspend = rtl8192_suspend, /* PM suspend fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200164 .resume = rtl8192_resume, /* PM resume fn */
165#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200166 .suspend = NULL, /* PM suspend fn */
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100167 .resume = NULL, /* PM resume fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200168#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -0200169};
170
Jerry Chuang8fc85982009-11-03 07:17:11 -0200171
Jennifer Naumann0db7a342012-12-05 21:40:19 +0100172typedef struct _CHANNEL_LIST {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200173 u8 Channel[32];
174 u8 Len;
Xenia Ragiadakou972ff922013-05-23 05:14:47 +0300175} CHANNEL_LIST, *PCHANNEL_LIST;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200176
177static CHANNEL_LIST ChannelPlan[] = {
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100178 {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,149,153,157,161,165},24}, //FCC
179 {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC
180 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //ETSI
Jerry Chuang8fc85982009-11-03 07:17:11 -0200181 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Spain. Change to ETSI.
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100182 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //France. Change to ETSI.
Jerry Chuang8fc85982009-11-03 07:17:11 -0200183 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, //MKK //MKK
184 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1
185 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Israel.
186 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, // For 11a , TELEC
187 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22}, //MIC
188 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14} //For Global Domain. 1-11:active scan, 12-14 passive scan. //+YJ, 080626
189};
190
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300191static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200192{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300193 int i, max_chan = -1, min_chan = -1;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300194 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300195 switch (channel_plan) {
Patrik Karlinf00c4932013-01-09 09:39:44 +0100196 case COUNTRY_CODE_FCC:
197 case COUNTRY_CODE_IC:
198 case COUNTRY_CODE_ETSI:
199 case COUNTRY_CODE_SPAIN:
200 case COUNTRY_CODE_FRANCE:
201 case COUNTRY_CODE_MKK:
202 case COUNTRY_CODE_MKK1:
203 case COUNTRY_CODE_ISRAEL:
204 case COUNTRY_CODE_TELEC:
Xenia Ragiadakou88e5a932013-06-04 23:32:31 +0300205 case COUNTRY_CODE_MIC:
Patrik Karlinf00c4932013-01-09 09:39:44 +0100206 Dot11d_Init(ieee);
207 ieee->bGlobalDomain = false;
208 //actually 8225 & 8256 rf chips only support B,G,24N mode
209 if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256)) {
210 min_chan = 1;
211 max_chan = 14;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300212 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +0300213 RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __func__);
Patrik Karlinf00c4932013-01-09 09:39:44 +0100214 }
215 if (ChannelPlan[channel_plan].Len != 0) {
216 // Clear old channel map
217 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
218 // Set new channel map
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300219 for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
Patrik Karlinf00c4932013-01-09 09:39:44 +0100220 if (ChannelPlan[channel_plan].Channel[i] < min_chan || ChannelPlan[channel_plan].Channel[i] > max_chan)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200221 break;
Patrik Karlinf00c4932013-01-09 09:39:44 +0100222 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200223 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200224 }
Patrik Karlinf00c4932013-01-09 09:39:44 +0100225 break;
226
227 case COUNTRY_CODE_GLOBAL_DOMAIN:
228 GET_DOT11D_INFO(ieee)->bEnabled = 0;//this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain settings.
229 Dot11d_Reset(ieee);
230 ieee->bGlobalDomain = true;
231 break;
Xenia Ragiadakou88e5a932013-06-04 23:32:31 +0300232
Patrik Karlinf00c4932013-01-09 09:39:44 +0100233 default:
234 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200235 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200236}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200237
Jerry Chuang8fc85982009-11-03 07:17:11 -0200238
Jerry Chuang8fc85982009-11-03 07:17:11 -0200239
240
Ana Reyf4c60742014-03-13 12:36:38 +0100241static void CamResetAllEntry(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200242{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200243 u32 ulcommand = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200244 //2004/02/11 In static WEP, OID_ADD_KEY or OID_ADD_WEP are set before STA associate to AP.
245 // However, ResetKey is called on OID_802_11_INFRASTRUCTURE_MODE and MlmeAssociateRequest
246 // 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 -0200247 ulcommand |= BIT31|BIT30;
248 write_nic_dword(dev, RWCAM, ulcommand);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200249
250}
251
252
253void write_cam(struct net_device *dev, u8 addr, u32 data)
254{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200255 write_nic_dword(dev, WCAMI, data);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300256 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200257}
258
259u32 read_cam(struct net_device *dev, u8 addr)
260{
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300261 u32 data;
262
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300263 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff));
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300264 read_nic_dword(dev, 0xa8, &data);
265 return data;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200266}
267
268void write_nic_byte_E(struct net_device *dev, int indx, u8 data)
269{
270 int status;
271 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
272 struct usb_device *udev = priv->udev;
273
274 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300275 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
276 indx|0xfe00, 0, &data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200277
278 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300279 netdev_err(dev, "write_nic_byte_E TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200280}
281
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300282int read_nic_byte_E(struct net_device *dev, int indx, u8 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200283{
284 int status;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200285 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
286 struct usb_device *udev = priv->udev;
287
288 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300289 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300290 indx|0xfe00, 0, data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200291
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300292 if (status < 0) {
293 netdev_err(dev, "%s failure status: %d\n", __func__, status);
294 return status;
295 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200296
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300297 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200298}
299//as 92U has extend page from 4 to 16, so modify functions below.
300void write_nic_byte(struct net_device *dev, int indx, u8 data)
301{
302 int status;
303
304 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
305 struct usb_device *udev = priv->udev;
306
307 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300308 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
309 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200310
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200311 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300312 netdev_err(dev, "write_nic_byte TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200313
314
315}
316
317
318void write_nic_word(struct net_device *dev, int indx, u16 data)
319{
320
321 int status;
322
323 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
324 struct usb_device *udev = priv->udev;
325
326 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300327 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
328 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200329
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200330 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300331 netdev_err(dev, "write_nic_word TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200332
333}
334
335
336void write_nic_dword(struct net_device *dev, int indx, u32 data)
337{
338
339 int status;
340
341 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
342 struct usb_device *udev = priv->udev;
343
344 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300345 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
346 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200347
348
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200349 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300350 netdev_err(dev, "write_nic_dword TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200351
352}
353
354
355
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300356int read_nic_byte(struct net_device *dev, int indx, u8 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200357{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200358 int status;
359 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
360 struct usb_device *udev = priv->udev;
361
362 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300363 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300364 (indx&0xff)|0xff00, (indx>>8)&0x0f, data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200365
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300366 if (status < 0) {
367 netdev_err(dev, "%s failure status: %d\n", __func__, status);
368 return status;
369 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200370
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300371 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200372}
373
374
375
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300376int read_nic_word(struct net_device *dev, int indx, u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200377{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200378 int status;
379 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
380 struct usb_device *udev = priv->udev;
381
382 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300383 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
384 (indx&0xff)|0xff00, (indx>>8)&0x0f,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300385 data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200386
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300387 if (status < 0) {
388 netdev_err(dev, "%s failure status: %d\n", __func__, status);
389 return status;
390 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200391
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300392 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200393}
394
Teodora Baluta46326d22013-10-16 01:59:17 +0300395static int read_nic_word_E(struct net_device *dev, int indx, u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200396{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200397 int status;
398 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
399 struct usb_device *udev = priv->udev;
400
401 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300402 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300403 indx|0xfe00, 0, data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200404
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300405 if (status < 0) {
406 netdev_err(dev, "%s failure status: %d\n", __func__, status);
407 return status;
408 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200409
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300410 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200411}
412
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300413int read_nic_dword(struct net_device *dev, int indx, u32 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200414{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200415 int status;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200416
417 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
418 struct usb_device *udev = priv->udev;
419
420 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300421 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
422 (indx&0xff)|0xff00, (indx>>8)&0x0f,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300423 data, 4, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200424
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300425 if (status < 0) {
426 netdev_err(dev, "%s failure status: %d\n", __func__, status);
427 return status;
428 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200429
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300430 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200431}
432
Mike Gilks616f58f2010-06-03 18:29:23 +0800433/* u8 read_phy_cck(struct net_device *dev, u8 adr); */
434/* u8 read_phy_ofdm(struct net_device *dev, u8 adr); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200435/* this might still called in what was the PHY rtl8185/rtl8192 common code
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300436 * plans are to possibility turn it again in one common code...
Jerry Chuang8fc85982009-11-03 07:17:11 -0200437 */
438inline void force_pci_posting(struct net_device *dev)
439{
440}
441
Jerry Chuang8fc85982009-11-03 07:17:11 -0200442static struct net_device_stats *rtl8192_stats(struct net_device *dev);
443void rtl8192_commit(struct net_device *dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200444void rtl8192_restart(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200445void watch_dog_timer_callback(unsigned long data);
446
447/****************************************************************************
Mike Gilks616f58f2010-06-03 18:29:23 +0800448 * -----------------------------PROCFS STUFF-------------------------
449*****************************************************************************
450 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200451
Mike Gilks616f58f2010-06-03 18:29:23 +0800452static struct proc_dir_entry *rtl8192_proc;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200453
David Howells0541f9d2013-04-08 15:17:33 +0100454static int proc_get_stats_ap(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200455{
David Howells0541f9d2013-04-08 15:17:33 +0100456 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200457 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
458 struct ieee80211_device *ieee = priv->ieee80211;
459 struct ieee80211_network *target;
460
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200461 list_for_each_entry(target, &ieee->network_list, list) {
David Howells0541f9d2013-04-08 15:17:33 +0100462 const char *wpa = "non_WPA";
Mike Gilks616f58f2010-06-03 18:29:23 +0800463 if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0)
David Howells0541f9d2013-04-08 15:17:33 +0100464 wpa = "WPA";
465
466 seq_printf(m, "%s %s\n", target->ssid, wpa);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200467 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200468
David Howells0541f9d2013-04-08 15:17:33 +0100469 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200470}
471
David Howells0541f9d2013-04-08 15:17:33 +0100472static int proc_get_registers(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200473{
David Howells0541f9d2013-04-08 15:17:33 +0100474 struct net_device *dev = m->private;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300475 int i, n, max = 0xff;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300476 u8 byte_rd;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200477
David Howells0541f9d2013-04-08 15:17:33 +0100478 seq_puts(m, "\n####################page 0##################\n ");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200479
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300480 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300481 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200482
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300483 for (i = 0; i < 16 && n <= max; i++, n++) {
484 read_nic_byte(dev, 0x000|n, &byte_rd);
485 seq_printf(m, "%2x ", byte_rd);
486 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200487 }
David Howells0541f9d2013-04-08 15:17:33 +0100488
489 seq_puts(m, "\n####################page 1##################\n ");
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300490 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300491 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200492
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300493 for (i = 0; i < 16 && n <= max; i++, n++) {
494 read_nic_byte(dev, 0x100|n, &byte_rd);
495 seq_printf(m, "%2x ", byte_rd);
496 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200497 }
David Howells0541f9d2013-04-08 15:17:33 +0100498
499 seq_puts(m, "\n####################page 3##################\n ");
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300500 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300501 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200502
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300503 for (i = 0; i < 16 && n <= max; i++, n++) {
504 read_nic_byte(dev, 0x300|n, &byte_rd);
505 seq_printf(m, "%2x ", byte_rd);
506 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200507 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200508
David Howells0541f9d2013-04-08 15:17:33 +0100509 seq_putc(m, '\n');
510 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200511}
512
David Howells0541f9d2013-04-08 15:17:33 +0100513static int proc_get_stats_tx(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200514{
David Howells0541f9d2013-04-08 15:17:33 +0100515 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200516 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
517
David Howells0541f9d2013-04-08 15:17:33 +0100518 seq_printf(m,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300519 "TX VI priority ok int: %lu\n"
520 "TX VI priority error int: %lu\n"
521 "TX VO priority ok int: %lu\n"
522 "TX VO priority error int: %lu\n"
523 "TX BE priority ok int: %lu\n"
524 "TX BE priority error int: %lu\n"
525 "TX BK priority ok int: %lu\n"
526 "TX BK priority error int: %lu\n"
527 "TX MANAGE priority ok int: %lu\n"
528 "TX MANAGE priority error int: %lu\n"
529 "TX BEACON priority ok int: %lu\n"
530 "TX BEACON priority error int: %lu\n"
531 "TX queue resume: %lu\n"
532 "TX queue stopped?: %d\n"
533 "TX fifo overflow: %lu\n"
534 "TX VI queue: %d\n"
535 "TX VO queue: %d\n"
536 "TX BE queue: %d\n"
537 "TX BK queue: %d\n"
538 "TX VI dropped: %lu\n"
539 "TX VO dropped: %lu\n"
540 "TX BE dropped: %lu\n"
541 "TX BK dropped: %lu\n"
542 "TX total data packets %lu\n",
543 priv->stats.txviokint,
544 priv->stats.txvierr,
545 priv->stats.txvookint,
546 priv->stats.txvoerr,
547 priv->stats.txbeokint,
548 priv->stats.txbeerr,
549 priv->stats.txbkokint,
550 priv->stats.txbkerr,
551 priv->stats.txmanageokint,
552 priv->stats.txmanageerr,
553 priv->stats.txbeaconokint,
554 priv->stats.txbeaconerr,
555 priv->stats.txresumed,
556 netif_queue_stopped(dev),
557 priv->stats.txoverflow,
558 atomic_read(&(priv->tx_pending[VI_PRIORITY])),
559 atomic_read(&(priv->tx_pending[VO_PRIORITY])),
560 atomic_read(&(priv->tx_pending[BE_PRIORITY])),
561 atomic_read(&(priv->tx_pending[BK_PRIORITY])),
562 priv->stats.txvidrop,
563 priv->stats.txvodrop,
564 priv->stats.txbedrop,
565 priv->stats.txbkdrop,
566 priv->stats.txdatapkt
Jerry Chuang8fc85982009-11-03 07:17:11 -0200567 );
568
David Howells0541f9d2013-04-08 15:17:33 +0100569 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200570}
571
David Howells0541f9d2013-04-08 15:17:33 +0100572static int proc_get_stats_rx(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200573{
David Howells0541f9d2013-04-08 15:17:33 +0100574 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200575 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
576
David Howells0541f9d2013-04-08 15:17:33 +0100577 seq_printf(m,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300578 "RX packets: %lu\n"
579 "RX urb status error: %lu\n"
580 "RX invalid urb error: %lu\n",
581 priv->stats.rxoktotal,
582 priv->stats.rxstaterr,
583 priv->stats.rxurberr);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200584
David Howells0541f9d2013-04-08 15:17:33 +0100585 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200586}
David Howells0541f9d2013-04-08 15:17:33 +0100587
Teodora Baluta46326d22013-10-16 01:59:17 +0300588static void rtl8192_proc_module_init(void)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200589{
590 RT_TRACE(COMP_INIT, "Initializing proc filesystem");
Al Viroe55d92b2011-07-24 02:07:46 -0400591 rtl8192_proc = proc_mkdir(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200592}
593
David Howells0541f9d2013-04-08 15:17:33 +0100594/*
595 * seq_file wrappers for procfile show routines.
596 */
597static int rtl8192_proc_open(struct inode *inode, struct file *file)
598{
David Howells4a520d22013-04-12 14:06:01 +0100599 struct net_device *dev = proc_get_parent_data(inode);
David Howells0541f9d2013-04-08 15:17:33 +0100600 int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
601
602 return single_open(file, show, dev);
603}
604
605static const struct file_operations rtl8192_proc_fops = {
606 .open = rtl8192_proc_open,
607 .read = seq_read,
608 .llseek = seq_lseek,
Al Virobae301d2013-05-05 00:15:43 -0400609 .release = single_release,
David Howells0541f9d2013-04-08 15:17:33 +0100610};
611
612/*
613 * Table of proc files we need to create.
614 */
615struct rtl8192_proc_file {
616 char name[12];
617 int (*show)(struct seq_file *, void *);
618};
619
620static const struct rtl8192_proc_file rtl8192_proc_files[] = {
621 { "stats-rx", &proc_get_stats_rx },
622 { "stats-tx", &proc_get_stats_tx },
623 { "stats-ap", &proc_get_stats_ap },
624 { "registers", &proc_get_registers },
625 { "" }
626};
627
Teodora Baluta46326d22013-10-16 01:59:17 +0300628static void rtl8192_proc_init_one(struct net_device *dev)
David Howells0541f9d2013-04-08 15:17:33 +0100629{
630 const struct rtl8192_proc_file *f;
David Howellscc87e0f2013-04-12 03:02:22 +0100631 struct proc_dir_entry *dir;
David Howells0541f9d2013-04-08 15:17:33 +0100632
633 if (rtl8192_proc) {
David Howellscc87e0f2013-04-12 03:02:22 +0100634 dir = proc_mkdir_data(dev->name, 0, rtl8192_proc, dev);
635 if (!dir) {
David Howells0541f9d2013-04-08 15:17:33 +0100636 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
637 dev->name);
638 return;
639 }
David Howells0541f9d2013-04-08 15:17:33 +0100640
641 for (f = rtl8192_proc_files; f->name[0]; f++) {
David Howellscc87e0f2013-04-12 03:02:22 +0100642 if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir,
643 &rtl8192_proc_fops, f->show)) {
David Howells0541f9d2013-04-08 15:17:33 +0100644 RT_TRACE(COMP_ERR, "Unable to initialize "
645 "/proc/net/rtl8192/%s/%s\n",
646 dev->name, f->name);
647 return;
648 }
649 }
650 }
651}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200652
Teodora Baluta46326d22013-10-16 01:59:17 +0300653static void rtl8192_proc_remove_one(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200654{
David Howellscc87e0f2013-04-12 03:02:22 +0100655 remove_proc_subtree(dev->name, rtl8192_proc);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200656}
657
Jerry Chuang8fc85982009-11-03 07:17:11 -0200658/****************************************************************************
659 -----------------------------MISC STUFF-------------------------
660*****************************************************************************/
661
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300662short check_nic_enough_desc(struct net_device *dev, int queue_index)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200663{
664 struct r8192_priv *priv = ieee80211_priv(dev);
665 int used = atomic_read(&priv->tx_pending[queue_index]);
666
667 return (used < MAX_TX_URB);
668}
669
Ana Reyf4c60742014-03-13 12:36:38 +0100670static void tx_timeout(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200671{
672 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200673
Jerry Chuang8fc85982009-11-03 07:17:11 -0200674 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200675}
676
677
678/* this is only for debug */
679void dump_eprom(struct net_device *dev)
680{
681 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300682 for (i = 0; i < 63; i++)
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300683 RT_TRACE(COMP_EPROM, "EEPROM addr %x : %x", i, eprom_read(dev, i));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200684}
685
Jerry Chuang8fc85982009-11-03 07:17:11 -0200686void rtl8192_update_msr(struct net_device *dev)
687{
688 struct r8192_priv *priv = ieee80211_priv(dev);
689 u8 msr;
690
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300691 read_nic_byte(dev, MSR, &msr);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300692 msr &= ~MSR_LINK_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200693
694 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
695 * msr must be updated if the state is ASSOCIATING.
696 * this is intentional and make sense for ad-hoc and
697 * master (see the create BSS/IBSS func)
698 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300699 if (priv->ieee80211->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200700
701 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
702 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
703 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
704 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
705 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
706 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
707
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300708 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200709 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300710 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200711
712 write_nic_byte(dev, MSR, msr);
713}
714
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300715void rtl8192_set_chan(struct net_device *dev, short ch)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200716{
717 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +0300718 RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __func__, ch);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300719 priv->chan = ch;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200720
721 /* this hack should avoid frame TX during channel setting*/
722
Jerry Chuang8fc85982009-11-03 07:17:11 -0200723#ifndef LOOP_TEST
Jerry Chuang8fc85982009-11-03 07:17:11 -0200724 //need to implement rf set channel here WB
725
726 if (priv->rf_set_chan)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300727 priv->rf_set_chan(dev, priv->chan);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200728 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200729#endif
730}
731
Jerry Chuang8fc85982009-11-03 07:17:11 -0200732static void rtl8192_rx_isr(struct urb *urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200733
Teodora Baluta46326d22013-10-16 01:59:17 +0300734static u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200735{
736
737#ifdef USB_RX_AGGREGATION_SUPPORT
738 if (pstats->bisrxaggrsubframe)
739 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
740 + pstats->RxBufShift + 8);
741 else
742#endif
743 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300744 + pstats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200745
746}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300747static int rtl8192_rx_initiate(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200748{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200749 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
750 struct urb *entry;
751 struct sk_buff *skb;
752 struct rtl8192_rx_info *info;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200753
754 /* nomal packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200755 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB) {
756 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
757 if (!skb)
758 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200759 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200760 if (!entry) {
761 kfree_skb(skb);
762 break;
763 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200764 usb_fill_bulk_urb(entry, priv->udev,
765 usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb),
766 RX_URB_SIZE, rtl8192_rx_isr, skb);
767 info = (struct rtl8192_rx_info *) skb->cb;
768 info->urb = entry;
769 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200770 info->out_pipe = 3; //denote rx normal packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200771 skb_queue_tail(&priv->rx_queue, skb);
772 usb_submit_urb(entry, GFP_KERNEL);
773 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200774
775 /* command packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200776 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300777 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200778 if (!skb)
779 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200780 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200781 if (!entry) {
782 kfree_skb(skb);
783 break;
784 }
785 usb_fill_bulk_urb(entry, priv->udev,
786 usb_rcvbulkpipe(priv->udev, 9), skb_tail_pointer(skb),
787 RX_URB_SIZE, rtl8192_rx_isr, skb);
788 info = (struct rtl8192_rx_info *) skb->cb;
789 info->urb = entry;
790 info->dev = dev;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300791 info->out_pipe = 9; //denote rx cmd packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200792 skb_queue_tail(&priv->rx_queue, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200793 usb_submit_urb(entry, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200794 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200795
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200796 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200797}
798
799void rtl8192_set_rxconf(struct net_device *dev)
800{
801 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
802 u32 rxconf;
803
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300804 read_nic_dword(dev, RCR, &rxconf);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300805 rxconf = rxconf & ~MAC_FILTER_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200806 rxconf = rxconf | RCR_AMF;
807 rxconf = rxconf | RCR_ADF;
808 rxconf = rxconf | RCR_AB;
809 rxconf = rxconf | RCR_AM;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200810
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300811 if (dev->flags & IFF_PROMISC)
812 DMESG("NIC in promisc mode");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200813
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300814 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300815 dev->flags & IFF_PROMISC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200816 rxconf = rxconf | RCR_AAP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300817 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200818 rxconf = rxconf | RCR_APM;
819 rxconf = rxconf | RCR_CBSSID;
820 }
821
822
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300823 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200824 rxconf = rxconf | RCR_AICV;
825 rxconf = rxconf | RCR_APWRMGT;
826 }
827
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300828 if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200829 rxconf = rxconf | RCR_ACRC32;
830
831
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300832 rxconf = rxconf & ~RX_FIFO_THRESHOLD_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200833 rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE<<RX_FIFO_THRESHOLD_SHIFT);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300834 rxconf = rxconf & ~MAX_RX_DMA_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200835 rxconf = rxconf | ((u32)7<<RCR_MXDMA_OFFSET);
836
Jerry Chuang8fc85982009-11-03 07:17:11 -0200837 rxconf = rxconf | RCR_ONLYERLPKT;
838
Jerry Chuang8fc85982009-11-03 07:17:11 -0200839 write_nic_dword(dev, RCR, rxconf);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200840}
841//wait to be removed
842void rtl8192_rx_enable(struct net_device *dev)
843{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200844 rtl8192_rx_initiate(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200845}
846
847
848void rtl8192_tx_enable(struct net_device *dev)
849{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200850}
851
Jerry Chuang8fc85982009-11-03 07:17:11 -0200852
853
854void rtl8192_rtx_disable(struct net_device *dev)
855{
856 u8 cmd;
857 struct r8192_priv *priv = ieee80211_priv(dev);
858 struct sk_buff *skb;
859 struct rtl8192_rx_info *info;
860
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300861 read_nic_byte(dev, CMDR, &cmd);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300862 write_nic_byte(dev, CMDR, cmd & ~(CR_TE|CR_RE));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200863 force_pci_posting(dev);
864 mdelay(10);
865
866 while ((skb = __skb_dequeue(&priv->rx_queue))) {
867 info = (struct rtl8192_rx_info *) skb->cb;
868 if (!info->urb)
869 continue;
870
871 usb_kill_urb(info->urb);
872 kfree_skb(skb);
873 }
874
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300875 if (skb_queue_len(&priv->skb_queue))
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300876 netdev_warn(dev, "skb_queue not empty\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200877
878 skb_queue_purge(&priv->skb_queue);
879 return;
880}
881
Jerry Chuang8fc85982009-11-03 07:17:11 -0200882inline u16 ieeerate2rtlrate(int rate)
883{
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300884 switch (rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200885 case 10:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300886 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200887 case 20:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300888 return 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200889 case 55:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300890 return 2;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200891 case 110:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300892 return 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200893 case 60:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300894 return 4;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200895 case 90:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300896 return 5;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200897 case 120:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300898 return 6;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200899 case 180:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300900 return 7;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200901 case 240:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300902 return 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200903 case 360:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300904 return 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200905 case 480:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300906 return 10;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200907 case 540:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300908 return 11;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200909 default:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300910 return 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200911
912 }
913}
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300914static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
Jerry Chuang8fc85982009-11-03 07:17:11 -0200915inline u16 rtl8192_rate2rate(short rate)
916{
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300917 if (rate > 11) return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200918 return rtl_rate[rate];
919}
920
921
Justin P. Mattock589b3d02012-04-30 07:41:36 -0700922/* The prototype of rx_isr has changed since one version of Linux Kernel */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200923static void rtl8192_rx_isr(struct urb *urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200924{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200925 struct sk_buff *skb = (struct sk_buff *) urb->context;
926 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
927 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200928 struct r8192_priv *priv = ieee80211_priv(dev);
929 int out_pipe = info->out_pipe;
930 int err;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300931 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200932 return;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200933 if (unlikely(urb->status)) {
934 info->urb = NULL;
935 priv->stats.rxstaterr++;
936 priv->ieee80211->stats.rx_errors++;
937 usb_free_urb(urb);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200938 return;
939 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200940 skb_unlink(skb, &priv->rx_queue);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200941 skb_put(skb, urb->actual_length);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200942
943 skb_queue_tail(&priv->skb_queue, skb);
944 tasklet_schedule(&priv->irq_rx_tasklet);
945
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200946 skb = dev_alloc_skb(RX_URB_SIZE);
947 if (unlikely(!skb)) {
948 usb_free_urb(urb);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300949 netdev_err(dev, "%s(): can't alloc skb\n", __func__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200950 /* TODO check rx queue length and refill *somewhere* */
951 return;
952 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200953
954 usb_fill_bulk_urb(urb, priv->udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300955 usb_rcvbulkpipe(priv->udev, out_pipe), skb_tail_pointer(skb),
956 RX_URB_SIZE, rtl8192_rx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200957
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200958 info = (struct rtl8192_rx_info *) skb->cb;
959 info->urb = urb;
960 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200961 info->out_pipe = out_pipe;
962
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200963 urb->transfer_buffer = skb_tail_pointer(skb);
964 urb->context = skb;
965 skb_queue_tail(&priv->rx_queue, skb);
966 err = usb_submit_urb(urb, GFP_ATOMIC);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300967 if (err && err != EPERM)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300968 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 -0200969}
970
Teodora Baluta46326d22013-10-16 01:59:17 +0300971static u32 rtl819xusb_rx_command_packet(struct net_device *dev,
972 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200973{
974 u32 status;
975
Jerry Chuang8fc85982009-11-03 07:17:11 -0200976 status = cmpk_message_handle_rx(dev, pstats);
977 if (status)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200978 DMESG("rxcommandpackethandle819xusb: It is a command packet\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200979
Jerry Chuang8fc85982009-11-03 07:17:11 -0200980 return status;
981}
982
Jerry Chuang8fc85982009-11-03 07:17:11 -0200983
Ana Reyf4c60742014-03-13 12:36:38 +0100984static void rtl8192_data_hard_stop(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200985{
986 //FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -0200987}
988
989
Ana Reyf4c60742014-03-13 12:36:38 +0100990static void rtl8192_data_hard_resume(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200991{
992 // FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -0200993}
994
995/* this function TX data frames when the ieee80211 stack requires this.
996 * It checks also if we need to stop the ieee tx queue, eventually do it
997 */
Ana Reyf4c60742014-03-13 12:36:38 +0100998static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200999{
1000 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1001 int ret;
1002 unsigned long flags;
1003 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1004 u8 queue_index = tcb_desc->queue_index;
1005
1006 /* shall not be referred by command packet */
Xenia Ragiadakou4a8d1132013-06-09 14:38:43 +03001007 RTL8192U_ASSERT(queue_index != TXCMD_QUEUE);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001008
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001009 spin_lock_irqsave(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001010
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001011 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001012 tcb_desc->bTxEnableFwCalcDur = 1;
1013 skb_push(skb, priv->ieee80211->tx_headroom);
1014 ret = rtl8192_tx(dev, skb);
1015
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001016 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001017
Jerry Chuang8fc85982009-11-03 07:17:11 -02001018 return;
1019}
1020
1021/* This is a rough attempt to TX a frame
1022 * This is called by the ieee 80211 stack to TX management frames.
1023 * If the ring is full packet are dropped (for data frame the queue
1024 * is stopped before this can happen).
1025 */
Ana Reyf4c60742014-03-13 12:36:38 +01001026static int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001027{
1028 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1029 int ret;
1030 unsigned long flags;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001031 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1032 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001033
1034
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001035 spin_lock_irqsave(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001036
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001037 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001038 if (queue_index == TXCMD_QUEUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001039 skb_push(skb, USB_HWDESC_HEADER_LEN);
1040 rtl819xU_tx_cmd(dev, skb);
1041 ret = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001042 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001043 return ret;
1044 } else {
1045 skb_push(skb, priv->ieee80211->tx_headroom);
1046 ret = rtl8192_tx(dev, skb);
1047 }
1048
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001049 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001050
1051 return ret;
1052}
1053
1054
1055void rtl8192_try_wake_queue(struct net_device *dev, int pri);
1056
1057#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1058u16 DrvAggr_PaddingAdd(struct net_device *dev, struct sk_buff *skb)
1059{
1060 u16 PaddingNum = 256 - ((skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES) % 256);
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03001061 return PaddingNum & 0xff;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001062}
1063
1064u8 MRateToHwRate8190Pci(u8 rate);
1065u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc);
1066u8 MapHwQueueToFirmwareQueue(u8 QueueID);
1067struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv_agg_txb *pSendList)
1068{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001069 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001070 struct r8192_priv *priv = ieee80211_priv(dev);
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001071 cb_desc *tcb_desc = NULL;
1072 u8 i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001073 u32 TotalLength;
1074 struct sk_buff *skb;
1075 struct sk_buff *agg_skb;
1076 tx_desc_819x_usb_aggr_subframe *tx_agg_desc = NULL;
1077 tx_fwinfo_819x_usb *tx_fwinfo = NULL;
1078
1079 //
1080 // Local variable initialization.
1081 //
1082 /* first skb initialization */
1083 skb = pSendList->tx_agg_frames[0];
1084 TotalLength = skb->len;
1085
1086 /* Get the total aggregation length including the padding space and
1087 * sub frame header.
1088 */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001089 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001090 TotalLength += DrvAggr_PaddingAdd(dev, skb);
1091 skb = pSendList->tx_agg_frames[i];
1092 TotalLength += (skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1093 }
1094
1095 /* allocate skb to contain the aggregated packets */
1096 agg_skb = dev_alloc_skb(TotalLength + ieee->tx_headroom);
1097 memset(agg_skb->data, 0, agg_skb->len);
1098 skb_reserve(agg_skb, ieee->tx_headroom);
1099
Jerry Chuang8fc85982009-11-03 07:17:11 -02001100 /* reserve info for first subframe Tx descriptor to be set in the tx function */
1101 skb = pSendList->tx_agg_frames[0];
1102 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1103 tcb_desc->drv_agg_enable = 1;
1104 tcb_desc->pkt_size = skb->len;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001105 tcb_desc->DrvAggrNum = pSendList->nr_drv_agg_frames;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001106 netdev_dbg(dev, "DrvAggNum = %d\n", tcb_desc->DrvAggrNum);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001107 memcpy(agg_skb->cb, skb->cb, sizeof(skb->cb));
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001108 memcpy(skb_put(agg_skb, skb->len), skb->data, skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001109
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001110 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001111 /* push the next sub frame to be 256 byte aline */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001112 skb_put(agg_skb, DrvAggr_PaddingAdd(dev, skb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001113
1114 /* Subframe drv Tx descriptor and firmware info setting */
1115 skb = pSendList->tx_agg_frames[i];
1116 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Isaku Yamahataa267a602013-06-14 17:58:35 +09001117 tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)skb_tail_pointer(agg_skb);
1118 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 -02001119
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001120 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001121 /* DWORD 0 */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001122 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001123 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1124 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1125 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001126 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001127 tx_fwinfo->AllowAggregation = 1;
1128 /* DWORD 1 */
1129 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1130 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1131 } else {
1132 tx_fwinfo->AllowAggregation = 0;
1133 /* DWORD 1 */
1134 tx_fwinfo->RxMF = 0;
1135 tx_fwinfo->RxAMD = 0;
1136 }
1137
1138 /* Protection mode related */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001139 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1140 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1141 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1142 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001143 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001144 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->RTSSC) : 0;
1145 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1) ? ((tcb_desc->bRTSBW) ? 1 : 0) : 0;
1146 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) :
1147 (tcb_desc->bRTSUseShortGI ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001148
1149 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001150 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001151 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001152 tx_fwinfo->TxBandwidth = 1;
1153 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1154 } else {
1155 tx_fwinfo->TxBandwidth = 0;
1156 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1157 }
1158 } else {
1159 tx_fwinfo->TxBandwidth = 0;
1160 tx_fwinfo->TxSubCarrier = 0;
1161 }
1162
1163 /* Fill Tx descriptor */
1164 memset(tx_agg_desc, 0, sizeof(tx_desc_819x_usb_aggr_subframe));
1165 /* DWORD 0 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001166 tx_agg_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001167 /* already raw data, need not to subtract header length */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001168 tx_agg_desc->PktSize = skb->len & 0xffff;
1169
1170 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001171 tx_agg_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001172 tx_agg_desc->RATid = tcb_desc->RATRIndex;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001173 tx_agg_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001174 tx_agg_desc->SecType = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001175
1176 if (tcb_desc->bHwSec) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001177 switch (priv->ieee80211->pairwise_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001178 case KEY_TYPE_WEP40:
1179 case KEY_TYPE_WEP104:
1180 tx_agg_desc->SecType = 0x1;
1181 tx_agg_desc->NoEnc = 0;
1182 break;
1183 case KEY_TYPE_TKIP:
1184 tx_agg_desc->SecType = 0x2;
1185 tx_agg_desc->NoEnc = 0;
1186 break;
1187 case KEY_TYPE_CCMP:
1188 tx_agg_desc->SecType = 0x3;
1189 tx_agg_desc->NoEnc = 0;
1190 break;
1191 case KEY_TYPE_NA:
1192 tx_agg_desc->SecType = 0x0;
1193 tx_agg_desc->NoEnc = 1;
1194 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001195 }
1196 }
1197
1198 tx_agg_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1199 tx_agg_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1200
1201 tx_agg_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1202 tx_agg_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1203
1204 tx_agg_desc->OWN = 1;
1205
1206 //DWORD 2
1207 /* According windows driver, it seems that there no need to fill this field */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001208
1209 /* to fill next packet */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001210 skb_put(agg_skb, TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1211 memcpy(skb_put(agg_skb, skb->len), skb->data, skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001212 }
1213
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001214 for (i = 0; i < pSendList->nr_drv_agg_frames; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001215 dev_kfree_skb_any(pSendList->tx_agg_frames[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001216
1217 return agg_skb;
1218}
1219
1220/* NOTE:
1221 This function return a list of PTCB which is proper to be aggregate with the input TCB.
1222 If no proper TCB is found to do aggregation, SendList will only contain the input TCB.
1223*/
1224u8 DrvAggr_GetAggregatibleList(struct net_device *dev, struct sk_buff *skb,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001225 struct ieee80211_drv_agg_txb *pSendList)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001226{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001227 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001228 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1229 u16 nMaxAggrNum = pHTInfo->UsbTxAggrNum;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001230 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001231 u8 QueueID = tcb_desc->queue_index;
1232
1233 do {
1234 pSendList->tx_agg_frames[pSendList->nr_drv_agg_frames++] = skb;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001235 if (pSendList->nr_drv_agg_frames >= nMaxAggrNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001236 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001237
Xenia Ragiadakou53c7f3c2013-05-22 18:22:35 +03001238 } while ((skb = skb_dequeue(&ieee->skb_drv_aggQ[QueueID])));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001239
1240 RT_TRACE(COMP_AMSDU, "DrvAggr_GetAggregatibleList, nAggrTcbNum = %d \n", pSendList->nr_drv_agg_frames);
1241 return pSendList->nr_drv_agg_frames;
1242}
1243#endif
1244
Jerry Chuang8fc85982009-11-03 07:17:11 -02001245static void rtl8192_tx_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001246{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001247 struct sk_buff *skb = (struct sk_buff *)tx_urb->context;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001248 struct net_device *dev = NULL;
1249 struct r8192_priv *priv = NULL;
1250 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1251 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001252
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001253 memcpy(&dev, (struct net_device *)(skb->cb), sizeof(struct net_device *));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001254 priv = ieee80211_priv(dev);
1255
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001256 if (tcb_desc->queue_index != TXCMD_QUEUE) {
1257 if (tx_urb->status == 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001258 dev->trans_start = jiffies;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001259 priv->stats.txoktotal++;
1260 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
1261 priv->stats.txbytesunicast += (skb->len - priv->ieee80211->tx_headroom);
1262 } else {
1263 priv->ieee80211->stats.tx_errors++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001264 /* TODO */
1265 }
1266 }
1267
1268 /* free skb and tx_urb */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001269 if (skb != NULL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001270 dev_kfree_skb_any(skb);
1271 usb_free_urb(tx_urb);
1272 atomic_dec(&priv->tx_pending[queue_index]);
1273 }
1274
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001275 //
1276 // Handle HW Beacon:
1277 // We had transfer our beacon frame to host controller at this moment.
1278 //
1279 //
1280 // Caution:
1281 // Handling the wait queue of command packets.
1282 // For Tx command packets, we must not do TCB fragment because it is not handled right now.
1283 // We must cut the packets to match the size of TX_CMD_PKT before we send it.
1284 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02001285
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001286 /* Handle MPDU in wait queue. */
1287 if (queue_index != BEACON_QUEUE) {
1288 /* Don't send data frame during scanning.*/
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001289 if ((skb_queue_len(&priv->ieee80211->skb_waitQ[queue_index]) != 0) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001290 (!(priv->ieee80211->queue_stop))) {
Chi Pham09adb6e2014-03-10 22:31:52 +01001291 skb = skb_dequeue(&(priv->ieee80211->skb_waitQ[queue_index]));
1292 if (skb)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001293 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001294
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001295 return; //modified by david to avoid further processing AMSDU
Jerry Chuang8fc85982009-11-03 07:17:11 -02001296 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001297#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001298 else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index]) != 0) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001299 (!(priv->ieee80211->queue_stop))) {
1300 // Tx Driver Aggregation process
1301 /* The driver will aggregation the packets according to the following stats
1302 * 1. check whether there's tx irq available, for it's a completion return
1303 * function, it should contain enough tx irq;
1304 * 2. check packet type;
1305 * 3. initialize sendlist, check whether the to-be send packet no greater than 1
1306 * 4. aggregates the packets, and fill firmware info and tx desc into it, etc.
1307 * 5. check whether the packet could be sent, otherwise just insert into wait head
1308 * */
1309 skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]);
1310 if (!check_nic_enough_desc(dev, queue_index)) {
1311 skb_queue_head(&(priv->ieee80211->skb_drv_aggQ[queue_index]), skb);
1312 return;
1313 }
1314
1315 /*TODO*/
1316 {
1317 struct ieee80211_drv_agg_txb SendList;
1318
1319 memset(&SendList, 0, sizeof(struct ieee80211_drv_agg_txb));
1320 if (DrvAggr_GetAggregatibleList(dev, skb, &SendList) > 1) {
1321 skb = DrvAggr_Aggregation(dev, &SendList);
1322
1323 }
1324 }
1325 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1326 }
1327#endif
1328 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001329
Jerry Chuang8fc85982009-11-03 07:17:11 -02001330}
1331
Ana Reyf4c60742014-03-13 12:36:38 +01001332static void rtl8192_config_rate(struct net_device *dev, u16 *rate_config)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001333{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001334 struct r8192_priv *priv = ieee80211_priv(dev);
1335 struct ieee80211_network *net;
1336 u8 i = 0, basic_rate = 0;
Xenia Ragiadakou003a2d12013-06-04 23:32:29 +03001337 net = &priv->ieee80211->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001338
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001339 for (i = 0; i < net->rates_len; i++) {
1340 basic_rate = net->rates[i]&0x7f;
1341 switch (basic_rate) {
1342 case MGN_1M: *rate_config |= RRSR_1M; break;
1343 case MGN_2M: *rate_config |= RRSR_2M; break;
1344 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1345 case MGN_11M: *rate_config |= RRSR_11M; break;
1346 case MGN_6M: *rate_config |= RRSR_6M; break;
1347 case MGN_9M: *rate_config |= RRSR_9M; break;
1348 case MGN_12M: *rate_config |= RRSR_12M; break;
1349 case MGN_18M: *rate_config |= RRSR_18M; break;
1350 case MGN_24M: *rate_config |= RRSR_24M; break;
1351 case MGN_36M: *rate_config |= RRSR_36M; break;
1352 case MGN_48M: *rate_config |= RRSR_48M; break;
1353 case MGN_54M: *rate_config |= RRSR_54M; break;
1354 }
1355 }
1356 for (i = 0; i < net->rates_ex_len; i++) {
1357 basic_rate = net->rates_ex[i]&0x7f;
1358 switch (basic_rate) {
1359 case MGN_1M: *rate_config |= RRSR_1M; break;
1360 case MGN_2M: *rate_config |= RRSR_2M; break;
1361 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1362 case MGN_11M: *rate_config |= RRSR_11M; break;
1363 case MGN_6M: *rate_config |= RRSR_6M; break;
1364 case MGN_9M: *rate_config |= RRSR_9M; break;
1365 case MGN_12M: *rate_config |= RRSR_12M; break;
1366 case MGN_18M: *rate_config |= RRSR_18M; break;
1367 case MGN_24M: *rate_config |= RRSR_24M; break;
1368 case MGN_36M: *rate_config |= RRSR_36M; break;
1369 case MGN_48M: *rate_config |= RRSR_48M; break;
1370 case MGN_54M: *rate_config |= RRSR_54M; break;
1371 }
1372 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001373}
1374
1375
1376#define SHORT_SLOT_TIME 9
1377#define NON_SHORT_SLOT_TIME 20
1378
Ana Reyf4c60742014-03-13 12:36:38 +01001379static void rtl8192_update_cap(struct net_device *dev, u16 cap)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001380{
1381 u32 tmp = 0;
1382 struct r8192_priv *priv = ieee80211_priv(dev);
1383 struct ieee80211_network *net = &priv->ieee80211->current_network;
1384 priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
1385 tmp = priv->basic_rate;
1386 if (priv->short_preamble)
1387 tmp |= BRSR_AckShortPmb;
1388 write_nic_dword(dev, RRSR, tmp);
1389
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001390 if (net->mode & (IEEE_G|IEEE_N_24G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001391 u8 slot_time = 0;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001392 if ((cap & WLAN_CAPABILITY_SHORT_SLOT) && (!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime)) //short slot time
Jerry Chuang8fc85982009-11-03 07:17:11 -02001393 slot_time = SHORT_SLOT_TIME;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001394 else //long slot time
1395 slot_time = NON_SHORT_SLOT_TIME;
1396 priv->slot_time = slot_time;
1397 write_nic_byte(dev, SLOT_TIME, slot_time);
1398 }
1399
1400}
Ana Reyf4c60742014-03-13 12:36:38 +01001401static void rtl8192_net_update(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001402{
1403
1404 struct r8192_priv *priv = ieee80211_priv(dev);
1405 struct ieee80211_network *net;
1406 u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
1407 u16 rate_config = 0;
Xenia Ragiadakou003a2d12013-06-04 23:32:29 +03001408 net = &priv->ieee80211->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001409
1410 rtl8192_config_rate(dev, &rate_config);
1411 priv->basic_rate = rate_config &= 0x15f;
1412
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001413 write_nic_dword(dev, BSSIDR, ((u32 *)net->bssid)[0]);
1414 write_nic_word(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001415
1416 rtl8192_update_msr(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001417 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001418 write_nic_word(dev, ATIMWND, 2);
1419 write_nic_word(dev, BCN_DMATIME, 1023);
1420 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
1421 write_nic_word(dev, BCN_DRV_EARLY_INT, 1);
1422 write_nic_byte(dev, BCN_ERR_THRESH, 100);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001423 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001424 // TODO: BcnIFS may required to be changed on ASIC
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001425 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001426
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001427 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001428 }
1429
1430
1431
1432}
1433
1434//temporary hw beacon is not used any more.
1435//open it when necessary
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001436void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001437{
1438
Jerry Chuang8fc85982009-11-03 07:17:11 -02001439}
Jerry Chuang8fc85982009-11-03 07:17:11 -02001440inline u8 rtl8192_IsWirelessBMode(u16 rate)
1441{
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03001442 if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220))
Jerry Chuang8fc85982009-11-03 07:17:11 -02001443 return 1;
1444 else return 0;
1445}
1446
1447u16 N_DBPSOfRate(u16 DataRate);
1448
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03001449u16 ComputeTxTime(u16 FrameLength, u16 DataRate, u8 bManagementFrame,
1450 u8 bShortPreamble)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001451{
1452 u16 FrameTime;
1453 u16 N_DBPS;
1454 u16 Ceiling;
1455
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001456 if (rtl8192_IsWirelessBMode(DataRate)) {
1457 if (bManagementFrame || !bShortPreamble || DataRate == 10) // long preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001458 FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001459 else // Short preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001460 FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03001461 if ((FrameLength*8 % (DataRate/10)) != 0) //Get the Ceilling
Xenia Ragiadakou7d79ec62013-06-04 23:32:30 +03001462 FrameTime++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001463 } else { //802.11g DSSS-OFDM PLCP length field calculation.
1464 N_DBPS = N_DBPSOfRate(DataRate);
1465 Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001466 + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001467 FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
1468 }
1469 return FrameTime;
1470}
1471
1472u16 N_DBPSOfRate(u16 DataRate)
1473{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001474 u16 N_DBPS = 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001475
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001476 switch (DataRate) {
1477 case 60:
1478 N_DBPS = 24;
1479 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001480
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001481 case 90:
1482 N_DBPS = 36;
1483 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001484
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001485 case 120:
1486 N_DBPS = 48;
1487 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001488
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001489 case 180:
1490 N_DBPS = 72;
1491 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001492
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001493 case 240:
1494 N_DBPS = 96;
1495 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001496
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001497 case 360:
1498 N_DBPS = 144;
1499 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001500
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001501 case 480:
1502 N_DBPS = 192;
1503 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001504
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001505 case 540:
1506 N_DBPS = 216;
1507 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001508
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001509 default:
1510 break;
1511 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001512
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001513 return N_DBPS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001514}
1515
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001516unsigned int txqueue2outpipe(struct r8192_priv *priv, unsigned int tx_queue)
1517{
1518 if (tx_queue >= 9) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03001519 RT_TRACE(COMP_ERR, "%s():Unknown queue ID!!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001520 return 0x04;
1521 }
1522 return priv->txqueue_to_outpipemap[tx_queue];
1523}
1524
1525short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
1526{
1527 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001528 int status;
1529 struct urb *tx_urb;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001530 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001531 tx_desc_cmd_819x_usb *pdesc = (tx_desc_cmd_819x_usb *)skb->data;
1532 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1533 u8 queue_index = tcb_desc->queue_index;
1534
Jerry Chuang8fc85982009-11-03 07:17:11 -02001535 atomic_inc(&priv->tx_pending[queue_index]);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001536 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001537 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001538 dev_kfree_skb(skb);
1539 return -ENOMEM;
1540 }
1541
1542 memset(pdesc, 0, USB_HWDESC_HEADER_LEN);
1543 /* Tx descriptor ought to be set according to the skb->cb */
1544 pdesc->FirstSeg = 1;//bFirstSeg;
1545 pdesc->LastSeg = 1;//bLastSeg;
1546 pdesc->CmdInit = tcb_desc->bCmdOrInit;
1547 pdesc->TxBufferSize = tcb_desc->txbuf_size;
1548 pdesc->OWN = 1;
1549 pdesc->LINIP = tcb_desc->bLastIniPkt;
1550
1551 //----------------------------------------------------------------------------
1552 // Fill up USB_OUT_CONTEXT.
1553 //----------------------------------------------------------------------------
1554 // Get index to out pipe from specified QueueID.
1555#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001556 idx_pipe = txqueue2outpipe(priv, queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001557#else
1558 idx_pipe = 0x04;
1559#endif
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03001560 usb_fill_bulk_urb(tx_urb, priv->udev, usb_sndbulkpipe(priv->udev, idx_pipe),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001561 skb->data, skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001562
Jerry Chuang8fc85982009-11-03 07:17:11 -02001563 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001564
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001565 if (!status) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001566 return 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001567 } else {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001568 DMESGE("Error TX CMD URB, error %d", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001569 return -1;
1570 }
1571}
1572
1573/*
1574 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1575 * in TxFwInfo data structure
1576 * 2006.10.30 by Emily
1577 *
1578 * \param QUEUEID Software Queue
1579*/
Teodora Baluta46326d22013-10-16 01:59:17 +03001580static u8 MapHwQueueToFirmwareQueue(u8 QueueID)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001581{
1582 u8 QueueSelect = 0x0; //defualt set to
1583
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001584 switch (QueueID) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001585 case BE_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001586 QueueSelect = QSLT_BE;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001587 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001588
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001589 case BK_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001590 QueueSelect = QSLT_BK;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001591 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001592
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001593 case VO_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001594 QueueSelect = QSLT_VO;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001595 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001596
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001597 case VI_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001598 QueueSelect = QSLT_VI;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001599 break;
1600 case MGNT_QUEUE:
1601 QueueSelect = QSLT_MGNT;
1602 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001603
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001604 case BEACON_QUEUE:
1605 QueueSelect = QSLT_BEACON;
1606 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001607
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001608 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
1609 // TODO: Remove Assertions
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001610 case TXCMD_QUEUE:
1611 QueueSelect = QSLT_CMD;
1612 break;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001613 case HIGH_QUEUE:
1614 QueueSelect = QSLT_HIGH;
1615 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001616
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001617 default:
1618 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
1619 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001620 }
1621 return QueueSelect;
1622}
1623
Ana Reyf4c60742014-03-13 12:36:38 +01001624static u8 MRateToHwRate8190Pci(u8 rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001625{
1626 u8 ret = DESC90_RATE1M;
1627
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001628 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001629 case MGN_1M: ret = DESC90_RATE1M; break;
1630 case MGN_2M: ret = DESC90_RATE2M; break;
1631 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1632 case MGN_11M: ret = DESC90_RATE11M; break;
1633 case MGN_6M: ret = DESC90_RATE6M; break;
1634 case MGN_9M: ret = DESC90_RATE9M; break;
1635 case MGN_12M: ret = DESC90_RATE12M; break;
1636 case MGN_18M: ret = DESC90_RATE18M; break;
1637 case MGN_24M: ret = DESC90_RATE24M; break;
1638 case MGN_36M: ret = DESC90_RATE36M; break;
1639 case MGN_48M: ret = DESC90_RATE48M; break;
1640 case MGN_54M: ret = DESC90_RATE54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001641
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001642 // HT rate since here
1643 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1644 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1645 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1646 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1647 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1648 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1649 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1650 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1651 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1652 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1653 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1654 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1655 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1656 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1657 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1658 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1659 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001660
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001661 default: break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001662 }
1663 return ret;
1664}
1665
1666
Teodora Baluta46326d22013-10-16 01:59:17 +03001667static u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001668{
1669 u8 tmp_Short;
1670
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001671 tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) : ((tcb_desc->bUseShortPreamble) ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001672
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03001673 if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001674 tmp_Short = 0;
1675
1676 return tmp_Short;
1677}
1678
Jerry Chuang8fc85982009-11-03 07:17:11 -02001679static void tx_zero_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001680{
1681 return;
1682}
1683
1684/*
1685 * The tx procedure is just as following,
1686 * skb->cb will contain all the following information,
1687 * priority, morefrag, rate, &dev.
1688 * */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001689short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001690{
1691 struct r8192_priv *priv = ieee80211_priv(dev);
1692 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1693 tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data;
1694 tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
1695 struct usb_device *udev = priv->udev;
1696 int pend;
1697 int status;
1698 struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001699 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001700 pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]);
1701 /* we are locked here so the two atomic_read and inc are executed
1702 * without interleaves
1703 * !!! For debug purpose
1704 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001705 if (pend > MAX_TX_URB) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001706 netdev_dbg(dev, "To discard skb packet!\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001707 dev_kfree_skb_any(skb);
1708 return -1;
1709 }
1710
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001711 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001712 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001713 dev_kfree_skb_any(skb);
1714 return -ENOMEM;
1715 }
1716
1717 /* Fill Tx firmware info */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001718 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001719 /* DWORD 0 */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001720 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001721 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1722 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1723 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001724 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001725 tx_fwinfo->AllowAggregation = 1;
1726 /* DWORD 1 */
1727 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1728 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1729 } else {
1730 tx_fwinfo->AllowAggregation = 0;
1731 /* DWORD 1 */
1732 tx_fwinfo->RxMF = 0;
1733 tx_fwinfo->RxAMD = 0;
1734 }
1735
1736 /* Protection mode related */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001737 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1738 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1739 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1740 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001741 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001742 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->RTSSC) : 0;
1743 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1) ? ((tcb_desc->bRTSBW) ? 1 : 0) : 0;
1744 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) :
1745 (tcb_desc->bRTSUseShortGI ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001746
1747 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001748 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001749 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001750 tx_fwinfo->TxBandwidth = 1;
1751 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1752 } else {
1753 tx_fwinfo->TxBandwidth = 0;
1754 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1755 }
1756 } else {
1757 tx_fwinfo->TxBandwidth = 0;
1758 tx_fwinfo->TxSubCarrier = 0;
1759 }
1760
1761#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1762 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001763 tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001764#endif
1765 /* Fill Tx descriptor */
1766 memset(tx_desc, 0, sizeof(tx_desc_819x_usb));
1767 /* DWORD 0 */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001768 tx_desc->LINIP = 0;
1769 tx_desc->CmdInit = 1;
1770 tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001771
1772#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001773 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001774 tx_desc->PktSize = tcb_desc->pkt_size;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001775 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02001776#endif
1777 {
1778 tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff;
1779 }
1780
1781 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001782 tx_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001783 tx_desc->RATid = tcb_desc->RATRIndex;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001784 tx_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001785 tx_desc->SecType = 0x0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001786 if (tcb_desc->bHwSec) {
1787 switch (priv->ieee80211->pairwise_key_type) {
1788 case KEY_TYPE_WEP40:
1789 case KEY_TYPE_WEP104:
1790 tx_desc->SecType = 0x1;
1791 tx_desc->NoEnc = 0;
1792 break;
1793 case KEY_TYPE_TKIP:
1794 tx_desc->SecType = 0x2;
1795 tx_desc->NoEnc = 0;
1796 break;
1797 case KEY_TYPE_CCMP:
1798 tx_desc->SecType = 0x3;
1799 tx_desc->NoEnc = 0;
1800 break;
1801 case KEY_TYPE_NA:
1802 tx_desc->SecType = 0x0;
1803 tx_desc->NoEnc = 1;
1804 break;
1805 }
1806 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001807
1808 tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1809 tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1810
1811 tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1812 tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1813
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001814 /* Fill fields that are required to be initialized in all of the descriptors */
1815 //DWORD 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001816 tx_desc->FirstSeg = 1;
1817 tx_desc->LastSeg = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001818 tx_desc->OWN = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001819
1820#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1821 if (tcb_desc->drv_agg_enable) {
1822 tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb);
1823 } else
1824#endif
1825 {
1826 //DWORD 2
1827 tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN);
1828 }
1829 /* Get index to out pipe from specified QueueID */
1830#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001831 idx_pipe = txqueue2outpipe(priv, tcb_desc->queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001832#else
1833 idx_pipe = 0x5;
1834#endif
1835
Jerry Chuang8fc85982009-11-03 07:17:11 -02001836 /* To submit bulk urb */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001837 usb_fill_bulk_urb(tx_urb, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001838 usb_sndbulkpipe(udev, idx_pipe), skb->data,
1839 skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001840
Jerry Chuang8fc85982009-11-03 07:17:11 -02001841 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001842 if (!status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001843 //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 -02001844 bool bSend0Byte = false;
1845 u8 zero = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001846 if (udev->speed == USB_SPEED_HIGH) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001847 if (skb->len > 0 && skb->len % 512 == 0)
1848 bSend0Byte = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001849 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001850 if (skb->len > 0 && skb->len % 64 == 0)
1851 bSend0Byte = true;
1852 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001853 if (bSend0Byte) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001854 tx_urb_zero = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001855 if (!tx_urb_zero) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001856 RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
1857 return -ENOMEM;
1858 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001859 usb_fill_bulk_urb(tx_urb_zero, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001860 usb_sndbulkpipe(udev, idx_pipe), &zero,
1861 0, tx_zero_isr, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001862 status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001863 if (status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001864 RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
1865 return -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001866 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001867 }
1868 dev->trans_start = jiffies;
1869 atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
1870 return 0;
Patrik Karlin29b48ae2013-01-09 09:40:23 +01001871 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001872 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 +03001873 status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001874 return -1;
1875 }
1876}
1877
Teodora Baluta46326d22013-10-16 01:59:17 +03001878static short rtl8192_usb_initendpoints(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001879{
1880 struct r8192_priv *priv = ieee80211_priv(dev);
1881
Julia Lawall32414872010-05-11 20:26:57 +02001882 priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB+1),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001883 GFP_KERNEL);
David Chosrovab8345172010-12-01 13:42:16 +01001884 if (priv->rx_urb == NULL)
1885 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001886
1887#ifndef JACKSON_NEW_RX
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001888 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001889
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001890 priv->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001891
1892 priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL);
1893
1894 priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE;
1895 }
1896#endif
1897
1898#ifdef THOMAS_BEACON
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001899 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001900 long align = 0;
1901 void *oldaddr, *newaddr;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001902
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001903 priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
1904 priv->oldaddr = kmalloc(16, GFP_KERNEL);
1905 oldaddr = priv->oldaddr;
1906 align = ((long)oldaddr) & 3;
1907 if (align) {
1908 newaddr = oldaddr + 4 - align;
1909 priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align;
1910 } else {
1911 newaddr = oldaddr;
1912 priv->rx_urb[16]->transfer_buffer_length = 16;
1913 }
1914 priv->rx_urb[16]->transfer_buffer = newaddr;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001915 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001916#endif
1917
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001918 memset(priv->rx_urb, 0, sizeof(struct urb *) * MAX_RX_URB);
Julia Lawall7a6cb0d2010-05-13 22:00:05 +02001919 priv->pp_rxskb = kcalloc(MAX_RX_URB, sizeof(struct sk_buff *),
Julia Lawall32414872010-05-11 20:26:57 +02001920 GFP_KERNEL);
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001921 if (!priv->pp_rxskb) {
1922 kfree(priv->rx_urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001923
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001924 priv->pp_rxskb = NULL;
1925 priv->rx_urb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001926
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001927 DMESGE("Endpoint Alloc Failure");
1928 return -ENOMEM;
1929 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001930
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001931 netdev_dbg(dev, "End of initendpoints\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001932 return 0;
1933
1934}
1935#ifdef THOMAS_BEACON
Teodora Baluta46326d22013-10-16 01:59:17 +03001936static void rtl8192_usb_deleteendpoints(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001937{
1938 int i;
1939 struct r8192_priv *priv = ieee80211_priv(dev);
1940
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001941 if (priv->rx_urb) {
1942 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001943 usb_kill_urb(priv->rx_urb[i]);
1944 usb_free_urb(priv->rx_urb[i]);
1945 }
1946 kfree(priv->rx_urb);
1947 priv->rx_urb = NULL;
1948 }
Ilia Mirkine72714f2011-03-13 00:29:07 -05001949 kfree(priv->oldaddr);
1950 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001951 if (priv->pp_rxskb) {
1952 kfree(priv->pp_rxskb);
Sachin Kamat875d2a12013-10-09 15:58:30 +05301953 priv->pp_rxskb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001954 }
1955}
1956#else
1957void rtl8192_usb_deleteendpoints(struct net_device *dev)
1958{
1959 int i;
1960 struct r8192_priv *priv = ieee80211_priv(dev);
1961
1962#ifndef JACKSON_NEW_RX
1963
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001964 if (priv->rx_urb) {
1965 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001966 usb_kill_urb(priv->rx_urb[i]);
1967 kfree(priv->rx_urb[i]->transfer_buffer);
1968 usb_free_urb(priv->rx_urb[i]);
1969 }
1970 kfree(priv->rx_urb);
1971 priv->rx_urb = NULL;
1972
1973 }
1974#else
Ilia Mirkine72714f2011-03-13 00:29:07 -05001975 kfree(priv->rx_urb);
1976 priv->rx_urb = NULL;
1977 kfree(priv->oldaddr);
1978 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001979 if (priv->pp_rxskb) {
1980 kfree(priv->pp_rxskb);
1981 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001982
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001983 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001984
1985#endif
1986}
1987#endif
1988
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001989extern void rtl8192_update_ratr_table(struct net_device *dev);
Ana Reyf4c60742014-03-13 12:36:38 +01001990static void rtl8192_link_change(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001991{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001992 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001993 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001994 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001995 rtl8192_net_update(dev);
1996 rtl8192_update_ratr_table(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001997 //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
1998 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001999 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002000 }
2001 /*update timing params*/
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002002 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002003 u32 reg = 0;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002004 read_nic_dword(dev, RCR, &reg);
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002005 if (priv->ieee80211->state == IEEE80211_LINKED)
2006 priv->ReceiveConfig = reg |= RCR_CBSSID;
2007 else
2008 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
2009 write_nic_dword(dev, RCR, reg);
2010 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002011}
2012
2013static struct ieee80211_qos_parameters def_qos_parameters = {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002014 {3, 3, 3, 3},/* cw_min */
2015 {7, 7, 7, 7},/* cw_max */
2016 {2, 2, 2, 2},/* aifs */
2017 {0, 0, 0, 0},/* flags */
2018 {0, 0, 0, 0} /* tx_op_limit */
Jerry Chuang8fc85982009-11-03 07:17:11 -02002019};
2020
2021
Ana Reyf4c60742014-03-13 12:36:38 +01002022static void rtl8192_update_beacon(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002023{
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002024 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
2025 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002026 struct ieee80211_device *ieee = priv->ieee80211;
2027 struct ieee80211_network *net = &ieee->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002028
2029 if (ieee->pHTInfo->bCurrentHTSupport)
2030 HTUpdateSelfAndPeerSetting(ieee, net);
2031 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
2032 rtl8192_update_cap(dev, net->capability);
2033}
2034/*
2035* background support to run QoS activate functionality
2036*/
Ana Reyf4c60742014-03-13 12:36:38 +01002037static int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, EDCAPARA_VO};
2038static void rtl8192_qos_activate(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002039{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002040 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
2041 struct net_device *dev = priv->ieee80211->dev;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002042 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2043 u8 mode = priv->ieee80211->current_network.mode;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002044 u8 u1bAIFS;
2045 u32 u4bAcParam;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002046 int i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002047
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002048 if (priv == NULL)
2049 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002050
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002051 mutex_lock(&priv->mutex);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002052 if (priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002053 goto success;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002054 RT_TRACE(COMP_QOS, "qos active process with associate response received\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002055 /* It better set slot time at first */
2056 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2057 /* update the ac parameter to related registers */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002058 for (i = 0; i < QOS_QUEUE_NUM; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002059 //Mode G/A: slotTimeTimer = 9; Mode B: 20
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002060 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002061 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002062 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2063 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2064 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002065
2066 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002067 }
2068
2069success:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002070 mutex_unlock(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002071}
2072
2073static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002074 int active_network,
2075 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002076{
2077 int ret = 0;
2078 u32 size = sizeof(struct ieee80211_qos_parameters);
2079
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002080 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002081 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002082
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002083 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2084 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002085
2086 if (network->flags & NETWORK_HAS_QOS_MASK) {
2087 if (active_network &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002088 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
Jerry Chuang8fc85982009-11-03 07:17:11 -02002089 network->qos_data.active = network->qos_data.supported;
2090
2091 if ((network->qos_data.active == 1) && (active_network == 1) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002092 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2093 (network->qos_data.old_param_count !=
2094 network->qos_data.param_count)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002095 network->qos_data.old_param_count =
2096 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002097 queue_work(priv->priv_wq, &priv->qos_activate);
Xenia Ragiadakoue6367212013-05-23 05:14:46 +03002098 RT_TRACE(COMP_QOS, "QoS parameters change call "
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002099 "qos_activate\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002100 }
2101 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002102 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002103 &def_qos_parameters, size);
2104
2105 if ((network->qos_data.active == 1) && (active_network == 1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002106 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002107 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2108 }
2109 network->qos_data.active = 0;
2110 network->qos_data.supported = 0;
2111 }
2112
2113 return 0;
2114}
2115
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002116/* handle and manage frame from beacon and probe response */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002117static int rtl8192_handle_beacon(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002118 struct ieee80211_beacon *beacon,
2119 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002120{
2121 struct r8192_priv *priv = ieee80211_priv(dev);
2122
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002123 rtl8192_qos_handle_probe_response(priv, 1, network);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002124 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002125 return 0;
2126
2127}
2128
2129/*
2130* handling the beaconing responses. if we get different QoS setting
2131* off the network from the associated setting, adjust the QoS
2132* setting
2133*/
2134static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002135 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002136{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002137 int ret = 0;
2138 unsigned long flags;
2139 u32 size = sizeof(struct ieee80211_qos_parameters);
2140 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002141
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002142 if ((priv == NULL) || (network == NULL))
2143 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002144
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002145 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002146 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002147
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002148 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2149 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002150
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002151 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002152 if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002153 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002154 &network->qos_data.parameters,
2155 sizeof(struct ieee80211_qos_parameters));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002156 priv->ieee80211->current_network.qos_data.active = 1;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002157 set_qos_param = 1;
2158 /* update qos parameter for current network */
2159 priv->ieee80211->current_network.qos_data.old_param_count =
2160 priv->ieee80211->current_network.qos_data.param_count;
2161 priv->ieee80211->current_network.qos_data.param_count =
2162 network->qos_data.param_count;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002163 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002164 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002165 &def_qos_parameters, size);
2166 priv->ieee80211->current_network.qos_data.active = 0;
2167 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002168 set_qos_param = 1;
2169 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002170
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002171 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002172
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002173 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 -02002174 if (set_qos_param == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002175 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002176
2177
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002178 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002179}
2180
2181
2182static int rtl8192_handle_assoc_response(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002183 struct ieee80211_assoc_response_frame *resp,
2184 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002185{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002186 struct r8192_priv *priv = ieee80211_priv(dev);
2187 rtl8192_qos_association_resp(priv, network);
2188 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002189}
2190
2191
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002192void rtl8192_update_ratr_table(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002193{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002194 struct r8192_priv *priv = ieee80211_priv(dev);
2195 struct ieee80211_device *ieee = priv->ieee80211;
2196 u8 *pMcsRate = ieee->dot11HTOperationalRateSet;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002197 u32 ratr_value = 0;
2198 u8 rate_index = 0;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002199 rtl8192_config_rate(dev, (u16 *)(&ratr_value));
2200 ratr_value |= (*(u16 *)(pMcsRate)) << 12;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002201 switch (ieee->mode) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002202 case IEEE_A:
2203 ratr_value &= 0x00000FF0;
2204 break;
2205 case IEEE_B:
2206 ratr_value &= 0x0000000F;
2207 break;
2208 case IEEE_G:
2209 ratr_value &= 0x00000FF7;
2210 break;
2211 case IEEE_N_24G:
2212 case IEEE_N_5G:
2213 if (ieee->pHTInfo->PeerMimoPs == 0) {//MIMO_PS_STATIC
2214 ratr_value &= 0x0007F007;
2215 } else {
2216 if (priv->rf_type == RF_1T2R)
2217 ratr_value &= 0x000FF007;
2218 else
2219 ratr_value &= 0x0F81F007;
2220 }
2221 break;
2222 default:
2223 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002224 }
2225 ratr_value &= 0x0FFFFFFF;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002226 if (ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002227 ratr_value |= 0x80000000;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002228 else if (!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002229 ratr_value |= 0x80000000;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002230 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2231 write_nic_byte(dev, UFWP, 1);
2232}
2233
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002234static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04};
Jerry Chuang8fc85982009-11-03 07:17:11 -02002235static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
Teodora Baluta46326d22013-10-16 01:59:17 +03002236static bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002237{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002238 struct r8192_priv *priv = ieee80211_priv(dev);
2239 struct ieee80211_device *ieee = priv->ieee80211;
2240 struct ieee80211_network *network = &ieee->current_network;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002241 int wpa_ie_len = ieee->wpa_ie_len;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002242 struct ieee80211_crypt_data *crypt;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002243 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002244
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002245 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002246 //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 +03002247 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 -02002248
2249 /* simply judge */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002250 if (encrypt && (wpa_ie_len == 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002251 /* wep encryption, no N mode setting */
2252 return false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002253 } else if ((wpa_ie_len != 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002254 /* parse pairwise key type */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002255 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 -02002256 return true;
2257 else
2258 return false;
2259 } else {
2260 return true;
2261 }
2262
Jerry Chuang8fc85982009-11-03 07:17:11 -02002263 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002264}
2265
Ana Reyf4c60742014-03-13 12:36:38 +01002266static bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002267{
2268 bool Reval;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002269 struct r8192_priv *priv = ieee80211_priv(dev);
2270 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002271
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002272 if (ieee->bHalfWirelessN24GMode == true)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002273 Reval = true;
2274 else
2275 Reval = false;
2276
2277 return Reval;
2278}
2279
Ana Reyf4c60742014-03-13 12:36:38 +01002280static void rtl8192_refresh_supportrate(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002281{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002282 struct ieee80211_device *ieee = priv->ieee80211;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002283 //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002284 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002285 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002286 else
2287 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2288 return;
2289}
2290
Ana Reyf4c60742014-03-13 12:36:38 +01002291static u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002292{
2293 struct r8192_priv *priv = ieee80211_priv(dev);
2294 u8 ret = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002295 switch (priv->rf_chip) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002296 case RF_8225:
2297 case RF_8256:
2298 case RF_PSEUDO_11N:
2299 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2300 break;
2301 case RF_8258:
2302 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2303 break;
2304 default:
2305 ret = WIRELESS_MODE_B;
2306 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002307 }
2308 return ret;
2309}
Ana Reyf4c60742014-03-13 12:36:38 +01002310static void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002311{
2312 struct r8192_priv *priv = ieee80211_priv(dev);
2313 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2314
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002315 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode) == 0)) {
2316 if (bSupportMode & WIRELESS_MODE_N_24G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002317 wireless_mode = WIRELESS_MODE_N_24G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002318 } else if (bSupportMode & WIRELESS_MODE_N_5G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002319 wireless_mode = WIRELESS_MODE_N_5G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002320 } else if ((bSupportMode & WIRELESS_MODE_A)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002321 wireless_mode = WIRELESS_MODE_A;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002322 } else if ((bSupportMode & WIRELESS_MODE_G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002323 wireless_mode = WIRELESS_MODE_G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002324 } else if ((bSupportMode & WIRELESS_MODE_B)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002325 wireless_mode = WIRELESS_MODE_B;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002326 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002327 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __func__, bSupportMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002328 wireless_mode = WIRELESS_MODE_B;
2329 }
2330 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002331#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 +03002332 ActUpdateChannelAccessSetting(pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002333#endif
2334 priv->ieee80211->mode = wireless_mode;
2335
2336 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2337 priv->ieee80211->pHTInfo->bEnableHT = 1;
2338 else
2339 priv->ieee80211->pHTInfo->bEnableHT = 0;
2340 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2341 rtl8192_refresh_supportrate(priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002342
2343}
2344//init priv variables here. only non_zero value should be initialized here.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002345static void rtl8192_init_priv_variable(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002346{
2347 struct r8192_priv *priv = ieee80211_priv(dev);
2348 u8 i;
2349 priv->card_8192 = NIC_8192U;
2350 priv->chan = 1; //set to channel 1
2351 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2352 priv->ieee80211->iw_mode = IW_MODE_INFRA;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002353 priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002354 priv->retry_rts = DEFAULT_RETRY_RTS;
2355 priv->retry_data = DEFAULT_RETRY_DATA;
2356 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2357 priv->ieee80211->rate = 110; //11 mbps
2358 priv->ieee80211->short_slot = 1;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002359 priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002360 priv->CckPwEnl = 6;
2361 //for silent reset
2362 priv->IrpPendingCount = 1;
2363 priv->ResetProgress = RESET_TYPE_NORESET;
2364 priv->bForcedSilentReset = 0;
2365 priv->bDisableNormalResetCheck = false;
2366 priv->force_reset = false;
2367
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002368 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002369 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2370 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2371 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2372 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2373 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002374 IEEE_SOFTMAC_BEACONS;//added by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002375
2376 priv->ieee80211->active_scan = 1;
2377 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2378 priv->ieee80211->host_encrypt = 1;
2379 priv->ieee80211->host_decrypt = 1;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002380 priv->ieee80211->start_send_beacons = NULL; //-by amy 080604
2381 priv->ieee80211->stop_send_beacons = NULL; //-by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002382 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2383 priv->ieee80211->set_chan = rtl8192_set_chan;
2384 priv->ieee80211->link_change = rtl8192_link_change;
2385 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2386 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2387 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2388 priv->ieee80211->init_wmmparam_flag = 0;
2389 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2390 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2391 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
2392 priv->ieee80211->qos_support = 1;
2393
2394 //added by WB
Jerry Chuang8fc85982009-11-03 07:17:11 -02002395 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2396 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2397 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2398 //added by david
2399 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
2400 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
2401 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2402 //added by amy
2403 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
2404 priv->card_type = USB;
2405#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002406 if (Adapter->bInHctTest) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002407 pHalData->ShortRetryLimit = 7;
2408 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002409 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002410#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002411 priv->ShortRetryLimit = 0x30;
2412 priv->LongRetryLimit = 0x30;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002413 priv->EarlyRxThreshold = 7;
2414 priv->enable_gpio0 = 0;
2415 priv->TransmitConfig =
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002416 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002417 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
2418 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002419 (false ? TCR_SAT : 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
Jerry Chuang8fc85982009-11-03 07:17:11 -02002420#ifdef TO_DO_LIST
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002421 if (Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002422 pHalData->ReceiveConfig = pHalData->CSMethod |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002423 RCR_AMF | RCR_ADF | //accept management/data
Jerry Chuang8fc85982009-11-03 07:17:11 -02002424 //guangan200710
2425 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2426 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002427 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002428 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2429 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002430 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002431 else
2432
2433#endif
2434 priv->ReceiveConfig =
2435 RCR_AMF | RCR_ADF | //accept management/data
2436 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2437 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Jerry Chuang8fc85982009-11-03 07:17:11 -02002438 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2439 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002440 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002441
2442 priv->AcmControl = 0;
Devendra Nagab7553422012-08-26 11:06:33 +05302443 priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002444
2445 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002446 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002447 skb_queue_head_init(&priv->skb_queue);
2448
2449 /* Tx related queue */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002450 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002451 skb_queue_head_init(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002452 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002453 skb_queue_head_init(&priv->ieee80211->skb_aggQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002454 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002455 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002456 priv->rf_set_chan = rtl8192_phy_SwChnl;
2457}
2458
2459//init lock here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002460static void rtl8192_init_priv_lock(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002461{
2462 spin_lock_init(&priv->tx_lock);
2463 spin_lock_init(&priv->irq_lock);//added by thomas
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002464 sema_init(&priv->wx_sem, 1);
2465 sema_init(&priv->rf_sem, 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002466 mutex_init(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002467}
2468
Jerry Chuang8fc85982009-11-03 07:17:11 -02002469extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002470
2471void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
2472//init tasklet and wait_queue here. only 2.6 above kernel is considered
2473#define DRV_NAME "wlan0"
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002474static void rtl8192_init_priv_task(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002475{
2476 struct r8192_priv *priv = ieee80211_priv(dev);
2477
Jerry Chuang8fc85982009-11-03 07:17:11 -02002478 priv->priv_wq = create_workqueue(DRV_NAME);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002479
Jerry Chuang8fc85982009-11-03 07:17:11 -02002480 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2481
Jerry Chuang8fc85982009-11-03 07:17:11 -02002482 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2483 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002484 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2485 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2486 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002487 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002488
2489 tasklet_init(&priv->irq_rx_tasklet,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002490 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2491 (unsigned long)priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002492}
2493
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002494static void rtl8192_get_eeprom_size(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002495{
2496 u16 curCR = 0;
2497 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002498 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002499 read_nic_word_E(dev, EPROM_CMD, &curCR);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002500 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
2501 //whether need I consider BIT5?
2502 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002503 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __func__, priv->epromtype);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002504}
2505
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002506//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002507static inline u16 endian_swap(u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002508{
2509 u16 tmp = *data;
2510 *data = (tmp >> 8) | (tmp << 8);
2511 return *data;
2512}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002513static void rtl8192_read_eeprom_info(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002514{
2515 u16 wEPROM_ID = 0;
2516 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
2517 u8 bLoad_From_EEPOM = false;
2518 struct r8192_priv *priv = ieee80211_priv(dev);
2519 u16 tmpValue = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002520 int i;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002521 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002522 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
2523 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
2524
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002525 if (wEPROM_ID != RTL8190_EEPROM_ID) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002526 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 +03002527 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002528 bLoad_From_EEPOM = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002529 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002530
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002531 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002532 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
2533 priv->eeprom_vid = endian_swap(&tmpValue);
2534 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
2535 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002536 priv->eeprom_ChannelPlan = ((tmpValue&0xff00)>>8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002537 priv->btxpowerdata_readfromEEPORM = true;
2538 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002539 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002540 priv->eeprom_vid = 0;
2541 priv->eeprom_pid = 0;
2542 priv->card_8192_version = VERSION_819xU_B;
2543 priv->eeprom_ChannelPlan = 0;
2544 priv->eeprom_CustomerID = 0;
2545 }
2546 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);
2547 //set channelplan from eeprom
2548 priv->ChannelPlan = priv->eeprom_ChannelPlan;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002549 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002550 int i;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002551 for (i = 0; i < 6; i += 2) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002552 u16 tmp = 0;
2553 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002554 *(u16 *)(&dev->dev_addr[i]) = tmp;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002555 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002556 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002557 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2558 //should I set IDR0 here?
2559 }
Joe Perches0ee9f672009-12-06 11:34:52 -08002560 RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002561 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
2562 priv->rf_chip = RF_8256;
2563
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002564 if (priv->card_8192_version == (u8)VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002565 //read Tx power gain offset of legacy OFDM to HT rate
2566 if (bLoad_From_EEPOM)
2567 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
2568 else
2569 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
2570 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
2571 //read ThermalMeter from EEPROM
2572 if (bLoad_From_EEPOM)
2573 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
2574 else
2575 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2576 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
2577 //vivi, for tx power track
2578 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2579 //read antenna tx power offset of B/C/D to A from EEPROM
2580 if (bLoad_From_EEPOM)
2581 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
2582 else
2583 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
2584 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
2585 // Read CrystalCap from EEPROM
2586 if (bLoad_From_EEPOM)
2587 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
2588 else
2589 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
2590 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
2591 //get per-channel Tx power level
2592 if (bLoad_From_EEPOM)
2593 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
2594 else
2595 priv->EEPROM_Def_Ver = 1;
2596 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002597 if (priv->EEPROM_Def_Ver == 0) { //old eeprom definition
Jerry Chuang8fc85982009-11-03 07:17:11 -02002598 int i;
2599 if (bLoad_From_EEPOM)
2600 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
2601 else
2602 priv->EEPROMTxPowerLevelCCK = 0x10;
2603 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002604 for (i = 0; i < 3; i++) {
2605 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002606 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
2607 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
2608 tmpValue = tmpValue & 0x00ff;
2609 else
2610 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002611 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002612 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002613 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002614 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
2615 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
2616 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002617 } else if (priv->EEPROM_Def_Ver == 1) {
2618 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002619 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
2620 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002621 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002622 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002623 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002624 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
2625
2626 if (bLoad_From_EEPOM)
2627 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
2628 else
2629 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002630 *((u16 *)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002631 if (bLoad_From_EEPOM)
2632 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
2633 else
2634 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002635 *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002636 if (bLoad_From_EEPOM)
2637 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
2638 else
2639 tmpValue = 0x10;
2640 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
2641 }//endif EEPROM_Def_Ver == 1
2642
2643 //update HAL variables
2644 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002645 for (i = 0; i < 14; i++) {
2646 if (i <= 3)
2647 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
2648 else if (i >= 4 && i <= 9)
2649 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
2650 else
2651 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
2652 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002653
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002654 for (i = 0; i < 14; i++) {
2655 if (priv->EEPROM_Def_Ver == 0) {
2656 if (i <= 3)
2657 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2658 else if (i >= 4 && i <= 9)
2659 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
2660 else
2661 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2662 } else if (priv->EEPROM_Def_Ver == 1) {
2663 if (i <= 3)
2664 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
2665 else if (i >= 4 && i <= 9)
2666 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
2667 else
2668 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002669 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002670 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002671 priv->TxPowerDiff = priv->EEPROMPwDiff;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002672 // Antenna B gain offset to antenna A, bit0~3
Jerry Chuang8fc85982009-11-03 07:17:11 -02002673 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
2674 // Antenna C gain offset to antenna A, bit4~7
2675 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
2676 // CrystalCap, bit12~15
2677 priv->CrystalCap = priv->EEPROMCrystalCap;
2678 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
2679 // 92U does not enable TX power tracking.
2680 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
2681 }//end if VersionID == VERSION_819xU_A
2682
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002683 //added by vivi, for dlink led, 20080416
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002684 switch (priv->eeprom_CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002685 case EEPROM_CID_RUNTOP:
2686 priv->CustomerID = RT_CID_819x_RUNTOP;
2687 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002688
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002689 case EEPROM_CID_DLINK:
2690 priv->CustomerID = RT_CID_DLINK;
2691 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002692
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002693 default:
2694 priv->CustomerID = RT_CID_DEFAULT;
2695 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002696
2697 }
2698
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002699 switch (priv->CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002700 case RT_CID_819x_RUNTOP:
2701 priv->LedStrategy = SW_LED_MODE2;
2702 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002703
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002704 case RT_CID_DLINK:
2705 priv->LedStrategy = SW_LED_MODE4;
2706 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002707
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002708 default:
2709 priv->LedStrategy = SW_LED_MODE0;
2710 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002711
2712 }
2713
2714
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002715 if (priv->rf_type == RF_1T2R) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002716 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002717 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002718 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
2719 }
2720
2721 // 2008/01/16 MH We can only know RF type in the function. So we have to init
2722 // DIG RATR table again.
2723 init_rate_adaptive(dev);
2724 //we need init DIG RATR table here again.
2725
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002726 RT_TRACE(COMP_EPROM, "<===========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002727 return;
2728}
2729
Ana Reyf4c60742014-03-13 12:36:38 +01002730static short rtl8192_get_channel_map(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002731{
2732 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002733 if (priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03002734 netdev_err(dev, "rtl8180_init: Error channel plan! Set to default.\n");
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002735 priv->ChannelPlan = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002736 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002737 RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002738
2739 rtl819x_set_channel_map(priv->ChannelPlan, priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002740 return 0;
2741}
2742
Ana Reyf4c60742014-03-13 12:36:38 +01002743static short rtl8192_init(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002744{
2745
2746 struct r8192_priv *priv = ieee80211_priv(dev);
2747
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002748 memset(&(priv->stats), 0, sizeof(struct Stats));
2749 memset(priv->txqueue_to_outpipemap, 0, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002750#ifdef PIPE12
2751 {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002752 int i = 0;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002753 u8 queuetopipe[] = {3, 2, 1, 0, 4, 8, 7, 6, 5};
2754 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002755 }
2756#else
2757 {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002758 u8 queuetopipe[] = {3, 2, 1, 0, 4, 4, 0, 4, 4};
2759 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002760 }
2761#endif
2762 rtl8192_init_priv_variable(dev);
2763 rtl8192_init_priv_lock(priv);
2764 rtl8192_init_priv_task(dev);
2765 rtl8192_get_eeprom_size(dev);
2766 rtl8192_read_eeprom_info(dev);
2767 rtl8192_get_channel_map(dev);
2768 init_hal_dm(dev);
2769 init_timer(&priv->watch_dog_timer);
2770 priv->watch_dog_timer.data = (unsigned long)dev;
2771 priv->watch_dog_timer.function = watch_dog_timer_callback;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002772 if (rtl8192_usb_initendpoints(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002773 DMESG("Endopoints initialization failed");
2774 return -ENOMEM;
2775 }
2776
Jerry Chuang8fc85982009-11-03 07:17:11 -02002777#ifdef DEBUG_EPROM
2778 dump_eprom(dev);
2779#endif
2780 return 0;
2781}
2782
2783/******************************************************************************
2784 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
2785 * not to do all the hw config as its name says
2786 * input: net_device dev
2787 * output: none
2788 * return: none
2789 * notice: This part need to modified according to the rate set we filtered
2790 * ****************************************************************************/
Ana Reyf4c60742014-03-13 12:36:38 +01002791static void rtl8192_hwconfig(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002792{
2793 u32 regRATR = 0, regRRSR = 0;
2794 u8 regBwOpMode = 0, regTmp = 0;
2795 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002796 u32 ratr_value = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002797
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002798 // Set RRSR, RATR, and BW_OPMODE registers
Jerry Chuang8fc85982009-11-03 07:17:11 -02002799 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002800 switch (priv->ieee80211->mode) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002801 case WIRELESS_MODE_B:
2802 regBwOpMode = BW_OPMODE_20MHZ;
2803 regRATR = RATE_ALL_CCK;
2804 regRRSR = RATE_ALL_CCK;
2805 break;
2806 case WIRELESS_MODE_A:
2807 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
2808 regRATR = RATE_ALL_OFDM_AG;
2809 regRRSR = RATE_ALL_OFDM_AG;
2810 break;
2811 case WIRELESS_MODE_G:
2812 regBwOpMode = BW_OPMODE_20MHZ;
2813 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2814 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2815 break;
2816 case WIRELESS_MODE_AUTO:
2817#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002818 if (Adapter->bInHctTest) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002819 regBwOpMode = BW_OPMODE_20MHZ;
2820 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2821 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002822 }
2823 else
2824#endif
2825 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002826 regBwOpMode = BW_OPMODE_20MHZ;
2827 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2828 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002829 }
2830 break;
2831 case WIRELESS_MODE_N_24G:
2832 // It support CCK rate by default.
2833 // CCK rate will be filtered out only when associated AP does not support it.
2834 regBwOpMode = BW_OPMODE_20MHZ;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002835 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2836 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002837 break;
2838 case WIRELESS_MODE_N_5G:
2839 regBwOpMode = BW_OPMODE_5G;
2840 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2841 regRRSR = RATE_ALL_OFDM_AG;
2842 break;
2843 }
2844
2845 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002846 ratr_value = regRATR;
2847 if (priv->rf_type == RF_1T2R)
2848 ratr_value &= ~(RATE_ALL_OFDM_2SS);
2849 write_nic_dword(dev, RATR0, ratr_value);
2850 write_nic_byte(dev, UFWP, 1);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002851 read_nic_byte(dev, 0x313, &regTmp);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002852 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
2853 write_nic_dword(dev, RRSR, regRRSR);
2854
2855 //
2856 // Set Retry Limit here
2857 //
2858 write_nic_word(dev, RETRY_LIMIT,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002859 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
2860 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002861 // Set Contention Window here
2862
2863 // Set Tx AGC
2864
2865 // Set Tx Antenna including Feedback control
2866
2867 // Set Auto Rate fallback control
2868
2869
2870}
2871
2872
2873//InitializeAdapter and PhyCfg
Ana Reyf4c60742014-03-13 12:36:38 +01002874static bool rtl8192_adapter_start(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002875{
2876 struct r8192_priv *priv = ieee80211_priv(dev);
2877 u32 dwRegRead = 0;
2878 bool init_status = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002879 u8 SECR_value = 0x0;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002880 u8 tmp;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002881 RT_TRACE(COMP_INIT, "====>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002882 priv->Rf_Mode = RF_OP_By_SW_3wire;
2883 //for ASIC power on sequence
2884 write_nic_byte_E(dev, 0x5f, 0x80);
2885 mdelay(50);
2886 write_nic_byte_E(dev, 0x5f, 0xf0);
2887 write_nic_byte_E(dev, 0x5d, 0x00);
2888 write_nic_byte_E(dev, 0x5e, 0x80);
2889 write_nic_byte(dev, 0x17, 0x37);
2890 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002891 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
2892 //config CPUReset Register
2893 //Firmware Reset or not?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002894 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002895 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
2896 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
2897 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
2898 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
2899 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002900 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __func__, priv->pFirmware->firmware_status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002901
2902 write_nic_dword(dev, CPU_GEN, dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002903 //config BB.
2904 rtl8192_BBConfig(dev);
2905
Jerry Chuang8fc85982009-11-03 07:17:11 -02002906 //Loopback mode or not
2907 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002908
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002909 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002910 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
2911 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
2912 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
2913 dwRegRead |= CPU_CCK_LOOPBACK;
2914 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002915 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __func__, priv->LoopbackMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002916
2917 write_nic_dword(dev, CPU_GEN, dwRegRead);
2918
2919 //after reset cpu, we need wait for a seconds to write in register.
2920 udelay(500);
2921
2922 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002923 read_nic_byte_E(dev, 0x5f, &tmp);
2924 write_nic_byte_E(dev, 0x5f, tmp|0x20);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002925
2926 //Set Hardware
2927 rtl8192_hwconfig(dev);
2928
2929 //turn on Tx/Rx
2930 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
2931
2932 //set IDR0 here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002933 write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
2934 write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002935
2936 //set RCR
2937 write_nic_dword(dev, RCR, priv->ReceiveConfig);
2938
2939 //Initialize Number of Reserved Pages in Firmware Queue
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002940 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 +03002941 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT |
2942 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT |
2943 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002944 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 +03002945 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002946 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002947 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002948 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
2949
2950 //Set AckTimeout
2951 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
2952 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
2953
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002954 if (priv->ResetProgress == RESET_TYPE_NORESET)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002955 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002956 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002957 CamResetAllEntry(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002958 SECR_value |= SCR_TxEncEnable;
2959 SECR_value |= SCR_RxDecEnable;
2960 SECR_value |= SCR_NoSKMC;
2961 write_nic_byte(dev, SECR, SECR_value);
2962 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002963
2964 //Beacon related
2965 write_nic_word(dev, ATIMWND, 2);
2966 write_nic_word(dev, BCN_INTERVAL, 100);
2967
Jerry Chuang8fc85982009-11-03 07:17:11 -02002968#define DEFAULT_EDCA 0x005e4332
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002969 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002970 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002971 for (i = 0; i < QOS_QUEUE_NUM; i++)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002972 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002973 }
2974#ifdef USB_RX_AGGREGATION_SUPPORT
2975 //3 For usb rx firmware aggregation control
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002976 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002977 u32 ulValue;
2978 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
2979 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002980 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002981 /*
2982 * If usb rx firmware aggregation is enabled,
2983 * when anyone of three threshold conditions above is reached,
2984 * firmware will send aggregated packet to driver.
2985 */
2986 write_nic_dword(dev, 0x1a8, ulValue);
2987 priv->bCurrentRxAggrEnable = true;
2988 }
2989#endif
2990
2991 rtl8192_phy_configmac(dev);
2992
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002993 if (priv->card_8192_version == (u8) VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002994 rtl8192_phy_getTxPower(dev);
2995 rtl8192_phy_setTxPower(dev, priv->chan);
2996 }
2997
2998 //Firmware download
2999 init_status = init_firmware(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003000 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003001 RT_TRACE(COMP_ERR, "ERR!!! %s(): Firmware download is failed\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003002 return init_status;
3003 }
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003004 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003005 //
3006#ifdef TO_DO_LIST
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003007 if (Adapter->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003008 if (pMgntInfo->RegRfOff == TRUE) { // User disable RF via registry.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003009 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
3010 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003011 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003012 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003013 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003014 } else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { // H/W or S/W RF OFF before sleep.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003015 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
3016 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003017 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003018 pHalData->eRFPowerState = eRfOn;
3019 pMgntInfo->RfOffReason = 0;
3020 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
3021 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003022 } else {
3023 if (pHalData->eRFPowerState == eRfOff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003024 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003025 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003026 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003027 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3028 }
3029 }
3030#endif
3031 //config RF.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003032 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003033 rtl8192_phy_RFConfig(dev);
3034 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003035 }
3036
3037
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003038 if (priv->ieee80211->FwRWRF)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003039 // We can force firmware to do RF-R/W
3040 priv->Rf_Mode = RF_OP_By_FW;
3041 else
3042 priv->Rf_Mode = RF_OP_By_SW_3wire;
3043
3044
3045 rtl8192_phy_updateInitGain(dev);
3046 /*--set CCK and OFDM Block "ON"--*/
3047 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3048 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3049
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003050 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003051 //if D or C cut
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003052 u8 tmpvalue;
3053 read_nic_byte(dev, 0x301, &tmpvalue);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003054 if (tmpvalue == 0x03) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003055 priv->bDcut = TRUE;
3056 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003057 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003058 priv->bDcut = FALSE;
3059 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
3060 }
3061 dm_initialize_txpower_tracking(dev);
3062
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003063 if (priv->bDcut == TRUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003064 u32 i, TempCCk;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003065 u32 tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003066 for (i = 0; i < TxBBGainTableLength; i++) {
3067 if (tmpRegA == priv->txbbgain_table[i].txbbgain_value) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003068 priv->rfa_txpowertrackingindex = (u8)i;
3069 priv->rfa_txpowertrackingindex_real = (u8)i;
3070 priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003071 break;
3072 }
3073 }
3074
3075 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3076
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003077 for (i = 0; i < CCKTxBBGainTableLength; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003078
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003079 if (TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0]) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003080 priv->cck_present_attentuation_20Mdefault = (u8) i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003081 break;
3082 }
3083 }
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003084 priv->cck_present_attentuation_40Mdefault = 0;
3085 priv->cck_present_attentuation_difference = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003086 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
3087
Jerry Chuang8fc85982009-11-03 07:17:11 -02003088 }
3089 }
3090 write_nic_byte(dev, 0x87, 0x0);
3091
3092
Jerry Chuang8fc85982009-11-03 07:17:11 -02003093 return init_status;
3094}
3095
3096/* this configures registers for beacon tx and enables it via
3097 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3098 * be used to stop beacon transmission
3099 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003100/***************************************************************************
3101 -------------------------------NET STUFF---------------------------
3102***************************************************************************/
3103
3104static struct net_device_stats *rtl8192_stats(struct net_device *dev)
3105{
3106 struct r8192_priv *priv = ieee80211_priv(dev);
3107
3108 return &priv->ieee80211->stats;
3109}
3110
Teodora Baluta46326d22013-10-16 01:59:17 +03003111static bool HalTxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003112{
3113 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003114 u16 RegTxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003115 bool bStuck = FALSE;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003116 read_nic_word(dev, 0x128, &RegTxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003117 RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", __func__, RegTxCounter, priv->TxCounter);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003118 if (priv->TxCounter == RegTxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003119 bStuck = TRUE;
3120
3121 priv->TxCounter = RegTxCounter;
3122
3123 return bStuck;
3124}
3125
3126/*
3127* <Assumption: RT_TX_SPINLOCK is acquired.>
3128* First added: 2006.11.19 by emily
3129*/
Ana Reyf4c60742014-03-13 12:36:38 +01003130static RESET_TYPE TxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003131{
3132 struct r8192_priv *priv = ieee80211_priv(dev);
3133 u8 QueueID;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003134 bool bCheckFwTxCnt = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003135
3136 //
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003137 // Decide such threshold according to current power save mode
Jerry Chuang8fc85982009-11-03 07:17:11 -02003138 //
3139
Xenia Ragiadakou7d79ec62013-06-04 23:32:30 +03003140 for (QueueID = 0; QueueID <= BEACON_QUEUE; QueueID++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003141 if (QueueID == TXCMD_QUEUE)
3142 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003143#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003144 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 -02003145#else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003146 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 -02003147#endif
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003148 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003149
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003150 bCheckFwTxCnt = true;
3151 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003152 if (bCheckFwTxCnt) {
3153 if (HalTxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003154 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
3155 return RESET_TYPE_SILENT;
3156 }
3157 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003158 return RESET_TYPE_NORESET;
3159}
3160
Teodora Baluta46326d22013-10-16 01:59:17 +03003161static bool HalRxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003162{
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003163 u16 RegRxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003164 struct r8192_priv *priv = ieee80211_priv(dev);
3165 bool bStuck = FALSE;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003166 static u8 rx_chk_cnt;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003167 read_nic_word(dev, 0x130, &RegRxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003168 RT_TRACE(COMP_RESET, "%s(): RegRxCounter is %d,RxCounter is %d\n", __func__, RegRxCounter, priv->RxCounter);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003169 // If rssi is small, we should check rx for long time because of bad rx.
3170 // or maybe it will continuous silent reset every 2 seconds.
3171 rx_chk_cnt++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003172 if (priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003173 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003174 } else if (priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003175 ((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_40M) ||
3176 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_20M))) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003177 if (rx_chk_cnt < 2)
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;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003181 } else if (((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_40M) ||
3182 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_20M)) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003183 priv->undecorated_smoothed_pwdb >= VeryLowRSSI) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003184 if (rx_chk_cnt < 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003185 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003186 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003187 rx_chk_cnt = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003188 } else {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003189 if (rx_chk_cnt < 8)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003190 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003191 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003192 rx_chk_cnt = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003193 }
3194
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003195 if (priv->RxCounter == RegRxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003196 bStuck = TRUE;
3197
3198 priv->RxCounter = RegRxCounter;
3199
3200 return bStuck;
3201}
3202
Teodora Baluta46326d22013-10-16 01:59:17 +03003203static RESET_TYPE RxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003204{
3205 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003206 bool bRxCheck = FALSE;
3207
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003208 if (priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003209 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003210
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003211 if (bRxCheck) {
3212 if (HalRxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003213 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
3214 return RESET_TYPE_SILENT;
3215 }
3216 }
3217 return RESET_TYPE_NORESET;
3218}
3219
3220
3221/**
3222* This function is called by Checkforhang to check whether we should ask OS to reset driver
3223*
3224* \param pAdapter The adapter context for this miniport
3225*
3226* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
3227* to judge whether there is tx stuck.
3228* Note: This function may be required to be rewrite for Vista OS.
3229* <<<Assumption: Tx spinlock has been acquired >>>
3230*
3231* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
3232*/
Ana Reyf4c60742014-03-13 12:36:38 +01003233static RESET_TYPE rtl819x_ifcheck_resetornot(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003234{
3235 struct r8192_priv *priv = ieee80211_priv(dev);
3236 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
3237 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003238 RT_RF_POWER_STATE rfState;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003239
3240 rfState = priv->ieee80211->eRFPowerState;
3241
3242 TxResetType = TxCheckStuck(dev);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003243 if (rfState != eRfOff ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003244 (priv->ieee80211->iw_mode != IW_MODE_ADHOC)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003245 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
3246 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
3247 // if driver is in firmware download failure status, driver should initialize RF in the following
3248 // silent reset procedure Emily, 2008.01.21
3249
3250 // Driver should not check RX stuck in IBSS mode because it is required to
3251 // set Check BSSID in order to send beacon, however, if check BSSID is
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003252 // set, STA cannot hear any packet at all. Emily, 2008.04.12
Jerry Chuang8fc85982009-11-03 07:17:11 -02003253 RxResetType = RxCheckStuck(dev);
3254 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003255 if (TxResetType == RESET_TYPE_NORMAL || RxResetType == RESET_TYPE_NORMAL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003256 return RESET_TYPE_NORMAL;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003257 } else if (TxResetType == RESET_TYPE_SILENT || RxResetType == RESET_TYPE_SILENT) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003258 RT_TRACE(COMP_RESET, "%s():silent reset\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003259 return RESET_TYPE_SILENT;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003260 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003261 return RESET_TYPE_NORESET;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003262 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003263
3264}
3265
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003266void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003267int _rtl8192_up(struct net_device *dev);
3268int rtl8192_close(struct net_device *dev);
3269
3270
3271
Ana Reyf4c60742014-03-13 12:36:38 +01003272static void CamRestoreAllEntry(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003273{
3274 u8 EntryId = 0;
3275 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003276 u8 *MacAddr = priv->ieee80211->current_network.bssid;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003277
3278 static u8 CAM_CONST_ADDR[4][6] = {
3279 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3280 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
3281 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03003282 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003283 static u8 CAM_CONST_BROAD[] = {
3284 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003285
3286 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
3287
3288
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003289 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40) ||
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003290 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003291
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003292 for (EntryId = 0; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003293 MacAddr = CAM_CONST_ADDR[EntryId];
3294 setKey(dev, EntryId, EntryId,
3295 priv->ieee80211->pairwise_key_type,
3296 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003297 }
3298
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003299 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003300
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003301 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3302 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3303 (u8 *)dev->dev_addr, 0, NULL);
3304 else
3305 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3306 MacAddr, 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003307 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003308
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003309 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3310 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3311 (u8 *)dev->dev_addr, 0, NULL);
3312 else
3313 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3314 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003315 }
3316
3317
3318
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003319 if (priv->ieee80211->group_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003320 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003321 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003322 setKey(dev, EntryId, EntryId,
3323 priv->ieee80211->group_key_type,
3324 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003325 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003326 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003327 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3328 CAM_CONST_ADDR[0], 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003329 } else if (priv->ieee80211->group_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003330 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003331 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003332 setKey(dev, EntryId, EntryId,
3333 priv->ieee80211->group_key_type,
3334 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003335 }
3336
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003337 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003338 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3339 CAM_CONST_ADDR[0], 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003340 }
3341}
3342//////////////////////////////////////////////////////////////
3343// This function is used to fix Tx/Rx stop bug temporarily.
3344// This function will do "system reset" to NIC when Tx or Rx is stuck.
3345// The method checking Tx/Rx stuck of this function is supported by FW,
3346// which reports Tx and Rx counter to register 0x128 and 0x130.
3347//////////////////////////////////////////////////////////////
Ana Reyf4c60742014-03-13 12:36:38 +01003348static void rtl819x_ifsilentreset(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003349{
Jerry Chuang8fc85982009-11-03 07:17:11 -02003350 struct r8192_priv *priv = ieee80211_priv(dev);
3351 u8 reset_times = 0;
3352 int reset_status = 0;
3353 struct ieee80211_device *ieee = priv->ieee80211;
3354
3355
3356 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
3357 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
3358
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003359 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003360RESET_START:
3361
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003362 RT_TRACE(COMP_RESET, "=========>Reset progress!! \n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003363
3364 // Set the variable for reset.
3365 priv->ResetProgress = RESET_TYPE_SILENT;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003366 down(&priv->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003367 if (priv->up == 0) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003368 RT_TRACE(COMP_ERR, "%s():the driver is not up! return\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003369 up(&priv->wx_sem);
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003370 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003371 }
3372 priv->up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003373 RT_TRACE(COMP_RESET, "%s():======>start to down the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003374
3375 rtl8192_rtx_disable(dev);
3376 rtl8192_cancel_deferred_work(priv);
3377 deinit_hal_dm(dev);
3378 del_timer_sync(&priv->watch_dog_timer);
3379
3380 ieee->sync_scan_hurryup = 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003381 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003382 down(&ieee->wx_sem);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003383 netdev_dbg(dev, "ieee->state is IEEE80211_LINKED\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003384 ieee80211_stop_send_beacons(priv->ieee80211);
3385 del_timer_sync(&ieee->associate_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003386 cancel_delayed_work(&ieee->associate_retry_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003387 ieee80211_stop_scan(ieee);
3388 netif_carrier_off(dev);
3389 up(&ieee->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003390 } else {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003391 netdev_dbg(dev, "ieee->state is NOT LINKED\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003392 ieee80211_softmac_stop_protocol(priv->ieee80211);
3393 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003394 up(&priv->wx_sem);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003395 RT_TRACE(COMP_RESET, "%s():<==========down process is finished\n", __func__);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003396 RT_TRACE(COMP_RESET, "%s():===========>start up the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003397 reset_status = _rtl8192_up(dev);
3398
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003399 RT_TRACE(COMP_RESET, "%s():<===========up process is finished\n", __func__);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003400 if (reset_status == -EAGAIN) {
3401 if (reset_times < 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003402 reset_times++;
3403 goto RESET_START;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003404 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003405 RT_TRACE(COMP_ERR, " ERR!!! %s(): Reset Failed!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003406 }
3407 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003408 ieee->is_silent_reset = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003409 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003410 if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003411 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3412
Jerry Chuang8fc85982009-11-03 07:17:11 -02003413 queue_work(ieee->wq, &ieee->associate_complete_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003414
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003415 } else if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003416 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3417 ieee->link_change(ieee->dev);
3418
Jerry Chuang8fc85982009-11-03 07:17:11 -02003419 ieee80211_start_send_beacons(ieee);
3420
3421 if (ieee->data_hard_resume)
3422 ieee->data_hard_resume(ieee->dev);
3423 netif_carrier_on(ieee->dev);
3424 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003425
3426 CamRestoreAllEntry(dev);
3427
3428 priv->ResetProgress = RESET_TYPE_NORESET;
3429 priv->reset_count++;
3430
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003431 priv->bForcedSilentReset = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003432 priv->bResetInProgress = false;
3433
3434 // For test --> force write UFWP.
3435 write_nic_byte(dev, UFWP, 1);
3436 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003437 }
3438}
3439
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003440void CAM_read_entry(struct net_device *dev, u32 iIndex)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003441{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003442 u32 target_command = 0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003443 u32 target_content = 0;
3444 u8 entry_i = 0;
3445 u32 ulStatus;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003446 s32 i = 100;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003447 for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003448 // polling bit, and No Write enable, and address
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003449 target_command = entry_i+CAM_CONTENT_COUNT*iIndex;
3450 target_command = target_command | BIT31;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003451
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003452 //Check polling bit is clear
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003453 while ((i--) >= 0) {
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003454 read_nic_dword(dev, RWCAM, &ulStatus);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003455 if (ulStatus & BIT31)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003456 continue;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003457 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003458 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003459 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003460 write_nic_dword(dev, RWCAM, target_command);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003461 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x \n", target_command);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003462 read_nic_dword(dev, RCAMO, &target_content);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003463 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n", target_content);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003464 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003465 printk("\n");
3466}
3467
Ana Reyf4c60742014-03-13 12:36:38 +01003468static void rtl819x_update_rxcounts(struct r8192_priv *priv, u32 *TotalRxBcnNum,
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003469 u32 *TotalRxDataNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003470{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003471 u16 SlotIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003472 u8 i;
3473
3474 *TotalRxBcnNum = 0;
3475 *TotalRxDataNum = 0;
3476
3477 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
3478 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
3479 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003480 for (i = 0; i < priv->ieee80211->LinkDetectInfo.SlotNum; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003481 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
3482 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
3483 }
3484}
3485
3486
Himangi Saraogid16e05f2014-03-09 04:21:41 +05303487void rtl819x_watchdog_wqcallback(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003488{
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003489 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003490 struct r8192_priv *priv = container_of(dwork, struct r8192_priv, watch_dog_wq);
3491 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003492 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003493 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003494 static u8 check_reset_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003495 bool bBusyTraffic = false;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003496 u32 TotalRxBcnNum = 0;
3497 u32 TotalRxDataNum = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003498
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003499 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003500 return;
3501 hal_dm_watchdog(dev);
3502
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003503 //to get busy traffic condition
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003504 if (ieee->state == IEEE80211_LINKED) {
3505 if (ieee->LinkDetectInfo.NumRxOkInPeriod > 666 ||
3506 ieee->LinkDetectInfo.NumTxOkInPeriod > 666 ) {
3507 bBusyTraffic = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003508 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003509 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
3510 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
3511 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
3512 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003513 //added by amy for AP roaming
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003514 if (priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003515
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003516 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
3517 if ((TotalRxBcnNum+TotalRxDataNum) == 0) {
3518#ifdef TODO
3519 if (rfState == eRfOff)
3520 RT_TRACE(COMP_ERR, "========>%s()\n", __func__);
3521#endif
3522 netdev_dbg(dev, "===>%s(): AP is power off, connect another one\n", __func__);
3523 priv->ieee80211->state = IEEE80211_ASSOCIATING;
3524 notify_wx_assoc_event(priv->ieee80211);
3525 RemovePeerTS(priv->ieee80211, priv->ieee80211->current_network.bssid);
3526 priv->ieee80211->link_change(dev);
3527 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003528
Jerry Chuang8fc85982009-11-03 07:17:11 -02003529 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003530 }
3531 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod = 0;
3532 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003533 //check if reset the driver
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003534 if (check_reset_cnt++ >= 3) {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003535 ResetType = rtl819x_ifcheck_resetornot(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003536 check_reset_cnt = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003537 }
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003538 if ((priv->force_reset) || (priv->ResetProgress == RESET_TYPE_NORESET &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003539 (priv->bForcedSilentReset ||
3540 (!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_SILENT)))) { // This is control by OID set in Pomelo
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003541 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 -02003542 rtl819x_ifsilentreset(dev);
3543 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003544 priv->force_reset = false;
3545 priv->bForcedSilentReset = false;
3546 priv->bResetInProgress = false;
3547 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
3548
3549}
3550
3551void watch_dog_timer_callback(unsigned long data)
3552{
3553 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003554 queue_delayed_work(priv->priv_wq, &priv->watch_dog_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003555 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
Jerry Chuang8fc85982009-11-03 07:17:11 -02003556}
3557int _rtl8192_up(struct net_device *dev)
3558{
3559 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003560 int init_status = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003561 priv->up = 1;
3562 priv->ieee80211->ieee_up = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003563 RT_TRACE(COMP_INIT, "Bringing up iface");
3564 init_status = rtl8192_adapter_start(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003565 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003566 RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization failed!\n", __func__);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003567 priv->up = priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003568 return -EAGAIN;
3569 }
3570 RT_TRACE(COMP_INIT, "start adapter finished\n");
3571 rtl8192_rx_enable(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003572 if (priv->ieee80211->state != IEEE80211_LINKED)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003573 ieee80211_softmac_start_protocol(priv->ieee80211);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003574 ieee80211_reset_queue(priv->ieee80211);
3575 watch_dog_timer_callback((unsigned long) dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003576 if (!netif_queue_stopped(dev))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003577 netif_start_queue(dev);
3578 else
3579 netif_wake_queue(dev);
3580
3581 return 0;
3582}
3583
3584
Ana Reyf4c60742014-03-13 12:36:38 +01003585static int rtl8192_open(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003586{
3587 struct r8192_priv *priv = ieee80211_priv(dev);
3588 int ret;
3589 down(&priv->wx_sem);
3590 ret = rtl8192_up(dev);
3591 up(&priv->wx_sem);
3592 return ret;
3593
3594}
3595
3596
3597int rtl8192_up(struct net_device *dev)
3598{
3599 struct r8192_priv *priv = ieee80211_priv(dev);
3600
3601 if (priv->up == 1) return -1;
3602
3603 return _rtl8192_up(dev);
3604}
3605
3606
3607int rtl8192_close(struct net_device *dev)
3608{
3609 struct r8192_priv *priv = ieee80211_priv(dev);
3610 int ret;
3611
3612 down(&priv->wx_sem);
3613
3614 ret = rtl8192_down(dev);
3615
3616 up(&priv->wx_sem);
3617
3618 return ret;
3619
3620}
3621
3622int rtl8192_down(struct net_device *dev)
3623{
3624 struct r8192_priv *priv = ieee80211_priv(dev);
3625 int i;
3626
3627 if (priv->up == 0) return -1;
3628
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003629 priv->up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003630 priv->ieee80211->ieee_up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003631 RT_TRACE(COMP_DOWN, "==========>%s()\n", __func__);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003632 /* FIXME */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003633 if (!netif_queue_stopped(dev))
3634 netif_stop_queue(dev);
3635
3636 rtl8192_rtx_disable(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003637
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003638 /* Tx related queue release */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003639 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003640 skb_queue_purge(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003641 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003642 skb_queue_purge(&priv->ieee80211->skb_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003643
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003644 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003645 skb_queue_purge(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003646
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003647 //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 -02003648 rtl8192_cancel_deferred_work(priv);
3649 deinit_hal_dm(dev);
3650 del_timer_sync(&priv->watch_dog_timer);
3651
3652
3653 ieee80211_softmac_stop_protocol(priv->ieee80211);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003654 memset(&priv->ieee80211->current_network, 0, offsetof(struct ieee80211_network, list));
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003655 RT_TRACE(COMP_DOWN, "<==========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003656
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003657 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003658}
3659
3660
3661void rtl8192_commit(struct net_device *dev)
3662{
3663 struct r8192_priv *priv = ieee80211_priv(dev);
3664 int reset_status = 0;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003665 if (priv->up == 0) return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003666 priv->up = 0;
3667
3668 rtl8192_cancel_deferred_work(priv);
3669 del_timer_sync(&priv->watch_dog_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003670
3671 ieee80211_softmac_stop_protocol(priv->ieee80211);
3672
Jerry Chuang8fc85982009-11-03 07:17:11 -02003673 rtl8192_rtx_disable(dev);
3674 reset_status = _rtl8192_up(dev);
3675
3676}
3677
Jerry Chuang8fc85982009-11-03 07:17:11 -02003678void rtl8192_restart(struct work_struct *work)
3679{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003680 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
3681 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003682
3683 down(&priv->wx_sem);
3684
3685 rtl8192_commit(dev);
3686
3687 up(&priv->wx_sem);
3688}
3689
3690static void r8192_set_multicast(struct net_device *dev)
3691{
3692 struct r8192_priv *priv = ieee80211_priv(dev);
3693 short promisc;
3694
Jerry Chuang8fc85982009-11-03 07:17:11 -02003695 /* FIXME FIXME */
3696
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003697 promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003698
3699 if (promisc != priv->promisc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003700
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003701 priv->promisc = promisc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003702}
3703
3704
Ana Reyf4c60742014-03-13 12:36:38 +01003705static int r8192_set_mac_adr(struct net_device *dev, void *mac)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003706{
3707 struct r8192_priv *priv = ieee80211_priv(dev);
3708 struct sockaddr *addr = mac;
3709
3710 down(&priv->wx_sem);
3711
3712 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
3713
Jerry Chuang8fc85982009-11-03 07:17:11 -02003714 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003715 up(&priv->wx_sem);
3716
3717 return 0;
3718}
3719
3720/* based on ipw2200 driver */
Ana Reyf4c60742014-03-13 12:36:38 +01003721static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003722{
3723 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3724 struct iwreq *wrq = (struct iwreq *)rq;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003725 int ret = -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003726 struct ieee80211_device *ieee = priv->ieee80211;
3727 u32 key[4];
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003728 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003729 struct iw_point *p = &wrq->u.data;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03003730 struct ieee_param *ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003731
3732 down(&priv->wx_sem);
3733
3734
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003735 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
3736 ret = -EINVAL;
3737 goto out;
3738 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003739
Teodora Baluta38272d22013-10-25 11:27:09 +03003740 ipw = memdup_user(p->pointer, p->length);
3741 if (IS_ERR(ipw)) {
3742 ret = PTR_ERR(ipw);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003743 goto out;
3744 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003745
3746 switch (cmd) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003747 case RTL_IOCTL_WPA_SUPPLICANT:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003748 //parse here for HW security
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003749 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) {
3750 if (ipw->u.crypt.set_tx) {
3751 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003752 ieee->pairwise_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003753 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003754 ieee->pairwise_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003755 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003756 if (ipw->u.crypt.key_len == 13)
3757 ieee->pairwise_key_type = KEY_TYPE_WEP104;
3758 else if (ipw->u.crypt.key_len == 5)
3759 ieee->pairwise_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003760 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003761 ieee->pairwise_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003762 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003763
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003764 if (ieee->pairwise_key_type) {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003765 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003766 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003767 //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!
3768 //added by WB.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003769 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 +01003770 if (ieee->auth_mode != 2)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003771 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 -02003772 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003773 } else {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003774 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003775 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003776 ieee->group_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003777 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003778 ieee->group_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003779 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003780 if (ipw->u.crypt.key_len == 13)
3781 ieee->group_key_type = KEY_TYPE_WEP104;
3782 else if (ipw->u.crypt.key_len == 5)
3783 ieee->group_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003784 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003785 ieee->group_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003786 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003787
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003788 if (ieee->group_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003789 setKey(dev, ipw->u.crypt.idx,
3790 ipw->u.crypt.idx, //KeyIndex
3791 ieee->group_key_type, //KeyType
3792 broadcast_addr, //MacAddr
3793 0, //DefaultKey
3794 key); //KeyContent
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003795 }
3796 }
3797 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003798 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
3799 break;
3800
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003801 default:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003802 ret = -EOPNOTSUPP;
3803 break;
3804 }
3805 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003806 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003807out:
3808 up(&priv->wx_sem);
3809 return ret;
3810}
3811
Ana Reyf4c60742014-03-13 12:36:38 +01003812static u8 HwRateToMRate90(bool bIsHT, u8 rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003813{
3814 u8 ret_rate = 0xff;
3815
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003816 if (!bIsHT) {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003817 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003818 case DESC90_RATE1M: ret_rate = MGN_1M; break;
3819 case DESC90_RATE2M: ret_rate = MGN_2M; break;
3820 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
3821 case DESC90_RATE11M: ret_rate = MGN_11M; break;
3822 case DESC90_RATE6M: ret_rate = MGN_6M; break;
3823 case DESC90_RATE9M: ret_rate = MGN_9M; break;
3824 case DESC90_RATE12M: ret_rate = MGN_12M; break;
3825 case DESC90_RATE18M: ret_rate = MGN_18M; break;
3826 case DESC90_RATE24M: ret_rate = MGN_24M; break;
3827 case DESC90_RATE36M: ret_rate = MGN_36M; break;
3828 case DESC90_RATE48M: ret_rate = MGN_48M; break;
3829 case DESC90_RATE54M: ret_rate = MGN_54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003830
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003831 default:
3832 ret_rate = 0xff;
3833 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
3834 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003835 }
3836
3837 } else {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003838 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003839 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
3840 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
3841 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
3842 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
3843 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
3844 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
3845 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
3846 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
3847 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
3848 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
3849 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
3850 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
3851 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
3852 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
3853 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
3854 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
3855 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003856
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003857 default:
3858 ret_rate = 0xff;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003859 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003860 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003861 }
3862 }
3863
3864 return ret_rate;
3865}
3866
3867/**
3868 * Function: UpdateRxPktTimeStamp
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003869 * Overview: Record the TSF time stamp when receiving a packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02003870 *
3871 * Input:
3872 * PADAPTER Adapter
3873 * PRT_RFD pRfd,
3874 *
3875 * Output:
3876 * PRT_RFD pRfd
3877 * (pRfd->Status.TimeStampHigh is updated)
3878 * (pRfd->Status.TimeStampLow is updated)
3879 * Return:
3880 * None
3881 */
Teodora Baluta46326d22013-10-16 01:59:17 +03003882static void UpdateRxPktTimeStamp8190(struct net_device *dev,
3883 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003884{
3885 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3886
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003887 if (stats->bIsAMPDU && !stats->bFirstMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003888 stats->mac_time[0] = priv->LastRxDescTSFLow;
3889 stats->mac_time[1] = priv->LastRxDescTSFHigh;
3890 } else {
3891 priv->LastRxDescTSFLow = stats->mac_time[0];
3892 priv->LastRxDescTSFHigh = stats->mac_time[1];
3893 }
3894}
3895
3896//by amy 080606
3897
Ana Reyf4c60742014-03-13 12:36:38 +01003898static long rtl819x_translate_todbm(u8 signal_strength_index)// 0-100 index.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003899{
3900 long signal_power; // in dBm.
3901
3902 // Translate to dBm (x=0.5y-95).
3903 signal_power = (long)((signal_strength_index + 1) >> 1);
3904 signal_power -= 95;
3905
3906 return signal_power;
3907}
3908
3909
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003910/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
Jerry Chuang8fc85982009-11-03 07:17:11 -02003911 be a local static. Otherwise, it may increase when we return from S3/S4. The
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003912 value will be kept in memory or disk. Declare the value in the adaptor
3913 and it will be reinitialized when returned from S3/S4. */
Ana Reyf4c60742014-03-13 12:36:38 +01003914static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
3915 struct ieee80211_rx_stats *pprevious_stats,
3916 struct ieee80211_rx_stats *pcurrent_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003917{
3918 bool bcheck = false;
3919 u8 rfpath;
3920 u32 nspatial_stream, tmp_val;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003921 static u32 slide_rssi_index, slide_rssi_statistics;
3922 static u32 slide_evm_index, slide_evm_statistics;
3923 static u32 last_rssi, last_evm;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003924
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003925 static u32 slide_beacon_adc_pwdb_index, slide_beacon_adc_pwdb_statistics;
3926 static u32 last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003927
3928 struct ieee80211_hdr_3addr *hdr;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003929 u16 sc;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003930 unsigned int frag, seq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003931 hdr = (struct ieee80211_hdr_3addr *)buffer;
3932 sc = le16_to_cpu(hdr->seq_ctl);
3933 frag = WLAN_GET_SEQ_FRAG(sc);
3934 seq = WLAN_GET_SEQ_SEQ(sc);
3935 //cosa add 04292008 to record the sequence number
3936 pcurrent_stats->Seq_Num = seq;
3937 //
3938 // Check whether we should take the previous packet into accounting
3939 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003940 if (!pprevious_stats->bIsAMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003941 // if previous packet is not aggregated packet
3942 bcheck = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003943 }
3944
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003945 if (slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003946 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
3947 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
3948 priv->stats.slide_rssi_total -= last_rssi;
3949 }
3950 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
3951
3952 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003953 if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003954 slide_rssi_index = 0;
3955
3956 // <1> Showed on UI for user, in dbm
3957 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
3958 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
3959 pcurrent_stats->rssi = priv->stats.signal_strength;
3960 //
3961 // If the previous packet does not match the criteria, neglect it
3962 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003963 if (!pprevious_stats->bPacketMatchBSSID) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003964 if (!pprevious_stats->bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003965 return;
3966 }
3967
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003968 if (!bcheck)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003969 return;
3970
3971
3972 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
3973
3974 //
3975 // Check RSSI
3976 //
3977 priv->stats.num_process_phyinfo++;
3978
3979 /* record the general signal strength to the sliding window. */
3980
3981
3982 // <2> Showed on UI for engineering
3983 // hardware does not provide rssi information for each rf path in CCK
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003984 if (!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA)) {
3985 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003986 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
3987 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003988
3989 //Fixed by Jacken 2008-03-20
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003990 if (priv->stats.rx_rssi_percentage[rfpath] == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003991 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003992 if (pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath]) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003993 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003994 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003995 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003996 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003997 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003998 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003999 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004000 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004001 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004002 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 -02004003 }
4004 }
4005
4006
4007 //
4008 // Check PWDB.
4009 //
4010 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004011 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004012 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004013
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004014 if (pprevious_stats->bPacketBeacon) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004015 /* record the beacon pwdb to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004016 if (slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004017 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
4018 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
4019 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004020 }
4021 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
4022 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004023 slide_beacon_adc_pwdb_index++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004024 if (slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004025 slide_beacon_adc_pwdb_index = 0;
4026 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004027 if (pprevious_stats->RxPWDBAll >= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004028 pprevious_stats->RxPWDBAll -= 3;
4029 }
4030
4031 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004032 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004033 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004034
4035
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004036 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004037 if (priv->undecorated_smoothed_pwdb < 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004038 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004039 if (pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004040 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004041 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4042 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004043 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004044 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004045 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004046 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4047 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004048 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004049
4050 }
4051
4052 //
4053 // Check EVM
4054 //
4055 /* record the general EVM to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004056 if (pprevious_stats->SignalQuality) {
4057 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4058 if (slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004059 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
4060 last_evm = priv->stats.slide_evm[slide_evm_index];
4061 priv->stats.slide_evm_total -= last_evm;
4062 }
4063
4064 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
4065
4066 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004067 if (slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004068 slide_evm_index = 0;
4069
4070 // <1> Showed on UI for user, in percentage.
4071 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
4072 priv->stats.signal_quality = tmp_val;
4073 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
4074 priv->stats.last_signal_strength_inpercent = tmp_val;
4075 }
4076
4077 // <2> Showed on UI for engineering
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004078 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4079 for (nspatial_stream = 0; nspatial_stream < 2; nspatial_stream++) { // 2 spatial stream
4080 if (pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004081 if (priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004082 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
Jerry Chuang8fc85982009-11-03 07:17:11 -02004083 priv->stats.rx_evm_percentage[nspatial_stream] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004084 ((priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004085 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004086 }
4087 }
4088 }
4089 }
4090
4091
4092}
4093
4094/*-----------------------------------------------------------------------------
4095 * Function: rtl819x_query_rxpwrpercentage()
4096 *
4097 * Overview:
4098 *
4099 * Input: char antpower
4100 *
4101 * Output: NONE
4102 *
4103 * Return: 0-100 percentage
4104 *
4105 * Revised History:
4106 * When Who Remark
4107 * 05/26/2008 amy Create Version 0 porting from windows code.
4108 *
4109 *---------------------------------------------------------------------------*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004110static u8 rtl819x_query_rxpwrpercentage(char antpower)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004111{
4112 if ((antpower <= -100) || (antpower >= 20))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004113 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004114 else if (antpower >= 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004115 return 100;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004116 else
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004117 return 100 + antpower;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004118
4119} /* QueryRxPwrPercentage */
4120
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004121static u8 rtl819x_evm_dbtopercentage(char value)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004122{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004123 char ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004124
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004125 ret_val = value;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004126
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004127 if (ret_val >= 0)
4128 ret_val = 0;
4129 if (ret_val <= -33)
4130 ret_val = -33;
4131 ret_val = 0 - ret_val;
4132 ret_val *= 3;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004133 if (ret_val == 99)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004134 ret_val = 100;
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004135 return ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004136}
4137//
4138// Description:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004139// We want good-looking for signal strength/quality
Jerry Chuang8fc85982009-11-03 07:17:11 -02004140// 2007/7/19 01:09, by cosa.
4141//
Teodora Baluta46326d22013-10-16 01:59:17 +03004142static long rtl819x_signal_scale_mapping(long currsig)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004143{
4144 long retsig;
4145
4146 // Step 1. Scale mapping.
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004147 if (currsig >= 61 && currsig <= 100)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004148 retsig = 90 + ((currsig - 60) / 4);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004149 else if (currsig >= 41 && currsig <= 60)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004150 retsig = 78 + ((currsig - 40) / 2);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004151 else if (currsig >= 31 && currsig <= 40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004152 retsig = 66 + (currsig - 30);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004153 else if (currsig >= 21 && currsig <= 30)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004154 retsig = 54 + (currsig - 20);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004155 else if (currsig >= 5 && currsig <= 20)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004156 retsig = 42 + (((currsig - 5) * 2) / 3);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004157 else if (currsig == 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004158 retsig = 36;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004159 else if (currsig == 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004160 retsig = 27;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004161 else if (currsig == 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004162 retsig = 18;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004163 else if (currsig == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004164 retsig = 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004165 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004166 retsig = currsig;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004167
4168 return retsig;
4169}
4170
Xenia Ragiadakouf2c3d802013-06-04 23:32:32 +03004171static inline bool rx_hal_is_cck_rate(struct rx_drvinfo_819x_usb *pdrvinfo)
4172{
4173 if (pdrvinfo->RxHT)
4174 return false;
4175
4176 switch (pdrvinfo->RxRate) {
4177 case DESC90_RATE1M:
4178 case DESC90_RATE2M:
4179 case DESC90_RATE5_5M:
4180 case DESC90_RATE11M:
4181 return true;
4182 default:
4183 return false;
4184 }
4185}
4186
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004187static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
4188 struct ieee80211_rx_stats *pstats,
4189 rx_drvinfo_819x_usb *pdrvinfo,
4190 struct ieee80211_rx_stats *precord_stats,
4191 bool bpacket_match_bssid,
4192 bool bpacket_toself,
4193 bool bPacketBeacon,
4194 bool bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004195{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004196 phy_sts_ofdm_819xusb_t *pofdm_buf;
4197 phy_sts_cck_819xusb_t *pcck_buf;
4198 phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004199 u8 *prxpkt;
4200 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004201 char rx_pwr[4], rx_pwr_all = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004202 char rx_snrX, rx_evmX;
4203 u8 evm, pwdb_all;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004204 u32 RSSI, total_rssi = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004205 u8 is_cck_rate = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004206 u8 rf_rx_num = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004207 u8 sq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004208
4209
4210 priv->stats.numqry_phystatus++;
4211
4212 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4213
4214 // Record it for next packet processing
4215 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4216 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4217 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004218 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004219 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4220 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4221
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004222 prxpkt = (u8 *)pdrvinfo;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004223
4224 /* Move pointer to the 16th bytes. Phy status start address. */
4225 prxpkt += sizeof(rx_drvinfo_819x_usb);
4226
4227 /* Initial the cck and ofdm buffer pointer */
4228 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
4229 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
4230
4231 pstats->RxMIMOSignalQuality[0] = -1;
4232 pstats->RxMIMOSignalQuality[1] = -1;
4233 precord_stats->RxMIMOSignalQuality[0] = -1;
4234 precord_stats->RxMIMOSignalQuality[1] = -1;
4235
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004236 if (is_cck_rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004237 //
4238 // (1)Hardware does not provide RSSI for CCK
4239 //
4240
4241 //
4242 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4243 //
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004244 u8 report;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004245
4246 priv->stats.numqry_phystatusCCK++;
4247
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004248 if (!priv->bCckHighPower) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004249 report = pcck_buf->cck_agc_rpt & 0xc0;
4250 report = report>>6;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004251 switch (report) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004252 //Fixed by Jacken from Bryant 2008-03-20
4253 //Original value is -38 , -26 , -14 , -2
4254 //Fixed value is -35 , -23 , -11 , 6
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004255 case 0x3:
4256 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4257 break;
4258 case 0x2:
4259 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4260 break;
4261 case 0x1:
4262 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4263 break;
4264 case 0x0:
4265 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
4266 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004267 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004268 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004269 report = pcck_buf->cck_agc_rpt & 0x60;
4270 report = report>>5;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004271 switch (report) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004272 case 0x3:
4273 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4274 break;
4275 case 0x2:
4276 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4277 break;
4278 case 0x1:
4279 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4280 break;
4281 case 0x0:
4282 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4283 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004284 }
4285 }
4286
4287 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4288 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4289 pstats->RecvSignalPower = pwdb_all;
4290
4291 //
4292 // (3) Get Signal Quality (EVM)
4293 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02004294
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004295 if (pstats->RxPWDBAll > 40) {
4296 sq = 100;
4297 } else {
4298 sq = pcck_buf->sq_rpt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004299
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004300 if (pcck_buf->sq_rpt > 64)
4301 sq = 0;
4302 else if (pcck_buf->sq_rpt < 20)
4303 sq = 100;
4304 else
4305 sq = ((64-sq) * 100) / 44;
4306 }
4307 pstats->SignalQuality = precord_stats->SignalQuality = sq;
4308 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
4309 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004310
4311 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004312 priv->stats.numqry_phystatusHT++;
4313 //
4314 // (1)Get RSSI for HT rate
4315 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004316 for (i = RF90_PATH_A; i < priv->NumTotalRFPath; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004317 // 2008/01/30 MH we will judge RF RX path now.
4318 if (priv->brfpath_rxenable[i])
4319 rf_rx_num++;
4320 else
4321 continue;
4322
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004323 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004324 continue;
4325
4326 //Fixed by Jacken from Bryant 2008-03-20
4327 //Original value is 106
4328 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
4329
4330 //Get Rx snr value in DB
4331 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
4332 rx_snrX = (char)(tmp_rxsnr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004333 rx_snrX /= 2;
4334 priv->stats.rxSNRdB[i] = (long)rx_snrX;
4335
4336 /* Translate DBM to percentage. */
4337 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
4338 total_rssi += RSSI;
4339
4340 /* Record Signal Strength for next packet */
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004341 pstats->RxMIMOSignalStrength[i] = (u8) RSSI;
4342 precord_stats->RxMIMOSignalStrength[i] = (u8) RSSI;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004343 }
4344
4345
4346 //
4347 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4348 //
4349 //Fixed by Jacken from Bryant 2008-03-20
4350 //Original value is 106
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004351 rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1)& 0x7f) -106;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004352 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4353
4354 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4355 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
4356
4357 //
4358 // (3)EVM of HT rate
4359 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004360 if (pdrvinfo->RxHT && pdrvinfo->RxRate >= DESC90_RATEMCS8 &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004361 pdrvinfo->RxRate <= DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004362 max_spatial_stream = 2; //both spatial stream make sense
4363 else
4364 max_spatial_stream = 1; //only spatial stream 1 makes sense
4365
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004366 for (i = 0; i < max_spatial_stream; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004367 tmp_rxevm = pofdm_buf->rxevm_X[i];
4368 rx_evmX = (char)(tmp_rxevm);
4369
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004370 // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004371 // will set the most significant bit to "zero" when doing shifting operation which may change a negative
Jerry Chuang8fc85982009-11-03 07:17:11 -02004372 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
4373 rx_evmX /= 2; //dbm
4374
4375 evm = rtl819x_evm_dbtopercentage(rx_evmX);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004376 if (i == 0) // Fill value in RFD, Get the first spatial stream only
4377 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
4378 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004379 }
4380
4381
4382 /* record rx statistics for debug */
4383 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
4384 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004385 if (pdrvinfo->BW) //40M channel
Jerry Chuang8fc85982009-11-03 07:17:11 -02004386 priv->stats.received_bwtype[1+prxsc->rxsc]++;
4387 else //20M channel
4388 priv->stats.received_bwtype[0]++;
4389 }
4390
4391 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
4392 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004393 if (is_cck_rate) {
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004394 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004395 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004396 // We can judge RX path number now.
4397 if (rf_rx_num != 0)
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004398 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi /= rf_rx_num)));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004399 }
4400} /* QueryRxPhyStatus8190Pci */
4401
Ana Reyf4c60742014-03-13 12:36:38 +01004402static void rtl8192_record_rxdesc_forlateruse(struct ieee80211_rx_stats *psrc_stats,
4403 struct ieee80211_rx_stats *ptarget_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004404{
4405 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
4406 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
4407 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
4408}
4409
4410
Teodora Baluta46326d22013-10-16 01:59:17 +03004411static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
4412 struct ieee80211_rx_stats *pstats,
4413 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004414{
4415 // TODO: We must only check packet for current MAC address. Not finish
4416 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004417 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004418 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4419 bool bpacket_match_bssid, bpacket_toself;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004420 bool bPacketBeacon = FALSE, bToSelfBA = FALSE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004421 static struct ieee80211_rx_stats previous_stats;
4422 struct ieee80211_hdr_3addr *hdr;//by amy
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004423 u16 fc, type;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004424
4425 // Get Signal Quality for only RX data queue (but not command queue)
4426
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004427 u8 *tmp_buf;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004428 u8 *praddr;
4429
4430 /* Get MAC frame start address. */
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004431 tmp_buf = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004432
4433 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
4434 fc = le16_to_cpu(hdr->frame_ctl);
4435 type = WLAN_FC_GET_TYPE(fc);
4436 praddr = hdr->addr1;
4437
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004438 /* Check if the received packet is acceptable. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004439 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004440 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
4441 && (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004442 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
4443
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004444 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON)
4445 bPacketBeacon = true;
4446 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK) {
4447 if ((eqMacAddr(praddr, dev->dev_addr)))
4448 bToSelfBA = true;
4449 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004450
Jerry Chuang8fc85982009-11-03 07:17:11 -02004451
4452
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004453 if (bpacket_match_bssid)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004454 priv->stats.numpacket_matchbssid++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004455 if (bpacket_toself)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004456 priv->stats.numpacket_toself++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004457 //
4458 // Process PHY information for previous packet (RSSI/PWDB/EVM)
4459 //
4460 // Because phy information is contained in the last packet of AMPDU only, so driver
4461 // should process phy information of previous packet
4462 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004463 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid, bpacket_toself, bPacketBeacon, bToSelfBA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004464 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
4465
4466}
4467
4468/**
4469* Function: UpdateReceivedRateHistogramStatistics
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004470* Overview: Record the received data rate
Jerry Chuang8fc85982009-11-03 07:17:11 -02004471*
4472* Input:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004473* struct net_device *dev
Jerry Chuang8fc85982009-11-03 07:17:11 -02004474* struct ieee80211_rx_stats *stats
4475*
4476* Output:
4477*
4478* (priv->stats.ReceivedRateHistogram[] is updated)
4479* Return:
4480* None
4481*/
Teodora Baluta46326d22013-10-16 01:59:17 +03004482static void
4483UpdateReceivedRateHistogramStatistics8190(struct net_device *dev,
4484 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004485{
4486 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004487 u32 rcvType = 1; //0: Total, 1:OK, 2:CRC, 3:ICV
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004488 u32 rateIndex;
4489 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02004490
4491
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004492 if (stats->bCRC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004493 rcvType = 2;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004494 else if (stats->bICV)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004495 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004496
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004497 if (stats->bShortPreamble)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004498 preamble_guardinterval = 1;// short
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004499 else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004500 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02004501
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004502 switch (stats->rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004503 //
4504 // CCK rate
4505 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004506 case MGN_1M: rateIndex = 0; break;
4507 case MGN_2M: rateIndex = 1; break;
4508 case MGN_5_5M: rateIndex = 2; break;
4509 case MGN_11M: rateIndex = 3; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004510 //
4511 // Legacy OFDM rate
4512 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004513 case MGN_6M: rateIndex = 4; break;
4514 case MGN_9M: rateIndex = 5; break;
4515 case MGN_12M: rateIndex = 6; break;
4516 case MGN_18M: rateIndex = 7; break;
4517 case MGN_24M: rateIndex = 8; break;
4518 case MGN_36M: rateIndex = 9; break;
4519 case MGN_48M: rateIndex = 10; break;
4520 case MGN_54M: rateIndex = 11; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004521 //
4522 // 11n High throughput rate
4523 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004524 case MGN_MCS0: rateIndex = 12; break;
4525 case MGN_MCS1: rateIndex = 13; break;
4526 case MGN_MCS2: rateIndex = 14; break;
4527 case MGN_MCS3: rateIndex = 15; break;
4528 case MGN_MCS4: rateIndex = 16; break;
4529 case MGN_MCS5: rateIndex = 17; break;
4530 case MGN_MCS6: rateIndex = 18; break;
4531 case MGN_MCS7: rateIndex = 19; break;
4532 case MGN_MCS8: rateIndex = 20; break;
4533 case MGN_MCS9: rateIndex = 21; break;
4534 case MGN_MCS10: rateIndex = 22; break;
4535 case MGN_MCS11: rateIndex = 23; break;
4536 case MGN_MCS12: rateIndex = 24; break;
4537 case MGN_MCS13: rateIndex = 25; break;
4538 case MGN_MCS14: rateIndex = 26; break;
4539 case MGN_MCS15: rateIndex = 27; break;
4540 default: rateIndex = 28; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004541 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004542 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
4543 priv->stats.received_rate_histogram[0][rateIndex]++; //total
4544 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004545}
4546
4547
Teodora Baluta46326d22013-10-16 01:59:17 +03004548static void query_rxdesc_status(struct sk_buff *skb,
4549 struct ieee80211_rx_stats *stats,
4550 bool bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004551{
4552 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004553 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004554 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004555 rx_drvinfo_819x_usb *driver_info = NULL;
4556
4557 //
4558 //Get Rx Descriptor Information
4559 //
4560#ifdef USB_RX_AGGREGATION_SUPPORT
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004561 if (bIsRxAggrSubframe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004562 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004563 stats->Length = desc->Length;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004564 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
4565 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
4566 stats->bICV = desc->ICV;
4567 stats->bCRC = desc->CRC32;
4568 stats->bHwError = stats->bCRC|stats->bICV;
4569 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
4570 } else
4571#endif
4572 {
4573 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
4574
4575 stats->Length = desc->Length;
4576 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004577 stats->RxBufShift = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004578 stats->bICV = desc->ICV;
4579 stats->bCRC = desc->CRC32;
4580 stats->bHwError = stats->bCRC|stats->bICV;
4581 //RTL8190 set this bit to indicate that Hw does not decrypt packet
4582 stats->Decrypted = !desc->SWDec;
4583 }
4584
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004585 if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004586 stats->bHwError = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004587 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004588 stats->bHwError = stats->bCRC|stats->bICV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004589
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004590 if (stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004591 stats->bHwError |= 1;
4592 //
4593 //Get Driver Info
4594 //
4595 // TODO: Need to verify it on FGPA platform
4596 //Driver info are written to the RxBuffer following rx desc
4597 if (stats->RxDrvInfoSize != 0) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004598 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004599 stats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004600 /* unit: 0.5M */
4601 /* TODO */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004602 if (!stats->bHwError) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004603 u8 ret_rate;
4604 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004605 if (ret_rate == 0xff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004606 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
4607 // Special Error Handling here, 2008.05.16, by Emily
4608
4609 stats->bHwError = 1;
4610 stats->rate = MGN_1M; //Set 1M rate by default
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004611 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004612 stats->rate = ret_rate;
4613 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004614 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004615 stats->rate = 0x02;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004616 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004617
4618 stats->bShortPreamble = driver_info->SPLCP;
4619
4620
4621 UpdateReceivedRateHistogramStatistics8190(dev, stats);
4622
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004623 stats->bIsAMPDU = (driver_info->PartAggr == 1);
4624 stats->bFirstMPDU = (driver_info->PartAggr == 1) && (driver_info->FirstAGGR == 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004625 stats->TimeStampLow = driver_info->TSFL;
4626 // xiong mask it, 070514
Jerry Chuang8fc85982009-11-03 07:17:11 -02004627
4628 UpdateRxPktTimeStamp8190(dev, stats);
4629
4630 //
4631 // Rx A-MPDU
4632 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004633 if (driver_info->FirstAGGR == 1 || driver_info->PartAggr == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004634 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004635 driver_info->FirstAGGR, driver_info->PartAggr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004636
4637 }
4638
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004639 skb_pull(skb, sizeof(rx_desc_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004640 //
4641 // Get Total offset of MPDU Frame Body
4642 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004643 if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004644 stats->bShift = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004645 skb_pull(skb, stats->RxBufShift + stats->RxDrvInfoSize);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004646 }
4647
4648#ifdef USB_RX_AGGREGATION_SUPPORT
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004649 /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004650 if (bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004651 skb_pull(skb, 8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004652#endif
4653 /* for debug 2008.5.29 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004654
4655 //added by vivi, for MP, 20080108
4656 stats->RxIs40MHzPacket = driver_info->BW;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004657 if (stats->RxDrvInfoSize != 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004658 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
4659
4660}
4661
4662u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
4663{
4664#ifdef USB_RX_AGGREGATION_SUPPORT
4665 if (bIsRxAggrSubframe)
4666 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
4667 + Status->RxBufShift + 8);
4668 else
4669#endif
4670 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004671 + Status->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004672}
4673
Ana Reyf4c60742014-03-13 12:36:38 +01004674static void rtl8192_rx_nomal(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004675{
4676 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004677 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004678 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4679 struct ieee80211_rx_stats stats = {
4680 .signal = 0,
4681 .noise = -98,
4682 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004683 .freq = IEEE80211_24GHZ_BAND,
4684 };
4685 u32 rx_pkt_len = 0;
4686 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
4687 bool unicast_packet = false;
4688#ifdef USB_RX_AGGREGATION_SUPPORT
4689 struct sk_buff *agg_skb = NULL;
4690 u32 TotalLength = 0;
4691 u32 TempDWord = 0;
4692 u32 PacketLength = 0;
4693 u32 PacketOccupiedLendth = 0;
4694 u8 TempByte = 0;
4695 u32 PacketShiftBytes = 0;
4696 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
4697 u8 PaddingBytes = 0;
4698 //add just for testing
4699 u8 testing;
4700
4701#endif
4702
4703 /* 20 is for ps-poll */
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004704 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004705#ifdef USB_RX_AGGREGATION_SUPPORT
4706 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
4707#endif
4708 /* first packet should not contain Rx aggregation header */
4709 query_rxdesc_status(skb, &stats, false);
4710 /* TODO */
4711 /* hardware related info */
4712#ifdef USB_RX_AGGREGATION_SUPPORT
4713 if (TempByte & BIT0) {
4714 agg_skb = skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004715 TotalLength = stats.Length - 4; /*sCrcLng*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02004716 /* though the head pointer has passed this position */
4717 TempDWord = *(u32 *)(agg_skb->data - 4);
4718 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
4719 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004720 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004721 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
4722 }
4723#endif
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004724 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004725 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4726
4727 rx_pkt_len = skb->len;
4728 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4729 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004730 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004731 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004732 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004733 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004734 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004735 /* unicast packet */
4736 unicast_packet = true;
4737 }
4738
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004739 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004740 dev_kfree_skb_any(skb);
4741 } else {
4742 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004743 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004744 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004745 }
4746#ifdef USB_RX_AGGREGATION_SUPPORT
4747 testing = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004748 if (TotalLength > 0) {
4749 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
4750 if ((PacketOccupiedLendth & 0xFF) != 0)
4751 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
4752 PacketOccupiedLendth -= 8;
4753 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
4754 if (agg_skb->len > TempDWord)
4755 skb_pull(agg_skb, TempDWord);
4756 else
4757 agg_skb->len = 0;
4758
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004759 while (agg_skb->len >= GetRxPacketShiftBytes819xUsb(&stats, true)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004760 u8 tmpCRC = 0, tmpICV = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004761 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
4762 tmpCRC = RxDescr->CRC32;
4763 tmpICV = RxDescr->ICV;
4764 memcpy(agg_skb->data, &agg_skb->data[44], 2);
4765 RxDescr->CRC32 = tmpCRC;
4766 RxDescr->ICV = tmpICV;
4767
4768 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
4769 stats.signal = 0;
4770 stats.noise = -98;
4771 stats.rate = 0;
4772 stats.freq = IEEE80211_24GHZ_BAND;
4773 query_rxdesc_status(agg_skb, &stats, true);
4774 PacketLength = stats.Length;
4775
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004776 if (PacketLength > agg_skb->len)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004777 break;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004778 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004779 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004780 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004781 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4782
4783 rx_pkt_len = skb->len;
4784 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4785 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004786 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004787 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004788 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004789 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004790 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004791 /* unicast packet */
4792 unicast_packet = true;
4793 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004794 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004795 dev_kfree_skb_any(skb);
4796 } else {
4797 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004798 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004799 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004800 }
4801 /* should trim the packet which has been copied to target skb */
4802 skb_pull(agg_skb, PacketLength);
4803 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
4804 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
4805 if ((PacketOccupiedLendth & 0xFF) != 0) {
4806 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
4807 if (agg_skb->len > PaddingBytes)
4808 skb_pull(agg_skb, PaddingBytes);
4809 else
4810 agg_skb->len = 0;
4811 }
4812 }
4813 dev_kfree_skb(agg_skb);
4814 }
4815#endif
4816 } else {
4817 priv->stats.rxurberr++;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03004818 netdev_dbg(dev, "actual_length: %d\n", skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004819 dev_kfree_skb_any(skb);
4820 }
4821
4822}
4823
Ana Reyf4c60742014-03-13 12:36:38 +01004824static void rtl819xusb_process_received_packet(struct net_device *dev,
4825 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004826{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004827 u8 *frame;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004828 u16 frame_len = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004829 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004830
4831 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
4832 //porting by amy 080508
4833 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
4834 frame = pstats->virtual_address;
4835 frame_len = pstats->packetlength;
4836#ifdef TODO // by amy about HCT
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004837 if (!Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004838 CountRxErrStatistics(Adapter, pRfd);
4839#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004840#ifdef ENABLE_PS //by amy for adding ps function in future
4841 RT_RF_POWER_STATE rtState;
4842 // When RF is off, we should not count the packet for hw/sw synchronize
4843 // reason, ie. there may be a duration while sw switch is changed and hw
4844 // switch is being changed. 2006.12.04, by shien chang.
4845 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8 *)(&rtState));
4846 if (rtState == eRfOff)
4847 return;
4848#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -02004849 priv->stats.rxframgment++;
4850
Jerry Chuang8fc85982009-11-03 07:17:11 -02004851#ifdef TODO
4852 RmMonitorSignalStrength(Adapter, pRfd);
4853#endif
4854 /* 2007/01/16 MH Add RX command packet handle here. */
4855 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
4856 if (rtl819xusb_rx_command_packet(dev, pstats))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004857 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004858
4859#ifdef SW_CRC_CHECK
4860 SwCrcCheck();
4861#endif
4862
4863
4864}
4865
Teodora Baluta46326d22013-10-16 01:59:17 +03004866static void query_rx_cmdpkt_desc_status(struct sk_buff *skb,
4867 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004868{
Jerry Chuang8fc85982009-11-03 07:17:11 -02004869 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004870
4871 //
4872 //Get Rx Descriptor Information
4873 //
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004874 stats->virtual_address = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004875 stats->Length = desc->Length;
4876 stats->RxDrvInfoSize = 0;
4877 stats->RxBufShift = 0;
4878 stats->packetlength = stats->Length-scrclng;
4879 stats->fraglength = stats->packetlength;
4880 stats->fragoffset = 0;
4881 stats->ntotalfrag = 1;
4882}
4883
4884
Ana Reyf4c60742014-03-13 12:36:38 +01004885static void rtl8192_rx_cmd(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004886{
4887 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
4888 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004889 /* TODO */
4890 struct ieee80211_rx_stats stats = {
4891 .signal = 0,
4892 .noise = -98,
4893 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004894 .freq = IEEE80211_24GHZ_BAND,
4895 };
4896
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004897 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004898
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004899 query_rx_cmdpkt_desc_status(skb, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004900 // this is to be done by amy 080508 prfd->queue_id = 1;
4901
4902
4903 //
4904 // Process the command packet received.
4905 //
4906
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004907 rtl819xusb_process_received_packet(dev, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004908
4909 dev_kfree_skb_any(skb);
4910 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004911}
4912
4913void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
4914{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004915 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004916 struct rtl8192_rx_info *info;
4917
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004918 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004919 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004920 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004921 /* Nomal packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004922 case 3:
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004923 priv->IrpPendingCount--;
4924 rtl8192_rx_nomal(skb);
4925 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004926
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004927 /* Command packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004928 case 9:
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004929 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004930 info->out_pipe);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004931
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004932 rtl8192_rx_cmd(skb);
4933 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004934
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004935 default: /* should never get here! */
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004936 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004937 info->out_pipe);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004938 dev_kfree_skb(skb);
4939 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004940
4941 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004942 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004943}
4944
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02004945static const struct net_device_ops rtl8192_netdev_ops = {
4946 .ndo_open = rtl8192_open,
4947 .ndo_stop = rtl8192_close,
4948 .ndo_get_stats = rtl8192_stats,
4949 .ndo_tx_timeout = tx_timeout,
4950 .ndo_do_ioctl = rtl8192_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00004951 .ndo_set_rx_mode = r8192_set_multicast,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02004952 .ndo_set_mac_address = r8192_set_mac_adr,
4953 .ndo_validate_addr = eth_validate_addr,
4954 .ndo_change_mtu = eth_change_mtu,
4955 .ndo_start_xmit = ieee80211_xmit,
4956};
Jerry Chuang8fc85982009-11-03 07:17:11 -02004957
4958
4959/****************************************************************************
4960 ---------------------------- USB_STUFF---------------------------
4961*****************************************************************************/
4962
Bill Pemberton25794522012-11-19 13:22:04 -05004963static int rtl8192_usb_probe(struct usb_interface *intf,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004964 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004965{
Jerry Chuang8fc85982009-11-03 07:17:11 -02004966 struct net_device *dev = NULL;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004967 struct r8192_priv *priv = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004968 struct usb_device *udev = interface_to_usbdev(intf);
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04004969 int ret;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004970 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02004971
4972 dev = alloc_ieee80211(sizeof(struct r8192_priv));
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04004973 if (dev == NULL)
4974 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004975
Jerry Chuang8fc85982009-11-03 07:17:11 -02004976 usb_set_intfdata(intf, dev);
4977 SET_NETDEV_DEV(dev, &intf->dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004978 priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004979 priv->ieee80211 = netdev_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004980 priv->udev = udev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004981
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004982 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004983
Jerry Chuang8fc85982009-11-03 07:17:11 -02004984#if WIRELESS_EXT >= 12
4985#if WIRELESS_EXT < 17
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004986 dev->get_wireless_stats = r8192_get_wireless_stats;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004987#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004988 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004989#endif
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004990 dev->type = ARPHRD_ETHER;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004991
4992 dev->watchdog_timeo = HZ*3; //modified by john, 0805
4993
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004994 if (dev_alloc_name(dev, ifname) < 0) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004995 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02004996 ifname = "wlan%d";
4997 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004998 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004999
5000 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005001 if (rtl8192_init(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005002 RT_TRACE(COMP_ERR, "Initialization failed");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005003 ret = -ENODEV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005004 goto fail;
5005 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005006 netif_carrier_off(dev);
5007 netif_stop_queue(dev);
5008
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005009 ret = register_netdev(dev);
5010 if (ret)
5011 goto fail2;
5012
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005013 RT_TRACE(COMP_INIT, "dev name=======> %s\n", dev->name);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005014 rtl8192_proc_init_one(dev);
5015
5016
5017 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005018 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005019
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005020fail2:
5021 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005022 kfree(priv->pFirmware);
5023 priv->pFirmware = NULL;
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005024 rtl8192_usb_deleteendpoints(dev);
5025 destroy_workqueue(priv->priv_wq);
5026 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005027fail:
5028 free_ieee80211(dev);
5029
5030 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005031 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005032}
5033
5034//detach all the work and timer structure declared or inititialize in r8192U_init function.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005035void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005036{
5037
Jerry Chuang8fc85982009-11-03 07:17:11 -02005038 cancel_work_sync(&priv->reset_wq);
5039 cancel_delayed_work(&priv->watch_dog_wq);
5040 cancel_delayed_work(&priv->update_beacon_wq);
5041 cancel_work_sync(&priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005042}
5043
5044
Bill Pembertona4a557e2012-11-19 13:26:46 -05005045static void rtl8192_usb_disconnect(struct usb_interface *intf)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005046{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005047 struct net_device *dev = usb_get_intfdata(intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005048
5049 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005050 if (dev) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005051
5052 unregister_netdev(dev);
5053
5054 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
5055 rtl8192_proc_remove_one(dev);
5056
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005057 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005058 kfree(priv->pFirmware);
5059 priv->pFirmware = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005060 rtl8192_usb_deleteendpoints(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005061 destroy_workqueue(priv->priv_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005062 mdelay(10);
5063
5064 }
5065 free_ieee80211(dev);
5066 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
5067}
5068
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005069/* fun with the built-in ieee80211 stack... */
5070extern int ieee80211_debug_init(void);
5071extern void ieee80211_debug_exit(void);
5072extern int ieee80211_crypto_init(void);
5073extern void ieee80211_crypto_deinit(void);
5074extern int ieee80211_crypto_tkip_init(void);
5075extern void ieee80211_crypto_tkip_exit(void);
5076extern int ieee80211_crypto_ccmp_init(void);
5077extern void ieee80211_crypto_ccmp_exit(void);
5078extern int ieee80211_crypto_wep_init(void);
5079extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005080
5081static int __init rtl8192_usb_module_init(void)
5082{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005083 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005084
5085#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005086 ret = ieee80211_debug_init();
5087 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005088 pr_err("ieee80211_debug_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005089 return ret;
5090 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005091#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005092 ret = ieee80211_crypto_init();
5093 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005094 pr_err("ieee80211_crypto_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005095 return ret;
5096 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005097
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005098 ret = ieee80211_crypto_tkip_init();
5099 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005100 pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005101 return ret;
5102 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005103
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005104 ret = ieee80211_crypto_ccmp_init();
5105 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005106 pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005107 return ret;
5108 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005109
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005110 ret = ieee80211_crypto_wep_init();
5111 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005112 pr_err("ieee80211_crypto_wep_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005113 return ret;
5114 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005115
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005116 pr_info("\nLinux kernel driver for RTL8192 based WLAN cards\n");
5117 pr_info("Copyright (c) 2007-2008, Realsil Wlan\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005118 RT_TRACE(COMP_INIT, "Initializing module");
5119 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
5120 rtl8192_proc_module_init();
5121 return usb_register(&rtl8192_usb_driver);
5122}
5123
5124
5125static void __exit rtl8192_usb_module_exit(void)
5126{
5127 usb_deregister(&rtl8192_usb_driver);
5128
5129 RT_TRACE(COMP_DOWN, "Exiting");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005130}
5131
5132
5133void rtl8192_try_wake_queue(struct net_device *dev, int pri)
5134{
5135 unsigned long flags;
5136 short enough_desc;
5137 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5138
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005139 spin_lock_irqsave(&priv->tx_lock, flags);
5140 enough_desc = check_nic_enough_desc(dev, pri);
5141 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005142
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005143 if (enough_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005144 ieee80211_wake_queue(priv->ieee80211);
5145}
5146
5147void EnableHWSecurityConfig8192(struct net_device *dev)
5148{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005149 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005150 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005151 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005152 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005153 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 -02005154 SECR_value |= SCR_RxUseDK;
5155 SECR_value |= SCR_TxUseDK;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005156 } 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 -02005157 SECR_value |= SCR_RxUseDK;
5158 SECR_value |= SCR_TxUseDK;
5159 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005160 //add HWSec active enable here.
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005161 //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 -02005162
5163 ieee->hwsec_active = 1;
5164
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005165 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 -02005166 ieee->hwsec_active = 0;
5167 SECR_value &= ~SCR_RxDecEnable;
5168 }
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03005169 RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __func__,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005170 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
5171 write_nic_byte(dev, SECR, SECR_value);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005172}
5173
5174
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03005175void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
5176 u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005177{
5178 u32 TargetCommand = 0;
5179 u32 TargetContent = 0;
5180 u16 usConfig = 0;
5181 u8 i;
5182 if (EntryNo >= TOTAL_CAM_ENTRY)
5183 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
5184
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005185 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 -02005186
5187 if (DefaultKey)
5188 usConfig |= BIT15 | (KeyType<<2);
5189 else
5190 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005191
5192
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005193 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005194 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
5195 TargetCommand |= BIT31|BIT16;
5196
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005197 if (i == 0) { //MAC|Config
Jerry Chuang8fc85982009-11-03 07:17:11 -02005198 TargetContent = (u32)(*(MacAddr+0)) << 16|
5199 (u32)(*(MacAddr+1)) << 24|
5200 (u32)usConfig;
5201
5202 write_nic_dword(dev, WCAMI, TargetContent);
5203 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005204 } else if (i == 1) { //MAC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005205 TargetContent = (u32)(*(MacAddr+2)) |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005206 (u32)(*(MacAddr+3)) << 8|
5207 (u32)(*(MacAddr+4)) << 16|
5208 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005209 write_nic_dword(dev, WCAMI, TargetContent);
5210 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005211 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005212 //Key Material
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005213 if (KeyContent != NULL) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005214 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)));
5215 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005216 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005217 }
5218 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005219
5220}
5221
5222/***************************************************************************
5223 ------------------- module init / exit stubs ----------------
5224****************************************************************************/
5225module_init(rtl8192_usb_module_init);
5226module_exit(rtl8192_usb_module_exit);