blob: 63a4cdf1dc048c601a8adeed251a7eca1b8ac801 [file] [log] [blame]
Jerry Chuang8fc85982009-11-03 07:17:11 -02001/******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3 * Linux device driver for RTL8192U
4 *
5 * Based on the r8187 driver, which is:
Andrea Merello559a4c32013-08-26 13:53:30 +02006 * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
Jerry Chuang8fc85982009-11-03 07:17:11 -02007 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * The full GNU General Public License is included in this distribution in the
21 * file called LICENSE.
22 *
23 * Contact Information:
24 * Jerry chuang <wlanfae@realtek.com>
25 */
26
27#ifndef CONFIG_FORCE_HARD_FLOAT
Xenia Ragiadakou27161412013-06-03 23:58:45 +030028double __floatsidf(int i)
29{
30 return i;
31}
32
33unsigned int __fixunsdfsi(double d)
34{
35 return d;
36}
37
38double __adddf3(double a, double b)
39{
40 return a+b;
41}
42
43double __addsf3(float a, float b)
44{
45 return a+b;
46}
47
48double __subdf3(double a, double b)
49{
50 return a-b;
51}
52
53double __extendsfdf2(float a)
54{
55 return a;
56}
Jerry Chuang8fc85982009-11-03 07:17:11 -020057#endif
58
59#undef LOOP_TEST
60#undef DUMP_RX
61#undef DUMP_TX
62#undef DEBUG_TX_DESC2
63#undef RX_DONT_PASS_UL
64#undef DEBUG_EPROM
65#undef DEBUG_RX_VERBOSE
66#undef DUMMY_RX
67#undef DEBUG_ZERO_RX
68#undef DEBUG_RX_SKB
69#undef DEBUG_TX_FRAG
70#undef DEBUG_RX_FRAG
71#undef DEBUG_TX_FILLDESC
72#undef DEBUG_TX
73#undef DEBUG_IRQ
74#undef DEBUG_RX
75#undef DEBUG_RXALLOC
76#undef DEBUG_REGISTERS
77#undef DEBUG_RING
78#undef DEBUG_IRQ_TASKLET
79#undef DEBUG_TX_ALLOC
80#undef DEBUG_TX_DESC
81
82#define CONFIG_RTL8192_IO_MAP
83
84#include <asm/uaccess.h>
85#include "r8192U_hw.h"
86#include "r8192U.h"
87#include "r8190_rtl8256.h" /* RTL8225 Radio frontend */
88#include "r8180_93cx6.h" /* Card EEPROM */
89#include "r8192U_wx.h"
90#include "r819xU_phy.h" //added by WB 4.30.2008
91#include "r819xU_phyreg.h"
92#include "r819xU_cmdpkt.h"
93#include "r8192U_dm.h"
Jerry Chuang8fc85982009-11-03 07:17:11 -020094#include <linux/usb.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090095#include <linux/slab.h>
David Howells0541f9d2013-04-08 15:17:33 +010096#include <linux/proc_fs.h>
97#include <linux/seq_file.h>
Jerry Chuang8fc85982009-11-03 07:17:11 -020098// FIXME: check if 2.6.7 is ok
Jerry Chuang8fc85982009-11-03 07:17:11 -020099
100#ifdef CONFIG_RTL8192_PM
101#include "r8192_pm.h"
102#endif
103
Jerry Chuang8fc85982009-11-03 07:17:11 -0200104#include "dot11d.h"
Jerry Chuang8fc85982009-11-03 07:17:11 -0200105//set here to open your trace code. //WB
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300106u32 rt_global_debug_component = COMP_DOWN |
Jerry Chuang8fc85982009-11-03 07:17:11 -0200107 COMP_SEC |
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300108 COMP_ERR; //always open err flags on
Jerry Chuang8fc85982009-11-03 07:17:11 -0200109
110#define TOTAL_CAM_ENTRY 32
111#define CAM_CONTENT_COUNT 8
112
Németh Mártona4577322010-01-10 00:18:34 +0100113static const struct usb_device_id rtl8192_usb_id_tbl[] = {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200114 /* Realtek */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200115 {USB_DEVICE(0x0bda, 0x8709)},
116 /* Corega */
117 {USB_DEVICE(0x07aa, 0x0043)},
118 /* Belkin */
119 {USB_DEVICE(0x050d, 0x805E)},
120 /* Sitecom */
121 {USB_DEVICE(0x0df6, 0x0031)},
122 /* EnGenius */
123 {USB_DEVICE(0x1740, 0x9201)},
124 /* Dlink */
125 {USB_DEVICE(0x2001, 0x3301)},
126 /* Zinwell */
127 {USB_DEVICE(0x5a57, 0x0290)},
Ben Hutchingse10ac152010-06-25 01:35:49 +0100128 /* LG */
129 {USB_DEVICE(0x043e, 0x7a01)},
Jerry Chuang8fc85982009-11-03 07:17:11 -0200130 {}
131};
132
133MODULE_LICENSE("GPL");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200134MODULE_VERSION("V 1.1");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200135MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl);
136MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards");
137
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300138static char *ifname = "wlan%d";
Jerry Chuang8fc85982009-11-03 07:17:11 -0200139static int hwwep = 1; //default use hw. set 0 to use software security
140static int channels = 0x3fff;
141
142
143
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300144module_param(ifname, charp, S_IRUGO|S_IWUSR);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300145module_param(hwwep, int, S_IRUGO|S_IWUSR);
146module_param(channels, int, S_IRUGO|S_IWUSR);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200147
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300148MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default");
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300149MODULE_PARM_DESC(hwwep, " Try to use hardware security support. ");
150MODULE_PARM_DESC(channels, " Channel bitmask for specific locales. NYI");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200151
Bill Pemberton25794522012-11-19 13:22:04 -0500152static int rtl8192_usb_probe(struct usb_interface *intf,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300153 const struct usb_device_id *id);
Bill Pembertona4a557e2012-11-19 13:26:46 -0500154static void rtl8192_usb_disconnect(struct usb_interface *intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200155
156
157static struct usb_driver rtl8192_usb_driver = {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200158 .name = RTL819xU_MODULE_NAME, /* Driver name */
159 .id_table = rtl8192_usb_id_tbl, /* PCI_ID table */
160 .probe = rtl8192_usb_probe, /* probe fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200161 .disconnect = rtl8192_usb_disconnect, /* remove fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200162#ifdef CONFIG_RTL8192_PM
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200163 .suspend = rtl8192_suspend, /* PM suspend fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200164 .resume = rtl8192_resume, /* PM resume fn */
165#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200166 .suspend = NULL, /* PM suspend fn */
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100167 .resume = NULL, /* PM resume fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200168#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -0200169};
170
Jerry Chuang8fc85982009-11-03 07:17:11 -0200171
Jennifer Naumann0db7a342012-12-05 21:40:19 +0100172typedef struct _CHANNEL_LIST {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200173 u8 Channel[32];
174 u8 Len;
Xenia Ragiadakou972ff922013-05-23 05:14:47 +0300175} CHANNEL_LIST, *PCHANNEL_LIST;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200176
177static CHANNEL_LIST ChannelPlan[] = {
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100178 {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,149,153,157,161,165},24}, //FCC
179 {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC
180 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //ETSI
Jerry Chuang8fc85982009-11-03 07:17:11 -0200181 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Spain. Change to ETSI.
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100182 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //France. Change to ETSI.
Jerry Chuang8fc85982009-11-03 07:17:11 -0200183 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, //MKK //MKK
184 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1
185 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Israel.
186 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, // For 11a , TELEC
187 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22}, //MIC
188 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14} //For Global Domain. 1-11:active scan, 12-14 passive scan. //+YJ, 080626
189};
190
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300191static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200192{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300193 int i, max_chan = -1, min_chan = -1;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300194 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300195 switch (channel_plan) {
Patrik Karlinf00c4932013-01-09 09:39:44 +0100196 case COUNTRY_CODE_FCC:
197 case COUNTRY_CODE_IC:
198 case COUNTRY_CODE_ETSI:
199 case COUNTRY_CODE_SPAIN:
200 case COUNTRY_CODE_FRANCE:
201 case COUNTRY_CODE_MKK:
202 case COUNTRY_CODE_MKK1:
203 case COUNTRY_CODE_ISRAEL:
204 case COUNTRY_CODE_TELEC:
Xenia Ragiadakou88e5a932013-06-04 23:32:31 +0300205 case COUNTRY_CODE_MIC:
Patrik Karlinf00c4932013-01-09 09:39:44 +0100206 Dot11d_Init(ieee);
207 ieee->bGlobalDomain = false;
208 //actually 8225 & 8256 rf chips only support B,G,24N mode
209 if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256)) {
210 min_chan = 1;
211 max_chan = 14;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300212 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +0300213 RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __func__);
Patrik Karlinf00c4932013-01-09 09:39:44 +0100214 }
215 if (ChannelPlan[channel_plan].Len != 0) {
216 // Clear old channel map
217 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
218 // Set new channel map
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300219 for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
Patrik Karlinf00c4932013-01-09 09:39:44 +0100220 if (ChannelPlan[channel_plan].Channel[i] < min_chan || ChannelPlan[channel_plan].Channel[i] > max_chan)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200221 break;
Patrik Karlinf00c4932013-01-09 09:39:44 +0100222 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200223 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200224 }
Patrik Karlinf00c4932013-01-09 09:39:44 +0100225 break;
226
227 case COUNTRY_CODE_GLOBAL_DOMAIN:
228 GET_DOT11D_INFO(ieee)->bEnabled = 0;//this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain settings.
229 Dot11d_Reset(ieee);
230 ieee->bGlobalDomain = true;
231 break;
Xenia Ragiadakou88e5a932013-06-04 23:32:31 +0300232
Patrik Karlinf00c4932013-01-09 09:39:44 +0100233 default:
234 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200235 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200236}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200237
Jerry Chuang8fc85982009-11-03 07:17:11 -0200238
Jerry Chuang8fc85982009-11-03 07:17:11 -0200239
240
241void CamResetAllEntry(struct net_device *dev)
242{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200243 u32 ulcommand = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200244 //2004/02/11 In static WEP, OID_ADD_KEY or OID_ADD_WEP are set before STA associate to AP.
245 // However, ResetKey is called on OID_802_11_INFRASTRUCTURE_MODE and MlmeAssociateRequest
246 // In this condition, Cam can not be reset because upper layer will not set this static key again.
Jerry Chuang8fc85982009-11-03 07:17:11 -0200247 ulcommand |= BIT31|BIT30;
248 write_nic_dword(dev, RWCAM, ulcommand);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200249
250}
251
252
253void write_cam(struct net_device *dev, u8 addr, u32 data)
254{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200255 write_nic_dword(dev, WCAMI, data);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300256 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200257}
258
259u32 read_cam(struct net_device *dev, u8 addr)
260{
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300261 u32 data;
262
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300263 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff));
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300264 read_nic_dword(dev, 0xa8, &data);
265 return data;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200266}
267
268void write_nic_byte_E(struct net_device *dev, int indx, u8 data)
269{
270 int status;
271 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
272 struct usb_device *udev = priv->udev;
273
274 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300275 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
276 indx|0xfe00, 0, &data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200277
278 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300279 netdev_err(dev, "write_nic_byte_E TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200280}
281
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300282int read_nic_byte_E(struct net_device *dev, int indx, u8 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200283{
284 int status;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200285 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
286 struct usb_device *udev = priv->udev;
287
288 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300289 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300290 indx|0xfe00, 0, data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200291
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300292 if (status < 0) {
293 netdev_err(dev, "%s failure status: %d\n", __func__, status);
294 return status;
295 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200296
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300297 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200298}
299//as 92U has extend page from 4 to 16, so modify functions below.
300void write_nic_byte(struct net_device *dev, int indx, u8 data)
301{
302 int status;
303
304 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
305 struct usb_device *udev = priv->udev;
306
307 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300308 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
309 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200310
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200311 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300312 netdev_err(dev, "write_nic_byte TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200313
314
315}
316
317
318void write_nic_word(struct net_device *dev, int indx, u16 data)
319{
320
321 int status;
322
323 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
324 struct usb_device *udev = priv->udev;
325
326 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300327 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
328 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200329
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200330 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300331 netdev_err(dev, "write_nic_word TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200332
333}
334
335
336void write_nic_dword(struct net_device *dev, int indx, u32 data)
337{
338
339 int status;
340
341 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
342 struct usb_device *udev = priv->udev;
343
344 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300345 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
346 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200347
348
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200349 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300350 netdev_err(dev, "write_nic_dword TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200351
352}
353
354
355
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300356int read_nic_byte(struct net_device *dev, int indx, u8 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200357{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200358 int status;
359 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
360 struct usb_device *udev = priv->udev;
361
362 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300363 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300364 (indx&0xff)|0xff00, (indx>>8)&0x0f, data, 1, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200365
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300366 if (status < 0) {
367 netdev_err(dev, "%s failure status: %d\n", __func__, status);
368 return status;
369 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200370
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300371 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200372}
373
374
375
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300376int read_nic_word(struct net_device *dev, int indx, u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200377{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200378 int status;
379 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
380 struct usb_device *udev = priv->udev;
381
382 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300383 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
384 (indx&0xff)|0xff00, (indx>>8)&0x0f,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300385 data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200386
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300387 if (status < 0) {
388 netdev_err(dev, "%s failure status: %d\n", __func__, status);
389 return status;
390 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200391
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300392 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200393}
394
Teodora Baluta46326d22013-10-16 01:59:17 +0300395static int read_nic_word_E(struct net_device *dev, int indx, u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200396{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200397 int status;
398 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
399 struct usb_device *udev = priv->udev;
400
401 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300402 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300403 indx|0xfe00, 0, data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200404
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300405 if (status < 0) {
406 netdev_err(dev, "%s failure status: %d\n", __func__, status);
407 return status;
408 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200409
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300410 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200411}
412
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300413int read_nic_dword(struct net_device *dev, int indx, u32 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200414{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200415 int status;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200416
417 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
418 struct usb_device *udev = priv->udev;
419
420 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300421 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
422 (indx&0xff)|0xff00, (indx>>8)&0x0f,
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300423 data, 4, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200424
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300425 if (status < 0) {
426 netdev_err(dev, "%s failure status: %d\n", __func__, status);
427 return status;
428 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200429
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300430 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200431}
432
Mike Gilks616f58f2010-06-03 18:29:23 +0800433/* u8 read_phy_cck(struct net_device *dev, u8 adr); */
434/* u8 read_phy_ofdm(struct net_device *dev, u8 adr); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200435/* this might still called in what was the PHY rtl8185/rtl8192 common code
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300436 * plans are to possibility turn it again in one common code...
Jerry Chuang8fc85982009-11-03 07:17:11 -0200437 */
438inline void force_pci_posting(struct net_device *dev)
439{
440}
441
Jerry Chuang8fc85982009-11-03 07:17:11 -0200442static struct net_device_stats *rtl8192_stats(struct net_device *dev);
443void rtl8192_commit(struct net_device *dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200444void rtl8192_restart(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200445void watch_dog_timer_callback(unsigned long data);
446
447/****************************************************************************
Mike Gilks616f58f2010-06-03 18:29:23 +0800448 * -----------------------------PROCFS STUFF-------------------------
449*****************************************************************************
450 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200451
Mike Gilks616f58f2010-06-03 18:29:23 +0800452static struct proc_dir_entry *rtl8192_proc;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200453
David Howells0541f9d2013-04-08 15:17:33 +0100454static int proc_get_stats_ap(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200455{
David Howells0541f9d2013-04-08 15:17:33 +0100456 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200457 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
458 struct ieee80211_device *ieee = priv->ieee80211;
459 struct ieee80211_network *target;
460
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200461 list_for_each_entry(target, &ieee->network_list, list) {
David Howells0541f9d2013-04-08 15:17:33 +0100462 const char *wpa = "non_WPA";
Mike Gilks616f58f2010-06-03 18:29:23 +0800463 if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0)
David Howells0541f9d2013-04-08 15:17:33 +0100464 wpa = "WPA";
465
466 seq_printf(m, "%s %s\n", target->ssid, wpa);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200467 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200468
David Howells0541f9d2013-04-08 15:17:33 +0100469 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200470}
471
David Howells0541f9d2013-04-08 15:17:33 +0100472static int proc_get_registers(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200473{
David Howells0541f9d2013-04-08 15:17:33 +0100474 struct net_device *dev = m->private;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300475 int i, n, max = 0xff;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300476 u8 byte_rd;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200477
David Howells0541f9d2013-04-08 15:17:33 +0100478 seq_puts(m, "\n####################page 0##################\n ");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200479
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300480 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300481 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200482
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300483 for (i = 0; i < 16 && n <= max; i++, n++) {
484 read_nic_byte(dev, 0x000|n, &byte_rd);
485 seq_printf(m, "%2x ", byte_rd);
486 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200487 }
David Howells0541f9d2013-04-08 15:17:33 +0100488
489 seq_puts(m, "\n####################page 1##################\n ");
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300490 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300491 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200492
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300493 for (i = 0; i < 16 && n <= max; i++, n++) {
494 read_nic_byte(dev, 0x100|n, &byte_rd);
495 seq_printf(m, "%2x ", byte_rd);
496 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200497 }
David Howells0541f9d2013-04-08 15:17:33 +0100498
499 seq_puts(m, "\n####################page 3##################\n ");
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300500 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300501 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200502
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300503 for (i = 0; i < 16 && n <= max; i++, n++) {
504 read_nic_byte(dev, 0x300|n, &byte_rd);
505 seq_printf(m, "%2x ", byte_rd);
506 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200507 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200508
David Howells0541f9d2013-04-08 15:17:33 +0100509 seq_putc(m, '\n');
510 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200511}
512
David Howells0541f9d2013-04-08 15:17:33 +0100513static int proc_get_stats_tx(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200514{
David Howells0541f9d2013-04-08 15:17:33 +0100515 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200516 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
517
David Howells0541f9d2013-04-08 15:17:33 +0100518 seq_printf(m,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300519 "TX VI priority ok int: %lu\n"
520 "TX VI priority error int: %lu\n"
521 "TX VO priority ok int: %lu\n"
522 "TX VO priority error int: %lu\n"
523 "TX BE priority ok int: %lu\n"
524 "TX BE priority error int: %lu\n"
525 "TX BK priority ok int: %lu\n"
526 "TX BK priority error int: %lu\n"
527 "TX MANAGE priority ok int: %lu\n"
528 "TX MANAGE priority error int: %lu\n"
529 "TX BEACON priority ok int: %lu\n"
530 "TX BEACON priority error int: %lu\n"
531 "TX queue resume: %lu\n"
532 "TX queue stopped?: %d\n"
533 "TX fifo overflow: %lu\n"
534 "TX VI queue: %d\n"
535 "TX VO queue: %d\n"
536 "TX BE queue: %d\n"
537 "TX BK queue: %d\n"
538 "TX VI dropped: %lu\n"
539 "TX VO dropped: %lu\n"
540 "TX BE dropped: %lu\n"
541 "TX BK dropped: %lu\n"
542 "TX total data packets %lu\n",
543 priv->stats.txviokint,
544 priv->stats.txvierr,
545 priv->stats.txvookint,
546 priv->stats.txvoerr,
547 priv->stats.txbeokint,
548 priv->stats.txbeerr,
549 priv->stats.txbkokint,
550 priv->stats.txbkerr,
551 priv->stats.txmanageokint,
552 priv->stats.txmanageerr,
553 priv->stats.txbeaconokint,
554 priv->stats.txbeaconerr,
555 priv->stats.txresumed,
556 netif_queue_stopped(dev),
557 priv->stats.txoverflow,
558 atomic_read(&(priv->tx_pending[VI_PRIORITY])),
559 atomic_read(&(priv->tx_pending[VO_PRIORITY])),
560 atomic_read(&(priv->tx_pending[BE_PRIORITY])),
561 atomic_read(&(priv->tx_pending[BK_PRIORITY])),
562 priv->stats.txvidrop,
563 priv->stats.txvodrop,
564 priv->stats.txbedrop,
565 priv->stats.txbkdrop,
566 priv->stats.txdatapkt
Jerry Chuang8fc85982009-11-03 07:17:11 -0200567 );
568
David Howells0541f9d2013-04-08 15:17:33 +0100569 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200570}
571
David Howells0541f9d2013-04-08 15:17:33 +0100572static int proc_get_stats_rx(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200573{
David Howells0541f9d2013-04-08 15:17:33 +0100574 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200575 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
576
David Howells0541f9d2013-04-08 15:17:33 +0100577 seq_printf(m,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300578 "RX packets: %lu\n"
579 "RX urb status error: %lu\n"
580 "RX invalid urb error: %lu\n",
581 priv->stats.rxoktotal,
582 priv->stats.rxstaterr,
583 priv->stats.rxurberr);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200584
David Howells0541f9d2013-04-08 15:17:33 +0100585 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200586}
David Howells0541f9d2013-04-08 15:17:33 +0100587
Teodora Baluta46326d22013-10-16 01:59:17 +0300588static void rtl8192_proc_module_init(void)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200589{
590 RT_TRACE(COMP_INIT, "Initializing proc filesystem");
Al Viroe55d92b2011-07-24 02:07:46 -0400591 rtl8192_proc = proc_mkdir(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200592}
593
594
595void rtl8192_proc_module_remove(void)
596{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200597 remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200598}
599
David Howells0541f9d2013-04-08 15:17:33 +0100600/*
601 * seq_file wrappers for procfile show routines.
602 */
603static int rtl8192_proc_open(struct inode *inode, struct file *file)
604{
David Howells4a520d22013-04-12 14:06:01 +0100605 struct net_device *dev = proc_get_parent_data(inode);
David Howells0541f9d2013-04-08 15:17:33 +0100606 int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
607
608 return single_open(file, show, dev);
609}
610
611static const struct file_operations rtl8192_proc_fops = {
612 .open = rtl8192_proc_open,
613 .read = seq_read,
614 .llseek = seq_lseek,
Al Virobae301d2013-05-05 00:15:43 -0400615 .release = single_release,
David Howells0541f9d2013-04-08 15:17:33 +0100616};
617
618/*
619 * Table of proc files we need to create.
620 */
621struct rtl8192_proc_file {
622 char name[12];
623 int (*show)(struct seq_file *, void *);
624};
625
626static const struct rtl8192_proc_file rtl8192_proc_files[] = {
627 { "stats-rx", &proc_get_stats_rx },
628 { "stats-tx", &proc_get_stats_tx },
629 { "stats-ap", &proc_get_stats_ap },
630 { "registers", &proc_get_registers },
631 { "" }
632};
633
Teodora Baluta46326d22013-10-16 01:59:17 +0300634static void rtl8192_proc_init_one(struct net_device *dev)
David Howells0541f9d2013-04-08 15:17:33 +0100635{
636 const struct rtl8192_proc_file *f;
David Howellscc87e0f2013-04-12 03:02:22 +0100637 struct proc_dir_entry *dir;
David Howells0541f9d2013-04-08 15:17:33 +0100638
639 if (rtl8192_proc) {
David Howellscc87e0f2013-04-12 03:02:22 +0100640 dir = proc_mkdir_data(dev->name, 0, rtl8192_proc, dev);
641 if (!dir) {
David Howells0541f9d2013-04-08 15:17:33 +0100642 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
643 dev->name);
644 return;
645 }
David Howells0541f9d2013-04-08 15:17:33 +0100646
647 for (f = rtl8192_proc_files; f->name[0]; f++) {
David Howellscc87e0f2013-04-12 03:02:22 +0100648 if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir,
649 &rtl8192_proc_fops, f->show)) {
David Howells0541f9d2013-04-08 15:17:33 +0100650 RT_TRACE(COMP_ERR, "Unable to initialize "
651 "/proc/net/rtl8192/%s/%s\n",
652 dev->name, f->name);
653 return;
654 }
655 }
656 }
657}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200658
Teodora Baluta46326d22013-10-16 01:59:17 +0300659static void rtl8192_proc_remove_one(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200660{
David Howellscc87e0f2013-04-12 03:02:22 +0100661 remove_proc_subtree(dev->name, rtl8192_proc);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200662}
663
Jerry Chuang8fc85982009-11-03 07:17:11 -0200664/****************************************************************************
665 -----------------------------MISC STUFF-------------------------
666*****************************************************************************/
667
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300668short check_nic_enough_desc(struct net_device *dev, int queue_index)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200669{
670 struct r8192_priv *priv = ieee80211_priv(dev);
671 int used = atomic_read(&priv->tx_pending[queue_index]);
672
673 return (used < MAX_TX_URB);
674}
675
676void tx_timeout(struct net_device *dev)
677{
678 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200679
Jerry Chuang8fc85982009-11-03 07:17:11 -0200680 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200681}
682
683
684/* this is only for debug */
685void dump_eprom(struct net_device *dev)
686{
687 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300688 for (i = 0; i < 63; i++)
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300689 RT_TRACE(COMP_EPROM, "EEPROM addr %x : %x", i, eprom_read(dev, i));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200690}
691
Jerry Chuang8fc85982009-11-03 07:17:11 -0200692
693/****************************************************************************
694 ------------------------------HW STUFF---------------------------
695*****************************************************************************/
696
Jerry Chuang8fc85982009-11-03 07:17:11 -0200697
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300698void rtl8192_set_mode(struct net_device *dev, int mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200699{
700 u8 ecmd;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300701 read_nic_byte(dev, EPROM_CMD, &ecmd);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300702 ecmd = ecmd & ~EPROM_CMD_OPERATING_MODE_MASK;
703 ecmd = ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300704 ecmd = ecmd & ~EPROM_CS_BIT;
705 ecmd = ecmd & ~EPROM_CK_BIT;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200706 write_nic_byte(dev, EPROM_CMD, ecmd);
707}
708
709
710void rtl8192_update_msr(struct net_device *dev)
711{
712 struct r8192_priv *priv = ieee80211_priv(dev);
713 u8 msr;
714
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300715 read_nic_byte(dev, MSR, &msr);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300716 msr &= ~MSR_LINK_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200717
718 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
719 * msr must be updated if the state is ASSOCIATING.
720 * this is intentional and make sense for ad-hoc and
721 * master (see the create BSS/IBSS func)
722 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300723 if (priv->ieee80211->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200724
725 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
726 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
727 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
728 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
729 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
730 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
731
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300732 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200733 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300734 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200735
736 write_nic_byte(dev, MSR, msr);
737}
738
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300739void rtl8192_set_chan(struct net_device *dev, short ch)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200740{
741 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +0300742 RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __func__, ch);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300743 priv->chan = ch;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200744
745 /* this hack should avoid frame TX during channel setting*/
746
Jerry Chuang8fc85982009-11-03 07:17:11 -0200747#ifndef LOOP_TEST
Jerry Chuang8fc85982009-11-03 07:17:11 -0200748 //need to implement rf set channel here WB
749
750 if (priv->rf_set_chan)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300751 priv->rf_set_chan(dev, priv->chan);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200752 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200753#endif
754}
755
Jerry Chuang8fc85982009-11-03 07:17:11 -0200756static void rtl8192_rx_isr(struct urb *urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200757
Teodora Baluta46326d22013-10-16 01:59:17 +0300758static u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200759{
760
761#ifdef USB_RX_AGGREGATION_SUPPORT
762 if (pstats->bisrxaggrsubframe)
763 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
764 + pstats->RxBufShift + 8);
765 else
766#endif
767 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300768 + pstats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200769
770}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300771static int rtl8192_rx_initiate(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200772{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200773 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
774 struct urb *entry;
775 struct sk_buff *skb;
776 struct rtl8192_rx_info *info;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200777
778 /* nomal packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200779 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB) {
780 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
781 if (!skb)
782 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200783 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200784 if (!entry) {
785 kfree_skb(skb);
786 break;
787 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200788 usb_fill_bulk_urb(entry, priv->udev,
789 usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb),
790 RX_URB_SIZE, rtl8192_rx_isr, skb);
791 info = (struct rtl8192_rx_info *) skb->cb;
792 info->urb = entry;
793 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200794 info->out_pipe = 3; //denote rx normal packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200795 skb_queue_tail(&priv->rx_queue, skb);
796 usb_submit_urb(entry, GFP_KERNEL);
797 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200798
799 /* command packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200800 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300801 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200802 if (!skb)
803 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200804 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200805 if (!entry) {
806 kfree_skb(skb);
807 break;
808 }
809 usb_fill_bulk_urb(entry, priv->udev,
810 usb_rcvbulkpipe(priv->udev, 9), skb_tail_pointer(skb),
811 RX_URB_SIZE, rtl8192_rx_isr, skb);
812 info = (struct rtl8192_rx_info *) skb->cb;
813 info->urb = entry;
814 info->dev = dev;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300815 info->out_pipe = 9; //denote rx cmd packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200816 skb_queue_tail(&priv->rx_queue, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200817 usb_submit_urb(entry, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200818 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200819
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200820 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200821}
822
823void rtl8192_set_rxconf(struct net_device *dev)
824{
825 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
826 u32 rxconf;
827
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300828 read_nic_dword(dev, RCR, &rxconf);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300829 rxconf = rxconf & ~MAC_FILTER_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200830 rxconf = rxconf | RCR_AMF;
831 rxconf = rxconf | RCR_ADF;
832 rxconf = rxconf | RCR_AB;
833 rxconf = rxconf | RCR_AM;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200834
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300835 if (dev->flags & IFF_PROMISC)
836 DMESG("NIC in promisc mode");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200837
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300838 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300839 dev->flags & IFF_PROMISC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200840 rxconf = rxconf | RCR_AAP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300841 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200842 rxconf = rxconf | RCR_APM;
843 rxconf = rxconf | RCR_CBSSID;
844 }
845
846
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300847 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200848 rxconf = rxconf | RCR_AICV;
849 rxconf = rxconf | RCR_APWRMGT;
850 }
851
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300852 if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200853 rxconf = rxconf | RCR_ACRC32;
854
855
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300856 rxconf = rxconf & ~RX_FIFO_THRESHOLD_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200857 rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE<<RX_FIFO_THRESHOLD_SHIFT);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300858 rxconf = rxconf & ~MAX_RX_DMA_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200859 rxconf = rxconf | ((u32)7<<RCR_MXDMA_OFFSET);
860
Jerry Chuang8fc85982009-11-03 07:17:11 -0200861 rxconf = rxconf | RCR_ONLYERLPKT;
862
Jerry Chuang8fc85982009-11-03 07:17:11 -0200863 write_nic_dword(dev, RCR, rxconf);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200864}
865//wait to be removed
866void rtl8192_rx_enable(struct net_device *dev)
867{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200868 rtl8192_rx_initiate(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200869}
870
871
872void rtl8192_tx_enable(struct net_device *dev)
873{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200874}
875
Jerry Chuang8fc85982009-11-03 07:17:11 -0200876
877
878void rtl8192_rtx_disable(struct net_device *dev)
879{
880 u8 cmd;
881 struct r8192_priv *priv = ieee80211_priv(dev);
882 struct sk_buff *skb;
883 struct rtl8192_rx_info *info;
884
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +0300885 read_nic_byte(dev, CMDR, &cmd);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +0300886 write_nic_byte(dev, CMDR, cmd & ~(CR_TE|CR_RE));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200887 force_pci_posting(dev);
888 mdelay(10);
889
890 while ((skb = __skb_dequeue(&priv->rx_queue))) {
891 info = (struct rtl8192_rx_info *) skb->cb;
892 if (!info->urb)
893 continue;
894
895 usb_kill_urb(info->urb);
896 kfree_skb(skb);
897 }
898
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300899 if (skb_queue_len(&priv->skb_queue))
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300900 netdev_warn(dev, "skb_queue not empty\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200901
902 skb_queue_purge(&priv->skb_queue);
903 return;
904}
905
906
907int alloc_tx_beacon_desc_ring(struct net_device *dev, int count)
908{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200909 return 0;
910}
911
Jerry Chuang8fc85982009-11-03 07:17:11 -0200912inline u16 ieeerate2rtlrate(int rate)
913{
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300914 switch (rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200915 case 10:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300916 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200917 case 20:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300918 return 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200919 case 55:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300920 return 2;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200921 case 110:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300922 return 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200923 case 60:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300924 return 4;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200925 case 90:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300926 return 5;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200927 case 120:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300928 return 6;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200929 case 180:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300930 return 7;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200931 case 240:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300932 return 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200933 case 360:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300934 return 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200935 case 480:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300936 return 10;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200937 case 540:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300938 return 11;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200939 default:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300940 return 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200941
942 }
943}
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300944static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
Jerry Chuang8fc85982009-11-03 07:17:11 -0200945inline u16 rtl8192_rate2rate(short rate)
946{
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300947 if (rate > 11) return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200948 return rtl_rate[rate];
949}
950
951
Justin P. Mattock589b3d02012-04-30 07:41:36 -0700952/* The prototype of rx_isr has changed since one version of Linux Kernel */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200953static void rtl8192_rx_isr(struct urb *urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200954{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200955 struct sk_buff *skb = (struct sk_buff *) urb->context;
956 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
957 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200958 struct r8192_priv *priv = ieee80211_priv(dev);
959 int out_pipe = info->out_pipe;
960 int err;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300961 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200962 return;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200963 if (unlikely(urb->status)) {
964 info->urb = NULL;
965 priv->stats.rxstaterr++;
966 priv->ieee80211->stats.rx_errors++;
967 usb_free_urb(urb);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200968 return;
969 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200970 skb_unlink(skb, &priv->rx_queue);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200971 skb_put(skb, urb->actual_length);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200972
973 skb_queue_tail(&priv->skb_queue, skb);
974 tasklet_schedule(&priv->irq_rx_tasklet);
975
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200976 skb = dev_alloc_skb(RX_URB_SIZE);
977 if (unlikely(!skb)) {
978 usb_free_urb(urb);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300979 netdev_err(dev, "%s(): can't alloc skb\n", __func__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200980 /* TODO check rx queue length and refill *somewhere* */
981 return;
982 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200983
984 usb_fill_bulk_urb(urb, priv->udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +0300985 usb_rcvbulkpipe(priv->udev, out_pipe), skb_tail_pointer(skb),
986 RX_URB_SIZE, rtl8192_rx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200987
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200988 info = (struct rtl8192_rx_info *) skb->cb;
989 info->urb = urb;
990 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200991 info->out_pipe = out_pipe;
992
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200993 urb->transfer_buffer = skb_tail_pointer(skb);
994 urb->context = skb;
995 skb_queue_tail(&priv->rx_queue, skb);
996 err = usb_submit_urb(urb, GFP_ATOMIC);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300997 if (err && err != EPERM)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300998 netdev_err(dev, "can not submit rxurb, err is %x, URB status is %x\n", err, urb->status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200999}
1000
Teodora Baluta46326d22013-10-16 01:59:17 +03001001static u32 rtl819xusb_rx_command_packet(struct net_device *dev,
1002 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001003{
1004 u32 status;
1005
Jerry Chuang8fc85982009-11-03 07:17:11 -02001006 status = cmpk_message_handle_rx(dev, pstats);
1007 if (status)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001008 DMESG("rxcommandpackethandle819xusb: It is a command packet\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001009
Jerry Chuang8fc85982009-11-03 07:17:11 -02001010 return status;
1011}
1012
Jerry Chuang8fc85982009-11-03 07:17:11 -02001013
1014void rtl8192_data_hard_stop(struct net_device *dev)
1015{
1016 //FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001017}
1018
1019
1020void rtl8192_data_hard_resume(struct net_device *dev)
1021{
1022 // FIXME !!
Jerry Chuang8fc85982009-11-03 07:17:11 -02001023}
1024
1025/* this function TX data frames when the ieee80211 stack requires this.
1026 * It checks also if we need to stop the ieee tx queue, eventually do it
1027 */
1028void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
1029{
1030 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1031 int ret;
1032 unsigned long flags;
1033 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1034 u8 queue_index = tcb_desc->queue_index;
1035
1036 /* shall not be referred by command packet */
Xenia Ragiadakou4a8d1132013-06-09 14:38:43 +03001037 RTL8192U_ASSERT(queue_index != TXCMD_QUEUE);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001038
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001039 spin_lock_irqsave(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001040
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001041 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001042 tcb_desc->bTxEnableFwCalcDur = 1;
1043 skb_push(skb, priv->ieee80211->tx_headroom);
1044 ret = rtl8192_tx(dev, skb);
1045
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001046 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001047
Jerry Chuang8fc85982009-11-03 07:17:11 -02001048 return;
1049}
1050
1051/* This is a rough attempt to TX a frame
1052 * This is called by the ieee 80211 stack to TX management frames.
1053 * If the ring is full packet are dropped (for data frame the queue
1054 * is stopped before this can happen).
1055 */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001056int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001057{
1058 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
1059 int ret;
1060 unsigned long flags;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001061 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1062 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001063
1064
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001065 spin_lock_irqsave(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001066
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001067 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001068 if (queue_index == TXCMD_QUEUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001069 skb_push(skb, USB_HWDESC_HEADER_LEN);
1070 rtl819xU_tx_cmd(dev, skb);
1071 ret = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001072 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001073 return ret;
1074 } else {
1075 skb_push(skb, priv->ieee80211->tx_headroom);
1076 ret = rtl8192_tx(dev, skb);
1077 }
1078
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001079 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001080
1081 return ret;
1082}
1083
1084
1085void rtl8192_try_wake_queue(struct net_device *dev, int pri);
1086
1087#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1088u16 DrvAggr_PaddingAdd(struct net_device *dev, struct sk_buff *skb)
1089{
1090 u16 PaddingNum = 256 - ((skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES) % 256);
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03001091 return PaddingNum & 0xff;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001092}
1093
1094u8 MRateToHwRate8190Pci(u8 rate);
1095u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc);
1096u8 MapHwQueueToFirmwareQueue(u8 QueueID);
1097struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv_agg_txb *pSendList)
1098{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001099 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001100 struct r8192_priv *priv = ieee80211_priv(dev);
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001101 cb_desc *tcb_desc = NULL;
1102 u8 i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001103 u32 TotalLength;
1104 struct sk_buff *skb;
1105 struct sk_buff *agg_skb;
1106 tx_desc_819x_usb_aggr_subframe *tx_agg_desc = NULL;
1107 tx_fwinfo_819x_usb *tx_fwinfo = NULL;
1108
1109 //
1110 // Local variable initialization.
1111 //
1112 /* first skb initialization */
1113 skb = pSendList->tx_agg_frames[0];
1114 TotalLength = skb->len;
1115
1116 /* Get the total aggregation length including the padding space and
1117 * sub frame header.
1118 */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001119 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001120 TotalLength += DrvAggr_PaddingAdd(dev, skb);
1121 skb = pSendList->tx_agg_frames[i];
1122 TotalLength += (skb->len + TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1123 }
1124
1125 /* allocate skb to contain the aggregated packets */
1126 agg_skb = dev_alloc_skb(TotalLength + ieee->tx_headroom);
1127 memset(agg_skb->data, 0, agg_skb->len);
1128 skb_reserve(agg_skb, ieee->tx_headroom);
1129
Jerry Chuang8fc85982009-11-03 07:17:11 -02001130 /* reserve info for first subframe Tx descriptor to be set in the tx function */
1131 skb = pSendList->tx_agg_frames[0];
1132 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1133 tcb_desc->drv_agg_enable = 1;
1134 tcb_desc->pkt_size = skb->len;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001135 tcb_desc->DrvAggrNum = pSendList->nr_drv_agg_frames;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001136 netdev_dbg(dev, "DrvAggNum = %d\n", tcb_desc->DrvAggrNum);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001137 memcpy(agg_skb->cb, skb->cb, sizeof(skb->cb));
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001138 memcpy(skb_put(agg_skb, skb->len), skb->data, skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001139
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03001140 for (i = 1; i < pSendList->nr_drv_agg_frames; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001141 /* push the next sub frame to be 256 byte aline */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001142 skb_put(agg_skb, DrvAggr_PaddingAdd(dev, skb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001143
1144 /* Subframe drv Tx descriptor and firmware info setting */
1145 skb = pSendList->tx_agg_frames[i];
1146 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Isaku Yamahataa267a602013-06-14 17:58:35 +09001147 tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)skb_tail_pointer(agg_skb);
1148 tx_fwinfo = (tx_fwinfo_819x_usb *)(skb_tail_pointer(agg_skb) + sizeof(tx_desc_819x_usb_aggr_subframe));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001149
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001150 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001151 /* DWORD 0 */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001152 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001153 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1154 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1155 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001156 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001157 tx_fwinfo->AllowAggregation = 1;
1158 /* DWORD 1 */
1159 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1160 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1161 } else {
1162 tx_fwinfo->AllowAggregation = 0;
1163 /* DWORD 1 */
1164 tx_fwinfo->RxMF = 0;
1165 tx_fwinfo->RxAMD = 0;
1166 }
1167
1168 /* Protection mode related */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001169 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1170 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1171 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1172 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001173 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001174 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->RTSSC) : 0;
1175 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1) ? ((tcb_desc->bRTSBW) ? 1 : 0) : 0;
1176 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) :
1177 (tcb_desc->bRTSUseShortGI ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001178
1179 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001180 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001181 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001182 tx_fwinfo->TxBandwidth = 1;
1183 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1184 } else {
1185 tx_fwinfo->TxBandwidth = 0;
1186 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1187 }
1188 } else {
1189 tx_fwinfo->TxBandwidth = 0;
1190 tx_fwinfo->TxSubCarrier = 0;
1191 }
1192
1193 /* Fill Tx descriptor */
1194 memset(tx_agg_desc, 0, sizeof(tx_desc_819x_usb_aggr_subframe));
1195 /* DWORD 0 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001196 tx_agg_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001197 /* already raw data, need not to subtract header length */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001198 tx_agg_desc->PktSize = skb->len & 0xffff;
1199
1200 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001201 tx_agg_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001202 tx_agg_desc->RATid = tcb_desc->RATRIndex;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001203 tx_agg_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001204 tx_agg_desc->SecType = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001205
1206 if (tcb_desc->bHwSec) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001207 switch (priv->ieee80211->pairwise_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001208 case KEY_TYPE_WEP40:
1209 case KEY_TYPE_WEP104:
1210 tx_agg_desc->SecType = 0x1;
1211 tx_agg_desc->NoEnc = 0;
1212 break;
1213 case KEY_TYPE_TKIP:
1214 tx_agg_desc->SecType = 0x2;
1215 tx_agg_desc->NoEnc = 0;
1216 break;
1217 case KEY_TYPE_CCMP:
1218 tx_agg_desc->SecType = 0x3;
1219 tx_agg_desc->NoEnc = 0;
1220 break;
1221 case KEY_TYPE_NA:
1222 tx_agg_desc->SecType = 0x0;
1223 tx_agg_desc->NoEnc = 1;
1224 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001225 }
1226 }
1227
1228 tx_agg_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1229 tx_agg_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1230
1231 tx_agg_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1232 tx_agg_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1233
1234 tx_agg_desc->OWN = 1;
1235
1236 //DWORD 2
1237 /* According windows driver, it seems that there no need to fill this field */
Jerry Chuang8fc85982009-11-03 07:17:11 -02001238
1239 /* to fill next packet */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001240 skb_put(agg_skb, TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES);
1241 memcpy(skb_put(agg_skb, skb->len), skb->data, skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001242 }
1243
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001244 for (i = 0; i < pSendList->nr_drv_agg_frames; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001245 dev_kfree_skb_any(pSendList->tx_agg_frames[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001246
1247 return agg_skb;
1248}
1249
1250/* NOTE:
1251 This function return a list of PTCB which is proper to be aggregate with the input TCB.
1252 If no proper TCB is found to do aggregation, SendList will only contain the input TCB.
1253*/
1254u8 DrvAggr_GetAggregatibleList(struct net_device *dev, struct sk_buff *skb,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001255 struct ieee80211_drv_agg_txb *pSendList)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001256{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001257 struct ieee80211_device *ieee = netdev_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001258 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1259 u16 nMaxAggrNum = pHTInfo->UsbTxAggrNum;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001260 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001261 u8 QueueID = tcb_desc->queue_index;
1262
1263 do {
1264 pSendList->tx_agg_frames[pSendList->nr_drv_agg_frames++] = skb;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001265 if (pSendList->nr_drv_agg_frames >= nMaxAggrNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001266 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001267
Xenia Ragiadakou53c7f3c2013-05-22 18:22:35 +03001268 } while ((skb = skb_dequeue(&ieee->skb_drv_aggQ[QueueID])));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001269
1270 RT_TRACE(COMP_AMSDU, "DrvAggr_GetAggregatibleList, nAggrTcbNum = %d \n", pSendList->nr_drv_agg_frames);
1271 return pSendList->nr_drv_agg_frames;
1272}
1273#endif
1274
Jerry Chuang8fc85982009-11-03 07:17:11 -02001275static void rtl8192_tx_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001276{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001277 struct sk_buff *skb = (struct sk_buff *)tx_urb->context;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001278 struct net_device *dev = NULL;
1279 struct r8192_priv *priv = NULL;
1280 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1281 u8 queue_index = tcb_desc->queue_index;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001282
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001283 memcpy(&dev, (struct net_device *)(skb->cb), sizeof(struct net_device *));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001284 priv = ieee80211_priv(dev);
1285
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001286 if (tcb_desc->queue_index != TXCMD_QUEUE) {
1287 if (tx_urb->status == 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001288 dev->trans_start = jiffies;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001289 priv->stats.txoktotal++;
1290 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
1291 priv->stats.txbytesunicast += (skb->len - priv->ieee80211->tx_headroom);
1292 } else {
1293 priv->ieee80211->stats.tx_errors++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001294 /* TODO */
1295 }
1296 }
1297
1298 /* free skb and tx_urb */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001299 if (skb != NULL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001300 dev_kfree_skb_any(skb);
1301 usb_free_urb(tx_urb);
1302 atomic_dec(&priv->tx_pending[queue_index]);
1303 }
1304
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001305 //
1306 // Handle HW Beacon:
1307 // We had transfer our beacon frame to host controller at this moment.
1308 //
1309 //
1310 // Caution:
1311 // Handling the wait queue of command packets.
1312 // For Tx command packets, we must not do TCB fragment because it is not handled right now.
1313 // We must cut the packets to match the size of TX_CMD_PKT before we send it.
1314 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02001315
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001316 /* Handle MPDU in wait queue. */
1317 if (queue_index != BEACON_QUEUE) {
1318 /* Don't send data frame during scanning.*/
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001319 if ((skb_queue_len(&priv->ieee80211->skb_waitQ[queue_index]) != 0) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001320 (!(priv->ieee80211->queue_stop))) {
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
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03001612 usb_fill_bulk_urb(tx_urb, priv->udev, usb_sndbulkpipe(priv->udev, idx_pipe),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001613 skb->data, skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001614
Jerry Chuang8fc85982009-11-03 07:17:11 -02001615 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001616
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001617 if (!status) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001618 return 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001619 } else {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001620 DMESGE("Error TX CMD URB, error %d", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001621 return -1;
1622 }
1623}
1624
1625/*
1626 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1627 * in TxFwInfo data structure
1628 * 2006.10.30 by Emily
1629 *
1630 * \param QUEUEID Software Queue
1631*/
Teodora Baluta46326d22013-10-16 01:59:17 +03001632static u8 MapHwQueueToFirmwareQueue(u8 QueueID)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001633{
1634 u8 QueueSelect = 0x0; //defualt set to
1635
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001636 switch (QueueID) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001637 case BE_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001638 QueueSelect = QSLT_BE;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001639 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001640
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001641 case BK_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001642 QueueSelect = QSLT_BK;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001643 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001644
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001645 case VO_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001646 QueueSelect = QSLT_VO;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001647 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001648
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001649 case VI_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001650 QueueSelect = QSLT_VI;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001651 break;
1652 case MGNT_QUEUE:
1653 QueueSelect = QSLT_MGNT;
1654 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001655
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001656 case BEACON_QUEUE:
1657 QueueSelect = QSLT_BEACON;
1658 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001659
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001660 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
1661 // TODO: Remove Assertions
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001662 case TXCMD_QUEUE:
1663 QueueSelect = QSLT_CMD;
1664 break;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001665 case HIGH_QUEUE:
1666 QueueSelect = QSLT_HIGH;
1667 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001668
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001669 default:
1670 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
1671 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001672 }
1673 return QueueSelect;
1674}
1675
1676u8 MRateToHwRate8190Pci(u8 rate)
1677{
1678 u8 ret = DESC90_RATE1M;
1679
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001680 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001681 case MGN_1M: ret = DESC90_RATE1M; break;
1682 case MGN_2M: ret = DESC90_RATE2M; break;
1683 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1684 case MGN_11M: ret = DESC90_RATE11M; break;
1685 case MGN_6M: ret = DESC90_RATE6M; break;
1686 case MGN_9M: ret = DESC90_RATE9M; break;
1687 case MGN_12M: ret = DESC90_RATE12M; break;
1688 case MGN_18M: ret = DESC90_RATE18M; break;
1689 case MGN_24M: ret = DESC90_RATE24M; break;
1690 case MGN_36M: ret = DESC90_RATE36M; break;
1691 case MGN_48M: ret = DESC90_RATE48M; break;
1692 case MGN_54M: ret = DESC90_RATE54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001693
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001694 // HT rate since here
1695 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1696 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1697 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1698 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1699 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1700 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1701 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1702 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1703 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1704 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1705 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1706 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1707 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1708 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1709 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1710 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1711 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001712
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001713 default: break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001714 }
1715 return ret;
1716}
1717
1718
Teodora Baluta46326d22013-10-16 01:59:17 +03001719static u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001720{
1721 u8 tmp_Short;
1722
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001723 tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) : ((tcb_desc->bUseShortPreamble) ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001724
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03001725 if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001726 tmp_Short = 0;
1727
1728 return tmp_Short;
1729}
1730
Jerry Chuang8fc85982009-11-03 07:17:11 -02001731static void tx_zero_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001732{
1733 return;
1734}
1735
1736/*
1737 * The tx procedure is just as following,
1738 * skb->cb will contain all the following information,
1739 * priority, morefrag, rate, &dev.
1740 * */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001741short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001742{
1743 struct r8192_priv *priv = ieee80211_priv(dev);
1744 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1745 tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data;
1746 tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
1747 struct usb_device *udev = priv->udev;
1748 int pend;
1749 int status;
1750 struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001751 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001752 pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]);
1753 /* we are locked here so the two atomic_read and inc are executed
1754 * without interleaves
1755 * !!! For debug purpose
1756 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001757 if (pend > MAX_TX_URB) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001758 netdev_dbg(dev, "To discard skb packet!\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001759 dev_kfree_skb_any(skb);
1760 return -1;
1761 }
1762
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001763 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001764 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001765 dev_kfree_skb_any(skb);
1766 return -ENOMEM;
1767 }
1768
1769 /* Fill Tx firmware info */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001770 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001771 /* DWORD 0 */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001772 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001773 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1774 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1775 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001776 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001777 tx_fwinfo->AllowAggregation = 1;
1778 /* DWORD 1 */
1779 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1780 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1781 } else {
1782 tx_fwinfo->AllowAggregation = 0;
1783 /* DWORD 1 */
1784 tx_fwinfo->RxMF = 0;
1785 tx_fwinfo->RxAMD = 0;
1786 }
1787
1788 /* Protection mode related */
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001789 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1790 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1791 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1792 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001793 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03001794 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->RTSSC) : 0;
1795 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1) ? ((tcb_desc->bRTSBW) ? 1 : 0) : 0;
1796 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) :
1797 (tcb_desc->bRTSUseShortGI ? 1 : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001798
1799 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001800 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001801 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001802 tx_fwinfo->TxBandwidth = 1;
1803 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1804 } else {
1805 tx_fwinfo->TxBandwidth = 0;
1806 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1807 }
1808 } else {
1809 tx_fwinfo->TxBandwidth = 0;
1810 tx_fwinfo->TxSubCarrier = 0;
1811 }
1812
1813#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1814 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001815 tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001816#endif
1817 /* Fill Tx descriptor */
1818 memset(tx_desc, 0, sizeof(tx_desc_819x_usb));
1819 /* DWORD 0 */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001820 tx_desc->LINIP = 0;
1821 tx_desc->CmdInit = 1;
1822 tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001823
1824#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001825 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001826 tx_desc->PktSize = tcb_desc->pkt_size;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001827 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02001828#endif
1829 {
1830 tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff;
1831 }
1832
1833 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001834 tx_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001835 tx_desc->RATid = tcb_desc->RATRIndex;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001836 tx_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001837 tx_desc->SecType = 0x0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001838 if (tcb_desc->bHwSec) {
1839 switch (priv->ieee80211->pairwise_key_type) {
1840 case KEY_TYPE_WEP40:
1841 case KEY_TYPE_WEP104:
1842 tx_desc->SecType = 0x1;
1843 tx_desc->NoEnc = 0;
1844 break;
1845 case KEY_TYPE_TKIP:
1846 tx_desc->SecType = 0x2;
1847 tx_desc->NoEnc = 0;
1848 break;
1849 case KEY_TYPE_CCMP:
1850 tx_desc->SecType = 0x3;
1851 tx_desc->NoEnc = 0;
1852 break;
1853 case KEY_TYPE_NA:
1854 tx_desc->SecType = 0x0;
1855 tx_desc->NoEnc = 1;
1856 break;
1857 }
1858 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001859
1860 tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1861 tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1862
1863 tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1864 tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1865
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001866 /* Fill fields that are required to be initialized in all of the descriptors */
1867 //DWORD 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001868 tx_desc->FirstSeg = 1;
1869 tx_desc->LastSeg = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001870 tx_desc->OWN = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001871
1872#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1873 if (tcb_desc->drv_agg_enable) {
1874 tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb);
1875 } else
1876#endif
1877 {
1878 //DWORD 2
1879 tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN);
1880 }
1881 /* Get index to out pipe from specified QueueID */
1882#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001883 idx_pipe = txqueue2outpipe(priv, tcb_desc->queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001884#else
1885 idx_pipe = 0x5;
1886#endif
1887
Jerry Chuang8fc85982009-11-03 07:17:11 -02001888 /* To submit bulk urb */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001889 usb_fill_bulk_urb(tx_urb, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001890 usb_sndbulkpipe(udev, idx_pipe), skb->data,
1891 skb->len, rtl8192_tx_isr, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001892
Jerry Chuang8fc85982009-11-03 07:17:11 -02001893 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001894 if (!status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001895 //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 -02001896 bool bSend0Byte = false;
1897 u8 zero = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001898 if (udev->speed == USB_SPEED_HIGH) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001899 if (skb->len > 0 && skb->len % 512 == 0)
1900 bSend0Byte = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001901 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001902 if (skb->len > 0 && skb->len % 64 == 0)
1903 bSend0Byte = true;
1904 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001905 if (bSend0Byte) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001906 tx_urb_zero = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001907 if (!tx_urb_zero) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001908 RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
1909 return -ENOMEM;
1910 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001911 usb_fill_bulk_urb(tx_urb_zero, udev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001912 usb_sndbulkpipe(udev, idx_pipe), &zero,
1913 0, tx_zero_isr, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001914 status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001915 if (status) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001916 RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
1917 return -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001918 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001919 }
1920 dev->trans_start = jiffies;
1921 atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
1922 return 0;
Patrik Karlin29b48ae2013-01-09 09:40:23 +01001923 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001924 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 +03001925 status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001926 return -1;
1927 }
1928}
1929
Teodora Baluta46326d22013-10-16 01:59:17 +03001930static short rtl8192_usb_initendpoints(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001931{
1932 struct r8192_priv *priv = ieee80211_priv(dev);
1933
Julia Lawall32414872010-05-11 20:26:57 +02001934 priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB+1),
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001935 GFP_KERNEL);
David Chosrovab8345172010-12-01 13:42:16 +01001936 if (priv->rx_urb == NULL)
1937 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001938
1939#ifndef JACKSON_NEW_RX
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001940 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001941
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001942 priv->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001943
1944 priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL);
1945
1946 priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE;
1947 }
1948#endif
1949
1950#ifdef THOMAS_BEACON
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001951 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001952 long align = 0;
1953 void *oldaddr, *newaddr;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001954
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03001955 priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
1956 priv->oldaddr = kmalloc(16, GFP_KERNEL);
1957 oldaddr = priv->oldaddr;
1958 align = ((long)oldaddr) & 3;
1959 if (align) {
1960 newaddr = oldaddr + 4 - align;
1961 priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align;
1962 } else {
1963 newaddr = oldaddr;
1964 priv->rx_urb[16]->transfer_buffer_length = 16;
1965 }
1966 priv->rx_urb[16]->transfer_buffer = newaddr;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001967 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001968#endif
1969
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001970 memset(priv->rx_urb, 0, sizeof(struct urb *) * MAX_RX_URB);
Julia Lawall7a6cb0d2010-05-13 22:00:05 +02001971 priv->pp_rxskb = kcalloc(MAX_RX_URB, sizeof(struct sk_buff *),
Julia Lawall32414872010-05-11 20:26:57 +02001972 GFP_KERNEL);
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001973 if (!priv->pp_rxskb) {
1974 kfree(priv->rx_urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001975
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001976 priv->pp_rxskb = NULL;
1977 priv->rx_urb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001978
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001979 DMESGE("Endpoint Alloc Failure");
1980 return -ENOMEM;
1981 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001982
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001983 netdev_dbg(dev, "End of initendpoints\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001984 return 0;
1985
1986}
1987#ifdef THOMAS_BEACON
Teodora Baluta46326d22013-10-16 01:59:17 +03001988static void rtl8192_usb_deleteendpoints(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001989{
1990 int i;
1991 struct r8192_priv *priv = ieee80211_priv(dev);
1992
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001993 if (priv->rx_urb) {
1994 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001995 usb_kill_urb(priv->rx_urb[i]);
1996 usb_free_urb(priv->rx_urb[i]);
1997 }
1998 kfree(priv->rx_urb);
1999 priv->rx_urb = NULL;
2000 }
Ilia Mirkine72714f2011-03-13 00:29:07 -05002001 kfree(priv->oldaddr);
2002 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002003 if (priv->pp_rxskb) {
2004 kfree(priv->pp_rxskb);
Sachin Kamat875d2a12013-10-09 15:58:30 +05302005 priv->pp_rxskb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002006 }
2007}
2008#else
2009void rtl8192_usb_deleteendpoints(struct net_device *dev)
2010{
2011 int i;
2012 struct r8192_priv *priv = ieee80211_priv(dev);
2013
2014#ifndef JACKSON_NEW_RX
2015
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002016 if (priv->rx_urb) {
2017 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002018 usb_kill_urb(priv->rx_urb[i]);
2019 kfree(priv->rx_urb[i]->transfer_buffer);
2020 usb_free_urb(priv->rx_urb[i]);
2021 }
2022 kfree(priv->rx_urb);
2023 priv->rx_urb = NULL;
2024
2025 }
2026#else
Ilia Mirkine72714f2011-03-13 00:29:07 -05002027 kfree(priv->rx_urb);
2028 priv->rx_urb = NULL;
2029 kfree(priv->oldaddr);
2030 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002031 if (priv->pp_rxskb) {
2032 kfree(priv->pp_rxskb);
2033 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002034
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002035 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002036
2037#endif
2038}
2039#endif
2040
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002041extern void rtl8192_update_ratr_table(struct net_device *dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002042void rtl8192_link_change(struct net_device *dev)
2043{
Jerry Chuang8fc85982009-11-03 07:17:11 -02002044 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002045 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002046 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002047 rtl8192_net_update(dev);
2048 rtl8192_update_ratr_table(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002049 //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
2050 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002051 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002052 }
2053 /*update timing params*/
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002054 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002055 u32 reg = 0;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002056 read_nic_dword(dev, RCR, &reg);
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002057 if (priv->ieee80211->state == IEEE80211_LINKED)
2058 priv->ReceiveConfig = reg |= RCR_CBSSID;
2059 else
2060 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
2061 write_nic_dword(dev, RCR, reg);
2062 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002063}
2064
2065static struct ieee80211_qos_parameters def_qos_parameters = {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002066 {3, 3, 3, 3},/* cw_min */
2067 {7, 7, 7, 7},/* cw_max */
2068 {2, 2, 2, 2},/* aifs */
2069 {0, 0, 0, 0},/* flags */
2070 {0, 0, 0, 0} /* tx_op_limit */
Jerry Chuang8fc85982009-11-03 07:17:11 -02002071};
2072
2073
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002074void rtl8192_update_beacon(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002075{
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002076 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
2077 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002078 struct ieee80211_device *ieee = priv->ieee80211;
2079 struct ieee80211_network *net = &ieee->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002080
2081 if (ieee->pHTInfo->bCurrentHTSupport)
2082 HTUpdateSelfAndPeerSetting(ieee, net);
2083 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
2084 rtl8192_update_cap(dev, net->capability);
2085}
2086/*
2087* background support to run QoS activate functionality
2088*/
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002089int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, EDCAPARA_VO};
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002090void rtl8192_qos_activate(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002091{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002092 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
2093 struct net_device *dev = priv->ieee80211->dev;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002094 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2095 u8 mode = priv->ieee80211->current_network.mode;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002096 u8 u1bAIFS;
2097 u32 u4bAcParam;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002098 int i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002099
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002100 if (priv == NULL)
2101 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002102
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002103 mutex_lock(&priv->mutex);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002104 if (priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002105 goto success;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002106 RT_TRACE(COMP_QOS, "qos active process with associate response received\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002107 /* It better set slot time at first */
2108 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2109 /* update the ac parameter to related registers */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002110 for (i = 0; i < QOS_QUEUE_NUM; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002111 //Mode G/A: slotTimeTimer = 9; Mode B: 20
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002112 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002113 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002114 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2115 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2116 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002117
2118 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002119 }
2120
2121success:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002122 mutex_unlock(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002123}
2124
2125static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002126 int active_network,
2127 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002128{
2129 int ret = 0;
2130 u32 size = sizeof(struct ieee80211_qos_parameters);
2131
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002132 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002133 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002134
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002135 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2136 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002137
2138 if (network->flags & NETWORK_HAS_QOS_MASK) {
2139 if (active_network &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002140 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
Jerry Chuang8fc85982009-11-03 07:17:11 -02002141 network->qos_data.active = network->qos_data.supported;
2142
2143 if ((network->qos_data.active == 1) && (active_network == 1) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002144 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2145 (network->qos_data.old_param_count !=
2146 network->qos_data.param_count)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002147 network->qos_data.old_param_count =
2148 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002149 queue_work(priv->priv_wq, &priv->qos_activate);
Xenia Ragiadakoue6367212013-05-23 05:14:46 +03002150 RT_TRACE(COMP_QOS, "QoS parameters change call "
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002151 "qos_activate\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002152 }
2153 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002154 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002155 &def_qos_parameters, size);
2156
2157 if ((network->qos_data.active == 1) && (active_network == 1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002158 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002159 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2160 }
2161 network->qos_data.active = 0;
2162 network->qos_data.supported = 0;
2163 }
2164
2165 return 0;
2166}
2167
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002168/* handle and manage frame from beacon and probe response */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002169static int rtl8192_handle_beacon(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002170 struct ieee80211_beacon *beacon,
2171 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002172{
2173 struct r8192_priv *priv = ieee80211_priv(dev);
2174
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002175 rtl8192_qos_handle_probe_response(priv, 1, network);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002176 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002177 return 0;
2178
2179}
2180
2181/*
2182* handling the beaconing responses. if we get different QoS setting
2183* off the network from the associated setting, adjust the QoS
2184* setting
2185*/
2186static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002187 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002188{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002189 int ret = 0;
2190 unsigned long flags;
2191 u32 size = sizeof(struct ieee80211_qos_parameters);
2192 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002193
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002194 if ((priv == NULL) || (network == NULL))
2195 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002196
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002197 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002198 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002199
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002200 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2201 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002202
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002203 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002204 if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002205 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002206 &network->qos_data.parameters,
2207 sizeof(struct ieee80211_qos_parameters));
Jerry Chuang8fc85982009-11-03 07:17:11 -02002208 priv->ieee80211->current_network.qos_data.active = 1;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002209 set_qos_param = 1;
2210 /* update qos parameter for current network */
2211 priv->ieee80211->current_network.qos_data.old_param_count =
2212 priv->ieee80211->current_network.qos_data.param_count;
2213 priv->ieee80211->current_network.qos_data.param_count =
2214 network->qos_data.param_count;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002215 } else {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002216 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
Jerry Chuang8fc85982009-11-03 07:17:11 -02002217 &def_qos_parameters, size);
2218 priv->ieee80211->current_network.qos_data.active = 0;
2219 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002220 set_qos_param = 1;
2221 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002222
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002223 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002224
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002225 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 -02002226 if (set_qos_param == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002227 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002228
2229
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002230 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002231}
2232
2233
2234static int rtl8192_handle_assoc_response(struct net_device *dev,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002235 struct ieee80211_assoc_response_frame *resp,
2236 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002237{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002238 struct r8192_priv *priv = ieee80211_priv(dev);
2239 rtl8192_qos_association_resp(priv, network);
2240 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002241}
2242
2243
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002244void rtl8192_update_ratr_table(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002245{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002246 struct r8192_priv *priv = ieee80211_priv(dev);
2247 struct ieee80211_device *ieee = priv->ieee80211;
2248 u8 *pMcsRate = ieee->dot11HTOperationalRateSet;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002249 u32 ratr_value = 0;
2250 u8 rate_index = 0;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002251 rtl8192_config_rate(dev, (u16 *)(&ratr_value));
2252 ratr_value |= (*(u16 *)(pMcsRate)) << 12;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002253 switch (ieee->mode) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002254 case IEEE_A:
2255 ratr_value &= 0x00000FF0;
2256 break;
2257 case IEEE_B:
2258 ratr_value &= 0x0000000F;
2259 break;
2260 case IEEE_G:
2261 ratr_value &= 0x00000FF7;
2262 break;
2263 case IEEE_N_24G:
2264 case IEEE_N_5G:
2265 if (ieee->pHTInfo->PeerMimoPs == 0) {//MIMO_PS_STATIC
2266 ratr_value &= 0x0007F007;
2267 } else {
2268 if (priv->rf_type == RF_1T2R)
2269 ratr_value &= 0x000FF007;
2270 else
2271 ratr_value &= 0x0F81F007;
2272 }
2273 break;
2274 default:
2275 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002276 }
2277 ratr_value &= 0x0FFFFFFF;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002278 if (ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002279 ratr_value |= 0x80000000;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002280 else if (!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002281 ratr_value |= 0x80000000;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002282 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2283 write_nic_byte(dev, UFWP, 1);
2284}
2285
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002286static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04};
Jerry Chuang8fc85982009-11-03 07:17:11 -02002287static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
Teodora Baluta46326d22013-10-16 01:59:17 +03002288static bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002289{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002290 struct r8192_priv *priv = ieee80211_priv(dev);
2291 struct ieee80211_device *ieee = priv->ieee80211;
2292 struct ieee80211_network *network = &ieee->current_network;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002293 int wpa_ie_len = ieee->wpa_ie_len;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002294 struct ieee80211_crypt_data *crypt;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002295 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002296
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002297 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002298 //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 +03002299 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 -02002300
2301 /* simply judge */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002302 if (encrypt && (wpa_ie_len == 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002303 /* wep encryption, no N mode setting */
2304 return false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002305 } else if ((wpa_ie_len != 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002306 /* parse pairwise key type */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002307 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 -02002308 return true;
2309 else
2310 return false;
2311 } else {
2312 return true;
2313 }
2314
Jerry Chuang8fc85982009-11-03 07:17:11 -02002315 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002316}
2317
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002318bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002319{
2320 bool Reval;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002321 struct r8192_priv *priv = ieee80211_priv(dev);
2322 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002323
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002324 if (ieee->bHalfWirelessN24GMode == true)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002325 Reval = true;
2326 else
2327 Reval = false;
2328
2329 return Reval;
2330}
2331
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002332void rtl8192_refresh_supportrate(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002333{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002334 struct ieee80211_device *ieee = priv->ieee80211;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002335 //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002336 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002337 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002338 else
2339 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2340 return;
2341}
2342
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002343u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002344{
2345 struct r8192_priv *priv = ieee80211_priv(dev);
2346 u8 ret = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002347 switch (priv->rf_chip) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002348 case RF_8225:
2349 case RF_8256:
2350 case RF_PSEUDO_11N:
2351 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2352 break;
2353 case RF_8258:
2354 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2355 break;
2356 default:
2357 ret = WIRELESS_MODE_B;
2358 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002359 }
2360 return ret;
2361}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002362void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002363{
2364 struct r8192_priv *priv = ieee80211_priv(dev);
2365 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2366
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002367 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode) == 0)) {
2368 if (bSupportMode & WIRELESS_MODE_N_24G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002369 wireless_mode = WIRELESS_MODE_N_24G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002370 } else if (bSupportMode & WIRELESS_MODE_N_5G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002371 wireless_mode = WIRELESS_MODE_N_5G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002372 } else if ((bSupportMode & WIRELESS_MODE_A)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002373 wireless_mode = WIRELESS_MODE_A;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002374 } else if ((bSupportMode & WIRELESS_MODE_G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002375 wireless_mode = WIRELESS_MODE_G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002376 } else if ((bSupportMode & WIRELESS_MODE_B)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002377 wireless_mode = WIRELESS_MODE_B;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002378 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002379 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __func__, bSupportMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002380 wireless_mode = WIRELESS_MODE_B;
2381 }
2382 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002383#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 +03002384 ActUpdateChannelAccessSetting(pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002385#endif
2386 priv->ieee80211->mode = wireless_mode;
2387
2388 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2389 priv->ieee80211->pHTInfo->bEnableHT = 1;
2390 else
2391 priv->ieee80211->pHTInfo->bEnableHT = 0;
2392 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2393 rtl8192_refresh_supportrate(priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002394
2395}
2396//init priv variables here. only non_zero value should be initialized here.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002397static void rtl8192_init_priv_variable(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002398{
2399 struct r8192_priv *priv = ieee80211_priv(dev);
2400 u8 i;
2401 priv->card_8192 = NIC_8192U;
2402 priv->chan = 1; //set to channel 1
2403 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2404 priv->ieee80211->iw_mode = IW_MODE_INFRA;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002405 priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002406 priv->retry_rts = DEFAULT_RETRY_RTS;
2407 priv->retry_data = DEFAULT_RETRY_DATA;
2408 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2409 priv->ieee80211->rate = 110; //11 mbps
2410 priv->ieee80211->short_slot = 1;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002411 priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002412 priv->CckPwEnl = 6;
2413 //for silent reset
2414 priv->IrpPendingCount = 1;
2415 priv->ResetProgress = RESET_TYPE_NORESET;
2416 priv->bForcedSilentReset = 0;
2417 priv->bDisableNormalResetCheck = false;
2418 priv->force_reset = false;
2419
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002420 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002421 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2422 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2423 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2424 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2425 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002426 IEEE_SOFTMAC_BEACONS;//added by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002427
2428 priv->ieee80211->active_scan = 1;
2429 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2430 priv->ieee80211->host_encrypt = 1;
2431 priv->ieee80211->host_decrypt = 1;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002432 priv->ieee80211->start_send_beacons = NULL; //-by amy 080604
2433 priv->ieee80211->stop_send_beacons = NULL; //-by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002434 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2435 priv->ieee80211->set_chan = rtl8192_set_chan;
2436 priv->ieee80211->link_change = rtl8192_link_change;
2437 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2438 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2439 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2440 priv->ieee80211->init_wmmparam_flag = 0;
2441 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2442 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2443 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
2444 priv->ieee80211->qos_support = 1;
2445
2446 //added by WB
Jerry Chuang8fc85982009-11-03 07:17:11 -02002447 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2448 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2449 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2450 //added by david
2451 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
2452 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
2453 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2454 //added by amy
2455 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
2456 priv->card_type = USB;
2457#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002458 if (Adapter->bInHctTest) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002459 pHalData->ShortRetryLimit = 7;
2460 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002461 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002462#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002463 priv->ShortRetryLimit = 0x30;
2464 priv->LongRetryLimit = 0x30;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002465 priv->EarlyRxThreshold = 7;
2466 priv->enable_gpio0 = 0;
2467 priv->TransmitConfig =
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002468 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002469 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
2470 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002471 (false ? TCR_SAT : 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
Jerry Chuang8fc85982009-11-03 07:17:11 -02002472#ifdef TO_DO_LIST
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002473 if (Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002474 pHalData->ReceiveConfig = pHalData->CSMethod |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002475 RCR_AMF | RCR_ADF | //accept management/data
Jerry Chuang8fc85982009-11-03 07:17:11 -02002476 //guangan200710
2477 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2478 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002479 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002480 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2481 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002482 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002483 else
2484
2485#endif
2486 priv->ReceiveConfig =
2487 RCR_AMF | RCR_ADF | //accept management/data
2488 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2489 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Jerry Chuang8fc85982009-11-03 07:17:11 -02002490 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2491 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03002492 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT : 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002493
2494 priv->AcmControl = 0;
Devendra Nagab7553422012-08-26 11:06:33 +05302495 priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002496
2497 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002498 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002499 skb_queue_head_init(&priv->skb_queue);
2500
2501 /* Tx related queue */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002502 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002503 skb_queue_head_init(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002504 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002505 skb_queue_head_init(&priv->ieee80211->skb_aggQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002506 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03002507 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002508 priv->rf_set_chan = rtl8192_phy_SwChnl;
2509}
2510
2511//init lock here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002512static void rtl8192_init_priv_lock(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002513{
2514 spin_lock_init(&priv->tx_lock);
2515 spin_lock_init(&priv->irq_lock);//added by thomas
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002516 sema_init(&priv->wx_sem, 1);
2517 sema_init(&priv->rf_sem, 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002518 mutex_init(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002519}
2520
Jerry Chuang8fc85982009-11-03 07:17:11 -02002521extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002522
2523void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
2524//init tasklet and wait_queue here. only 2.6 above kernel is considered
2525#define DRV_NAME "wlan0"
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002526static void rtl8192_init_priv_task(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002527{
2528 struct r8192_priv *priv = ieee80211_priv(dev);
2529
Jerry Chuang8fc85982009-11-03 07:17:11 -02002530 priv->priv_wq = create_workqueue(DRV_NAME);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002531
Jerry Chuang8fc85982009-11-03 07:17:11 -02002532 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2533
Jerry Chuang8fc85982009-11-03 07:17:11 -02002534 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2535 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002536 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2537 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2538 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002539 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002540
2541 tasklet_init(&priv->irq_rx_tasklet,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002542 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2543 (unsigned long)priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002544}
2545
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002546static void rtl8192_get_eeprom_size(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002547{
2548 u16 curCR = 0;
2549 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002550 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002551 read_nic_word_E(dev, EPROM_CMD, &curCR);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002552 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
2553 //whether need I consider BIT5?
2554 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002555 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __func__, priv->epromtype);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002556}
2557
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002558//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002559static inline u16 endian_swap(u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002560{
2561 u16 tmp = *data;
2562 *data = (tmp >> 8) | (tmp << 8);
2563 return *data;
2564}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002565static void rtl8192_read_eeprom_info(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002566{
2567 u16 wEPROM_ID = 0;
2568 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
2569 u8 bLoad_From_EEPOM = false;
2570 struct r8192_priv *priv = ieee80211_priv(dev);
2571 u16 tmpValue = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002572 int i;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002573 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002574 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
2575 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
2576
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002577 if (wEPROM_ID != RTL8190_EEPROM_ID) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002578 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 +03002579 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002580 bLoad_From_EEPOM = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002581 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002582
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002583 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002584 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
2585 priv->eeprom_vid = endian_swap(&tmpValue);
2586 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
2587 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002588 priv->eeprom_ChannelPlan = ((tmpValue&0xff00)>>8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002589 priv->btxpowerdata_readfromEEPORM = true;
2590 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002591 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002592 priv->eeprom_vid = 0;
2593 priv->eeprom_pid = 0;
2594 priv->card_8192_version = VERSION_819xU_B;
2595 priv->eeprom_ChannelPlan = 0;
2596 priv->eeprom_CustomerID = 0;
2597 }
2598 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);
2599 //set channelplan from eeprom
2600 priv->ChannelPlan = priv->eeprom_ChannelPlan;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002601 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002602 int i;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002603 for (i = 0; i < 6; i += 2) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002604 u16 tmp = 0;
2605 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002606 *(u16 *)(&dev->dev_addr[i]) = tmp;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002607 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002608 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002609 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2610 //should I set IDR0 here?
2611 }
Joe Perches0ee9f672009-12-06 11:34:52 -08002612 RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002613 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
2614 priv->rf_chip = RF_8256;
2615
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002616 if (priv->card_8192_version == (u8)VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002617 //read Tx power gain offset of legacy OFDM to HT rate
2618 if (bLoad_From_EEPOM)
2619 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
2620 else
2621 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
2622 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
2623 //read ThermalMeter from EEPROM
2624 if (bLoad_From_EEPOM)
2625 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
2626 else
2627 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2628 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
2629 //vivi, for tx power track
2630 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2631 //read antenna tx power offset of B/C/D to A from EEPROM
2632 if (bLoad_From_EEPOM)
2633 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
2634 else
2635 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
2636 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
2637 // Read CrystalCap from EEPROM
2638 if (bLoad_From_EEPOM)
2639 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
2640 else
2641 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
2642 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
2643 //get per-channel Tx power level
2644 if (bLoad_From_EEPOM)
2645 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
2646 else
2647 priv->EEPROM_Def_Ver = 1;
2648 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002649 if (priv->EEPROM_Def_Ver == 0) { //old eeprom definition
Jerry Chuang8fc85982009-11-03 07:17:11 -02002650 int i;
2651 if (bLoad_From_EEPOM)
2652 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
2653 else
2654 priv->EEPROMTxPowerLevelCCK = 0x10;
2655 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002656 for (i = 0; i < 3; i++) {
2657 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002658 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
2659 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
2660 tmpValue = tmpValue & 0x00ff;
2661 else
2662 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002663 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002664 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002665 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002666 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
2667 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
2668 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002669 } else if (priv->EEPROM_Def_Ver == 1) {
2670 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002671 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
2672 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002673 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002674 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002675 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002676 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
2677
2678 if (bLoad_From_EEPOM)
2679 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
2680 else
2681 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002682 *((u16 *)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002683 if (bLoad_From_EEPOM)
2684 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
2685 else
2686 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002687 *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002688 if (bLoad_From_EEPOM)
2689 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
2690 else
2691 tmpValue = 0x10;
2692 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
2693 }//endif EEPROM_Def_Ver == 1
2694
2695 //update HAL variables
2696 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002697 for (i = 0; i < 14; i++) {
2698 if (i <= 3)
2699 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
2700 else if (i >= 4 && i <= 9)
2701 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
2702 else
2703 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
2704 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002705
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002706 for (i = 0; i < 14; i++) {
2707 if (priv->EEPROM_Def_Ver == 0) {
2708 if (i <= 3)
2709 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2710 else if (i >= 4 && i <= 9)
2711 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
2712 else
2713 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
2714 } else if (priv->EEPROM_Def_Ver == 1) {
2715 if (i <= 3)
2716 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
2717 else if (i >= 4 && i <= 9)
2718 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
2719 else
2720 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002721 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002722 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002723 priv->TxPowerDiff = priv->EEPROMPwDiff;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002724 // Antenna B gain offset to antenna A, bit0~3
Jerry Chuang8fc85982009-11-03 07:17:11 -02002725 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
2726 // Antenna C gain offset to antenna A, bit4~7
2727 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
2728 // CrystalCap, bit12~15
2729 priv->CrystalCap = priv->EEPROMCrystalCap;
2730 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
2731 // 92U does not enable TX power tracking.
2732 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
2733 }//end if VersionID == VERSION_819xU_A
2734
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002735 //added by vivi, for dlink led, 20080416
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002736 switch (priv->eeprom_CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002737 case EEPROM_CID_RUNTOP:
2738 priv->CustomerID = RT_CID_819x_RUNTOP;
2739 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002740
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002741 case EEPROM_CID_DLINK:
2742 priv->CustomerID = RT_CID_DLINK;
2743 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002744
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002745 default:
2746 priv->CustomerID = RT_CID_DEFAULT;
2747 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002748
2749 }
2750
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002751 switch (priv->CustomerID) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002752 case RT_CID_819x_RUNTOP:
2753 priv->LedStrategy = SW_LED_MODE2;
2754 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002755
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002756 case RT_CID_DLINK:
2757 priv->LedStrategy = SW_LED_MODE4;
2758 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002759
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002760 default:
2761 priv->LedStrategy = SW_LED_MODE0;
2762 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002763
2764 }
2765
2766
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002767 if (priv->rf_type == RF_1T2R) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002768 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002769 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002770 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
2771 }
2772
2773 // 2008/01/16 MH We can only know RF type in the function. So we have to init
2774 // DIG RATR table again.
2775 init_rate_adaptive(dev);
2776 //we need init DIG RATR table here again.
2777
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002778 RT_TRACE(COMP_EPROM, "<===========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002779 return;
2780}
2781
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002782short rtl8192_get_channel_map(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002783{
2784 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002785 if (priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03002786 netdev_err(dev, "rtl8180_init: Error channel plan! Set to default.\n");
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002787 priv->ChannelPlan = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002788 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002789 RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002790
2791 rtl819x_set_channel_map(priv->ChannelPlan, priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002792 return 0;
2793}
2794
2795short rtl8192_init(struct net_device *dev)
2796{
2797
2798 struct r8192_priv *priv = ieee80211_priv(dev);
2799
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002800 memset(&(priv->stats), 0, sizeof(struct Stats));
2801 memset(priv->txqueue_to_outpipemap, 0, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002802#ifdef PIPE12
2803 {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002804 int i = 0;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002805 u8 queuetopipe[] = {3, 2, 1, 0, 4, 8, 7, 6, 5};
2806 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002807 }
2808#else
2809 {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002810 u8 queuetopipe[] = {3, 2, 1, 0, 4, 4, 0, 4, 4};
2811 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002812 }
2813#endif
2814 rtl8192_init_priv_variable(dev);
2815 rtl8192_init_priv_lock(priv);
2816 rtl8192_init_priv_task(dev);
2817 rtl8192_get_eeprom_size(dev);
2818 rtl8192_read_eeprom_info(dev);
2819 rtl8192_get_channel_map(dev);
2820 init_hal_dm(dev);
2821 init_timer(&priv->watch_dog_timer);
2822 priv->watch_dog_timer.data = (unsigned long)dev;
2823 priv->watch_dog_timer.function = watch_dog_timer_callback;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002824 if (rtl8192_usb_initendpoints(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002825 DMESG("Endopoints initialization failed");
2826 return -ENOMEM;
2827 }
2828
Jerry Chuang8fc85982009-11-03 07:17:11 -02002829#ifdef DEBUG_EPROM
2830 dump_eprom(dev);
2831#endif
2832 return 0;
2833}
2834
2835/******************************************************************************
2836 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
2837 * not to do all the hw config as its name says
2838 * input: net_device dev
2839 * output: none
2840 * return: none
2841 * notice: This part need to modified according to the rate set we filtered
2842 * ****************************************************************************/
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002843void rtl8192_hwconfig(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002844{
2845 u32 regRATR = 0, regRRSR = 0;
2846 u8 regBwOpMode = 0, regTmp = 0;
2847 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002848 u32 ratr_value = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002849
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002850 // Set RRSR, RATR, and BW_OPMODE registers
Jerry Chuang8fc85982009-11-03 07:17:11 -02002851 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002852 switch (priv->ieee80211->mode) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002853 case WIRELESS_MODE_B:
2854 regBwOpMode = BW_OPMODE_20MHZ;
2855 regRATR = RATE_ALL_CCK;
2856 regRRSR = RATE_ALL_CCK;
2857 break;
2858 case WIRELESS_MODE_A:
2859 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
2860 regRATR = RATE_ALL_OFDM_AG;
2861 regRRSR = RATE_ALL_OFDM_AG;
2862 break;
2863 case WIRELESS_MODE_G:
2864 regBwOpMode = BW_OPMODE_20MHZ;
2865 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2866 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2867 break;
2868 case WIRELESS_MODE_AUTO:
2869#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002870 if (Adapter->bInHctTest) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002871 regBwOpMode = BW_OPMODE_20MHZ;
2872 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2873 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002874 }
2875 else
2876#endif
2877 {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002878 regBwOpMode = BW_OPMODE_20MHZ;
2879 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2880 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002881 }
2882 break;
2883 case WIRELESS_MODE_N_24G:
2884 // It support CCK rate by default.
2885 // CCK rate will be filtered out only when associated AP does not support it.
2886 regBwOpMode = BW_OPMODE_20MHZ;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002887 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2888 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002889 break;
2890 case WIRELESS_MODE_N_5G:
2891 regBwOpMode = BW_OPMODE_5G;
2892 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2893 regRRSR = RATE_ALL_OFDM_AG;
2894 break;
2895 }
2896
2897 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002898 ratr_value = regRATR;
2899 if (priv->rf_type == RF_1T2R)
2900 ratr_value &= ~(RATE_ALL_OFDM_2SS);
2901 write_nic_dword(dev, RATR0, ratr_value);
2902 write_nic_byte(dev, UFWP, 1);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002903 read_nic_byte(dev, 0x313, &regTmp);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002904 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
2905 write_nic_dword(dev, RRSR, regRRSR);
2906
2907 //
2908 // Set Retry Limit here
2909 //
2910 write_nic_word(dev, RETRY_LIMIT,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002911 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
2912 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002913 // Set Contention Window here
2914
2915 // Set Tx AGC
2916
2917 // Set Tx Antenna including Feedback control
2918
2919 // Set Auto Rate fallback control
2920
2921
2922}
2923
2924
2925//InitializeAdapter and PhyCfg
2926bool rtl8192_adapter_start(struct net_device *dev)
2927{
2928 struct r8192_priv *priv = ieee80211_priv(dev);
2929 u32 dwRegRead = 0;
2930 bool init_status = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002931 u8 SECR_value = 0x0;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002932 u8 tmp;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002933 RT_TRACE(COMP_INIT, "====>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002934 priv->Rf_Mode = RF_OP_By_SW_3wire;
2935 //for ASIC power on sequence
2936 write_nic_byte_E(dev, 0x5f, 0x80);
2937 mdelay(50);
2938 write_nic_byte_E(dev, 0x5f, 0xf0);
2939 write_nic_byte_E(dev, 0x5d, 0x00);
2940 write_nic_byte_E(dev, 0x5e, 0x80);
2941 write_nic_byte(dev, 0x17, 0x37);
2942 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002943 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
2944 //config CPUReset Register
2945 //Firmware Reset or not?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002946 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002947 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
2948 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
2949 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
2950 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
2951 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002952 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __func__, priv->pFirmware->firmware_status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002953
2954 write_nic_dword(dev, CPU_GEN, dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002955 //config BB.
2956 rtl8192_BBConfig(dev);
2957
Jerry Chuang8fc85982009-11-03 07:17:11 -02002958 //Loopback mode or not
2959 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002960
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002961 read_nic_dword(dev, CPU_GEN, &dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002962 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
2963 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
2964 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
2965 dwRegRead |= CPU_CCK_LOOPBACK;
2966 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002967 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __func__, priv->LoopbackMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002968
2969 write_nic_dword(dev, CPU_GEN, dwRegRead);
2970
2971 //after reset cpu, we need wait for a seconds to write in register.
2972 udelay(500);
2973
2974 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03002975 read_nic_byte_E(dev, 0x5f, &tmp);
2976 write_nic_byte_E(dev, 0x5f, tmp|0x20);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002977
2978 //Set Hardware
2979 rtl8192_hwconfig(dev);
2980
2981 //turn on Tx/Rx
2982 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
2983
2984 //set IDR0 here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002985 write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
2986 write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002987
2988 //set RCR
2989 write_nic_dword(dev, RCR, priv->ReceiveConfig);
2990
2991 //Initialize Number of Reserved Pages in Firmware Queue
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002992 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 +03002993 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT |
2994 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT |
2995 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002996 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 +03002997 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03002998 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW|
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03002999 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003000 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
3001
3002 //Set AckTimeout
3003 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
3004 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
3005
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003006 if (priv->ResetProgress == RESET_TYPE_NORESET)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003007 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003008 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003009 CamResetAllEntry(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003010 SECR_value |= SCR_TxEncEnable;
3011 SECR_value |= SCR_RxDecEnable;
3012 SECR_value |= SCR_NoSKMC;
3013 write_nic_byte(dev, SECR, SECR_value);
3014 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003015
3016 //Beacon related
3017 write_nic_word(dev, ATIMWND, 2);
3018 write_nic_word(dev, BCN_INTERVAL, 100);
3019
Jerry Chuang8fc85982009-11-03 07:17:11 -02003020#define DEFAULT_EDCA 0x005e4332
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003021 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003022 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003023 for (i = 0; i < QOS_QUEUE_NUM; i++)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003024 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003025 }
3026#ifdef USB_RX_AGGREGATION_SUPPORT
3027 //3 For usb rx firmware aggregation control
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003028 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003029 u32 ulValue;
3030 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
3031 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003032 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003033 /*
3034 * If usb rx firmware aggregation is enabled,
3035 * when anyone of three threshold conditions above is reached,
3036 * firmware will send aggregated packet to driver.
3037 */
3038 write_nic_dword(dev, 0x1a8, ulValue);
3039 priv->bCurrentRxAggrEnable = true;
3040 }
3041#endif
3042
3043 rtl8192_phy_configmac(dev);
3044
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003045 if (priv->card_8192_version == (u8) VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003046 rtl8192_phy_getTxPower(dev);
3047 rtl8192_phy_setTxPower(dev, priv->chan);
3048 }
3049
3050 //Firmware download
3051 init_status = init_firmware(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003052 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003053 RT_TRACE(COMP_ERR, "ERR!!! %s(): Firmware download is failed\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003054 return init_status;
3055 }
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003056 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003057 //
3058#ifdef TO_DO_LIST
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003059 if (Adapter->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003060 if (pMgntInfo->RegRfOff == TRUE) { // User disable RF via registry.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003061 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
3062 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003063 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003064 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003065 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003066 } else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { // H/W or S/W RF OFF before sleep.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003067 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
3068 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003069 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003070 pHalData->eRFPowerState = eRfOn;
3071 pMgntInfo->RfOffReason = 0;
3072 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
3073 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003074 } else {
3075 if (pHalData->eRFPowerState == eRfOff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003076 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003077 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003078 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003079 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3080 }
3081 }
3082#endif
3083 //config RF.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003084 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003085 rtl8192_phy_RFConfig(dev);
3086 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003087 }
3088
3089
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003090 if (priv->ieee80211->FwRWRF)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003091 // We can force firmware to do RF-R/W
3092 priv->Rf_Mode = RF_OP_By_FW;
3093 else
3094 priv->Rf_Mode = RF_OP_By_SW_3wire;
3095
3096
3097 rtl8192_phy_updateInitGain(dev);
3098 /*--set CCK and OFDM Block "ON"--*/
3099 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3100 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3101
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003102 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003103 //if D or C cut
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003104 u8 tmpvalue;
3105 read_nic_byte(dev, 0x301, &tmpvalue);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003106 if (tmpvalue == 0x03) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003107 priv->bDcut = TRUE;
3108 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003109 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003110 priv->bDcut = FALSE;
3111 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
3112 }
3113 dm_initialize_txpower_tracking(dev);
3114
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003115 if (priv->bDcut == TRUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003116 u32 i, TempCCk;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003117 u32 tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003118 for (i = 0; i < TxBBGainTableLength; i++) {
3119 if (tmpRegA == priv->txbbgain_table[i].txbbgain_value) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003120 priv->rfa_txpowertrackingindex = (u8)i;
3121 priv->rfa_txpowertrackingindex_real = (u8)i;
3122 priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003123 break;
3124 }
3125 }
3126
3127 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3128
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003129 for (i = 0; i < CCKTxBBGainTableLength; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003130
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003131 if (TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0]) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003132 priv->cck_present_attentuation_20Mdefault = (u8) i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003133 break;
3134 }
3135 }
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003136 priv->cck_present_attentuation_40Mdefault = 0;
3137 priv->cck_present_attentuation_difference = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003138 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
3139
Jerry Chuang8fc85982009-11-03 07:17:11 -02003140 }
3141 }
3142 write_nic_byte(dev, 0x87, 0x0);
3143
3144
Jerry Chuang8fc85982009-11-03 07:17:11 -02003145 return init_status;
3146}
3147
3148/* this configures registers for beacon tx and enables it via
3149 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3150 * be used to stop beacon transmission
3151 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003152/***************************************************************************
3153 -------------------------------NET STUFF---------------------------
3154***************************************************************************/
3155
3156static struct net_device_stats *rtl8192_stats(struct net_device *dev)
3157{
3158 struct r8192_priv *priv = ieee80211_priv(dev);
3159
3160 return &priv->ieee80211->stats;
3161}
3162
Teodora Baluta46326d22013-10-16 01:59:17 +03003163static bool HalTxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003164{
3165 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003166 u16 RegTxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003167 bool bStuck = FALSE;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003168 read_nic_word(dev, 0x128, &RegTxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003169 RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", __func__, RegTxCounter, priv->TxCounter);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003170 if (priv->TxCounter == RegTxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003171 bStuck = TRUE;
3172
3173 priv->TxCounter = RegTxCounter;
3174
3175 return bStuck;
3176}
3177
3178/*
3179* <Assumption: RT_TX_SPINLOCK is acquired.>
3180* First added: 2006.11.19 by emily
3181*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003182RESET_TYPE TxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003183{
3184 struct r8192_priv *priv = ieee80211_priv(dev);
3185 u8 QueueID;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003186 bool bCheckFwTxCnt = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003187
3188 //
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003189 // Decide such threshold according to current power save mode
Jerry Chuang8fc85982009-11-03 07:17:11 -02003190 //
3191
Xenia Ragiadakou7d79ec62013-06-04 23:32:30 +03003192 for (QueueID = 0; QueueID <= BEACON_QUEUE; QueueID++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003193 if (QueueID == TXCMD_QUEUE)
3194 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003195#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003196 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 -02003197#else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003198 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 -02003199#endif
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003200 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003201
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003202 bCheckFwTxCnt = true;
3203 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003204 if (bCheckFwTxCnt) {
3205 if (HalTxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003206 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
3207 return RESET_TYPE_SILENT;
3208 }
3209 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003210 return RESET_TYPE_NORESET;
3211}
3212
Teodora Baluta46326d22013-10-16 01:59:17 +03003213static bool HalRxCheckStuck819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003214{
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003215 u16 RegRxCounter;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003216 struct r8192_priv *priv = ieee80211_priv(dev);
3217 bool bStuck = FALSE;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003218 static u8 rx_chk_cnt;
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003219 read_nic_word(dev, 0x130, &RegRxCounter);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003220 RT_TRACE(COMP_RESET, "%s(): RegRxCounter is %d,RxCounter is %d\n", __func__, RegRxCounter, priv->RxCounter);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003221 // If rssi is small, we should check rx for long time because of bad rx.
3222 // or maybe it will continuous silent reset every 2 seconds.
3223 rx_chk_cnt++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003224 if (priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003225 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003226 } else if (priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003227 ((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_40M) ||
3228 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_20M))) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003229 if (rx_chk_cnt < 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003230 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003231 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003232 rx_chk_cnt = 0;
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003233 } else if (((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_40M) ||
3234 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 && priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_20M)) &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003235 priv->undecorated_smoothed_pwdb >= VeryLowRSSI) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003236 if (rx_chk_cnt < 4)
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 Ragiadakou27161412013-06-03 23:58:45 +03003240 } else {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003241 if (rx_chk_cnt < 8)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003242 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003243 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003244 rx_chk_cnt = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003245 }
3246
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003247 if (priv->RxCounter == RegRxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003248 bStuck = TRUE;
3249
3250 priv->RxCounter = RegRxCounter;
3251
3252 return bStuck;
3253}
3254
Teodora Baluta46326d22013-10-16 01:59:17 +03003255static RESET_TYPE RxCheckStuck(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003256{
3257 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003258 bool bRxCheck = FALSE;
3259
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003260 if (priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003261 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003262
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003263 if (bRxCheck) {
3264 if (HalRxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003265 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
3266 return RESET_TYPE_SILENT;
3267 }
3268 }
3269 return RESET_TYPE_NORESET;
3270}
3271
3272
3273/**
3274* This function is called by Checkforhang to check whether we should ask OS to reset driver
3275*
3276* \param pAdapter The adapter context for this miniport
3277*
3278* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
3279* to judge whether there is tx stuck.
3280* Note: This function may be required to be rewrite for Vista OS.
3281* <<<Assumption: Tx spinlock has been acquired >>>
3282*
3283* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
3284*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003285RESET_TYPE rtl819x_ifcheck_resetornot(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003286{
3287 struct r8192_priv *priv = ieee80211_priv(dev);
3288 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
3289 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003290 RT_RF_POWER_STATE rfState;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003291
3292 rfState = priv->ieee80211->eRFPowerState;
3293
3294 TxResetType = TxCheckStuck(dev);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003295 if (rfState != eRfOff ||
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003296 (priv->ieee80211->iw_mode != IW_MODE_ADHOC)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003297 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
3298 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
3299 // if driver is in firmware download failure status, driver should initialize RF in the following
3300 // silent reset procedure Emily, 2008.01.21
3301
3302 // Driver should not check RX stuck in IBSS mode because it is required to
3303 // set Check BSSID in order to send beacon, however, if check BSSID is
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003304 // set, STA cannot hear any packet at all. Emily, 2008.04.12
Jerry Chuang8fc85982009-11-03 07:17:11 -02003305 RxResetType = RxCheckStuck(dev);
3306 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003307 if (TxResetType == RESET_TYPE_NORMAL || RxResetType == RESET_TYPE_NORMAL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003308 return RESET_TYPE_NORMAL;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003309 } else if (TxResetType == RESET_TYPE_SILENT || RxResetType == RESET_TYPE_SILENT) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003310 RT_TRACE(COMP_RESET, "%s():silent reset\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003311 return RESET_TYPE_SILENT;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003312 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003313 return RESET_TYPE_NORESET;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003314 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003315
3316}
3317
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003318void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003319int _rtl8192_up(struct net_device *dev);
3320int rtl8192_close(struct net_device *dev);
3321
3322
3323
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003324void CamRestoreAllEntry(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003325{
3326 u8 EntryId = 0;
3327 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003328 u8 *MacAddr = priv->ieee80211->current_network.bssid;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003329
3330 static u8 CAM_CONST_ADDR[4][6] = {
3331 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3332 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
3333 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03003334 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003335 static u8 CAM_CONST_BROAD[] = {
3336 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003337
3338 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
3339
3340
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003341 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40) ||
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003342 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003343
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003344 for (EntryId = 0; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003345 MacAddr = CAM_CONST_ADDR[EntryId];
3346 setKey(dev, EntryId, EntryId,
3347 priv->ieee80211->pairwise_key_type,
3348 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003349 }
3350
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003351 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003352
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003353 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3354 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3355 (u8 *)dev->dev_addr, 0, NULL);
3356 else
3357 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3358 MacAddr, 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003359 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003360
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003361 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3362 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3363 (u8 *)dev->dev_addr, 0, NULL);
3364 else
3365 setKey(dev, 4, 0, priv->ieee80211->pairwise_key_type,
3366 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003367 }
3368
3369
3370
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003371 if (priv->ieee80211->group_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003372 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003373 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003374 setKey(dev, EntryId, EntryId,
3375 priv->ieee80211->group_key_type,
3376 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003377 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003378 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003379 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3380 CAM_CONST_ADDR[0], 0, NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003381 } else if (priv->ieee80211->group_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003382 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003383 for (EntryId = 1; EntryId < 4; EntryId++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003384 setKey(dev, EntryId, EntryId,
3385 priv->ieee80211->group_key_type,
3386 MacAddr, 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003387 }
3388
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003389 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003390 setKey(dev, 0, 0, priv->ieee80211->group_key_type,
3391 CAM_CONST_ADDR[0], 0, NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003392 }
3393}
3394//////////////////////////////////////////////////////////////
3395// This function is used to fix Tx/Rx stop bug temporarily.
3396// This function will do "system reset" to NIC when Tx or Rx is stuck.
3397// The method checking Tx/Rx stuck of this function is supported by FW,
3398// which reports Tx and Rx counter to register 0x128 and 0x130.
3399//////////////////////////////////////////////////////////////
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003400void rtl819x_ifsilentreset(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003401{
Jerry Chuang8fc85982009-11-03 07:17:11 -02003402 struct r8192_priv *priv = ieee80211_priv(dev);
3403 u8 reset_times = 0;
3404 int reset_status = 0;
3405 struct ieee80211_device *ieee = priv->ieee80211;
3406
3407
3408 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
3409 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
3410
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003411 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003412RESET_START:
3413
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003414 RT_TRACE(COMP_RESET, "=========>Reset progress!! \n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003415
3416 // Set the variable for reset.
3417 priv->ResetProgress = RESET_TYPE_SILENT;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003418 down(&priv->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003419 if (priv->up == 0) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003420 RT_TRACE(COMP_ERR, "%s():the driver is not up! return\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003421 up(&priv->wx_sem);
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003422 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003423 }
3424 priv->up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003425 RT_TRACE(COMP_RESET, "%s():======>start to down the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003426
3427 rtl8192_rtx_disable(dev);
3428 rtl8192_cancel_deferred_work(priv);
3429 deinit_hal_dm(dev);
3430 del_timer_sync(&priv->watch_dog_timer);
3431
3432 ieee->sync_scan_hurryup = 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003433 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003434 down(&ieee->wx_sem);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003435 netdev_dbg(dev, "ieee->state is IEEE80211_LINKED\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003436 ieee80211_stop_send_beacons(priv->ieee80211);
3437 del_timer_sync(&ieee->associate_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003438 cancel_delayed_work(&ieee->associate_retry_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003439 ieee80211_stop_scan(ieee);
3440 netif_carrier_off(dev);
3441 up(&ieee->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003442 } else {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003443 netdev_dbg(dev, "ieee->state is NOT LINKED\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003444 ieee80211_softmac_stop_protocol(priv->ieee80211);
3445 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003446 up(&priv->wx_sem);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003447 RT_TRACE(COMP_RESET, "%s():<==========down process is finished\n", __func__);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003448 RT_TRACE(COMP_RESET, "%s():===========>start up the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003449 reset_status = _rtl8192_up(dev);
3450
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003451 RT_TRACE(COMP_RESET, "%s():<===========up process is finished\n", __func__);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003452 if (reset_status == -EAGAIN) {
3453 if (reset_times < 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003454 reset_times++;
3455 goto RESET_START;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003456 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003457 RT_TRACE(COMP_ERR, " ERR!!! %s(): Reset Failed!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003458 }
3459 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003460 ieee->is_silent_reset = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003461 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003462 if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003463 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3464
Jerry Chuang8fc85982009-11-03 07:17:11 -02003465 queue_work(ieee->wq, &ieee->associate_complete_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003466
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003467 } else if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003468 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3469 ieee->link_change(ieee->dev);
3470
Jerry Chuang8fc85982009-11-03 07:17:11 -02003471 ieee80211_start_send_beacons(ieee);
3472
3473 if (ieee->data_hard_resume)
3474 ieee->data_hard_resume(ieee->dev);
3475 netif_carrier_on(ieee->dev);
3476 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003477
3478 CamRestoreAllEntry(dev);
3479
3480 priv->ResetProgress = RESET_TYPE_NORESET;
3481 priv->reset_count++;
3482
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003483 priv->bForcedSilentReset = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003484 priv->bResetInProgress = false;
3485
3486 // For test --> force write UFWP.
3487 write_nic_byte(dev, UFWP, 1);
3488 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003489 }
3490}
3491
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003492void CAM_read_entry(struct net_device *dev, u32 iIndex)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003493{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003494 u32 target_command = 0;
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003495 u32 target_content = 0;
3496 u8 entry_i = 0;
3497 u32 ulStatus;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003498 s32 i = 100;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003499 for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003500 // polling bit, and No Write enable, and address
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003501 target_command = entry_i+CAM_CONTENT_COUNT*iIndex;
3502 target_command = target_command | BIT31;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003503
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003504 //Check polling bit is clear
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003505 while ((i--) >= 0) {
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003506 read_nic_dword(dev, RWCAM, &ulStatus);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003507 if (ulStatus & BIT31)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003508 continue;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003509 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003510 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003511 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003512 write_nic_dword(dev, RWCAM, target_command);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003513 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x \n", target_command);
Xenia Ragiadakoub3d42bf2013-06-06 16:40:51 +03003514 read_nic_dword(dev, RCAMO, &target_content);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003515 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n", target_content);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003516 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003517 printk("\n");
3518}
3519
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003520void rtl819x_update_rxcounts(struct r8192_priv *priv, u32 *TotalRxBcnNum,
3521 u32 *TotalRxDataNum)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003522{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003523 u16 SlotIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003524 u8 i;
3525
3526 *TotalRxBcnNum = 0;
3527 *TotalRxDataNum = 0;
3528
3529 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
3530 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
3531 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003532 for (i = 0; i < priv->ieee80211->LinkDetectInfo.SlotNum; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003533 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
3534 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
3535 }
3536}
3537
3538
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03003539extern void rtl819x_watchdog_wqcallback(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003540{
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003541 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003542 struct r8192_priv *priv = container_of(dwork, struct r8192_priv, watch_dog_wq);
3543 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003544 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003545 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003546 static u8 check_reset_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003547 bool bBusyTraffic = false;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003548 u32 TotalRxBcnNum = 0;
3549 u32 TotalRxDataNum = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003550
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003551 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003552 return;
3553 hal_dm_watchdog(dev);
3554
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003555 //to get busy traffic condition
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003556 if (ieee->state == IEEE80211_LINKED) {
3557 if (ieee->LinkDetectInfo.NumRxOkInPeriod > 666 ||
3558 ieee->LinkDetectInfo.NumTxOkInPeriod > 666 ) {
3559 bBusyTraffic = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003560 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003561 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
3562 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
3563 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
3564 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003565 //added by amy for AP roaming
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003566 if (priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003567
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003568 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
3569 if ((TotalRxBcnNum+TotalRxDataNum) == 0) {
3570#ifdef TODO
3571 if (rfState == eRfOff)
3572 RT_TRACE(COMP_ERR, "========>%s()\n", __func__);
3573#endif
3574 netdev_dbg(dev, "===>%s(): AP is power off, connect another one\n", __func__);
3575 priv->ieee80211->state = IEEE80211_ASSOCIATING;
3576 notify_wx_assoc_event(priv->ieee80211);
3577 RemovePeerTS(priv->ieee80211, priv->ieee80211->current_network.bssid);
3578 priv->ieee80211->link_change(dev);
3579 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003580
Jerry Chuang8fc85982009-11-03 07:17:11 -02003581 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003582 }
3583 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod = 0;
3584 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003585 //check if reset the driver
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003586 if (check_reset_cnt++ >= 3) {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003587 ResetType = rtl819x_ifcheck_resetornot(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003588 check_reset_cnt = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003589 }
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003590 if ((priv->force_reset) || (priv->ResetProgress == RESET_TYPE_NORESET &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003591 (priv->bForcedSilentReset ||
3592 (!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_SILENT)))) { // This is control by OID set in Pomelo
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003593 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 -02003594 rtl819x_ifsilentreset(dev);
3595 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003596 priv->force_reset = false;
3597 priv->bForcedSilentReset = false;
3598 priv->bResetInProgress = false;
3599 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
3600
3601}
3602
3603void watch_dog_timer_callback(unsigned long data)
3604{
3605 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003606 queue_delayed_work(priv->priv_wq, &priv->watch_dog_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003607 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
Jerry Chuang8fc85982009-11-03 07:17:11 -02003608}
3609int _rtl8192_up(struct net_device *dev)
3610{
3611 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003612 int init_status = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003613 priv->up = 1;
3614 priv->ieee80211->ieee_up = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003615 RT_TRACE(COMP_INIT, "Bringing up iface");
3616 init_status = rtl8192_adapter_start(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003617 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003618 RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization failed!\n", __func__);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003619 priv->up = priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003620 return -EAGAIN;
3621 }
3622 RT_TRACE(COMP_INIT, "start adapter finished\n");
3623 rtl8192_rx_enable(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003624 if (priv->ieee80211->state != IEEE80211_LINKED)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003625 ieee80211_softmac_start_protocol(priv->ieee80211);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003626 ieee80211_reset_queue(priv->ieee80211);
3627 watch_dog_timer_callback((unsigned long) dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003628 if (!netif_queue_stopped(dev))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003629 netif_start_queue(dev);
3630 else
3631 netif_wake_queue(dev);
3632
3633 return 0;
3634}
3635
3636
3637int rtl8192_open(struct net_device *dev)
3638{
3639 struct r8192_priv *priv = ieee80211_priv(dev);
3640 int ret;
3641 down(&priv->wx_sem);
3642 ret = rtl8192_up(dev);
3643 up(&priv->wx_sem);
3644 return ret;
3645
3646}
3647
3648
3649int rtl8192_up(struct net_device *dev)
3650{
3651 struct r8192_priv *priv = ieee80211_priv(dev);
3652
3653 if (priv->up == 1) return -1;
3654
3655 return _rtl8192_up(dev);
3656}
3657
3658
3659int rtl8192_close(struct net_device *dev)
3660{
3661 struct r8192_priv *priv = ieee80211_priv(dev);
3662 int ret;
3663
3664 down(&priv->wx_sem);
3665
3666 ret = rtl8192_down(dev);
3667
3668 up(&priv->wx_sem);
3669
3670 return ret;
3671
3672}
3673
3674int rtl8192_down(struct net_device *dev)
3675{
3676 struct r8192_priv *priv = ieee80211_priv(dev);
3677 int i;
3678
3679 if (priv->up == 0) return -1;
3680
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003681 priv->up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003682 priv->ieee80211->ieee_up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003683 RT_TRACE(COMP_DOWN, "==========>%s()\n", __func__);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003684 /* FIXME */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003685 if (!netif_queue_stopped(dev))
3686 netif_stop_queue(dev);
3687
3688 rtl8192_rtx_disable(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003689
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003690 /* Tx related queue release */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003691 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003692 skb_queue_purge(&priv->ieee80211->skb_waitQ[i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003693 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003694 skb_queue_purge(&priv->ieee80211->skb_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003695
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003696 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Xenia Ragiadakoub1753c42013-06-04 23:32:26 +03003697 skb_queue_purge(&priv->ieee80211->skb_drv_aggQ[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003698
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003699 //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 -02003700 rtl8192_cancel_deferred_work(priv);
3701 deinit_hal_dm(dev);
3702 del_timer_sync(&priv->watch_dog_timer);
3703
3704
3705 ieee80211_softmac_stop_protocol(priv->ieee80211);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003706 memset(&priv->ieee80211->current_network, 0, offsetof(struct ieee80211_network, list));
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003707 RT_TRACE(COMP_DOWN, "<==========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003708
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003709 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003710}
3711
3712
3713void rtl8192_commit(struct net_device *dev)
3714{
3715 struct r8192_priv *priv = ieee80211_priv(dev);
3716 int reset_status = 0;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003717 if (priv->up == 0) return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003718 priv->up = 0;
3719
3720 rtl8192_cancel_deferred_work(priv);
3721 del_timer_sync(&priv->watch_dog_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003722
3723 ieee80211_softmac_stop_protocol(priv->ieee80211);
3724
Jerry Chuang8fc85982009-11-03 07:17:11 -02003725 rtl8192_rtx_disable(dev);
3726 reset_status = _rtl8192_up(dev);
3727
3728}
3729
Jerry Chuang8fc85982009-11-03 07:17:11 -02003730void rtl8192_restart(struct work_struct *work)
3731{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003732 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
3733 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003734
3735 down(&priv->wx_sem);
3736
3737 rtl8192_commit(dev);
3738
3739 up(&priv->wx_sem);
3740}
3741
3742static void r8192_set_multicast(struct net_device *dev)
3743{
3744 struct r8192_priv *priv = ieee80211_priv(dev);
3745 short promisc;
3746
Jerry Chuang8fc85982009-11-03 07:17:11 -02003747 /* FIXME FIXME */
3748
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03003749 promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003750
3751 if (promisc != priv->promisc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003752
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003753 priv->promisc = promisc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003754}
3755
3756
3757int r8192_set_mac_adr(struct net_device *dev, void *mac)
3758{
3759 struct r8192_priv *priv = ieee80211_priv(dev);
3760 struct sockaddr *addr = mac;
3761
3762 down(&priv->wx_sem);
3763
3764 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
3765
Jerry Chuang8fc85982009-11-03 07:17:11 -02003766 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003767 up(&priv->wx_sem);
3768
3769 return 0;
3770}
3771
3772/* based on ipw2200 driver */
3773int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3774{
3775 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3776 struct iwreq *wrq = (struct iwreq *)rq;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003777 int ret = -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003778 struct ieee80211_device *ieee = priv->ieee80211;
3779 u32 key[4];
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003780 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003781 struct iw_point *p = &wrq->u.data;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03003782 struct ieee_param *ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003783
3784 down(&priv->wx_sem);
3785
3786
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003787 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
3788 ret = -EINVAL;
3789 goto out;
3790 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003791
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003792 ipw = kmalloc(p->length, GFP_KERNEL);
3793 if (ipw == NULL) {
3794 ret = -ENOMEM;
3795 goto out;
3796 }
3797 if (copy_from_user(ipw, p->pointer, p->length)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003798 kfree(ipw);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003799 ret = -EFAULT;
3800 goto out;
3801 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003802
3803 switch (cmd) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003804 case RTL_IOCTL_WPA_SUPPLICANT:
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003805 //parse here for HW security
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003806 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) {
3807 if (ipw->u.crypt.set_tx) {
3808 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003809 ieee->pairwise_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003810 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003811 ieee->pairwise_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003812 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003813 if (ipw->u.crypt.key_len == 13)
3814 ieee->pairwise_key_type = KEY_TYPE_WEP104;
3815 else if (ipw->u.crypt.key_len == 5)
3816 ieee->pairwise_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003817 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003818 ieee->pairwise_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003819 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003820
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003821 if (ieee->pairwise_key_type) {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003822 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003823 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003824 //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!
3825 //added by WB.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003826 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 +01003827 if (ieee->auth_mode != 2)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003828 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 -02003829 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003830 } else {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003831 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003832 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003833 ieee->group_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003834 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003835 ieee->group_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003836 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003837 if (ipw->u.crypt.key_len == 13)
3838 ieee->group_key_type = KEY_TYPE_WEP104;
3839 else if (ipw->u.crypt.key_len == 5)
3840 ieee->group_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003841 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003842 ieee->group_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003843 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003844
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003845 if (ieee->group_key_type) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03003846 setKey(dev, ipw->u.crypt.idx,
3847 ipw->u.crypt.idx, //KeyIndex
3848 ieee->group_key_type, //KeyType
3849 broadcast_addr, //MacAddr
3850 0, //DefaultKey
3851 key); //KeyContent
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003852 }
3853 }
3854 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003855 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
3856 break;
3857
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003858 default:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003859 ret = -EOPNOTSUPP;
3860 break;
3861 }
3862 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003863 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003864out:
3865 up(&priv->wx_sem);
3866 return ret;
3867}
3868
3869u8 HwRateToMRate90(bool bIsHT, u8 rate)
3870{
3871 u8 ret_rate = 0xff;
3872
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003873 if (!bIsHT) {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003874 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003875 case DESC90_RATE1M: ret_rate = MGN_1M; break;
3876 case DESC90_RATE2M: ret_rate = MGN_2M; break;
3877 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
3878 case DESC90_RATE11M: ret_rate = MGN_11M; break;
3879 case DESC90_RATE6M: ret_rate = MGN_6M; break;
3880 case DESC90_RATE9M: ret_rate = MGN_9M; break;
3881 case DESC90_RATE12M: ret_rate = MGN_12M; break;
3882 case DESC90_RATE18M: ret_rate = MGN_18M; break;
3883 case DESC90_RATE24M: ret_rate = MGN_24M; break;
3884 case DESC90_RATE36M: ret_rate = MGN_36M; break;
3885 case DESC90_RATE48M: ret_rate = MGN_48M; break;
3886 case DESC90_RATE54M: ret_rate = MGN_54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003887
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003888 default:
3889 ret_rate = 0xff;
3890 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
3891 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003892 }
3893
3894 } else {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003895 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003896 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
3897 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
3898 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
3899 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
3900 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
3901 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
3902 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
3903 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
3904 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
3905 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
3906 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
3907 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
3908 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
3909 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
3910 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
3911 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
3912 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003913
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003914 default:
3915 ret_rate = 0xff;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003916 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003917 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003918 }
3919 }
3920
3921 return ret_rate;
3922}
3923
3924/**
3925 * Function: UpdateRxPktTimeStamp
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003926 * Overview: Record the TSF time stamp when receiving a packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02003927 *
3928 * Input:
3929 * PADAPTER Adapter
3930 * PRT_RFD pRfd,
3931 *
3932 * Output:
3933 * PRT_RFD pRfd
3934 * (pRfd->Status.TimeStampHigh is updated)
3935 * (pRfd->Status.TimeStampLow is updated)
3936 * Return:
3937 * None
3938 */
Teodora Baluta46326d22013-10-16 01:59:17 +03003939static void UpdateRxPktTimeStamp8190(struct net_device *dev,
3940 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003941{
3942 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3943
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003944 if (stats->bIsAMPDU && !stats->bFirstMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003945 stats->mac_time[0] = priv->LastRxDescTSFLow;
3946 stats->mac_time[1] = priv->LastRxDescTSFHigh;
3947 } else {
3948 priv->LastRxDescTSFLow = stats->mac_time[0];
3949 priv->LastRxDescTSFHigh = stats->mac_time[1];
3950 }
3951}
3952
3953//by amy 080606
3954
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003955long rtl819x_translate_todbm(u8 signal_strength_index)// 0-100 index.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003956{
3957 long signal_power; // in dBm.
3958
3959 // Translate to dBm (x=0.5y-95).
3960 signal_power = (long)((signal_strength_index + 1) >> 1);
3961 signal_power -= 95;
3962
3963 return signal_power;
3964}
3965
3966
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003967/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
Jerry Chuang8fc85982009-11-03 07:17:11 -02003968 be a local static. Otherwise, it may increase when we return from S3/S4. The
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003969 value will be kept in memory or disk. Declare the value in the adaptor
3970 and it will be reinitialized when returned from S3/S4. */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003971void 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 -02003972{
3973 bool bcheck = false;
3974 u8 rfpath;
3975 u32 nspatial_stream, tmp_val;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003976 static u32 slide_rssi_index, slide_rssi_statistics;
3977 static u32 slide_evm_index, slide_evm_statistics;
3978 static u32 last_rssi, last_evm;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003979
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003980 static u32 slide_beacon_adc_pwdb_index, slide_beacon_adc_pwdb_statistics;
3981 static u32 last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003982
3983 struct ieee80211_hdr_3addr *hdr;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003984 u16 sc;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003985 unsigned int frag, seq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003986 hdr = (struct ieee80211_hdr_3addr *)buffer;
3987 sc = le16_to_cpu(hdr->seq_ctl);
3988 frag = WLAN_GET_SEQ_FRAG(sc);
3989 seq = WLAN_GET_SEQ_SEQ(sc);
3990 //cosa add 04292008 to record the sequence number
3991 pcurrent_stats->Seq_Num = seq;
3992 //
3993 // Check whether we should take the previous packet into accounting
3994 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003995 if (!pprevious_stats->bIsAMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003996 // if previous packet is not aggregated packet
3997 bcheck = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003998 }
3999
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004000 if (slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004001 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
4002 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
4003 priv->stats.slide_rssi_total -= last_rssi;
4004 }
4005 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
4006
4007 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004008 if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004009 slide_rssi_index = 0;
4010
4011 // <1> Showed on UI for user, in dbm
4012 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
4013 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
4014 pcurrent_stats->rssi = priv->stats.signal_strength;
4015 //
4016 // If the previous packet does not match the criteria, neglect it
4017 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004018 if (!pprevious_stats->bPacketMatchBSSID) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004019 if (!pprevious_stats->bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004020 return;
4021 }
4022
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004023 if (!bcheck)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004024 return;
4025
4026
4027 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
4028
4029 //
4030 // Check RSSI
4031 //
4032 priv->stats.num_process_phyinfo++;
4033
4034 /* record the general signal strength to the sliding window. */
4035
4036
4037 // <2> Showed on UI for engineering
4038 // hardware does not provide rssi information for each rf path in CCK
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004039 if (!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA)) {
4040 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004041 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
4042 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004043
4044 //Fixed by Jacken 2008-03-20
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004045 if (priv->stats.rx_rssi_percentage[rfpath] == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004046 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004047 if (pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath]) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004048 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004049 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004050 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004051 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004052 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004053 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004054 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004055 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004056 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004057 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 -02004058 }
4059 }
4060
4061
4062 //
4063 // Check PWDB.
4064 //
4065 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004066 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004067 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004068
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004069 if (pprevious_stats->bPacketBeacon) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004070 /* record the beacon pwdb to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004071 if (slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004072 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
4073 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
4074 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004075 }
4076 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
4077 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004078 slide_beacon_adc_pwdb_index++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004079 if (slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004080 slide_beacon_adc_pwdb_index = 0;
4081 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004082 if (pprevious_stats->RxPWDBAll >= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004083 pprevious_stats->RxPWDBAll -= 3;
4084 }
4085
4086 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004087 pprevious_stats->bIsCCK ? "CCK" : "OFDM",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004088 pprevious_stats->RxPWDBAll);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004089
4090
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004091 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004092 if (priv->undecorated_smoothed_pwdb < 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004093 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004094 if (pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004095 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004096 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4097 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004098 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004099 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004100 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004101 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
4102 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004103 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004104
4105 }
4106
4107 //
4108 // Check EVM
4109 //
4110 /* record the general EVM to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004111 if (pprevious_stats->SignalQuality) {
4112 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4113 if (slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004114 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
4115 last_evm = priv->stats.slide_evm[slide_evm_index];
4116 priv->stats.slide_evm_total -= last_evm;
4117 }
4118
4119 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
4120
4121 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004122 if (slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004123 slide_evm_index = 0;
4124
4125 // <1> Showed on UI for user, in percentage.
4126 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
4127 priv->stats.signal_quality = tmp_val;
4128 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
4129 priv->stats.last_signal_strength_inpercent = tmp_val;
4130 }
4131
4132 // <2> Showed on UI for engineering
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004133 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4134 for (nspatial_stream = 0; nspatial_stream < 2; nspatial_stream++) { // 2 spatial stream
4135 if (pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004136 if (priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004137 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
Jerry Chuang8fc85982009-11-03 07:17:11 -02004138 priv->stats.rx_evm_percentage[nspatial_stream] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004139 ((priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004140 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004141 }
4142 }
4143 }
4144 }
4145
4146
4147}
4148
4149/*-----------------------------------------------------------------------------
4150 * Function: rtl819x_query_rxpwrpercentage()
4151 *
4152 * Overview:
4153 *
4154 * Input: char antpower
4155 *
4156 * Output: NONE
4157 *
4158 * Return: 0-100 percentage
4159 *
4160 * Revised History:
4161 * When Who Remark
4162 * 05/26/2008 amy Create Version 0 porting from windows code.
4163 *
4164 *---------------------------------------------------------------------------*/
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004165static u8 rtl819x_query_rxpwrpercentage(char antpower)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004166{
4167 if ((antpower <= -100) || (antpower >= 20))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004168 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004169 else if (antpower >= 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004170 return 100;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004171 else
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004172 return 100 + antpower;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004173
4174} /* QueryRxPwrPercentage */
4175
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004176static u8 rtl819x_evm_dbtopercentage(char value)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004177{
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004178 char ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004179
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004180 ret_val = value;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004181
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004182 if (ret_val >= 0)
4183 ret_val = 0;
4184 if (ret_val <= -33)
4185 ret_val = -33;
4186 ret_val = 0 - ret_val;
4187 ret_val *= 3;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004188 if (ret_val == 99)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004189 ret_val = 100;
Xenia Ragiadakou2c7c0c32013-06-04 23:32:27 +03004190 return ret_val;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004191}
4192//
4193// Description:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004194// We want good-looking for signal strength/quality
Jerry Chuang8fc85982009-11-03 07:17:11 -02004195// 2007/7/19 01:09, by cosa.
4196//
Teodora Baluta46326d22013-10-16 01:59:17 +03004197static long rtl819x_signal_scale_mapping(long currsig)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004198{
4199 long retsig;
4200
4201 // Step 1. Scale mapping.
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004202 if (currsig >= 61 && currsig <= 100)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004203 retsig = 90 + ((currsig - 60) / 4);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004204 else if (currsig >= 41 && currsig <= 60)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004205 retsig = 78 + ((currsig - 40) / 2);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004206 else if (currsig >= 31 && currsig <= 40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004207 retsig = 66 + (currsig - 30);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004208 else if (currsig >= 21 && currsig <= 30)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004209 retsig = 54 + (currsig - 20);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004210 else if (currsig >= 5 && currsig <= 20)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004211 retsig = 42 + (((currsig - 5) * 2) / 3);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004212 else if (currsig == 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004213 retsig = 36;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004214 else if (currsig == 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004215 retsig = 27;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004216 else if (currsig == 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004217 retsig = 18;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004218 else if (currsig == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004219 retsig = 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004220 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004221 retsig = currsig;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004222
4223 return retsig;
4224}
4225
Xenia Ragiadakouf2c3d802013-06-04 23:32:32 +03004226static inline bool rx_hal_is_cck_rate(struct rx_drvinfo_819x_usb *pdrvinfo)
4227{
4228 if (pdrvinfo->RxHT)
4229 return false;
4230
4231 switch (pdrvinfo->RxRate) {
4232 case DESC90_RATE1M:
4233 case DESC90_RATE2M:
4234 case DESC90_RATE5_5M:
4235 case DESC90_RATE11M:
4236 return true;
4237 default:
4238 return false;
4239 }
4240}
4241
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004242static void rtl8192_query_rxphystatus(struct r8192_priv *priv,
4243 struct ieee80211_rx_stats *pstats,
4244 rx_drvinfo_819x_usb *pdrvinfo,
4245 struct ieee80211_rx_stats *precord_stats,
4246 bool bpacket_match_bssid,
4247 bool bpacket_toself,
4248 bool bPacketBeacon,
4249 bool bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004250{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004251 phy_sts_ofdm_819xusb_t *pofdm_buf;
4252 phy_sts_cck_819xusb_t *pcck_buf;
4253 phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004254 u8 *prxpkt;
4255 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004256 char rx_pwr[4], rx_pwr_all = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004257 char rx_snrX, rx_evmX;
4258 u8 evm, pwdb_all;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004259 u32 RSSI, total_rssi = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004260 u8 is_cck_rate = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004261 u8 rf_rx_num = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004262 u8 sq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004263
4264
4265 priv->stats.numqry_phystatus++;
4266
4267 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4268
4269 // Record it for next packet processing
4270 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4271 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4272 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004273 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004274 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4275 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4276
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004277 prxpkt = (u8 *)pdrvinfo;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004278
4279 /* Move pointer to the 16th bytes. Phy status start address. */
4280 prxpkt += sizeof(rx_drvinfo_819x_usb);
4281
4282 /* Initial the cck and ofdm buffer pointer */
4283 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
4284 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
4285
4286 pstats->RxMIMOSignalQuality[0] = -1;
4287 pstats->RxMIMOSignalQuality[1] = -1;
4288 precord_stats->RxMIMOSignalQuality[0] = -1;
4289 precord_stats->RxMIMOSignalQuality[1] = -1;
4290
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004291 if (is_cck_rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004292 //
4293 // (1)Hardware does not provide RSSI for CCK
4294 //
4295
4296 //
4297 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4298 //
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004299 u8 report;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004300
4301 priv->stats.numqry_phystatusCCK++;
4302
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004303 if (!priv->bCckHighPower) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004304 report = pcck_buf->cck_agc_rpt & 0xc0;
4305 report = report>>6;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004306 switch (report) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004307 //Fixed by Jacken from Bryant 2008-03-20
4308 //Original value is -38 , -26 , -14 , -2
4309 //Fixed value is -35 , -23 , -11 , 6
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004310 case 0x3:
4311 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4312 break;
4313 case 0x2:
4314 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4315 break;
4316 case 0x1:
4317 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4318 break;
4319 case 0x0:
4320 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
4321 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004322 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004323 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004324 report = pcck_buf->cck_agc_rpt & 0x60;
4325 report = report>>5;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004326 switch (report) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004327 case 0x3:
4328 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4329 break;
4330 case 0x2:
4331 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4332 break;
4333 case 0x1:
4334 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4335 break;
4336 case 0x0:
4337 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4338 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004339 }
4340 }
4341
4342 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4343 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4344 pstats->RecvSignalPower = pwdb_all;
4345
4346 //
4347 // (3) Get Signal Quality (EVM)
4348 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02004349
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004350 if (pstats->RxPWDBAll > 40) {
4351 sq = 100;
4352 } else {
4353 sq = pcck_buf->sq_rpt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004354
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004355 if (pcck_buf->sq_rpt > 64)
4356 sq = 0;
4357 else if (pcck_buf->sq_rpt < 20)
4358 sq = 100;
4359 else
4360 sq = ((64-sq) * 100) / 44;
4361 }
4362 pstats->SignalQuality = precord_stats->SignalQuality = sq;
4363 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
4364 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004365
4366 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004367 priv->stats.numqry_phystatusHT++;
4368 //
4369 // (1)Get RSSI for HT rate
4370 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004371 for (i = RF90_PATH_A; i < priv->NumTotalRFPath; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004372 // 2008/01/30 MH we will judge RF RX path now.
4373 if (priv->brfpath_rxenable[i])
4374 rf_rx_num++;
4375 else
4376 continue;
4377
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004378 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004379 continue;
4380
4381 //Fixed by Jacken from Bryant 2008-03-20
4382 //Original value is 106
4383 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
4384
4385 //Get Rx snr value in DB
4386 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
4387 rx_snrX = (char)(tmp_rxsnr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004388 rx_snrX /= 2;
4389 priv->stats.rxSNRdB[i] = (long)rx_snrX;
4390
4391 /* Translate DBM to percentage. */
4392 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
4393 total_rssi += RSSI;
4394
4395 /* Record Signal Strength for next packet */
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004396 pstats->RxMIMOSignalStrength[i] = (u8) RSSI;
4397 precord_stats->RxMIMOSignalStrength[i] = (u8) RSSI;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004398 }
4399
4400
4401 //
4402 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4403 //
4404 //Fixed by Jacken from Bryant 2008-03-20
4405 //Original value is 106
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004406 rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1)& 0x7f) -106;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004407 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4408
4409 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4410 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
4411
4412 //
4413 // (3)EVM of HT rate
4414 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004415 if (pdrvinfo->RxHT && pdrvinfo->RxRate >= DESC90_RATEMCS8 &&
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004416 pdrvinfo->RxRate <= DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004417 max_spatial_stream = 2; //both spatial stream make sense
4418 else
4419 max_spatial_stream = 1; //only spatial stream 1 makes sense
4420
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004421 for (i = 0; i < max_spatial_stream; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004422 tmp_rxevm = pofdm_buf->rxevm_X[i];
4423 rx_evmX = (char)(tmp_rxevm);
4424
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004425 // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004426 // will set the most significant bit to "zero" when doing shifting operation which may change a negative
Jerry Chuang8fc85982009-11-03 07:17:11 -02004427 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
4428 rx_evmX /= 2; //dbm
4429
4430 evm = rtl819x_evm_dbtopercentage(rx_evmX);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004431 if (i == 0) // Fill value in RFD, Get the first spatial stream only
4432 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
4433 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004434 }
4435
4436
4437 /* record rx statistics for debug */
4438 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
4439 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004440 if (pdrvinfo->BW) //40M channel
Jerry Chuang8fc85982009-11-03 07:17:11 -02004441 priv->stats.received_bwtype[1+prxsc->rxsc]++;
4442 else //20M channel
4443 priv->stats.received_bwtype[0]++;
4444 }
4445
4446 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
4447 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004448 if (is_cck_rate) {
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004449 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004450 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004451 // We can judge RX path number now.
4452 if (rf_rx_num != 0)
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004453 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi /= rf_rx_num)));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004454 }
4455} /* QueryRxPhyStatus8190Pci */
4456
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004457void rtl8192_record_rxdesc_forlateruse(struct ieee80211_rx_stats *psrc_stats,
4458 struct ieee80211_rx_stats *ptarget_stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004459{
4460 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
4461 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
4462 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
4463}
4464
4465
Teodora Baluta46326d22013-10-16 01:59:17 +03004466static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
4467 struct ieee80211_rx_stats *pstats,
4468 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004469{
4470 // TODO: We must only check packet for current MAC address. Not finish
4471 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004472 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004473 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4474 bool bpacket_match_bssid, bpacket_toself;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004475 bool bPacketBeacon = FALSE, bToSelfBA = FALSE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004476 static struct ieee80211_rx_stats previous_stats;
4477 struct ieee80211_hdr_3addr *hdr;//by amy
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004478 u16 fc, type;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004479
4480 // Get Signal Quality for only RX data queue (but not command queue)
4481
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004482 u8 *tmp_buf;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004483 u8 *praddr;
4484
4485 /* Get MAC frame start address. */
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004486 tmp_buf = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004487
4488 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
4489 fc = le16_to_cpu(hdr->frame_ctl);
4490 type = WLAN_FC_GET_TYPE(fc);
4491 praddr = hdr->addr1;
4492
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004493 /* Check if the received packet is acceptable. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004494 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Xenia Ragiadakou15f6d3a2013-06-04 23:32:28 +03004495 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
4496 && (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004497 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
4498
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004499 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON)
4500 bPacketBeacon = true;
4501 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK) {
4502 if ((eqMacAddr(praddr, dev->dev_addr)))
4503 bToSelfBA = true;
4504 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004505
Jerry Chuang8fc85982009-11-03 07:17:11 -02004506
4507
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004508 if (bpacket_match_bssid)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004509 priv->stats.numpacket_matchbssid++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004510 if (bpacket_toself)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004511 priv->stats.numpacket_toself++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004512 //
4513 // Process PHY information for previous packet (RSSI/PWDB/EVM)
4514 //
4515 // Because phy information is contained in the last packet of AMPDU only, so driver
4516 // should process phy information of previous packet
4517 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004518 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid, bpacket_toself, bPacketBeacon, bToSelfBA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004519 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
4520
4521}
4522
4523/**
4524* Function: UpdateReceivedRateHistogramStatistics
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004525* Overview: Record the received data rate
Jerry Chuang8fc85982009-11-03 07:17:11 -02004526*
4527* Input:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004528* struct net_device *dev
Jerry Chuang8fc85982009-11-03 07:17:11 -02004529* struct ieee80211_rx_stats *stats
4530*
4531* Output:
4532*
4533* (priv->stats.ReceivedRateHistogram[] is updated)
4534* Return:
4535* None
4536*/
Teodora Baluta46326d22013-10-16 01:59:17 +03004537static void
4538UpdateReceivedRateHistogramStatistics8190(struct net_device *dev,
4539 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004540{
4541 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004542 u32 rcvType = 1; //0: Total, 1:OK, 2:CRC, 3:ICV
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004543 u32 rateIndex;
4544 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02004545
4546
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004547 if (stats->bCRC)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004548 rcvType = 2;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004549 else if (stats->bICV)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004550 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004551
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004552 if (stats->bShortPreamble)
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004553 preamble_guardinterval = 1;// short
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004554 else
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004555 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02004556
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004557 switch (stats->rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004558 //
4559 // CCK rate
4560 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004561 case MGN_1M: rateIndex = 0; break;
4562 case MGN_2M: rateIndex = 1; break;
4563 case MGN_5_5M: rateIndex = 2; break;
4564 case MGN_11M: rateIndex = 3; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004565 //
4566 // Legacy OFDM rate
4567 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004568 case MGN_6M: rateIndex = 4; break;
4569 case MGN_9M: rateIndex = 5; break;
4570 case MGN_12M: rateIndex = 6; break;
4571 case MGN_18M: rateIndex = 7; break;
4572 case MGN_24M: rateIndex = 8; break;
4573 case MGN_36M: rateIndex = 9; break;
4574 case MGN_48M: rateIndex = 10; break;
4575 case MGN_54M: rateIndex = 11; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004576 //
4577 // 11n High throughput rate
4578 //
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004579 case MGN_MCS0: rateIndex = 12; break;
4580 case MGN_MCS1: rateIndex = 13; break;
4581 case MGN_MCS2: rateIndex = 14; break;
4582 case MGN_MCS3: rateIndex = 15; break;
4583 case MGN_MCS4: rateIndex = 16; break;
4584 case MGN_MCS5: rateIndex = 17; break;
4585 case MGN_MCS6: rateIndex = 18; break;
4586 case MGN_MCS7: rateIndex = 19; break;
4587 case MGN_MCS8: rateIndex = 20; break;
4588 case MGN_MCS9: rateIndex = 21; break;
4589 case MGN_MCS10: rateIndex = 22; break;
4590 case MGN_MCS11: rateIndex = 23; break;
4591 case MGN_MCS12: rateIndex = 24; break;
4592 case MGN_MCS13: rateIndex = 25; break;
4593 case MGN_MCS14: rateIndex = 26; break;
4594 case MGN_MCS15: rateIndex = 27; break;
4595 default: rateIndex = 28; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004596 }
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004597 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
4598 priv->stats.received_rate_histogram[0][rateIndex]++; //total
4599 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004600}
4601
4602
Teodora Baluta46326d22013-10-16 01:59:17 +03004603static void query_rxdesc_status(struct sk_buff *skb,
4604 struct ieee80211_rx_stats *stats,
4605 bool bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004606{
4607 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004608 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004609 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004610 rx_drvinfo_819x_usb *driver_info = NULL;
4611
4612 //
4613 //Get Rx Descriptor Information
4614 //
4615#ifdef USB_RX_AGGREGATION_SUPPORT
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004616 if (bIsRxAggrSubframe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004617 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004618 stats->Length = desc->Length;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004619 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
4620 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
4621 stats->bICV = desc->ICV;
4622 stats->bCRC = desc->CRC32;
4623 stats->bHwError = stats->bCRC|stats->bICV;
4624 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
4625 } else
4626#endif
4627 {
4628 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
4629
4630 stats->Length = desc->Length;
4631 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004632 stats->RxBufShift = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004633 stats->bICV = desc->ICV;
4634 stats->bCRC = desc->CRC32;
4635 stats->bHwError = stats->bCRC|stats->bICV;
4636 //RTL8190 set this bit to indicate that Hw does not decrypt packet
4637 stats->Decrypted = !desc->SWDec;
4638 }
4639
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004640 if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004641 stats->bHwError = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004642 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004643 stats->bHwError = stats->bCRC|stats->bICV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004644
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004645 if (stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004646 stats->bHwError |= 1;
4647 //
4648 //Get Driver Info
4649 //
4650 // TODO: Need to verify it on FGPA platform
4651 //Driver info are written to the RxBuffer following rx desc
4652 if (stats->RxDrvInfoSize != 0) {
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004653 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) +
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004654 stats->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004655 /* unit: 0.5M */
4656 /* TODO */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004657 if (!stats->bHwError) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004658 u8 ret_rate;
4659 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004660 if (ret_rate == 0xff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004661 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
4662 // Special Error Handling here, 2008.05.16, by Emily
4663
4664 stats->bHwError = 1;
4665 stats->rate = MGN_1M; //Set 1M rate by default
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004666 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004667 stats->rate = ret_rate;
4668 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004669 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004670 stats->rate = 0x02;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004671 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004672
4673 stats->bShortPreamble = driver_info->SPLCP;
4674
4675
4676 UpdateReceivedRateHistogramStatistics8190(dev, stats);
4677
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004678 stats->bIsAMPDU = (driver_info->PartAggr == 1);
4679 stats->bFirstMPDU = (driver_info->PartAggr == 1) && (driver_info->FirstAGGR == 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004680 stats->TimeStampLow = driver_info->TSFL;
4681 // xiong mask it, 070514
Jerry Chuang8fc85982009-11-03 07:17:11 -02004682
4683 UpdateRxPktTimeStamp8190(dev, stats);
4684
4685 //
4686 // Rx A-MPDU
4687 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004688 if (driver_info->FirstAGGR == 1 || driver_info->PartAggr == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004689 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004690 driver_info->FirstAGGR, driver_info->PartAggr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004691
4692 }
4693
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004694 skb_pull(skb, sizeof(rx_desc_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004695 //
4696 // Get Total offset of MPDU Frame Body
4697 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004698 if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004699 stats->bShift = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004700 skb_pull(skb, stats->RxBufShift + stats->RxDrvInfoSize);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004701 }
4702
4703#ifdef USB_RX_AGGREGATION_SUPPORT
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004704 /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004705 if (bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004706 skb_pull(skb, 8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004707#endif
4708 /* for debug 2008.5.29 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004709
4710 //added by vivi, for MP, 20080108
4711 stats->RxIs40MHzPacket = driver_info->BW;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004712 if (stats->RxDrvInfoSize != 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004713 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
4714
4715}
4716
4717u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
4718{
4719#ifdef USB_RX_AGGREGATION_SUPPORT
4720 if (bIsRxAggrSubframe)
4721 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
4722 + Status->RxBufShift + 8);
4723 else
4724#endif
4725 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004726 + Status->RxBufShift);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004727}
4728
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004729void rtl8192_rx_nomal(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004730{
4731 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004732 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004733 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4734 struct ieee80211_rx_stats stats = {
4735 .signal = 0,
4736 .noise = -98,
4737 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004738 .freq = IEEE80211_24GHZ_BAND,
4739 };
4740 u32 rx_pkt_len = 0;
4741 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
4742 bool unicast_packet = false;
4743#ifdef USB_RX_AGGREGATION_SUPPORT
4744 struct sk_buff *agg_skb = NULL;
4745 u32 TotalLength = 0;
4746 u32 TempDWord = 0;
4747 u32 PacketLength = 0;
4748 u32 PacketOccupiedLendth = 0;
4749 u8 TempByte = 0;
4750 u32 PacketShiftBytes = 0;
4751 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
4752 u8 PaddingBytes = 0;
4753 //add just for testing
4754 u8 testing;
4755
4756#endif
4757
4758 /* 20 is for ps-poll */
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004759 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004760#ifdef USB_RX_AGGREGATION_SUPPORT
4761 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
4762#endif
4763 /* first packet should not contain Rx aggregation header */
4764 query_rxdesc_status(skb, &stats, false);
4765 /* TODO */
4766 /* hardware related info */
4767#ifdef USB_RX_AGGREGATION_SUPPORT
4768 if (TempByte & BIT0) {
4769 agg_skb = skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004770 TotalLength = stats.Length - 4; /*sCrcLng*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02004771 /* though the head pointer has passed this position */
4772 TempDWord = *(u32 *)(agg_skb->data - 4);
4773 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
4774 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004775 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004776 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
4777 }
4778#endif
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004779 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004780 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4781
4782 rx_pkt_len = skb->len;
4783 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4784 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004785 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004786 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004787 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004788 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004789 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004790 /* unicast packet */
4791 unicast_packet = true;
4792 }
4793
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004794 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004795 dev_kfree_skb_any(skb);
4796 } else {
4797 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004798 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004799 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004800 }
4801#ifdef USB_RX_AGGREGATION_SUPPORT
4802 testing = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004803 if (TotalLength > 0) {
4804 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
4805 if ((PacketOccupiedLendth & 0xFF) != 0)
4806 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
4807 PacketOccupiedLendth -= 8;
4808 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
4809 if (agg_skb->len > TempDWord)
4810 skb_pull(agg_skb, TempDWord);
4811 else
4812 agg_skb->len = 0;
4813
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004814 while (agg_skb->len >= GetRxPacketShiftBytes819xUsb(&stats, true)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004815 u8 tmpCRC = 0, tmpICV = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004816 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
4817 tmpCRC = RxDescr->CRC32;
4818 tmpICV = RxDescr->ICV;
4819 memcpy(agg_skb->data, &agg_skb->data[44], 2);
4820 RxDescr->CRC32 = tmpCRC;
4821 RxDescr->ICV = tmpICV;
4822
4823 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
4824 stats.signal = 0;
4825 stats.noise = -98;
4826 stats.rate = 0;
4827 stats.freq = IEEE80211_24GHZ_BAND;
4828 query_rxdesc_status(agg_skb, &stats, true);
4829 PacketLength = stats.Length;
4830
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004831 if (PacketLength > agg_skb->len)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004832 break;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004833 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004834 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004835 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004836 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4837
4838 rx_pkt_len = skb->len;
4839 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4840 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004841 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004842 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004843 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004844 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004845 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004846 /* unicast packet */
4847 unicast_packet = true;
4848 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004849 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004850 dev_kfree_skb_any(skb);
4851 } else {
4852 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004853 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004854 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004855 }
4856 /* should trim the packet which has been copied to target skb */
4857 skb_pull(agg_skb, PacketLength);
4858 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
4859 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
4860 if ((PacketOccupiedLendth & 0xFF) != 0) {
4861 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
4862 if (agg_skb->len > PaddingBytes)
4863 skb_pull(agg_skb, PaddingBytes);
4864 else
4865 agg_skb->len = 0;
4866 }
4867 }
4868 dev_kfree_skb(agg_skb);
4869 }
4870#endif
4871 } else {
4872 priv->stats.rxurberr++;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03004873 netdev_dbg(dev, "actual_length: %d\n", skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004874 dev_kfree_skb_any(skb);
4875 }
4876
4877}
4878
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03004879void rtl819xusb_process_received_packet(struct net_device *dev,
4880 struct ieee80211_rx_stats *pstats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004881{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004882 u8 *frame;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004883 u16 frame_len = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004884 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004885
4886 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
4887 //porting by amy 080508
4888 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
4889 frame = pstats->virtual_address;
4890 frame_len = pstats->packetlength;
4891#ifdef TODO // by amy about HCT
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004892 if (!Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004893 CountRxErrStatistics(Adapter, pRfd);
4894#endif
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004895#ifdef ENABLE_PS //by amy for adding ps function in future
4896 RT_RF_POWER_STATE rtState;
4897 // When RF is off, we should not count the packet for hw/sw synchronize
4898 // reason, ie. there may be a duration while sw switch is changed and hw
4899 // switch is being changed. 2006.12.04, by shien chang.
4900 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8 *)(&rtState));
4901 if (rtState == eRfOff)
4902 return;
4903#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -02004904 priv->stats.rxframgment++;
4905
Jerry Chuang8fc85982009-11-03 07:17:11 -02004906#ifdef TODO
4907 RmMonitorSignalStrength(Adapter, pRfd);
4908#endif
4909 /* 2007/01/16 MH Add RX command packet handle here. */
4910 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
4911 if (rtl819xusb_rx_command_packet(dev, pstats))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004912 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004913
4914#ifdef SW_CRC_CHECK
4915 SwCrcCheck();
4916#endif
4917
4918
4919}
4920
Teodora Baluta46326d22013-10-16 01:59:17 +03004921static void query_rx_cmdpkt_desc_status(struct sk_buff *skb,
4922 struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004923{
Jerry Chuang8fc85982009-11-03 07:17:11 -02004924 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004925
4926 //
4927 //Get Rx Descriptor Information
4928 //
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004929 stats->virtual_address = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004930 stats->Length = desc->Length;
4931 stats->RxDrvInfoSize = 0;
4932 stats->RxBufShift = 0;
4933 stats->packetlength = stats->Length-scrclng;
4934 stats->fraglength = stats->packetlength;
4935 stats->fragoffset = 0;
4936 stats->ntotalfrag = 1;
4937}
4938
4939
4940void rtl8192_rx_cmd(struct sk_buff *skb)
4941{
4942 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
4943 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004944 /* TODO */
4945 struct ieee80211_rx_stats stats = {
4946 .signal = 0,
4947 .noise = -98,
4948 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004949 .freq = IEEE80211_24GHZ_BAND,
4950 };
4951
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004952 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004953
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004954 query_rx_cmdpkt_desc_status(skb, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004955 // this is to be done by amy 080508 prfd->queue_id = 1;
4956
4957
4958 //
4959 // Process the command packet received.
4960 //
4961
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004962 rtl819xusb_process_received_packet(dev, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004963
4964 dev_kfree_skb_any(skb);
4965 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004966}
4967
4968void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
4969{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004970 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004971 struct rtl8192_rx_info *info;
4972
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004973 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004974 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004975 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004976 /* Nomal packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004977 case 3:
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004978 priv->IrpPendingCount--;
4979 rtl8192_rx_nomal(skb);
4980 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004981
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004982 /* Command packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004983 case 9:
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004984 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004985 info->out_pipe);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004986
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004987 rtl8192_rx_cmd(skb);
4988 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004989
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004990 default: /* should never get here! */
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03004991 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03004992 info->out_pipe);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01004993 dev_kfree_skb(skb);
4994 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004995
4996 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004997 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004998}
4999
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005000static const struct net_device_ops rtl8192_netdev_ops = {
5001 .ndo_open = rtl8192_open,
5002 .ndo_stop = rtl8192_close,
5003 .ndo_get_stats = rtl8192_stats,
5004 .ndo_tx_timeout = tx_timeout,
5005 .ndo_do_ioctl = rtl8192_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00005006 .ndo_set_rx_mode = r8192_set_multicast,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005007 .ndo_set_mac_address = r8192_set_mac_adr,
5008 .ndo_validate_addr = eth_validate_addr,
5009 .ndo_change_mtu = eth_change_mtu,
5010 .ndo_start_xmit = ieee80211_xmit,
5011};
Jerry Chuang8fc85982009-11-03 07:17:11 -02005012
5013
5014/****************************************************************************
5015 ---------------------------- USB_STUFF---------------------------
5016*****************************************************************************/
5017
Bill Pemberton25794522012-11-19 13:22:04 -05005018static int rtl8192_usb_probe(struct usb_interface *intf,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005019 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005020{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005021 struct net_device *dev = NULL;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005022 struct r8192_priv *priv = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005023 struct usb_device *udev = interface_to_usbdev(intf);
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005024 int ret;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005025 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005026
5027 dev = alloc_ieee80211(sizeof(struct r8192_priv));
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005028 if (dev == NULL)
5029 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005030
Jerry Chuang8fc85982009-11-03 07:17:11 -02005031 usb_set_intfdata(intf, dev);
5032 SET_NETDEV_DEV(dev, &intf->dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005033 priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005034 priv->ieee80211 = netdev_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005035 priv->udev = udev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005036
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005037 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005038
Jerry Chuang8fc85982009-11-03 07:17:11 -02005039#if WIRELESS_EXT >= 12
5040#if WIRELESS_EXT < 17
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005041 dev->get_wireless_stats = r8192_get_wireless_stats;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005042#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005043 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005044#endif
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005045 dev->type = ARPHRD_ETHER;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005046
5047 dev->watchdog_timeo = HZ*3; //modified by john, 0805
5048
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005049 if (dev_alloc_name(dev, ifname) < 0) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005050 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005051 ifname = "wlan%d";
5052 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005053 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005054
5055 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005056 if (rtl8192_init(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005057 RT_TRACE(COMP_ERR, "Initialization failed");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005058 ret = -ENODEV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005059 goto fail;
5060 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005061 netif_carrier_off(dev);
5062 netif_stop_queue(dev);
5063
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005064 ret = register_netdev(dev);
5065 if (ret)
5066 goto fail2;
5067
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005068 RT_TRACE(COMP_INIT, "dev name=======> %s\n", dev->name);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005069 rtl8192_proc_init_one(dev);
5070
5071
5072 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005073 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005074
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005075fail2:
5076 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005077 kfree(priv->pFirmware);
5078 priv->pFirmware = NULL;
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005079 rtl8192_usb_deleteendpoints(dev);
5080 destroy_workqueue(priv->priv_wq);
5081 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005082fail:
5083 free_ieee80211(dev);
5084
5085 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005086 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005087}
5088
5089//detach all the work and timer structure declared or inititialize in r8192U_init function.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005090void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005091{
5092
Jerry Chuang8fc85982009-11-03 07:17:11 -02005093 cancel_work_sync(&priv->reset_wq);
5094 cancel_delayed_work(&priv->watch_dog_wq);
5095 cancel_delayed_work(&priv->update_beacon_wq);
5096 cancel_work_sync(&priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005097}
5098
5099
Bill Pembertona4a557e2012-11-19 13:26:46 -05005100static void rtl8192_usb_disconnect(struct usb_interface *intf)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005101{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005102 struct net_device *dev = usb_get_intfdata(intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005103
5104 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005105 if (dev) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005106
5107 unregister_netdev(dev);
5108
5109 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
5110 rtl8192_proc_remove_one(dev);
5111
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005112 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005113 kfree(priv->pFirmware);
5114 priv->pFirmware = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005115 rtl8192_usb_deleteendpoints(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005116 destroy_workqueue(priv->priv_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005117 mdelay(10);
5118
5119 }
5120 free_ieee80211(dev);
5121 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
5122}
5123
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005124/* fun with the built-in ieee80211 stack... */
5125extern int ieee80211_debug_init(void);
5126extern void ieee80211_debug_exit(void);
5127extern int ieee80211_crypto_init(void);
5128extern void ieee80211_crypto_deinit(void);
5129extern int ieee80211_crypto_tkip_init(void);
5130extern void ieee80211_crypto_tkip_exit(void);
5131extern int ieee80211_crypto_ccmp_init(void);
5132extern void ieee80211_crypto_ccmp_exit(void);
5133extern int ieee80211_crypto_wep_init(void);
5134extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005135
5136static int __init rtl8192_usb_module_init(void)
5137{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005138 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005139
5140#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005141 ret = ieee80211_debug_init();
5142 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005143 pr_err("ieee80211_debug_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005144 return ret;
5145 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005146#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005147 ret = ieee80211_crypto_init();
5148 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005149 pr_err("ieee80211_crypto_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005150 return ret;
5151 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005152
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005153 ret = ieee80211_crypto_tkip_init();
5154 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005155 pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005156 return ret;
5157 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005158
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005159 ret = ieee80211_crypto_ccmp_init();
5160 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005161 pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005162 return ret;
5163 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005164
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005165 ret = ieee80211_crypto_wep_init();
5166 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005167 pr_err("ieee80211_crypto_wep_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005168 return ret;
5169 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005170
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005171 pr_info("\nLinux kernel driver for RTL8192 based WLAN cards\n");
5172 pr_info("Copyright (c) 2007-2008, Realsil Wlan\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005173 RT_TRACE(COMP_INIT, "Initializing module");
5174 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
5175 rtl8192_proc_module_init();
5176 return usb_register(&rtl8192_usb_driver);
5177}
5178
5179
5180static void __exit rtl8192_usb_module_exit(void)
5181{
5182 usb_deregister(&rtl8192_usb_driver);
5183
5184 RT_TRACE(COMP_DOWN, "Exiting");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005185}
5186
5187
5188void rtl8192_try_wake_queue(struct net_device *dev, int pri)
5189{
5190 unsigned long flags;
5191 short enough_desc;
5192 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5193
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005194 spin_lock_irqsave(&priv->tx_lock, flags);
5195 enough_desc = check_nic_enough_desc(dev, pri);
5196 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005197
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005198 if (enough_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005199 ieee80211_wake_queue(priv->ieee80211);
5200}
5201
5202void EnableHWSecurityConfig8192(struct net_device *dev)
5203{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005204 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005205 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005206 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005207 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005208 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 -02005209 SECR_value |= SCR_RxUseDK;
5210 SECR_value |= SCR_TxUseDK;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005211 } 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 -02005212 SECR_value |= SCR_RxUseDK;
5213 SECR_value |= SCR_TxUseDK;
5214 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005215 //add HWSec active enable here.
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005216 //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 -02005217
5218 ieee->hwsec_active = 1;
5219
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005220 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 -02005221 ieee->hwsec_active = 0;
5222 SECR_value &= ~SCR_RxDecEnable;
5223 }
Xenia Ragiadakouf0a60a142013-06-03 23:58:47 +03005224 RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __func__,
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005225 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
5226 write_nic_byte(dev, SECR, SECR_value);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005227}
5228
5229
Xenia Ragiadakou70bdf8a2013-06-03 23:58:46 +03005230void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
5231 u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005232{
5233 u32 TargetCommand = 0;
5234 u32 TargetContent = 0;
5235 u16 usConfig = 0;
5236 u8 i;
5237 if (EntryNo >= TOTAL_CAM_ENTRY)
5238 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
5239
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005240 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 -02005241
5242 if (DefaultKey)
5243 usConfig |= BIT15 | (KeyType<<2);
5244 else
5245 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005246
5247
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005248 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005249 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
5250 TargetCommand |= BIT31|BIT16;
5251
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005252 if (i == 0) { //MAC|Config
Jerry Chuang8fc85982009-11-03 07:17:11 -02005253 TargetContent = (u32)(*(MacAddr+0)) << 16|
5254 (u32)(*(MacAddr+1)) << 24|
5255 (u32)usConfig;
5256
5257 write_nic_dword(dev, WCAMI, TargetContent);
5258 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005259 } else if (i == 1) { //MAC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005260 TargetContent = (u32)(*(MacAddr+2)) |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005261 (u32)(*(MacAddr+3)) << 8|
5262 (u32)(*(MacAddr+4)) << 16|
5263 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005264 write_nic_dword(dev, WCAMI, TargetContent);
5265 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005266 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005267 //Key Material
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005268 if (KeyContent != NULL) {
Xenia Ragiadakou8f896d62013-06-03 23:58:48 +03005269 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)));
5270 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005271 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005272 }
5273 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005274
5275}
5276
5277/***************************************************************************
5278 ------------------- module init / exit stubs ----------------
5279****************************************************************************/
5280module_init(rtl8192_usb_module_init);
5281module_exit(rtl8192_usb_module_exit);