blob: 97af38f9f281a95c6f9bc8b07bc4c201c67479c3 [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
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002048 mutex_lock(&priv->mutex);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002049 if (priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002050 goto success;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002051 RT_TRACE(COMP_QOS, "qos active process with associate response received\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002052 /* It better set slot time at first */
2053 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2054 /* update the ac parameter to related registers */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002055 for (i = 0; i < QOS_QUEUE_NUM; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002056 //Mode G/A: slotTimeTimer = 9; Mode B: 20
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002057 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002058 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002059 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2060 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2061 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002062
2063 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002064 }
2065
2066success:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002067 mutex_unlock(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002068}
2069
2070static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002071 int active_network,
2072 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002073{
2074 int ret = 0;
2075 u32 size = sizeof(struct ieee80211_qos_parameters);
2076
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002077 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002078 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002079
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002080 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2081 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002082
2083 if (network->flags & NETWORK_HAS_QOS_MASK) {
2084 if (active_network &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002085 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
Jerry Chuang8fc85982009-11-03 07:17:11 -02002086 network->qos_data.active = network->qos_data.supported;
2087
2088 if ((network->qos_data.active == 1) && (active_network == 1) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002089 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2090 (network->qos_data.old_param_count !=
2091 network->qos_data.param_count)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002092 network->qos_data.old_param_count =
2093 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002094 queue_work(priv->priv_wq, &priv->qos_activate);
Xenia Ragiadakoue6367212013-05-23 05:14:46 +03002095 RT_TRACE(COMP_QOS, "QoS parameters change call "
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002096 "qos_activate\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002097 }
2098 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002099 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002100 &def_qos_parameters, size);
2101
2102 if ((network->qos_data.active == 1) && (active_network == 1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002103 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002104 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2105 }
2106 network->qos_data.active = 0;
2107 network->qos_data.supported = 0;
2108 }
2109
2110 return 0;
2111}
2112
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002113/* handle and manage frame from beacon and probe response */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002114static int rtl8192_handle_beacon(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002115 struct ieee80211_beacon *beacon,
2116 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002117{
2118 struct r8192_priv *priv = ieee80211_priv(dev);
2119
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002120 rtl8192_qos_handle_probe_response(priv, 1, network);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002121 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002122 return 0;
2123
2124}
2125
2126/*
2127* handling the beaconing responses. if we get different QoS setting
2128* off the network from the associated setting, adjust the QoS
2129* setting
2130*/
2131static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002132 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002133{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002134 int ret = 0;
2135 unsigned long flags;
2136 u32 size = sizeof(struct ieee80211_qos_parameters);
2137 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002138
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002139 if ((priv == NULL) || (network == NULL))
2140 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002141
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002142 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002143 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002144
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002145 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2146 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002147
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002148 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002149 if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002150 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002151 &network->qos_data.parameters,
2152 sizeof(struct ieee80211_qos_parameters));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002153 priv->ieee80211->current_network.qos_data.active = 1;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002154 set_qos_param = 1;
2155 /* update qos parameter for current network */
2156 priv->ieee80211->current_network.qos_data.old_param_count =
2157 priv->ieee80211->current_network.qos_data.param_count;
2158 priv->ieee80211->current_network.qos_data.param_count =
2159 network->qos_data.param_count;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002160 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002161 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002162 &def_qos_parameters, size);
2163 priv->ieee80211->current_network.qos_data.active = 0;
2164 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002165 set_qos_param = 1;
2166 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002167
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002168 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002169
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002170 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 -02002171 if (set_qos_param == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002172 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002173
2174
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002175 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002176}
2177
2178
2179static int rtl8192_handle_assoc_response(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002180 struct ieee80211_assoc_response_frame *resp,
2181 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002182{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002183 struct r8192_priv *priv = ieee80211_priv(dev);
2184 rtl8192_qos_association_resp(priv, network);
2185 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002186}
2187
2188
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002189void rtl8192_update_ratr_table(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002190{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002191 struct r8192_priv *priv = ieee80211_priv(dev);
2192 struct ieee80211_device *ieee = priv->ieee80211;
2193 u8 *pMcsRate = ieee->dot11HTOperationalRateSet;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002194 u32 ratr_value = 0;
2195 u8 rate_index = 0;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002196 rtl8192_config_rate(dev, (u16 *)(&ratr_value));
2197 ratr_value |= (*(u16 *)(pMcsRate)) << 12;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002198 switch (ieee->mode) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002199 case IEEE_A:
2200 ratr_value &= 0x00000FF0;
2201 break;
2202 case IEEE_B:
2203 ratr_value &= 0x0000000F;
2204 break;
2205 case IEEE_G:
2206 ratr_value &= 0x00000FF7;
2207 break;
2208 case IEEE_N_24G:
2209 case IEEE_N_5G:
2210 if (ieee->pHTInfo->PeerMimoPs == 0) {//MIMO_PS_STATIC
2211 ratr_value &= 0x0007F007;
2212 } else {
2213 if (priv->rf_type == RF_1T2R)
2214 ratr_value &= 0x000FF007;
2215 else
2216 ratr_value &= 0x0F81F007;
2217 }
2218 break;
2219 default:
2220 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002221 }
2222 ratr_value &= 0x0FFFFFFF;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002223 if (ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002224 ratr_value |= 0x80000000;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002225 else if (!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002226 ratr_value |= 0x80000000;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002227 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2228 write_nic_byte(dev, UFWP, 1);
2229}
2230
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002231static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04};
Jerry Chuang8fc85982009-11-03 07:17:11 -02002232static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
Teodora Baluta46326d22013-10-16 01:59:17 +03002233static bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002234{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002235 struct r8192_priv *priv = ieee80211_priv(dev);
2236 struct ieee80211_device *ieee = priv->ieee80211;
2237 struct ieee80211_network *network = &ieee->current_network;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002238 int wpa_ie_len = ieee->wpa_ie_len;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002239 struct ieee80211_crypt_data *crypt;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002240 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002241
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002242 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002243 //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 +03002244 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 -02002245
2246 /* simply judge */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002247 if (encrypt && (wpa_ie_len == 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002248 /* wep encryption, no N mode setting */
2249 return false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002250 } else if ((wpa_ie_len != 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002251 /* parse pairwise key type */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002252 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 -02002253 return true;
2254 else
2255 return false;
2256 } else {
2257 return true;
2258 }
2259
Jerry Chuang8fc85982009-11-03 07:17:11 -02002260 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002261}
2262
Ana Reyf4c60742014-03-13 12:36:38 +01002263static bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002264{
2265 bool Reval;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002266 struct r8192_priv *priv = ieee80211_priv(dev);
2267 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002268
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002269 if (ieee->bHalfWirelessN24GMode == true)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002270 Reval = true;
2271 else
2272 Reval = false;
2273
2274 return Reval;
2275}
2276
Ana Reyf4c60742014-03-13 12:36:38 +01002277static void rtl8192_refresh_supportrate(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002278{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002279 struct ieee80211_device *ieee = priv->ieee80211;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002280 //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002281 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002282 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002283 else
2284 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2285 return;
2286}
2287
Ana Reyf4c60742014-03-13 12:36:38 +01002288static u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002289{
2290 struct r8192_priv *priv = ieee80211_priv(dev);
2291 u8 ret = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002292 switch (priv->rf_chip) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002293 case RF_8225:
2294 case RF_8256:
2295 case RF_PSEUDO_11N:
2296 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2297 break;
2298 case RF_8258:
2299 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2300 break;
2301 default:
2302 ret = WIRELESS_MODE_B;
2303 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002304 }
2305 return ret;
2306}
Ana Reyf4c60742014-03-13 12:36:38 +01002307static void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002308{
2309 struct r8192_priv *priv = ieee80211_priv(dev);
2310 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2311
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002312 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode) == 0)) {
2313 if (bSupportMode & WIRELESS_MODE_N_24G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002314 wireless_mode = WIRELESS_MODE_N_24G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002315 } else if (bSupportMode & WIRELESS_MODE_N_5G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002316 wireless_mode = WIRELESS_MODE_N_5G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002317 } else if ((bSupportMode & WIRELESS_MODE_A)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002318 wireless_mode = WIRELESS_MODE_A;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002319 } else if ((bSupportMode & WIRELESS_MODE_G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002320 wireless_mode = WIRELESS_MODE_G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002321 } else if ((bSupportMode & WIRELESS_MODE_B)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002322 wireless_mode = WIRELESS_MODE_B;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002323 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002324 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __func__, bSupportMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002325 wireless_mode = WIRELESS_MODE_B;
2326 }
2327 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002328#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 +03002329 ActUpdateChannelAccessSetting(pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002330#endif
2331 priv->ieee80211->mode = wireless_mode;
2332
2333 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2334 priv->ieee80211->pHTInfo->bEnableHT = 1;
2335 else
2336 priv->ieee80211->pHTInfo->bEnableHT = 0;
2337 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2338 rtl8192_refresh_supportrate(priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002339
2340}
2341//init priv variables here. only non_zero value should be initialized here.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002342static void rtl8192_init_priv_variable(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002343{
2344 struct r8192_priv *priv = ieee80211_priv(dev);
2345 u8 i;
2346 priv->card_8192 = NIC_8192U;
2347 priv->chan = 1; //set to channel 1
2348 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2349 priv->ieee80211->iw_mode = IW_MODE_INFRA;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002350 priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002351 priv->retry_rts = DEFAULT_RETRY_RTS;
2352 priv->retry_data = DEFAULT_RETRY_DATA;
2353 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2354 priv->ieee80211->rate = 110; //11 mbps
2355 priv->ieee80211->short_slot = 1;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002356 priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002357 priv->CckPwEnl = 6;
2358 //for silent reset
2359 priv->IrpPendingCount = 1;
2360 priv->ResetProgress = RESET_TYPE_NORESET;
2361 priv->bForcedSilentReset = 0;
2362 priv->bDisableNormalResetCheck = false;
2363 priv->force_reset = false;
2364
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002365 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002366 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2367 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2368 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2369 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2370 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002371 IEEE_SOFTMAC_BEACONS;//added by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002372
2373 priv->ieee80211->active_scan = 1;
2374 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2375 priv->ieee80211->host_encrypt = 1;
2376 priv->ieee80211->host_decrypt = 1;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002377 priv->ieee80211->start_send_beacons = NULL; //-by amy 080604
2378 priv->ieee80211->stop_send_beacons = NULL; //-by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002379 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2380 priv->ieee80211->set_chan = rtl8192_set_chan;
2381 priv->ieee80211->link_change = rtl8192_link_change;
2382 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2383 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2384 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2385 priv->ieee80211->init_wmmparam_flag = 0;
2386 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2387 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2388 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
2389 priv->ieee80211->qos_support = 1;
2390
2391 //added by WB
Jerry Chuang8fc85982009-11-03 07:17:11 -02002392 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2393 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2394 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2395 //added by david
2396 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
2397 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
2398 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2399 //added by amy
2400 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
2401 priv->card_type = USB;
2402#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002403 if (Adapter->bInHctTest) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002404 pHalData->ShortRetryLimit = 7;
2405 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002406 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002407#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002408 priv->ShortRetryLimit = 0x30;
2409 priv->LongRetryLimit = 0x30;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002410 priv->EarlyRxThreshold = 7;
2411 priv->enable_gpio0 = 0;
2412 priv->TransmitConfig =
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002413 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002414 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
2415 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002416 (false ? TCR_SAT : 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
Jerry Chuang8fc85982009-11-03 07:17:11 -02002417#ifdef TO_DO_LIST
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002418 if (Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002419 pHalData->ReceiveConfig = pHalData->CSMethod |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002420 RCR_AMF | RCR_ADF | //accept management/data
Jerry Chuang8fc85982009-11-03 07:17:11 -02002421 //guangan200710
2422 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2423 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002424 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002425 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2426 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002427 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002428 else
2429
2430#endif
2431 priv->ReceiveConfig =
2432 RCR_AMF | RCR_ADF | //accept management/data
2433 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2434 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Jerry Chuang8fc85982009-11-03 07:17:11 -02002435 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2436 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002437 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002438
2439 priv->AcmControl = 0;
Devendra Nagab7553422012-08-26 11:06:33 +05302440 priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002441
2442 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002443 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002444 skb_queue_head_init(&priv->skb_queue);
2445
2446 /* Tx related queue */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002447 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002448 skb_queue_head_init(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002449 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002450 skb_queue_head_init(&priv->ieee80211->skb_aggQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002451 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002452 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002453 priv->rf_set_chan = rtl8192_phy_SwChnl;
2454}
2455
2456//init lock here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002457static void rtl8192_init_priv_lock(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002458{
2459 spin_lock_init(&priv->tx_lock);
2460 spin_lock_init(&priv->irq_lock);//added by thomas
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002461 sema_init(&priv->wx_sem, 1);
2462 sema_init(&priv->rf_sem, 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002463 mutex_init(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002464}
2465
Jerry Chuang8fc85982009-11-03 07:17:11 -02002466extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002467
2468void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
2469//init tasklet and wait_queue here. only 2.6 above kernel is considered
2470#define DRV_NAME "wlan0"
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002471static void rtl8192_init_priv_task(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002472{
2473 struct r8192_priv *priv = ieee80211_priv(dev);
2474
Jerry Chuang8fc85982009-11-03 07:17:11 -02002475 priv->priv_wq = create_workqueue(DRV_NAME);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002476
Jerry Chuang8fc85982009-11-03 07:17:11 -02002477 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2478
Jerry Chuang8fc85982009-11-03 07:17:11 -02002479 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2480 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002481 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2482 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2483 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002484 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002485
2486 tasklet_init(&priv->irq_rx_tasklet,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002487 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2488 (unsigned long)priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002489}
2490
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002491static void rtl8192_get_eeprom_size(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002492{
2493 u16 curCR = 0;
2494 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002495 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002496 read_nic_word_E(dev, EPROM_CMD, &curCR);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002497 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
2498 //whether need I consider BIT5?
2499 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002500 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __func__, priv->epromtype);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002501}
2502
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002503//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002504static inline u16 endian_swap(u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002505{
2506 u16 tmp = *data;
2507 *data = (tmp >> 8) | (tmp << 8);
2508 return *data;
2509}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002510static void rtl8192_read_eeprom_info(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002511{
2512 u16 wEPROM_ID = 0;
2513 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
2514 u8 bLoad_From_EEPOM = false;
2515 struct r8192_priv *priv = ieee80211_priv(dev);
2516 u16 tmpValue = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002517 int i;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002518 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002519 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
2520 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
2521
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002522 if (wEPROM_ID != RTL8190_EEPROM_ID) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002523 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 +03002524 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002525 bLoad_From_EEPOM = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002526 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002527
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002528 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002529 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
2530 priv->eeprom_vid = endian_swap(&tmpValue);
2531 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
2532 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002533 priv->eeprom_ChannelPlan = ((tmpValue&0xff00)>>8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002534 priv->btxpowerdata_readfromEEPORM = true;
2535 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002536 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002537 priv->eeprom_vid = 0;
2538 priv->eeprom_pid = 0;
2539 priv->card_8192_version = VERSION_819xU_B;
2540 priv->eeprom_ChannelPlan = 0;
2541 priv->eeprom_CustomerID = 0;
2542 }
2543 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);
2544 //set channelplan from eeprom
2545 priv->ChannelPlan = priv->eeprom_ChannelPlan;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002546 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002547 int i;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002548 for (i = 0; i < 6; i += 2) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002549 u16 tmp = 0;
2550 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002551 *(u16 *)(&dev->dev_addr[i]) = tmp;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002552 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002553 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002554 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2555 //should I set IDR0 here?
2556 }
Joe Perches0ee9f672009-12-06 11:34:52 -08002557 RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002558 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
2559 priv->rf_chip = RF_8256;
2560
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002561 if (priv->card_8192_version == (u8)VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002562 //read Tx power gain offset of legacy OFDM to HT rate
2563 if (bLoad_From_EEPOM)
2564 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
2565 else
2566 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
2567 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
2568 //read ThermalMeter from EEPROM
2569 if (bLoad_From_EEPOM)
2570 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
2571 else
2572 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2573 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
2574 //vivi, for tx power track
2575 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2576 //read antenna tx power offset of B/C/D to A from EEPROM
2577 if (bLoad_From_EEPOM)
2578 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
2579 else
2580 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
2581 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
2582 // Read CrystalCap from EEPROM
2583 if (bLoad_From_EEPOM)
2584 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
2585 else
2586 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
2587 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
2588 //get per-channel Tx power level
2589 if (bLoad_From_EEPOM)
2590 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
2591 else
2592 priv->EEPROM_Def_Ver = 1;
2593 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002594 if (priv->EEPROM_Def_Ver == 0) { //old eeprom definition
Jerry Chuang8fc85982009-11-03 07:17:11 -02002595 int i;
2596 if (bLoad_From_EEPOM)
2597 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
2598 else
2599 priv->EEPROMTxPowerLevelCCK = 0x10;
2600 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002601 for (i = 0; i < 3; i++) {
2602 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002603 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
2604 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
2605 tmpValue = tmpValue & 0x00ff;
2606 else
2607 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002608 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002609 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002610 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002611 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
2612 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
2613 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002614 } else if (priv->EEPROM_Def_Ver == 1) {
2615 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002616 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
2617 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002618 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002619 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002620 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002621 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
2622
2623 if (bLoad_From_EEPOM)
2624 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
2625 else
2626 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002627 *((u16 *)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002628 if (bLoad_From_EEPOM)
2629 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
2630 else
2631 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002632 *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002633 if (bLoad_From_EEPOM)
2634 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
2635 else
2636 tmpValue = 0x10;
2637 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
2638 }//endif EEPROM_Def_Ver == 1
2639
2640 //update HAL variables
2641 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002642 for (i = 0; i < 14; i++) {
2643 if (i <= 3)
2644 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
2645 else if (i >= 4 && i <= 9)
2646 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
2647 else
2648 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
2649 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002650
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002651 for (i = 0; i < 14; i++) {
2652 if (priv->EEPROM_Def_Ver == 0) {
2653 if (i <= 3)
2654 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2655 else if (i >= 4 && i <= 9)
2656 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
2657 else
2658 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2659 } else if (priv->EEPROM_Def_Ver == 1) {
2660 if (i <= 3)
2661 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
2662 else if (i >= 4 && i <= 9)
2663 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
2664 else
2665 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002666 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002667 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002668 priv->TxPowerDiff = priv->EEPROMPwDiff;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002669 // Antenna B gain offset to antenna A, bit0~3
Jerry Chuang8fc85982009-11-03 07:17:11 -02002670 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
2671 // Antenna C gain offset to antenna A, bit4~7
2672 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
2673 // CrystalCap, bit12~15
2674 priv->CrystalCap = priv->EEPROMCrystalCap;
2675 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
2676 // 92U does not enable TX power tracking.
2677 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
2678 }//end if VersionID == VERSION_819xU_A
2679
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002680 //added by vivi, for dlink led, 20080416
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002681 switch (priv->eeprom_CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002682 case EEPROM_CID_RUNTOP:
2683 priv->CustomerID = RT_CID_819x_RUNTOP;
2684 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002685
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002686 case EEPROM_CID_DLINK:
2687 priv->CustomerID = RT_CID_DLINK;
2688 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002689
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002690 default:
2691 priv->CustomerID = RT_CID_DEFAULT;
2692 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002693
2694 }
2695
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002696 switch (priv->CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002697 case RT_CID_819x_RUNTOP:
2698 priv->LedStrategy = SW_LED_MODE2;
2699 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002700
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002701 case RT_CID_DLINK:
2702 priv->LedStrategy = SW_LED_MODE4;
2703 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002704
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002705 default:
2706 priv->LedStrategy = SW_LED_MODE0;
2707 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002708
2709 }
2710
2711
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002712 if (priv->rf_type == RF_1T2R) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002713 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002714 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002715 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
2716 }
2717
2718 // 2008/01/16 MH We can only know RF type in the function. So we have to init
2719 // DIG RATR table again.
2720 init_rate_adaptive(dev);
2721 //we need init DIG RATR table here again.
2722
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002723 RT_TRACE(COMP_EPROM, "<===========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002724 return;
2725}
2726
Ana Reyf4c60742014-03-13 12:36:38 +01002727static short rtl8192_get_channel_map(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002728{
2729 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002730 if (priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03002731 netdev_err(dev, "rtl8180_init: Error channel plan! Set to default.\n");
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002732 priv->ChannelPlan = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002733 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002734 RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002735
2736 rtl819x_set_channel_map(priv->ChannelPlan, priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002737 return 0;
2738}
2739
Ana Reyf4c60742014-03-13 12:36:38 +01002740static short rtl8192_init(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002741{
2742
2743 struct r8192_priv *priv = ieee80211_priv(dev);
2744
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002745 memset(&(priv->stats), 0, sizeof(struct Stats));
2746 memset(priv->txqueue_to_outpipemap, 0, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002747#ifdef PIPE12
2748 {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002749 int i = 0;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002750 u8 queuetopipe[] = {3, 2, 1, 0, 4, 8, 7, 6, 5};
2751 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002752 }
2753#else
2754 {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002755 u8 queuetopipe[] = {3, 2, 1, 0, 4, 4, 0, 4, 4};
2756 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002757 }
2758#endif
2759 rtl8192_init_priv_variable(dev);
2760 rtl8192_init_priv_lock(priv);
2761 rtl8192_init_priv_task(dev);
2762 rtl8192_get_eeprom_size(dev);
2763 rtl8192_read_eeprom_info(dev);
2764 rtl8192_get_channel_map(dev);
2765 init_hal_dm(dev);
2766 init_timer(&priv->watch_dog_timer);
2767 priv->watch_dog_timer.data = (unsigned long)dev;
2768 priv->watch_dog_timer.function = watch_dog_timer_callback;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002769 if (rtl8192_usb_initendpoints(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002770 DMESG("Endopoints initialization failed");
2771 return -ENOMEM;
2772 }
2773
Jerry Chuang8fc85982009-11-03 07:17:11 -02002774#ifdef DEBUG_EPROM
2775 dump_eprom(dev);
2776#endif
2777 return 0;
2778}
2779
2780/******************************************************************************
2781 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
2782 * not to do all the hw config as its name says
2783 * input: net_device dev
2784 * output: none
2785 * return: none
2786 * notice: This part need to modified according to the rate set we filtered
2787 * ****************************************************************************/
Ana Reyf4c60742014-03-13 12:36:38 +01002788static void rtl8192_hwconfig(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002789{
2790 u32 regRATR = 0, regRRSR = 0;
2791 u8 regBwOpMode = 0, regTmp = 0;
2792 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002793 u32 ratr_value = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002794
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002795 // Set RRSR, RATR, and BW_OPMODE registers
Jerry Chuang8fc85982009-11-03 07:17:11 -02002796 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002797 switch (priv->ieee80211->mode) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002798 case WIRELESS_MODE_B:
2799 regBwOpMode = BW_OPMODE_20MHZ;
2800 regRATR = RATE_ALL_CCK;
2801 regRRSR = RATE_ALL_CCK;
2802 break;
2803 case WIRELESS_MODE_A:
2804 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
2805 regRATR = RATE_ALL_OFDM_AG;
2806 regRRSR = RATE_ALL_OFDM_AG;
2807 break;
2808 case WIRELESS_MODE_G:
2809 regBwOpMode = BW_OPMODE_20MHZ;
2810 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2811 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2812 break;
2813 case WIRELESS_MODE_AUTO:
2814#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002815 if (Adapter->bInHctTest) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002816 regBwOpMode = BW_OPMODE_20MHZ;
2817 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2818 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002819 }
2820 else
2821#endif
2822 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002823 regBwOpMode = BW_OPMODE_20MHZ;
2824 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2825 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002826 }
2827 break;
2828 case WIRELESS_MODE_N_24G:
2829 // It support CCK rate by default.
2830 // CCK rate will be filtered out only when associated AP does not support it.
2831 regBwOpMode = BW_OPMODE_20MHZ;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002832 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2833 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002834 break;
2835 case WIRELESS_MODE_N_5G:
2836 regBwOpMode = BW_OPMODE_5G;
2837 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2838 regRRSR = RATE_ALL_OFDM_AG;
2839 break;
2840 }
2841
2842 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002843 ratr_value = regRATR;
2844 if (priv->rf_type == RF_1T2R)
2845 ratr_value &= ~(RATE_ALL_OFDM_2SS);
2846 write_nic_dword(dev, RATR0, ratr_value);
2847 write_nic_byte(dev, UFWP, 1);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002848 read_nic_byte(dev, 0x313, &regTmp);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002849 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
2850 write_nic_dword(dev, RRSR, regRRSR);
2851
2852 //
2853 // Set Retry Limit here
2854 //
2855 write_nic_word(dev, RETRY_LIMIT,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002856 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
2857 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002858 // Set Contention Window here
2859
2860 // Set Tx AGC
2861
2862 // Set Tx Antenna including Feedback control
2863
2864 // Set Auto Rate fallback control
2865
2866
2867}
2868
2869
2870//InitializeAdapter and PhyCfg
Ana Reyf4c60742014-03-13 12:36:38 +01002871static bool rtl8192_adapter_start(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002872{
2873 struct r8192_priv *priv = ieee80211_priv(dev);
2874 u32 dwRegRead = 0;
2875 bool init_status = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002876 u8 SECR_value = 0x0;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002877 u8 tmp;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002878 RT_TRACE(COMP_INIT, "====>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002879 priv->Rf_Mode = RF_OP_By_SW_3wire;
2880 //for ASIC power on sequence
2881 write_nic_byte_E(dev, 0x5f, 0x80);
2882 mdelay(50);
2883 write_nic_byte_E(dev, 0x5f, 0xf0);
2884 write_nic_byte_E(dev, 0x5d, 0x00);
2885 write_nic_byte_E(dev, 0x5e, 0x80);
2886 write_nic_byte(dev, 0x17, 0x37);
2887 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002888 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
2889 //config CPUReset Register
2890 //Firmware Reset or not?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002891 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002892 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
2893 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
2894 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
2895 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
2896 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002897 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __func__, priv->pFirmware->firmware_status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002898
2899 write_nic_dword(dev, CPU_GEN, dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002900 //config BB.
2901 rtl8192_BBConfig(dev);
2902
Jerry Chuang8fc85982009-11-03 07:17:11 -02002903 //Loopback mode or not
2904 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002905
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002906 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002907 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
2908 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
2909 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
2910 dwRegRead |= CPU_CCK_LOOPBACK;
2911 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002912 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __func__, priv->LoopbackMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002913
2914 write_nic_dword(dev, CPU_GEN, dwRegRead);
2915
2916 //after reset cpu, we need wait for a seconds to write in register.
2917 udelay(500);
2918
2919 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002920 read_nic_byte_E(dev, 0x5f, &tmp);
2921 write_nic_byte_E(dev, 0x5f, tmp|0x20);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002922
2923 //Set Hardware
2924 rtl8192_hwconfig(dev);
2925
2926 //turn on Tx/Rx
2927 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
2928
2929 //set IDR0 here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002930 write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
2931 write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002932
2933 //set RCR
2934 write_nic_dword(dev, RCR, priv->ReceiveConfig);
2935
2936 //Initialize Number of Reserved Pages in Firmware Queue
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002937 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 +03002938 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT |
2939 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT |
2940 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002941 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 +03002942 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002943 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002944 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002945 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
2946
2947 //Set AckTimeout
2948 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
2949 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
2950
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002951 if (priv->ResetProgress == RESET_TYPE_NORESET)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002952 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002953 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002954 CamResetAllEntry(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002955 SECR_value |= SCR_TxEncEnable;
2956 SECR_value |= SCR_RxDecEnable;
2957 SECR_value |= SCR_NoSKMC;
2958 write_nic_byte(dev, SECR, SECR_value);
2959 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002960
2961 //Beacon related
2962 write_nic_word(dev, ATIMWND, 2);
2963 write_nic_word(dev, BCN_INTERVAL, 100);
2964
Jerry Chuang8fc85982009-11-03 07:17:11 -02002965#define DEFAULT_EDCA 0x005e4332
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002966 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002967 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002968 for (i = 0; i < QOS_QUEUE_NUM; i++)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002969 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002970 }
2971#ifdef USB_RX_AGGREGATION_SUPPORT
2972 //3 For usb rx firmware aggregation control
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002973 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002974 u32 ulValue;
2975 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
2976 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002977 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002978 /*
2979 * If usb rx firmware aggregation is enabled,
2980 * when anyone of three threshold conditions above is reached,
2981 * firmware will send aggregated packet to driver.
2982 */
2983 write_nic_dword(dev, 0x1a8, ulValue);
2984 priv->bCurrentRxAggrEnable = true;
2985 }
2986#endif
2987
2988 rtl8192_phy_configmac(dev);
2989
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002990 if (priv->card_8192_version == (u8) VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002991 rtl8192_phy_getTxPower(dev);
2992 rtl8192_phy_setTxPower(dev, priv->chan);
2993 }
2994
2995 //Firmware download
2996 init_status = init_firmware(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002997 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002998 RT_TRACE(COMP_ERR, "ERR!!! %s(): Firmware download is failed\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002999 return init_status;
3000 }
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003001 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003002 //
3003#ifdef TO_DO_LIST
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003004 if (Adapter->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003005 if (pMgntInfo->RegRfOff == TRUE) { // User disable RF via registry.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003006 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
3007 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003008 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003009 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003010 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003011 } else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { // H/W or S/W RF OFF before sleep.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003012 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
3013 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003014 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003015 pHalData->eRFPowerState = eRfOn;
3016 pMgntInfo->RfOffReason = 0;
3017 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
3018 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003019 } else {
3020 if (pHalData->eRFPowerState == eRfOff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003021 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003022 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003023 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003024 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3025 }
3026 }
3027#endif
3028 //config RF.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003029 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003030 rtl8192_phy_RFConfig(dev);
3031 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003032 }
3033
3034
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003035 if (priv->ieee80211->FwRWRF)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003036 // We can force firmware to do RF-R/W
3037 priv->Rf_Mode = RF_OP_By_FW;
3038 else
3039 priv->Rf_Mode = RF_OP_By_SW_3wire;
3040
3041
3042 rtl8192_phy_updateInitGain(dev);
3043 /*--set CCK and OFDM Block "ON"--*/
3044 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3045 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3046
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003047 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003048 //if D or C cut
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003049 u8 tmpvalue;
3050 read_nic_byte(dev, 0x301, &tmpvalue);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003051 if (tmpvalue == 0x03) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003052 priv->bDcut = TRUE;
3053 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003054 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003055 priv->bDcut = FALSE;
3056 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
3057 }
3058 dm_initialize_txpower_tracking(dev);
3059
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003060 if (priv->bDcut == TRUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003061 u32 i, TempCCk;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003062 u32 tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003063 for (i = 0; i < TxBBGainTableLength; i++) {
3064 if (tmpRegA == priv->txbbgain_table[i].txbbgain_value) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003065 priv->rfa_txpowertrackingindex = (u8)i;
3066 priv->rfa_txpowertrackingindex_real = (u8)i;
3067 priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003068 break;
3069 }
3070 }
3071
3072 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3073
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003074 for (i = 0; i < CCKTxBBGainTableLength; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003075
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003076 if (TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0]) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003077 priv->cck_present_attentuation_20Mdefault = (u8) i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003078 break;
3079 }
3080 }
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003081 priv->cck_present_attentuation_40Mdefault = 0;
3082 priv->cck_present_attentuation_difference = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003083 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
3084
Jerry Chuang8fc85982009-11-03 07:17:11 -02003085 }
3086 }
3087 write_nic_byte(dev, 0x87, 0x0);
3088
3089
Jerry Chuang8fc85982009-11-03 07:17:11 -02003090 return init_status;
3091}
3092
3093/* this configures registers for beacon tx and enables it via
3094 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3095 * be used to stop beacon transmission
3096 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003097/***************************************************************************
3098 -------------------------------NET STUFF---------------------------
3099***************************************************************************/
3100
3101static struct net_device_stats *rtl8192_stats(struct net_device *dev)
3102{
3103 struct r8192_priv *priv = ieee80211_priv(dev);
3104
3105 return &priv->ieee80211->stats;
3106}
3107
Teodora Baluta46326d22013-10-16 01:59:17 +03003108static bool HalTxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003109{
3110 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003111 u16 RegTxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003112 bool bStuck = FALSE;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003113 read_nic_word(dev, 0x128, &RegTxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003114 RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", __func__, RegTxCounter, priv->TxCounter);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003115 if (priv->TxCounter == RegTxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003116 bStuck = TRUE;
3117
3118 priv->TxCounter = RegTxCounter;
3119
3120 return bStuck;
3121}
3122
3123/*
3124* <Assumption: RT_TX_SPINLOCK is acquired.>
3125* First added: 2006.11.19 by emily
3126*/
Ana Reyf4c60742014-03-13 12:36:38 +01003127static RESET_TYPE TxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003128{
3129 struct r8192_priv *priv = ieee80211_priv(dev);
3130 u8 QueueID;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003131 bool bCheckFwTxCnt = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003132
3133 //
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003134 // Decide such threshold according to current power save mode
Jerry Chuang8fc85982009-11-03 07:17:11 -02003135 //
3136
Xenia Ragiadakou7d79ec62013-06-04 23:32:30 +03003137 for (QueueID = 0; QueueID <= BEACON_QUEUE; QueueID++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003138 if (QueueID == TXCMD_QUEUE)
3139 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003140#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003141 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 -02003142#else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003143 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 -02003144#endif
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003145 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003146
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003147 bCheckFwTxCnt = true;
3148 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003149 if (bCheckFwTxCnt) {
3150 if (HalTxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003151 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
3152 return RESET_TYPE_SILENT;
3153 }
3154 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003155 return RESET_TYPE_NORESET;
3156}
3157
Teodora Baluta46326d22013-10-16 01:59:17 +03003158static bool HalRxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003159{
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003160 u16 RegRxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003161 struct r8192_priv *priv = ieee80211_priv(dev);
3162 bool bStuck = FALSE;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003163 static u8 rx_chk_cnt;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003164 read_nic_word(dev, 0x130, &RegRxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003165 RT_TRACE(COMP_RESET, "%s(): RegRxCounter is %d,RxCounter is %d\n", __func__, RegRxCounter, priv->RxCounter);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003166 // If rssi is small, we should check rx for long time because of bad rx.
3167 // or maybe it will continuous silent reset every 2 seconds.
3168 rx_chk_cnt++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003169 if (priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003170 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003171 } else if (priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003172 ((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_40M) ||
3173 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_20M))) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003174 if (rx_chk_cnt < 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003175 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003176 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003177 rx_chk_cnt = 0;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003178 } else if (((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_40M) ||
3179 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_20M)) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003180 priv->undecorated_smoothed_pwdb >= VeryLowRSSI) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003181 if (rx_chk_cnt < 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003182 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003183 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003184 rx_chk_cnt = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003185 } else {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003186 if (rx_chk_cnt < 8)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003187 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003188 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003189 rx_chk_cnt = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003190 }
3191
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003192 if (priv->RxCounter == RegRxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003193 bStuck = TRUE;
3194
3195 priv->RxCounter = RegRxCounter;
3196
3197 return bStuck;
3198}
3199
Teodora Baluta46326d22013-10-16 01:59:17 +03003200static RESET_TYPE RxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003201{
3202 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003203 bool bRxCheck = FALSE;
3204
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003205 if (priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003206 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003207
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003208 if (bRxCheck) {
3209 if (HalRxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003210 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
3211 return RESET_TYPE_SILENT;
3212 }
3213 }
3214 return RESET_TYPE_NORESET;
3215}
3216
3217
3218/**
3219* This function is called by Checkforhang to check whether we should ask OS to reset driver
3220*
3221* \param pAdapter The adapter context for this miniport
3222*
3223* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
3224* to judge whether there is tx stuck.
3225* Note: This function may be required to be rewrite for Vista OS.
3226* <<<Assumption: Tx spinlock has been acquired >>>
3227*
3228* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
3229*/
Ana Reyf4c60742014-03-13 12:36:38 +01003230static RESET_TYPE rtl819x_ifcheck_resetornot(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003231{
3232 struct r8192_priv *priv = ieee80211_priv(dev);
3233 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
3234 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003235 RT_RF_POWER_STATE rfState;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003236
3237 rfState = priv->ieee80211->eRFPowerState;
3238
3239 TxResetType = TxCheckStuck(dev);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003240 if (rfState != eRfOff ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003241 (priv->ieee80211->iw_mode != IW_MODE_ADHOC)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003242 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
3243 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
3244 // if driver is in firmware download failure status, driver should initialize RF in the following
3245 // silent reset procedure Emily, 2008.01.21
3246
3247 // Driver should not check RX stuck in IBSS mode because it is required to
3248 // set Check BSSID in order to send beacon, however, if check BSSID is
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003249 // set, STA cannot hear any packet at all. Emily, 2008.04.12
Jerry Chuang8fc85982009-11-03 07:17:11 -02003250 RxResetType = RxCheckStuck(dev);
3251 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003252 if (TxResetType == RESET_TYPE_NORMAL || RxResetType == RESET_TYPE_NORMAL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003253 return RESET_TYPE_NORMAL;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003254 } else if (TxResetType == RESET_TYPE_SILENT || RxResetType == RESET_TYPE_SILENT) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003255 RT_TRACE(COMP_RESET, "%s():silent reset\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003256 return RESET_TYPE_SILENT;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003257 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003258 return RESET_TYPE_NORESET;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003259 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003260
3261}
3262
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003263void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003264int _rtl8192_up(struct net_device *dev);
3265int rtl8192_close(struct net_device *dev);
3266
3267
3268
Ana Reyf4c60742014-03-13 12:36:38 +01003269static void CamRestoreAllEntry(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003270{
3271 u8 EntryId = 0;
3272 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003273 u8 *MacAddr = priv->ieee80211->current_network.bssid;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003274
3275 static u8 CAM_CONST_ADDR[4][6] = {
3276 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3277 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
3278 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03003279 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003280 static u8 CAM_CONST_BROAD[] = {
3281 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003282
3283 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
3284
3285
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003286 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40) ||
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003287 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003288
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003289 for (EntryId = 0; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003290 MacAddr = CAM_CONST_ADDR[EntryId];
3291 setKey(dev, EntryId, EntryId,
3292 priv->ieee80211->pairwise_key_type,
3293 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003294 }
3295
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003296 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003297
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003298 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3299 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3300 (u8 *)dev->dev_addr, 0, NULL);
3301 else
3302 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3303 MacAddr, 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003304 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003305
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003306 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3307 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3308 (u8 *)dev->dev_addr, 0, NULL);
3309 else
3310 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3311 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003312 }
3313
3314
3315
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003316 if (priv->ieee80211->group_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003317 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003318 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003319 setKey(dev, EntryId, EntryId,
3320 priv->ieee80211->group_key_type,
3321 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003322 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003323 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003324 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3325 CAM_CONST_ADDR[0], 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003326 } else if (priv->ieee80211->group_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003327 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003328 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003329 setKey(dev, EntryId, EntryId,
3330 priv->ieee80211->group_key_type,
3331 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003332 }
3333
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003334 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003335 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3336 CAM_CONST_ADDR[0], 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003337 }
3338}
3339//////////////////////////////////////////////////////////////
3340// This function is used to fix Tx/Rx stop bug temporarily.
3341// This function will do "system reset" to NIC when Tx or Rx is stuck.
3342// The method checking Tx/Rx stuck of this function is supported by FW,
3343// which reports Tx and Rx counter to register 0x128 and 0x130.
3344//////////////////////////////////////////////////////////////
Ana Reyf4c60742014-03-13 12:36:38 +01003345static void rtl819x_ifsilentreset(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003346{
Jerry Chuang8fc85982009-11-03 07:17:11 -02003347 struct r8192_priv *priv = ieee80211_priv(dev);
3348 u8 reset_times = 0;
3349 int reset_status = 0;
3350 struct ieee80211_device *ieee = priv->ieee80211;
3351
3352
3353 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
3354 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
3355
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003356 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003357RESET_START:
3358
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003359 RT_TRACE(COMP_RESET, "=========>Reset progress!! \n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003360
3361 // Set the variable for reset.
3362 priv->ResetProgress = RESET_TYPE_SILENT;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003363 down(&priv->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003364 if (priv->up == 0) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003365 RT_TRACE(COMP_ERR, "%s():the driver is not up! return\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003366 up(&priv->wx_sem);
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003367 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003368 }
3369 priv->up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003370 RT_TRACE(COMP_RESET, "%s():======>start to down the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003371
3372 rtl8192_rtx_disable(dev);
3373 rtl8192_cancel_deferred_work(priv);
3374 deinit_hal_dm(dev);
3375 del_timer_sync(&priv->watch_dog_timer);
3376
3377 ieee->sync_scan_hurryup = 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003378 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003379 down(&ieee->wx_sem);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003380 netdev_dbg(dev, "ieee->state is IEEE80211_LINKED\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003381 ieee80211_stop_send_beacons(priv->ieee80211);
3382 del_timer_sync(&ieee->associate_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003383 cancel_delayed_work(&ieee->associate_retry_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003384 ieee80211_stop_scan(ieee);
3385 netif_carrier_off(dev);
3386 up(&ieee->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003387 } else {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003388 netdev_dbg(dev, "ieee->state is NOT LINKED\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003389 ieee80211_softmac_stop_protocol(priv->ieee80211);
3390 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003391 up(&priv->wx_sem);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003392 RT_TRACE(COMP_RESET, "%s():<==========down process is finished\n", __func__);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003393 RT_TRACE(COMP_RESET, "%s():===========>start up the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003394 reset_status = _rtl8192_up(dev);
3395
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003396 RT_TRACE(COMP_RESET, "%s():<===========up process is finished\n", __func__);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003397 if (reset_status == -EAGAIN) {
3398 if (reset_times < 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003399 reset_times++;
3400 goto RESET_START;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003401 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003402 RT_TRACE(COMP_ERR, " ERR!!! %s(): Reset Failed!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003403 }
3404 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003405 ieee->is_silent_reset = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003406 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003407 if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003408 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3409
Jerry Chuang8fc85982009-11-03 07:17:11 -02003410 queue_work(ieee->wq, &ieee->associate_complete_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003411
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003412 } else if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003413 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3414 ieee->link_change(ieee->dev);
3415
Jerry Chuang8fc85982009-11-03 07:17:11 -02003416 ieee80211_start_send_beacons(ieee);
3417
3418 if (ieee->data_hard_resume)
3419 ieee->data_hard_resume(ieee->dev);
3420 netif_carrier_on(ieee->dev);
3421 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003422
3423 CamRestoreAllEntry(dev);
3424
3425 priv->ResetProgress = RESET_TYPE_NORESET;
3426 priv->reset_count++;
3427
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003428 priv->bForcedSilentReset = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003429 priv->bResetInProgress = false;
3430
3431 // For test --> force write UFWP.
3432 write_nic_byte(dev, UFWP, 1);
3433 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003434 }
3435}
3436
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003437void CAM_read_entry(struct net_device *dev, u32 iIndex)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003438{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003439 u32 target_command = 0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003440 u32 target_content = 0;
3441 u8 entry_i = 0;
3442 u32 ulStatus;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003443 s32 i = 100;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003444 for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003445 // polling bit, and No Write enable, and address
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003446 target_command = entry_i+CAM_CONTENT_COUNT*iIndex;
3447 target_command = target_command | BIT31;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003448
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003449 //Check polling bit is clear
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003450 while ((i--) >= 0) {
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003451 read_nic_dword(dev, RWCAM, &ulStatus);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003452 if (ulStatus & BIT31)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003453 continue;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003454 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003455 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003456 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003457 write_nic_dword(dev, RWCAM, target_command);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003458 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x \n", target_command);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003459 read_nic_dword(dev, RCAMO, &target_content);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003460 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n", target_content);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003461 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003462 printk("\n");
3463}
3464
Ana Reyf4c60742014-03-13 12:36:38 +01003465static void rtl819x_update_rxcounts(struct r8192_priv *priv, u32 *TotalRxBcnNum,
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003466 u32 *TotalRxDataNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003467{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003468 u16 SlotIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003469 u8 i;
3470
3471 *TotalRxBcnNum = 0;
3472 *TotalRxDataNum = 0;
3473
3474 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
3475 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
3476 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003477 for (i = 0; i < priv->ieee80211->LinkDetectInfo.SlotNum; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003478 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
3479 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
3480 }
3481}
3482
3483
Himangi Saraogid16e05f2014-03-09 04:21:41 +05303484void rtl819x_watchdog_wqcallback(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003485{
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003486 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003487 struct r8192_priv *priv = container_of(dwork, struct r8192_priv, watch_dog_wq);
3488 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003489 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003490 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003491 static u8 check_reset_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003492 bool bBusyTraffic = false;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003493 u32 TotalRxBcnNum = 0;
3494 u32 TotalRxDataNum = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003495
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003496 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003497 return;
3498 hal_dm_watchdog(dev);
3499
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003500 //to get busy traffic condition
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003501 if (ieee->state == IEEE80211_LINKED) {
3502 if (ieee->LinkDetectInfo.NumRxOkInPeriod > 666 ||
3503 ieee->LinkDetectInfo.NumTxOkInPeriod > 666 ) {
3504 bBusyTraffic = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003505 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003506 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
3507 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
3508 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
3509 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003510 //added by amy for AP roaming
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003511 if (priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003512
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003513 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
3514 if ((TotalRxBcnNum+TotalRxDataNum) == 0) {
3515#ifdef TODO
3516 if (rfState == eRfOff)
3517 RT_TRACE(COMP_ERR, "========>%s()\n", __func__);
3518#endif
3519 netdev_dbg(dev, "===>%s(): AP is power off, connect another one\n", __func__);
3520 priv->ieee80211->state = IEEE80211_ASSOCIATING;
3521 notify_wx_assoc_event(priv->ieee80211);
3522 RemovePeerTS(priv->ieee80211, priv->ieee80211->current_network.bssid);
3523 priv->ieee80211->link_change(dev);
3524 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003525
Jerry Chuang8fc85982009-11-03 07:17:11 -02003526 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003527 }
3528 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod = 0;
3529 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003530 //check if reset the driver
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003531 if (check_reset_cnt++ >= 3) {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003532 ResetType = rtl819x_ifcheck_resetornot(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003533 check_reset_cnt = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003534 }
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003535 if ((priv->force_reset) || (priv->ResetProgress == RESET_TYPE_NORESET &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003536 (priv->bForcedSilentReset ||
3537 (!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_SILENT)))) { // This is control by OID set in Pomelo
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003538 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 -02003539 rtl819x_ifsilentreset(dev);
3540 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003541 priv->force_reset = false;
3542 priv->bForcedSilentReset = false;
3543 priv->bResetInProgress = false;
3544 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
3545
3546}
3547
3548void watch_dog_timer_callback(unsigned long data)
3549{
3550 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003551 queue_delayed_work(priv->priv_wq, &priv->watch_dog_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003552 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
Jerry Chuang8fc85982009-11-03 07:17:11 -02003553}
3554int _rtl8192_up(struct net_device *dev)
3555{
3556 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003557 int init_status = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003558 priv->up = 1;
3559 priv->ieee80211->ieee_up = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003560 RT_TRACE(COMP_INIT, "Bringing up iface");
3561 init_status = rtl8192_adapter_start(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003562 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003563 RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization failed!\n", __func__);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003564 priv->up = priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003565 return -EAGAIN;
3566 }
3567 RT_TRACE(COMP_INIT, "start adapter finished\n");
3568 rtl8192_rx_enable(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003569 if (priv->ieee80211->state != IEEE80211_LINKED)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003570 ieee80211_softmac_start_protocol(priv->ieee80211);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003571 ieee80211_reset_queue(priv->ieee80211);
3572 watch_dog_timer_callback((unsigned long) dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003573 if (!netif_queue_stopped(dev))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003574 netif_start_queue(dev);
3575 else
3576 netif_wake_queue(dev);
3577
3578 return 0;
3579}
3580
3581
Ana Reyf4c60742014-03-13 12:36:38 +01003582static int rtl8192_open(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003583{
3584 struct r8192_priv *priv = ieee80211_priv(dev);
3585 int ret;
3586 down(&priv->wx_sem);
3587 ret = rtl8192_up(dev);
3588 up(&priv->wx_sem);
3589 return ret;
3590
3591}
3592
3593
3594int rtl8192_up(struct net_device *dev)
3595{
3596 struct r8192_priv *priv = ieee80211_priv(dev);
3597
3598 if (priv->up == 1) return -1;
3599
3600 return _rtl8192_up(dev);
3601}
3602
3603
3604int rtl8192_close(struct net_device *dev)
3605{
3606 struct r8192_priv *priv = ieee80211_priv(dev);
3607 int ret;
3608
3609 down(&priv->wx_sem);
3610
3611 ret = rtl8192_down(dev);
3612
3613 up(&priv->wx_sem);
3614
3615 return ret;
3616
3617}
3618
3619int rtl8192_down(struct net_device *dev)
3620{
3621 struct r8192_priv *priv = ieee80211_priv(dev);
3622 int i;
3623
3624 if (priv->up == 0) return -1;
3625
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003626 priv->up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003627 priv->ieee80211->ieee_up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003628 RT_TRACE(COMP_DOWN, "==========>%s()\n", __func__);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003629 /* FIXME */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003630 if (!netif_queue_stopped(dev))
3631 netif_stop_queue(dev);
3632
3633 rtl8192_rtx_disable(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003634
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003635 /* Tx related queue release */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003636 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003637 skb_queue_purge(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003638 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003639 skb_queue_purge(&priv->ieee80211->skb_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003640
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_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003643
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003644 //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 -02003645 rtl8192_cancel_deferred_work(priv);
3646 deinit_hal_dm(dev);
3647 del_timer_sync(&priv->watch_dog_timer);
3648
3649
3650 ieee80211_softmac_stop_protocol(priv->ieee80211);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003651 memset(&priv->ieee80211->current_network, 0, offsetof(struct ieee80211_network, list));
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003652 RT_TRACE(COMP_DOWN, "<==========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003653
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003654 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003655}
3656
3657
3658void rtl8192_commit(struct net_device *dev)
3659{
3660 struct r8192_priv *priv = ieee80211_priv(dev);
3661 int reset_status = 0;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003662 if (priv->up == 0) return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003663 priv->up = 0;
3664
3665 rtl8192_cancel_deferred_work(priv);
3666 del_timer_sync(&priv->watch_dog_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003667
3668 ieee80211_softmac_stop_protocol(priv->ieee80211);
3669
Jerry Chuang8fc85982009-11-03 07:17:11 -02003670 rtl8192_rtx_disable(dev);
3671 reset_status = _rtl8192_up(dev);
3672
3673}
3674
Jerry Chuang8fc85982009-11-03 07:17:11 -02003675void rtl8192_restart(struct work_struct *work)
3676{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003677 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
3678 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003679
3680 down(&priv->wx_sem);
3681
3682 rtl8192_commit(dev);
3683
3684 up(&priv->wx_sem);
3685}
3686
3687static void r8192_set_multicast(struct net_device *dev)
3688{
3689 struct r8192_priv *priv = ieee80211_priv(dev);
3690 short promisc;
3691
Jerry Chuang8fc85982009-11-03 07:17:11 -02003692 /* FIXME FIXME */
3693
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003694 promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003695
3696 if (promisc != priv->promisc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003697
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003698 priv->promisc = promisc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003699}
3700
3701
Ana Reyf4c60742014-03-13 12:36:38 +01003702static int r8192_set_mac_adr(struct net_device *dev, void *mac)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003703{
3704 struct r8192_priv *priv = ieee80211_priv(dev);
3705 struct sockaddr *addr = mac;
3706
3707 down(&priv->wx_sem);
3708
3709 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
3710
Jerry Chuang8fc85982009-11-03 07:17:11 -02003711 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003712 up(&priv->wx_sem);
3713
3714 return 0;
3715}
3716
3717/* based on ipw2200 driver */
Ana Reyf4c60742014-03-13 12:36:38 +01003718static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003719{
3720 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3721 struct iwreq *wrq = (struct iwreq *)rq;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003722 int ret = -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003723 struct ieee80211_device *ieee = priv->ieee80211;
3724 u32 key[4];
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003725 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003726 struct iw_point *p = &wrq->u.data;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03003727 struct ieee_param *ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003728
3729 down(&priv->wx_sem);
3730
3731
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003732 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
3733 ret = -EINVAL;
3734 goto out;
3735 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003736
Teodora Baluta38272d22013-10-25 11:27:09 +03003737 ipw = memdup_user(p->pointer, p->length);
3738 if (IS_ERR(ipw)) {
3739 ret = PTR_ERR(ipw);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003740 goto out;
3741 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003742
3743 switch (cmd) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003744 case RTL_IOCTL_WPA_SUPPLICANT:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003745 //parse here for HW security
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003746 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) {
3747 if (ipw->u.crypt.set_tx) {
3748 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003749 ieee->pairwise_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003750 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003751 ieee->pairwise_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003752 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003753 if (ipw->u.crypt.key_len == 13)
3754 ieee->pairwise_key_type = KEY_TYPE_WEP104;
3755 else if (ipw->u.crypt.key_len == 5)
3756 ieee->pairwise_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003757 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003758 ieee->pairwise_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003759 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003760
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003761 if (ieee->pairwise_key_type) {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003762 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003763 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003764 //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!
3765 //added by WB.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003766 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 +01003767 if (ieee->auth_mode != 2)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003768 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 -02003769 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003770 } else {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003771 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003772 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003773 ieee->group_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003774 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003775 ieee->group_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003776 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003777 if (ipw->u.crypt.key_len == 13)
3778 ieee->group_key_type = KEY_TYPE_WEP104;
3779 else if (ipw->u.crypt.key_len == 5)
3780 ieee->group_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003781 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003782 ieee->group_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003783 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003784
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003785 if (ieee->group_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003786 setKey(dev, ipw->u.crypt.idx,
3787 ipw->u.crypt.idx, //KeyIndex
3788 ieee->group_key_type, //KeyType
3789 broadcast_addr, //MacAddr
3790 0, //DefaultKey
3791 key); //KeyContent
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003792 }
3793 }
3794 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003795 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
3796 break;
3797
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003798 default:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003799 ret = -EOPNOTSUPP;
3800 break;
3801 }
3802 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003803 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003804out:
3805 up(&priv->wx_sem);
3806 return ret;
3807}
3808
Ana Reyf4c60742014-03-13 12:36:38 +01003809static u8 HwRateToMRate90(bool bIsHT, u8 rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003810{
3811 u8 ret_rate = 0xff;
3812
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003813 if (!bIsHT) {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003814 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003815 case DESC90_RATE1M: ret_rate = MGN_1M; break;
3816 case DESC90_RATE2M: ret_rate = MGN_2M; break;
3817 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
3818 case DESC90_RATE11M: ret_rate = MGN_11M; break;
3819 case DESC90_RATE6M: ret_rate = MGN_6M; break;
3820 case DESC90_RATE9M: ret_rate = MGN_9M; break;
3821 case DESC90_RATE12M: ret_rate = MGN_12M; break;
3822 case DESC90_RATE18M: ret_rate = MGN_18M; break;
3823 case DESC90_RATE24M: ret_rate = MGN_24M; break;
3824 case DESC90_RATE36M: ret_rate = MGN_36M; break;
3825 case DESC90_RATE48M: ret_rate = MGN_48M; break;
3826 case DESC90_RATE54M: ret_rate = MGN_54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003827
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003828 default:
3829 ret_rate = 0xff;
3830 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
3831 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003832 }
3833
3834 } else {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003835 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003836 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
3837 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
3838 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
3839 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
3840 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
3841 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
3842 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
3843 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
3844 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
3845 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
3846 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
3847 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
3848 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
3849 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
3850 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
3851 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
3852 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003853
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003854 default:
3855 ret_rate = 0xff;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003856 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003857 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003858 }
3859 }
3860
3861 return ret_rate;
3862}
3863
3864/**
3865 * Function: UpdateRxPktTimeStamp
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003866 * Overview: Record the TSF time stamp when receiving a packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02003867 *
3868 * Input:
3869 * PADAPTER Adapter
3870 * PRT_RFD pRfd,
3871 *
3872 * Output:
3873 * PRT_RFD pRfd
3874 * (pRfd->Status.TimeStampHigh is updated)
3875 * (pRfd->Status.TimeStampLow is updated)
3876 * Return:
3877 * None
3878 */
Teodora Baluta46326d22013-10-16 01:59:17 +03003879static void UpdateRxPktTimeStamp8190(struct net_device *dev,
3880 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003881{
3882 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3883
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003884 if (stats->bIsAMPDU && !stats->bFirstMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003885 stats->mac_time[0] = priv->LastRxDescTSFLow;
3886 stats->mac_time[1] = priv->LastRxDescTSFHigh;
3887 } else {
3888 priv->LastRxDescTSFLow = stats->mac_time[0];
3889 priv->LastRxDescTSFHigh = stats->mac_time[1];
3890 }
3891}
3892
3893//by amy 080606
3894
Ana Reyf4c60742014-03-13 12:36:38 +01003895static long rtl819x_translate_todbm(u8 signal_strength_index)// 0-100 index.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003896{
3897 long signal_power; // in dBm.
3898
3899 // Translate to dBm (x=0.5y-95).
3900 signal_power = (long)((signal_strength_index + 1) >> 1);
3901 signal_power -= 95;
3902
3903 return signal_power;
3904}
3905
3906
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003907/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
Jerry Chuang8fc85982009-11-03 07:17:11 -02003908 be a local static. Otherwise, it may increase when we return from S3/S4. The
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003909 value will be kept in memory or disk. Declare the value in the adaptor
3910 and it will be reinitialized when returned from S3/S4. */
Ana Reyf4c60742014-03-13 12:36:38 +01003911static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
3912 struct ieee80211_rx_stats *pprevious_stats,
3913 struct ieee80211_rx_stats *pcurrent_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003914{
3915 bool bcheck = false;
3916 u8 rfpath;
3917 u32 nspatial_stream, tmp_val;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003918 static u32 slide_rssi_index, slide_rssi_statistics;
3919 static u32 slide_evm_index, slide_evm_statistics;
3920 static u32 last_rssi, last_evm;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003921
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003922 static u32 slide_beacon_adc_pwdb_index, slide_beacon_adc_pwdb_statistics;
3923 static u32 last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003924
3925 struct ieee80211_hdr_3addr *hdr;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003926 u16 sc;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003927 unsigned int frag, seq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003928 hdr = (struct ieee80211_hdr_3addr *)buffer;
3929 sc = le16_to_cpu(hdr->seq_ctl);
3930 frag = WLAN_GET_SEQ_FRAG(sc);
3931 seq = WLAN_GET_SEQ_SEQ(sc);
3932 //cosa add 04292008 to record the sequence number
3933 pcurrent_stats->Seq_Num = seq;
3934 //
3935 // Check whether we should take the previous packet into accounting
3936 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003937 if (!pprevious_stats->bIsAMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003938 // if previous packet is not aggregated packet
3939 bcheck = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003940 }
3941
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003942 if (slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003943 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
3944 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
3945 priv->stats.slide_rssi_total -= last_rssi;
3946 }
3947 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
3948
3949 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003950 if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003951 slide_rssi_index = 0;
3952
3953 // <1> Showed on UI for user, in dbm
3954 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
3955 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
3956 pcurrent_stats->rssi = priv->stats.signal_strength;
3957 //
3958 // If the previous packet does not match the criteria, neglect it
3959 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003960 if (!pprevious_stats->bPacketMatchBSSID) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003961 if (!pprevious_stats->bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003962 return;
3963 }
3964
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003965 if (!bcheck)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003966 return;
3967
3968
3969 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
3970
3971 //
3972 // Check RSSI
3973 //
3974 priv->stats.num_process_phyinfo++;
3975
3976 /* record the general signal strength to the sliding window. */
3977
3978
3979 // <2> Showed on UI for engineering
3980 // hardware does not provide rssi information for each rf path in CCK
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003981 if (!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA)) {
3982 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003983 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
3984 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003985
3986 //Fixed by Jacken 2008-03-20
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003987 if (priv->stats.rx_rssi_percentage[rfpath] == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003988 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003989 if (pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath]) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003990 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003991 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003992 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003993 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003994 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003995 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003996 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003997 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003998 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003999 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 -02004000 }
4001 }
4002
4003
4004 //
4005 // Check PWDB.
4006 //
4007 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004008 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004009 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004010
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004011 if (pprevious_stats->bPacketBeacon) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004012 /* record the beacon pwdb to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004013 if (slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004014 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
4015 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
4016 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004017 }
4018 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
4019 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004020 slide_beacon_adc_pwdb_index++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004021 if (slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004022 slide_beacon_adc_pwdb_index = 0;
4023 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004024 if (pprevious_stats->RxPWDBAll >= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004025 pprevious_stats->RxPWDBAll -= 3;
4026 }
4027
4028 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004029 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004030 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004031
4032
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004033 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004034 if (priv->undecorated_smoothed_pwdb < 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004035 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004036 if (pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004037 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004038 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4039 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004040 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004041 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004042 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004043 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4044 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004045 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004046
4047 }
4048
4049 //
4050 // Check EVM
4051 //
4052 /* record the general EVM to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004053 if (pprevious_stats->SignalQuality) {
4054 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4055 if (slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004056 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
4057 last_evm = priv->stats.slide_evm[slide_evm_index];
4058 priv->stats.slide_evm_total -= last_evm;
4059 }
4060
4061 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
4062
4063 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004064 if (slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004065 slide_evm_index = 0;
4066
4067 // <1> Showed on UI for user, in percentage.
4068 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
4069 priv->stats.signal_quality = tmp_val;
4070 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
4071 priv->stats.last_signal_strength_inpercent = tmp_val;
4072 }
4073
4074 // <2> Showed on UI for engineering
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004075 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4076 for (nspatial_stream = 0; nspatial_stream < 2; nspatial_stream++) { // 2 spatial stream
4077 if (pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004078 if (priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004079 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
Jerry Chuang8fc85982009-11-03 07:17:11 -02004080 priv->stats.rx_evm_percentage[nspatial_stream] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004081 ((priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004082 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004083 }
4084 }
4085 }
4086 }
4087
4088
4089}
4090
4091/*-----------------------------------------------------------------------------
4092 * Function: rtl819x_query_rxpwrpercentage()
4093 *
4094 * Overview:
4095 *
4096 * Input: char antpower
4097 *
4098 * Output: NONE
4099 *
4100 * Return: 0-100 percentage
4101 *
4102 * Revised History:
4103 * When Who Remark
4104 * 05/26/2008 amy Create Version 0 porting from windows code.
4105 *
4106 *---------------------------------------------------------------------------*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004107static u8 rtl819x_query_rxpwrpercentage(char antpower)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004108{
4109 if ((antpower <= -100) || (antpower >= 20))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004110 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004111 else if (antpower >= 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004112 return 100;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004113 else
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004114 return 100 + antpower;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004115
4116} /* QueryRxPwrPercentage */
4117
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004118static u8 rtl819x_evm_dbtopercentage(char value)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004119{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004120 char ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004121
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004122 ret_val = value;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004123
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004124 if (ret_val >= 0)
4125 ret_val = 0;
4126 if (ret_val <= -33)
4127 ret_val = -33;
4128 ret_val = 0 - ret_val;
4129 ret_val *= 3;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004130 if (ret_val == 99)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004131 ret_val = 100;
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004132 return ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004133}
4134//
4135// Description:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004136// We want good-looking for signal strength/quality
Jerry Chuang8fc85982009-11-03 07:17:11 -02004137// 2007/7/19 01:09, by cosa.
4138//
Teodora Baluta46326d22013-10-16 01:59:17 +03004139static long rtl819x_signal_scale_mapping(long currsig)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004140{
4141 long retsig;
4142
4143 // Step 1. Scale mapping.
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004144 if (currsig >= 61 && currsig <= 100)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004145 retsig = 90 + ((currsig - 60) / 4);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004146 else if (currsig >= 41 && currsig <= 60)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004147 retsig = 78 + ((currsig - 40) / 2);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004148 else if (currsig >= 31 && currsig <= 40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004149 retsig = 66 + (currsig - 30);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004150 else if (currsig >= 21 && currsig <= 30)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004151 retsig = 54 + (currsig - 20);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004152 else if (currsig >= 5 && currsig <= 20)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004153 retsig = 42 + (((currsig - 5) * 2) / 3);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004154 else if (currsig == 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004155 retsig = 36;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004156 else if (currsig == 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004157 retsig = 27;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004158 else if (currsig == 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004159 retsig = 18;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004160 else if (currsig == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004161 retsig = 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004162 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004163 retsig = currsig;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004164
4165 return retsig;
4166}
4167
Xenia Ragiadakouf2c3d802013-06-04 23:32:32 +03004168static inline bool rx_hal_is_cck_rate(struct rx_drvinfo_819x_usb *pdrvinfo)
4169{
4170 if (pdrvinfo->RxHT)
4171 return false;
4172
4173 switch (pdrvinfo->RxRate) {
4174 case DESC90_RATE1M:
4175 case DESC90_RATE2M:
4176 case DESC90_RATE5_5M:
4177 case DESC90_RATE11M:
4178 return true;
4179 default:
4180 return false;
4181 }
4182}
4183
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004184static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
4185 struct ieee80211_rx_stats *pstats,
4186 rx_drvinfo_819x_usb *pdrvinfo,
4187 struct ieee80211_rx_stats *precord_stats,
4188 bool bpacket_match_bssid,
4189 bool bpacket_toself,
4190 bool bPacketBeacon,
4191 bool bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004192{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004193 phy_sts_ofdm_819xusb_t *pofdm_buf;
4194 phy_sts_cck_819xusb_t *pcck_buf;
4195 phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004196 u8 *prxpkt;
4197 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004198 char rx_pwr[4], rx_pwr_all = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004199 char rx_snrX, rx_evmX;
4200 u8 evm, pwdb_all;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004201 u32 RSSI, total_rssi = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004202 u8 is_cck_rate = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004203 u8 rf_rx_num = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004204 u8 sq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004205
4206
4207 priv->stats.numqry_phystatus++;
4208
4209 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4210
4211 // Record it for next packet processing
4212 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4213 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4214 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004215 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004216 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4217 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4218
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004219 prxpkt = (u8 *)pdrvinfo;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004220
4221 /* Move pointer to the 16th bytes. Phy status start address. */
4222 prxpkt += sizeof(rx_drvinfo_819x_usb);
4223
4224 /* Initial the cck and ofdm buffer pointer */
4225 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
4226 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
4227
4228 pstats->RxMIMOSignalQuality[0] = -1;
4229 pstats->RxMIMOSignalQuality[1] = -1;
4230 precord_stats->RxMIMOSignalQuality[0] = -1;
4231 precord_stats->RxMIMOSignalQuality[1] = -1;
4232
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004233 if (is_cck_rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004234 //
4235 // (1)Hardware does not provide RSSI for CCK
4236 //
4237
4238 //
4239 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4240 //
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004241 u8 report;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004242
4243 priv->stats.numqry_phystatusCCK++;
4244
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004245 if (!priv->bCckHighPower) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004246 report = pcck_buf->cck_agc_rpt & 0xc0;
4247 report = report>>6;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004248 switch (report) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004249 //Fixed by Jacken from Bryant 2008-03-20
4250 //Original value is -38 , -26 , -14 , -2
4251 //Fixed value is -35 , -23 , -11 , 6
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004252 case 0x3:
4253 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4254 break;
4255 case 0x2:
4256 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4257 break;
4258 case 0x1:
4259 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4260 break;
4261 case 0x0:
4262 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
4263 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004264 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004265 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004266 report = pcck_buf->cck_agc_rpt & 0x60;
4267 report = report>>5;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004268 switch (report) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004269 case 0x3:
4270 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4271 break;
4272 case 0x2:
4273 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4274 break;
4275 case 0x1:
4276 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4277 break;
4278 case 0x0:
4279 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4280 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004281 }
4282 }
4283
4284 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4285 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4286 pstats->RecvSignalPower = pwdb_all;
4287
4288 //
4289 // (3) Get Signal Quality (EVM)
4290 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02004291
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004292 if (pstats->RxPWDBAll > 40) {
4293 sq = 100;
4294 } else {
4295 sq = pcck_buf->sq_rpt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004296
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004297 if (pcck_buf->sq_rpt > 64)
4298 sq = 0;
4299 else if (pcck_buf->sq_rpt < 20)
4300 sq = 100;
4301 else
4302 sq = ((64-sq) * 100) / 44;
4303 }
4304 pstats->SignalQuality = precord_stats->SignalQuality = sq;
4305 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
4306 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004307
4308 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004309 priv->stats.numqry_phystatusHT++;
4310 //
4311 // (1)Get RSSI for HT rate
4312 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004313 for (i = RF90_PATH_A; i < priv->NumTotalRFPath; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004314 // 2008/01/30 MH we will judge RF RX path now.
4315 if (priv->brfpath_rxenable[i])
4316 rf_rx_num++;
4317 else
4318 continue;
4319
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004320 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004321 continue;
4322
4323 //Fixed by Jacken from Bryant 2008-03-20
4324 //Original value is 106
4325 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
4326
4327 //Get Rx snr value in DB
4328 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
4329 rx_snrX = (char)(tmp_rxsnr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004330 rx_snrX /= 2;
4331 priv->stats.rxSNRdB[i] = (long)rx_snrX;
4332
4333 /* Translate DBM to percentage. */
4334 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
4335 total_rssi += RSSI;
4336
4337 /* Record Signal Strength for next packet */
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004338 pstats->RxMIMOSignalStrength[i] = (u8) RSSI;
4339 precord_stats->RxMIMOSignalStrength[i] = (u8) RSSI;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004340 }
4341
4342
4343 //
4344 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4345 //
4346 //Fixed by Jacken from Bryant 2008-03-20
4347 //Original value is 106
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004348 rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1)& 0x7f) -106;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004349 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4350
4351 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4352 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
4353
4354 //
4355 // (3)EVM of HT rate
4356 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004357 if (pdrvinfo->RxHT && pdrvinfo->RxRate >= DESC90_RATEMCS8 &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004358 pdrvinfo->RxRate <= DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004359 max_spatial_stream = 2; //both spatial stream make sense
4360 else
4361 max_spatial_stream = 1; //only spatial stream 1 makes sense
4362
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004363 for (i = 0; i < max_spatial_stream; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004364 tmp_rxevm = pofdm_buf->rxevm_X[i];
4365 rx_evmX = (char)(tmp_rxevm);
4366
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004367 // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004368 // will set the most significant bit to "zero" when doing shifting operation which may change a negative
Jerry Chuang8fc85982009-11-03 07:17:11 -02004369 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
4370 rx_evmX /= 2; //dbm
4371
4372 evm = rtl819x_evm_dbtopercentage(rx_evmX);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004373 if (i == 0) // Fill value in RFD, Get the first spatial stream only
4374 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
4375 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004376 }
4377
4378
4379 /* record rx statistics for debug */
4380 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
4381 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004382 if (pdrvinfo->BW) //40M channel
Jerry Chuang8fc85982009-11-03 07:17:11 -02004383 priv->stats.received_bwtype[1+prxsc->rxsc]++;
4384 else //20M channel
4385 priv->stats.received_bwtype[0]++;
4386 }
4387
4388 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
4389 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004390 if (is_cck_rate) {
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004391 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004392 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004393 // We can judge RX path number now.
4394 if (rf_rx_num != 0)
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004395 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi /= rf_rx_num)));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004396 }
4397} /* QueryRxPhyStatus8190Pci */
4398
Ana Reyf4c60742014-03-13 12:36:38 +01004399static void rtl8192_record_rxdesc_forlateruse(struct ieee80211_rx_stats *psrc_stats,
4400 struct ieee80211_rx_stats *ptarget_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004401{
4402 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
4403 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
4404 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
4405}
4406
4407
Teodora Baluta46326d22013-10-16 01:59:17 +03004408static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
4409 struct ieee80211_rx_stats *pstats,
4410 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004411{
4412 // TODO: We must only check packet for current MAC address. Not finish
4413 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004414 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004415 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4416 bool bpacket_match_bssid, bpacket_toself;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004417 bool bPacketBeacon = FALSE, bToSelfBA = FALSE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004418 static struct ieee80211_rx_stats previous_stats;
4419 struct ieee80211_hdr_3addr *hdr;//by amy
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004420 u16 fc, type;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004421
4422 // Get Signal Quality for only RX data queue (but not command queue)
4423
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004424 u8 *tmp_buf;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004425 u8 *praddr;
4426
4427 /* Get MAC frame start address. */
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004428 tmp_buf = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004429
4430 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
4431 fc = le16_to_cpu(hdr->frame_ctl);
4432 type = WLAN_FC_GET_TYPE(fc);
4433 praddr = hdr->addr1;
4434
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004435 /* Check if the received packet is acceptable. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004436 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004437 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
4438 && (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004439 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
4440
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004441 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON)
4442 bPacketBeacon = true;
4443 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK) {
4444 if ((eqMacAddr(praddr, dev->dev_addr)))
4445 bToSelfBA = true;
4446 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004447
Jerry Chuang8fc85982009-11-03 07:17:11 -02004448
4449
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004450 if (bpacket_match_bssid)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004451 priv->stats.numpacket_matchbssid++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004452 if (bpacket_toself)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004453 priv->stats.numpacket_toself++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004454 //
4455 // Process PHY information for previous packet (RSSI/PWDB/EVM)
4456 //
4457 // Because phy information is contained in the last packet of AMPDU only, so driver
4458 // should process phy information of previous packet
4459 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004460 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid, bpacket_toself, bPacketBeacon, bToSelfBA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004461 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
4462
4463}
4464
4465/**
4466* Function: UpdateReceivedRateHistogramStatistics
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004467* Overview: Record the received data rate
Jerry Chuang8fc85982009-11-03 07:17:11 -02004468*
4469* Input:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004470* struct net_device *dev
Jerry Chuang8fc85982009-11-03 07:17:11 -02004471* struct ieee80211_rx_stats *stats
4472*
4473* Output:
4474*
4475* (priv->stats.ReceivedRateHistogram[] is updated)
4476* Return:
4477* None
4478*/
Teodora Baluta46326d22013-10-16 01:59:17 +03004479static void
4480UpdateReceivedRateHistogramStatistics8190(struct net_device *dev,
4481 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004482{
4483 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004484 u32 rcvType = 1; //0: Total, 1:OK, 2:CRC, 3:ICV
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004485 u32 rateIndex;
4486 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02004487
4488
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004489 if (stats->bCRC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004490 rcvType = 2;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004491 else if (stats->bICV)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004492 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004493
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004494 if (stats->bShortPreamble)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004495 preamble_guardinterval = 1;// short
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004496 else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004497 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02004498
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004499 switch (stats->rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004500 //
4501 // CCK rate
4502 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004503 case MGN_1M: rateIndex = 0; break;
4504 case MGN_2M: rateIndex = 1; break;
4505 case MGN_5_5M: rateIndex = 2; break;
4506 case MGN_11M: rateIndex = 3; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004507 //
4508 // Legacy OFDM rate
4509 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004510 case MGN_6M: rateIndex = 4; break;
4511 case MGN_9M: rateIndex = 5; break;
4512 case MGN_12M: rateIndex = 6; break;
4513 case MGN_18M: rateIndex = 7; break;
4514 case MGN_24M: rateIndex = 8; break;
4515 case MGN_36M: rateIndex = 9; break;
4516 case MGN_48M: rateIndex = 10; break;
4517 case MGN_54M: rateIndex = 11; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004518 //
4519 // 11n High throughput rate
4520 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004521 case MGN_MCS0: rateIndex = 12; break;
4522 case MGN_MCS1: rateIndex = 13; break;
4523 case MGN_MCS2: rateIndex = 14; break;
4524 case MGN_MCS3: rateIndex = 15; break;
4525 case MGN_MCS4: rateIndex = 16; break;
4526 case MGN_MCS5: rateIndex = 17; break;
4527 case MGN_MCS6: rateIndex = 18; break;
4528 case MGN_MCS7: rateIndex = 19; break;
4529 case MGN_MCS8: rateIndex = 20; break;
4530 case MGN_MCS9: rateIndex = 21; break;
4531 case MGN_MCS10: rateIndex = 22; break;
4532 case MGN_MCS11: rateIndex = 23; break;
4533 case MGN_MCS12: rateIndex = 24; break;
4534 case MGN_MCS13: rateIndex = 25; break;
4535 case MGN_MCS14: rateIndex = 26; break;
4536 case MGN_MCS15: rateIndex = 27; break;
4537 default: rateIndex = 28; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004538 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004539 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
4540 priv->stats.received_rate_histogram[0][rateIndex]++; //total
4541 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004542}
4543
4544
Teodora Baluta46326d22013-10-16 01:59:17 +03004545static void query_rxdesc_status(struct sk_buff *skb,
4546 struct ieee80211_rx_stats *stats,
4547 bool bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004548{
4549 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004550 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004551 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004552 rx_drvinfo_819x_usb *driver_info = NULL;
4553
4554 //
4555 //Get Rx Descriptor Information
4556 //
4557#ifdef USB_RX_AGGREGATION_SUPPORT
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004558 if (bIsRxAggrSubframe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004559 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004560 stats->Length = desc->Length;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004561 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
4562 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
4563 stats->bICV = desc->ICV;
4564 stats->bCRC = desc->CRC32;
4565 stats->bHwError = stats->bCRC|stats->bICV;
4566 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
4567 } else
4568#endif
4569 {
4570 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
4571
4572 stats->Length = desc->Length;
4573 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004574 stats->RxBufShift = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004575 stats->bICV = desc->ICV;
4576 stats->bCRC = desc->CRC32;
4577 stats->bHwError = stats->bCRC|stats->bICV;
4578 //RTL8190 set this bit to indicate that Hw does not decrypt packet
4579 stats->Decrypted = !desc->SWDec;
4580 }
4581
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004582 if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004583 stats->bHwError = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004584 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004585 stats->bHwError = stats->bCRC|stats->bICV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004586
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004587 if (stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004588 stats->bHwError |= 1;
4589 //
4590 //Get Driver Info
4591 //
4592 // TODO: Need to verify it on FGPA platform
4593 //Driver info are written to the RxBuffer following rx desc
4594 if (stats->RxDrvInfoSize != 0) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004595 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004596 stats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004597 /* unit: 0.5M */
4598 /* TODO */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004599 if (!stats->bHwError) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004600 u8 ret_rate;
4601 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004602 if (ret_rate == 0xff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004603 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
4604 // Special Error Handling here, 2008.05.16, by Emily
4605
4606 stats->bHwError = 1;
4607 stats->rate = MGN_1M; //Set 1M rate by default
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004608 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004609 stats->rate = ret_rate;
4610 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004611 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004612 stats->rate = 0x02;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004613 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004614
4615 stats->bShortPreamble = driver_info->SPLCP;
4616
4617
4618 UpdateReceivedRateHistogramStatistics8190(dev, stats);
4619
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004620 stats->bIsAMPDU = (driver_info->PartAggr == 1);
4621 stats->bFirstMPDU = (driver_info->PartAggr == 1) && (driver_info->FirstAGGR == 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004622 stats->TimeStampLow = driver_info->TSFL;
4623 // xiong mask it, 070514
Jerry Chuang8fc85982009-11-03 07:17:11 -02004624
4625 UpdateRxPktTimeStamp8190(dev, stats);
4626
4627 //
4628 // Rx A-MPDU
4629 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004630 if (driver_info->FirstAGGR == 1 || driver_info->PartAggr == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004631 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004632 driver_info->FirstAGGR, driver_info->PartAggr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004633
4634 }
4635
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004636 skb_pull(skb, sizeof(rx_desc_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004637 //
4638 // Get Total offset of MPDU Frame Body
4639 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004640 if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004641 stats->bShift = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004642 skb_pull(skb, stats->RxBufShift + stats->RxDrvInfoSize);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004643 }
4644
4645#ifdef USB_RX_AGGREGATION_SUPPORT
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004646 /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004647 if (bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004648 skb_pull(skb, 8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004649#endif
4650 /* for debug 2008.5.29 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004651
4652 //added by vivi, for MP, 20080108
4653 stats->RxIs40MHzPacket = driver_info->BW;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004654 if (stats->RxDrvInfoSize != 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004655 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
4656
4657}
4658
4659u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
4660{
4661#ifdef USB_RX_AGGREGATION_SUPPORT
4662 if (bIsRxAggrSubframe)
4663 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
4664 + Status->RxBufShift + 8);
4665 else
4666#endif
4667 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004668 + Status->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004669}
4670
Ana Reyf4c60742014-03-13 12:36:38 +01004671static void rtl8192_rx_nomal(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004672{
4673 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004674 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004675 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4676 struct ieee80211_rx_stats stats = {
4677 .signal = 0,
4678 .noise = -98,
4679 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004680 .freq = IEEE80211_24GHZ_BAND,
4681 };
4682 u32 rx_pkt_len = 0;
4683 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
4684 bool unicast_packet = false;
4685#ifdef USB_RX_AGGREGATION_SUPPORT
4686 struct sk_buff *agg_skb = NULL;
4687 u32 TotalLength = 0;
4688 u32 TempDWord = 0;
4689 u32 PacketLength = 0;
4690 u32 PacketOccupiedLendth = 0;
4691 u8 TempByte = 0;
4692 u32 PacketShiftBytes = 0;
4693 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
4694 u8 PaddingBytes = 0;
4695 //add just for testing
4696 u8 testing;
4697
4698#endif
4699
4700 /* 20 is for ps-poll */
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004701 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004702#ifdef USB_RX_AGGREGATION_SUPPORT
4703 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
4704#endif
4705 /* first packet should not contain Rx aggregation header */
4706 query_rxdesc_status(skb, &stats, false);
4707 /* TODO */
4708 /* hardware related info */
4709#ifdef USB_RX_AGGREGATION_SUPPORT
4710 if (TempByte & BIT0) {
4711 agg_skb = skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004712 TotalLength = stats.Length - 4; /*sCrcLng*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02004713 /* though the head pointer has passed this position */
4714 TempDWord = *(u32 *)(agg_skb->data - 4);
4715 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
4716 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004717 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004718 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
4719 }
4720#endif
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004721 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004722 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4723
4724 rx_pkt_len = skb->len;
4725 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4726 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004727 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004728 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004729 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004730 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004731 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004732 /* unicast packet */
4733 unicast_packet = true;
4734 }
4735
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004736 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004737 dev_kfree_skb_any(skb);
4738 } else {
4739 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004740 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004741 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004742 }
4743#ifdef USB_RX_AGGREGATION_SUPPORT
4744 testing = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004745 if (TotalLength > 0) {
4746 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
4747 if ((PacketOccupiedLendth & 0xFF) != 0)
4748 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
4749 PacketOccupiedLendth -= 8;
4750 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
4751 if (agg_skb->len > TempDWord)
4752 skb_pull(agg_skb, TempDWord);
4753 else
4754 agg_skb->len = 0;
4755
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004756 while (agg_skb->len >= GetRxPacketShiftBytes819xUsb(&stats, true)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004757 u8 tmpCRC = 0, tmpICV = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004758 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
4759 tmpCRC = RxDescr->CRC32;
4760 tmpICV = RxDescr->ICV;
4761 memcpy(agg_skb->data, &agg_skb->data[44], 2);
4762 RxDescr->CRC32 = tmpCRC;
4763 RxDescr->ICV = tmpICV;
4764
4765 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
4766 stats.signal = 0;
4767 stats.noise = -98;
4768 stats.rate = 0;
4769 stats.freq = IEEE80211_24GHZ_BAND;
4770 query_rxdesc_status(agg_skb, &stats, true);
4771 PacketLength = stats.Length;
4772
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004773 if (PacketLength > agg_skb->len)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004774 break;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004775 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004776 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004777 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004778 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4779
4780 rx_pkt_len = skb->len;
4781 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4782 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004783 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004784 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004785 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004786 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004787 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004788 /* unicast packet */
4789 unicast_packet = true;
4790 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004791 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004792 dev_kfree_skb_any(skb);
4793 } else {
4794 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004795 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004796 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004797 }
4798 /* should trim the packet which has been copied to target skb */
4799 skb_pull(agg_skb, PacketLength);
4800 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
4801 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
4802 if ((PacketOccupiedLendth & 0xFF) != 0) {
4803 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
4804 if (agg_skb->len > PaddingBytes)
4805 skb_pull(agg_skb, PaddingBytes);
4806 else
4807 agg_skb->len = 0;
4808 }
4809 }
4810 dev_kfree_skb(agg_skb);
4811 }
4812#endif
4813 } else {
4814 priv->stats.rxurberr++;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03004815 netdev_dbg(dev, "actual_length: %d\n", skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004816 dev_kfree_skb_any(skb);
4817 }
4818
4819}
4820
Ana Reyf4c60742014-03-13 12:36:38 +01004821static void rtl819xusb_process_received_packet(struct net_device *dev,
4822 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004823{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004824 u8 *frame;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004825 u16 frame_len = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004826 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004827
4828 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
4829 //porting by amy 080508
4830 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
4831 frame = pstats->virtual_address;
4832 frame_len = pstats->packetlength;
4833#ifdef TODO // by amy about HCT
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004834 if (!Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004835 CountRxErrStatistics(Adapter, pRfd);
4836#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004837#ifdef ENABLE_PS //by amy for adding ps function in future
4838 RT_RF_POWER_STATE rtState;
4839 // When RF is off, we should not count the packet for hw/sw synchronize
4840 // reason, ie. there may be a duration while sw switch is changed and hw
4841 // switch is being changed. 2006.12.04, by shien chang.
4842 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8 *)(&rtState));
4843 if (rtState == eRfOff)
4844 return;
4845#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -02004846 priv->stats.rxframgment++;
4847
Jerry Chuang8fc85982009-11-03 07:17:11 -02004848#ifdef TODO
4849 RmMonitorSignalStrength(Adapter, pRfd);
4850#endif
4851 /* 2007/01/16 MH Add RX command packet handle here. */
4852 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
4853 if (rtl819xusb_rx_command_packet(dev, pstats))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004854 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004855
4856#ifdef SW_CRC_CHECK
4857 SwCrcCheck();
4858#endif
4859
4860
4861}
4862
Teodora Baluta46326d22013-10-16 01:59:17 +03004863static void query_rx_cmdpkt_desc_status(struct sk_buff *skb,
4864 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004865{
Jerry Chuang8fc85982009-11-03 07:17:11 -02004866 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004867
4868 //
4869 //Get Rx Descriptor Information
4870 //
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004871 stats->virtual_address = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004872 stats->Length = desc->Length;
4873 stats->RxDrvInfoSize = 0;
4874 stats->RxBufShift = 0;
4875 stats->packetlength = stats->Length-scrclng;
4876 stats->fraglength = stats->packetlength;
4877 stats->fragoffset = 0;
4878 stats->ntotalfrag = 1;
4879}
4880
4881
Ana Reyf4c60742014-03-13 12:36:38 +01004882static void rtl8192_rx_cmd(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004883{
4884 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
4885 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004886 /* TODO */
4887 struct ieee80211_rx_stats stats = {
4888 .signal = 0,
4889 .noise = -98,
4890 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004891 .freq = IEEE80211_24GHZ_BAND,
4892 };
4893
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004894 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004895
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004896 query_rx_cmdpkt_desc_status(skb, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004897 // this is to be done by amy 080508 prfd->queue_id = 1;
4898
4899
4900 //
4901 // Process the command packet received.
4902 //
4903
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004904 rtl819xusb_process_received_packet(dev, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004905
4906 dev_kfree_skb_any(skb);
4907 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004908}
4909
4910void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
4911{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004912 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004913 struct rtl8192_rx_info *info;
4914
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004915 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004916 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004917 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004918 /* Nomal packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004919 case 3:
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004920 priv->IrpPendingCount--;
4921 rtl8192_rx_nomal(skb);
4922 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004923
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004924 /* Command packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004925 case 9:
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004926 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004927 info->out_pipe);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004928
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004929 rtl8192_rx_cmd(skb);
4930 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004931
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004932 default: /* should never get here! */
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004933 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004934 info->out_pipe);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004935 dev_kfree_skb(skb);
4936 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004937
4938 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004939 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004940}
4941
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02004942static const struct net_device_ops rtl8192_netdev_ops = {
4943 .ndo_open = rtl8192_open,
4944 .ndo_stop = rtl8192_close,
4945 .ndo_get_stats = rtl8192_stats,
4946 .ndo_tx_timeout = tx_timeout,
4947 .ndo_do_ioctl = rtl8192_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00004948 .ndo_set_rx_mode = r8192_set_multicast,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02004949 .ndo_set_mac_address = r8192_set_mac_adr,
4950 .ndo_validate_addr = eth_validate_addr,
4951 .ndo_change_mtu = eth_change_mtu,
4952 .ndo_start_xmit = ieee80211_xmit,
4953};
Jerry Chuang8fc85982009-11-03 07:17:11 -02004954
4955
4956/****************************************************************************
4957 ---------------------------- USB_STUFF---------------------------
4958*****************************************************************************/
4959
Bill Pemberton25794522012-11-19 13:22:04 -05004960static int rtl8192_usb_probe(struct usb_interface *intf,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004961 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004962{
Jerry Chuang8fc85982009-11-03 07:17:11 -02004963 struct net_device *dev = NULL;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004964 struct r8192_priv *priv = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004965 struct usb_device *udev = interface_to_usbdev(intf);
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04004966 int ret;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004967 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02004968
4969 dev = alloc_ieee80211(sizeof(struct r8192_priv));
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04004970 if (dev == NULL)
4971 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004972
Jerry Chuang8fc85982009-11-03 07:17:11 -02004973 usb_set_intfdata(intf, dev);
4974 SET_NETDEV_DEV(dev, &intf->dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004975 priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004976 priv->ieee80211 = netdev_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004977 priv->udev = udev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004978
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004979 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004980
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004981 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Joel Pelaez Jorgee6c1ef62014-05-23 14:27:43 -05004982
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004983 dev->type = ARPHRD_ETHER;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004984
4985 dev->watchdog_timeo = HZ*3; //modified by john, 0805
4986
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004987 if (dev_alloc_name(dev, ifname) < 0) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004988 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02004989 ifname = "wlan%d";
4990 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004991 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004992
4993 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004994 if (rtl8192_init(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004995 RT_TRACE(COMP_ERR, "Initialization failed");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04004996 ret = -ENODEV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004997 goto fail;
4998 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004999 netif_carrier_off(dev);
5000 netif_stop_queue(dev);
5001
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005002 ret = register_netdev(dev);
5003 if (ret)
5004 goto fail2;
5005
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005006 RT_TRACE(COMP_INIT, "dev name=======> %s\n", dev->name);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005007 rtl8192_proc_init_one(dev);
5008
5009
5010 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005011 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005012
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005013fail2:
5014 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005015 kfree(priv->pFirmware);
5016 priv->pFirmware = NULL;
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005017 rtl8192_usb_deleteendpoints(dev);
5018 destroy_workqueue(priv->priv_wq);
5019 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005020fail:
5021 free_ieee80211(dev);
5022
5023 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005024 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005025}
5026
5027//detach all the work and timer structure declared or inititialize in r8192U_init function.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005028void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005029{
5030
Jerry Chuang8fc85982009-11-03 07:17:11 -02005031 cancel_work_sync(&priv->reset_wq);
5032 cancel_delayed_work(&priv->watch_dog_wq);
5033 cancel_delayed_work(&priv->update_beacon_wq);
5034 cancel_work_sync(&priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005035}
5036
5037
Bill Pembertona4a557e2012-11-19 13:26:46 -05005038static void rtl8192_usb_disconnect(struct usb_interface *intf)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005039{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005040 struct net_device *dev = usb_get_intfdata(intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005041
5042 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005043 if (dev) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005044
5045 unregister_netdev(dev);
5046
5047 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
5048 rtl8192_proc_remove_one(dev);
5049
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005050 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005051 kfree(priv->pFirmware);
5052 priv->pFirmware = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005053 rtl8192_usb_deleteendpoints(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005054 destroy_workqueue(priv->priv_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005055 mdelay(10);
5056
5057 }
5058 free_ieee80211(dev);
5059 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
5060}
5061
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005062/* fun with the built-in ieee80211 stack... */
5063extern int ieee80211_debug_init(void);
5064extern void ieee80211_debug_exit(void);
5065extern int ieee80211_crypto_init(void);
5066extern void ieee80211_crypto_deinit(void);
5067extern int ieee80211_crypto_tkip_init(void);
5068extern void ieee80211_crypto_tkip_exit(void);
5069extern int ieee80211_crypto_ccmp_init(void);
5070extern void ieee80211_crypto_ccmp_exit(void);
5071extern int ieee80211_crypto_wep_init(void);
5072extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005073
5074static int __init rtl8192_usb_module_init(void)
5075{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005076 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005077
5078#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005079 ret = ieee80211_debug_init();
5080 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005081 pr_err("ieee80211_debug_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005082 return ret;
5083 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005084#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005085 ret = ieee80211_crypto_init();
5086 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005087 pr_err("ieee80211_crypto_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005088 return ret;
5089 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005090
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005091 ret = ieee80211_crypto_tkip_init();
5092 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005093 pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005094 return ret;
5095 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005096
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005097 ret = ieee80211_crypto_ccmp_init();
5098 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005099 pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005100 return ret;
5101 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005102
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005103 ret = ieee80211_crypto_wep_init();
5104 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005105 pr_err("ieee80211_crypto_wep_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005106 return ret;
5107 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005108
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005109 pr_info("\nLinux kernel driver for RTL8192 based WLAN cards\n");
5110 pr_info("Copyright (c) 2007-2008, Realsil Wlan\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005111 RT_TRACE(COMP_INIT, "Initializing module");
5112 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
5113 rtl8192_proc_module_init();
5114 return usb_register(&rtl8192_usb_driver);
5115}
5116
5117
5118static void __exit rtl8192_usb_module_exit(void)
5119{
5120 usb_deregister(&rtl8192_usb_driver);
5121
5122 RT_TRACE(COMP_DOWN, "Exiting");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005123}
5124
5125
5126void rtl8192_try_wake_queue(struct net_device *dev, int pri)
5127{
5128 unsigned long flags;
5129 short enough_desc;
5130 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5131
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005132 spin_lock_irqsave(&priv->tx_lock, flags);
5133 enough_desc = check_nic_enough_desc(dev, pri);
5134 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005135
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005136 if (enough_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005137 ieee80211_wake_queue(priv->ieee80211);
5138}
5139
5140void EnableHWSecurityConfig8192(struct net_device *dev)
5141{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005142 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005143 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005144 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005145 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005146 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 -02005147 SECR_value |= SCR_RxUseDK;
5148 SECR_value |= SCR_TxUseDK;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005149 } 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 -02005150 SECR_value |= SCR_RxUseDK;
5151 SECR_value |= SCR_TxUseDK;
5152 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005153 //add HWSec active enable here.
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005154 //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 -02005155
5156 ieee->hwsec_active = 1;
5157
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005158 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 -02005159 ieee->hwsec_active = 0;
5160 SECR_value &= ~SCR_RxDecEnable;
5161 }
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03005162 RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __func__,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005163 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
5164 write_nic_byte(dev, SECR, SECR_value);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005165}
5166
5167
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03005168void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
5169 u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005170{
5171 u32 TargetCommand = 0;
5172 u32 TargetContent = 0;
5173 u16 usConfig = 0;
5174 u8 i;
5175 if (EntryNo >= TOTAL_CAM_ENTRY)
5176 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
5177
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005178 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 -02005179
5180 if (DefaultKey)
5181 usConfig |= BIT15 | (KeyType<<2);
5182 else
5183 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005184
5185
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005186 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005187 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
5188 TargetCommand |= BIT31|BIT16;
5189
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005190 if (i == 0) { //MAC|Config
Jerry Chuang8fc85982009-11-03 07:17:11 -02005191 TargetContent = (u32)(*(MacAddr+0)) << 16|
5192 (u32)(*(MacAddr+1)) << 24|
5193 (u32)usConfig;
5194
5195 write_nic_dword(dev, WCAMI, TargetContent);
5196 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005197 } else if (i == 1) { //MAC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005198 TargetContent = (u32)(*(MacAddr+2)) |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005199 (u32)(*(MacAddr+3)) << 8|
5200 (u32)(*(MacAddr+4)) << 16|
5201 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005202 write_nic_dword(dev, WCAMI, TargetContent);
5203 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005204 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005205 //Key Material
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005206 if (KeyContent != NULL) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005207 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)));
5208 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005209 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005210 }
5211 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005212
5213}
5214
5215/***************************************************************************
5216 ------------------- module init / exit stubs ----------------
5217****************************************************************************/
5218module_init(rtl8192_usb_module_init);
5219module_exit(rtl8192_usb_module_exit);