blob: cd0946db025c3c51fd7d98ae46f88f0675606b5c [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
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300395int 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
Jerry Chuang8fc85982009-11-03 07:17:11 -0200588void rtl8192_proc_module_init(void)
589{
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
634void rtl8192_proc_init_one(struct net_device *dev)
635{
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
659void rtl8192_proc_remove_one(struct net_device *dev)
660{
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
758u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
759{
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
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03001001u32 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))) {
1321 if (NULL != (skb = skb_dequeue(&(priv->ieee80211->skb_waitQ[queue_index]))))
1322 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001323
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001324 return; //modified by david to avoid further processing AMSDU
Jerry Chuang8fc85982009-11-03 07:17:11 -02001325 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001326#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001327 else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index]) != 0) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001328 (!(priv->ieee80211->queue_stop))) {
1329 // Tx Driver Aggregation process
1330 /* The driver will aggregation the packets according to the following stats
1331 * 1. check whether there's tx irq available, for it's a completion return
1332 * function, it should contain enough tx irq;
1333 * 2. check packet type;
1334 * 3. initialize sendlist, check whether the to-be send packet no greater than 1
1335 * 4. aggregates the packets, and fill firmware info and tx desc into it, etc.
1336 * 5. check whether the packet could be sent, otherwise just insert into wait head
1337 * */
1338 skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]);
1339 if (!check_nic_enough_desc(dev, queue_index)) {
1340 skb_queue_head(&(priv->ieee80211->skb_drv_aggQ[queue_index]), skb);
1341 return;
1342 }
1343
1344 /*TODO*/
1345 {
1346 struct ieee80211_drv_agg_txb SendList;
1347
1348 memset(&SendList, 0, sizeof(struct ieee80211_drv_agg_txb));
1349 if (DrvAggr_GetAggregatibleList(dev, skb, &SendList) > 1) {
1350 skb = DrvAggr_Aggregation(dev, &SendList);
1351
1352 }
1353 }
1354 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1355 }
1356#endif
1357 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001358
Jerry Chuang8fc85982009-11-03 07:17:11 -02001359}
1360
1361void rtl8192_beacon_stop(struct net_device *dev)
1362{
1363 u8 msr, msrm, msr2;
1364 struct r8192_priv *priv = ieee80211_priv(dev);
1365
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03001366 read_nic_byte(dev, MSR, &msr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001367 msrm = msr & MSR_LINK_MASK;
1368 msr2 = msr & ~MSR_LINK_MASK;
1369
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001370 if (NIC_8192U == priv->card_8192)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001371 usb_kill_urb(priv->rx_urb[MAX_RX_URB]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001372 if ((msrm == (MSR_LINK_ADHOC<<MSR_LINK_SHIFT) ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001373 (msrm == (MSR_LINK_MASTER<<MSR_LINK_SHIFT)))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001374 write_nic_byte(dev, MSR, msr2 | MSR_LINK_NONE);
1375 write_nic_byte(dev, MSR, msr);
1376 }
1377}
1378
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001379void rtl8192_config_rate(struct net_device *dev, u16 *rate_config)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001380{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001381 struct r8192_priv *priv = ieee80211_priv(dev);
1382 struct ieee80211_network *net;
1383 u8 i = 0, basic_rate = 0;
Xenia Ragiadakou003a2d12013-06-04 23:32:29 +03001384 net = &priv->ieee80211->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001385
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001386 for (i = 0; i < net->rates_len; i++) {
1387 basic_rate = net->rates[i]&0x7f;
1388 switch (basic_rate) {
1389 case MGN_1M: *rate_config |= RRSR_1M; break;
1390 case MGN_2M: *rate_config |= RRSR_2M; break;
1391 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1392 case MGN_11M: *rate_config |= RRSR_11M; break;
1393 case MGN_6M: *rate_config |= RRSR_6M; break;
1394 case MGN_9M: *rate_config |= RRSR_9M; break;
1395 case MGN_12M: *rate_config |= RRSR_12M; break;
1396 case MGN_18M: *rate_config |= RRSR_18M; break;
1397 case MGN_24M: *rate_config |= RRSR_24M; break;
1398 case MGN_36M: *rate_config |= RRSR_36M; break;
1399 case MGN_48M: *rate_config |= RRSR_48M; break;
1400 case MGN_54M: *rate_config |= RRSR_54M; break;
1401 }
1402 }
1403 for (i = 0; i < net->rates_ex_len; i++) {
1404 basic_rate = net->rates_ex[i]&0x7f;
1405 switch (basic_rate) {
1406 case MGN_1M: *rate_config |= RRSR_1M; break;
1407 case MGN_2M: *rate_config |= RRSR_2M; break;
1408 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
1409 case MGN_11M: *rate_config |= RRSR_11M; break;
1410 case MGN_6M: *rate_config |= RRSR_6M; break;
1411 case MGN_9M: *rate_config |= RRSR_9M; break;
1412 case MGN_12M: *rate_config |= RRSR_12M; break;
1413 case MGN_18M: *rate_config |= RRSR_18M; break;
1414 case MGN_24M: *rate_config |= RRSR_24M; break;
1415 case MGN_36M: *rate_config |= RRSR_36M; break;
1416 case MGN_48M: *rate_config |= RRSR_48M; break;
1417 case MGN_54M: *rate_config |= RRSR_54M; break;
1418 }
1419 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001420}
1421
1422
1423#define SHORT_SLOT_TIME 9
1424#define NON_SHORT_SLOT_TIME 20
1425
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001426void rtl8192_update_cap(struct net_device *dev, u16 cap)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001427{
1428 u32 tmp = 0;
1429 struct r8192_priv *priv = ieee80211_priv(dev);
1430 struct ieee80211_network *net = &priv->ieee80211->current_network;
1431 priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
1432 tmp = priv->basic_rate;
1433 if (priv->short_preamble)
1434 tmp |= BRSR_AckShortPmb;
1435 write_nic_dword(dev, RRSR, tmp);
1436
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001437 if (net->mode & (IEEE_G|IEEE_N_24G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001438 u8 slot_time = 0;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001439 if ((cap & WLAN_CAPABILITY_SHORT_SLOT) && (!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime)) //short slot time
Jerry Chuang8fc85982009-11-03 07:17:11 -02001440 slot_time = SHORT_SLOT_TIME;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001441 else //long slot time
1442 slot_time = NON_SHORT_SLOT_TIME;
1443 priv->slot_time = slot_time;
1444 write_nic_byte(dev, SLOT_TIME, slot_time);
1445 }
1446
1447}
1448void rtl8192_net_update(struct net_device *dev)
1449{
1450
1451 struct r8192_priv *priv = ieee80211_priv(dev);
1452 struct ieee80211_network *net;
1453 u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
1454 u16 rate_config = 0;
Xenia Ragiadakou003a2d12013-06-04 23:32:29 +03001455 net = &priv->ieee80211->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001456
1457 rtl8192_config_rate(dev, &rate_config);
1458 priv->basic_rate = rate_config &= 0x15f;
1459
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001460 write_nic_dword(dev, BSSIDR, ((u32 *)net->bssid)[0]);
1461 write_nic_word(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001462
1463 rtl8192_update_msr(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001464 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001465 write_nic_word(dev, ATIMWND, 2);
1466 write_nic_word(dev, BCN_DMATIME, 1023);
1467 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
1468 write_nic_word(dev, BCN_DRV_EARLY_INT, 1);
1469 write_nic_byte(dev, BCN_ERR_THRESH, 100);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001470 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001471 // TODO: BcnIFS may required to be changed on ASIC
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001472 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001473
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001474 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001475 }
1476
1477
1478
1479}
1480
1481//temporary hw beacon is not used any more.
1482//open it when necessary
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001483void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001484{
1485
Jerry Chuang8fc85982009-11-03 07:17:11 -02001486}
Jerry Chuang8fc85982009-11-03 07:17:11 -02001487inline u8 rtl8192_IsWirelessBMode(u16 rate)
1488{
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03001489 if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220))
Jerry Chuang8fc85982009-11-03 07:17:11 -02001490 return 1;
1491 else return 0;
1492}
1493
1494u16 N_DBPSOfRate(u16 DataRate);
1495
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03001496u16 ComputeTxTime(u16 FrameLength, u16 DataRate, u8 bManagementFrame,
1497 u8 bShortPreamble)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001498{
1499 u16 FrameTime;
1500 u16 N_DBPS;
1501 u16 Ceiling;
1502
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001503 if (rtl8192_IsWirelessBMode(DataRate)) {
1504 if (bManagementFrame || !bShortPreamble || DataRate == 10) // long preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001505 FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001506 else // Short preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001507 FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03001508 if ((FrameLength*8 % (DataRate/10)) != 0) //Get the Ceilling
Xenia Ragiadakou7d79ec62013-06-04 23:32:30 +03001509 FrameTime++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001510 } else { //802.11g DSSS-OFDM PLCP length field calculation.
1511 N_DBPS = N_DBPSOfRate(DataRate);
1512 Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001513 + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001514 FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
1515 }
1516 return FrameTime;
1517}
1518
1519u16 N_DBPSOfRate(u16 DataRate)
1520{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001521 u16 N_DBPS = 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001522
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001523 switch (DataRate) {
1524 case 60:
1525 N_DBPS = 24;
1526 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001527
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001528 case 90:
1529 N_DBPS = 36;
1530 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001531
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001532 case 120:
1533 N_DBPS = 48;
1534 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001535
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001536 case 180:
1537 N_DBPS = 72;
1538 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001539
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001540 case 240:
1541 N_DBPS = 96;
1542 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001543
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001544 case 360:
1545 N_DBPS = 144;
1546 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001547
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001548 case 480:
1549 N_DBPS = 192;
1550 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001551
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001552 case 540:
1553 N_DBPS = 216;
1554 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001555
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001556 default:
1557 break;
1558 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001559
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001560 return N_DBPS;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001561}
1562
1563void rtl819xU_cmd_isr(struct urb *tx_cmd_urb, struct pt_regs *regs)
1564{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001565 usb_free_urb(tx_cmd_urb);
1566}
1567
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001568unsigned int txqueue2outpipe(struct r8192_priv *priv, unsigned int tx_queue)
1569{
1570 if (tx_queue >= 9) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03001571 RT_TRACE(COMP_ERR, "%s():Unknown queue ID!!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001572 return 0x04;
1573 }
1574 return priv->txqueue_to_outpipemap[tx_queue];
1575}
1576
1577short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
1578{
1579 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001580 int status;
1581 struct urb *tx_urb;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001582 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001583 tx_desc_cmd_819x_usb *pdesc = (tx_desc_cmd_819x_usb *)skb->data;
1584 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1585 u8 queue_index = tcb_desc->queue_index;
1586
Jerry Chuang8fc85982009-11-03 07:17:11 -02001587 atomic_inc(&priv->tx_pending[queue_index]);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001588 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001589 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001590 dev_kfree_skb(skb);
1591 return -ENOMEM;
1592 }
1593
1594 memset(pdesc, 0, USB_HWDESC_HEADER_LEN);
1595 /* Tx descriptor ought to be set according to the skb->cb */
1596 pdesc->FirstSeg = 1;//bFirstSeg;
1597 pdesc->LastSeg = 1;//bLastSeg;
1598 pdesc->CmdInit = tcb_desc->bCmdOrInit;
1599 pdesc->TxBufferSize = tcb_desc->txbuf_size;
1600 pdesc->OWN = 1;
1601 pdesc->LINIP = tcb_desc->bLastIniPkt;
1602
1603 //----------------------------------------------------------------------------
1604 // Fill up USB_OUT_CONTEXT.
1605 //----------------------------------------------------------------------------
1606 // Get index to out pipe from specified QueueID.
1607#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001608 idx_pipe = txqueue2outpipe(priv, queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001609#else
1610 idx_pipe = 0x04;
1611#endif
1612#ifdef JOHN_DUMP_TXDESC
1613 int i;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001614 printk("<Tx descriptor>--rate %x---", rate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001615 for (i = 0; i < 8; i++)
1616 printk("%8x ", tx[i]);
1617 printk("\n");
1618#endif
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03001619 usb_fill_bulk_urb(tx_urb, priv->udev, usb_sndbulkpipe(priv->udev, idx_pipe),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001620 skb->data, skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001621
Jerry Chuang8fc85982009-11-03 07:17:11 -02001622 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001623
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001624 if (!status) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001625 return 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001626 } else {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001627 DMESGE("Error TX CMD URB, error %d", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001628 return -1;
1629 }
1630}
1631
1632/*
1633 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1634 * in TxFwInfo data structure
1635 * 2006.10.30 by Emily
1636 *
1637 * \param QUEUEID Software Queue
1638*/
1639u8 MapHwQueueToFirmwareQueue(u8 QueueID)
1640{
1641 u8 QueueSelect = 0x0; //defualt set to
1642
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001643 switch (QueueID) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001644 case BE_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001645 QueueSelect = QSLT_BE;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001646 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001647
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001648 case BK_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001649 QueueSelect = QSLT_BK;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001650 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001651
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001652 case VO_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001653 QueueSelect = QSLT_VO;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001654 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001655
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001656 case VI_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001657 QueueSelect = QSLT_VI;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001658 break;
1659 case MGNT_QUEUE:
1660 QueueSelect = QSLT_MGNT;
1661 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001662
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001663 case BEACON_QUEUE:
1664 QueueSelect = QSLT_BEACON;
1665 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001666
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001667 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
1668 // TODO: Remove Assertions
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001669 case TXCMD_QUEUE:
1670 QueueSelect = QSLT_CMD;
1671 break;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001672 case HIGH_QUEUE:
1673 QueueSelect = QSLT_HIGH;
1674 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001675
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001676 default:
1677 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
1678 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001679 }
1680 return QueueSelect;
1681}
1682
1683u8 MRateToHwRate8190Pci(u8 rate)
1684{
1685 u8 ret = DESC90_RATE1M;
1686
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001687 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001688 case MGN_1M: ret = DESC90_RATE1M; break;
1689 case MGN_2M: ret = DESC90_RATE2M; break;
1690 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1691 case MGN_11M: ret = DESC90_RATE11M; break;
1692 case MGN_6M: ret = DESC90_RATE6M; break;
1693 case MGN_9M: ret = DESC90_RATE9M; break;
1694 case MGN_12M: ret = DESC90_RATE12M; break;
1695 case MGN_18M: ret = DESC90_RATE18M; break;
1696 case MGN_24M: ret = DESC90_RATE24M; break;
1697 case MGN_36M: ret = DESC90_RATE36M; break;
1698 case MGN_48M: ret = DESC90_RATE48M; break;
1699 case MGN_54M: ret = DESC90_RATE54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001700
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001701 // HT rate since here
1702 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1703 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1704 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1705 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1706 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1707 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1708 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1709 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1710 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1711 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1712 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1713 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1714 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1715 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1716 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1717 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1718 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001719
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001720 default: break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001721 }
1722 return ret;
1723}
1724
1725
1726u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
1727{
1728 u8 tmp_Short;
1729
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001730 tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) : ((tcb_desc->bUseShortPreamble) ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001731
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03001732 if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001733 tmp_Short = 0;
1734
1735 return tmp_Short;
1736}
1737
Jerry Chuang8fc85982009-11-03 07:17:11 -02001738static void tx_zero_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001739{
1740 return;
1741}
1742
1743/*
1744 * The tx procedure is just as following,
1745 * skb->cb will contain all the following information,
1746 * priority, morefrag, rate, &dev.
1747 * */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001748short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001749{
1750 struct r8192_priv *priv = ieee80211_priv(dev);
1751 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1752 tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data;
1753 tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
1754 struct usb_device *udev = priv->udev;
1755 int pend;
1756 int status;
1757 struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001758 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001759 pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]);
1760 /* we are locked here so the two atomic_read and inc are executed
1761 * without interleaves
1762 * !!! For debug purpose
1763 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001764 if (pend > MAX_TX_URB) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001765 netdev_dbg(dev, "To discard skb packet!\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001766 dev_kfree_skb_any(skb);
1767 return -1;
1768 }
1769
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001770 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001771 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001772 dev_kfree_skb_any(skb);
1773 return -ENOMEM;
1774 }
1775
1776 /* Fill Tx firmware info */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001777 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001778 /* DWORD 0 */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001779 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001780 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1781 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1782 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001783 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001784 tx_fwinfo->AllowAggregation = 1;
1785 /* DWORD 1 */
1786 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1787 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1788 } else {
1789 tx_fwinfo->AllowAggregation = 0;
1790 /* DWORD 1 */
1791 tx_fwinfo->RxMF = 0;
1792 tx_fwinfo->RxAMD = 0;
1793 }
1794
1795 /* Protection mode related */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001796 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1797 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1798 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1799 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001800 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001801 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->RTSSC) : 0;
1802 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1) ? ((tcb_desc->bRTSBW) ? 1 : 0) : 0;
1803 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) :
1804 (tcb_desc->bRTSUseShortGI ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001805
1806 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001807 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001808 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001809 tx_fwinfo->TxBandwidth = 1;
1810 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1811 } else {
1812 tx_fwinfo->TxBandwidth = 0;
1813 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1814 }
1815 } else {
1816 tx_fwinfo->TxBandwidth = 0;
1817 tx_fwinfo->TxSubCarrier = 0;
1818 }
1819
1820#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1821 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001822 tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001823#endif
1824 /* Fill Tx descriptor */
1825 memset(tx_desc, 0, sizeof(tx_desc_819x_usb));
1826 /* DWORD 0 */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001827 tx_desc->LINIP = 0;
1828 tx_desc->CmdInit = 1;
1829 tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001830
1831#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001832 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001833 tx_desc->PktSize = tcb_desc->pkt_size;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001834 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02001835#endif
1836 {
1837 tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff;
1838 }
1839
1840 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001841 tx_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001842 tx_desc->RATid = tcb_desc->RATRIndex;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001843 tx_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001844 tx_desc->SecType = 0x0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001845 if (tcb_desc->bHwSec) {
1846 switch (priv->ieee80211->pairwise_key_type) {
1847 case KEY_TYPE_WEP40:
1848 case KEY_TYPE_WEP104:
1849 tx_desc->SecType = 0x1;
1850 tx_desc->NoEnc = 0;
1851 break;
1852 case KEY_TYPE_TKIP:
1853 tx_desc->SecType = 0x2;
1854 tx_desc->NoEnc = 0;
1855 break;
1856 case KEY_TYPE_CCMP:
1857 tx_desc->SecType = 0x3;
1858 tx_desc->NoEnc = 0;
1859 break;
1860 case KEY_TYPE_NA:
1861 tx_desc->SecType = 0x0;
1862 tx_desc->NoEnc = 1;
1863 break;
1864 }
1865 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001866
1867 tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1868 tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1869
1870 tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1871 tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1872
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001873 /* Fill fields that are required to be initialized in all of the descriptors */
1874 //DWORD 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001875 tx_desc->FirstSeg = 1;
1876 tx_desc->LastSeg = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001877 tx_desc->OWN = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001878
1879#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1880 if (tcb_desc->drv_agg_enable) {
1881 tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb);
1882 } else
1883#endif
1884 {
1885 //DWORD 2
1886 tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN);
1887 }
1888 /* Get index to out pipe from specified QueueID */
1889#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001890 idx_pipe = txqueue2outpipe(priv, tcb_desc->queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001891#else
1892 idx_pipe = 0x5;
1893#endif
1894
Jerry Chuang8fc85982009-11-03 07:17:11 -02001895 /* To submit bulk urb */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001896 usb_fill_bulk_urb(tx_urb, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001897 usb_sndbulkpipe(udev, idx_pipe), skb->data,
1898 skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001899
Jerry Chuang8fc85982009-11-03 07:17:11 -02001900 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001901 if (!status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001902 //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 -02001903 bool bSend0Byte = false;
1904 u8 zero = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001905 if (udev->speed == USB_SPEED_HIGH) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001906 if (skb->len > 0 && skb->len % 512 == 0)
1907 bSend0Byte = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001908 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001909 if (skb->len > 0 && skb->len % 64 == 0)
1910 bSend0Byte = true;
1911 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001912 if (bSend0Byte) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001913 tx_urb_zero = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001914 if (!tx_urb_zero) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001915 RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
1916 return -ENOMEM;
1917 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001918 usb_fill_bulk_urb(tx_urb_zero, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001919 usb_sndbulkpipe(udev, idx_pipe), &zero,
1920 0, tx_zero_isr, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001921 status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001922 if (status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001923 RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
1924 return -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001925 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001926 }
1927 dev->trans_start = jiffies;
1928 atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
1929 return 0;
Patrik Karlin29b48ae2013-01-09 09:40:23 +01001930 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001931 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 +03001932 status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001933 return -1;
1934 }
1935}
1936
1937short rtl8192_usb_initendpoints(struct net_device *dev)
1938{
1939 struct r8192_priv *priv = ieee80211_priv(dev);
1940
Julia Lawall32414872010-05-11 20:26:57 +02001941 priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB+1),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001942 GFP_KERNEL);
David Chosrovab8345172010-12-01 13:42:16 +01001943 if (priv->rx_urb == NULL)
1944 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001945
1946#ifndef JACKSON_NEW_RX
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001947 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001948
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001949 priv->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001950
1951 priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL);
1952
1953 priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE;
1954 }
1955#endif
1956
1957#ifdef THOMAS_BEACON
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001958 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001959 long align = 0;
1960 void *oldaddr, *newaddr;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001961
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001962 priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
1963 priv->oldaddr = kmalloc(16, GFP_KERNEL);
1964 oldaddr = priv->oldaddr;
1965 align = ((long)oldaddr) & 3;
1966 if (align) {
1967 newaddr = oldaddr + 4 - align;
1968 priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align;
1969 } else {
1970 newaddr = oldaddr;
1971 priv->rx_urb[16]->transfer_buffer_length = 16;
1972 }
1973 priv->rx_urb[16]->transfer_buffer = newaddr;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001974 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001975#endif
1976
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001977 memset(priv->rx_urb, 0, sizeof(struct urb *) * MAX_RX_URB);
Julia Lawall7a6cb0d2010-05-13 22:00:05 +02001978 priv->pp_rxskb = kcalloc(MAX_RX_URB, sizeof(struct sk_buff *),
Julia Lawall32414872010-05-11 20:26:57 +02001979 GFP_KERNEL);
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001980 if (!priv->pp_rxskb) {
1981 kfree(priv->rx_urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001982
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001983 priv->pp_rxskb = NULL;
1984 priv->rx_urb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001985
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001986 DMESGE("Endpoint Alloc Failure");
1987 return -ENOMEM;
1988 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001989
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001990 netdev_dbg(dev, "End of initendpoints\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001991 return 0;
1992
1993}
1994#ifdef THOMAS_BEACON
1995void rtl8192_usb_deleteendpoints(struct net_device *dev)
1996{
1997 int i;
1998 struct r8192_priv *priv = ieee80211_priv(dev);
1999
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002000 if (priv->rx_urb) {
2001 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002002 usb_kill_urb(priv->rx_urb[i]);
2003 usb_free_urb(priv->rx_urb[i]);
2004 }
2005 kfree(priv->rx_urb);
2006 priv->rx_urb = NULL;
2007 }
Ilia Mirkine72714f2011-03-13 00:29:07 -05002008 kfree(priv->oldaddr);
2009 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002010 if (priv->pp_rxskb) {
2011 kfree(priv->pp_rxskb);
2012 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002013 }
2014}
2015#else
2016void rtl8192_usb_deleteendpoints(struct net_device *dev)
2017{
2018 int i;
2019 struct r8192_priv *priv = ieee80211_priv(dev);
2020
2021#ifndef JACKSON_NEW_RX
2022
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002023 if (priv->rx_urb) {
2024 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002025 usb_kill_urb(priv->rx_urb[i]);
2026 kfree(priv->rx_urb[i]->transfer_buffer);
2027 usb_free_urb(priv->rx_urb[i]);
2028 }
2029 kfree(priv->rx_urb);
2030 priv->rx_urb = NULL;
2031
2032 }
2033#else
Ilia Mirkine72714f2011-03-13 00:29:07 -05002034 kfree(priv->rx_urb);
2035 priv->rx_urb = NULL;
2036 kfree(priv->oldaddr);
2037 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002038 if (priv->pp_rxskb) {
2039 kfree(priv->pp_rxskb);
2040 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002041
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002042 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002043
2044#endif
2045}
2046#endif
2047
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002048extern void rtl8192_update_ratr_table(struct net_device *dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002049void rtl8192_link_change(struct net_device *dev)
2050{
Jerry Chuang8fc85982009-11-03 07:17:11 -02002051 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002052 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002053 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002054 rtl8192_net_update(dev);
2055 rtl8192_update_ratr_table(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002056 //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
2057 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002058 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002059 }
2060 /*update timing params*/
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002061 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002062 u32 reg = 0;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002063 read_nic_dword(dev, RCR, &reg);
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002064 if (priv->ieee80211->state == IEEE80211_LINKED)
2065 priv->ReceiveConfig = reg |= RCR_CBSSID;
2066 else
2067 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
2068 write_nic_dword(dev, RCR, reg);
2069 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002070}
2071
2072static struct ieee80211_qos_parameters def_qos_parameters = {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002073 {3, 3, 3, 3},/* cw_min */
2074 {7, 7, 7, 7},/* cw_max */
2075 {2, 2, 2, 2},/* aifs */
2076 {0, 0, 0, 0},/* flags */
2077 {0, 0, 0, 0} /* tx_op_limit */
Jerry Chuang8fc85982009-11-03 07:17:11 -02002078};
2079
2080
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002081void rtl8192_update_beacon(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002082{
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002083 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
2084 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002085 struct ieee80211_device *ieee = priv->ieee80211;
2086 struct ieee80211_network *net = &ieee->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002087
2088 if (ieee->pHTInfo->bCurrentHTSupport)
2089 HTUpdateSelfAndPeerSetting(ieee, net);
2090 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
2091 rtl8192_update_cap(dev, net->capability);
2092}
2093/*
2094* background support to run QoS activate functionality
2095*/
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002096int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, EDCAPARA_VO};
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002097void rtl8192_qos_activate(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002098{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002099 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
2100 struct net_device *dev = priv->ieee80211->dev;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002101 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2102 u8 mode = priv->ieee80211->current_network.mode;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002103 u8 u1bAIFS;
2104 u32 u4bAcParam;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002105 int i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002106
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002107 if (priv == NULL)
2108 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002109
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002110 mutex_lock(&priv->mutex);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002111 if (priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002112 goto success;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002113 RT_TRACE(COMP_QOS, "qos active process with associate response received\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002114 /* It better set slot time at first */
2115 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2116 /* update the ac parameter to related registers */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002117 for (i = 0; i < QOS_QUEUE_NUM; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002118 //Mode G/A: slotTimeTimer = 9; Mode B: 20
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002119 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002120 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002121 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2122 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2123 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002124
2125 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002126 }
2127
2128success:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002129 mutex_unlock(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002130}
2131
2132static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002133 int active_network,
2134 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002135{
2136 int ret = 0;
2137 u32 size = sizeof(struct ieee80211_qos_parameters);
2138
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002139 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002140 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002141
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002142 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2143 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002144
2145 if (network->flags & NETWORK_HAS_QOS_MASK) {
2146 if (active_network &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002147 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
Jerry Chuang8fc85982009-11-03 07:17:11 -02002148 network->qos_data.active = network->qos_data.supported;
2149
2150 if ((network->qos_data.active == 1) && (active_network == 1) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002151 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2152 (network->qos_data.old_param_count !=
2153 network->qos_data.param_count)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002154 network->qos_data.old_param_count =
2155 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002156 queue_work(priv->priv_wq, &priv->qos_activate);
Xenia Ragiadakoue6367212013-05-23 05:14:46 +03002157 RT_TRACE(COMP_QOS, "QoS parameters change call "
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002158 "qos_activate\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002159 }
2160 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002161 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002162 &def_qos_parameters, size);
2163
2164 if ((network->qos_data.active == 1) && (active_network == 1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002165 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002166 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2167 }
2168 network->qos_data.active = 0;
2169 network->qos_data.supported = 0;
2170 }
2171
2172 return 0;
2173}
2174
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002175/* handle and manage frame from beacon and probe response */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002176static int rtl8192_handle_beacon(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002177 struct ieee80211_beacon *beacon,
2178 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002179{
2180 struct r8192_priv *priv = ieee80211_priv(dev);
2181
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002182 rtl8192_qos_handle_probe_response(priv, 1, network);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002183 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002184 return 0;
2185
2186}
2187
2188/*
2189* handling the beaconing responses. if we get different QoS setting
2190* off the network from the associated setting, adjust the QoS
2191* setting
2192*/
2193static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002194 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002195{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002196 int ret = 0;
2197 unsigned long flags;
2198 u32 size = sizeof(struct ieee80211_qos_parameters);
2199 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002200
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002201 if ((priv == NULL) || (network == NULL))
2202 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002203
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002204 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002205 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002206
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002207 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2208 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002209
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002210 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002211 if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002212 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002213 &network->qos_data.parameters,
2214 sizeof(struct ieee80211_qos_parameters));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002215 priv->ieee80211->current_network.qos_data.active = 1;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002216 set_qos_param = 1;
2217 /* update qos parameter for current network */
2218 priv->ieee80211->current_network.qos_data.old_param_count =
2219 priv->ieee80211->current_network.qos_data.param_count;
2220 priv->ieee80211->current_network.qos_data.param_count =
2221 network->qos_data.param_count;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002222 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002223 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002224 &def_qos_parameters, size);
2225 priv->ieee80211->current_network.qos_data.active = 0;
2226 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002227 set_qos_param = 1;
2228 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002229
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002230 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002231
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002232 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 -02002233 if (set_qos_param == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002234 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002235
2236
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002237 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002238}
2239
2240
2241static int rtl8192_handle_assoc_response(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002242 struct ieee80211_assoc_response_frame *resp,
2243 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002244{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002245 struct r8192_priv *priv = ieee80211_priv(dev);
2246 rtl8192_qos_association_resp(priv, network);
2247 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002248}
2249
2250
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002251void rtl8192_update_ratr_table(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002252{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002253 struct r8192_priv *priv = ieee80211_priv(dev);
2254 struct ieee80211_device *ieee = priv->ieee80211;
2255 u8 *pMcsRate = ieee->dot11HTOperationalRateSet;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002256 u32 ratr_value = 0;
2257 u8 rate_index = 0;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002258 rtl8192_config_rate(dev, (u16 *)(&ratr_value));
2259 ratr_value |= (*(u16 *)(pMcsRate)) << 12;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002260 switch (ieee->mode) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002261 case IEEE_A:
2262 ratr_value &= 0x00000FF0;
2263 break;
2264 case IEEE_B:
2265 ratr_value &= 0x0000000F;
2266 break;
2267 case IEEE_G:
2268 ratr_value &= 0x00000FF7;
2269 break;
2270 case IEEE_N_24G:
2271 case IEEE_N_5G:
2272 if (ieee->pHTInfo->PeerMimoPs == 0) {//MIMO_PS_STATIC
2273 ratr_value &= 0x0007F007;
2274 } else {
2275 if (priv->rf_type == RF_1T2R)
2276 ratr_value &= 0x000FF007;
2277 else
2278 ratr_value &= 0x0F81F007;
2279 }
2280 break;
2281 default:
2282 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002283 }
2284 ratr_value &= 0x0FFFFFFF;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002285 if (ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002286 ratr_value |= 0x80000000;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002287 else if (!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002288 ratr_value |= 0x80000000;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002289 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2290 write_nic_byte(dev, UFWP, 1);
2291}
2292
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002293static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04};
Jerry Chuang8fc85982009-11-03 07:17:11 -02002294static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002295bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002296{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002297 struct r8192_priv *priv = ieee80211_priv(dev);
2298 struct ieee80211_device *ieee = priv->ieee80211;
2299 struct ieee80211_network *network = &ieee->current_network;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002300 int wpa_ie_len = ieee->wpa_ie_len;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002301 struct ieee80211_crypt_data *crypt;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002302 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002303
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002304 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002305 //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 +03002306 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 -02002307
2308 /* simply judge */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002309 if (encrypt && (wpa_ie_len == 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002310 /* wep encryption, no N mode setting */
2311 return false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002312 } else if ((wpa_ie_len != 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002313 /* parse pairwise key type */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002314 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 -02002315 return true;
2316 else
2317 return false;
2318 } else {
2319 return true;
2320 }
2321
Jerry Chuang8fc85982009-11-03 07:17:11 -02002322 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002323}
2324
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002325bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002326{
2327 bool Reval;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002328 struct r8192_priv *priv = ieee80211_priv(dev);
2329 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002330
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002331 if (ieee->bHalfWirelessN24GMode == true)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002332 Reval = true;
2333 else
2334 Reval = false;
2335
2336 return Reval;
2337}
2338
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002339void rtl8192_refresh_supportrate(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002340{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002341 struct ieee80211_device *ieee = priv->ieee80211;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002342 //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002343 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002344 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002345 else
2346 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2347 return;
2348}
2349
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002350u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002351{
2352 struct r8192_priv *priv = ieee80211_priv(dev);
2353 u8 ret = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002354 switch (priv->rf_chip) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002355 case RF_8225:
2356 case RF_8256:
2357 case RF_PSEUDO_11N:
2358 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2359 break;
2360 case RF_8258:
2361 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2362 break;
2363 default:
2364 ret = WIRELESS_MODE_B;
2365 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002366 }
2367 return ret;
2368}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002369void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002370{
2371 struct r8192_priv *priv = ieee80211_priv(dev);
2372 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2373
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002374 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode) == 0)) {
2375 if (bSupportMode & WIRELESS_MODE_N_24G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002376 wireless_mode = WIRELESS_MODE_N_24G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002377 } else if (bSupportMode & WIRELESS_MODE_N_5G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002378 wireless_mode = WIRELESS_MODE_N_5G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002379 } else if ((bSupportMode & WIRELESS_MODE_A)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002380 wireless_mode = WIRELESS_MODE_A;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002381 } else if ((bSupportMode & WIRELESS_MODE_G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002382 wireless_mode = WIRELESS_MODE_G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002383 } else if ((bSupportMode & WIRELESS_MODE_B)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002384 wireless_mode = WIRELESS_MODE_B;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002385 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002386 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __func__, bSupportMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002387 wireless_mode = WIRELESS_MODE_B;
2388 }
2389 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002390#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 +03002391 ActUpdateChannelAccessSetting(pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002392#endif
2393 priv->ieee80211->mode = wireless_mode;
2394
2395 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2396 priv->ieee80211->pHTInfo->bEnableHT = 1;
2397 else
2398 priv->ieee80211->pHTInfo->bEnableHT = 0;
2399 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2400 rtl8192_refresh_supportrate(priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002401
2402}
2403//init priv variables here. only non_zero value should be initialized here.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002404static void rtl8192_init_priv_variable(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002405{
2406 struct r8192_priv *priv = ieee80211_priv(dev);
2407 u8 i;
2408 priv->card_8192 = NIC_8192U;
2409 priv->chan = 1; //set to channel 1
2410 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2411 priv->ieee80211->iw_mode = IW_MODE_INFRA;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002412 priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002413 priv->retry_rts = DEFAULT_RETRY_RTS;
2414 priv->retry_data = DEFAULT_RETRY_DATA;
2415 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2416 priv->ieee80211->rate = 110; //11 mbps
2417 priv->ieee80211->short_slot = 1;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002418 priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002419 priv->CckPwEnl = 6;
2420 //for silent reset
2421 priv->IrpPendingCount = 1;
2422 priv->ResetProgress = RESET_TYPE_NORESET;
2423 priv->bForcedSilentReset = 0;
2424 priv->bDisableNormalResetCheck = false;
2425 priv->force_reset = false;
2426
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002427 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002428 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2429 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2430 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2431 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2432 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002433 IEEE_SOFTMAC_BEACONS;//added by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002434
2435 priv->ieee80211->active_scan = 1;
2436 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2437 priv->ieee80211->host_encrypt = 1;
2438 priv->ieee80211->host_decrypt = 1;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002439 priv->ieee80211->start_send_beacons = NULL; //-by amy 080604
2440 priv->ieee80211->stop_send_beacons = NULL; //-by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002441 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2442 priv->ieee80211->set_chan = rtl8192_set_chan;
2443 priv->ieee80211->link_change = rtl8192_link_change;
2444 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2445 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2446 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2447 priv->ieee80211->init_wmmparam_flag = 0;
2448 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2449 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2450 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
2451 priv->ieee80211->qos_support = 1;
2452
2453 //added by WB
Jerry Chuang8fc85982009-11-03 07:17:11 -02002454 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2455 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2456 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2457 //added by david
2458 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
2459 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
2460 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2461 //added by amy
2462 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
2463 priv->card_type = USB;
2464#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002465 if (Adapter->bInHctTest) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002466 pHalData->ShortRetryLimit = 7;
2467 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002468 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002469#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002470 priv->ShortRetryLimit = 0x30;
2471 priv->LongRetryLimit = 0x30;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002472 priv->EarlyRxThreshold = 7;
2473 priv->enable_gpio0 = 0;
2474 priv->TransmitConfig =
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002475 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002476 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
2477 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002478 (false ? TCR_SAT : 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
Jerry Chuang8fc85982009-11-03 07:17:11 -02002479#ifdef TO_DO_LIST
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002480 if (Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002481 pHalData->ReceiveConfig = pHalData->CSMethod |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002482 RCR_AMF | RCR_ADF | //accept management/data
Jerry Chuang8fc85982009-11-03 07:17:11 -02002483 //guangan200710
2484 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2485 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002486 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002487 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2488 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002489 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002490 else
2491
2492#endif
2493 priv->ReceiveConfig =
2494 RCR_AMF | RCR_ADF | //accept management/data
2495 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2496 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Jerry Chuang8fc85982009-11-03 07:17:11 -02002497 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2498 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002499 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002500
2501 priv->AcmControl = 0;
Devendra Nagab7553422012-08-26 11:06:33 +05302502 priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002503
2504 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002505 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002506 skb_queue_head_init(&priv->skb_queue);
2507
2508 /* Tx related queue */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002509 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002510 skb_queue_head_init(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002511 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002512 skb_queue_head_init(&priv->ieee80211->skb_aggQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002513 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002514 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002515 priv->rf_set_chan = rtl8192_phy_SwChnl;
2516}
2517
2518//init lock here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002519static void rtl8192_init_priv_lock(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002520{
2521 spin_lock_init(&priv->tx_lock);
2522 spin_lock_init(&priv->irq_lock);//added by thomas
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002523 sema_init(&priv->wx_sem, 1);
2524 sema_init(&priv->rf_sem, 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002525 mutex_init(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002526}
2527
Jerry Chuang8fc85982009-11-03 07:17:11 -02002528extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002529
2530void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
2531//init tasklet and wait_queue here. only 2.6 above kernel is considered
2532#define DRV_NAME "wlan0"
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002533static void rtl8192_init_priv_task(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002534{
2535 struct r8192_priv *priv = ieee80211_priv(dev);
2536
Jerry Chuang8fc85982009-11-03 07:17:11 -02002537 priv->priv_wq = create_workqueue(DRV_NAME);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002538
Jerry Chuang8fc85982009-11-03 07:17:11 -02002539 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2540
Jerry Chuang8fc85982009-11-03 07:17:11 -02002541 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2542 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002543 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2544 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2545 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002546 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002547
2548 tasklet_init(&priv->irq_rx_tasklet,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002549 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2550 (unsigned long)priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002551}
2552
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002553static void rtl8192_get_eeprom_size(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002554{
2555 u16 curCR = 0;
2556 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002557 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002558 read_nic_word_E(dev, EPROM_CMD, &curCR);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002559 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
2560 //whether need I consider BIT5?
2561 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002562 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __func__, priv->epromtype);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002563}
2564
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002565//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002566static inline u16 endian_swap(u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002567{
2568 u16 tmp = *data;
2569 *data = (tmp >> 8) | (tmp << 8);
2570 return *data;
2571}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002572static void rtl8192_read_eeprom_info(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002573{
2574 u16 wEPROM_ID = 0;
2575 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
2576 u8 bLoad_From_EEPOM = false;
2577 struct r8192_priv *priv = ieee80211_priv(dev);
2578 u16 tmpValue = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002579 int i;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002580 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002581 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
2582 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
2583
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002584 if (wEPROM_ID != RTL8190_EEPROM_ID) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002585 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 +03002586 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002587 bLoad_From_EEPOM = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002588 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002589
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002590 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002591 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
2592 priv->eeprom_vid = endian_swap(&tmpValue);
2593 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
2594 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002595 priv->eeprom_ChannelPlan = ((tmpValue&0xff00)>>8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002596 priv->btxpowerdata_readfromEEPORM = true;
2597 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002598 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002599 priv->eeprom_vid = 0;
2600 priv->eeprom_pid = 0;
2601 priv->card_8192_version = VERSION_819xU_B;
2602 priv->eeprom_ChannelPlan = 0;
2603 priv->eeprom_CustomerID = 0;
2604 }
2605 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);
2606 //set channelplan from eeprom
2607 priv->ChannelPlan = priv->eeprom_ChannelPlan;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002608 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002609 int i;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002610 for (i = 0; i < 6; i += 2) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002611 u16 tmp = 0;
2612 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002613 *(u16 *)(&dev->dev_addr[i]) = tmp;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002614 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002615 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002616 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2617 //should I set IDR0 here?
2618 }
Joe Perches0ee9f672009-12-06 11:34:52 -08002619 RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002620 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
2621 priv->rf_chip = RF_8256;
2622
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002623 if (priv->card_8192_version == (u8)VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002624 //read Tx power gain offset of legacy OFDM to HT rate
2625 if (bLoad_From_EEPOM)
2626 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
2627 else
2628 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
2629 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
2630 //read ThermalMeter from EEPROM
2631 if (bLoad_From_EEPOM)
2632 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
2633 else
2634 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2635 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
2636 //vivi, for tx power track
2637 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2638 //read antenna tx power offset of B/C/D to A from EEPROM
2639 if (bLoad_From_EEPOM)
2640 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
2641 else
2642 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
2643 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
2644 // Read CrystalCap from EEPROM
2645 if (bLoad_From_EEPOM)
2646 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
2647 else
2648 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
2649 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
2650 //get per-channel Tx power level
2651 if (bLoad_From_EEPOM)
2652 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
2653 else
2654 priv->EEPROM_Def_Ver = 1;
2655 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002656 if (priv->EEPROM_Def_Ver == 0) { //old eeprom definition
Jerry Chuang8fc85982009-11-03 07:17:11 -02002657 int i;
2658 if (bLoad_From_EEPOM)
2659 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
2660 else
2661 priv->EEPROMTxPowerLevelCCK = 0x10;
2662 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002663 for (i = 0; i < 3; i++) {
2664 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002665 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
2666 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
2667 tmpValue = tmpValue & 0x00ff;
2668 else
2669 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002670 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002671 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002672 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002673 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
2674 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
2675 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002676 } else if (priv->EEPROM_Def_Ver == 1) {
2677 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002678 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
2679 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002680 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002681 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002682 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002683 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
2684
2685 if (bLoad_From_EEPOM)
2686 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
2687 else
2688 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002689 *((u16 *)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002690 if (bLoad_From_EEPOM)
2691 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
2692 else
2693 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002694 *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002695 if (bLoad_From_EEPOM)
2696 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
2697 else
2698 tmpValue = 0x10;
2699 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
2700 }//endif EEPROM_Def_Ver == 1
2701
2702 //update HAL variables
2703 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002704 for (i = 0; i < 14; i++) {
2705 if (i <= 3)
2706 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
2707 else if (i >= 4 && i <= 9)
2708 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
2709 else
2710 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
2711 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002712
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002713 for (i = 0; i < 14; i++) {
2714 if (priv->EEPROM_Def_Ver == 0) {
2715 if (i <= 3)
2716 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2717 else if (i >= 4 && i <= 9)
2718 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
2719 else
2720 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2721 } else if (priv->EEPROM_Def_Ver == 1) {
2722 if (i <= 3)
2723 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
2724 else if (i >= 4 && i <= 9)
2725 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
2726 else
2727 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002728 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002729 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002730 priv->TxPowerDiff = priv->EEPROMPwDiff;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002731 // Antenna B gain offset to antenna A, bit0~3
Jerry Chuang8fc85982009-11-03 07:17:11 -02002732 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
2733 // Antenna C gain offset to antenna A, bit4~7
2734 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
2735 // CrystalCap, bit12~15
2736 priv->CrystalCap = priv->EEPROMCrystalCap;
2737 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
2738 // 92U does not enable TX power tracking.
2739 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
2740 }//end if VersionID == VERSION_819xU_A
2741
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002742 //added by vivi, for dlink led, 20080416
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002743 switch (priv->eeprom_CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002744 case EEPROM_CID_RUNTOP:
2745 priv->CustomerID = RT_CID_819x_RUNTOP;
2746 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002747
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002748 case EEPROM_CID_DLINK:
2749 priv->CustomerID = RT_CID_DLINK;
2750 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002751
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002752 default:
2753 priv->CustomerID = RT_CID_DEFAULT;
2754 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002755
2756 }
2757
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002758 switch (priv->CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002759 case RT_CID_819x_RUNTOP:
2760 priv->LedStrategy = SW_LED_MODE2;
2761 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002762
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002763 case RT_CID_DLINK:
2764 priv->LedStrategy = SW_LED_MODE4;
2765 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002766
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002767 default:
2768 priv->LedStrategy = SW_LED_MODE0;
2769 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002770
2771 }
2772
2773
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002774 if (priv->rf_type == RF_1T2R) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002775 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002776 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002777 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
2778 }
2779
2780 // 2008/01/16 MH We can only know RF type in the function. So we have to init
2781 // DIG RATR table again.
2782 init_rate_adaptive(dev);
2783 //we need init DIG RATR table here again.
2784
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002785 RT_TRACE(COMP_EPROM, "<===========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002786 return;
2787}
2788
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002789short rtl8192_get_channel_map(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002790{
2791 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002792 if (priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03002793 netdev_err(dev, "rtl8180_init: Error channel plan! Set to default.\n");
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002794 priv->ChannelPlan = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002795 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002796 RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002797
2798 rtl819x_set_channel_map(priv->ChannelPlan, priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002799 return 0;
2800}
2801
2802short rtl8192_init(struct net_device *dev)
2803{
2804
2805 struct r8192_priv *priv = ieee80211_priv(dev);
2806
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002807 memset(&(priv->stats), 0, sizeof(struct Stats));
2808 memset(priv->txqueue_to_outpipemap, 0, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002809#ifdef PIPE12
2810 {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002811 int i = 0;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002812 u8 queuetopipe[] = {3, 2, 1, 0, 4, 8, 7, 6, 5};
2813 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002814 }
2815#else
2816 {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002817 u8 queuetopipe[] = {3, 2, 1, 0, 4, 4, 0, 4, 4};
2818 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002819 }
2820#endif
2821 rtl8192_init_priv_variable(dev);
2822 rtl8192_init_priv_lock(priv);
2823 rtl8192_init_priv_task(dev);
2824 rtl8192_get_eeprom_size(dev);
2825 rtl8192_read_eeprom_info(dev);
2826 rtl8192_get_channel_map(dev);
2827 init_hal_dm(dev);
2828 init_timer(&priv->watch_dog_timer);
2829 priv->watch_dog_timer.data = (unsigned long)dev;
2830 priv->watch_dog_timer.function = watch_dog_timer_callback;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002831 if (rtl8192_usb_initendpoints(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002832 DMESG("Endopoints initialization failed");
2833 return -ENOMEM;
2834 }
2835
Jerry Chuang8fc85982009-11-03 07:17:11 -02002836#ifdef DEBUG_EPROM
2837 dump_eprom(dev);
2838#endif
2839 return 0;
2840}
2841
2842/******************************************************************************
2843 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
2844 * not to do all the hw config as its name says
2845 * input: net_device dev
2846 * output: none
2847 * return: none
2848 * notice: This part need to modified according to the rate set we filtered
2849 * ****************************************************************************/
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002850void rtl8192_hwconfig(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002851{
2852 u32 regRATR = 0, regRRSR = 0;
2853 u8 regBwOpMode = 0, regTmp = 0;
2854 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002855 u32 ratr_value = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002856
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002857 // Set RRSR, RATR, and BW_OPMODE registers
Jerry Chuang8fc85982009-11-03 07:17:11 -02002858 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002859 switch (priv->ieee80211->mode) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002860 case WIRELESS_MODE_B:
2861 regBwOpMode = BW_OPMODE_20MHZ;
2862 regRATR = RATE_ALL_CCK;
2863 regRRSR = RATE_ALL_CCK;
2864 break;
2865 case WIRELESS_MODE_A:
2866 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
2867 regRATR = RATE_ALL_OFDM_AG;
2868 regRRSR = RATE_ALL_OFDM_AG;
2869 break;
2870 case WIRELESS_MODE_G:
2871 regBwOpMode = BW_OPMODE_20MHZ;
2872 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2873 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2874 break;
2875 case WIRELESS_MODE_AUTO:
2876#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002877 if (Adapter->bInHctTest) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002878 regBwOpMode = BW_OPMODE_20MHZ;
2879 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2880 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002881 }
2882 else
2883#endif
2884 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002885 regBwOpMode = BW_OPMODE_20MHZ;
2886 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2887 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002888 }
2889 break;
2890 case WIRELESS_MODE_N_24G:
2891 // It support CCK rate by default.
2892 // CCK rate will be filtered out only when associated AP does not support it.
2893 regBwOpMode = BW_OPMODE_20MHZ;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002894 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2895 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002896 break;
2897 case WIRELESS_MODE_N_5G:
2898 regBwOpMode = BW_OPMODE_5G;
2899 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2900 regRRSR = RATE_ALL_OFDM_AG;
2901 break;
2902 }
2903
2904 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002905 ratr_value = regRATR;
2906 if (priv->rf_type == RF_1T2R)
2907 ratr_value &= ~(RATE_ALL_OFDM_2SS);
2908 write_nic_dword(dev, RATR0, ratr_value);
2909 write_nic_byte(dev, UFWP, 1);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002910 read_nic_byte(dev, 0x313, &regTmp);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002911 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
2912 write_nic_dword(dev, RRSR, regRRSR);
2913
2914 //
2915 // Set Retry Limit here
2916 //
2917 write_nic_word(dev, RETRY_LIMIT,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002918 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
2919 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002920 // Set Contention Window here
2921
2922 // Set Tx AGC
2923
2924 // Set Tx Antenna including Feedback control
2925
2926 // Set Auto Rate fallback control
2927
2928
2929}
2930
2931
2932//InitializeAdapter and PhyCfg
2933bool rtl8192_adapter_start(struct net_device *dev)
2934{
2935 struct r8192_priv *priv = ieee80211_priv(dev);
2936 u32 dwRegRead = 0;
2937 bool init_status = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002938 u8 SECR_value = 0x0;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002939 u8 tmp;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002940 RT_TRACE(COMP_INIT, "====>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002941 priv->Rf_Mode = RF_OP_By_SW_3wire;
2942 //for ASIC power on sequence
2943 write_nic_byte_E(dev, 0x5f, 0x80);
2944 mdelay(50);
2945 write_nic_byte_E(dev, 0x5f, 0xf0);
2946 write_nic_byte_E(dev, 0x5d, 0x00);
2947 write_nic_byte_E(dev, 0x5e, 0x80);
2948 write_nic_byte(dev, 0x17, 0x37);
2949 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002950 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
2951 //config CPUReset Register
2952 //Firmware Reset or not?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002953 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002954 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
2955 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
2956 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
2957 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
2958 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002959 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __func__, priv->pFirmware->firmware_status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002960
2961 write_nic_dword(dev, CPU_GEN, dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002962 //config BB.
2963 rtl8192_BBConfig(dev);
2964
Jerry Chuang8fc85982009-11-03 07:17:11 -02002965 //Loopback mode or not
2966 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002967
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002968 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002969 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
2970 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
2971 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
2972 dwRegRead |= CPU_CCK_LOOPBACK;
2973 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002974 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __func__, priv->LoopbackMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002975
2976 write_nic_dword(dev, CPU_GEN, dwRegRead);
2977
2978 //after reset cpu, we need wait for a seconds to write in register.
2979 udelay(500);
2980
2981 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002982 read_nic_byte_E(dev, 0x5f, &tmp);
2983 write_nic_byte_E(dev, 0x5f, tmp|0x20);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002984
2985 //Set Hardware
2986 rtl8192_hwconfig(dev);
2987
2988 //turn on Tx/Rx
2989 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
2990
2991 //set IDR0 here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002992 write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
2993 write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002994
2995 //set RCR
2996 write_nic_dword(dev, RCR, priv->ReceiveConfig);
2997
2998 //Initialize Number of Reserved Pages in Firmware Queue
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002999 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 +03003000 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT |
3001 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT |
3002 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03003003 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 +03003004 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03003005 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003006 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003007 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
3008
3009 //Set AckTimeout
3010 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
3011 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
3012
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003013 if (priv->ResetProgress == RESET_TYPE_NORESET)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003014 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003015 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003016 CamResetAllEntry(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003017 SECR_value |= SCR_TxEncEnable;
3018 SECR_value |= SCR_RxDecEnable;
3019 SECR_value |= SCR_NoSKMC;
3020 write_nic_byte(dev, SECR, SECR_value);
3021 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003022
3023 //Beacon related
3024 write_nic_word(dev, ATIMWND, 2);
3025 write_nic_word(dev, BCN_INTERVAL, 100);
3026
Jerry Chuang8fc85982009-11-03 07:17:11 -02003027#define DEFAULT_EDCA 0x005e4332
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003028 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003029 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003030 for (i = 0; i < QOS_QUEUE_NUM; i++)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003031 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003032 }
3033#ifdef USB_RX_AGGREGATION_SUPPORT
3034 //3 For usb rx firmware aggregation control
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003035 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003036 u32 ulValue;
3037 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
3038 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003039 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003040 /*
3041 * If usb rx firmware aggregation is enabled,
3042 * when anyone of three threshold conditions above is reached,
3043 * firmware will send aggregated packet to driver.
3044 */
3045 write_nic_dword(dev, 0x1a8, ulValue);
3046 priv->bCurrentRxAggrEnable = true;
3047 }
3048#endif
3049
3050 rtl8192_phy_configmac(dev);
3051
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003052 if (priv->card_8192_version == (u8) VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003053 rtl8192_phy_getTxPower(dev);
3054 rtl8192_phy_setTxPower(dev, priv->chan);
3055 }
3056
3057 //Firmware download
3058 init_status = init_firmware(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003059 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003060 RT_TRACE(COMP_ERR, "ERR!!! %s(): Firmware download is failed\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003061 return init_status;
3062 }
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003063 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003064 //
3065#ifdef TO_DO_LIST
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003066 if (Adapter->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003067 if (pMgntInfo->RegRfOff == TRUE) { // User disable RF via registry.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003068 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
3069 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003070 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003071 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003072 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003073 } else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { // H/W or S/W RF OFF before sleep.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003074 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
3075 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003076 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003077 pHalData->eRFPowerState = eRfOn;
3078 pMgntInfo->RfOffReason = 0;
3079 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
3080 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003081 } else {
3082 if (pHalData->eRFPowerState == eRfOff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003083 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003084 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003085 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003086 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3087 }
3088 }
3089#endif
3090 //config RF.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003091 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003092 rtl8192_phy_RFConfig(dev);
3093 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003094 }
3095
3096
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003097 if (priv->ieee80211->FwRWRF)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003098 // We can force firmware to do RF-R/W
3099 priv->Rf_Mode = RF_OP_By_FW;
3100 else
3101 priv->Rf_Mode = RF_OP_By_SW_3wire;
3102
3103
3104 rtl8192_phy_updateInitGain(dev);
3105 /*--set CCK and OFDM Block "ON"--*/
3106 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3107 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3108
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003109 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003110 //if D or C cut
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003111 u8 tmpvalue;
3112 read_nic_byte(dev, 0x301, &tmpvalue);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003113 if (tmpvalue == 0x03) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003114 priv->bDcut = TRUE;
3115 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003116 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003117 priv->bDcut = FALSE;
3118 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
3119 }
3120 dm_initialize_txpower_tracking(dev);
3121
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003122 if (priv->bDcut == TRUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003123 u32 i, TempCCk;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003124 u32 tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003125 for (i = 0; i < TxBBGainTableLength; i++) {
3126 if (tmpRegA == priv->txbbgain_table[i].txbbgain_value) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003127 priv->rfa_txpowertrackingindex = (u8)i;
3128 priv->rfa_txpowertrackingindex_real = (u8)i;
3129 priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003130 break;
3131 }
3132 }
3133
3134 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3135
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003136 for (i = 0; i < CCKTxBBGainTableLength; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003137
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003138 if (TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0]) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003139 priv->cck_present_attentuation_20Mdefault = (u8) i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003140 break;
3141 }
3142 }
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003143 priv->cck_present_attentuation_40Mdefault = 0;
3144 priv->cck_present_attentuation_difference = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003145 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
3146
Jerry Chuang8fc85982009-11-03 07:17:11 -02003147 }
3148 }
3149 write_nic_byte(dev, 0x87, 0x0);
3150
3151
Jerry Chuang8fc85982009-11-03 07:17:11 -02003152 return init_status;
3153}
3154
3155/* this configures registers for beacon tx and enables it via
3156 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3157 * be used to stop beacon transmission
3158 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003159/***************************************************************************
3160 -------------------------------NET STUFF---------------------------
3161***************************************************************************/
3162
3163static struct net_device_stats *rtl8192_stats(struct net_device *dev)
3164{
3165 struct r8192_priv *priv = ieee80211_priv(dev);
3166
3167 return &priv->ieee80211->stats;
3168}
3169
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003170bool HalTxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003171{
3172 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003173 u16 RegTxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003174 bool bStuck = FALSE;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003175 read_nic_word(dev, 0x128, &RegTxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003176 RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", __func__, RegTxCounter, priv->TxCounter);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003177 if (priv->TxCounter == RegTxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003178 bStuck = TRUE;
3179
3180 priv->TxCounter = RegTxCounter;
3181
3182 return bStuck;
3183}
3184
3185/*
3186* <Assumption: RT_TX_SPINLOCK is acquired.>
3187* First added: 2006.11.19 by emily
3188*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003189RESET_TYPE TxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003190{
3191 struct r8192_priv *priv = ieee80211_priv(dev);
3192 u8 QueueID;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003193 bool bCheckFwTxCnt = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003194
3195 //
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003196 // Decide such threshold according to current power save mode
Jerry Chuang8fc85982009-11-03 07:17:11 -02003197 //
3198
Xenia Ragiadakou7d79ec62013-06-04 23:32:30 +03003199 for (QueueID = 0; QueueID <= BEACON_QUEUE; QueueID++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003200 if (QueueID == TXCMD_QUEUE)
3201 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003202#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003203 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 -02003204#else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003205 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 -02003206#endif
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003207 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003208
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003209 bCheckFwTxCnt = true;
3210 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003211 if (bCheckFwTxCnt) {
3212 if (HalTxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003213 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
3214 return RESET_TYPE_SILENT;
3215 }
3216 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003217 return RESET_TYPE_NORESET;
3218}
3219
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003220bool HalRxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003221{
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003222 u16 RegRxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003223 struct r8192_priv *priv = ieee80211_priv(dev);
3224 bool bStuck = FALSE;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003225 static u8 rx_chk_cnt;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003226 read_nic_word(dev, 0x130, &RegRxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003227 RT_TRACE(COMP_RESET, "%s(): RegRxCounter is %d,RxCounter is %d\n", __func__, RegRxCounter, priv->RxCounter);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003228 // If rssi is small, we should check rx for long time because of bad rx.
3229 // or maybe it will continuous silent reset every 2 seconds.
3230 rx_chk_cnt++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003231 if (priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003232 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003233 } else if (priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003234 ((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 Ragiadakou34fc4382013-05-22 18:22:33 +03003236 if (rx_chk_cnt < 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003237 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003238 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003239 rx_chk_cnt = 0;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003240 } else if (((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_40M) ||
3241 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_20M)) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003242 priv->undecorated_smoothed_pwdb >= VeryLowRSSI) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003243 if (rx_chk_cnt < 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003244 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003245 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003246 rx_chk_cnt = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003247 } else {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003248 if (rx_chk_cnt < 8)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003249 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003250 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003251 rx_chk_cnt = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003252 }
3253
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003254 if (priv->RxCounter == RegRxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003255 bStuck = TRUE;
3256
3257 priv->RxCounter = RegRxCounter;
3258
3259 return bStuck;
3260}
3261
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003262RESET_TYPE RxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003263{
3264 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003265 bool bRxCheck = FALSE;
3266
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003267 if (priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003268 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003269
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003270 if (bRxCheck) {
3271 if (HalRxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003272 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
3273 return RESET_TYPE_SILENT;
3274 }
3275 }
3276 return RESET_TYPE_NORESET;
3277}
3278
3279
3280/**
3281* This function is called by Checkforhang to check whether we should ask OS to reset driver
3282*
3283* \param pAdapter The adapter context for this miniport
3284*
3285* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
3286* to judge whether there is tx stuck.
3287* Note: This function may be required to be rewrite for Vista OS.
3288* <<<Assumption: Tx spinlock has been acquired >>>
3289*
3290* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
3291*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003292RESET_TYPE rtl819x_ifcheck_resetornot(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003293{
3294 struct r8192_priv *priv = ieee80211_priv(dev);
3295 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
3296 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003297 RT_RF_POWER_STATE rfState;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003298
3299 rfState = priv->ieee80211->eRFPowerState;
3300
3301 TxResetType = TxCheckStuck(dev);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003302 if (rfState != eRfOff ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003303 (priv->ieee80211->iw_mode != IW_MODE_ADHOC)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003304 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
3305 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
3306 // if driver is in firmware download failure status, driver should initialize RF in the following
3307 // silent reset procedure Emily, 2008.01.21
3308
3309 // Driver should not check RX stuck in IBSS mode because it is required to
3310 // set Check BSSID in order to send beacon, however, if check BSSID is
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003311 // set, STA cannot hear any packet at all. Emily, 2008.04.12
Jerry Chuang8fc85982009-11-03 07:17:11 -02003312 RxResetType = RxCheckStuck(dev);
3313 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003314 if (TxResetType == RESET_TYPE_NORMAL || RxResetType == RESET_TYPE_NORMAL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003315 return RESET_TYPE_NORMAL;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003316 } else if (TxResetType == RESET_TYPE_SILENT || RxResetType == RESET_TYPE_SILENT) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003317 RT_TRACE(COMP_RESET, "%s():silent reset\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003318 return RESET_TYPE_SILENT;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003319 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003320 return RESET_TYPE_NORESET;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003321 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003322
3323}
3324
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003325void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003326int _rtl8192_up(struct net_device *dev);
3327int rtl8192_close(struct net_device *dev);
3328
3329
3330
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003331void CamRestoreAllEntry(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003332{
3333 u8 EntryId = 0;
3334 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003335 u8 *MacAddr = priv->ieee80211->current_network.bssid;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003336
3337 static u8 CAM_CONST_ADDR[4][6] = {
3338 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3339 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
3340 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03003341 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003342 static u8 CAM_CONST_BROAD[] = {
3343 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003344
3345 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
3346
3347
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003348 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40) ||
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003349 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003350
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003351 for (EntryId = 0; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003352 MacAddr = CAM_CONST_ADDR[EntryId];
3353 setKey(dev, EntryId, EntryId,
3354 priv->ieee80211->pairwise_key_type,
3355 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003356 }
3357
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003358 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003359
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003360 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3361 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3362 (u8 *)dev->dev_addr, 0, NULL);
3363 else
3364 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3365 MacAddr, 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003366 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003367
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003368 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3369 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3370 (u8 *)dev->dev_addr, 0, NULL);
3371 else
3372 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3373 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003374 }
3375
3376
3377
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003378 if (priv->ieee80211->group_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003379 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003380 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003381 setKey(dev, EntryId, EntryId,
3382 priv->ieee80211->group_key_type,
3383 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003384 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003385 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003386 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3387 CAM_CONST_ADDR[0], 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003388 } else if (priv->ieee80211->group_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003389 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003390 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003391 setKey(dev, EntryId, EntryId,
3392 priv->ieee80211->group_key_type,
3393 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003394 }
3395
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003396 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003397 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3398 CAM_CONST_ADDR[0], 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003399 }
3400}
3401//////////////////////////////////////////////////////////////
3402// This function is used to fix Tx/Rx stop bug temporarily.
3403// This function will do "system reset" to NIC when Tx or Rx is stuck.
3404// The method checking Tx/Rx stuck of this function is supported by FW,
3405// which reports Tx and Rx counter to register 0x128 and 0x130.
3406//////////////////////////////////////////////////////////////
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003407void rtl819x_ifsilentreset(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003408{
Jerry Chuang8fc85982009-11-03 07:17:11 -02003409 struct r8192_priv *priv = ieee80211_priv(dev);
3410 u8 reset_times = 0;
3411 int reset_status = 0;
3412 struct ieee80211_device *ieee = priv->ieee80211;
3413
3414
3415 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
3416 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
3417
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003418 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003419RESET_START:
3420
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003421 RT_TRACE(COMP_RESET, "=========>Reset progress!! \n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003422
3423 // Set the variable for reset.
3424 priv->ResetProgress = RESET_TYPE_SILENT;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003425 down(&priv->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003426 if (priv->up == 0) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003427 RT_TRACE(COMP_ERR, "%s():the driver is not up! return\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003428 up(&priv->wx_sem);
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003429 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003430 }
3431 priv->up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003432 RT_TRACE(COMP_RESET, "%s():======>start to down the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003433
3434 rtl8192_rtx_disable(dev);
3435 rtl8192_cancel_deferred_work(priv);
3436 deinit_hal_dm(dev);
3437 del_timer_sync(&priv->watch_dog_timer);
3438
3439 ieee->sync_scan_hurryup = 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003440 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003441 down(&ieee->wx_sem);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003442 netdev_dbg(dev, "ieee->state is IEEE80211_LINKED\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003443 ieee80211_stop_send_beacons(priv->ieee80211);
3444 del_timer_sync(&ieee->associate_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003445 cancel_delayed_work(&ieee->associate_retry_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003446 ieee80211_stop_scan(ieee);
3447 netif_carrier_off(dev);
3448 up(&ieee->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003449 } else {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003450 netdev_dbg(dev, "ieee->state is NOT LINKED\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003451 ieee80211_softmac_stop_protocol(priv->ieee80211);
3452 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003453 up(&priv->wx_sem);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003454 RT_TRACE(COMP_RESET, "%s():<==========down process is finished\n", __func__);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003455 RT_TRACE(COMP_RESET, "%s():===========>start up the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003456 reset_status = _rtl8192_up(dev);
3457
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003458 RT_TRACE(COMP_RESET, "%s():<===========up process is finished\n", __func__);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003459 if (reset_status == -EAGAIN) {
3460 if (reset_times < 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003461 reset_times++;
3462 goto RESET_START;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003463 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003464 RT_TRACE(COMP_ERR, " ERR!!! %s(): Reset Failed!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003465 }
3466 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003467 ieee->is_silent_reset = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003468 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003469 if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003470 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3471
Jerry Chuang8fc85982009-11-03 07:17:11 -02003472 queue_work(ieee->wq, &ieee->associate_complete_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003473
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003474 } else if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003475 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3476 ieee->link_change(ieee->dev);
3477
Jerry Chuang8fc85982009-11-03 07:17:11 -02003478 ieee80211_start_send_beacons(ieee);
3479
3480 if (ieee->data_hard_resume)
3481 ieee->data_hard_resume(ieee->dev);
3482 netif_carrier_on(ieee->dev);
3483 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003484
3485 CamRestoreAllEntry(dev);
3486
3487 priv->ResetProgress = RESET_TYPE_NORESET;
3488 priv->reset_count++;
3489
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003490 priv->bForcedSilentReset = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003491 priv->bResetInProgress = false;
3492
3493 // For test --> force write UFWP.
3494 write_nic_byte(dev, UFWP, 1);
3495 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003496 }
3497}
3498
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003499void CAM_read_entry(struct net_device *dev, u32 iIndex)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003500{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003501 u32 target_command = 0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003502 u32 target_content = 0;
3503 u8 entry_i = 0;
3504 u32 ulStatus;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003505 s32 i = 100;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003506 for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003507 // polling bit, and No Write enable, and address
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003508 target_command = entry_i+CAM_CONTENT_COUNT*iIndex;
3509 target_command = target_command | BIT31;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003510
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003511 //Check polling bit is clear
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003512 while ((i--) >= 0) {
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003513 read_nic_dword(dev, RWCAM, &ulStatus);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003514 if (ulStatus & BIT31)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003515 continue;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003516 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003517 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003518 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003519 write_nic_dword(dev, RWCAM, target_command);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003520 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x \n", target_command);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003521 read_nic_dword(dev, RCAMO, &target_content);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003522 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n", target_content);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003523 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003524 printk("\n");
3525}
3526
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003527void rtl819x_update_rxcounts(struct r8192_priv *priv, u32 *TotalRxBcnNum,
3528 u32 *TotalRxDataNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003529{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003530 u16 SlotIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003531 u8 i;
3532
3533 *TotalRxBcnNum = 0;
3534 *TotalRxDataNum = 0;
3535
3536 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
3537 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
3538 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003539 for (i = 0; i < priv->ieee80211->LinkDetectInfo.SlotNum; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003540 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
3541 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
3542 }
3543}
3544
3545
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003546extern void rtl819x_watchdog_wqcallback(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003547{
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003548 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003549 struct r8192_priv *priv = container_of(dwork, struct r8192_priv, watch_dog_wq);
3550 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003551 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003552 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003553 static u8 check_reset_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003554 bool bBusyTraffic = false;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003555 u32 TotalRxBcnNum = 0;
3556 u32 TotalRxDataNum = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003557
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003558 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003559 return;
3560 hal_dm_watchdog(dev);
3561
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003562 //to get busy traffic condition
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003563 if (ieee->state == IEEE80211_LINKED) {
3564 if (ieee->LinkDetectInfo.NumRxOkInPeriod > 666 ||
3565 ieee->LinkDetectInfo.NumTxOkInPeriod > 666 ) {
3566 bBusyTraffic = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003567 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003568 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
3569 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
3570 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
3571 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003572 //added by amy for AP roaming
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003573 if (priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003574
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003575 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
3576 if ((TotalRxBcnNum+TotalRxDataNum) == 0) {
3577#ifdef TODO
3578 if (rfState == eRfOff)
3579 RT_TRACE(COMP_ERR, "========>%s()\n", __func__);
3580#endif
3581 netdev_dbg(dev, "===>%s(): AP is power off, connect another one\n", __func__);
3582 priv->ieee80211->state = IEEE80211_ASSOCIATING;
3583 notify_wx_assoc_event(priv->ieee80211);
3584 RemovePeerTS(priv->ieee80211, priv->ieee80211->current_network.bssid);
3585 priv->ieee80211->link_change(dev);
3586 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003587
Jerry Chuang8fc85982009-11-03 07:17:11 -02003588 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003589 }
3590 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod = 0;
3591 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003592 //check if reset the driver
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003593 if (check_reset_cnt++ >= 3) {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003594 ResetType = rtl819x_ifcheck_resetornot(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003595 check_reset_cnt = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003596 }
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003597 if ((priv->force_reset) || (priv->ResetProgress == RESET_TYPE_NORESET &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003598 (priv->bForcedSilentReset ||
3599 (!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_SILENT)))) { // This is control by OID set in Pomelo
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003600 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 -02003601 rtl819x_ifsilentreset(dev);
3602 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003603 priv->force_reset = false;
3604 priv->bForcedSilentReset = false;
3605 priv->bResetInProgress = false;
3606 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
3607
3608}
3609
3610void watch_dog_timer_callback(unsigned long data)
3611{
3612 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003613 queue_delayed_work(priv->priv_wq, &priv->watch_dog_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003614 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
Jerry Chuang8fc85982009-11-03 07:17:11 -02003615}
3616int _rtl8192_up(struct net_device *dev)
3617{
3618 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003619 int init_status = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003620 priv->up = 1;
3621 priv->ieee80211->ieee_up = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003622 RT_TRACE(COMP_INIT, "Bringing up iface");
3623 init_status = rtl8192_adapter_start(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003624 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003625 RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization failed!\n", __func__);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003626 priv->up = priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003627 return -EAGAIN;
3628 }
3629 RT_TRACE(COMP_INIT, "start adapter finished\n");
3630 rtl8192_rx_enable(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003631 if (priv->ieee80211->state != IEEE80211_LINKED)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003632 ieee80211_softmac_start_protocol(priv->ieee80211);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003633 ieee80211_reset_queue(priv->ieee80211);
3634 watch_dog_timer_callback((unsigned long) dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003635 if (!netif_queue_stopped(dev))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003636 netif_start_queue(dev);
3637 else
3638 netif_wake_queue(dev);
3639
3640 return 0;
3641}
3642
3643
3644int rtl8192_open(struct net_device *dev)
3645{
3646 struct r8192_priv *priv = ieee80211_priv(dev);
3647 int ret;
3648 down(&priv->wx_sem);
3649 ret = rtl8192_up(dev);
3650 up(&priv->wx_sem);
3651 return ret;
3652
3653}
3654
3655
3656int rtl8192_up(struct net_device *dev)
3657{
3658 struct r8192_priv *priv = ieee80211_priv(dev);
3659
3660 if (priv->up == 1) return -1;
3661
3662 return _rtl8192_up(dev);
3663}
3664
3665
3666int rtl8192_close(struct net_device *dev)
3667{
3668 struct r8192_priv *priv = ieee80211_priv(dev);
3669 int ret;
3670
3671 down(&priv->wx_sem);
3672
3673 ret = rtl8192_down(dev);
3674
3675 up(&priv->wx_sem);
3676
3677 return ret;
3678
3679}
3680
3681int rtl8192_down(struct net_device *dev)
3682{
3683 struct r8192_priv *priv = ieee80211_priv(dev);
3684 int i;
3685
3686 if (priv->up == 0) return -1;
3687
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003688 priv->up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003689 priv->ieee80211->ieee_up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003690 RT_TRACE(COMP_DOWN, "==========>%s()\n", __func__);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003691 /* FIXME */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003692 if (!netif_queue_stopped(dev))
3693 netif_stop_queue(dev);
3694
3695 rtl8192_rtx_disable(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003696
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003697 /* Tx related queue release */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003698 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003699 skb_queue_purge(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003700 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003701 skb_queue_purge(&priv->ieee80211->skb_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003702
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003703 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003704 skb_queue_purge(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003705
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003706 //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 -02003707 rtl8192_cancel_deferred_work(priv);
3708 deinit_hal_dm(dev);
3709 del_timer_sync(&priv->watch_dog_timer);
3710
3711
3712 ieee80211_softmac_stop_protocol(priv->ieee80211);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003713 memset(&priv->ieee80211->current_network, 0, offsetof(struct ieee80211_network, list));
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003714 RT_TRACE(COMP_DOWN, "<==========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003715
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003716 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003717}
3718
3719
3720void rtl8192_commit(struct net_device *dev)
3721{
3722 struct r8192_priv *priv = ieee80211_priv(dev);
3723 int reset_status = 0;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003724 if (priv->up == 0) return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003725 priv->up = 0;
3726
3727 rtl8192_cancel_deferred_work(priv);
3728 del_timer_sync(&priv->watch_dog_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003729
3730 ieee80211_softmac_stop_protocol(priv->ieee80211);
3731
Jerry Chuang8fc85982009-11-03 07:17:11 -02003732 rtl8192_rtx_disable(dev);
3733 reset_status = _rtl8192_up(dev);
3734
3735}
3736
Jerry Chuang8fc85982009-11-03 07:17:11 -02003737void rtl8192_restart(struct work_struct *work)
3738{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003739 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
3740 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003741
3742 down(&priv->wx_sem);
3743
3744 rtl8192_commit(dev);
3745
3746 up(&priv->wx_sem);
3747}
3748
3749static void r8192_set_multicast(struct net_device *dev)
3750{
3751 struct r8192_priv *priv = ieee80211_priv(dev);
3752 short promisc;
3753
Jerry Chuang8fc85982009-11-03 07:17:11 -02003754 /* FIXME FIXME */
3755
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003756 promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003757
3758 if (promisc != priv->promisc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003759
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003760 priv->promisc = promisc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003761}
3762
3763
3764int r8192_set_mac_adr(struct net_device *dev, void *mac)
3765{
3766 struct r8192_priv *priv = ieee80211_priv(dev);
3767 struct sockaddr *addr = mac;
3768
3769 down(&priv->wx_sem);
3770
3771 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
3772
Jerry Chuang8fc85982009-11-03 07:17:11 -02003773 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003774 up(&priv->wx_sem);
3775
3776 return 0;
3777}
3778
3779/* based on ipw2200 driver */
3780int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3781{
3782 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3783 struct iwreq *wrq = (struct iwreq *)rq;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003784 int ret = -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003785 struct ieee80211_device *ieee = priv->ieee80211;
3786 u32 key[4];
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003787 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003788 struct iw_point *p = &wrq->u.data;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03003789 struct ieee_param *ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003790
3791 down(&priv->wx_sem);
3792
3793
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003794 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
3795 ret = -EINVAL;
3796 goto out;
3797 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003798
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003799 ipw = kmalloc(p->length, GFP_KERNEL);
3800 if (ipw == NULL) {
3801 ret = -ENOMEM;
3802 goto out;
3803 }
3804 if (copy_from_user(ipw, p->pointer, p->length)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003805 kfree(ipw);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003806 ret = -EFAULT;
3807 goto out;
3808 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003809
3810 switch (cmd) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003811 case RTL_IOCTL_WPA_SUPPLICANT:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003812 //parse here for HW security
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003813 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) {
3814 if (ipw->u.crypt.set_tx) {
3815 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003816 ieee->pairwise_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003817 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003818 ieee->pairwise_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003819 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003820 if (ipw->u.crypt.key_len == 13)
3821 ieee->pairwise_key_type = KEY_TYPE_WEP104;
3822 else if (ipw->u.crypt.key_len == 5)
3823 ieee->pairwise_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003824 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003825 ieee->pairwise_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003826 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003827
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003828 if (ieee->pairwise_key_type) {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003829 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003830 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003831 //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!
3832 //added by WB.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003833 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 +01003834 if (ieee->auth_mode != 2)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003835 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 -02003836 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003837 } else {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003838 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003839 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003840 ieee->group_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003841 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003842 ieee->group_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003843 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003844 if (ipw->u.crypt.key_len == 13)
3845 ieee->group_key_type = KEY_TYPE_WEP104;
3846 else if (ipw->u.crypt.key_len == 5)
3847 ieee->group_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003848 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003849 ieee->group_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003850 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003851
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003852 if (ieee->group_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003853 setKey(dev, ipw->u.crypt.idx,
3854 ipw->u.crypt.idx, //KeyIndex
3855 ieee->group_key_type, //KeyType
3856 broadcast_addr, //MacAddr
3857 0, //DefaultKey
3858 key); //KeyContent
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003859 }
3860 }
3861 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003862#ifdef JOHN_HWSEC_DEBUG
3863 //john's test 0711
3864 printk("@@ wrq->u pointer = ");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003865 for (i = 0; i < wrq->u.data.length; i++) {
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003866 if (i%10 == 0) printk("\n");
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003867 printk("%8x|", ((u32 *)wrq->u.data.pointer)[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003868 }
3869 printk("\n");
3870#endif /*JOHN_HWSEC_DEBUG*/
3871 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
3872 break;
3873
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003874 default:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003875 ret = -EOPNOTSUPP;
3876 break;
3877 }
3878 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003879 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003880out:
3881 up(&priv->wx_sem);
3882 return ret;
3883}
3884
3885u8 HwRateToMRate90(bool bIsHT, u8 rate)
3886{
3887 u8 ret_rate = 0xff;
3888
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003889 if (!bIsHT) {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003890 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003891 case DESC90_RATE1M: ret_rate = MGN_1M; break;
3892 case DESC90_RATE2M: ret_rate = MGN_2M; break;
3893 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
3894 case DESC90_RATE11M: ret_rate = MGN_11M; break;
3895 case DESC90_RATE6M: ret_rate = MGN_6M; break;
3896 case DESC90_RATE9M: ret_rate = MGN_9M; break;
3897 case DESC90_RATE12M: ret_rate = MGN_12M; break;
3898 case DESC90_RATE18M: ret_rate = MGN_18M; break;
3899 case DESC90_RATE24M: ret_rate = MGN_24M; break;
3900 case DESC90_RATE36M: ret_rate = MGN_36M; break;
3901 case DESC90_RATE48M: ret_rate = MGN_48M; break;
3902 case DESC90_RATE54M: ret_rate = MGN_54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003903
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003904 default:
3905 ret_rate = 0xff;
3906 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
3907 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003908 }
3909
3910 } else {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003911 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003912 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
3913 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
3914 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
3915 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
3916 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
3917 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
3918 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
3919 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
3920 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
3921 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
3922 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
3923 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
3924 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
3925 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
3926 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
3927 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
3928 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003929
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003930 default:
3931 ret_rate = 0xff;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003932 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003933 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003934 }
3935 }
3936
3937 return ret_rate;
3938}
3939
3940/**
3941 * Function: UpdateRxPktTimeStamp
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003942 * Overview: Record the TSF time stamp when receiving a packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02003943 *
3944 * Input:
3945 * PADAPTER Adapter
3946 * PRT_RFD pRfd,
3947 *
3948 * Output:
3949 * PRT_RFD pRfd
3950 * (pRfd->Status.TimeStampHigh is updated)
3951 * (pRfd->Status.TimeStampLow is updated)
3952 * Return:
3953 * None
3954 */
Xenia Ragiadakoue6367212013-05-23 05:14:46 +03003955void UpdateRxPktTimeStamp8190(struct net_device *dev, struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003956{
3957 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3958
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003959 if (stats->bIsAMPDU && !stats->bFirstMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003960 stats->mac_time[0] = priv->LastRxDescTSFLow;
3961 stats->mac_time[1] = priv->LastRxDescTSFHigh;
3962 } else {
3963 priv->LastRxDescTSFLow = stats->mac_time[0];
3964 priv->LastRxDescTSFHigh = stats->mac_time[1];
3965 }
3966}
3967
3968//by amy 080606
3969
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003970long rtl819x_translate_todbm(u8 signal_strength_index)// 0-100 index.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003971{
3972 long signal_power; // in dBm.
3973
3974 // Translate to dBm (x=0.5y-95).
3975 signal_power = (long)((signal_strength_index + 1) >> 1);
3976 signal_power -= 95;
3977
3978 return signal_power;
3979}
3980
3981
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003982/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
Jerry Chuang8fc85982009-11-03 07:17:11 -02003983 be a local static. Otherwise, it may increase when we return from S3/S4. The
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003984 value will be kept in memory or disk. Declare the value in the adaptor
3985 and it will be reinitialized when returned from S3/S4. */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003986void 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 -02003987{
3988 bool bcheck = false;
3989 u8 rfpath;
3990 u32 nspatial_stream, tmp_val;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003991 static u32 slide_rssi_index, slide_rssi_statistics;
3992 static u32 slide_evm_index, slide_evm_statistics;
3993 static u32 last_rssi, last_evm;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003994
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003995 static u32 slide_beacon_adc_pwdb_index, slide_beacon_adc_pwdb_statistics;
3996 static u32 last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003997
3998 struct ieee80211_hdr_3addr *hdr;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003999 u16 sc;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004000 unsigned int frag, seq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004001 hdr = (struct ieee80211_hdr_3addr *)buffer;
4002 sc = le16_to_cpu(hdr->seq_ctl);
4003 frag = WLAN_GET_SEQ_FRAG(sc);
4004 seq = WLAN_GET_SEQ_SEQ(sc);
4005 //cosa add 04292008 to record the sequence number
4006 pcurrent_stats->Seq_Num = seq;
4007 //
4008 // Check whether we should take the previous packet into accounting
4009 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004010 if (!pprevious_stats->bIsAMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004011 // if previous packet is not aggregated packet
4012 bcheck = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004013 }
4014
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004015 if (slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004016 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
4017 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
4018 priv->stats.slide_rssi_total -= last_rssi;
4019 }
4020 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
4021
4022 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004023 if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004024 slide_rssi_index = 0;
4025
4026 // <1> Showed on UI for user, in dbm
4027 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
4028 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
4029 pcurrent_stats->rssi = priv->stats.signal_strength;
4030 //
4031 // If the previous packet does not match the criteria, neglect it
4032 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004033 if (!pprevious_stats->bPacketMatchBSSID) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004034 if (!pprevious_stats->bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004035 return;
4036 }
4037
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004038 if (!bcheck)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004039 return;
4040
4041
4042 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
4043
4044 //
4045 // Check RSSI
4046 //
4047 priv->stats.num_process_phyinfo++;
4048
4049 /* record the general signal strength to the sliding window. */
4050
4051
4052 // <2> Showed on UI for engineering
4053 // hardware does not provide rssi information for each rf path in CCK
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004054 if (!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA)) {
4055 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004056 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
4057 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004058
4059 //Fixed by Jacken 2008-03-20
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004060 if (priv->stats.rx_rssi_percentage[rfpath] == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004061 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004062 if (pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath]) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004063 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004064 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004065 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004066 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004067 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004068 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004069 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004070 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004071 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004072 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 -02004073 }
4074 }
4075
4076
4077 //
4078 // Check PWDB.
4079 //
4080 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004081 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004082 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004083
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004084 if (pprevious_stats->bPacketBeacon) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004085 /* record the beacon pwdb to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004086 if (slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004087 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
4088 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
4089 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004090 }
4091 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
4092 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004093 slide_beacon_adc_pwdb_index++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004094 if (slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004095 slide_beacon_adc_pwdb_index = 0;
4096 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004097 if (pprevious_stats->RxPWDBAll >= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004098 pprevious_stats->RxPWDBAll -= 3;
4099 }
4100
4101 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004102 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004103 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004104
4105
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004106 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004107 if (priv->undecorated_smoothed_pwdb < 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004108 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004109 if (pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004110 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004111 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4112 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004113 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004114 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004115 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004116 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4117 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004118 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004119
4120 }
4121
4122 //
4123 // Check EVM
4124 //
4125 /* record the general EVM to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004126 if (pprevious_stats->SignalQuality) {
4127 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4128 if (slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004129 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
4130 last_evm = priv->stats.slide_evm[slide_evm_index];
4131 priv->stats.slide_evm_total -= last_evm;
4132 }
4133
4134 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
4135
4136 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004137 if (slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004138 slide_evm_index = 0;
4139
4140 // <1> Showed on UI for user, in percentage.
4141 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
4142 priv->stats.signal_quality = tmp_val;
4143 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
4144 priv->stats.last_signal_strength_inpercent = tmp_val;
4145 }
4146
4147 // <2> Showed on UI for engineering
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004148 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4149 for (nspatial_stream = 0; nspatial_stream < 2; nspatial_stream++) { // 2 spatial stream
4150 if (pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004151 if (priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004152 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
Jerry Chuang8fc85982009-11-03 07:17:11 -02004153 priv->stats.rx_evm_percentage[nspatial_stream] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004154 ((priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004155 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004156 }
4157 }
4158 }
4159 }
4160
4161
4162}
4163
4164/*-----------------------------------------------------------------------------
4165 * Function: rtl819x_query_rxpwrpercentage()
4166 *
4167 * Overview:
4168 *
4169 * Input: char antpower
4170 *
4171 * Output: NONE
4172 *
4173 * Return: 0-100 percentage
4174 *
4175 * Revised History:
4176 * When Who Remark
4177 * 05/26/2008 amy Create Version 0 porting from windows code.
4178 *
4179 *---------------------------------------------------------------------------*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004180static u8 rtl819x_query_rxpwrpercentage(char antpower)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004181{
4182 if ((antpower <= -100) || (antpower >= 20))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004183 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004184 else if (antpower >= 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004185 return 100;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004186 else
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004187 return 100 + antpower;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004188
4189} /* QueryRxPwrPercentage */
4190
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004191static u8 rtl819x_evm_dbtopercentage(char value)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004192{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004193 char ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004194
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004195 ret_val = value;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004196
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004197 if (ret_val >= 0)
4198 ret_val = 0;
4199 if (ret_val <= -33)
4200 ret_val = -33;
4201 ret_val = 0 - ret_val;
4202 ret_val *= 3;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004203 if (ret_val == 99)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004204 ret_val = 100;
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004205 return ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004206}
4207//
4208// Description:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004209// We want good-looking for signal strength/quality
Jerry Chuang8fc85982009-11-03 07:17:11 -02004210// 2007/7/19 01:09, by cosa.
4211//
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004212long rtl819x_signal_scale_mapping(long currsig)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004213{
4214 long retsig;
4215
4216 // Step 1. Scale mapping.
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004217 if (currsig >= 61 && currsig <= 100)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004218 retsig = 90 + ((currsig - 60) / 4);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004219 else if (currsig >= 41 && currsig <= 60)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004220 retsig = 78 + ((currsig - 40) / 2);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004221 else if (currsig >= 31 && currsig <= 40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004222 retsig = 66 + (currsig - 30);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004223 else if (currsig >= 21 && currsig <= 30)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004224 retsig = 54 + (currsig - 20);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004225 else if (currsig >= 5 && currsig <= 20)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004226 retsig = 42 + (((currsig - 5) * 2) / 3);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004227 else if (currsig == 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004228 retsig = 36;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004229 else if (currsig == 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004230 retsig = 27;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004231 else if (currsig == 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004232 retsig = 18;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004233 else if (currsig == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004234 retsig = 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004235 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004236 retsig = currsig;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004237
4238 return retsig;
4239}
4240
Xenia Ragiadakouf2c3d802013-06-04 23:32:32 +03004241static inline bool rx_hal_is_cck_rate(struct rx_drvinfo_819x_usb *pdrvinfo)
4242{
4243 if (pdrvinfo->RxHT)
4244 return false;
4245
4246 switch (pdrvinfo->RxRate) {
4247 case DESC90_RATE1M:
4248 case DESC90_RATE2M:
4249 case DESC90_RATE5_5M:
4250 case DESC90_RATE11M:
4251 return true;
4252 default:
4253 return false;
4254 }
4255}
4256
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004257static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
4258 struct ieee80211_rx_stats *pstats,
4259 rx_drvinfo_819x_usb *pdrvinfo,
4260 struct ieee80211_rx_stats *precord_stats,
4261 bool bpacket_match_bssid,
4262 bool bpacket_toself,
4263 bool bPacketBeacon,
4264 bool bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004265{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004266 phy_sts_ofdm_819xusb_t *pofdm_buf;
4267 phy_sts_cck_819xusb_t *pcck_buf;
4268 phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004269 u8 *prxpkt;
4270 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004271 char rx_pwr[4], rx_pwr_all = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004272 char rx_snrX, rx_evmX;
4273 u8 evm, pwdb_all;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004274 u32 RSSI, total_rssi = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004275 u8 is_cck_rate = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004276 u8 rf_rx_num = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004277 u8 sq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004278
4279
4280 priv->stats.numqry_phystatus++;
4281
4282 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4283
4284 // Record it for next packet processing
4285 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4286 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4287 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004288 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004289 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4290 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4291
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004292 prxpkt = (u8 *)pdrvinfo;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004293
4294 /* Move pointer to the 16th bytes. Phy status start address. */
4295 prxpkt += sizeof(rx_drvinfo_819x_usb);
4296
4297 /* Initial the cck and ofdm buffer pointer */
4298 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
4299 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
4300
4301 pstats->RxMIMOSignalQuality[0] = -1;
4302 pstats->RxMIMOSignalQuality[1] = -1;
4303 precord_stats->RxMIMOSignalQuality[0] = -1;
4304 precord_stats->RxMIMOSignalQuality[1] = -1;
4305
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004306 if (is_cck_rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004307 //
4308 // (1)Hardware does not provide RSSI for CCK
4309 //
4310
4311 //
4312 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4313 //
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004314 u8 report;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004315
4316 priv->stats.numqry_phystatusCCK++;
4317
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004318 if (!priv->bCckHighPower) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004319 report = pcck_buf->cck_agc_rpt & 0xc0;
4320 report = report>>6;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004321 switch (report) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004322 //Fixed by Jacken from Bryant 2008-03-20
4323 //Original value is -38 , -26 , -14 , -2
4324 //Fixed value is -35 , -23 , -11 , 6
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004325 case 0x3:
4326 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4327 break;
4328 case 0x2:
4329 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4330 break;
4331 case 0x1:
4332 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4333 break;
4334 case 0x0:
4335 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
4336 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004337 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004338 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004339 report = pcck_buf->cck_agc_rpt & 0x60;
4340 report = report>>5;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004341 switch (report) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004342 case 0x3:
4343 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4344 break;
4345 case 0x2:
4346 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4347 break;
4348 case 0x1:
4349 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4350 break;
4351 case 0x0:
4352 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4353 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004354 }
4355 }
4356
4357 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4358 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4359 pstats->RecvSignalPower = pwdb_all;
4360
4361 //
4362 // (3) Get Signal Quality (EVM)
4363 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02004364
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004365 if (pstats->RxPWDBAll > 40) {
4366 sq = 100;
4367 } else {
4368 sq = pcck_buf->sq_rpt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004369
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004370 if (pcck_buf->sq_rpt > 64)
4371 sq = 0;
4372 else if (pcck_buf->sq_rpt < 20)
4373 sq = 100;
4374 else
4375 sq = ((64-sq) * 100) / 44;
4376 }
4377 pstats->SignalQuality = precord_stats->SignalQuality = sq;
4378 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
4379 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004380
4381 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004382 priv->stats.numqry_phystatusHT++;
4383 //
4384 // (1)Get RSSI for HT rate
4385 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004386 for (i = RF90_PATH_A; i < priv->NumTotalRFPath; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004387 // 2008/01/30 MH we will judge RF RX path now.
4388 if (priv->brfpath_rxenable[i])
4389 rf_rx_num++;
4390 else
4391 continue;
4392
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004393 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004394 continue;
4395
4396 //Fixed by Jacken from Bryant 2008-03-20
4397 //Original value is 106
4398 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
4399
4400 //Get Rx snr value in DB
4401 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
4402 rx_snrX = (char)(tmp_rxsnr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004403 rx_snrX /= 2;
4404 priv->stats.rxSNRdB[i] = (long)rx_snrX;
4405
4406 /* Translate DBM to percentage. */
4407 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
4408 total_rssi += RSSI;
4409
4410 /* Record Signal Strength for next packet */
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004411 pstats->RxMIMOSignalStrength[i] = (u8) RSSI;
4412 precord_stats->RxMIMOSignalStrength[i] = (u8) RSSI;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004413 }
4414
4415
4416 //
4417 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4418 //
4419 //Fixed by Jacken from Bryant 2008-03-20
4420 //Original value is 106
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004421 rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1)& 0x7f) -106;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004422 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4423
4424 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4425 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
4426
4427 //
4428 // (3)EVM of HT rate
4429 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004430 if (pdrvinfo->RxHT && pdrvinfo->RxRate >= DESC90_RATEMCS8 &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004431 pdrvinfo->RxRate <= DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004432 max_spatial_stream = 2; //both spatial stream make sense
4433 else
4434 max_spatial_stream = 1; //only spatial stream 1 makes sense
4435
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004436 for (i = 0; i < max_spatial_stream; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004437 tmp_rxevm = pofdm_buf->rxevm_X[i];
4438 rx_evmX = (char)(tmp_rxevm);
4439
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004440 // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004441 // will set the most significant bit to "zero" when doing shifting operation which may change a negative
Jerry Chuang8fc85982009-11-03 07:17:11 -02004442 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
4443 rx_evmX /= 2; //dbm
4444
4445 evm = rtl819x_evm_dbtopercentage(rx_evmX);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004446 if (i == 0) // Fill value in RFD, Get the first spatial stream only
4447 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
4448 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004449 }
4450
4451
4452 /* record rx statistics for debug */
4453 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
4454 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004455 if (pdrvinfo->BW) //40M channel
Jerry Chuang8fc85982009-11-03 07:17:11 -02004456 priv->stats.received_bwtype[1+prxsc->rxsc]++;
4457 else //20M channel
4458 priv->stats.received_bwtype[0]++;
4459 }
4460
4461 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
4462 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004463 if (is_cck_rate) {
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004464 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004465 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004466 // We can judge RX path number now.
4467 if (rf_rx_num != 0)
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004468 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi /= rf_rx_num)));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004469 }
4470} /* QueryRxPhyStatus8190Pci */
4471
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004472void rtl8192_record_rxdesc_forlateruse(struct ieee80211_rx_stats *psrc_stats,
4473 struct ieee80211_rx_stats *ptarget_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004474{
4475 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
4476 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
4477 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
4478}
4479
4480
4481void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004482 struct ieee80211_rx_stats *pstats,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004483 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004484{
4485 // TODO: We must only check packet for current MAC address. Not finish
4486 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004487 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004488 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4489 bool bpacket_match_bssid, bpacket_toself;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004490 bool bPacketBeacon = FALSE, bToSelfBA = FALSE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004491 static struct ieee80211_rx_stats previous_stats;
4492 struct ieee80211_hdr_3addr *hdr;//by amy
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004493 u16 fc, type;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004494
4495 // Get Signal Quality for only RX data queue (but not command queue)
4496
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004497 u8 *tmp_buf;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004498 u8 *praddr;
4499
4500 /* Get MAC frame start address. */
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004501 tmp_buf = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004502
4503 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
4504 fc = le16_to_cpu(hdr->frame_ctl);
4505 type = WLAN_FC_GET_TYPE(fc);
4506 praddr = hdr->addr1;
4507
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004508 /* Check if the received packet is acceptable. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004509 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004510 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
4511 && (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004512 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
4513
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004514 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON)
4515 bPacketBeacon = true;
4516 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK) {
4517 if ((eqMacAddr(praddr, dev->dev_addr)))
4518 bToSelfBA = true;
4519 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004520
Jerry Chuang8fc85982009-11-03 07:17:11 -02004521
4522
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004523 if (bpacket_match_bssid)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004524 priv->stats.numpacket_matchbssid++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004525 if (bpacket_toself)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004526 priv->stats.numpacket_toself++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004527 //
4528 // Process PHY information for previous packet (RSSI/PWDB/EVM)
4529 //
4530 // Because phy information is contained in the last packet of AMPDU only, so driver
4531 // should process phy information of previous packet
4532 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004533 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid, bpacket_toself, bPacketBeacon, bToSelfBA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004534 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
4535
4536}
4537
4538/**
4539* Function: UpdateReceivedRateHistogramStatistics
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004540* Overview: Record the received data rate
Jerry Chuang8fc85982009-11-03 07:17:11 -02004541*
4542* Input:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004543* struct net_device *dev
Jerry Chuang8fc85982009-11-03 07:17:11 -02004544* struct ieee80211_rx_stats *stats
4545*
4546* Output:
4547*
4548* (priv->stats.ReceivedRateHistogram[] is updated)
4549* Return:
4550* None
4551*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004552void UpdateReceivedRateHistogramStatistics8190(struct net_device *dev,
4553 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004554{
4555 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004556 u32 rcvType = 1; //0: Total, 1:OK, 2:CRC, 3:ICV
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004557 u32 rateIndex;
4558 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02004559
4560
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004561 if (stats->bCRC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004562 rcvType = 2;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004563 else if (stats->bICV)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004564 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004565
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004566 if (stats->bShortPreamble)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004567 preamble_guardinterval = 1;// short
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004568 else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004569 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02004570
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004571 switch (stats->rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004572 //
4573 // CCK rate
4574 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004575 case MGN_1M: rateIndex = 0; break;
4576 case MGN_2M: rateIndex = 1; break;
4577 case MGN_5_5M: rateIndex = 2; break;
4578 case MGN_11M: rateIndex = 3; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004579 //
4580 // Legacy OFDM rate
4581 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004582 case MGN_6M: rateIndex = 4; break;
4583 case MGN_9M: rateIndex = 5; break;
4584 case MGN_12M: rateIndex = 6; break;
4585 case MGN_18M: rateIndex = 7; break;
4586 case MGN_24M: rateIndex = 8; break;
4587 case MGN_36M: rateIndex = 9; break;
4588 case MGN_48M: rateIndex = 10; break;
4589 case MGN_54M: rateIndex = 11; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004590 //
4591 // 11n High throughput rate
4592 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004593 case MGN_MCS0: rateIndex = 12; break;
4594 case MGN_MCS1: rateIndex = 13; break;
4595 case MGN_MCS2: rateIndex = 14; break;
4596 case MGN_MCS3: rateIndex = 15; break;
4597 case MGN_MCS4: rateIndex = 16; break;
4598 case MGN_MCS5: rateIndex = 17; break;
4599 case MGN_MCS6: rateIndex = 18; break;
4600 case MGN_MCS7: rateIndex = 19; break;
4601 case MGN_MCS8: rateIndex = 20; break;
4602 case MGN_MCS9: rateIndex = 21; break;
4603 case MGN_MCS10: rateIndex = 22; break;
4604 case MGN_MCS11: rateIndex = 23; break;
4605 case MGN_MCS12: rateIndex = 24; break;
4606 case MGN_MCS13: rateIndex = 25; break;
4607 case MGN_MCS14: rateIndex = 26; break;
4608 case MGN_MCS15: rateIndex = 27; break;
4609 default: rateIndex = 28; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004610 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004611 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
4612 priv->stats.received_rate_histogram[0][rateIndex]++; //total
4613 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004614}
4615
4616
4617void query_rxdesc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats, bool bIsRxAggrSubframe)
4618{
4619 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004620 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004621 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004622 rx_drvinfo_819x_usb *driver_info = NULL;
4623
4624 //
4625 //Get Rx Descriptor Information
4626 //
4627#ifdef USB_RX_AGGREGATION_SUPPORT
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004628 if (bIsRxAggrSubframe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004629 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004630 stats->Length = desc->Length;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004631 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
4632 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
4633 stats->bICV = desc->ICV;
4634 stats->bCRC = desc->CRC32;
4635 stats->bHwError = stats->bCRC|stats->bICV;
4636 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
4637 } else
4638#endif
4639 {
4640 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
4641
4642 stats->Length = desc->Length;
4643 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004644 stats->RxBufShift = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004645 stats->bICV = desc->ICV;
4646 stats->bCRC = desc->CRC32;
4647 stats->bHwError = stats->bCRC|stats->bICV;
4648 //RTL8190 set this bit to indicate that Hw does not decrypt packet
4649 stats->Decrypted = !desc->SWDec;
4650 }
4651
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004652 if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004653 stats->bHwError = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004654 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004655 stats->bHwError = stats->bCRC|stats->bICV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004656
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004657 if (stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004658 stats->bHwError |= 1;
4659 //
4660 //Get Driver Info
4661 //
4662 // TODO: Need to verify it on FGPA platform
4663 //Driver info are written to the RxBuffer following rx desc
4664 if (stats->RxDrvInfoSize != 0) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004665 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004666 stats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004667 /* unit: 0.5M */
4668 /* TODO */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004669 if (!stats->bHwError) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004670 u8 ret_rate;
4671 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004672 if (ret_rate == 0xff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004673 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
4674 // Special Error Handling here, 2008.05.16, by Emily
4675
4676 stats->bHwError = 1;
4677 stats->rate = MGN_1M; //Set 1M rate by default
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004678 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004679 stats->rate = ret_rate;
4680 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004681 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004682 stats->rate = 0x02;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004683 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004684
4685 stats->bShortPreamble = driver_info->SPLCP;
4686
4687
4688 UpdateReceivedRateHistogramStatistics8190(dev, stats);
4689
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004690 stats->bIsAMPDU = (driver_info->PartAggr == 1);
4691 stats->bFirstMPDU = (driver_info->PartAggr == 1) && (driver_info->FirstAGGR == 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004692 stats->TimeStampLow = driver_info->TSFL;
4693 // xiong mask it, 070514
Jerry Chuang8fc85982009-11-03 07:17:11 -02004694
4695 UpdateRxPktTimeStamp8190(dev, stats);
4696
4697 //
4698 // Rx A-MPDU
4699 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004700 if (driver_info->FirstAGGR == 1 || driver_info->PartAggr == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004701 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004702 driver_info->FirstAGGR, driver_info->PartAggr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004703
4704 }
4705
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004706 skb_pull(skb, sizeof(rx_desc_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004707 //
4708 // Get Total offset of MPDU Frame Body
4709 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004710 if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004711 stats->bShift = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004712 skb_pull(skb, stats->RxBufShift + stats->RxDrvInfoSize);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004713 }
4714
4715#ifdef USB_RX_AGGREGATION_SUPPORT
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004716 /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004717 if (bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004718 skb_pull(skb, 8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004719#endif
4720 /* for debug 2008.5.29 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004721
4722 //added by vivi, for MP, 20080108
4723 stats->RxIs40MHzPacket = driver_info->BW;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004724 if (stats->RxDrvInfoSize != 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004725 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
4726
4727}
4728
4729u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
4730{
4731#ifdef USB_RX_AGGREGATION_SUPPORT
4732 if (bIsRxAggrSubframe)
4733 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
4734 + Status->RxBufShift + 8);
4735 else
4736#endif
4737 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004738 + Status->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004739}
4740
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004741void rtl8192_rx_nomal(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004742{
4743 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004744 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004745 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4746 struct ieee80211_rx_stats stats = {
4747 .signal = 0,
4748 .noise = -98,
4749 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004750 .freq = IEEE80211_24GHZ_BAND,
4751 };
4752 u32 rx_pkt_len = 0;
4753 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
4754 bool unicast_packet = false;
4755#ifdef USB_RX_AGGREGATION_SUPPORT
4756 struct sk_buff *agg_skb = NULL;
4757 u32 TotalLength = 0;
4758 u32 TempDWord = 0;
4759 u32 PacketLength = 0;
4760 u32 PacketOccupiedLendth = 0;
4761 u8 TempByte = 0;
4762 u32 PacketShiftBytes = 0;
4763 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
4764 u8 PaddingBytes = 0;
4765 //add just for testing
4766 u8 testing;
4767
4768#endif
4769
4770 /* 20 is for ps-poll */
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004771 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004772#ifdef USB_RX_AGGREGATION_SUPPORT
4773 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
4774#endif
4775 /* first packet should not contain Rx aggregation header */
4776 query_rxdesc_status(skb, &stats, false);
4777 /* TODO */
4778 /* hardware related info */
4779#ifdef USB_RX_AGGREGATION_SUPPORT
4780 if (TempByte & BIT0) {
4781 agg_skb = skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004782 TotalLength = stats.Length - 4; /*sCrcLng*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02004783 /* though the head pointer has passed this position */
4784 TempDWord = *(u32 *)(agg_skb->data - 4);
4785 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
4786 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004787 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004788 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
4789 }
4790#endif
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004791 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004792 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4793
4794 rx_pkt_len = skb->len;
4795 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4796 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004797 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004798 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004799 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004800 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004801 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004802 /* unicast packet */
4803 unicast_packet = true;
4804 }
4805
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004806 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004807 dev_kfree_skb_any(skb);
4808 } else {
4809 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004810 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004811 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004812 }
4813#ifdef USB_RX_AGGREGATION_SUPPORT
4814 testing = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004815 if (TotalLength > 0) {
4816 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
4817 if ((PacketOccupiedLendth & 0xFF) != 0)
4818 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
4819 PacketOccupiedLendth -= 8;
4820 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
4821 if (agg_skb->len > TempDWord)
4822 skb_pull(agg_skb, TempDWord);
4823 else
4824 agg_skb->len = 0;
4825
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004826 while (agg_skb->len >= GetRxPacketShiftBytes819xUsb(&stats, true)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004827 u8 tmpCRC = 0, tmpICV = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004828 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
4829 tmpCRC = RxDescr->CRC32;
4830 tmpICV = RxDescr->ICV;
4831 memcpy(agg_skb->data, &agg_skb->data[44], 2);
4832 RxDescr->CRC32 = tmpCRC;
4833 RxDescr->ICV = tmpICV;
4834
4835 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
4836 stats.signal = 0;
4837 stats.noise = -98;
4838 stats.rate = 0;
4839 stats.freq = IEEE80211_24GHZ_BAND;
4840 query_rxdesc_status(agg_skb, &stats, true);
4841 PacketLength = stats.Length;
4842
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004843 if (PacketLength > agg_skb->len)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004844 break;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004845 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004846 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004847 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004848 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4849
4850 rx_pkt_len = skb->len;
4851 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4852 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004853 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004854 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004855 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004856 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004857 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004858 /* unicast packet */
4859 unicast_packet = true;
4860 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004861 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004862 dev_kfree_skb_any(skb);
4863 } else {
4864 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004865 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004866 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004867 }
4868 /* should trim the packet which has been copied to target skb */
4869 skb_pull(agg_skb, PacketLength);
4870 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
4871 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
4872 if ((PacketOccupiedLendth & 0xFF) != 0) {
4873 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
4874 if (agg_skb->len > PaddingBytes)
4875 skb_pull(agg_skb, PaddingBytes);
4876 else
4877 agg_skb->len = 0;
4878 }
4879 }
4880 dev_kfree_skb(agg_skb);
4881 }
4882#endif
4883 } else {
4884 priv->stats.rxurberr++;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03004885 netdev_dbg(dev, "actual_length: %d\n", skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004886 dev_kfree_skb_any(skb);
4887 }
4888
4889}
4890
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004891void rtl819xusb_process_received_packet(struct net_device *dev,
4892 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004893{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004894 u8 *frame;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004895 u16 frame_len = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004896 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004897
4898 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
4899 //porting by amy 080508
4900 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
4901 frame = pstats->virtual_address;
4902 frame_len = pstats->packetlength;
4903#ifdef TODO // by amy about HCT
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004904 if (!Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004905 CountRxErrStatistics(Adapter, pRfd);
4906#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004907#ifdef ENABLE_PS //by amy for adding ps function in future
4908 RT_RF_POWER_STATE rtState;
4909 // When RF is off, we should not count the packet for hw/sw synchronize
4910 // reason, ie. there may be a duration while sw switch is changed and hw
4911 // switch is being changed. 2006.12.04, by shien chang.
4912 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8 *)(&rtState));
4913 if (rtState == eRfOff)
4914 return;
4915#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -02004916 priv->stats.rxframgment++;
4917
Jerry Chuang8fc85982009-11-03 07:17:11 -02004918#ifdef TODO
4919 RmMonitorSignalStrength(Adapter, pRfd);
4920#endif
4921 /* 2007/01/16 MH Add RX command packet handle here. */
4922 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
4923 if (rtl819xusb_rx_command_packet(dev, pstats))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004924 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004925
4926#ifdef SW_CRC_CHECK
4927 SwCrcCheck();
4928#endif
4929
4930
4931}
4932
4933void query_rx_cmdpkt_desc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats)
4934{
Jerry Chuang8fc85982009-11-03 07:17:11 -02004935 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004936
4937 //
4938 //Get Rx Descriptor Information
4939 //
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004940 stats->virtual_address = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004941 stats->Length = desc->Length;
4942 stats->RxDrvInfoSize = 0;
4943 stats->RxBufShift = 0;
4944 stats->packetlength = stats->Length-scrclng;
4945 stats->fraglength = stats->packetlength;
4946 stats->fragoffset = 0;
4947 stats->ntotalfrag = 1;
4948}
4949
4950
4951void rtl8192_rx_cmd(struct sk_buff *skb)
4952{
4953 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
4954 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004955 /* TODO */
4956 struct ieee80211_rx_stats stats = {
4957 .signal = 0,
4958 .noise = -98,
4959 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004960 .freq = IEEE80211_24GHZ_BAND,
4961 };
4962
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004963 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004964
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004965 query_rx_cmdpkt_desc_status(skb, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004966 // this is to be done by amy 080508 prfd->queue_id = 1;
4967
4968
4969 //
4970 // Process the command packet received.
4971 //
4972
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004973 rtl819xusb_process_received_packet(dev, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004974
4975 dev_kfree_skb_any(skb);
4976 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004977}
4978
4979void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
4980{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004981 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004982 struct rtl8192_rx_info *info;
4983
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004984 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004985 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004986 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004987 /* Nomal packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004988 case 3:
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004989 priv->IrpPendingCount--;
4990 rtl8192_rx_nomal(skb);
4991 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004992
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004993 /* Command packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004994 case 9:
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004995 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004996 info->out_pipe);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004997
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004998 rtl8192_rx_cmd(skb);
4999 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005000
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005001 default: /* should never get here! */
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03005002 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005003 info->out_pipe);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005004 dev_kfree_skb(skb);
5005 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005006
5007 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005008 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005009}
5010
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005011static const struct net_device_ops rtl8192_netdev_ops = {
5012 .ndo_open = rtl8192_open,
5013 .ndo_stop = rtl8192_close,
5014 .ndo_get_stats = rtl8192_stats,
5015 .ndo_tx_timeout = tx_timeout,
5016 .ndo_do_ioctl = rtl8192_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00005017 .ndo_set_rx_mode = r8192_set_multicast,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005018 .ndo_set_mac_address = r8192_set_mac_adr,
5019 .ndo_validate_addr = eth_validate_addr,
5020 .ndo_change_mtu = eth_change_mtu,
5021 .ndo_start_xmit = ieee80211_xmit,
5022};
Jerry Chuang8fc85982009-11-03 07:17:11 -02005023
5024
5025/****************************************************************************
5026 ---------------------------- USB_STUFF---------------------------
5027*****************************************************************************/
5028
Bill Pemberton25794522012-11-19 13:22:04 -05005029static int rtl8192_usb_probe(struct usb_interface *intf,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005030 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005031{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005032 struct net_device *dev = NULL;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005033 struct r8192_priv *priv = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005034 struct usb_device *udev = interface_to_usbdev(intf);
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005035 int ret;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005036 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005037
5038 dev = alloc_ieee80211(sizeof(struct r8192_priv));
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005039 if (dev == NULL)
5040 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005041
Jerry Chuang8fc85982009-11-03 07:17:11 -02005042 usb_set_intfdata(intf, dev);
5043 SET_NETDEV_DEV(dev, &intf->dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005044 priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005045 priv->ieee80211 = netdev_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005046 priv->udev = udev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005047
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005048 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005049
Jerry Chuang8fc85982009-11-03 07:17:11 -02005050#if WIRELESS_EXT >= 12
5051#if WIRELESS_EXT < 17
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005052 dev->get_wireless_stats = r8192_get_wireless_stats;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005053#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005054 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005055#endif
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005056 dev->type = ARPHRD_ETHER;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005057
5058 dev->watchdog_timeo = HZ*3; //modified by john, 0805
5059
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005060 if (dev_alloc_name(dev, ifname) < 0) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005061 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005062 ifname = "wlan%d";
5063 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005064 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005065
5066 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005067 if (rtl8192_init(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005068 RT_TRACE(COMP_ERR, "Initialization failed");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005069 ret = -ENODEV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005070 goto fail;
5071 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005072 netif_carrier_off(dev);
5073 netif_stop_queue(dev);
5074
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005075 ret = register_netdev(dev);
5076 if (ret)
5077 goto fail2;
5078
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005079 RT_TRACE(COMP_INIT, "dev name=======> %s\n", dev->name);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005080 rtl8192_proc_init_one(dev);
5081
5082
5083 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005084 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005085
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005086fail2:
5087 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005088 kfree(priv->pFirmware);
5089 priv->pFirmware = NULL;
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005090 rtl8192_usb_deleteendpoints(dev);
5091 destroy_workqueue(priv->priv_wq);
5092 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005093fail:
5094 free_ieee80211(dev);
5095
5096 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005097 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005098}
5099
5100//detach all the work and timer structure declared or inititialize in r8192U_init function.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005101void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005102{
5103
Jerry Chuang8fc85982009-11-03 07:17:11 -02005104 cancel_work_sync(&priv->reset_wq);
5105 cancel_delayed_work(&priv->watch_dog_wq);
5106 cancel_delayed_work(&priv->update_beacon_wq);
5107 cancel_work_sync(&priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005108}
5109
5110
Bill Pembertona4a557e2012-11-19 13:26:46 -05005111static void rtl8192_usb_disconnect(struct usb_interface *intf)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005112{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005113 struct net_device *dev = usb_get_intfdata(intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005114
5115 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005116 if (dev) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005117
5118 unregister_netdev(dev);
5119
5120 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
5121 rtl8192_proc_remove_one(dev);
5122
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005123 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005124 kfree(priv->pFirmware);
5125 priv->pFirmware = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005126 rtl8192_usb_deleteendpoints(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005127 destroy_workqueue(priv->priv_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005128 mdelay(10);
5129
5130 }
5131 free_ieee80211(dev);
5132 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
5133}
5134
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005135/* fun with the built-in ieee80211 stack... */
5136extern int ieee80211_debug_init(void);
5137extern void ieee80211_debug_exit(void);
5138extern int ieee80211_crypto_init(void);
5139extern void ieee80211_crypto_deinit(void);
5140extern int ieee80211_crypto_tkip_init(void);
5141extern void ieee80211_crypto_tkip_exit(void);
5142extern int ieee80211_crypto_ccmp_init(void);
5143extern void ieee80211_crypto_ccmp_exit(void);
5144extern int ieee80211_crypto_wep_init(void);
5145extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005146
5147static int __init rtl8192_usb_module_init(void)
5148{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005149 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005150
5151#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005152 ret = ieee80211_debug_init();
5153 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005154 pr_err("ieee80211_debug_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005155 return ret;
5156 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005157#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005158 ret = ieee80211_crypto_init();
5159 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005160 pr_err("ieee80211_crypto_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005161 return ret;
5162 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005163
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005164 ret = ieee80211_crypto_tkip_init();
5165 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005166 pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005167 return ret;
5168 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005169
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005170 ret = ieee80211_crypto_ccmp_init();
5171 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005172 pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005173 return ret;
5174 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005175
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005176 ret = ieee80211_crypto_wep_init();
5177 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005178 pr_err("ieee80211_crypto_wep_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005179 return ret;
5180 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005181
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005182 pr_info("\nLinux kernel driver for RTL8192 based WLAN cards\n");
5183 pr_info("Copyright (c) 2007-2008, Realsil Wlan\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005184 RT_TRACE(COMP_INIT, "Initializing module");
5185 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
5186 rtl8192_proc_module_init();
5187 return usb_register(&rtl8192_usb_driver);
5188}
5189
5190
5191static void __exit rtl8192_usb_module_exit(void)
5192{
5193 usb_deregister(&rtl8192_usb_driver);
5194
5195 RT_TRACE(COMP_DOWN, "Exiting");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005196}
5197
5198
5199void rtl8192_try_wake_queue(struct net_device *dev, int pri)
5200{
5201 unsigned long flags;
5202 short enough_desc;
5203 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5204
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005205 spin_lock_irqsave(&priv->tx_lock, flags);
5206 enough_desc = check_nic_enough_desc(dev, pri);
5207 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005208
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005209 if (enough_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005210 ieee80211_wake_queue(priv->ieee80211);
5211}
5212
5213void EnableHWSecurityConfig8192(struct net_device *dev)
5214{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005215 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005216 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005217 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005218 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005219 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 -02005220 SECR_value |= SCR_RxUseDK;
5221 SECR_value |= SCR_TxUseDK;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005222 } 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 -02005223 SECR_value |= SCR_RxUseDK;
5224 SECR_value |= SCR_TxUseDK;
5225 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005226 //add HWSec active enable here.
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005227 //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 -02005228
5229 ieee->hwsec_active = 1;
5230
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005231 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 -02005232 ieee->hwsec_active = 0;
5233 SECR_value &= ~SCR_RxDecEnable;
5234 }
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03005235 RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __func__,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005236 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
5237 write_nic_byte(dev, SECR, SECR_value);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005238}
5239
5240
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03005241void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
5242 u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005243{
5244 u32 TargetCommand = 0;
5245 u32 TargetContent = 0;
5246 u16 usConfig = 0;
5247 u8 i;
5248 if (EntryNo >= TOTAL_CAM_ENTRY)
5249 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
5250
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005251 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 -02005252
5253 if (DefaultKey)
5254 usConfig |= BIT15 | (KeyType<<2);
5255 else
5256 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005257
5258
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005259 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005260 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
5261 TargetCommand |= BIT31|BIT16;
5262
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005263 if (i == 0) { //MAC|Config
Jerry Chuang8fc85982009-11-03 07:17:11 -02005264 TargetContent = (u32)(*(MacAddr+0)) << 16|
5265 (u32)(*(MacAddr+1)) << 24|
5266 (u32)usConfig;
5267
5268 write_nic_dword(dev, WCAMI, TargetContent);
5269 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005270 } else if (i == 1) { //MAC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005271 TargetContent = (u32)(*(MacAddr+2)) |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005272 (u32)(*(MacAddr+3)) << 8|
5273 (u32)(*(MacAddr+4)) << 16|
5274 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005275 write_nic_dword(dev, WCAMI, TargetContent);
5276 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005277 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005278 //Key Material
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005279 if (KeyContent != NULL) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005280 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)));
5281 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005282 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005283 }
5284 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005285
5286}
5287
5288/***************************************************************************
5289 ------------------- module init / exit stubs ----------------
5290****************************************************************************/
5291module_init(rtl8192_usb_module_init);
5292module_exit(rtl8192_usb_module_exit);