blob: 834afca0c74bc5ab828a276901d4859e764b9cbf [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
241void CamResetAllEntry(struct net_device *dev)
242{
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
594
595void rtl8192_proc_module_remove(void)
596{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200597 remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200598}
599
David Howells0541f9d2013-04-08 15:17:33 +0100600/*
601 * seq_file wrappers for procfile show routines.
602 */
603static int rtl8192_proc_open(struct inode *inode, struct file *file)
604{
David Howells4a520d22013-04-12 14:06:01 +0100605 struct net_device *dev = proc_get_parent_data(inode);
David Howells0541f9d2013-04-08 15:17:33 +0100606 int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
607
608 return single_open(file, show, dev);
609}
610
611static const struct file_operations rtl8192_proc_fops = {
612 .open = rtl8192_proc_open,
613 .read = seq_read,
614 .llseek = seq_lseek,
Al Virobae301d2013-05-05 00:15:43 -0400615 .release = single_release,
David Howells0541f9d2013-04-08 15:17:33 +0100616};
617
618/*
619 * Table of proc files we need to create.
620 */
621struct rtl8192_proc_file {
622 char name[12];
623 int (*show)(struct seq_file *, void *);
624};
625
626static const struct rtl8192_proc_file rtl8192_proc_files[] = {
627 { "stats-rx", &proc_get_stats_rx },
628 { "stats-tx", &proc_get_stats_tx },
629 { "stats-ap", &proc_get_stats_ap },
630 { "registers", &proc_get_registers },
631 { "" }
632};
633
Teodora Baluta46326d22013-10-16 01:59:17 +0300634static void rtl8192_proc_init_one(struct net_device *dev)
David Howells0541f9d2013-04-08 15:17:33 +0100635{
636 const struct rtl8192_proc_file *f;
David Howellscc87e0f2013-04-12 03:02:22 +0100637 struct proc_dir_entry *dir;
David Howells0541f9d2013-04-08 15:17:33 +0100638
639 if (rtl8192_proc) {
David Howellscc87e0f2013-04-12 03:02:22 +0100640 dir = proc_mkdir_data(dev->name, 0, rtl8192_proc, dev);
641 if (!dir) {
David Howells0541f9d2013-04-08 15:17:33 +0100642 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
643 dev->name);
644 return;
645 }
David Howells0541f9d2013-04-08 15:17:33 +0100646
647 for (f = rtl8192_proc_files; f->name[0]; f++) {
David Howellscc87e0f2013-04-12 03:02:22 +0100648 if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir,
649 &rtl8192_proc_fops, f->show)) {
David Howells0541f9d2013-04-08 15:17:33 +0100650 RT_TRACE(COMP_ERR, "Unable to initialize "
651 "/proc/net/rtl8192/%s/%s\n",
652 dev->name, f->name);
653 return;
654 }
655 }
656 }
657}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200658
Teodora Baluta46326d22013-10-16 01:59:17 +0300659static void rtl8192_proc_remove_one(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200660{
David Howellscc87e0f2013-04-12 03:02:22 +0100661 remove_proc_subtree(dev->name, rtl8192_proc);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200662}
663
Jerry Chuang8fc85982009-11-03 07:17:11 -0200664/****************************************************************************
665 -----------------------------MISC STUFF-------------------------
666*****************************************************************************/
667
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300668short check_nic_enough_desc(struct net_device *dev, int queue_index)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200669{
670 struct r8192_priv *priv = ieee80211_priv(dev);
671 int used = atomic_read(&priv->tx_pending[queue_index]);
672
673 return (used < MAX_TX_URB);
674}
675
676void tx_timeout(struct net_device *dev)
677{
678 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200679
Jerry Chuang8fc85982009-11-03 07:17:11 -0200680 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200681}
682
683
684/* this is only for debug */
685void dump_eprom(struct net_device *dev)
686{
687 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300688 for (i = 0; i < 63; i++)
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300689 RT_TRACE(COMP_EPROM, "EEPROM addr %x : %x", i, eprom_read(dev, i));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200690}
691
Jerry Chuang8fc85982009-11-03 07:17:11 -0200692
693/****************************************************************************
694 ------------------------------HW STUFF---------------------------
695*****************************************************************************/
696
Jerry Chuang8fc85982009-11-03 07:17:11 -0200697
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300698void rtl8192_set_mode(struct net_device *dev, int mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200699{
700 u8 ecmd;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300701 read_nic_byte(dev, EPROM_CMD, &ecmd);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300702 ecmd = ecmd & ~EPROM_CMD_OPERATING_MODE_MASK;
703 ecmd = ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300704 ecmd = ecmd & ~EPROM_CS_BIT;
705 ecmd = ecmd & ~EPROM_CK_BIT;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200706 write_nic_byte(dev, EPROM_CMD, ecmd);
707}
708
709
710void rtl8192_update_msr(struct net_device *dev)
711{
712 struct r8192_priv *priv = ieee80211_priv(dev);
713 u8 msr;
714
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300715 read_nic_byte(dev, MSR, &msr);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300716 msr &= ~MSR_LINK_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200717
718 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
719 * msr must be updated if the state is ASSOCIATING.
720 * this is intentional and make sense for ad-hoc and
721 * master (see the create BSS/IBSS func)
722 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300723 if (priv->ieee80211->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200724
725 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
726 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
727 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
728 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
729 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
730 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
731
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300732 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200733 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300734 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200735
736 write_nic_byte(dev, MSR, msr);
737}
738
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300739void rtl8192_set_chan(struct net_device *dev, short ch)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200740{
741 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +0300742 RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __func__, ch);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300743 priv->chan = ch;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200744
745 /* this hack should avoid frame TX during channel setting*/
746
Jerry Chuang8fc85982009-11-03 07:17:11 -0200747#ifndef LOOP_TEST
Jerry Chuang8fc85982009-11-03 07:17:11 -0200748 //need to implement rf set channel here WB
749
750 if (priv->rf_set_chan)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300751 priv->rf_set_chan(dev, priv->chan);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200752 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200753#endif
754}
755
Jerry Chuang8fc85982009-11-03 07:17:11 -0200756static void rtl8192_rx_isr(struct urb *urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200757
Teodora Baluta46326d22013-10-16 01:59:17 +0300758static u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200759{
760
761#ifdef USB_RX_AGGREGATION_SUPPORT
762 if (pstats->bisrxaggrsubframe)
763 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
764 + pstats->RxBufShift + 8);
765 else
766#endif
767 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300768 + pstats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200769
770}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300771static int rtl8192_rx_initiate(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200772{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200773 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
774 struct urb *entry;
775 struct sk_buff *skb;
776 struct rtl8192_rx_info *info;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200777
778 /* nomal packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200779 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB) {
780 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
781 if (!skb)
782 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200783 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200784 if (!entry) {
785 kfree_skb(skb);
786 break;
787 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200788 usb_fill_bulk_urb(entry, priv->udev,
789 usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb),
790 RX_URB_SIZE, rtl8192_rx_isr, skb);
791 info = (struct rtl8192_rx_info *) skb->cb;
792 info->urb = entry;
793 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200794 info->out_pipe = 3; //denote rx normal packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200795 skb_queue_tail(&priv->rx_queue, skb);
796 usb_submit_urb(entry, GFP_KERNEL);
797 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200798
799 /* command packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200800 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300801 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200802 if (!skb)
803 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200804 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200805 if (!entry) {
806 kfree_skb(skb);
807 break;
808 }
809 usb_fill_bulk_urb(entry, priv->udev,
810 usb_rcvbulkpipe(priv->udev, 9), skb_tail_pointer(skb),
811 RX_URB_SIZE, rtl8192_rx_isr, skb);
812 info = (struct rtl8192_rx_info *) skb->cb;
813 info->urb = entry;
814 info->dev = dev;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300815 info->out_pipe = 9; //denote rx cmd packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200816 skb_queue_tail(&priv->rx_queue, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200817 usb_submit_urb(entry, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200818 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200819
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200820 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200821}
822
823void rtl8192_set_rxconf(struct net_device *dev)
824{
825 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
826 u32 rxconf;
827
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300828 read_nic_dword(dev, RCR, &rxconf);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300829 rxconf = rxconf & ~MAC_FILTER_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200830 rxconf = rxconf | RCR_AMF;
831 rxconf = rxconf | RCR_ADF;
832 rxconf = rxconf | RCR_AB;
833 rxconf = rxconf | RCR_AM;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200834
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300835 if (dev->flags & IFF_PROMISC)
836 DMESG("NIC in promisc mode");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200837
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300838 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300839 dev->flags & IFF_PROMISC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200840 rxconf = rxconf | RCR_AAP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300841 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200842 rxconf = rxconf | RCR_APM;
843 rxconf = rxconf | RCR_CBSSID;
844 }
845
846
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300847 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200848 rxconf = rxconf | RCR_AICV;
849 rxconf = rxconf | RCR_APWRMGT;
850 }
851
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300852 if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200853 rxconf = rxconf | RCR_ACRC32;
854
855
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300856 rxconf = rxconf & ~RX_FIFO_THRESHOLD_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200857 rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE<<RX_FIFO_THRESHOLD_SHIFT);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300858 rxconf = rxconf & ~MAX_RX_DMA_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200859 rxconf = rxconf | ((u32)7<<RCR_MXDMA_OFFSET);
860
Jerry Chuang8fc85982009-11-03 07:17:11 -0200861 rxconf = rxconf | RCR_ONLYERLPKT;
862
Jerry Chuang8fc85982009-11-03 07:17:11 -0200863 write_nic_dword(dev, RCR, rxconf);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200864}
865//wait to be removed
866void rtl8192_rx_enable(struct net_device *dev)
867{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200868 rtl8192_rx_initiate(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200869}
870
871
872void rtl8192_tx_enable(struct net_device *dev)
873{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200874}
875
Jerry Chuang8fc85982009-11-03 07:17:11 -0200876
877
878void rtl8192_rtx_disable(struct net_device *dev)
879{
880 u8 cmd;
881 struct r8192_priv *priv = ieee80211_priv(dev);
882 struct sk_buff *skb;
883 struct rtl8192_rx_info *info;
884
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300885 read_nic_byte(dev, CMDR, &cmd);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300886 write_nic_byte(dev, CMDR, cmd & ~(CR_TE|CR_RE));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200887 force_pci_posting(dev);
888 mdelay(10);
889
890 while ((skb = __skb_dequeue(&priv->rx_queue))) {
891 info = (struct rtl8192_rx_info *) skb->cb;
892 if (!info->urb)
893 continue;
894
895 usb_kill_urb(info->urb);
896 kfree_skb(skb);
897 }
898
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300899 if (skb_queue_len(&priv->skb_queue))
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300900 netdev_warn(dev, "skb_queue not empty\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200901
902 skb_queue_purge(&priv->skb_queue);
903 return;
904}
905
906
907int alloc_tx_beacon_desc_ring(struct net_device *dev, int count)
908{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200909 return 0;
910}
911
Jerry Chuang8fc85982009-11-03 07:17:11 -0200912inline u16 ieeerate2rtlrate(int rate)
913{
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300914 switch (rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200915 case 10:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300916 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200917 case 20:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300918 return 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200919 case 55:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300920 return 2;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200921 case 110:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300922 return 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200923 case 60:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300924 return 4;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200925 case 90:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300926 return 5;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200927 case 120:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300928 return 6;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200929 case 180:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300930 return 7;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200931 case 240:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300932 return 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200933 case 360:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300934 return 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200935 case 480:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300936 return 10;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200937 case 540:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300938 return 11;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200939 default:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300940 return 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200941
942 }
943}
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300944static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
Jerry Chuang8fc85982009-11-03 07:17:11 -0200945inline u16 rtl8192_rate2rate(short rate)
946{
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300947 if (rate > 11) return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200948 return rtl_rate[rate];
949}
950
951
Justin P. Mattock589b3d02012-04-30 07:41:36 -0700952/* The prototype of rx_isr has changed since one version of Linux Kernel */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200953static void rtl8192_rx_isr(struct urb *urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200954{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200955 struct sk_buff *skb = (struct sk_buff *) urb->context;
956 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
957 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200958 struct r8192_priv *priv = ieee80211_priv(dev);
959 int out_pipe = info->out_pipe;
960 int err;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300961 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200962 return;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200963 if (unlikely(urb->status)) {
964 info->urb = NULL;
965 priv->stats.rxstaterr++;
966 priv->ieee80211->stats.rx_errors++;
967 usb_free_urb(urb);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200968 return;
969 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200970 skb_unlink(skb, &priv->rx_queue);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200971 skb_put(skb, urb->actual_length);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200972
973 skb_queue_tail(&priv->skb_queue, skb);
974 tasklet_schedule(&priv->irq_rx_tasklet);
975
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200976 skb = dev_alloc_skb(RX_URB_SIZE);
977 if (unlikely(!skb)) {
978 usb_free_urb(urb);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300979 netdev_err(dev, "%s(): can't alloc skb\n", __func__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200980 /* TODO check rx queue length and refill *somewhere* */
981 return;
982 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200983
984 usb_fill_bulk_urb(urb, priv->udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300985 usb_rcvbulkpipe(priv->udev, out_pipe), skb_tail_pointer(skb),
986 RX_URB_SIZE, rtl8192_rx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200987
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200988 info = (struct rtl8192_rx_info *) skb->cb;
989 info->urb = urb;
990 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200991 info->out_pipe = out_pipe;
992
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200993 urb->transfer_buffer = skb_tail_pointer(skb);
994 urb->context = skb;
995 skb_queue_tail(&priv->rx_queue, skb);
996 err = usb_submit_urb(urb, GFP_ATOMIC);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300997 if (err && err != EPERM)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300998 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 -0200999}
1000
Teodora Baluta46326d22013-10-16 01:59:17 +03001001static u32 rtl819xusb_rx_command_packet(struct net_device *dev,
1002 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001003{
1004 u32 status;
1005
Jerry Chuang8fc85982009-11-03 07:17:11 -02001006 status = cmpk_message_handle_rx(dev, pstats);
1007 if (status)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001008 DMESG("rxcommandpackethandle819xusb: It is a command packet\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001009
Jerry Chuang8fc85982009-11-03 07:17:11 -02001010 return status;
1011}
1012
Jerry Chuang8fc85982009-11-03 07:17:11 -02001013
1014void rtl8192_data_hard_stop(struct net_device *dev)
1015{
1016 //FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001017}
1018
1019
1020void rtl8192_data_hard_resume(struct net_device *dev)
1021{
1022 // FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001023}
1024
1025/* this function TX data frames when the ieee80211 stack requires this.
1026 * It checks also if we need to stop the ieee tx queue, eventually do it
1027 */
1028void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
1029{
1030 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1031 int ret;
1032 unsigned long flags;
1033 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1034 u8 queue_index = tcb_desc->queue_index;
1035
1036 /* shall not be referred by command packet */
Xenia Ragiadakou4a8d1132013-06-09 14:38:43 +03001037 RTL8192U_ASSERT(queue_index != TXCMD_QUEUE);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001038
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001039 spin_lock_irqsave(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001040
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001041 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001042 tcb_desc->bTxEnableFwCalcDur = 1;
1043 skb_push(skb, priv->ieee80211->tx_headroom);
1044 ret = rtl8192_tx(dev, skb);
1045
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001046 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001047
Jerry Chuang8fc85982009-11-03 07:17:11 -02001048 return;
1049}
1050
1051/* This is a rough attempt to TX a frame
1052 * This is called by the ieee 80211 stack to TX management frames.
1053 * If the ring is full packet are dropped (for data frame the queue
1054 * is stopped before this can happen).
1055 */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001056int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001057{
1058 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1059 int ret;
1060 unsigned long flags;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001061 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1062 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001063
1064
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001065 spin_lock_irqsave(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001066
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001067 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001068 if (queue_index == TXCMD_QUEUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001069 skb_push(skb, USB_HWDESC_HEADER_LEN);
1070 rtl819xU_tx_cmd(dev, skb);
1071 ret = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001072 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001073 return ret;
1074 } else {
1075 skb_push(skb, priv->ieee80211->tx_headroom);
1076 ret = rtl8192_tx(dev, skb);
1077 }
1078
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001079 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001080
1081 return ret;
1082}
1083
1084
1085void rtl8192_try_wake_queue(struct net_device *dev, int pri);
1086
1087#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1088u16 DrvAggr_PaddingAdd(struct net_device *dev, struct sk_buff *skb)
1089{
1090 u16 PaddingNum = 256 - ((skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES) % 256);
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03001091 return PaddingNum & 0xff;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001092}
1093
1094u8 MRateToHwRate8190Pci(u8 rate);
1095u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc);
1096u8 MapHwQueueToFirmwareQueue(u8 QueueID);
1097struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv_agg_txb *pSendList)
1098{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001099 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001100 struct r8192_priv *priv = ieee80211_priv(dev);
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001101 cb_desc *tcb_desc = NULL;
1102 u8 i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001103 u32 TotalLength;
1104 struct sk_buff *skb;
1105 struct sk_buff *agg_skb;
1106 tx_desc_819x_usb_aggr_subframe *tx_agg_desc = NULL;
1107 tx_fwinfo_819x_usb *tx_fwinfo = NULL;
1108
1109 //
1110 // Local variable initialization.
1111 //
1112 /* first skb initialization */
1113 skb = pSendList->tx_agg_frames[0];
1114 TotalLength = skb->len;
1115
1116 /* Get the total aggregation length including the padding space and
1117 * sub frame header.
1118 */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001119 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001120 TotalLength += DrvAggr_PaddingAdd(dev, skb);
1121 skb = pSendList->tx_agg_frames[i];
1122 TotalLength += (skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1123 }
1124
1125 /* allocate skb to contain the aggregated packets */
1126 agg_skb = dev_alloc_skb(TotalLength + ieee->tx_headroom);
1127 memset(agg_skb->data, 0, agg_skb->len);
1128 skb_reserve(agg_skb, ieee->tx_headroom);
1129
Jerry Chuang8fc85982009-11-03 07:17:11 -02001130 /* reserve info for first subframe Tx descriptor to be set in the tx function */
1131 skb = pSendList->tx_agg_frames[0];
1132 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1133 tcb_desc->drv_agg_enable = 1;
1134 tcb_desc->pkt_size = skb->len;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001135 tcb_desc->DrvAggrNum = pSendList->nr_drv_agg_frames;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001136 netdev_dbg(dev, "DrvAggNum = %d\n", tcb_desc->DrvAggrNum);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001137 memcpy(agg_skb->cb, skb->cb, sizeof(skb->cb));
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001138 memcpy(skb_put(agg_skb, skb->len), skb->data, skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001139
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001140 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001141 /* push the next sub frame to be 256 byte aline */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001142 skb_put(agg_skb, DrvAggr_PaddingAdd(dev, skb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001143
1144 /* Subframe drv Tx descriptor and firmware info setting */
1145 skb = pSendList->tx_agg_frames[i];
1146 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Isaku Yamahataa267a602013-06-14 17:58:35 +09001147 tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)skb_tail_pointer(agg_skb);
1148 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 -02001149
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001150 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001151 /* DWORD 0 */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001152 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001153 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1154 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1155 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001156 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001157 tx_fwinfo->AllowAggregation = 1;
1158 /* DWORD 1 */
1159 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1160 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1161 } else {
1162 tx_fwinfo->AllowAggregation = 0;
1163 /* DWORD 1 */
1164 tx_fwinfo->RxMF = 0;
1165 tx_fwinfo->RxAMD = 0;
1166 }
1167
1168 /* Protection mode related */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001169 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1170 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1171 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1172 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001173 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001174 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->RTSSC) : 0;
1175 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1) ? ((tcb_desc->bRTSBW) ? 1 : 0) : 0;
1176 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) :
1177 (tcb_desc->bRTSUseShortGI ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001178
1179 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001180 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001181 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001182 tx_fwinfo->TxBandwidth = 1;
1183 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1184 } else {
1185 tx_fwinfo->TxBandwidth = 0;
1186 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1187 }
1188 } else {
1189 tx_fwinfo->TxBandwidth = 0;
1190 tx_fwinfo->TxSubCarrier = 0;
1191 }
1192
1193 /* Fill Tx descriptor */
1194 memset(tx_agg_desc, 0, sizeof(tx_desc_819x_usb_aggr_subframe));
1195 /* DWORD 0 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001196 tx_agg_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001197 /* already raw data, need not to subtract header length */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001198 tx_agg_desc->PktSize = skb->len & 0xffff;
1199
1200 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001201 tx_agg_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001202 tx_agg_desc->RATid = tcb_desc->RATRIndex;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001203 tx_agg_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001204 tx_agg_desc->SecType = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001205
1206 if (tcb_desc->bHwSec) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001207 switch (priv->ieee80211->pairwise_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001208 case KEY_TYPE_WEP40:
1209 case KEY_TYPE_WEP104:
1210 tx_agg_desc->SecType = 0x1;
1211 tx_agg_desc->NoEnc = 0;
1212 break;
1213 case KEY_TYPE_TKIP:
1214 tx_agg_desc->SecType = 0x2;
1215 tx_agg_desc->NoEnc = 0;
1216 break;
1217 case KEY_TYPE_CCMP:
1218 tx_agg_desc->SecType = 0x3;
1219 tx_agg_desc->NoEnc = 0;
1220 break;
1221 case KEY_TYPE_NA:
1222 tx_agg_desc->SecType = 0x0;
1223 tx_agg_desc->NoEnc = 1;
1224 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001225 }
1226 }
1227
1228 tx_agg_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1229 tx_agg_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1230
1231 tx_agg_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1232 tx_agg_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1233
1234 tx_agg_desc->OWN = 1;
1235
1236 //DWORD 2
1237 /* According windows driver, it seems that there no need to fill this field */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001238
1239 /* to fill next packet */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001240 skb_put(agg_skb, TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1241 memcpy(skb_put(agg_skb, skb->len), skb->data, skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001242 }
1243
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001244 for (i = 0; i < pSendList->nr_drv_agg_frames; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001245 dev_kfree_skb_any(pSendList->tx_agg_frames[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001246
1247 return agg_skb;
1248}
1249
1250/* NOTE:
1251 This function return a list of PTCB which is proper to be aggregate with the input TCB.
1252 If no proper TCB is found to do aggregation, SendList will only contain the input TCB.
1253*/
1254u8 DrvAggr_GetAggregatibleList(struct net_device *dev, struct sk_buff *skb,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001255 struct ieee80211_drv_agg_txb *pSendList)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001256{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001257 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001258 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1259 u16 nMaxAggrNum = pHTInfo->UsbTxAggrNum;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001260 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001261 u8 QueueID = tcb_desc->queue_index;
1262
1263 do {
1264 pSendList->tx_agg_frames[pSendList->nr_drv_agg_frames++] = skb;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001265 if (pSendList->nr_drv_agg_frames >= nMaxAggrNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001266 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001267
Xenia Ragiadakou53c7f3c2013-05-22 18:22:35 +03001268 } while ((skb = skb_dequeue(&ieee->skb_drv_aggQ[QueueID])));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001269
1270 RT_TRACE(COMP_AMSDU, "DrvAggr_GetAggregatibleList, nAggrTcbNum = %d \n", pSendList->nr_drv_agg_frames);
1271 return pSendList->nr_drv_agg_frames;
1272}
1273#endif
1274
Jerry Chuang8fc85982009-11-03 07:17:11 -02001275static void rtl8192_tx_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001276{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001277 struct sk_buff *skb = (struct sk_buff *)tx_urb->context;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001278 struct net_device *dev = NULL;
1279 struct r8192_priv *priv = NULL;
1280 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1281 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001282
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001283 memcpy(&dev, (struct net_device *)(skb->cb), sizeof(struct net_device *));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001284 priv = ieee80211_priv(dev);
1285
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001286 if (tcb_desc->queue_index != TXCMD_QUEUE) {
1287 if (tx_urb->status == 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001288 dev->trans_start = jiffies;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001289 priv->stats.txoktotal++;
1290 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
1291 priv->stats.txbytesunicast += (skb->len - priv->ieee80211->tx_headroom);
1292 } else {
1293 priv->ieee80211->stats.tx_errors++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001294 /* TODO */
1295 }
1296 }
1297
1298 /* free skb and tx_urb */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001299 if (skb != NULL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001300 dev_kfree_skb_any(skb);
1301 usb_free_urb(tx_urb);
1302 atomic_dec(&priv->tx_pending[queue_index]);
1303 }
1304
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001305 //
1306 // Handle HW Beacon:
1307 // We had transfer our beacon frame to host controller at this moment.
1308 //
1309 //
1310 // Caution:
1311 // Handling the wait queue of command packets.
1312 // For Tx command packets, we must not do TCB fragment because it is not handled right now.
1313 // We must cut the packets to match the size of TX_CMD_PKT before we send it.
1314 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02001315
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001316 /* Handle MPDU in wait queue. */
1317 if (queue_index != BEACON_QUEUE) {
1318 /* Don't send data frame during scanning.*/
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001319 if ((skb_queue_len(&priv->ieee80211->skb_waitQ[queue_index]) != 0) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001320 (!(priv->ieee80211->queue_stop))) {
Chi Pham09adb6e2014-03-10 22:31:52 +01001321 skb = skb_dequeue(&(priv->ieee80211->skb_waitQ[queue_index]));
1322 if (skb)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001323 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001324
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001325 return; //modified by david to avoid further processing AMSDU
Jerry Chuang8fc85982009-11-03 07:17:11 -02001326 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001327#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001328 else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index]) != 0) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001329 (!(priv->ieee80211->queue_stop))) {
1330 // Tx Driver Aggregation process
1331 /* The driver will aggregation the packets according to the following stats
1332 * 1. check whether there's tx irq available, for it's a completion return
1333 * function, it should contain enough tx irq;
1334 * 2. check packet type;
1335 * 3. initialize sendlist, check whether the to-be send packet no greater than 1
1336 * 4. aggregates the packets, and fill firmware info and tx desc into it, etc.
1337 * 5. check whether the packet could be sent, otherwise just insert into wait head
1338 * */
1339 skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]);
1340 if (!check_nic_enough_desc(dev, queue_index)) {
1341 skb_queue_head(&(priv->ieee80211->skb_drv_aggQ[queue_index]), skb);
1342 return;
1343 }
1344
1345 /*TODO*/
1346 {
1347 struct ieee80211_drv_agg_txb SendList;
1348
1349 memset(&SendList, 0, sizeof(struct ieee80211_drv_agg_txb));
1350 if (DrvAggr_GetAggregatibleList(dev, skb, &SendList) > 1) {
1351 skb = DrvAggr_Aggregation(dev, &SendList);
1352
1353 }
1354 }
1355 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1356 }
1357#endif
1358 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001359
Jerry Chuang8fc85982009-11-03 07:17:11 -02001360}
1361
1362void rtl8192_beacon_stop(struct net_device *dev)
1363{
1364 u8 msr, msrm, msr2;
1365 struct r8192_priv *priv = ieee80211_priv(dev);
1366
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03001367 read_nic_byte(dev, MSR, &msr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001368 msrm = msr & MSR_LINK_MASK;
1369 msr2 = msr & ~MSR_LINK_MASK;
1370
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001371 if (NIC_8192U == priv->card_8192)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001372 usb_kill_urb(priv->rx_urb[MAX_RX_URB]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001373 if ((msrm == (MSR_LINK_ADHOC<<MSR_LINK_SHIFT) ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001374 (msrm == (MSR_LINK_MASTER<<MSR_LINK_SHIFT)))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001375 write_nic_byte(dev, MSR, msr2 | MSR_LINK_NONE);
1376 write_nic_byte(dev, MSR, msr);
1377 }
1378}
1379
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001380void rtl8192_config_rate(struct net_device *dev, u16 *rate_config)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001381{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001382 struct r8192_priv *priv = ieee80211_priv(dev);
1383 struct ieee80211_network *net;
1384 u8 i = 0, basic_rate = 0;
Xenia Ragiadakou003a2d12013-06-04 23:32:29 +03001385 net = &priv->ieee80211->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001386
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001387 for (i = 0; i < net->rates_len; i++) {
1388 basic_rate = net->rates[i]&0x7f;
1389 switch (basic_rate) {
1390 case MGN_1M: *rate_config |= RRSR_1M; break;
1391 case MGN_2M: *rate_config |= RRSR_2M; break;
1392 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1393 case MGN_11M: *rate_config |= RRSR_11M; break;
1394 case MGN_6M: *rate_config |= RRSR_6M; break;
1395 case MGN_9M: *rate_config |= RRSR_9M; break;
1396 case MGN_12M: *rate_config |= RRSR_12M; break;
1397 case MGN_18M: *rate_config |= RRSR_18M; break;
1398 case MGN_24M: *rate_config |= RRSR_24M; break;
1399 case MGN_36M: *rate_config |= RRSR_36M; break;
1400 case MGN_48M: *rate_config |= RRSR_48M; break;
1401 case MGN_54M: *rate_config |= RRSR_54M; break;
1402 }
1403 }
1404 for (i = 0; i < net->rates_ex_len; i++) {
1405 basic_rate = net->rates_ex[i]&0x7f;
1406 switch (basic_rate) {
1407 case MGN_1M: *rate_config |= RRSR_1M; break;
1408 case MGN_2M: *rate_config |= RRSR_2M; break;
1409 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1410 case MGN_11M: *rate_config |= RRSR_11M; break;
1411 case MGN_6M: *rate_config |= RRSR_6M; break;
1412 case MGN_9M: *rate_config |= RRSR_9M; break;
1413 case MGN_12M: *rate_config |= RRSR_12M; break;
1414 case MGN_18M: *rate_config |= RRSR_18M; break;
1415 case MGN_24M: *rate_config |= RRSR_24M; break;
1416 case MGN_36M: *rate_config |= RRSR_36M; break;
1417 case MGN_48M: *rate_config |= RRSR_48M; break;
1418 case MGN_54M: *rate_config |= RRSR_54M; break;
1419 }
1420 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001421}
1422
1423
1424#define SHORT_SLOT_TIME 9
1425#define NON_SHORT_SLOT_TIME 20
1426
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001427void rtl8192_update_cap(struct net_device *dev, u16 cap)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001428{
1429 u32 tmp = 0;
1430 struct r8192_priv *priv = ieee80211_priv(dev);
1431 struct ieee80211_network *net = &priv->ieee80211->current_network;
1432 priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
1433 tmp = priv->basic_rate;
1434 if (priv->short_preamble)
1435 tmp |= BRSR_AckShortPmb;
1436 write_nic_dword(dev, RRSR, tmp);
1437
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001438 if (net->mode & (IEEE_G|IEEE_N_24G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001439 u8 slot_time = 0;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001440 if ((cap & WLAN_CAPABILITY_SHORT_SLOT) && (!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime)) //short slot time
Jerry Chuang8fc85982009-11-03 07:17:11 -02001441 slot_time = SHORT_SLOT_TIME;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001442 else //long slot time
1443 slot_time = NON_SHORT_SLOT_TIME;
1444 priv->slot_time = slot_time;
1445 write_nic_byte(dev, SLOT_TIME, slot_time);
1446 }
1447
1448}
1449void rtl8192_net_update(struct net_device *dev)
1450{
1451
1452 struct r8192_priv *priv = ieee80211_priv(dev);
1453 struct ieee80211_network *net;
1454 u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
1455 u16 rate_config = 0;
Xenia Ragiadakou003a2d12013-06-04 23:32:29 +03001456 net = &priv->ieee80211->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001457
1458 rtl8192_config_rate(dev, &rate_config);
1459 priv->basic_rate = rate_config &= 0x15f;
1460
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001461 write_nic_dword(dev, BSSIDR, ((u32 *)net->bssid)[0]);
1462 write_nic_word(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001463
1464 rtl8192_update_msr(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001465 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001466 write_nic_word(dev, ATIMWND, 2);
1467 write_nic_word(dev, BCN_DMATIME, 1023);
1468 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
1469 write_nic_word(dev, BCN_DRV_EARLY_INT, 1);
1470 write_nic_byte(dev, BCN_ERR_THRESH, 100);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001471 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001472 // TODO: BcnIFS may required to be changed on ASIC
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001473 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001474
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001475 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001476 }
1477
1478
1479
1480}
1481
1482//temporary hw beacon is not used any more.
1483//open it when necessary
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001484void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001485{
1486
Jerry Chuang8fc85982009-11-03 07:17:11 -02001487}
Jerry Chuang8fc85982009-11-03 07:17:11 -02001488inline u8 rtl8192_IsWirelessBMode(u16 rate)
1489{
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03001490 if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220))
Jerry Chuang8fc85982009-11-03 07:17:11 -02001491 return 1;
1492 else return 0;
1493}
1494
1495u16 N_DBPSOfRate(u16 DataRate);
1496
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03001497u16 ComputeTxTime(u16 FrameLength, u16 DataRate, u8 bManagementFrame,
1498 u8 bShortPreamble)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001499{
1500 u16 FrameTime;
1501 u16 N_DBPS;
1502 u16 Ceiling;
1503
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001504 if (rtl8192_IsWirelessBMode(DataRate)) {
1505 if (bManagementFrame || !bShortPreamble || DataRate == 10) // long preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001506 FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001507 else // Short preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001508 FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03001509 if ((FrameLength*8 % (DataRate/10)) != 0) //Get the Ceilling
Xenia Ragiadakou7d79ec62013-06-04 23:32:30 +03001510 FrameTime++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001511 } else { //802.11g DSSS-OFDM PLCP length field calculation.
1512 N_DBPS = N_DBPSOfRate(DataRate);
1513 Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001514 + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001515 FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
1516 }
1517 return FrameTime;
1518}
1519
1520u16 N_DBPSOfRate(u16 DataRate)
1521{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001522 u16 N_DBPS = 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001523
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001524 switch (DataRate) {
1525 case 60:
1526 N_DBPS = 24;
1527 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001528
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001529 case 90:
1530 N_DBPS = 36;
1531 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001532
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001533 case 120:
1534 N_DBPS = 48;
1535 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001536
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001537 case 180:
1538 N_DBPS = 72;
1539 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001540
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001541 case 240:
1542 N_DBPS = 96;
1543 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001544
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001545 case 360:
1546 N_DBPS = 144;
1547 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001548
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001549 case 480:
1550 N_DBPS = 192;
1551 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001552
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001553 case 540:
1554 N_DBPS = 216;
1555 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001556
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001557 default:
1558 break;
1559 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001560
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001561 return N_DBPS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001562}
1563
1564void rtl819xU_cmd_isr(struct urb *tx_cmd_urb, struct pt_regs *regs)
1565{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001566 usb_free_urb(tx_cmd_urb);
1567}
1568
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001569unsigned int txqueue2outpipe(struct r8192_priv *priv, unsigned int tx_queue)
1570{
1571 if (tx_queue >= 9) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03001572 RT_TRACE(COMP_ERR, "%s():Unknown queue ID!!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001573 return 0x04;
1574 }
1575 return priv->txqueue_to_outpipemap[tx_queue];
1576}
1577
1578short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
1579{
1580 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001581 int status;
1582 struct urb *tx_urb;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001583 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001584 tx_desc_cmd_819x_usb *pdesc = (tx_desc_cmd_819x_usb *)skb->data;
1585 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1586 u8 queue_index = tcb_desc->queue_index;
1587
Jerry Chuang8fc85982009-11-03 07:17:11 -02001588 atomic_inc(&priv->tx_pending[queue_index]);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001589 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001590 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001591 dev_kfree_skb(skb);
1592 return -ENOMEM;
1593 }
1594
1595 memset(pdesc, 0, USB_HWDESC_HEADER_LEN);
1596 /* Tx descriptor ought to be set according to the skb->cb */
1597 pdesc->FirstSeg = 1;//bFirstSeg;
1598 pdesc->LastSeg = 1;//bLastSeg;
1599 pdesc->CmdInit = tcb_desc->bCmdOrInit;
1600 pdesc->TxBufferSize = tcb_desc->txbuf_size;
1601 pdesc->OWN = 1;
1602 pdesc->LINIP = tcb_desc->bLastIniPkt;
1603
1604 //----------------------------------------------------------------------------
1605 // Fill up USB_OUT_CONTEXT.
1606 //----------------------------------------------------------------------------
1607 // Get index to out pipe from specified QueueID.
1608#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001609 idx_pipe = txqueue2outpipe(priv, queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001610#else
1611 idx_pipe = 0x04;
1612#endif
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03001613 usb_fill_bulk_urb(tx_urb, priv->udev, usb_sndbulkpipe(priv->udev, idx_pipe),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001614 skb->data, skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001615
Jerry Chuang8fc85982009-11-03 07:17:11 -02001616 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001617
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001618 if (!status) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001619 return 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001620 } else {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001621 DMESGE("Error TX CMD URB, error %d", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001622 return -1;
1623 }
1624}
1625
1626/*
1627 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1628 * in TxFwInfo data structure
1629 * 2006.10.30 by Emily
1630 *
1631 * \param QUEUEID Software Queue
1632*/
Teodora Baluta46326d22013-10-16 01:59:17 +03001633static u8 MapHwQueueToFirmwareQueue(u8 QueueID)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001634{
1635 u8 QueueSelect = 0x0; //defualt set to
1636
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001637 switch (QueueID) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001638 case BE_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001639 QueueSelect = QSLT_BE;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001640 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001641
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001642 case BK_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001643 QueueSelect = QSLT_BK;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001644 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001645
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001646 case VO_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001647 QueueSelect = QSLT_VO;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001648 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001649
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001650 case VI_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001651 QueueSelect = QSLT_VI;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001652 break;
1653 case MGNT_QUEUE:
1654 QueueSelect = QSLT_MGNT;
1655 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001656
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001657 case BEACON_QUEUE:
1658 QueueSelect = QSLT_BEACON;
1659 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001660
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001661 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
1662 // TODO: Remove Assertions
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001663 case TXCMD_QUEUE:
1664 QueueSelect = QSLT_CMD;
1665 break;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001666 case HIGH_QUEUE:
1667 QueueSelect = QSLT_HIGH;
1668 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001669
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001670 default:
1671 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
1672 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001673 }
1674 return QueueSelect;
1675}
1676
1677u8 MRateToHwRate8190Pci(u8 rate)
1678{
1679 u8 ret = DESC90_RATE1M;
1680
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001681 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001682 case MGN_1M: ret = DESC90_RATE1M; break;
1683 case MGN_2M: ret = DESC90_RATE2M; break;
1684 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1685 case MGN_11M: ret = DESC90_RATE11M; break;
1686 case MGN_6M: ret = DESC90_RATE6M; break;
1687 case MGN_9M: ret = DESC90_RATE9M; break;
1688 case MGN_12M: ret = DESC90_RATE12M; break;
1689 case MGN_18M: ret = DESC90_RATE18M; break;
1690 case MGN_24M: ret = DESC90_RATE24M; break;
1691 case MGN_36M: ret = DESC90_RATE36M; break;
1692 case MGN_48M: ret = DESC90_RATE48M; break;
1693 case MGN_54M: ret = DESC90_RATE54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001694
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001695 // HT rate since here
1696 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1697 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1698 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1699 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1700 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1701 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1702 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1703 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1704 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1705 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1706 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1707 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1708 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1709 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1710 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1711 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1712 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001713
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001714 default: break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001715 }
1716 return ret;
1717}
1718
1719
Teodora Baluta46326d22013-10-16 01:59:17 +03001720static u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001721{
1722 u8 tmp_Short;
1723
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001724 tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) : ((tcb_desc->bUseShortPreamble) ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001725
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03001726 if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001727 tmp_Short = 0;
1728
1729 return tmp_Short;
1730}
1731
Jerry Chuang8fc85982009-11-03 07:17:11 -02001732static void tx_zero_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001733{
1734 return;
1735}
1736
1737/*
1738 * The tx procedure is just as following,
1739 * skb->cb will contain all the following information,
1740 * priority, morefrag, rate, &dev.
1741 * */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001742short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001743{
1744 struct r8192_priv *priv = ieee80211_priv(dev);
1745 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1746 tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data;
1747 tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
1748 struct usb_device *udev = priv->udev;
1749 int pend;
1750 int status;
1751 struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001752 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001753 pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]);
1754 /* we are locked here so the two atomic_read and inc are executed
1755 * without interleaves
1756 * !!! For debug purpose
1757 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001758 if (pend > MAX_TX_URB) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001759 netdev_dbg(dev, "To discard skb packet!\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001760 dev_kfree_skb_any(skb);
1761 return -1;
1762 }
1763
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001764 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001765 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001766 dev_kfree_skb_any(skb);
1767 return -ENOMEM;
1768 }
1769
1770 /* Fill Tx firmware info */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001771 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001772 /* DWORD 0 */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001773 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001774 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1775 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1776 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001777 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001778 tx_fwinfo->AllowAggregation = 1;
1779 /* DWORD 1 */
1780 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1781 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1782 } else {
1783 tx_fwinfo->AllowAggregation = 0;
1784 /* DWORD 1 */
1785 tx_fwinfo->RxMF = 0;
1786 tx_fwinfo->RxAMD = 0;
1787 }
1788
1789 /* Protection mode related */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001790 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1791 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1792 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1793 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001794 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001795 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->RTSSC) : 0;
1796 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1) ? ((tcb_desc->bRTSBW) ? 1 : 0) : 0;
1797 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) :
1798 (tcb_desc->bRTSUseShortGI ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001799
1800 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001801 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001802 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001803 tx_fwinfo->TxBandwidth = 1;
1804 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1805 } else {
1806 tx_fwinfo->TxBandwidth = 0;
1807 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1808 }
1809 } else {
1810 tx_fwinfo->TxBandwidth = 0;
1811 tx_fwinfo->TxSubCarrier = 0;
1812 }
1813
1814#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1815 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001816 tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001817#endif
1818 /* Fill Tx descriptor */
1819 memset(tx_desc, 0, sizeof(tx_desc_819x_usb));
1820 /* DWORD 0 */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001821 tx_desc->LINIP = 0;
1822 tx_desc->CmdInit = 1;
1823 tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001824
1825#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001826 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001827 tx_desc->PktSize = tcb_desc->pkt_size;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001828 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02001829#endif
1830 {
1831 tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff;
1832 }
1833
1834 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001835 tx_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001836 tx_desc->RATid = tcb_desc->RATRIndex;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001837 tx_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001838 tx_desc->SecType = 0x0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001839 if (tcb_desc->bHwSec) {
1840 switch (priv->ieee80211->pairwise_key_type) {
1841 case KEY_TYPE_WEP40:
1842 case KEY_TYPE_WEP104:
1843 tx_desc->SecType = 0x1;
1844 tx_desc->NoEnc = 0;
1845 break;
1846 case KEY_TYPE_TKIP:
1847 tx_desc->SecType = 0x2;
1848 tx_desc->NoEnc = 0;
1849 break;
1850 case KEY_TYPE_CCMP:
1851 tx_desc->SecType = 0x3;
1852 tx_desc->NoEnc = 0;
1853 break;
1854 case KEY_TYPE_NA:
1855 tx_desc->SecType = 0x0;
1856 tx_desc->NoEnc = 1;
1857 break;
1858 }
1859 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001860
1861 tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1862 tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1863
1864 tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1865 tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1866
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001867 /* Fill fields that are required to be initialized in all of the descriptors */
1868 //DWORD 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001869 tx_desc->FirstSeg = 1;
1870 tx_desc->LastSeg = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001871 tx_desc->OWN = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001872
1873#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1874 if (tcb_desc->drv_agg_enable) {
1875 tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb);
1876 } else
1877#endif
1878 {
1879 //DWORD 2
1880 tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN);
1881 }
1882 /* Get index to out pipe from specified QueueID */
1883#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001884 idx_pipe = txqueue2outpipe(priv, tcb_desc->queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001885#else
1886 idx_pipe = 0x5;
1887#endif
1888
Jerry Chuang8fc85982009-11-03 07:17:11 -02001889 /* To submit bulk urb */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001890 usb_fill_bulk_urb(tx_urb, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001891 usb_sndbulkpipe(udev, idx_pipe), skb->data,
1892 skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001893
Jerry Chuang8fc85982009-11-03 07:17:11 -02001894 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001895 if (!status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001896 //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 -02001897 bool bSend0Byte = false;
1898 u8 zero = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001899 if (udev->speed == USB_SPEED_HIGH) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001900 if (skb->len > 0 && skb->len % 512 == 0)
1901 bSend0Byte = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001902 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001903 if (skb->len > 0 && skb->len % 64 == 0)
1904 bSend0Byte = true;
1905 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001906 if (bSend0Byte) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001907 tx_urb_zero = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001908 if (!tx_urb_zero) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001909 RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
1910 return -ENOMEM;
1911 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001912 usb_fill_bulk_urb(tx_urb_zero, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001913 usb_sndbulkpipe(udev, idx_pipe), &zero,
1914 0, tx_zero_isr, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001915 status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001916 if (status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001917 RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
1918 return -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001919 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001920 }
1921 dev->trans_start = jiffies;
1922 atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
1923 return 0;
Patrik Karlin29b48ae2013-01-09 09:40:23 +01001924 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001925 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 +03001926 status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001927 return -1;
1928 }
1929}
1930
Teodora Baluta46326d22013-10-16 01:59:17 +03001931static short rtl8192_usb_initendpoints(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001932{
1933 struct r8192_priv *priv = ieee80211_priv(dev);
1934
Julia Lawall32414872010-05-11 20:26:57 +02001935 priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB+1),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001936 GFP_KERNEL);
David Chosrovab8345172010-12-01 13:42:16 +01001937 if (priv->rx_urb == NULL)
1938 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001939
1940#ifndef JACKSON_NEW_RX
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001941 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001942
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001943 priv->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001944
1945 priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL);
1946
1947 priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE;
1948 }
1949#endif
1950
1951#ifdef THOMAS_BEACON
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001952 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001953 long align = 0;
1954 void *oldaddr, *newaddr;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001955
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001956 priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
1957 priv->oldaddr = kmalloc(16, GFP_KERNEL);
1958 oldaddr = priv->oldaddr;
1959 align = ((long)oldaddr) & 3;
1960 if (align) {
1961 newaddr = oldaddr + 4 - align;
1962 priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align;
1963 } else {
1964 newaddr = oldaddr;
1965 priv->rx_urb[16]->transfer_buffer_length = 16;
1966 }
1967 priv->rx_urb[16]->transfer_buffer = newaddr;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001968 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001969#endif
1970
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001971 memset(priv->rx_urb, 0, sizeof(struct urb *) * MAX_RX_URB);
Julia Lawall7a6cb0d2010-05-13 22:00:05 +02001972 priv->pp_rxskb = kcalloc(MAX_RX_URB, sizeof(struct sk_buff *),
Julia Lawall32414872010-05-11 20:26:57 +02001973 GFP_KERNEL);
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001974 if (!priv->pp_rxskb) {
1975 kfree(priv->rx_urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001976
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001977 priv->pp_rxskb = NULL;
1978 priv->rx_urb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001979
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001980 DMESGE("Endpoint Alloc Failure");
1981 return -ENOMEM;
1982 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001983
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001984 netdev_dbg(dev, "End of initendpoints\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001985 return 0;
1986
1987}
1988#ifdef THOMAS_BEACON
Teodora Baluta46326d22013-10-16 01:59:17 +03001989static void rtl8192_usb_deleteendpoints(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001990{
1991 int i;
1992 struct r8192_priv *priv = ieee80211_priv(dev);
1993
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001994 if (priv->rx_urb) {
1995 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001996 usb_kill_urb(priv->rx_urb[i]);
1997 usb_free_urb(priv->rx_urb[i]);
1998 }
1999 kfree(priv->rx_urb);
2000 priv->rx_urb = NULL;
2001 }
Ilia Mirkine72714f2011-03-13 00:29:07 -05002002 kfree(priv->oldaddr);
2003 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002004 if (priv->pp_rxskb) {
2005 kfree(priv->pp_rxskb);
Sachin Kamat875d2a12013-10-09 15:58:30 +05302006 priv->pp_rxskb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002007 }
2008}
2009#else
2010void rtl8192_usb_deleteendpoints(struct net_device *dev)
2011{
2012 int i;
2013 struct r8192_priv *priv = ieee80211_priv(dev);
2014
2015#ifndef JACKSON_NEW_RX
2016
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002017 if (priv->rx_urb) {
2018 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002019 usb_kill_urb(priv->rx_urb[i]);
2020 kfree(priv->rx_urb[i]->transfer_buffer);
2021 usb_free_urb(priv->rx_urb[i]);
2022 }
2023 kfree(priv->rx_urb);
2024 priv->rx_urb = NULL;
2025
2026 }
2027#else
Ilia Mirkine72714f2011-03-13 00:29:07 -05002028 kfree(priv->rx_urb);
2029 priv->rx_urb = NULL;
2030 kfree(priv->oldaddr);
2031 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002032 if (priv->pp_rxskb) {
2033 kfree(priv->pp_rxskb);
2034 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002035
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002036 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002037
2038#endif
2039}
2040#endif
2041
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002042extern void rtl8192_update_ratr_table(struct net_device *dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002043void rtl8192_link_change(struct net_device *dev)
2044{
Jerry Chuang8fc85982009-11-03 07:17:11 -02002045 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002046 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002047 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002048 rtl8192_net_update(dev);
2049 rtl8192_update_ratr_table(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002050 //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
2051 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002052 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002053 }
2054 /*update timing params*/
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002055 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002056 u32 reg = 0;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002057 read_nic_dword(dev, RCR, &reg);
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002058 if (priv->ieee80211->state == IEEE80211_LINKED)
2059 priv->ReceiveConfig = reg |= RCR_CBSSID;
2060 else
2061 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
2062 write_nic_dword(dev, RCR, reg);
2063 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002064}
2065
2066static struct ieee80211_qos_parameters def_qos_parameters = {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002067 {3, 3, 3, 3},/* cw_min */
2068 {7, 7, 7, 7},/* cw_max */
2069 {2, 2, 2, 2},/* aifs */
2070 {0, 0, 0, 0},/* flags */
2071 {0, 0, 0, 0} /* tx_op_limit */
Jerry Chuang8fc85982009-11-03 07:17:11 -02002072};
2073
2074
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002075void rtl8192_update_beacon(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002076{
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002077 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
2078 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002079 struct ieee80211_device *ieee = priv->ieee80211;
2080 struct ieee80211_network *net = &ieee->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002081
2082 if (ieee->pHTInfo->bCurrentHTSupport)
2083 HTUpdateSelfAndPeerSetting(ieee, net);
2084 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
2085 rtl8192_update_cap(dev, net->capability);
2086}
2087/*
2088* background support to run QoS activate functionality
2089*/
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002090int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, EDCAPARA_VO};
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002091void rtl8192_qos_activate(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002092{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002093 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
2094 struct net_device *dev = priv->ieee80211->dev;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002095 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2096 u8 mode = priv->ieee80211->current_network.mode;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002097 u8 u1bAIFS;
2098 u32 u4bAcParam;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002099 int i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002100
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002101 if (priv == NULL)
2102 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002103
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002104 mutex_lock(&priv->mutex);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002105 if (priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002106 goto success;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002107 RT_TRACE(COMP_QOS, "qos active process with associate response received\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002108 /* It better set slot time at first */
2109 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2110 /* update the ac parameter to related registers */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002111 for (i = 0; i < QOS_QUEUE_NUM; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002112 //Mode G/A: slotTimeTimer = 9; Mode B: 20
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002113 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002114 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002115 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2116 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2117 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002118
2119 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002120 }
2121
2122success:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002123 mutex_unlock(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002124}
2125
2126static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002127 int active_network,
2128 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002129{
2130 int ret = 0;
2131 u32 size = sizeof(struct ieee80211_qos_parameters);
2132
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002133 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002134 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002135
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002136 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2137 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002138
2139 if (network->flags & NETWORK_HAS_QOS_MASK) {
2140 if (active_network &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002141 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
Jerry Chuang8fc85982009-11-03 07:17:11 -02002142 network->qos_data.active = network->qos_data.supported;
2143
2144 if ((network->qos_data.active == 1) && (active_network == 1) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002145 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2146 (network->qos_data.old_param_count !=
2147 network->qos_data.param_count)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002148 network->qos_data.old_param_count =
2149 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002150 queue_work(priv->priv_wq, &priv->qos_activate);
Xenia Ragiadakoue6367212013-05-23 05:14:46 +03002151 RT_TRACE(COMP_QOS, "QoS parameters change call "
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002152 "qos_activate\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002153 }
2154 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002155 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002156 &def_qos_parameters, size);
2157
2158 if ((network->qos_data.active == 1) && (active_network == 1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002159 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002160 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2161 }
2162 network->qos_data.active = 0;
2163 network->qos_data.supported = 0;
2164 }
2165
2166 return 0;
2167}
2168
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002169/* handle and manage frame from beacon and probe response */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002170static int rtl8192_handle_beacon(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002171 struct ieee80211_beacon *beacon,
2172 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002173{
2174 struct r8192_priv *priv = ieee80211_priv(dev);
2175
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002176 rtl8192_qos_handle_probe_response(priv, 1, network);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002177 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002178 return 0;
2179
2180}
2181
2182/*
2183* handling the beaconing responses. if we get different QoS setting
2184* off the network from the associated setting, adjust the QoS
2185* setting
2186*/
2187static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002188 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002189{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002190 int ret = 0;
2191 unsigned long flags;
2192 u32 size = sizeof(struct ieee80211_qos_parameters);
2193 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002194
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002195 if ((priv == NULL) || (network == NULL))
2196 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002197
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002198 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002199 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002200
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002201 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2202 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002203
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002204 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002205 if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002206 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002207 &network->qos_data.parameters,
2208 sizeof(struct ieee80211_qos_parameters));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002209 priv->ieee80211->current_network.qos_data.active = 1;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002210 set_qos_param = 1;
2211 /* update qos parameter for current network */
2212 priv->ieee80211->current_network.qos_data.old_param_count =
2213 priv->ieee80211->current_network.qos_data.param_count;
2214 priv->ieee80211->current_network.qos_data.param_count =
2215 network->qos_data.param_count;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002216 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002217 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002218 &def_qos_parameters, size);
2219 priv->ieee80211->current_network.qos_data.active = 0;
2220 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002221 set_qos_param = 1;
2222 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002223
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002224 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002225
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002226 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 -02002227 if (set_qos_param == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002228 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002229
2230
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002231 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002232}
2233
2234
2235static int rtl8192_handle_assoc_response(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002236 struct ieee80211_assoc_response_frame *resp,
2237 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002238{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002239 struct r8192_priv *priv = ieee80211_priv(dev);
2240 rtl8192_qos_association_resp(priv, network);
2241 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002242}
2243
2244
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002245void rtl8192_update_ratr_table(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002246{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002247 struct r8192_priv *priv = ieee80211_priv(dev);
2248 struct ieee80211_device *ieee = priv->ieee80211;
2249 u8 *pMcsRate = ieee->dot11HTOperationalRateSet;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002250 u32 ratr_value = 0;
2251 u8 rate_index = 0;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002252 rtl8192_config_rate(dev, (u16 *)(&ratr_value));
2253 ratr_value |= (*(u16 *)(pMcsRate)) << 12;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002254 switch (ieee->mode) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002255 case IEEE_A:
2256 ratr_value &= 0x00000FF0;
2257 break;
2258 case IEEE_B:
2259 ratr_value &= 0x0000000F;
2260 break;
2261 case IEEE_G:
2262 ratr_value &= 0x00000FF7;
2263 break;
2264 case IEEE_N_24G:
2265 case IEEE_N_5G:
2266 if (ieee->pHTInfo->PeerMimoPs == 0) {//MIMO_PS_STATIC
2267 ratr_value &= 0x0007F007;
2268 } else {
2269 if (priv->rf_type == RF_1T2R)
2270 ratr_value &= 0x000FF007;
2271 else
2272 ratr_value &= 0x0F81F007;
2273 }
2274 break;
2275 default:
2276 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002277 }
2278 ratr_value &= 0x0FFFFFFF;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002279 if (ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002280 ratr_value |= 0x80000000;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002281 else if (!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002282 ratr_value |= 0x80000000;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002283 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2284 write_nic_byte(dev, UFWP, 1);
2285}
2286
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002287static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04};
Jerry Chuang8fc85982009-11-03 07:17:11 -02002288static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
Teodora Baluta46326d22013-10-16 01:59:17 +03002289static bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002290{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002291 struct r8192_priv *priv = ieee80211_priv(dev);
2292 struct ieee80211_device *ieee = priv->ieee80211;
2293 struct ieee80211_network *network = &ieee->current_network;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002294 int wpa_ie_len = ieee->wpa_ie_len;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002295 struct ieee80211_crypt_data *crypt;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002296 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002297
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002298 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002299 //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 +03002300 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 -02002301
2302 /* simply judge */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002303 if (encrypt && (wpa_ie_len == 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002304 /* wep encryption, no N mode setting */
2305 return false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002306 } else if ((wpa_ie_len != 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002307 /* parse pairwise key type */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002308 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 -02002309 return true;
2310 else
2311 return false;
2312 } else {
2313 return true;
2314 }
2315
Jerry Chuang8fc85982009-11-03 07:17:11 -02002316 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002317}
2318
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002319bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002320{
2321 bool Reval;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002322 struct r8192_priv *priv = ieee80211_priv(dev);
2323 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002324
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002325 if (ieee->bHalfWirelessN24GMode == true)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002326 Reval = true;
2327 else
2328 Reval = false;
2329
2330 return Reval;
2331}
2332
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002333void rtl8192_refresh_supportrate(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002334{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002335 struct ieee80211_device *ieee = priv->ieee80211;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002336 //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002337 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002338 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002339 else
2340 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2341 return;
2342}
2343
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002344u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002345{
2346 struct r8192_priv *priv = ieee80211_priv(dev);
2347 u8 ret = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002348 switch (priv->rf_chip) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002349 case RF_8225:
2350 case RF_8256:
2351 case RF_PSEUDO_11N:
2352 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2353 break;
2354 case RF_8258:
2355 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2356 break;
2357 default:
2358 ret = WIRELESS_MODE_B;
2359 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002360 }
2361 return ret;
2362}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002363void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002364{
2365 struct r8192_priv *priv = ieee80211_priv(dev);
2366 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2367
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002368 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode) == 0)) {
2369 if (bSupportMode & WIRELESS_MODE_N_24G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002370 wireless_mode = WIRELESS_MODE_N_24G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002371 } else if (bSupportMode & WIRELESS_MODE_N_5G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002372 wireless_mode = WIRELESS_MODE_N_5G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002373 } else if ((bSupportMode & WIRELESS_MODE_A)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002374 wireless_mode = WIRELESS_MODE_A;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002375 } else if ((bSupportMode & WIRELESS_MODE_G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002376 wireless_mode = WIRELESS_MODE_G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002377 } else if ((bSupportMode & WIRELESS_MODE_B)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002378 wireless_mode = WIRELESS_MODE_B;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002379 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002380 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __func__, bSupportMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002381 wireless_mode = WIRELESS_MODE_B;
2382 }
2383 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002384#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 +03002385 ActUpdateChannelAccessSetting(pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002386#endif
2387 priv->ieee80211->mode = wireless_mode;
2388
2389 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2390 priv->ieee80211->pHTInfo->bEnableHT = 1;
2391 else
2392 priv->ieee80211->pHTInfo->bEnableHT = 0;
2393 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2394 rtl8192_refresh_supportrate(priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002395
2396}
2397//init priv variables here. only non_zero value should be initialized here.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002398static void rtl8192_init_priv_variable(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002399{
2400 struct r8192_priv *priv = ieee80211_priv(dev);
2401 u8 i;
2402 priv->card_8192 = NIC_8192U;
2403 priv->chan = 1; //set to channel 1
2404 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2405 priv->ieee80211->iw_mode = IW_MODE_INFRA;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002406 priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002407 priv->retry_rts = DEFAULT_RETRY_RTS;
2408 priv->retry_data = DEFAULT_RETRY_DATA;
2409 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2410 priv->ieee80211->rate = 110; //11 mbps
2411 priv->ieee80211->short_slot = 1;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002412 priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002413 priv->CckPwEnl = 6;
2414 //for silent reset
2415 priv->IrpPendingCount = 1;
2416 priv->ResetProgress = RESET_TYPE_NORESET;
2417 priv->bForcedSilentReset = 0;
2418 priv->bDisableNormalResetCheck = false;
2419 priv->force_reset = false;
2420
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002421 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002422 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2423 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2424 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2425 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2426 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002427 IEEE_SOFTMAC_BEACONS;//added by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002428
2429 priv->ieee80211->active_scan = 1;
2430 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2431 priv->ieee80211->host_encrypt = 1;
2432 priv->ieee80211->host_decrypt = 1;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002433 priv->ieee80211->start_send_beacons = NULL; //-by amy 080604
2434 priv->ieee80211->stop_send_beacons = NULL; //-by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002435 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2436 priv->ieee80211->set_chan = rtl8192_set_chan;
2437 priv->ieee80211->link_change = rtl8192_link_change;
2438 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2439 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2440 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2441 priv->ieee80211->init_wmmparam_flag = 0;
2442 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2443 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2444 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
2445 priv->ieee80211->qos_support = 1;
2446
2447 //added by WB
Jerry Chuang8fc85982009-11-03 07:17:11 -02002448 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2449 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2450 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2451 //added by david
2452 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
2453 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
2454 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2455 //added by amy
2456 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
2457 priv->card_type = USB;
2458#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002459 if (Adapter->bInHctTest) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002460 pHalData->ShortRetryLimit = 7;
2461 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002462 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002463#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002464 priv->ShortRetryLimit = 0x30;
2465 priv->LongRetryLimit = 0x30;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002466 priv->EarlyRxThreshold = 7;
2467 priv->enable_gpio0 = 0;
2468 priv->TransmitConfig =
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002469 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002470 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
2471 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002472 (false ? TCR_SAT : 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
Jerry Chuang8fc85982009-11-03 07:17:11 -02002473#ifdef TO_DO_LIST
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002474 if (Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002475 pHalData->ReceiveConfig = pHalData->CSMethod |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002476 RCR_AMF | RCR_ADF | //accept management/data
Jerry Chuang8fc85982009-11-03 07:17:11 -02002477 //guangan200710
2478 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2479 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002480 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002481 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2482 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002483 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002484 else
2485
2486#endif
2487 priv->ReceiveConfig =
2488 RCR_AMF | RCR_ADF | //accept management/data
2489 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2490 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Jerry Chuang8fc85982009-11-03 07:17:11 -02002491 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2492 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002493 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002494
2495 priv->AcmControl = 0;
Devendra Nagab7553422012-08-26 11:06:33 +05302496 priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002497
2498 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002499 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002500 skb_queue_head_init(&priv->skb_queue);
2501
2502 /* Tx related queue */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002503 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002504 skb_queue_head_init(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002505 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002506 skb_queue_head_init(&priv->ieee80211->skb_aggQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002507 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002508 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002509 priv->rf_set_chan = rtl8192_phy_SwChnl;
2510}
2511
2512//init lock here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002513static void rtl8192_init_priv_lock(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002514{
2515 spin_lock_init(&priv->tx_lock);
2516 spin_lock_init(&priv->irq_lock);//added by thomas
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002517 sema_init(&priv->wx_sem, 1);
2518 sema_init(&priv->rf_sem, 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002519 mutex_init(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002520}
2521
Jerry Chuang8fc85982009-11-03 07:17:11 -02002522extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002523
2524void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
2525//init tasklet and wait_queue here. only 2.6 above kernel is considered
2526#define DRV_NAME "wlan0"
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002527static void rtl8192_init_priv_task(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002528{
2529 struct r8192_priv *priv = ieee80211_priv(dev);
2530
Jerry Chuang8fc85982009-11-03 07:17:11 -02002531 priv->priv_wq = create_workqueue(DRV_NAME);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002532
Jerry Chuang8fc85982009-11-03 07:17:11 -02002533 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2534
Jerry Chuang8fc85982009-11-03 07:17:11 -02002535 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2536 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002537 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2538 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2539 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002540 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002541
2542 tasklet_init(&priv->irq_rx_tasklet,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002543 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2544 (unsigned long)priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002545}
2546
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002547static void rtl8192_get_eeprom_size(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002548{
2549 u16 curCR = 0;
2550 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002551 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002552 read_nic_word_E(dev, EPROM_CMD, &curCR);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002553 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
2554 //whether need I consider BIT5?
2555 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002556 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __func__, priv->epromtype);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002557}
2558
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002559//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002560static inline u16 endian_swap(u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002561{
2562 u16 tmp = *data;
2563 *data = (tmp >> 8) | (tmp << 8);
2564 return *data;
2565}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002566static void rtl8192_read_eeprom_info(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002567{
2568 u16 wEPROM_ID = 0;
2569 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
2570 u8 bLoad_From_EEPOM = false;
2571 struct r8192_priv *priv = ieee80211_priv(dev);
2572 u16 tmpValue = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002573 int i;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002574 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002575 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
2576 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
2577
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002578 if (wEPROM_ID != RTL8190_EEPROM_ID) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002579 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 +03002580 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002581 bLoad_From_EEPOM = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002582 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002583
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002584 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002585 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
2586 priv->eeprom_vid = endian_swap(&tmpValue);
2587 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
2588 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002589 priv->eeprom_ChannelPlan = ((tmpValue&0xff00)>>8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002590 priv->btxpowerdata_readfromEEPORM = true;
2591 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002592 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002593 priv->eeprom_vid = 0;
2594 priv->eeprom_pid = 0;
2595 priv->card_8192_version = VERSION_819xU_B;
2596 priv->eeprom_ChannelPlan = 0;
2597 priv->eeprom_CustomerID = 0;
2598 }
2599 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);
2600 //set channelplan from eeprom
2601 priv->ChannelPlan = priv->eeprom_ChannelPlan;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002602 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002603 int i;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002604 for (i = 0; i < 6; i += 2) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002605 u16 tmp = 0;
2606 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002607 *(u16 *)(&dev->dev_addr[i]) = tmp;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002608 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002609 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002610 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2611 //should I set IDR0 here?
2612 }
Joe Perches0ee9f672009-12-06 11:34:52 -08002613 RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002614 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
2615 priv->rf_chip = RF_8256;
2616
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002617 if (priv->card_8192_version == (u8)VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002618 //read Tx power gain offset of legacy OFDM to HT rate
2619 if (bLoad_From_EEPOM)
2620 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
2621 else
2622 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
2623 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
2624 //read ThermalMeter from EEPROM
2625 if (bLoad_From_EEPOM)
2626 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
2627 else
2628 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2629 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
2630 //vivi, for tx power track
2631 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2632 //read antenna tx power offset of B/C/D to A from EEPROM
2633 if (bLoad_From_EEPOM)
2634 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
2635 else
2636 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
2637 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
2638 // Read CrystalCap from EEPROM
2639 if (bLoad_From_EEPOM)
2640 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
2641 else
2642 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
2643 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
2644 //get per-channel Tx power level
2645 if (bLoad_From_EEPOM)
2646 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
2647 else
2648 priv->EEPROM_Def_Ver = 1;
2649 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002650 if (priv->EEPROM_Def_Ver == 0) { //old eeprom definition
Jerry Chuang8fc85982009-11-03 07:17:11 -02002651 int i;
2652 if (bLoad_From_EEPOM)
2653 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
2654 else
2655 priv->EEPROMTxPowerLevelCCK = 0x10;
2656 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002657 for (i = 0; i < 3; i++) {
2658 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002659 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
2660 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
2661 tmpValue = tmpValue & 0x00ff;
2662 else
2663 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002664 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002665 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002666 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002667 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
2668 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
2669 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002670 } else if (priv->EEPROM_Def_Ver == 1) {
2671 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002672 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
2673 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002674 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002675 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002676 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002677 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
2678
2679 if (bLoad_From_EEPOM)
2680 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
2681 else
2682 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002683 *((u16 *)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002684 if (bLoad_From_EEPOM)
2685 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
2686 else
2687 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002688 *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002689 if (bLoad_From_EEPOM)
2690 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
2691 else
2692 tmpValue = 0x10;
2693 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
2694 }//endif EEPROM_Def_Ver == 1
2695
2696 //update HAL variables
2697 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002698 for (i = 0; i < 14; i++) {
2699 if (i <= 3)
2700 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
2701 else if (i >= 4 && i <= 9)
2702 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
2703 else
2704 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
2705 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002706
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002707 for (i = 0; i < 14; i++) {
2708 if (priv->EEPROM_Def_Ver == 0) {
2709 if (i <= 3)
2710 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2711 else if (i >= 4 && i <= 9)
2712 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
2713 else
2714 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2715 } else if (priv->EEPROM_Def_Ver == 1) {
2716 if (i <= 3)
2717 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
2718 else if (i >= 4 && i <= 9)
2719 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
2720 else
2721 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002722 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002723 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002724 priv->TxPowerDiff = priv->EEPROMPwDiff;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002725 // Antenna B gain offset to antenna A, bit0~3
Jerry Chuang8fc85982009-11-03 07:17:11 -02002726 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
2727 // Antenna C gain offset to antenna A, bit4~7
2728 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
2729 // CrystalCap, bit12~15
2730 priv->CrystalCap = priv->EEPROMCrystalCap;
2731 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
2732 // 92U does not enable TX power tracking.
2733 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
2734 }//end if VersionID == VERSION_819xU_A
2735
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002736 //added by vivi, for dlink led, 20080416
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002737 switch (priv->eeprom_CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002738 case EEPROM_CID_RUNTOP:
2739 priv->CustomerID = RT_CID_819x_RUNTOP;
2740 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002741
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002742 case EEPROM_CID_DLINK:
2743 priv->CustomerID = RT_CID_DLINK;
2744 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002745
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002746 default:
2747 priv->CustomerID = RT_CID_DEFAULT;
2748 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002749
2750 }
2751
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002752 switch (priv->CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002753 case RT_CID_819x_RUNTOP:
2754 priv->LedStrategy = SW_LED_MODE2;
2755 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002756
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002757 case RT_CID_DLINK:
2758 priv->LedStrategy = SW_LED_MODE4;
2759 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002760
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002761 default:
2762 priv->LedStrategy = SW_LED_MODE0;
2763 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002764
2765 }
2766
2767
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002768 if (priv->rf_type == RF_1T2R) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002769 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002770 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002771 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
2772 }
2773
2774 // 2008/01/16 MH We can only know RF type in the function. So we have to init
2775 // DIG RATR table again.
2776 init_rate_adaptive(dev);
2777 //we need init DIG RATR table here again.
2778
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002779 RT_TRACE(COMP_EPROM, "<===========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002780 return;
2781}
2782
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002783short rtl8192_get_channel_map(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002784{
2785 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002786 if (priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03002787 netdev_err(dev, "rtl8180_init: Error channel plan! Set to default.\n");
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002788 priv->ChannelPlan = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002789 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002790 RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002791
2792 rtl819x_set_channel_map(priv->ChannelPlan, priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002793 return 0;
2794}
2795
2796short rtl8192_init(struct net_device *dev)
2797{
2798
2799 struct r8192_priv *priv = ieee80211_priv(dev);
2800
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002801 memset(&(priv->stats), 0, sizeof(struct Stats));
2802 memset(priv->txqueue_to_outpipemap, 0, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002803#ifdef PIPE12
2804 {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002805 int i = 0;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002806 u8 queuetopipe[] = {3, 2, 1, 0, 4, 8, 7, 6, 5};
2807 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002808 }
2809#else
2810 {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002811 u8 queuetopipe[] = {3, 2, 1, 0, 4, 4, 0, 4, 4};
2812 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002813 }
2814#endif
2815 rtl8192_init_priv_variable(dev);
2816 rtl8192_init_priv_lock(priv);
2817 rtl8192_init_priv_task(dev);
2818 rtl8192_get_eeprom_size(dev);
2819 rtl8192_read_eeprom_info(dev);
2820 rtl8192_get_channel_map(dev);
2821 init_hal_dm(dev);
2822 init_timer(&priv->watch_dog_timer);
2823 priv->watch_dog_timer.data = (unsigned long)dev;
2824 priv->watch_dog_timer.function = watch_dog_timer_callback;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002825 if (rtl8192_usb_initendpoints(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002826 DMESG("Endopoints initialization failed");
2827 return -ENOMEM;
2828 }
2829
Jerry Chuang8fc85982009-11-03 07:17:11 -02002830#ifdef DEBUG_EPROM
2831 dump_eprom(dev);
2832#endif
2833 return 0;
2834}
2835
2836/******************************************************************************
2837 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
2838 * not to do all the hw config as its name says
2839 * input: net_device dev
2840 * output: none
2841 * return: none
2842 * notice: This part need to modified according to the rate set we filtered
2843 * ****************************************************************************/
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002844void rtl8192_hwconfig(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002845{
2846 u32 regRATR = 0, regRRSR = 0;
2847 u8 regBwOpMode = 0, regTmp = 0;
2848 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002849 u32 ratr_value = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002850
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002851 // Set RRSR, RATR, and BW_OPMODE registers
Jerry Chuang8fc85982009-11-03 07:17:11 -02002852 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002853 switch (priv->ieee80211->mode) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002854 case WIRELESS_MODE_B:
2855 regBwOpMode = BW_OPMODE_20MHZ;
2856 regRATR = RATE_ALL_CCK;
2857 regRRSR = RATE_ALL_CCK;
2858 break;
2859 case WIRELESS_MODE_A:
2860 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
2861 regRATR = RATE_ALL_OFDM_AG;
2862 regRRSR = RATE_ALL_OFDM_AG;
2863 break;
2864 case WIRELESS_MODE_G:
2865 regBwOpMode = BW_OPMODE_20MHZ;
2866 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2867 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2868 break;
2869 case WIRELESS_MODE_AUTO:
2870#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002871 if (Adapter->bInHctTest) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002872 regBwOpMode = BW_OPMODE_20MHZ;
2873 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2874 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002875 }
2876 else
2877#endif
2878 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002879 regBwOpMode = BW_OPMODE_20MHZ;
2880 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2881 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002882 }
2883 break;
2884 case WIRELESS_MODE_N_24G:
2885 // It support CCK rate by default.
2886 // CCK rate will be filtered out only when associated AP does not support it.
2887 regBwOpMode = BW_OPMODE_20MHZ;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002888 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2889 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002890 break;
2891 case WIRELESS_MODE_N_5G:
2892 regBwOpMode = BW_OPMODE_5G;
2893 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2894 regRRSR = RATE_ALL_OFDM_AG;
2895 break;
2896 }
2897
2898 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002899 ratr_value = regRATR;
2900 if (priv->rf_type == RF_1T2R)
2901 ratr_value &= ~(RATE_ALL_OFDM_2SS);
2902 write_nic_dword(dev, RATR0, ratr_value);
2903 write_nic_byte(dev, UFWP, 1);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002904 read_nic_byte(dev, 0x313, &regTmp);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002905 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
2906 write_nic_dword(dev, RRSR, regRRSR);
2907
2908 //
2909 // Set Retry Limit here
2910 //
2911 write_nic_word(dev, RETRY_LIMIT,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002912 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
2913 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002914 // Set Contention Window here
2915
2916 // Set Tx AGC
2917
2918 // Set Tx Antenna including Feedback control
2919
2920 // Set Auto Rate fallback control
2921
2922
2923}
2924
2925
2926//InitializeAdapter and PhyCfg
2927bool rtl8192_adapter_start(struct net_device *dev)
2928{
2929 struct r8192_priv *priv = ieee80211_priv(dev);
2930 u32 dwRegRead = 0;
2931 bool init_status = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002932 u8 SECR_value = 0x0;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002933 u8 tmp;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002934 RT_TRACE(COMP_INIT, "====>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002935 priv->Rf_Mode = RF_OP_By_SW_3wire;
2936 //for ASIC power on sequence
2937 write_nic_byte_E(dev, 0x5f, 0x80);
2938 mdelay(50);
2939 write_nic_byte_E(dev, 0x5f, 0xf0);
2940 write_nic_byte_E(dev, 0x5d, 0x00);
2941 write_nic_byte_E(dev, 0x5e, 0x80);
2942 write_nic_byte(dev, 0x17, 0x37);
2943 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002944 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
2945 //config CPUReset Register
2946 //Firmware Reset or not?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002947 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002948 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
2949 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
2950 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
2951 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
2952 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002953 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __func__, priv->pFirmware->firmware_status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002954
2955 write_nic_dword(dev, CPU_GEN, dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002956 //config BB.
2957 rtl8192_BBConfig(dev);
2958
Jerry Chuang8fc85982009-11-03 07:17:11 -02002959 //Loopback mode or not
2960 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002961
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002962 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002963 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
2964 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
2965 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
2966 dwRegRead |= CPU_CCK_LOOPBACK;
2967 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002968 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __func__, priv->LoopbackMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002969
2970 write_nic_dword(dev, CPU_GEN, dwRegRead);
2971
2972 //after reset cpu, we need wait for a seconds to write in register.
2973 udelay(500);
2974
2975 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002976 read_nic_byte_E(dev, 0x5f, &tmp);
2977 write_nic_byte_E(dev, 0x5f, tmp|0x20);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002978
2979 //Set Hardware
2980 rtl8192_hwconfig(dev);
2981
2982 //turn on Tx/Rx
2983 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
2984
2985 //set IDR0 here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002986 write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
2987 write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002988
2989 //set RCR
2990 write_nic_dword(dev, RCR, priv->ReceiveConfig);
2991
2992 //Initialize Number of Reserved Pages in Firmware Queue
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002993 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 +03002994 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT |
2995 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT |
2996 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002997 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 +03002998 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002999 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003000 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003001 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
3002
3003 //Set AckTimeout
3004 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
3005 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
3006
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003007 if (priv->ResetProgress == RESET_TYPE_NORESET)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003008 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003009 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003010 CamResetAllEntry(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003011 SECR_value |= SCR_TxEncEnable;
3012 SECR_value |= SCR_RxDecEnable;
3013 SECR_value |= SCR_NoSKMC;
3014 write_nic_byte(dev, SECR, SECR_value);
3015 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003016
3017 //Beacon related
3018 write_nic_word(dev, ATIMWND, 2);
3019 write_nic_word(dev, BCN_INTERVAL, 100);
3020
Jerry Chuang8fc85982009-11-03 07:17:11 -02003021#define DEFAULT_EDCA 0x005e4332
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003022 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003023 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003024 for (i = 0; i < QOS_QUEUE_NUM; i++)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003025 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003026 }
3027#ifdef USB_RX_AGGREGATION_SUPPORT
3028 //3 For usb rx firmware aggregation control
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003029 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003030 u32 ulValue;
3031 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
3032 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003033 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003034 /*
3035 * If usb rx firmware aggregation is enabled,
3036 * when anyone of three threshold conditions above is reached,
3037 * firmware will send aggregated packet to driver.
3038 */
3039 write_nic_dword(dev, 0x1a8, ulValue);
3040 priv->bCurrentRxAggrEnable = true;
3041 }
3042#endif
3043
3044 rtl8192_phy_configmac(dev);
3045
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003046 if (priv->card_8192_version == (u8) VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003047 rtl8192_phy_getTxPower(dev);
3048 rtl8192_phy_setTxPower(dev, priv->chan);
3049 }
3050
3051 //Firmware download
3052 init_status = init_firmware(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003053 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003054 RT_TRACE(COMP_ERR, "ERR!!! %s(): Firmware download is failed\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003055 return init_status;
3056 }
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003057 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003058 //
3059#ifdef TO_DO_LIST
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003060 if (Adapter->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003061 if (pMgntInfo->RegRfOff == TRUE) { // User disable RF via registry.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003062 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
3063 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003064 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003065 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003066 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003067 } else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { // H/W or S/W RF OFF before sleep.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003068 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
3069 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003070 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003071 pHalData->eRFPowerState = eRfOn;
3072 pMgntInfo->RfOffReason = 0;
3073 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
3074 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003075 } else {
3076 if (pHalData->eRFPowerState == eRfOff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003077 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003078 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003079 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003080 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3081 }
3082 }
3083#endif
3084 //config RF.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003085 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003086 rtl8192_phy_RFConfig(dev);
3087 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003088 }
3089
3090
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003091 if (priv->ieee80211->FwRWRF)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003092 // We can force firmware to do RF-R/W
3093 priv->Rf_Mode = RF_OP_By_FW;
3094 else
3095 priv->Rf_Mode = RF_OP_By_SW_3wire;
3096
3097
3098 rtl8192_phy_updateInitGain(dev);
3099 /*--set CCK and OFDM Block "ON"--*/
3100 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3101 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3102
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003103 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003104 //if D or C cut
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003105 u8 tmpvalue;
3106 read_nic_byte(dev, 0x301, &tmpvalue);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003107 if (tmpvalue == 0x03) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003108 priv->bDcut = TRUE;
3109 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003110 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003111 priv->bDcut = FALSE;
3112 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
3113 }
3114 dm_initialize_txpower_tracking(dev);
3115
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003116 if (priv->bDcut == TRUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003117 u32 i, TempCCk;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003118 u32 tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003119 for (i = 0; i < TxBBGainTableLength; i++) {
3120 if (tmpRegA == priv->txbbgain_table[i].txbbgain_value) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003121 priv->rfa_txpowertrackingindex = (u8)i;
3122 priv->rfa_txpowertrackingindex_real = (u8)i;
3123 priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003124 break;
3125 }
3126 }
3127
3128 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3129
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003130 for (i = 0; i < CCKTxBBGainTableLength; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003131
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003132 if (TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0]) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003133 priv->cck_present_attentuation_20Mdefault = (u8) i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003134 break;
3135 }
3136 }
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003137 priv->cck_present_attentuation_40Mdefault = 0;
3138 priv->cck_present_attentuation_difference = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003139 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
3140
Jerry Chuang8fc85982009-11-03 07:17:11 -02003141 }
3142 }
3143 write_nic_byte(dev, 0x87, 0x0);
3144
3145
Jerry Chuang8fc85982009-11-03 07:17:11 -02003146 return init_status;
3147}
3148
3149/* this configures registers for beacon tx and enables it via
3150 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3151 * be used to stop beacon transmission
3152 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003153/***************************************************************************
3154 -------------------------------NET STUFF---------------------------
3155***************************************************************************/
3156
3157static struct net_device_stats *rtl8192_stats(struct net_device *dev)
3158{
3159 struct r8192_priv *priv = ieee80211_priv(dev);
3160
3161 return &priv->ieee80211->stats;
3162}
3163
Teodora Baluta46326d22013-10-16 01:59:17 +03003164static bool HalTxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003165{
3166 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003167 u16 RegTxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003168 bool bStuck = FALSE;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003169 read_nic_word(dev, 0x128, &RegTxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003170 RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", __func__, RegTxCounter, priv->TxCounter);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003171 if (priv->TxCounter == RegTxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003172 bStuck = TRUE;
3173
3174 priv->TxCounter = RegTxCounter;
3175
3176 return bStuck;
3177}
3178
3179/*
3180* <Assumption: RT_TX_SPINLOCK is acquired.>
3181* First added: 2006.11.19 by emily
3182*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003183RESET_TYPE TxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003184{
3185 struct r8192_priv *priv = ieee80211_priv(dev);
3186 u8 QueueID;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003187 bool bCheckFwTxCnt = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003188
3189 //
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003190 // Decide such threshold according to current power save mode
Jerry Chuang8fc85982009-11-03 07:17:11 -02003191 //
3192
Xenia Ragiadakou7d79ec62013-06-04 23:32:30 +03003193 for (QueueID = 0; QueueID <= BEACON_QUEUE; QueueID++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003194 if (QueueID == TXCMD_QUEUE)
3195 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003196#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003197 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 -02003198#else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003199 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 -02003200#endif
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003201 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003202
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003203 bCheckFwTxCnt = true;
3204 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003205 if (bCheckFwTxCnt) {
3206 if (HalTxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003207 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
3208 return RESET_TYPE_SILENT;
3209 }
3210 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003211 return RESET_TYPE_NORESET;
3212}
3213
Teodora Baluta46326d22013-10-16 01:59:17 +03003214static bool HalRxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003215{
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003216 u16 RegRxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003217 struct r8192_priv *priv = ieee80211_priv(dev);
3218 bool bStuck = FALSE;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003219 static u8 rx_chk_cnt;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003220 read_nic_word(dev, 0x130, &RegRxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003221 RT_TRACE(COMP_RESET, "%s(): RegRxCounter is %d,RxCounter is %d\n", __func__, RegRxCounter, priv->RxCounter);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003222 // If rssi is small, we should check rx for long time because of bad rx.
3223 // or maybe it will continuous silent reset every 2 seconds.
3224 rx_chk_cnt++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003225 if (priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003226 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003227 } else if (priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003228 ((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_40M) ||
3229 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_20M))) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003230 if (rx_chk_cnt < 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003231 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003232 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003233 rx_chk_cnt = 0;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003234 } else if (((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_40M) ||
3235 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_20M)) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003236 priv->undecorated_smoothed_pwdb >= VeryLowRSSI) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003237 if (rx_chk_cnt < 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003238 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003239 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003240 rx_chk_cnt = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003241 } else {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003242 if (rx_chk_cnt < 8)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003243 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003244 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003245 rx_chk_cnt = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003246 }
3247
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003248 if (priv->RxCounter == RegRxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003249 bStuck = TRUE;
3250
3251 priv->RxCounter = RegRxCounter;
3252
3253 return bStuck;
3254}
3255
Teodora Baluta46326d22013-10-16 01:59:17 +03003256static RESET_TYPE RxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003257{
3258 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003259 bool bRxCheck = FALSE;
3260
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003261 if (priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003262 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003263
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003264 if (bRxCheck) {
3265 if (HalRxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003266 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
3267 return RESET_TYPE_SILENT;
3268 }
3269 }
3270 return RESET_TYPE_NORESET;
3271}
3272
3273
3274/**
3275* This function is called by Checkforhang to check whether we should ask OS to reset driver
3276*
3277* \param pAdapter The adapter context for this miniport
3278*
3279* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
3280* to judge whether there is tx stuck.
3281* Note: This function may be required to be rewrite for Vista OS.
3282* <<<Assumption: Tx spinlock has been acquired >>>
3283*
3284* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
3285*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003286RESET_TYPE rtl819x_ifcheck_resetornot(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003287{
3288 struct r8192_priv *priv = ieee80211_priv(dev);
3289 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
3290 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003291 RT_RF_POWER_STATE rfState;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003292
3293 rfState = priv->ieee80211->eRFPowerState;
3294
3295 TxResetType = TxCheckStuck(dev);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003296 if (rfState != eRfOff ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003297 (priv->ieee80211->iw_mode != IW_MODE_ADHOC)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003298 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
3299 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
3300 // if driver is in firmware download failure status, driver should initialize RF in the following
3301 // silent reset procedure Emily, 2008.01.21
3302
3303 // Driver should not check RX stuck in IBSS mode because it is required to
3304 // set Check BSSID in order to send beacon, however, if check BSSID is
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003305 // set, STA cannot hear any packet at all. Emily, 2008.04.12
Jerry Chuang8fc85982009-11-03 07:17:11 -02003306 RxResetType = RxCheckStuck(dev);
3307 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003308 if (TxResetType == RESET_TYPE_NORMAL || RxResetType == RESET_TYPE_NORMAL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003309 return RESET_TYPE_NORMAL;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003310 } else if (TxResetType == RESET_TYPE_SILENT || RxResetType == RESET_TYPE_SILENT) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003311 RT_TRACE(COMP_RESET, "%s():silent reset\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003312 return RESET_TYPE_SILENT;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003313 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003314 return RESET_TYPE_NORESET;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003315 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003316
3317}
3318
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003319void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003320int _rtl8192_up(struct net_device *dev);
3321int rtl8192_close(struct net_device *dev);
3322
3323
3324
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003325void CamRestoreAllEntry(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003326{
3327 u8 EntryId = 0;
3328 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003329 u8 *MacAddr = priv->ieee80211->current_network.bssid;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003330
3331 static u8 CAM_CONST_ADDR[4][6] = {
3332 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3333 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
3334 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03003335 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003336 static u8 CAM_CONST_BROAD[] = {
3337 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003338
3339 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
3340
3341
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003342 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40) ||
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003343 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003344
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003345 for (EntryId = 0; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003346 MacAddr = CAM_CONST_ADDR[EntryId];
3347 setKey(dev, EntryId, EntryId,
3348 priv->ieee80211->pairwise_key_type,
3349 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003350 }
3351
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003352 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003353
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003354 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3355 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3356 (u8 *)dev->dev_addr, 0, NULL);
3357 else
3358 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3359 MacAddr, 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003360 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003361
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003362 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3363 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3364 (u8 *)dev->dev_addr, 0, NULL);
3365 else
3366 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3367 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003368 }
3369
3370
3371
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003372 if (priv->ieee80211->group_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003373 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003374 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003375 setKey(dev, EntryId, EntryId,
3376 priv->ieee80211->group_key_type,
3377 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003378 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003379 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003380 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3381 CAM_CONST_ADDR[0], 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003382 } else if (priv->ieee80211->group_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003383 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003384 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003385 setKey(dev, EntryId, EntryId,
3386 priv->ieee80211->group_key_type,
3387 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003388 }
3389
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003390 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003391 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3392 CAM_CONST_ADDR[0], 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003393 }
3394}
3395//////////////////////////////////////////////////////////////
3396// This function is used to fix Tx/Rx stop bug temporarily.
3397// This function will do "system reset" to NIC when Tx or Rx is stuck.
3398// The method checking Tx/Rx stuck of this function is supported by FW,
3399// which reports Tx and Rx counter to register 0x128 and 0x130.
3400//////////////////////////////////////////////////////////////
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003401void rtl819x_ifsilentreset(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003402{
Jerry Chuang8fc85982009-11-03 07:17:11 -02003403 struct r8192_priv *priv = ieee80211_priv(dev);
3404 u8 reset_times = 0;
3405 int reset_status = 0;
3406 struct ieee80211_device *ieee = priv->ieee80211;
3407
3408
3409 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
3410 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
3411
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003412 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003413RESET_START:
3414
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003415 RT_TRACE(COMP_RESET, "=========>Reset progress!! \n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003416
3417 // Set the variable for reset.
3418 priv->ResetProgress = RESET_TYPE_SILENT;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003419 down(&priv->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003420 if (priv->up == 0) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003421 RT_TRACE(COMP_ERR, "%s():the driver is not up! return\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003422 up(&priv->wx_sem);
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003423 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003424 }
3425 priv->up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003426 RT_TRACE(COMP_RESET, "%s():======>start to down the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003427
3428 rtl8192_rtx_disable(dev);
3429 rtl8192_cancel_deferred_work(priv);
3430 deinit_hal_dm(dev);
3431 del_timer_sync(&priv->watch_dog_timer);
3432
3433 ieee->sync_scan_hurryup = 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003434 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003435 down(&ieee->wx_sem);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003436 netdev_dbg(dev, "ieee->state is IEEE80211_LINKED\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003437 ieee80211_stop_send_beacons(priv->ieee80211);
3438 del_timer_sync(&ieee->associate_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003439 cancel_delayed_work(&ieee->associate_retry_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003440 ieee80211_stop_scan(ieee);
3441 netif_carrier_off(dev);
3442 up(&ieee->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003443 } else {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003444 netdev_dbg(dev, "ieee->state is NOT LINKED\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003445 ieee80211_softmac_stop_protocol(priv->ieee80211);
3446 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003447 up(&priv->wx_sem);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003448 RT_TRACE(COMP_RESET, "%s():<==========down process is finished\n", __func__);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003449 RT_TRACE(COMP_RESET, "%s():===========>start up the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003450 reset_status = _rtl8192_up(dev);
3451
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003452 RT_TRACE(COMP_RESET, "%s():<===========up process is finished\n", __func__);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003453 if (reset_status == -EAGAIN) {
3454 if (reset_times < 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003455 reset_times++;
3456 goto RESET_START;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003457 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003458 RT_TRACE(COMP_ERR, " ERR!!! %s(): Reset Failed!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003459 }
3460 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003461 ieee->is_silent_reset = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003462 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003463 if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003464 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3465
Jerry Chuang8fc85982009-11-03 07:17:11 -02003466 queue_work(ieee->wq, &ieee->associate_complete_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003467
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003468 } else if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003469 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3470 ieee->link_change(ieee->dev);
3471
Jerry Chuang8fc85982009-11-03 07:17:11 -02003472 ieee80211_start_send_beacons(ieee);
3473
3474 if (ieee->data_hard_resume)
3475 ieee->data_hard_resume(ieee->dev);
3476 netif_carrier_on(ieee->dev);
3477 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003478
3479 CamRestoreAllEntry(dev);
3480
3481 priv->ResetProgress = RESET_TYPE_NORESET;
3482 priv->reset_count++;
3483
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003484 priv->bForcedSilentReset = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003485 priv->bResetInProgress = false;
3486
3487 // For test --> force write UFWP.
3488 write_nic_byte(dev, UFWP, 1);
3489 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003490 }
3491}
3492
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003493void CAM_read_entry(struct net_device *dev, u32 iIndex)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003494{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003495 u32 target_command = 0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003496 u32 target_content = 0;
3497 u8 entry_i = 0;
3498 u32 ulStatus;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003499 s32 i = 100;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003500 for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003501 // polling bit, and No Write enable, and address
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003502 target_command = entry_i+CAM_CONTENT_COUNT*iIndex;
3503 target_command = target_command | BIT31;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003504
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003505 //Check polling bit is clear
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003506 while ((i--) >= 0) {
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003507 read_nic_dword(dev, RWCAM, &ulStatus);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003508 if (ulStatus & BIT31)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003509 continue;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003510 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003511 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003512 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003513 write_nic_dword(dev, RWCAM, target_command);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003514 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x \n", target_command);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003515 read_nic_dword(dev, RCAMO, &target_content);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003516 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n", target_content);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003517 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003518 printk("\n");
3519}
3520
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003521void rtl819x_update_rxcounts(struct r8192_priv *priv, u32 *TotalRxBcnNum,
3522 u32 *TotalRxDataNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003523{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003524 u16 SlotIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003525 u8 i;
3526
3527 *TotalRxBcnNum = 0;
3528 *TotalRxDataNum = 0;
3529
3530 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
3531 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
3532 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003533 for (i = 0; i < priv->ieee80211->LinkDetectInfo.SlotNum; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003534 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
3535 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
3536 }
3537}
3538
3539
Himangi Saraogid16e05f2014-03-09 04:21:41 +05303540void rtl819x_watchdog_wqcallback(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003541{
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003542 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003543 struct r8192_priv *priv = container_of(dwork, struct r8192_priv, watch_dog_wq);
3544 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003545 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003546 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003547 static u8 check_reset_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003548 bool bBusyTraffic = false;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003549 u32 TotalRxBcnNum = 0;
3550 u32 TotalRxDataNum = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003551
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003552 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003553 return;
3554 hal_dm_watchdog(dev);
3555
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003556 //to get busy traffic condition
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003557 if (ieee->state == IEEE80211_LINKED) {
3558 if (ieee->LinkDetectInfo.NumRxOkInPeriod > 666 ||
3559 ieee->LinkDetectInfo.NumTxOkInPeriod > 666 ) {
3560 bBusyTraffic = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003561 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003562 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
3563 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
3564 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
3565 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003566 //added by amy for AP roaming
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003567 if (priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003568
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003569 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
3570 if ((TotalRxBcnNum+TotalRxDataNum) == 0) {
3571#ifdef TODO
3572 if (rfState == eRfOff)
3573 RT_TRACE(COMP_ERR, "========>%s()\n", __func__);
3574#endif
3575 netdev_dbg(dev, "===>%s(): AP is power off, connect another one\n", __func__);
3576 priv->ieee80211->state = IEEE80211_ASSOCIATING;
3577 notify_wx_assoc_event(priv->ieee80211);
3578 RemovePeerTS(priv->ieee80211, priv->ieee80211->current_network.bssid);
3579 priv->ieee80211->link_change(dev);
3580 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003581
Jerry Chuang8fc85982009-11-03 07:17:11 -02003582 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003583 }
3584 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod = 0;
3585 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003586 //check if reset the driver
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003587 if (check_reset_cnt++ >= 3) {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003588 ResetType = rtl819x_ifcheck_resetornot(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003589 check_reset_cnt = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003590 }
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003591 if ((priv->force_reset) || (priv->ResetProgress == RESET_TYPE_NORESET &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003592 (priv->bForcedSilentReset ||
3593 (!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_SILENT)))) { // This is control by OID set in Pomelo
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003594 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 -02003595 rtl819x_ifsilentreset(dev);
3596 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003597 priv->force_reset = false;
3598 priv->bForcedSilentReset = false;
3599 priv->bResetInProgress = false;
3600 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
3601
3602}
3603
3604void watch_dog_timer_callback(unsigned long data)
3605{
3606 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003607 queue_delayed_work(priv->priv_wq, &priv->watch_dog_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003608 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
Jerry Chuang8fc85982009-11-03 07:17:11 -02003609}
3610int _rtl8192_up(struct net_device *dev)
3611{
3612 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003613 int init_status = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003614 priv->up = 1;
3615 priv->ieee80211->ieee_up = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003616 RT_TRACE(COMP_INIT, "Bringing up iface");
3617 init_status = rtl8192_adapter_start(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003618 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003619 RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization failed!\n", __func__);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003620 priv->up = priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003621 return -EAGAIN;
3622 }
3623 RT_TRACE(COMP_INIT, "start adapter finished\n");
3624 rtl8192_rx_enable(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003625 if (priv->ieee80211->state != IEEE80211_LINKED)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003626 ieee80211_softmac_start_protocol(priv->ieee80211);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003627 ieee80211_reset_queue(priv->ieee80211);
3628 watch_dog_timer_callback((unsigned long) dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003629 if (!netif_queue_stopped(dev))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003630 netif_start_queue(dev);
3631 else
3632 netif_wake_queue(dev);
3633
3634 return 0;
3635}
3636
3637
3638int rtl8192_open(struct net_device *dev)
3639{
3640 struct r8192_priv *priv = ieee80211_priv(dev);
3641 int ret;
3642 down(&priv->wx_sem);
3643 ret = rtl8192_up(dev);
3644 up(&priv->wx_sem);
3645 return ret;
3646
3647}
3648
3649
3650int rtl8192_up(struct net_device *dev)
3651{
3652 struct r8192_priv *priv = ieee80211_priv(dev);
3653
3654 if (priv->up == 1) return -1;
3655
3656 return _rtl8192_up(dev);
3657}
3658
3659
3660int rtl8192_close(struct net_device *dev)
3661{
3662 struct r8192_priv *priv = ieee80211_priv(dev);
3663 int ret;
3664
3665 down(&priv->wx_sem);
3666
3667 ret = rtl8192_down(dev);
3668
3669 up(&priv->wx_sem);
3670
3671 return ret;
3672
3673}
3674
3675int rtl8192_down(struct net_device *dev)
3676{
3677 struct r8192_priv *priv = ieee80211_priv(dev);
3678 int i;
3679
3680 if (priv->up == 0) return -1;
3681
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003682 priv->up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003683 priv->ieee80211->ieee_up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003684 RT_TRACE(COMP_DOWN, "==========>%s()\n", __func__);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003685 /* FIXME */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003686 if (!netif_queue_stopped(dev))
3687 netif_stop_queue(dev);
3688
3689 rtl8192_rtx_disable(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003690
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003691 /* Tx related queue release */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003692 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003693 skb_queue_purge(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003694 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003695 skb_queue_purge(&priv->ieee80211->skb_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003696
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003697 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003698 skb_queue_purge(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003699
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003700 //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 -02003701 rtl8192_cancel_deferred_work(priv);
3702 deinit_hal_dm(dev);
3703 del_timer_sync(&priv->watch_dog_timer);
3704
3705
3706 ieee80211_softmac_stop_protocol(priv->ieee80211);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003707 memset(&priv->ieee80211->current_network, 0, offsetof(struct ieee80211_network, list));
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003708 RT_TRACE(COMP_DOWN, "<==========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003709
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003710 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003711}
3712
3713
3714void rtl8192_commit(struct net_device *dev)
3715{
3716 struct r8192_priv *priv = ieee80211_priv(dev);
3717 int reset_status = 0;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003718 if (priv->up == 0) return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003719 priv->up = 0;
3720
3721 rtl8192_cancel_deferred_work(priv);
3722 del_timer_sync(&priv->watch_dog_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003723
3724 ieee80211_softmac_stop_protocol(priv->ieee80211);
3725
Jerry Chuang8fc85982009-11-03 07:17:11 -02003726 rtl8192_rtx_disable(dev);
3727 reset_status = _rtl8192_up(dev);
3728
3729}
3730
Jerry Chuang8fc85982009-11-03 07:17:11 -02003731void rtl8192_restart(struct work_struct *work)
3732{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003733 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
3734 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003735
3736 down(&priv->wx_sem);
3737
3738 rtl8192_commit(dev);
3739
3740 up(&priv->wx_sem);
3741}
3742
3743static void r8192_set_multicast(struct net_device *dev)
3744{
3745 struct r8192_priv *priv = ieee80211_priv(dev);
3746 short promisc;
3747
Jerry Chuang8fc85982009-11-03 07:17:11 -02003748 /* FIXME FIXME */
3749
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003750 promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003751
3752 if (promisc != priv->promisc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003753
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003754 priv->promisc = promisc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003755}
3756
3757
3758int r8192_set_mac_adr(struct net_device *dev, void *mac)
3759{
3760 struct r8192_priv *priv = ieee80211_priv(dev);
3761 struct sockaddr *addr = mac;
3762
3763 down(&priv->wx_sem);
3764
3765 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
3766
Jerry Chuang8fc85982009-11-03 07:17:11 -02003767 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003768 up(&priv->wx_sem);
3769
3770 return 0;
3771}
3772
3773/* based on ipw2200 driver */
3774int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3775{
3776 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3777 struct iwreq *wrq = (struct iwreq *)rq;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003778 int ret = -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003779 struct ieee80211_device *ieee = priv->ieee80211;
3780 u32 key[4];
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003781 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003782 struct iw_point *p = &wrq->u.data;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03003783 struct ieee_param *ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003784
3785 down(&priv->wx_sem);
3786
3787
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003788 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
3789 ret = -EINVAL;
3790 goto out;
3791 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003792
Teodora Baluta38272d22013-10-25 11:27:09 +03003793 ipw = memdup_user(p->pointer, p->length);
3794 if (IS_ERR(ipw)) {
3795 ret = PTR_ERR(ipw);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003796 goto out;
3797 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003798
3799 switch (cmd) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003800 case RTL_IOCTL_WPA_SUPPLICANT:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003801 //parse here for HW security
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003802 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) {
3803 if (ipw->u.crypt.set_tx) {
3804 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003805 ieee->pairwise_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003806 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003807 ieee->pairwise_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003808 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003809 if (ipw->u.crypt.key_len == 13)
3810 ieee->pairwise_key_type = KEY_TYPE_WEP104;
3811 else if (ipw->u.crypt.key_len == 5)
3812 ieee->pairwise_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003813 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003814 ieee->pairwise_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003815 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003816
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003817 if (ieee->pairwise_key_type) {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003818 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003819 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003820 //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!
3821 //added by WB.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003822 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 +01003823 if (ieee->auth_mode != 2)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003824 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 -02003825 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003826 } else {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003827 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003828 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003829 ieee->group_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003830 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003831 ieee->group_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003832 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003833 if (ipw->u.crypt.key_len == 13)
3834 ieee->group_key_type = KEY_TYPE_WEP104;
3835 else if (ipw->u.crypt.key_len == 5)
3836 ieee->group_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003837 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003838 ieee->group_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003839 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003840
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003841 if (ieee->group_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003842 setKey(dev, ipw->u.crypt.idx,
3843 ipw->u.crypt.idx, //KeyIndex
3844 ieee->group_key_type, //KeyType
3845 broadcast_addr, //MacAddr
3846 0, //DefaultKey
3847 key); //KeyContent
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003848 }
3849 }
3850 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003851 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
3852 break;
3853
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003854 default:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003855 ret = -EOPNOTSUPP;
3856 break;
3857 }
3858 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003859 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003860out:
3861 up(&priv->wx_sem);
3862 return ret;
3863}
3864
3865u8 HwRateToMRate90(bool bIsHT, u8 rate)
3866{
3867 u8 ret_rate = 0xff;
3868
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003869 if (!bIsHT) {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003870 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003871 case DESC90_RATE1M: ret_rate = MGN_1M; break;
3872 case DESC90_RATE2M: ret_rate = MGN_2M; break;
3873 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
3874 case DESC90_RATE11M: ret_rate = MGN_11M; break;
3875 case DESC90_RATE6M: ret_rate = MGN_6M; break;
3876 case DESC90_RATE9M: ret_rate = MGN_9M; break;
3877 case DESC90_RATE12M: ret_rate = MGN_12M; break;
3878 case DESC90_RATE18M: ret_rate = MGN_18M; break;
3879 case DESC90_RATE24M: ret_rate = MGN_24M; break;
3880 case DESC90_RATE36M: ret_rate = MGN_36M; break;
3881 case DESC90_RATE48M: ret_rate = MGN_48M; break;
3882 case DESC90_RATE54M: ret_rate = MGN_54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003883
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003884 default:
3885 ret_rate = 0xff;
3886 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
3887 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003888 }
3889
3890 } else {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003891 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003892 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
3893 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
3894 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
3895 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
3896 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
3897 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
3898 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
3899 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
3900 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
3901 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
3902 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
3903 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
3904 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
3905 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
3906 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
3907 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
3908 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003909
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003910 default:
3911 ret_rate = 0xff;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003912 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003913 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003914 }
3915 }
3916
3917 return ret_rate;
3918}
3919
3920/**
3921 * Function: UpdateRxPktTimeStamp
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003922 * Overview: Record the TSF time stamp when receiving a packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02003923 *
3924 * Input:
3925 * PADAPTER Adapter
3926 * PRT_RFD pRfd,
3927 *
3928 * Output:
3929 * PRT_RFD pRfd
3930 * (pRfd->Status.TimeStampHigh is updated)
3931 * (pRfd->Status.TimeStampLow is updated)
3932 * Return:
3933 * None
3934 */
Teodora Baluta46326d22013-10-16 01:59:17 +03003935static void UpdateRxPktTimeStamp8190(struct net_device *dev,
3936 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003937{
3938 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3939
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003940 if (stats->bIsAMPDU && !stats->bFirstMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003941 stats->mac_time[0] = priv->LastRxDescTSFLow;
3942 stats->mac_time[1] = priv->LastRxDescTSFHigh;
3943 } else {
3944 priv->LastRxDescTSFLow = stats->mac_time[0];
3945 priv->LastRxDescTSFHigh = stats->mac_time[1];
3946 }
3947}
3948
3949//by amy 080606
3950
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003951long rtl819x_translate_todbm(u8 signal_strength_index)// 0-100 index.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003952{
3953 long signal_power; // in dBm.
3954
3955 // Translate to dBm (x=0.5y-95).
3956 signal_power = (long)((signal_strength_index + 1) >> 1);
3957 signal_power -= 95;
3958
3959 return signal_power;
3960}
3961
3962
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003963/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
Jerry Chuang8fc85982009-11-03 07:17:11 -02003964 be a local static. Otherwise, it may increase when we return from S3/S4. The
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003965 value will be kept in memory or disk. Declare the value in the adaptor
3966 and it will be reinitialized when returned from S3/S4. */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003967void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer, struct ieee80211_rx_stats *pprevious_stats, struct ieee80211_rx_stats *pcurrent_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003968{
3969 bool bcheck = false;
3970 u8 rfpath;
3971 u32 nspatial_stream, tmp_val;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003972 static u32 slide_rssi_index, slide_rssi_statistics;
3973 static u32 slide_evm_index, slide_evm_statistics;
3974 static u32 last_rssi, last_evm;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003975
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003976 static u32 slide_beacon_adc_pwdb_index, slide_beacon_adc_pwdb_statistics;
3977 static u32 last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003978
3979 struct ieee80211_hdr_3addr *hdr;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003980 u16 sc;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003981 unsigned int frag, seq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003982 hdr = (struct ieee80211_hdr_3addr *)buffer;
3983 sc = le16_to_cpu(hdr->seq_ctl);
3984 frag = WLAN_GET_SEQ_FRAG(sc);
3985 seq = WLAN_GET_SEQ_SEQ(sc);
3986 //cosa add 04292008 to record the sequence number
3987 pcurrent_stats->Seq_Num = seq;
3988 //
3989 // Check whether we should take the previous packet into accounting
3990 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003991 if (!pprevious_stats->bIsAMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003992 // if previous packet is not aggregated packet
3993 bcheck = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003994 }
3995
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003996 if (slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003997 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
3998 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
3999 priv->stats.slide_rssi_total -= last_rssi;
4000 }
4001 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
4002
4003 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004004 if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004005 slide_rssi_index = 0;
4006
4007 // <1> Showed on UI for user, in dbm
4008 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
4009 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
4010 pcurrent_stats->rssi = priv->stats.signal_strength;
4011 //
4012 // If the previous packet does not match the criteria, neglect it
4013 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004014 if (!pprevious_stats->bPacketMatchBSSID) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004015 if (!pprevious_stats->bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004016 return;
4017 }
4018
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004019 if (!bcheck)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004020 return;
4021
4022
4023 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
4024
4025 //
4026 // Check RSSI
4027 //
4028 priv->stats.num_process_phyinfo++;
4029
4030 /* record the general signal strength to the sliding window. */
4031
4032
4033 // <2> Showed on UI for engineering
4034 // hardware does not provide rssi information for each rf path in CCK
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004035 if (!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA)) {
4036 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004037 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
4038 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004039
4040 //Fixed by Jacken 2008-03-20
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004041 if (priv->stats.rx_rssi_percentage[rfpath] == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004042 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004043 if (pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath]) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004044 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004045 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004046 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004047 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004048 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004049 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004050 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004051 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004052 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004053 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 -02004054 }
4055 }
4056
4057
4058 //
4059 // Check PWDB.
4060 //
4061 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004062 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004063 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004064
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004065 if (pprevious_stats->bPacketBeacon) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004066 /* record the beacon pwdb to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004067 if (slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004068 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
4069 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
4070 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004071 }
4072 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
4073 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004074 slide_beacon_adc_pwdb_index++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004075 if (slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004076 slide_beacon_adc_pwdb_index = 0;
4077 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004078 if (pprevious_stats->RxPWDBAll >= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004079 pprevious_stats->RxPWDBAll -= 3;
4080 }
4081
4082 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004083 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004084 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004085
4086
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004087 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004088 if (priv->undecorated_smoothed_pwdb < 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004089 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004090 if (pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004091 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004092 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4093 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004094 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004095 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004096 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004097 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4098 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004099 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004100
4101 }
4102
4103 //
4104 // Check EVM
4105 //
4106 /* record the general EVM to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004107 if (pprevious_stats->SignalQuality) {
4108 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4109 if (slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004110 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
4111 last_evm = priv->stats.slide_evm[slide_evm_index];
4112 priv->stats.slide_evm_total -= last_evm;
4113 }
4114
4115 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
4116
4117 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004118 if (slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004119 slide_evm_index = 0;
4120
4121 // <1> Showed on UI for user, in percentage.
4122 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
4123 priv->stats.signal_quality = tmp_val;
4124 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
4125 priv->stats.last_signal_strength_inpercent = tmp_val;
4126 }
4127
4128 // <2> Showed on UI for engineering
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004129 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4130 for (nspatial_stream = 0; nspatial_stream < 2; nspatial_stream++) { // 2 spatial stream
4131 if (pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004132 if (priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004133 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
Jerry Chuang8fc85982009-11-03 07:17:11 -02004134 priv->stats.rx_evm_percentage[nspatial_stream] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004135 ((priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004136 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004137 }
4138 }
4139 }
4140 }
4141
4142
4143}
4144
4145/*-----------------------------------------------------------------------------
4146 * Function: rtl819x_query_rxpwrpercentage()
4147 *
4148 * Overview:
4149 *
4150 * Input: char antpower
4151 *
4152 * Output: NONE
4153 *
4154 * Return: 0-100 percentage
4155 *
4156 * Revised History:
4157 * When Who Remark
4158 * 05/26/2008 amy Create Version 0 porting from windows code.
4159 *
4160 *---------------------------------------------------------------------------*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004161static u8 rtl819x_query_rxpwrpercentage(char antpower)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004162{
4163 if ((antpower <= -100) || (antpower >= 20))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004164 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004165 else if (antpower >= 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004166 return 100;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004167 else
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004168 return 100 + antpower;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004169
4170} /* QueryRxPwrPercentage */
4171
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004172static u8 rtl819x_evm_dbtopercentage(char value)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004173{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004174 char ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004175
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004176 ret_val = value;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004177
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004178 if (ret_val >= 0)
4179 ret_val = 0;
4180 if (ret_val <= -33)
4181 ret_val = -33;
4182 ret_val = 0 - ret_val;
4183 ret_val *= 3;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004184 if (ret_val == 99)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004185 ret_val = 100;
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004186 return ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004187}
4188//
4189// Description:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004190// We want good-looking for signal strength/quality
Jerry Chuang8fc85982009-11-03 07:17:11 -02004191// 2007/7/19 01:09, by cosa.
4192//
Teodora Baluta46326d22013-10-16 01:59:17 +03004193static long rtl819x_signal_scale_mapping(long currsig)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004194{
4195 long retsig;
4196
4197 // Step 1. Scale mapping.
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004198 if (currsig >= 61 && currsig <= 100)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004199 retsig = 90 + ((currsig - 60) / 4);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004200 else if (currsig >= 41 && currsig <= 60)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004201 retsig = 78 + ((currsig - 40) / 2);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004202 else if (currsig >= 31 && currsig <= 40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004203 retsig = 66 + (currsig - 30);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004204 else if (currsig >= 21 && currsig <= 30)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004205 retsig = 54 + (currsig - 20);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004206 else if (currsig >= 5 && currsig <= 20)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004207 retsig = 42 + (((currsig - 5) * 2) / 3);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004208 else if (currsig == 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004209 retsig = 36;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004210 else if (currsig == 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004211 retsig = 27;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004212 else if (currsig == 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004213 retsig = 18;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004214 else if (currsig == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004215 retsig = 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004216 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004217 retsig = currsig;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004218
4219 return retsig;
4220}
4221
Xenia Ragiadakouf2c3d802013-06-04 23:32:32 +03004222static inline bool rx_hal_is_cck_rate(struct rx_drvinfo_819x_usb *pdrvinfo)
4223{
4224 if (pdrvinfo->RxHT)
4225 return false;
4226
4227 switch (pdrvinfo->RxRate) {
4228 case DESC90_RATE1M:
4229 case DESC90_RATE2M:
4230 case DESC90_RATE5_5M:
4231 case DESC90_RATE11M:
4232 return true;
4233 default:
4234 return false;
4235 }
4236}
4237
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004238static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
4239 struct ieee80211_rx_stats *pstats,
4240 rx_drvinfo_819x_usb *pdrvinfo,
4241 struct ieee80211_rx_stats *precord_stats,
4242 bool bpacket_match_bssid,
4243 bool bpacket_toself,
4244 bool bPacketBeacon,
4245 bool bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004246{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004247 phy_sts_ofdm_819xusb_t *pofdm_buf;
4248 phy_sts_cck_819xusb_t *pcck_buf;
4249 phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004250 u8 *prxpkt;
4251 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004252 char rx_pwr[4], rx_pwr_all = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004253 char rx_snrX, rx_evmX;
4254 u8 evm, pwdb_all;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004255 u32 RSSI, total_rssi = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004256 u8 is_cck_rate = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004257 u8 rf_rx_num = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004258 u8 sq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004259
4260
4261 priv->stats.numqry_phystatus++;
4262
4263 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4264
4265 // Record it for next packet processing
4266 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4267 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4268 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004269 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004270 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4271 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4272
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004273 prxpkt = (u8 *)pdrvinfo;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004274
4275 /* Move pointer to the 16th bytes. Phy status start address. */
4276 prxpkt += sizeof(rx_drvinfo_819x_usb);
4277
4278 /* Initial the cck and ofdm buffer pointer */
4279 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
4280 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
4281
4282 pstats->RxMIMOSignalQuality[0] = -1;
4283 pstats->RxMIMOSignalQuality[1] = -1;
4284 precord_stats->RxMIMOSignalQuality[0] = -1;
4285 precord_stats->RxMIMOSignalQuality[1] = -1;
4286
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004287 if (is_cck_rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004288 //
4289 // (1)Hardware does not provide RSSI for CCK
4290 //
4291
4292 //
4293 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4294 //
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004295 u8 report;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004296
4297 priv->stats.numqry_phystatusCCK++;
4298
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004299 if (!priv->bCckHighPower) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004300 report = pcck_buf->cck_agc_rpt & 0xc0;
4301 report = report>>6;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004302 switch (report) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004303 //Fixed by Jacken from Bryant 2008-03-20
4304 //Original value is -38 , -26 , -14 , -2
4305 //Fixed value is -35 , -23 , -11 , 6
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004306 case 0x3:
4307 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4308 break;
4309 case 0x2:
4310 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4311 break;
4312 case 0x1:
4313 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4314 break;
4315 case 0x0:
4316 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
4317 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004318 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004319 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004320 report = pcck_buf->cck_agc_rpt & 0x60;
4321 report = report>>5;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004322 switch (report) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004323 case 0x3:
4324 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4325 break;
4326 case 0x2:
4327 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4328 break;
4329 case 0x1:
4330 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4331 break;
4332 case 0x0:
4333 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4334 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004335 }
4336 }
4337
4338 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4339 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4340 pstats->RecvSignalPower = pwdb_all;
4341
4342 //
4343 // (3) Get Signal Quality (EVM)
4344 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02004345
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004346 if (pstats->RxPWDBAll > 40) {
4347 sq = 100;
4348 } else {
4349 sq = pcck_buf->sq_rpt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004350
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004351 if (pcck_buf->sq_rpt > 64)
4352 sq = 0;
4353 else if (pcck_buf->sq_rpt < 20)
4354 sq = 100;
4355 else
4356 sq = ((64-sq) * 100) / 44;
4357 }
4358 pstats->SignalQuality = precord_stats->SignalQuality = sq;
4359 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
4360 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004361
4362 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004363 priv->stats.numqry_phystatusHT++;
4364 //
4365 // (1)Get RSSI for HT rate
4366 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004367 for (i = RF90_PATH_A; i < priv->NumTotalRFPath; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004368 // 2008/01/30 MH we will judge RF RX path now.
4369 if (priv->brfpath_rxenable[i])
4370 rf_rx_num++;
4371 else
4372 continue;
4373
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004374 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004375 continue;
4376
4377 //Fixed by Jacken from Bryant 2008-03-20
4378 //Original value is 106
4379 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
4380
4381 //Get Rx snr value in DB
4382 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
4383 rx_snrX = (char)(tmp_rxsnr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004384 rx_snrX /= 2;
4385 priv->stats.rxSNRdB[i] = (long)rx_snrX;
4386
4387 /* Translate DBM to percentage. */
4388 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
4389 total_rssi += RSSI;
4390
4391 /* Record Signal Strength for next packet */
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004392 pstats->RxMIMOSignalStrength[i] = (u8) RSSI;
4393 precord_stats->RxMIMOSignalStrength[i] = (u8) RSSI;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004394 }
4395
4396
4397 //
4398 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4399 //
4400 //Fixed by Jacken from Bryant 2008-03-20
4401 //Original value is 106
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004402 rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1)& 0x7f) -106;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004403 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4404
4405 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4406 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
4407
4408 //
4409 // (3)EVM of HT rate
4410 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004411 if (pdrvinfo->RxHT && pdrvinfo->RxRate >= DESC90_RATEMCS8 &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004412 pdrvinfo->RxRate <= DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004413 max_spatial_stream = 2; //both spatial stream make sense
4414 else
4415 max_spatial_stream = 1; //only spatial stream 1 makes sense
4416
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004417 for (i = 0; i < max_spatial_stream; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004418 tmp_rxevm = pofdm_buf->rxevm_X[i];
4419 rx_evmX = (char)(tmp_rxevm);
4420
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004421 // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004422 // will set the most significant bit to "zero" when doing shifting operation which may change a negative
Jerry Chuang8fc85982009-11-03 07:17:11 -02004423 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
4424 rx_evmX /= 2; //dbm
4425
4426 evm = rtl819x_evm_dbtopercentage(rx_evmX);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004427 if (i == 0) // Fill value in RFD, Get the first spatial stream only
4428 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
4429 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004430 }
4431
4432
4433 /* record rx statistics for debug */
4434 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
4435 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004436 if (pdrvinfo->BW) //40M channel
Jerry Chuang8fc85982009-11-03 07:17:11 -02004437 priv->stats.received_bwtype[1+prxsc->rxsc]++;
4438 else //20M channel
4439 priv->stats.received_bwtype[0]++;
4440 }
4441
4442 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
4443 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004444 if (is_cck_rate) {
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004445 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004446 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004447 // We can judge RX path number now.
4448 if (rf_rx_num != 0)
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004449 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi /= rf_rx_num)));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004450 }
4451} /* QueryRxPhyStatus8190Pci */
4452
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004453void rtl8192_record_rxdesc_forlateruse(struct ieee80211_rx_stats *psrc_stats,
4454 struct ieee80211_rx_stats *ptarget_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004455{
4456 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
4457 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
4458 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
4459}
4460
4461
Teodora Baluta46326d22013-10-16 01:59:17 +03004462static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
4463 struct ieee80211_rx_stats *pstats,
4464 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004465{
4466 // TODO: We must only check packet for current MAC address. Not finish
4467 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004468 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004469 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4470 bool bpacket_match_bssid, bpacket_toself;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004471 bool bPacketBeacon = FALSE, bToSelfBA = FALSE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004472 static struct ieee80211_rx_stats previous_stats;
4473 struct ieee80211_hdr_3addr *hdr;//by amy
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004474 u16 fc, type;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004475
4476 // Get Signal Quality for only RX data queue (but not command queue)
4477
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004478 u8 *tmp_buf;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004479 u8 *praddr;
4480
4481 /* Get MAC frame start address. */
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004482 tmp_buf = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004483
4484 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
4485 fc = le16_to_cpu(hdr->frame_ctl);
4486 type = WLAN_FC_GET_TYPE(fc);
4487 praddr = hdr->addr1;
4488
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004489 /* Check if the received packet is acceptable. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004490 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004491 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
4492 && (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004493 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
4494
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004495 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON)
4496 bPacketBeacon = true;
4497 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK) {
4498 if ((eqMacAddr(praddr, dev->dev_addr)))
4499 bToSelfBA = true;
4500 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004501
Jerry Chuang8fc85982009-11-03 07:17:11 -02004502
4503
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004504 if (bpacket_match_bssid)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004505 priv->stats.numpacket_matchbssid++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004506 if (bpacket_toself)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004507 priv->stats.numpacket_toself++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004508 //
4509 // Process PHY information for previous packet (RSSI/PWDB/EVM)
4510 //
4511 // Because phy information is contained in the last packet of AMPDU only, so driver
4512 // should process phy information of previous packet
4513 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004514 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid, bpacket_toself, bPacketBeacon, bToSelfBA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004515 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
4516
4517}
4518
4519/**
4520* Function: UpdateReceivedRateHistogramStatistics
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004521* Overview: Record the received data rate
Jerry Chuang8fc85982009-11-03 07:17:11 -02004522*
4523* Input:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004524* struct net_device *dev
Jerry Chuang8fc85982009-11-03 07:17:11 -02004525* struct ieee80211_rx_stats *stats
4526*
4527* Output:
4528*
4529* (priv->stats.ReceivedRateHistogram[] is updated)
4530* Return:
4531* None
4532*/
Teodora Baluta46326d22013-10-16 01:59:17 +03004533static void
4534UpdateReceivedRateHistogramStatistics8190(struct net_device *dev,
4535 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004536{
4537 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004538 u32 rcvType = 1; //0: Total, 1:OK, 2:CRC, 3:ICV
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004539 u32 rateIndex;
4540 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02004541
4542
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004543 if (stats->bCRC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004544 rcvType = 2;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004545 else if (stats->bICV)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004546 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004547
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004548 if (stats->bShortPreamble)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004549 preamble_guardinterval = 1;// short
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004550 else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004551 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02004552
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004553 switch (stats->rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004554 //
4555 // CCK rate
4556 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004557 case MGN_1M: rateIndex = 0; break;
4558 case MGN_2M: rateIndex = 1; break;
4559 case MGN_5_5M: rateIndex = 2; break;
4560 case MGN_11M: rateIndex = 3; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004561 //
4562 // Legacy OFDM rate
4563 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004564 case MGN_6M: rateIndex = 4; break;
4565 case MGN_9M: rateIndex = 5; break;
4566 case MGN_12M: rateIndex = 6; break;
4567 case MGN_18M: rateIndex = 7; break;
4568 case MGN_24M: rateIndex = 8; break;
4569 case MGN_36M: rateIndex = 9; break;
4570 case MGN_48M: rateIndex = 10; break;
4571 case MGN_54M: rateIndex = 11; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004572 //
4573 // 11n High throughput rate
4574 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004575 case MGN_MCS0: rateIndex = 12; break;
4576 case MGN_MCS1: rateIndex = 13; break;
4577 case MGN_MCS2: rateIndex = 14; break;
4578 case MGN_MCS3: rateIndex = 15; break;
4579 case MGN_MCS4: rateIndex = 16; break;
4580 case MGN_MCS5: rateIndex = 17; break;
4581 case MGN_MCS6: rateIndex = 18; break;
4582 case MGN_MCS7: rateIndex = 19; break;
4583 case MGN_MCS8: rateIndex = 20; break;
4584 case MGN_MCS9: rateIndex = 21; break;
4585 case MGN_MCS10: rateIndex = 22; break;
4586 case MGN_MCS11: rateIndex = 23; break;
4587 case MGN_MCS12: rateIndex = 24; break;
4588 case MGN_MCS13: rateIndex = 25; break;
4589 case MGN_MCS14: rateIndex = 26; break;
4590 case MGN_MCS15: rateIndex = 27; break;
4591 default: rateIndex = 28; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004592 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004593 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
4594 priv->stats.received_rate_histogram[0][rateIndex]++; //total
4595 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004596}
4597
4598
Teodora Baluta46326d22013-10-16 01:59:17 +03004599static void query_rxdesc_status(struct sk_buff *skb,
4600 struct ieee80211_rx_stats *stats,
4601 bool bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004602{
4603 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004604 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004605 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004606 rx_drvinfo_819x_usb *driver_info = NULL;
4607
4608 //
4609 //Get Rx Descriptor Information
4610 //
4611#ifdef USB_RX_AGGREGATION_SUPPORT
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004612 if (bIsRxAggrSubframe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004613 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004614 stats->Length = desc->Length;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004615 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
4616 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
4617 stats->bICV = desc->ICV;
4618 stats->bCRC = desc->CRC32;
4619 stats->bHwError = stats->bCRC|stats->bICV;
4620 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
4621 } else
4622#endif
4623 {
4624 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
4625
4626 stats->Length = desc->Length;
4627 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004628 stats->RxBufShift = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004629 stats->bICV = desc->ICV;
4630 stats->bCRC = desc->CRC32;
4631 stats->bHwError = stats->bCRC|stats->bICV;
4632 //RTL8190 set this bit to indicate that Hw does not decrypt packet
4633 stats->Decrypted = !desc->SWDec;
4634 }
4635
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004636 if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004637 stats->bHwError = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004638 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004639 stats->bHwError = stats->bCRC|stats->bICV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004640
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004641 if (stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004642 stats->bHwError |= 1;
4643 //
4644 //Get Driver Info
4645 //
4646 // TODO: Need to verify it on FGPA platform
4647 //Driver info are written to the RxBuffer following rx desc
4648 if (stats->RxDrvInfoSize != 0) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004649 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004650 stats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004651 /* unit: 0.5M */
4652 /* TODO */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004653 if (!stats->bHwError) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004654 u8 ret_rate;
4655 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004656 if (ret_rate == 0xff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004657 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
4658 // Special Error Handling here, 2008.05.16, by Emily
4659
4660 stats->bHwError = 1;
4661 stats->rate = MGN_1M; //Set 1M rate by default
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004662 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004663 stats->rate = ret_rate;
4664 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004665 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004666 stats->rate = 0x02;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004667 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004668
4669 stats->bShortPreamble = driver_info->SPLCP;
4670
4671
4672 UpdateReceivedRateHistogramStatistics8190(dev, stats);
4673
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004674 stats->bIsAMPDU = (driver_info->PartAggr == 1);
4675 stats->bFirstMPDU = (driver_info->PartAggr == 1) && (driver_info->FirstAGGR == 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004676 stats->TimeStampLow = driver_info->TSFL;
4677 // xiong mask it, 070514
Jerry Chuang8fc85982009-11-03 07:17:11 -02004678
4679 UpdateRxPktTimeStamp8190(dev, stats);
4680
4681 //
4682 // Rx A-MPDU
4683 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004684 if (driver_info->FirstAGGR == 1 || driver_info->PartAggr == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004685 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004686 driver_info->FirstAGGR, driver_info->PartAggr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004687
4688 }
4689
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004690 skb_pull(skb, sizeof(rx_desc_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004691 //
4692 // Get Total offset of MPDU Frame Body
4693 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004694 if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004695 stats->bShift = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004696 skb_pull(skb, stats->RxBufShift + stats->RxDrvInfoSize);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004697 }
4698
4699#ifdef USB_RX_AGGREGATION_SUPPORT
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004700 /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004701 if (bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004702 skb_pull(skb, 8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004703#endif
4704 /* for debug 2008.5.29 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004705
4706 //added by vivi, for MP, 20080108
4707 stats->RxIs40MHzPacket = driver_info->BW;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004708 if (stats->RxDrvInfoSize != 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004709 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
4710
4711}
4712
4713u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
4714{
4715#ifdef USB_RX_AGGREGATION_SUPPORT
4716 if (bIsRxAggrSubframe)
4717 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
4718 + Status->RxBufShift + 8);
4719 else
4720#endif
4721 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004722 + Status->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004723}
4724
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004725void rtl8192_rx_nomal(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004726{
4727 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004728 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004729 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4730 struct ieee80211_rx_stats stats = {
4731 .signal = 0,
4732 .noise = -98,
4733 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004734 .freq = IEEE80211_24GHZ_BAND,
4735 };
4736 u32 rx_pkt_len = 0;
4737 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
4738 bool unicast_packet = false;
4739#ifdef USB_RX_AGGREGATION_SUPPORT
4740 struct sk_buff *agg_skb = NULL;
4741 u32 TotalLength = 0;
4742 u32 TempDWord = 0;
4743 u32 PacketLength = 0;
4744 u32 PacketOccupiedLendth = 0;
4745 u8 TempByte = 0;
4746 u32 PacketShiftBytes = 0;
4747 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
4748 u8 PaddingBytes = 0;
4749 //add just for testing
4750 u8 testing;
4751
4752#endif
4753
4754 /* 20 is for ps-poll */
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004755 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004756#ifdef USB_RX_AGGREGATION_SUPPORT
4757 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
4758#endif
4759 /* first packet should not contain Rx aggregation header */
4760 query_rxdesc_status(skb, &stats, false);
4761 /* TODO */
4762 /* hardware related info */
4763#ifdef USB_RX_AGGREGATION_SUPPORT
4764 if (TempByte & BIT0) {
4765 agg_skb = skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004766 TotalLength = stats.Length - 4; /*sCrcLng*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02004767 /* though the head pointer has passed this position */
4768 TempDWord = *(u32 *)(agg_skb->data - 4);
4769 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
4770 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004771 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004772 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
4773 }
4774#endif
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004775 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004776 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4777
4778 rx_pkt_len = skb->len;
4779 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4780 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004781 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004782 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004783 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004784 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004785 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004786 /* unicast packet */
4787 unicast_packet = true;
4788 }
4789
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004790 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004791 dev_kfree_skb_any(skb);
4792 } else {
4793 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004794 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004795 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004796 }
4797#ifdef USB_RX_AGGREGATION_SUPPORT
4798 testing = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004799 if (TotalLength > 0) {
4800 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
4801 if ((PacketOccupiedLendth & 0xFF) != 0)
4802 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
4803 PacketOccupiedLendth -= 8;
4804 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
4805 if (agg_skb->len > TempDWord)
4806 skb_pull(agg_skb, TempDWord);
4807 else
4808 agg_skb->len = 0;
4809
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004810 while (agg_skb->len >= GetRxPacketShiftBytes819xUsb(&stats, true)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004811 u8 tmpCRC = 0, tmpICV = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004812 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
4813 tmpCRC = RxDescr->CRC32;
4814 tmpICV = RxDescr->ICV;
4815 memcpy(agg_skb->data, &agg_skb->data[44], 2);
4816 RxDescr->CRC32 = tmpCRC;
4817 RxDescr->ICV = tmpICV;
4818
4819 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
4820 stats.signal = 0;
4821 stats.noise = -98;
4822 stats.rate = 0;
4823 stats.freq = IEEE80211_24GHZ_BAND;
4824 query_rxdesc_status(agg_skb, &stats, true);
4825 PacketLength = stats.Length;
4826
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004827 if (PacketLength > agg_skb->len)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004828 break;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004829 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004830 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004831 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004832 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4833
4834 rx_pkt_len = skb->len;
4835 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4836 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004837 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004838 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004839 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004840 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004841 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004842 /* unicast packet */
4843 unicast_packet = true;
4844 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004845 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004846 dev_kfree_skb_any(skb);
4847 } else {
4848 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004849 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004850 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004851 }
4852 /* should trim the packet which has been copied to target skb */
4853 skb_pull(agg_skb, PacketLength);
4854 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
4855 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
4856 if ((PacketOccupiedLendth & 0xFF) != 0) {
4857 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
4858 if (agg_skb->len > PaddingBytes)
4859 skb_pull(agg_skb, PaddingBytes);
4860 else
4861 agg_skb->len = 0;
4862 }
4863 }
4864 dev_kfree_skb(agg_skb);
4865 }
4866#endif
4867 } else {
4868 priv->stats.rxurberr++;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03004869 netdev_dbg(dev, "actual_length: %d\n", skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004870 dev_kfree_skb_any(skb);
4871 }
4872
4873}
4874
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004875void rtl819xusb_process_received_packet(struct net_device *dev,
4876 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004877{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004878 u8 *frame;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004879 u16 frame_len = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004880 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004881
4882 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
4883 //porting by amy 080508
4884 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
4885 frame = pstats->virtual_address;
4886 frame_len = pstats->packetlength;
4887#ifdef TODO // by amy about HCT
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004888 if (!Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004889 CountRxErrStatistics(Adapter, pRfd);
4890#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004891#ifdef ENABLE_PS //by amy for adding ps function in future
4892 RT_RF_POWER_STATE rtState;
4893 // When RF is off, we should not count the packet for hw/sw synchronize
4894 // reason, ie. there may be a duration while sw switch is changed and hw
4895 // switch is being changed. 2006.12.04, by shien chang.
4896 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8 *)(&rtState));
4897 if (rtState == eRfOff)
4898 return;
4899#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -02004900 priv->stats.rxframgment++;
4901
Jerry Chuang8fc85982009-11-03 07:17:11 -02004902#ifdef TODO
4903 RmMonitorSignalStrength(Adapter, pRfd);
4904#endif
4905 /* 2007/01/16 MH Add RX command packet handle here. */
4906 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
4907 if (rtl819xusb_rx_command_packet(dev, pstats))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004908 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004909
4910#ifdef SW_CRC_CHECK
4911 SwCrcCheck();
4912#endif
4913
4914
4915}
4916
Teodora Baluta46326d22013-10-16 01:59:17 +03004917static void query_rx_cmdpkt_desc_status(struct sk_buff *skb,
4918 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004919{
Jerry Chuang8fc85982009-11-03 07:17:11 -02004920 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004921
4922 //
4923 //Get Rx Descriptor Information
4924 //
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004925 stats->virtual_address = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004926 stats->Length = desc->Length;
4927 stats->RxDrvInfoSize = 0;
4928 stats->RxBufShift = 0;
4929 stats->packetlength = stats->Length-scrclng;
4930 stats->fraglength = stats->packetlength;
4931 stats->fragoffset = 0;
4932 stats->ntotalfrag = 1;
4933}
4934
4935
4936void rtl8192_rx_cmd(struct sk_buff *skb)
4937{
4938 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
4939 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004940 /* TODO */
4941 struct ieee80211_rx_stats stats = {
4942 .signal = 0,
4943 .noise = -98,
4944 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004945 .freq = IEEE80211_24GHZ_BAND,
4946 };
4947
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004948 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004949
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004950 query_rx_cmdpkt_desc_status(skb, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004951 // this is to be done by amy 080508 prfd->queue_id = 1;
4952
4953
4954 //
4955 // Process the command packet received.
4956 //
4957
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004958 rtl819xusb_process_received_packet(dev, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004959
4960 dev_kfree_skb_any(skb);
4961 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004962}
4963
4964void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
4965{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004966 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004967 struct rtl8192_rx_info *info;
4968
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004969 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004970 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004971 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004972 /* Nomal packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004973 case 3:
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004974 priv->IrpPendingCount--;
4975 rtl8192_rx_nomal(skb);
4976 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004977
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004978 /* Command packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004979 case 9:
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004980 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004981 info->out_pipe);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004982
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004983 rtl8192_rx_cmd(skb);
4984 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004985
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004986 default: /* should never get here! */
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004987 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004988 info->out_pipe);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004989 dev_kfree_skb(skb);
4990 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004991
4992 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004993 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004994}
4995
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02004996static const struct net_device_ops rtl8192_netdev_ops = {
4997 .ndo_open = rtl8192_open,
4998 .ndo_stop = rtl8192_close,
4999 .ndo_get_stats = rtl8192_stats,
5000 .ndo_tx_timeout = tx_timeout,
5001 .ndo_do_ioctl = rtl8192_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00005002 .ndo_set_rx_mode = r8192_set_multicast,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005003 .ndo_set_mac_address = r8192_set_mac_adr,
5004 .ndo_validate_addr = eth_validate_addr,
5005 .ndo_change_mtu = eth_change_mtu,
5006 .ndo_start_xmit = ieee80211_xmit,
5007};
Jerry Chuang8fc85982009-11-03 07:17:11 -02005008
5009
5010/****************************************************************************
5011 ---------------------------- USB_STUFF---------------------------
5012*****************************************************************************/
5013
Bill Pemberton25794522012-11-19 13:22:04 -05005014static int rtl8192_usb_probe(struct usb_interface *intf,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005015 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005016{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005017 struct net_device *dev = NULL;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005018 struct r8192_priv *priv = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005019 struct usb_device *udev = interface_to_usbdev(intf);
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005020 int ret;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005021 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005022
5023 dev = alloc_ieee80211(sizeof(struct r8192_priv));
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005024 if (dev == NULL)
5025 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005026
Jerry Chuang8fc85982009-11-03 07:17:11 -02005027 usb_set_intfdata(intf, dev);
5028 SET_NETDEV_DEV(dev, &intf->dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005029 priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005030 priv->ieee80211 = netdev_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005031 priv->udev = udev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005032
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005033 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005034
Jerry Chuang8fc85982009-11-03 07:17:11 -02005035#if WIRELESS_EXT >= 12
5036#if WIRELESS_EXT < 17
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005037 dev->get_wireless_stats = r8192_get_wireless_stats;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005038#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005039 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005040#endif
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005041 dev->type = ARPHRD_ETHER;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005042
5043 dev->watchdog_timeo = HZ*3; //modified by john, 0805
5044
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005045 if (dev_alloc_name(dev, ifname) < 0) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005046 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005047 ifname = "wlan%d";
5048 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005049 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005050
5051 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005052 if (rtl8192_init(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005053 RT_TRACE(COMP_ERR, "Initialization failed");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005054 ret = -ENODEV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005055 goto fail;
5056 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005057 netif_carrier_off(dev);
5058 netif_stop_queue(dev);
5059
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005060 ret = register_netdev(dev);
5061 if (ret)
5062 goto fail2;
5063
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005064 RT_TRACE(COMP_INIT, "dev name=======> %s\n", dev->name);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005065 rtl8192_proc_init_one(dev);
5066
5067
5068 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005069 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005070
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005071fail2:
5072 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005073 kfree(priv->pFirmware);
5074 priv->pFirmware = NULL;
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005075 rtl8192_usb_deleteendpoints(dev);
5076 destroy_workqueue(priv->priv_wq);
5077 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005078fail:
5079 free_ieee80211(dev);
5080
5081 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005082 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005083}
5084
5085//detach all the work and timer structure declared or inititialize in r8192U_init function.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005086void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005087{
5088
Jerry Chuang8fc85982009-11-03 07:17:11 -02005089 cancel_work_sync(&priv->reset_wq);
5090 cancel_delayed_work(&priv->watch_dog_wq);
5091 cancel_delayed_work(&priv->update_beacon_wq);
5092 cancel_work_sync(&priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005093}
5094
5095
Bill Pembertona4a557e2012-11-19 13:26:46 -05005096static void rtl8192_usb_disconnect(struct usb_interface *intf)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005097{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005098 struct net_device *dev = usb_get_intfdata(intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005099
5100 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005101 if (dev) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005102
5103 unregister_netdev(dev);
5104
5105 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
5106 rtl8192_proc_remove_one(dev);
5107
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005108 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005109 kfree(priv->pFirmware);
5110 priv->pFirmware = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005111 rtl8192_usb_deleteendpoints(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005112 destroy_workqueue(priv->priv_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005113 mdelay(10);
5114
5115 }
5116 free_ieee80211(dev);
5117 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
5118}
5119
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005120/* fun with the built-in ieee80211 stack... */
5121extern int ieee80211_debug_init(void);
5122extern void ieee80211_debug_exit(void);
5123extern int ieee80211_crypto_init(void);
5124extern void ieee80211_crypto_deinit(void);
5125extern int ieee80211_crypto_tkip_init(void);
5126extern void ieee80211_crypto_tkip_exit(void);
5127extern int ieee80211_crypto_ccmp_init(void);
5128extern void ieee80211_crypto_ccmp_exit(void);
5129extern int ieee80211_crypto_wep_init(void);
5130extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005131
5132static int __init rtl8192_usb_module_init(void)
5133{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005134 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005135
5136#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005137 ret = ieee80211_debug_init();
5138 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005139 pr_err("ieee80211_debug_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005140 return ret;
5141 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005142#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005143 ret = ieee80211_crypto_init();
5144 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005145 pr_err("ieee80211_crypto_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005146 return ret;
5147 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005148
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005149 ret = ieee80211_crypto_tkip_init();
5150 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005151 pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005152 return ret;
5153 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005154
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005155 ret = ieee80211_crypto_ccmp_init();
5156 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005157 pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005158 return ret;
5159 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005160
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005161 ret = ieee80211_crypto_wep_init();
5162 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005163 pr_err("ieee80211_crypto_wep_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005164 return ret;
5165 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005166
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005167 pr_info("\nLinux kernel driver for RTL8192 based WLAN cards\n");
5168 pr_info("Copyright (c) 2007-2008, Realsil Wlan\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005169 RT_TRACE(COMP_INIT, "Initializing module");
5170 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
5171 rtl8192_proc_module_init();
5172 return usb_register(&rtl8192_usb_driver);
5173}
5174
5175
5176static void __exit rtl8192_usb_module_exit(void)
5177{
5178 usb_deregister(&rtl8192_usb_driver);
5179
5180 RT_TRACE(COMP_DOWN, "Exiting");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005181}
5182
5183
5184void rtl8192_try_wake_queue(struct net_device *dev, int pri)
5185{
5186 unsigned long flags;
5187 short enough_desc;
5188 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5189
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005190 spin_lock_irqsave(&priv->tx_lock, flags);
5191 enough_desc = check_nic_enough_desc(dev, pri);
5192 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005193
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005194 if (enough_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005195 ieee80211_wake_queue(priv->ieee80211);
5196}
5197
5198void EnableHWSecurityConfig8192(struct net_device *dev)
5199{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005200 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005201 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005202 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005203 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005204 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 -02005205 SECR_value |= SCR_RxUseDK;
5206 SECR_value |= SCR_TxUseDK;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005207 } 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 -02005208 SECR_value |= SCR_RxUseDK;
5209 SECR_value |= SCR_TxUseDK;
5210 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005211 //add HWSec active enable here.
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005212 //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 -02005213
5214 ieee->hwsec_active = 1;
5215
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005216 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 -02005217 ieee->hwsec_active = 0;
5218 SECR_value &= ~SCR_RxDecEnable;
5219 }
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03005220 RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __func__,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005221 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
5222 write_nic_byte(dev, SECR, SECR_value);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005223}
5224
5225
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03005226void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
5227 u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005228{
5229 u32 TargetCommand = 0;
5230 u32 TargetContent = 0;
5231 u16 usConfig = 0;
5232 u8 i;
5233 if (EntryNo >= TOTAL_CAM_ENTRY)
5234 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
5235
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005236 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 -02005237
5238 if (DefaultKey)
5239 usConfig |= BIT15 | (KeyType<<2);
5240 else
5241 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005242
5243
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005244 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005245 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
5246 TargetCommand |= BIT31|BIT16;
5247
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005248 if (i == 0) { //MAC|Config
Jerry Chuang8fc85982009-11-03 07:17:11 -02005249 TargetContent = (u32)(*(MacAddr+0)) << 16|
5250 (u32)(*(MacAddr+1)) << 24|
5251 (u32)usConfig;
5252
5253 write_nic_dword(dev, WCAMI, TargetContent);
5254 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005255 } else if (i == 1) { //MAC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005256 TargetContent = (u32)(*(MacAddr+2)) |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005257 (u32)(*(MacAddr+3)) << 8|
5258 (u32)(*(MacAddr+4)) << 16|
5259 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005260 write_nic_dword(dev, WCAMI, TargetContent);
5261 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005262 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005263 //Key Material
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005264 if (KeyContent != NULL) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005265 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)));
5266 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005267 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005268 }
5269 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005270
5271}
5272
5273/***************************************************************************
5274 ------------------- module init / exit stubs ----------------
5275****************************************************************************/
5276module_init(rtl8192_usb_module_init);
5277module_exit(rtl8192_usb_module_exit);