blob: 265a2840ec36bf4568e3bedeff510bd5d17ad485 [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:
6 * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
7 * 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
106u32 rt_global_debug_component = \
Jerry Chuang8fc85982009-11-03 07:17:11 -0200107 COMP_DOWN |
Jerry Chuang8fc85982009-11-03 07:17:11 -0200108 COMP_SEC |
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300109 COMP_ERR; //always open err flags on
Jerry Chuang8fc85982009-11-03 07:17:11 -0200110
111#define TOTAL_CAM_ENTRY 32
112#define CAM_CONTENT_COUNT 8
113
Németh Mártona4577322010-01-10 00:18:34 +0100114static const struct usb_device_id rtl8192_usb_id_tbl[] = {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200115 /* Realtek */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200116 {USB_DEVICE(0x0bda, 0x8709)},
117 /* Corega */
118 {USB_DEVICE(0x07aa, 0x0043)},
119 /* Belkin */
120 {USB_DEVICE(0x050d, 0x805E)},
121 /* Sitecom */
122 {USB_DEVICE(0x0df6, 0x0031)},
123 /* EnGenius */
124 {USB_DEVICE(0x1740, 0x9201)},
125 /* Dlink */
126 {USB_DEVICE(0x2001, 0x3301)},
127 /* Zinwell */
128 {USB_DEVICE(0x5a57, 0x0290)},
Ben Hutchingse10ac152010-06-25 01:35:49 +0100129 /* LG */
130 {USB_DEVICE(0x043e, 0x7a01)},
Jerry Chuang8fc85982009-11-03 07:17:11 -0200131 {}
132};
133
134MODULE_LICENSE("GPL");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200135MODULE_VERSION("V 1.1");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200136MODULE_DEVICE_TABLE(usb, rtl8192_usb_id_tbl);
137MODULE_DESCRIPTION("Linux driver for Realtek RTL8192 USB WiFi cards");
138
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300139static char *ifname = "wlan%d";
Jerry Chuang8fc85982009-11-03 07:17:11 -0200140static int hwwep = 1; //default use hw. set 0 to use software security
141static int channels = 0x3fff;
142
143
144
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300145module_param(ifname, charp, S_IRUGO|S_IWUSR);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300146module_param(hwwep, int, S_IRUGO|S_IWUSR);
147module_param(channels, int, S_IRUGO|S_IWUSR);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200148
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300149MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default");
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300150MODULE_PARM_DESC(hwwep, " Try to use hardware security support. ");
151MODULE_PARM_DESC(channels, " Channel bitmask for specific locales. NYI");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200152
Bill Pemberton25794522012-11-19 13:22:04 -0500153static int rtl8192_usb_probe(struct usb_interface *intf,
Jerry Chuang8fc85982009-11-03 07:17:11 -0200154 const struct usb_device_id *id);
Bill Pembertona4a557e2012-11-19 13:26:46 -0500155static void rtl8192_usb_disconnect(struct usb_interface *intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200156
157
158static struct usb_driver rtl8192_usb_driver = {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200159 .name = RTL819xU_MODULE_NAME, /* Driver name */
160 .id_table = rtl8192_usb_id_tbl, /* PCI_ID table */
161 .probe = rtl8192_usb_probe, /* probe fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200162 .disconnect = rtl8192_usb_disconnect, /* remove fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200163#ifdef CONFIG_RTL8192_PM
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200164 .suspend = rtl8192_suspend, /* PM suspend fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200165 .resume = rtl8192_resume, /* PM resume fn */
166#else
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200167 .suspend = NULL, /* PM suspend fn */
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100168 .resume = NULL, /* PM resume fn */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200169#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -0200170};
171
Jerry Chuang8fc85982009-11-03 07:17:11 -0200172
Jennifer Naumann0db7a342012-12-05 21:40:19 +0100173typedef struct _CHANNEL_LIST {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200174 u8 Channel[32];
175 u8 Len;
Xenia Ragiadakou972ff922013-05-23 05:14:47 +0300176} CHANNEL_LIST, *PCHANNEL_LIST;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200177
178static CHANNEL_LIST ChannelPlan[] = {
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100179 {{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
180 {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC
181 {{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 -0200182 {{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 +0100183 {{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 -0200184 {{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
185 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1
186 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Israel.
187 {{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
188 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22}, //MIC
189 {{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
190};
191
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300192static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200193{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300194 int i, max_chan = -1, min_chan = -1;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300195 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300196 switch (channel_plan) {
Patrik Karlinf00c4932013-01-09 09:39:44 +0100197 case COUNTRY_CODE_FCC:
198 case COUNTRY_CODE_IC:
199 case COUNTRY_CODE_ETSI:
200 case COUNTRY_CODE_SPAIN:
201 case COUNTRY_CODE_FRANCE:
202 case COUNTRY_CODE_MKK:
203 case COUNTRY_CODE_MKK1:
204 case COUNTRY_CODE_ISRAEL:
205 case COUNTRY_CODE_TELEC:
206 case COUNTRY_CODE_MIC:
207 Dot11d_Init(ieee);
208 ieee->bGlobalDomain = false;
209 //actually 8225 & 8256 rf chips only support B,G,24N mode
210 if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256)) {
211 min_chan = 1;
212 max_chan = 14;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300213 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +0300214 RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __func__);
Patrik Karlinf00c4932013-01-09 09:39:44 +0100215 }
216 if (ChannelPlan[channel_plan].Len != 0) {
217 // Clear old channel map
218 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
219 // Set new channel map
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300220 for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
Patrik Karlinf00c4932013-01-09 09:39:44 +0100221 if (ChannelPlan[channel_plan].Channel[i] < min_chan || ChannelPlan[channel_plan].Channel[i] > max_chan)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200222 break;
Patrik Karlinf00c4932013-01-09 09:39:44 +0100223 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200224 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200225 }
Patrik Karlinf00c4932013-01-09 09:39:44 +0100226 break;
227
228 case COUNTRY_CODE_GLOBAL_DOMAIN:
229 GET_DOT11D_INFO(ieee)->bEnabled = 0;//this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain settings.
230 Dot11d_Reset(ieee);
231 ieee->bGlobalDomain = true;
232 break;
233
234 default:
235 break;
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
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100240#define rx_hal_is_cck_rate(_pdrvinfo)\
Jerry Chuang8fc85982009-11-03 07:17:11 -0200241 (_pdrvinfo->RxRate == DESC90_RATE1M ||\
242 _pdrvinfo->RxRate == DESC90_RATE2M ||\
243 _pdrvinfo->RxRate == DESC90_RATE5_5M ||\
244 _pdrvinfo->RxRate == DESC90_RATE11M) &&\
245 !_pdrvinfo->RxHT\
246
247
248void CamResetAllEntry(struct net_device *dev)
249{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200250 u32 ulcommand = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200251 //2004/02/11 In static WEP, OID_ADD_KEY or OID_ADD_WEP are set before STA associate to AP.
252 // However, ResetKey is called on OID_802_11_INFRASTRUCTURE_MODE and MlmeAssociateRequest
253 // 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 -0200254 ulcommand |= BIT31|BIT30;
255 write_nic_dword(dev, RWCAM, ulcommand);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200256
257}
258
259
260void write_cam(struct net_device *dev, u8 addr, u32 data)
261{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200262 write_nic_dword(dev, WCAMI, data);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300263 write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200264}
265
266u32 read_cam(struct net_device *dev, u8 addr)
267{
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300268 write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff));
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200269 return read_nic_dword(dev, 0xa8);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200270}
271
272void write_nic_byte_E(struct net_device *dev, int indx, u8 data)
273{
274 int status;
275 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
276 struct usb_device *udev = priv->udev;
277
278 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
279 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
280 indx|0xfe00, 0, &data, 1, HZ / 2);
281
282 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300283 netdev_err(dev, "write_nic_byte_E TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200284}
285
286u8 read_nic_byte_E(struct net_device *dev, int indx)
287{
288 int status;
289 u8 data;
290 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
291 struct usb_device *udev = priv->udev;
292
293 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
294 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
295 indx|0xfe00, 0, &data, 1, HZ / 2);
296
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200297 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300298 netdev_err(dev, "read_nic_byte_E TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200299
300 return data;
301}
302//as 92U has extend page from 4 to 16, so modify functions below.
303void write_nic_byte(struct net_device *dev, int indx, u8 data)
304{
305 int status;
306
307 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
308 struct usb_device *udev = priv->udev;
309
310 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
311 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
312 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
313
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200314 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300315 netdev_err(dev, "write_nic_byte TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200316
317
318}
319
320
321void write_nic_word(struct net_device *dev, int indx, u16 data)
322{
323
324 int status;
325
326 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
327 struct usb_device *udev = priv->udev;
328
329 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
330 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
331 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 2, HZ / 2);
332
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200333 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300334 netdev_err(dev, "write_nic_word TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200335
336}
337
338
339void write_nic_dword(struct net_device *dev, int indx, u32 data)
340{
341
342 int status;
343
344 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
345 struct usb_device *udev = priv->udev;
346
347 status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
348 RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE,
349 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 4, HZ / 2);
350
351
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200352 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300353 netdev_err(dev, "write_nic_dword TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200354
355}
356
357
358
359u8 read_nic_byte(struct net_device *dev, int indx)
360{
361 u8 data;
362 int status;
363 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
364 struct usb_device *udev = priv->udev;
365
366 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
367 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
368 (indx&0xff)|0xff00, (indx>>8)&0x0f, &data, 1, HZ / 2);
369
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200370 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300371 netdev_err(dev, "read_nic_byte TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200372
373 return data;
374}
375
376
377
378u16 read_nic_word(struct net_device *dev, int indx)
379{
380 u16 data;
381 int status;
382 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
383 struct usb_device *udev = priv->udev;
384
385 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Mike Gilks616f58f2010-06-03 18:29:23 +0800386 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
387 (indx&0xff)|0xff00, (indx>>8)&0x0f,
388 &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200389
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200390 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300391 netdev_err(dev, "read_nic_word TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200392
393 return data;
394}
395
396u16 read_nic_word_E(struct net_device *dev, int indx)
397{
398 u16 data;
399 int status;
400 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
401 struct usb_device *udev = priv->udev;
402
403 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
404 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
Mike Gilks616f58f2010-06-03 18:29:23 +0800405 indx|0xfe00, 0, &data, 2, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200406
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200407 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300408 netdev_err(dev, "read_nic_word TimeOut! status: %d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200409
410 return data;
411}
412
413u32 read_nic_dword(struct net_device *dev, int indx)
414{
415 u32 data;
416 int status;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200417
418 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
419 struct usb_device *udev = priv->udev;
420
421 status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
Mike Gilks616f58f2010-06-03 18:29:23 +0800422 RTL8187_REQ_GET_REGS, RTL8187_REQT_READ,
423 (indx&0xff)|0xff00, (indx>>8)&0x0f,
424 &data, 4, HZ / 2);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200425
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200426 if (status < 0)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300427 netdev_err(dev, "read_nic_dword TimeOut! status:%d\n", status);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200428
429 return data;
430}
431
Mike Gilks616f58f2010-06-03 18:29:23 +0800432/* u8 read_phy_cck(struct net_device *dev, u8 adr); */
433/* u8 read_phy_ofdm(struct net_device *dev, u8 adr); */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200434/* this might still called in what was the PHY rtl8185/rtl8192 common code
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300435 * plans are to possibility turn it again in one common code...
Jerry Chuang8fc85982009-11-03 07:17:11 -0200436 */
437inline void force_pci_posting(struct net_device *dev)
438{
439}
440
Jerry Chuang8fc85982009-11-03 07:17:11 -0200441static struct net_device_stats *rtl8192_stats(struct net_device *dev);
442void rtl8192_commit(struct net_device *dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200443void rtl8192_restart(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200444void watch_dog_timer_callback(unsigned long data);
445
446/****************************************************************************
Mike Gilks616f58f2010-06-03 18:29:23 +0800447 * -----------------------------PROCFS STUFF-------------------------
448*****************************************************************************
449 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200450
Mike Gilks616f58f2010-06-03 18:29:23 +0800451static struct proc_dir_entry *rtl8192_proc;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200452
David Howells0541f9d2013-04-08 15:17:33 +0100453static int proc_get_stats_ap(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200454{
David Howells0541f9d2013-04-08 15:17:33 +0100455 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200456 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
457 struct ieee80211_device *ieee = priv->ieee80211;
458 struct ieee80211_network *target;
459
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200460 list_for_each_entry(target, &ieee->network_list, list) {
David Howells0541f9d2013-04-08 15:17:33 +0100461 const char *wpa = "non_WPA";
Mike Gilks616f58f2010-06-03 18:29:23 +0800462 if (target->wpa_ie_len > 0 || target->rsn_ie_len > 0)
David Howells0541f9d2013-04-08 15:17:33 +0100463 wpa = "WPA";
464
465 seq_printf(m, "%s %s\n", target->ssid, wpa);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200466 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200467
David Howells0541f9d2013-04-08 15:17:33 +0100468 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200469}
470
David Howells0541f9d2013-04-08 15:17:33 +0100471static int proc_get_registers(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200472{
David Howells0541f9d2013-04-08 15:17:33 +0100473 struct net_device *dev = m->private;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300474 int i, n, max = 0xff;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200475
David Howells0541f9d2013-04-08 15:17:33 +0100476 seq_puts(m, "\n####################page 0##################\n ");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200477
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300478 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300479 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200480
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300481 for (i = 0; i < 16 && n <= max; i++, n++)
482 seq_printf(m, "%2x ", read_nic_byte(dev, 0x000|n));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200483 }
David Howells0541f9d2013-04-08 15:17:33 +0100484
485 seq_puts(m, "\n####################page 1##################\n ");
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300486 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300487 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200488
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300489 for (i = 0; i < 16 && n <= max; i++, n++)
490 seq_printf(m, "%2x ", read_nic_byte(dev, 0x100|n));
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200491 }
David Howells0541f9d2013-04-08 15:17:33 +0100492
493 seq_puts(m, "\n####################page 3##################\n ");
Xenia Ragiadakou3db37642013-05-22 18:22:38 +0300494 for (n = 0; n <= max;) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300495 seq_printf(m, "\nD: %2x > ", n);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200496
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300497 for (i = 0; i < 16 && n <= max; i++, n++)
498 seq_printf(m, "%2x ", read_nic_byte(dev, 0x300|n));
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200499 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200500
David Howells0541f9d2013-04-08 15:17:33 +0100501 seq_putc(m, '\n');
502 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200503}
504
David Howells0541f9d2013-04-08 15:17:33 +0100505static int proc_get_stats_tx(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200506{
David Howells0541f9d2013-04-08 15:17:33 +0100507 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200508 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
509
David Howells0541f9d2013-04-08 15:17:33 +0100510 seq_printf(m,
Jerry Chuang8fc85982009-11-03 07:17:11 -0200511 "TX VI priority ok int: %lu\n"
512 "TX VI priority error int: %lu\n"
513 "TX VO priority ok int: %lu\n"
514 "TX VO priority error int: %lu\n"
515 "TX BE priority ok int: %lu\n"
516 "TX BE priority error int: %lu\n"
517 "TX BK priority ok int: %lu\n"
518 "TX BK priority error int: %lu\n"
519 "TX MANAGE priority ok int: %lu\n"
520 "TX MANAGE priority error int: %lu\n"
521 "TX BEACON priority ok int: %lu\n"
522 "TX BEACON priority error int: %lu\n"
Jerry Chuang8fc85982009-11-03 07:17:11 -0200523 "TX queue resume: %lu\n"
524 "TX queue stopped?: %d\n"
525 "TX fifo overflow: %lu\n"
Jerry Chuang8fc85982009-11-03 07:17:11 -0200526 "TX VI queue: %d\n"
527 "TX VO queue: %d\n"
528 "TX BE queue: %d\n"
529 "TX BK queue: %d\n"
Jerry Chuang8fc85982009-11-03 07:17:11 -0200530 "TX VI dropped: %lu\n"
531 "TX VO dropped: %lu\n"
532 "TX BE dropped: %lu\n"
533 "TX BK dropped: %lu\n"
534 "TX total data packets %lu\n",
Jerry Chuang8fc85982009-11-03 07:17:11 -0200535 priv->stats.txviokint,
536 priv->stats.txvierr,
537 priv->stats.txvookint,
538 priv->stats.txvoerr,
539 priv->stats.txbeokint,
540 priv->stats.txbeerr,
541 priv->stats.txbkokint,
542 priv->stats.txbkerr,
543 priv->stats.txmanageokint,
544 priv->stats.txmanageerr,
545 priv->stats.txbeaconokint,
546 priv->stats.txbeaconerr,
Jerry Chuang8fc85982009-11-03 07:17:11 -0200547 priv->stats.txresumed,
548 netif_queue_stopped(dev),
549 priv->stats.txoverflow,
Jerry Chuang8fc85982009-11-03 07:17:11 -0200550 atomic_read(&(priv->tx_pending[VI_PRIORITY])),
551 atomic_read(&(priv->tx_pending[VO_PRIORITY])),
552 atomic_read(&(priv->tx_pending[BE_PRIORITY])),
553 atomic_read(&(priv->tx_pending[BK_PRIORITY])),
Jerry Chuang8fc85982009-11-03 07:17:11 -0200554 priv->stats.txvidrop,
555 priv->stats.txvodrop,
556 priv->stats.txbedrop,
557 priv->stats.txbkdrop,
558 priv->stats.txdatapkt
Jerry Chuang8fc85982009-11-03 07:17:11 -0200559 );
560
David Howells0541f9d2013-04-08 15:17:33 +0100561 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200562}
563
David Howells0541f9d2013-04-08 15:17:33 +0100564static int proc_get_stats_rx(struct seq_file *m, void *v)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200565{
David Howells0541f9d2013-04-08 15:17:33 +0100566 struct net_device *dev = m->private;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200567 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
568
David Howells0541f9d2013-04-08 15:17:33 +0100569 seq_printf(m,
Jerry Chuang8fc85982009-11-03 07:17:11 -0200570 "RX packets: %lu\n"
571 "RX urb status error: %lu\n"
572 "RX invalid urb error: %lu\n",
573 priv->stats.rxoktotal,
574 priv->stats.rxstaterr,
575 priv->stats.rxurberr);
576
David Howells0541f9d2013-04-08 15:17:33 +0100577 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200578}
David Howells0541f9d2013-04-08 15:17:33 +0100579
Jerry Chuang8fc85982009-11-03 07:17:11 -0200580void rtl8192_proc_module_init(void)
581{
582 RT_TRACE(COMP_INIT, "Initializing proc filesystem");
Al Viroe55d92b2011-07-24 02:07:46 -0400583 rtl8192_proc = proc_mkdir(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200584}
585
586
587void rtl8192_proc_module_remove(void)
588{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200589 remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200590}
591
David Howells0541f9d2013-04-08 15:17:33 +0100592/*
593 * seq_file wrappers for procfile show routines.
594 */
595static int rtl8192_proc_open(struct inode *inode, struct file *file)
596{
David Howells4a520d22013-04-12 14:06:01 +0100597 struct net_device *dev = proc_get_parent_data(inode);
David Howells0541f9d2013-04-08 15:17:33 +0100598 int (*show)(struct seq_file *, void *) = PDE_DATA(inode);
599
600 return single_open(file, show, dev);
601}
602
603static const struct file_operations rtl8192_proc_fops = {
604 .open = rtl8192_proc_open,
605 .read = seq_read,
606 .llseek = seq_lseek,
Al Virobae301d2013-05-05 00:15:43 -0400607 .release = single_release,
David Howells0541f9d2013-04-08 15:17:33 +0100608};
609
610/*
611 * Table of proc files we need to create.
612 */
613struct rtl8192_proc_file {
614 char name[12];
615 int (*show)(struct seq_file *, void *);
616};
617
618static const struct rtl8192_proc_file rtl8192_proc_files[] = {
619 { "stats-rx", &proc_get_stats_rx },
620 { "stats-tx", &proc_get_stats_tx },
621 { "stats-ap", &proc_get_stats_ap },
622 { "registers", &proc_get_registers },
623 { "" }
624};
625
626void rtl8192_proc_init_one(struct net_device *dev)
627{
628 const struct rtl8192_proc_file *f;
David Howellscc87e0f2013-04-12 03:02:22 +0100629 struct proc_dir_entry *dir;
David Howells0541f9d2013-04-08 15:17:33 +0100630
631 if (rtl8192_proc) {
David Howellscc87e0f2013-04-12 03:02:22 +0100632 dir = proc_mkdir_data(dev->name, 0, rtl8192_proc, dev);
633 if (!dir) {
David Howells0541f9d2013-04-08 15:17:33 +0100634 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
635 dev->name);
636 return;
637 }
David Howells0541f9d2013-04-08 15:17:33 +0100638
639 for (f = rtl8192_proc_files; f->name[0]; f++) {
David Howellscc87e0f2013-04-12 03:02:22 +0100640 if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir,
641 &rtl8192_proc_fops, f->show)) {
David Howells0541f9d2013-04-08 15:17:33 +0100642 RT_TRACE(COMP_ERR, "Unable to initialize "
643 "/proc/net/rtl8192/%s/%s\n",
644 dev->name, f->name);
645 return;
646 }
647 }
648 }
649}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200650
651void rtl8192_proc_remove_one(struct net_device *dev)
652{
David Howellscc87e0f2013-04-12 03:02:22 +0100653 remove_proc_subtree(dev->name, rtl8192_proc);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200654}
655
Jerry Chuang8fc85982009-11-03 07:17:11 -0200656/****************************************************************************
657 -----------------------------MISC STUFF-------------------------
658*****************************************************************************/
659
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300660short check_nic_enough_desc(struct net_device *dev, int queue_index)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200661{
662 struct r8192_priv *priv = ieee80211_priv(dev);
663 int used = atomic_read(&priv->tx_pending[queue_index]);
664
665 return (used < MAX_TX_URB);
666}
667
668void tx_timeout(struct net_device *dev)
669{
670 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200671
Jerry Chuang8fc85982009-11-03 07:17:11 -0200672 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200673}
674
675
676/* this is only for debug */
677void dump_eprom(struct net_device *dev)
678{
679 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300680 for (i = 0; i < 63; i++)
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300681 RT_TRACE(COMP_EPROM, "EEPROM addr %x : %x", i, eprom_read(dev, i));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200682}
683
Jerry Chuang8fc85982009-11-03 07:17:11 -0200684
685/****************************************************************************
686 ------------------------------HW STUFF---------------------------
687*****************************************************************************/
688
Jerry Chuang8fc85982009-11-03 07:17:11 -0200689
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300690void rtl8192_set_mode(struct net_device *dev, int mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200691{
692 u8 ecmd;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300693 ecmd = read_nic_byte(dev, EPROM_CMD);
694 ecmd = ecmd & ~EPROM_CMD_OPERATING_MODE_MASK;
695 ecmd = ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
696 ecmd = ecmd & ~(1<<EPROM_CS_SHIFT);
697 ecmd = ecmd & ~(1<<EPROM_CK_SHIFT);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200698 write_nic_byte(dev, EPROM_CMD, ecmd);
699}
700
701
702void rtl8192_update_msr(struct net_device *dev)
703{
704 struct r8192_priv *priv = ieee80211_priv(dev);
705 u8 msr;
706
707 msr = read_nic_byte(dev, MSR);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300708 msr &= ~MSR_LINK_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200709
710 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
711 * msr must be updated if the state is ASSOCIATING.
712 * this is intentional and make sense for ad-hoc and
713 * master (see the create BSS/IBSS func)
714 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300715 if (priv->ieee80211->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200716
717 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
718 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
719 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
720 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
721 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
722 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
723
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300724 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200725 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300726 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200727
728 write_nic_byte(dev, MSR, msr);
729}
730
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300731void rtl8192_set_chan(struct net_device *dev, short ch)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200732{
733 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +0300734 RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __func__, ch);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +0300735 priv->chan = ch;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200736
737 /* this hack should avoid frame TX during channel setting*/
738
Jerry Chuang8fc85982009-11-03 07:17:11 -0200739#ifndef LOOP_TEST
Jerry Chuang8fc85982009-11-03 07:17:11 -0200740 //need to implement rf set channel here WB
741
742 if (priv->rf_set_chan)
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300743 priv->rf_set_chan(dev, priv->chan);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200744 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200745#endif
746}
747
Jerry Chuang8fc85982009-11-03 07:17:11 -0200748static void rtl8192_rx_isr(struct urb *urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200749
750u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
751{
752
753#ifdef USB_RX_AGGREGATION_SUPPORT
754 if (pstats->bisrxaggrsubframe)
755 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
756 + pstats->RxBufShift + 8);
757 else
758#endif
759 return (sizeof(rx_desc_819x_usb) + pstats->RxDrvInfoSize
760 + pstats->RxBufShift);
761
762}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +0300763static int rtl8192_rx_initiate(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200764{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200765 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
766 struct urb *entry;
767 struct sk_buff *skb;
768 struct rtl8192_rx_info *info;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200769
770 /* nomal packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200771 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB) {
772 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
773 if (!skb)
774 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200775 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200776 if (!entry) {
777 kfree_skb(skb);
778 break;
779 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200780 usb_fill_bulk_urb(entry, priv->udev,
781 usb_rcvbulkpipe(priv->udev, 3), skb_tail_pointer(skb),
782 RX_URB_SIZE, rtl8192_rx_isr, skb);
783 info = (struct rtl8192_rx_info *) skb->cb;
784 info->urb = entry;
785 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200786 info->out_pipe = 3; //denote rx normal packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200787 skb_queue_tail(&priv->rx_queue, skb);
788 usb_submit_urb(entry, GFP_KERNEL);
789 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200790
791 /* command packet rx procedure */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200792 while (skb_queue_len(&priv->rx_queue) < MAX_RX_URB + 3) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300793 skb = __dev_alloc_skb(RX_URB_SIZE, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200794 if (!skb)
795 break;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200796 entry = usb_alloc_urb(0, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200797 if (!entry) {
798 kfree_skb(skb);
799 break;
800 }
801 usb_fill_bulk_urb(entry, priv->udev,
802 usb_rcvbulkpipe(priv->udev, 9), skb_tail_pointer(skb),
803 RX_URB_SIZE, rtl8192_rx_isr, skb);
804 info = (struct rtl8192_rx_info *) skb->cb;
805 info->urb = entry;
806 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200807 info->out_pipe = 9; //denote rx cmd packet queue
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200808 skb_queue_tail(&priv->rx_queue, skb);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200809 usb_submit_urb(entry, GFP_KERNEL);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200810 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200811
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200812 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200813}
814
815void rtl8192_set_rxconf(struct net_device *dev)
816{
817 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
818 u32 rxconf;
819
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300820 rxconf = read_nic_dword(dev, RCR);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300821 rxconf = rxconf & ~MAC_FILTER_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200822 rxconf = rxconf | RCR_AMF;
823 rxconf = rxconf | RCR_ADF;
824 rxconf = rxconf | RCR_AB;
825 rxconf = rxconf | RCR_AM;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200826
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300827 if (dev->flags & IFF_PROMISC)
828 DMESG("NIC in promisc mode");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200829
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300830 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || \
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300831 dev->flags & IFF_PROMISC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200832 rxconf = rxconf | RCR_AAP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300833 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200834 rxconf = rxconf | RCR_APM;
835 rxconf = rxconf | RCR_CBSSID;
836 }
837
838
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300839 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200840 rxconf = rxconf | RCR_AICV;
841 rxconf = rxconf | RCR_APWRMGT;
842 }
843
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +0300844 if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200845 rxconf = rxconf | RCR_ACRC32;
846
847
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300848 rxconf = rxconf & ~RX_FIFO_THRESHOLD_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200849 rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE<<RX_FIFO_THRESHOLD_SHIFT);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300850 rxconf = rxconf & ~MAX_RX_DMA_MASK;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200851 rxconf = rxconf | ((u32)7<<RCR_MXDMA_OFFSET);
852
Jerry Chuang8fc85982009-11-03 07:17:11 -0200853 rxconf = rxconf | RCR_ONLYERLPKT;
854
Jerry Chuang8fc85982009-11-03 07:17:11 -0200855 write_nic_dword(dev, RCR, rxconf);
856
857 #ifdef DEBUG_RX
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300858 DMESG("rxconf: %x %x", rxconf, read_nic_dword(dev, RCR));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200859 #endif
860}
861//wait to be removed
862void rtl8192_rx_enable(struct net_device *dev)
863{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200864 rtl8192_rx_initiate(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200865}
866
867
868void rtl8192_tx_enable(struct net_device *dev)
869{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200870}
871
Jerry Chuang8fc85982009-11-03 07:17:11 -0200872
873
874void rtl8192_rtx_disable(struct net_device *dev)
875{
876 u8 cmd;
877 struct r8192_priv *priv = ieee80211_priv(dev);
878 struct sk_buff *skb;
879 struct rtl8192_rx_info *info;
880
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300881 cmd = read_nic_byte(dev, CMDR);
Xenia Ragiadakou4b150932013-05-13 23:36:38 +0300882 write_nic_byte(dev, CMDR, cmd & \
883 ~(CR_TE|CR_RE));
Jerry Chuang8fc85982009-11-03 07:17:11 -0200884 force_pci_posting(dev);
885 mdelay(10);
886
887 while ((skb = __skb_dequeue(&priv->rx_queue))) {
888 info = (struct rtl8192_rx_info *) skb->cb;
889 if (!info->urb)
890 continue;
891
892 usb_kill_urb(info->urb);
893 kfree_skb(skb);
894 }
895
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300896 if (skb_queue_len(&priv->skb_queue))
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300897 netdev_warn(dev, "skb_queue not empty\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -0200898
899 skb_queue_purge(&priv->skb_queue);
900 return;
901}
902
903
904int alloc_tx_beacon_desc_ring(struct net_device *dev, int count)
905{
Jerry Chuang8fc85982009-11-03 07:17:11 -0200906 return 0;
907}
908
Jerry Chuang8fc85982009-11-03 07:17:11 -0200909inline u16 ieeerate2rtlrate(int rate)
910{
Xenia Ragiadakou27161412013-06-03 23:58:45 +0300911 switch (rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200912 case 10:
913 return 0;
914 case 20:
915 return 1;
916 case 55:
917 return 2;
918 case 110:
919 return 3;
920 case 60:
921 return 4;
922 case 90:
923 return 5;
924 case 120:
925 return 6;
926 case 180:
927 return 7;
928 case 240:
929 return 8;
930 case 360:
931 return 9;
932 case 480:
933 return 10;
934 case 540:
935 return 11;
936 default:
937 return 3;
938
939 }
940}
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +0300941static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
Jerry Chuang8fc85982009-11-03 07:17:11 -0200942inline u16 rtl8192_rate2rate(short rate)
943{
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +0300944 if (rate > 11) return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200945 return rtl_rate[rate];
946}
947
948
Justin P. Mattock589b3d02012-04-30 07:41:36 -0700949/* The prototype of rx_isr has changed since one version of Linux Kernel */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200950static void rtl8192_rx_isr(struct urb *urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200951{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200952 struct sk_buff *skb = (struct sk_buff *) urb->context;
953 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
954 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200955 struct r8192_priv *priv = ieee80211_priv(dev);
956 int out_pipe = info->out_pipe;
957 int err;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300958 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200959 return;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200960 if (unlikely(urb->status)) {
961 info->urb = NULL;
962 priv->stats.rxstaterr++;
963 priv->ieee80211->stats.rx_errors++;
964 usb_free_urb(urb);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200965 return;
966 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200967 skb_unlink(skb, &priv->rx_queue);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200968 skb_put(skb, urb->actual_length);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200969
970 skb_queue_tail(&priv->skb_queue, skb);
971 tasklet_schedule(&priv->irq_rx_tasklet);
972
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200973 skb = dev_alloc_skb(RX_URB_SIZE);
974 if (unlikely(!skb)) {
975 usb_free_urb(urb);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300976 netdev_err(dev, "%s(): can't alloc skb\n", __func__);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200977 /* TODO check rx queue length and refill *somewhere* */
978 return;
979 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200980
981 usb_fill_bulk_urb(urb, priv->udev,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -0200982 usb_rcvbulkpipe(priv->udev, out_pipe), skb_tail_pointer(skb),
Jerry Chuang8fc85982009-11-03 07:17:11 -0200983 RX_URB_SIZE, rtl8192_rx_isr, skb);
984
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200985 info = (struct rtl8192_rx_info *) skb->cb;
986 info->urb = urb;
987 info->dev = dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200988 info->out_pipe = out_pipe;
989
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200990 urb->transfer_buffer = skb_tail_pointer(skb);
991 urb->context = skb;
992 skb_queue_tail(&priv->rx_queue, skb);
993 err = usb_submit_urb(urb, GFP_ATOMIC);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +0300994 if (err && err != EPERM)
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +0300995 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 -0200996}
997
998u32
999rtl819xusb_rx_command_packet(
1000 struct net_device *dev,
1001 struct ieee80211_rx_stats *pstats
1002 )
1003{
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 */
1037 assert(queue_index != TXCMD_QUEUE);
1038
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);
1091 return (PaddingNum&0xff);
1092}
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);
1147 tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)agg_skb->tail;
1148 tx_fwinfo = (tx_fwinfo_819x_usb *)(agg_skb->tail + sizeof(tx_desc_819x_usb_aggr_subframe));
1149
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 */
1152 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0;
1153 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 */
1169 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;
1173 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +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):\
Jerry Chuang8fc85982009-11-03 07:17:11 -02001177 (tcb_desc->bRTSUseShortGI?1:0);
1178
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;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001203 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) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001208 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;
1225 }
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,
1255 struct ieee80211_drv_agg_txb *pSendList)
1256{
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
Jerry Chuang8fc85982009-11-03 07:17:11 -02001305 //
1306 // Handle HW Beacon:
Uwe Kleine-Königaf02b582010-10-26 21:57:53 +02001307 // We had transfer our beacon frame to host controller at this moment.
Jerry Chuang8fc85982009-11-03 07:17:11 -02001308 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02001309 //
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 //
1315
1316 /* Handle MPDU in wait queue. */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001317 if (queue_index != BEACON_QUEUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001318 /* Don't send data frame during scanning.*/
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001319 if ((skb_queue_len(&priv->ieee80211->skb_waitQ[queue_index]) != 0)&&\
Jerry Chuang8fc85982009-11-03 07:17:11 -02001320 (!(priv->ieee80211->queue_stop))) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001321 if (NULL != (skb = skb_dequeue(&(priv->ieee80211->skb_waitQ[queue_index]))))
Jerry Chuang8fc85982009-11-03 07:17:11 -02001322 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
1323
1324 return; //modified by david to avoid further processing AMSDU
1325 }
1326#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03001327 else if ((skb_queue_len(&priv->ieee80211->skb_drv_aggQ[queue_index]) != 0)&&\
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001328 (!(priv->ieee80211->queue_stop))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001329 // Tx Driver Aggregation process
Justin P. Mattock589b3d02012-04-30 07:41:36 -07001330 /* The driver will aggregation the packets according to the following stats
Jerry Chuang8fc85982009-11-03 07:17:11 -02001331 * 1. check whether there's tx irq available, for it's a completion return
1332 * function, it should contain enough tx irq;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07001333 * 2. check packet type;
Uwe Kleine-König9b0131c2010-09-01 15:40:25 +02001334 * 3. initialize sendlist, check whether the to-be send packet no greater than 1
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07001335 * 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
Jerry Chuang8fc85982009-11-03 07:17:11 -02001337 * */
1338 skb = skb_dequeue(&priv->ieee80211->skb_drv_aggQ[queue_index]);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001339 if (!check_nic_enough_desc(dev, queue_index)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001340 skb_queue_head(&(priv->ieee80211->skb_drv_aggQ[queue_index]), skb);
1341 return;
1342 }
1343
Jerry Chuang8fc85982009-11-03 07:17:11 -02001344 /*TODO*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02001345 {
1346 struct ieee80211_drv_agg_txb SendList;
1347
1348 memset(&SendList, 0, sizeof(struct ieee80211_drv_agg_txb));
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001349 if (DrvAggr_GetAggregatibleList(dev, skb, &SendList) > 1) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001350 skb = DrvAggr_Aggregation(dev, &SendList);
1351
Jerry Chuang8fc85982009-11-03 07:17:11 -02001352 }
1353 }
1354 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001355 }
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
1366 msr = read_nic_byte(dev, MSR);
1367 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 Ragiadakou27161412013-06-03 23:58:45 +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{
1381 struct r8192_priv *priv = ieee80211_priv(dev);
1382 struct ieee80211_network *net;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001383 u8 i = 0, basic_rate = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001384 net = & priv->ieee80211->current_network;
1385
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001386 for (i = 0; i < net->rates_len; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001387 basic_rate = net->rates[i]&0x7f;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001388 switch (basic_rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001389 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 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001403 for (i = 0; i < net->rates_ex_len; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001404 basic_rate = net->rates_ex[i]&0x7f;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001405 switch (basic_rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001406 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 }
1420}
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 Ragiadakou27161412013-06-03 23:58:45 +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;
1455 net = & priv->ieee80211->current_network;
1456
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) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001465 write_nic_word(dev, ATIMWND, 2);
1466 write_nic_word(dev, BCN_DMATIME, 1023);
1467 write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001468 write_nic_word(dev, BCN_DRV_EARLY_INT, 1);
1469 write_nic_byte(dev, BCN_ERR_THRESH, 100);
1470 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
1471 // 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
1474 write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
1475 }
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
1496u16 ComputeTxTime(
1497 u16 FrameLength,
1498 u16 DataRate,
1499 u8 bManagementFrame,
1500 u8 bShortPreamble
1501)
1502{
1503 u16 FrameTime;
1504 u16 N_DBPS;
1505 u16 Ceiling;
1506
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001507 if (rtl8192_IsWirelessBMode(DataRate)) {
1508 if (bManagementFrame || !bShortPreamble || DataRate == 10) // long preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001509 FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001510 else // Short preamble
Jerry Chuang8fc85982009-11-03 07:17:11 -02001511 FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03001512 if ((FrameLength*8 % (DataRate/10)) != 0) //Get the Ceilling
Jerry Chuang8fc85982009-11-03 07:17:11 -02001513 FrameTime ++;
1514 } else { //802.11g DSSS-OFDM PLCP length field calculation.
1515 N_DBPS = N_DBPSOfRate(DataRate);
1516 Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
1517 + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
1518 FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
1519 }
1520 return FrameTime;
1521}
1522
1523u16 N_DBPSOfRate(u16 DataRate)
1524{
1525 u16 N_DBPS = 24;
1526
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001527 switch (DataRate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001528 case 60:
1529 N_DBPS = 24;
1530 break;
1531
1532 case 90:
1533 N_DBPS = 36;
1534 break;
1535
1536 case 120:
1537 N_DBPS = 48;
1538 break;
1539
1540 case 180:
1541 N_DBPS = 72;
1542 break;
1543
1544 case 240:
1545 N_DBPS = 96;
1546 break;
1547
1548 case 360:
1549 N_DBPS = 144;
1550 break;
1551
1552 case 480:
1553 N_DBPS = 192;
1554 break;
1555
1556 case 540:
1557 N_DBPS = 216;
1558 break;
1559
1560 default:
1561 break;
1562 }
1563
1564 return N_DBPS;
1565}
1566
1567void rtl819xU_cmd_isr(struct urb *tx_cmd_urb, struct pt_regs *regs)
1568{
Jerry Chuang8fc85982009-11-03 07:17:11 -02001569 usb_free_urb(tx_cmd_urb);
1570}
1571
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001572unsigned int txqueue2outpipe(struct r8192_priv *priv, unsigned int tx_queue)
1573{
1574 if (tx_queue >= 9) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03001575 RT_TRACE(COMP_ERR, "%s():Unknown queue ID!!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001576 return 0x04;
1577 }
1578 return priv->txqueue_to_outpipemap[tx_queue];
1579}
1580
1581short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb)
1582{
1583 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001584 int status;
1585 struct urb *tx_urb;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01001586 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001587 tx_desc_cmd_819x_usb *pdesc = (tx_desc_cmd_819x_usb *)skb->data;
1588 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1589 u8 queue_index = tcb_desc->queue_index;
1590
Jerry Chuang8fc85982009-11-03 07:17:11 -02001591 atomic_inc(&priv->tx_pending[queue_index]);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001592 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001593 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001594 dev_kfree_skb(skb);
1595 return -ENOMEM;
1596 }
1597
1598 memset(pdesc, 0, USB_HWDESC_HEADER_LEN);
1599 /* Tx descriptor ought to be set according to the skb->cb */
1600 pdesc->FirstSeg = 1;//bFirstSeg;
1601 pdesc->LastSeg = 1;//bLastSeg;
1602 pdesc->CmdInit = tcb_desc->bCmdOrInit;
1603 pdesc->TxBufferSize = tcb_desc->txbuf_size;
1604 pdesc->OWN = 1;
1605 pdesc->LINIP = tcb_desc->bLastIniPkt;
1606
1607 //----------------------------------------------------------------------------
1608 // Fill up USB_OUT_CONTEXT.
1609 //----------------------------------------------------------------------------
1610 // Get index to out pipe from specified QueueID.
1611#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001612 idx_pipe = txqueue2outpipe(priv, queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001613#else
1614 idx_pipe = 0x04;
1615#endif
1616#ifdef JOHN_DUMP_TXDESC
1617 int i;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001618 printk("<Tx descriptor>--rate %x---", rate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001619 for (i = 0; i < 8; i++)
1620 printk("%8x ", tx[i]);
1621 printk("\n");
1622#endif
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001623 usb_fill_bulk_urb(tx_urb, priv->udev, usb_sndbulkpipe(priv->udev, idx_pipe), \
Jerry Chuang8fc85982009-11-03 07:17:11 -02001624 skb->data, skb->len, rtl8192_tx_isr, skb);
1625
Jerry Chuang8fc85982009-11-03 07:17:11 -02001626 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001627
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001628 if (!status) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001629 return 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001630 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001631 DMESGE("Error TX CMD URB, error %d",
1632 status);
1633 return -1;
1634 }
1635}
1636
1637/*
1638 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1639 * in TxFwInfo data structure
1640 * 2006.10.30 by Emily
1641 *
1642 * \param QUEUEID Software Queue
1643*/
1644u8 MapHwQueueToFirmwareQueue(u8 QueueID)
1645{
1646 u8 QueueSelect = 0x0; //defualt set to
1647
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001648 switch (QueueID) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001649 case BE_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001650 QueueSelect = QSLT_BE;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001651 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001652
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001653 case BK_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001654 QueueSelect = QSLT_BK;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001655 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001656
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001657 case VO_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001658 QueueSelect = QSLT_VO;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001659 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001660
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001661 case VI_QUEUE:
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03001662 QueueSelect = QSLT_VI;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001663 break;
1664 case MGNT_QUEUE:
1665 QueueSelect = QSLT_MGNT;
1666 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001667
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001668 case BEACON_QUEUE:
1669 QueueSelect = QSLT_BEACON;
1670 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001671
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001672 // TODO: 2006.10.30 mark other queue selection until we verify it is OK
1673 // TODO: Remove Assertions
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001674 case TXCMD_QUEUE:
1675 QueueSelect = QSLT_CMD;
1676 break;
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001677 case HIGH_QUEUE:
1678 QueueSelect = QSLT_HIGH;
1679 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001680
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001681 default:
1682 RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
1683 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001684 }
1685 return QueueSelect;
1686}
1687
1688u8 MRateToHwRate8190Pci(u8 rate)
1689{
1690 u8 ret = DESC90_RATE1M;
1691
Xenia Ragiadakouad638452013-05-12 03:15:08 +03001692 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001693 case MGN_1M: ret = DESC90_RATE1M; break;
1694 case MGN_2M: ret = DESC90_RATE2M; break;
1695 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1696 case MGN_11M: ret = DESC90_RATE11M; break;
1697 case MGN_6M: ret = DESC90_RATE6M; break;
1698 case MGN_9M: ret = DESC90_RATE9M; break;
1699 case MGN_12M: ret = DESC90_RATE12M; break;
1700 case MGN_18M: ret = DESC90_RATE18M; break;
1701 case MGN_24M: ret = DESC90_RATE24M; break;
1702 case MGN_36M: ret = DESC90_RATE36M; break;
1703 case MGN_48M: ret = DESC90_RATE48M; break;
1704 case MGN_54M: ret = DESC90_RATE54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001705
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001706 // HT rate since here
1707 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1708 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1709 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1710 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1711 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1712 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1713 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1714 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1715 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1716 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1717 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1718 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1719 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1720 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1721 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1722 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1723 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001724
Sebastian Hahn24fbe872012-12-05 21:40:22 +01001725 default: break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001726 }
1727 return ret;
1728}
1729
1730
1731u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
1732{
1733 u8 tmp_Short;
1734
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03001735 tmp_Short = (TxHT == 1)?((tcb_desc->bUseShortGI)?1:0):((tcb_desc->bUseShortPreamble)?1:0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001736
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03001737 if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001738 tmp_Short = 0;
1739
1740 return tmp_Short;
1741}
1742
Jerry Chuang8fc85982009-11-03 07:17:11 -02001743static void tx_zero_isr(struct urb *tx_urb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001744{
1745 return;
1746}
1747
1748/*
1749 * The tx procedure is just as following,
1750 * skb->cb will contain all the following information,
1751 * priority, morefrag, rate, &dev.
1752 * */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001753short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001754{
1755 struct r8192_priv *priv = ieee80211_priv(dev);
1756 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1757 tx_desc_819x_usb *tx_desc = (tx_desc_819x_usb *)skb->data;
1758 tx_fwinfo_819x_usb *tx_fwinfo = (tx_fwinfo_819x_usb *)(skb->data + USB_HWDESC_HEADER_LEN);
1759 struct usb_device *udev = priv->udev;
1760 int pend;
1761 int status;
1762 struct urb *tx_urb = NULL, *tx_urb_zero = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001763 unsigned int idx_pipe;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001764 pend = atomic_read(&priv->tx_pending[tcb_desc->queue_index]);
1765 /* we are locked here so the two atomic_read and inc are executed
1766 * without interleaves
1767 * !!! For debug purpose
1768 */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001769 if (pend > MAX_TX_URB) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001770 netdev_dbg(dev, "To discard skb packet!\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001771 dev_kfree_skb_any(skb);
1772 return -1;
1773 }
1774
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001775 tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001776 if (!tx_urb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001777 dev_kfree_skb_any(skb);
1778 return -ENOMEM;
1779 }
1780
1781 /* Fill Tx firmware info */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001782 memset(tx_fwinfo, 0, sizeof(tx_fwinfo_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02001783 /* DWORD 0 */
1784 tx_fwinfo->TxHT = (tcb_desc->data_rate&0x80)?1:0;
1785 tx_fwinfo->TxRate = MRateToHwRate8190Pci(tcb_desc->data_rate);
1786 tx_fwinfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1787 tx_fwinfo->Short = QueryIsShort(tx_fwinfo->TxHT, tx_fwinfo->TxRate, tcb_desc);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001788 if (tcb_desc->bAMPDUEnable) {//AMPDU enabled
Jerry Chuang8fc85982009-11-03 07:17:11 -02001789 tx_fwinfo->AllowAggregation = 1;
1790 /* DWORD 1 */
1791 tx_fwinfo->RxMF = tcb_desc->ampdu_factor;
1792 tx_fwinfo->RxAMD = tcb_desc->ampdu_density&0x07;//ampdudensity
1793 } else {
1794 tx_fwinfo->AllowAggregation = 0;
1795 /* DWORD 1 */
1796 tx_fwinfo->RxMF = 0;
1797 tx_fwinfo->RxAMD = 0;
1798 }
1799
1800 /* Protection mode related */
1801 tx_fwinfo->RtsEnable = (tcb_desc->bRTSEnable)?1:0;
1802 tx_fwinfo->CtsEnable = (tcb_desc->bCTSEnable)?1:0;
1803 tx_fwinfo->RtsSTBC = (tcb_desc->bRTSSTBC)?1:0;
1804 tx_fwinfo->RtsHT = (tcb_desc->rts_rate&0x80)?1:0;
1805 tx_fwinfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03001806 tx_fwinfo->RtsSubcarrier = (tx_fwinfo->RtsHT == 0)?(tcb_desc->RTSSC):0;
1807 tx_fwinfo->RtsBandwidth = (tx_fwinfo->RtsHT == 1)?((tcb_desc->bRTSBW)?1:0):0;
1808 tx_fwinfo->RtsShort = (tx_fwinfo->RtsHT == 0)?(tcb_desc->bRTSUseShortPreamble?1:0):\
Jerry Chuang8fc85982009-11-03 07:17:11 -02001809 (tcb_desc->bRTSUseShortGI?1:0);
1810
1811 /* Set Bandwidth and sub-channel settings. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001812 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03001813 if (tcb_desc->bPacketBW) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001814 tx_fwinfo->TxBandwidth = 1;
1815 tx_fwinfo->TxSubCarrier = 0; //By SD3's Jerry suggestion, use duplicated mode
1816 } else {
1817 tx_fwinfo->TxBandwidth = 0;
1818 tx_fwinfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1819 }
1820 } else {
1821 tx_fwinfo->TxBandwidth = 0;
1822 tx_fwinfo->TxSubCarrier = 0;
1823 }
1824
1825#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1826 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001827 tx_fwinfo->Tx_INFO_RSVD = (tcb_desc->DrvAggrNum & 0x1f) << 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001828#endif
1829 /* Fill Tx descriptor */
1830 memset(tx_desc, 0, sizeof(tx_desc_819x_usb));
1831 /* DWORD 0 */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001832 tx_desc->LINIP = 0;
1833 tx_desc->CmdInit = 1;
1834 tx_desc->Offset = sizeof(tx_fwinfo_819x_usb) + 8;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001835
1836#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001837 if (tcb_desc->drv_agg_enable)
Jerry Chuang8fc85982009-11-03 07:17:11 -02001838 tx_desc->PktSize = tcb_desc->pkt_size;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001839 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02001840#endif
1841 {
1842 tx_desc->PktSize = (skb->len - TX_PACKET_SHIFT_BYTES) & 0xffff;
1843 }
1844
1845 /*DWORD 1*/
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03001846 tx_desc->SecCAMID = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001847 tx_desc->RATid = tcb_desc->RATRIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001848 tx_desc->NoEnc = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001849 tx_desc->SecType = 0x0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001850 if (tcb_desc->bHwSec) {
1851 switch (priv->ieee80211->pairwise_key_type) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001852 case KEY_TYPE_WEP40:
1853 case KEY_TYPE_WEP104:
1854 tx_desc->SecType = 0x1;
1855 tx_desc->NoEnc = 0;
1856 break;
1857 case KEY_TYPE_TKIP:
1858 tx_desc->SecType = 0x2;
1859 tx_desc->NoEnc = 0;
1860 break;
1861 case KEY_TYPE_CCMP:
1862 tx_desc->SecType = 0x3;
1863 tx_desc->NoEnc = 0;
1864 break;
1865 case KEY_TYPE_NA:
1866 tx_desc->SecType = 0x0;
1867 tx_desc->NoEnc = 1;
1868 break;
1869 }
1870 }
1871
1872 tx_desc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1873 tx_desc->TxFWInfoSize = sizeof(tx_fwinfo_819x_usb);
1874
1875 tx_desc->DISFB = tcb_desc->bTxDisableRateFallBack;
1876 tx_desc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1877
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001878 /* Fill fields that are required to be initialized in all of the descriptors */
1879 //DWORD 0
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001880 tx_desc->FirstSeg = 1;
1881 tx_desc->LastSeg = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001882 tx_desc->OWN = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001883
1884#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
1885 if (tcb_desc->drv_agg_enable) {
1886 tx_desc->TxBufferSize = tcb_desc->pkt_size + sizeof(tx_fwinfo_819x_usb);
1887 } else
1888#endif
1889 {
1890 //DWORD 2
1891 tx_desc->TxBufferSize = (u32)(skb->len - USB_HWDESC_HEADER_LEN);
1892 }
1893 /* Get index to out pipe from specified QueueID */
1894#ifndef USE_ONE_PIPE
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001895 idx_pipe = txqueue2outpipe(priv, tcb_desc->queue_index);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001896#else
1897 idx_pipe = 0x5;
1898#endif
1899
Jerry Chuang8fc85982009-11-03 07:17:11 -02001900 /* To submit bulk urb */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001901 usb_fill_bulk_urb(tx_urb, udev,
1902 usb_sndbulkpipe(udev, idx_pipe), skb->data,
Jerry Chuang8fc85982009-11-03 07:17:11 -02001903 skb->len, rtl8192_tx_isr, skb);
1904
Jerry Chuang8fc85982009-11-03 07:17:11 -02001905 status = usb_submit_urb(tx_urb, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001906 if (!status) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001907//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
1908 bool bSend0Byte = false;
1909 u8 zero = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001910 if (udev->speed == USB_SPEED_HIGH) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001911 if (skb->len > 0 && skb->len % 512 == 0)
1912 bSend0Byte = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001913 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001914 if (skb->len > 0 && skb->len % 64 == 0)
1915 bSend0Byte = true;
1916 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001917 if (bSend0Byte) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001918 tx_urb_zero = usb_alloc_urb(0, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001919 if (!tx_urb_zero) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001920 RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
1921 return -ENOMEM;
1922 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001923 usb_fill_bulk_urb(tx_urb_zero, udev,
1924 usb_sndbulkpipe(udev, idx_pipe), &zero,
Jerry Chuang8fc85982009-11-03 07:17:11 -02001925 0, tx_zero_isr, dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001926 status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001927 if (status) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001928 RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
1929 return -1;
1930 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001931 }
1932 dev->trans_start = jiffies;
1933 atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
1934 return 0;
Patrik Karlin29b48ae2013-01-09 09:40:23 +01001935 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001936 RT_TRACE(COMP_ERR, "Error TX URB %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]),
1937 status);
1938 return -1;
1939 }
1940}
1941
1942short rtl8192_usb_initendpoints(struct net_device *dev)
1943{
1944 struct r8192_priv *priv = ieee80211_priv(dev);
1945
Julia Lawall32414872010-05-11 20:26:57 +02001946 priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB+1),
1947 GFP_KERNEL);
David Chosrovab8345172010-12-01 13:42:16 +01001948 if (priv->rx_urb == NULL)
1949 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001950
1951#ifndef JACKSON_NEW_RX
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001952 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001953
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03001954 priv->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001955
1956 priv->rx_urb[i]->transfer_buffer = kmalloc(RX_URB_SIZE, GFP_KERNEL);
1957
1958 priv->rx_urb[i]->transfer_buffer_length = RX_URB_SIZE;
1959 }
1960#endif
1961
1962#ifdef THOMAS_BEACON
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001963 {
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001964 long align = 0;
1965 void *oldaddr, *newaddr;
1966
Jerry Chuang8fc85982009-11-03 07:17:11 -02001967 priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001968 priv->oldaddr = kmalloc(16, GFP_KERNEL);
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001969 oldaddr = priv->oldaddr;
1970 align = ((long)oldaddr) & 3;
1971 if (align) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001972 newaddr = oldaddr + 4 - align;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001973 priv->rx_urb[16]->transfer_buffer_length = 16 - 4 + align;
1974 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02001975 newaddr = oldaddr;
1976 priv->rx_urb[16]->transfer_buffer_length = 16;
1977 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02001978 priv->rx_urb[16]->transfer_buffer = newaddr;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03001979 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001980#endif
1981
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03001982 memset(priv->rx_urb, 0, sizeof(struct urb *) * MAX_RX_URB);
Julia Lawall7a6cb0d2010-05-13 22:00:05 +02001983 priv->pp_rxskb = kcalloc(MAX_RX_URB, sizeof(struct sk_buff *),
Julia Lawall32414872010-05-11 20:26:57 +02001984 GFP_KERNEL);
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001985 if (!priv->pp_rxskb) {
1986 kfree(priv->rx_urb);
Jerry Chuang8fc85982009-11-03 07:17:11 -02001987
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001988 priv->pp_rxskb = NULL;
1989 priv->rx_urb = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02001990
Peter Senna Tschudin2e464f02012-09-12 17:06:43 +02001991 DMESGE("Endpoint Alloc Failure");
1992 return -ENOMEM;
1993 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02001994
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03001995 netdev_dbg(dev, "End of initendpoints\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02001996 return 0;
1997
1998}
1999#ifdef THOMAS_BEACON
2000void rtl8192_usb_deleteendpoints(struct net_device *dev)
2001{
2002 int i;
2003 struct r8192_priv *priv = ieee80211_priv(dev);
2004
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002005 if (priv->rx_urb) {
2006 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002007 usb_kill_urb(priv->rx_urb[i]);
2008 usb_free_urb(priv->rx_urb[i]);
2009 }
2010 kfree(priv->rx_urb);
2011 priv->rx_urb = NULL;
2012 }
Ilia Mirkine72714f2011-03-13 00:29:07 -05002013 kfree(priv->oldaddr);
2014 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002015 if (priv->pp_rxskb) {
2016 kfree(priv->pp_rxskb);
2017 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002018 }
2019}
2020#else
2021void rtl8192_usb_deleteendpoints(struct net_device *dev)
2022{
2023 int i;
2024 struct r8192_priv *priv = ieee80211_priv(dev);
2025
2026#ifndef JACKSON_NEW_RX
2027
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002028 if (priv->rx_urb) {
2029 for (i = 0; i < (MAX_RX_URB+1); i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002030 usb_kill_urb(priv->rx_urb[i]);
2031 kfree(priv->rx_urb[i]->transfer_buffer);
2032 usb_free_urb(priv->rx_urb[i]);
2033 }
2034 kfree(priv->rx_urb);
2035 priv->rx_urb = NULL;
2036
2037 }
2038#else
Ilia Mirkine72714f2011-03-13 00:29:07 -05002039 kfree(priv->rx_urb);
2040 priv->rx_urb = NULL;
2041 kfree(priv->oldaddr);
2042 priv->oldaddr = NULL;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002043 if (priv->pp_rxskb) {
2044 kfree(priv->pp_rxskb);
2045 priv->pp_rxskb = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002046
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002047 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002048
2049#endif
2050}
2051#endif
2052
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002053extern void rtl8192_update_ratr_table(struct net_device *dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002054void rtl8192_link_change(struct net_device *dev)
2055{
Jerry Chuang8fc85982009-11-03 07:17:11 -02002056 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002057 struct ieee80211_device *ieee = priv->ieee80211;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002058 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002059 rtl8192_net_update(dev);
2060 rtl8192_update_ratr_table(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002061 //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
2062 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
2063 EnableHWSecurityConfig8192(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002064 }
2065 /*update timing params*/
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002066 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002067 u32 reg = 0;
2068 reg = read_nic_dword(dev, RCR);
2069 if (priv->ieee80211->state == IEEE80211_LINKED)
2070 priv->ReceiveConfig = reg |= RCR_CBSSID;
2071 else
2072 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
2073 write_nic_dword(dev, RCR, reg);
2074 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002075}
2076
2077static struct ieee80211_qos_parameters def_qos_parameters = {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002078 {3, 3, 3, 3},/* cw_min */
2079 {7, 7, 7, 7},/* cw_max */
2080 {2, 2, 2, 2},/* aifs */
2081 {0, 0, 0, 0},/* flags */
2082 {0, 0, 0, 0} /* tx_op_limit */
Jerry Chuang8fc85982009-11-03 07:17:11 -02002083};
2084
2085
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002086void rtl8192_update_beacon(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002087{
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01002088 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
2089 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002090 struct ieee80211_device *ieee = priv->ieee80211;
2091 struct ieee80211_network *net = &ieee->current_network;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002092
2093 if (ieee->pHTInfo->bCurrentHTSupport)
2094 HTUpdateSelfAndPeerSetting(ieee, net);
2095 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
2096 rtl8192_update_cap(dev, net->capability);
2097}
2098/*
2099* background support to run QoS activate functionality
2100*/
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002101int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, EDCAPARA_VO};
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002102void rtl8192_qos_activate(struct work_struct *work)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002103{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002104 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
2105 struct net_device *dev = priv->ieee80211->dev;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002106 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
2107 u8 mode = priv->ieee80211->current_network.mode;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002108 u8 u1bAIFS;
2109 u32 u4bAcParam;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002110 int i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002111
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002112 if (priv == NULL)
2113 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002114
Jerry Chuang8fc85982009-11-03 07:17:11 -02002115 mutex_lock(&priv->mutex);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002116 if (priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002117 goto success;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002118 RT_TRACE(COMP_QOS, "qos active process with associate response received\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02002119 /* It better set slot time at first */
2120 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
2121 /* update the ac parameter to related registers */
Xenia Ragiadakou212bff32013-05-22 18:22:34 +03002122 for (i = 0; i < QOS_QUEUE_NUM; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002123 //Mode G/A: slotTimeTimer = 9; Mode B: 20
2124 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime;
2125 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
2126 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
2127 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
2128 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
2129
2130 write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002131 }
2132
2133success:
Jerry Chuang8fc85982009-11-03 07:17:11 -02002134 mutex_unlock(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002135}
2136
2137static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
2138 int active_network,
2139 struct ieee80211_network *network)
2140{
2141 int ret = 0;
2142 u32 size = sizeof(struct ieee80211_qos_parameters);
2143
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002144 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002145 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002146
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002147 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2148 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002149
2150 if (network->flags & NETWORK_HAS_QOS_MASK) {
2151 if (active_network &&
2152 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
2153 network->qos_data.active = network->qos_data.supported;
2154
2155 if ((network->qos_data.active == 1) && (active_network == 1) &&
2156 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
2157 (network->qos_data.old_param_count !=
2158 network->qos_data.param_count)) {
2159 network->qos_data.old_param_count =
2160 network->qos_data.param_count;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002161 queue_work(priv->priv_wq, &priv->qos_activate);
Xenia Ragiadakoue6367212013-05-23 05:14:46 +03002162 RT_TRACE(COMP_QOS, "QoS parameters change call "
Jerry Chuang8fc85982009-11-03 07:17:11 -02002163 "qos_activate\n");
2164 }
2165 } else {
2166 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2167 &def_qos_parameters, size);
2168
2169 if ((network->qos_data.active == 1) && (active_network == 1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002170 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002171 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
2172 }
2173 network->qos_data.active = 0;
2174 network->qos_data.supported = 0;
2175 }
2176
2177 return 0;
2178}
2179
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002180/* handle and manage frame from beacon and probe response */
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002181static int rtl8192_handle_beacon(struct net_device *dev,
2182 struct ieee80211_beacon *beacon,
2183 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002184{
2185 struct r8192_priv *priv = ieee80211_priv(dev);
2186
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002187 rtl8192_qos_handle_probe_response(priv, 1, network);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002188 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002189 return 0;
2190
2191}
2192
2193/*
2194* handling the beaconing responses. if we get different QoS setting
2195* off the network from the associated setting, adjust the QoS
2196* setting
2197*/
2198static int rtl8192_qos_association_resp(struct r8192_priv *priv,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002199 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002200{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002201 int ret = 0;
2202 unsigned long flags;
2203 u32 size = sizeof(struct ieee80211_qos_parameters);
2204 int set_qos_param = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002205
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002206 if ((priv == NULL) || (network == NULL))
2207 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002208
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002209 if (priv->ieee80211->state != IEEE80211_LINKED)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002210 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002211
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002212 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
2213 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002214
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002215 spin_lock_irqsave(&priv->ieee80211->lock, flags);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002216 if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002217 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2218 &network->qos_data.parameters,\
2219 sizeof(struct ieee80211_qos_parameters));
2220 priv->ieee80211->current_network.qos_data.active = 1;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002221 set_qos_param = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002222 /* update qos parameter for current network */
2223 priv->ieee80211->current_network.qos_data.old_param_count = \
2224 priv->ieee80211->current_network.qos_data.param_count;
2225 priv->ieee80211->current_network.qos_data.param_count = \
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002226 network->qos_data.param_count;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002227 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002228 memcpy(&priv->ieee80211->current_network.qos_data.parameters,\
2229 &def_qos_parameters, size);
2230 priv->ieee80211->current_network.qos_data.active = 0;
2231 priv->ieee80211->current_network.qos_data.supported = 0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002232 set_qos_param = 1;
2233 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002234
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002235 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002236
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002237 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 -02002238 if (set_qos_param == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002239 queue_work(priv->priv_wq, &priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002240
2241
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002242 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002243}
2244
2245
2246static int rtl8192_handle_assoc_response(struct net_device *dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002247 struct ieee80211_assoc_response_frame *resp,
2248 struct ieee80211_network *network)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002249{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002250 struct r8192_priv *priv = ieee80211_priv(dev);
2251 rtl8192_qos_association_resp(priv, network);
2252 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002253}
2254
2255
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002256void rtl8192_update_ratr_table(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002257{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002258 struct r8192_priv *priv = ieee80211_priv(dev);
2259 struct ieee80211_device *ieee = priv->ieee80211;
2260 u8 *pMcsRate = ieee->dot11HTOperationalRateSet;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002261 u32 ratr_value = 0;
2262 u8 rate_index = 0;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002263 rtl8192_config_rate(dev, (u16 *)(&ratr_value));
2264 ratr_value |= (*(u16 *)(pMcsRate)) << 12;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002265 switch (ieee->mode) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002266 case IEEE_A:
2267 ratr_value &= 0x00000FF0;
2268 break;
2269 case IEEE_B:
2270 ratr_value &= 0x0000000F;
2271 break;
2272 case IEEE_G:
2273 ratr_value &= 0x00000FF7;
2274 break;
2275 case IEEE_N_24G:
2276 case IEEE_N_5G:
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002277 if (ieee->pHTInfo->PeerMimoPs == 0) {//MIMO_PS_STATIC
Jerry Chuang8fc85982009-11-03 07:17:11 -02002278 ratr_value &= 0x0007F007;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002279 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002280 if (priv->rf_type == RF_1T2R)
2281 ratr_value &= 0x000FF007;
2282 else
2283 ratr_value &= 0x0F81F007;
2284 }
2285 break;
2286 default:
2287 break;
2288 }
2289 ratr_value &= 0x0FFFFFFF;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002290 if (ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002291 ratr_value |= 0x80000000;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002292 else if (!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002293 ratr_value |= 0x80000000;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002294 write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
2295 write_nic_byte(dev, UFWP, 1);
2296}
2297
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002298static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04};
Jerry Chuang8fc85982009-11-03 07:17:11 -02002299static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002300bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002301{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002302 struct r8192_priv *priv = ieee80211_priv(dev);
2303 struct ieee80211_device *ieee = priv->ieee80211;
2304 struct ieee80211_network *network = &ieee->current_network;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002305 int wpa_ie_len = ieee->wpa_ie_len;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002306 struct ieee80211_crypt_data *crypt;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002307 int encrypt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002308
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002309 crypt = ieee->crypt[ieee->tx_keyidx];
Jerry Chuang8fc85982009-11-03 07:17:11 -02002310 //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 +03002311 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 -02002312
2313 /* simply judge */
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002314 if (encrypt && (wpa_ie_len == 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002315 /* wep encryption, no N mode setting */
2316 return false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002317 } else if ((wpa_ie_len != 0)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002318 /* parse pairwise key type */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002319 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 -02002320 return true;
2321 else
2322 return false;
2323 } else {
2324 return true;
2325 }
2326
Jerry Chuang8fc85982009-11-03 07:17:11 -02002327 return true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002328}
2329
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002330bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002331{
2332 bool Reval;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002333 struct r8192_priv *priv = ieee80211_priv(dev);
2334 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002335
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002336 if (ieee->bHalfWirelessN24GMode == true)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002337 Reval = true;
2338 else
2339 Reval = false;
2340
2341 return Reval;
2342}
2343
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002344void rtl8192_refresh_supportrate(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002345{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002346 struct ieee80211_device *ieee = priv->ieee80211;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002347 //we do not consider set support rate for ABG mode, only HT MCS rate is set here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002348 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002349 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002350 else
2351 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
2352 return;
2353}
2354
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002355u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002356{
2357 struct r8192_priv *priv = ieee80211_priv(dev);
2358 u8 ret = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002359 switch (priv->rf_chip) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002360 case RF_8225:
2361 case RF_8256:
2362 case RF_PSEUDO_11N:
2363 ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
2364 break;
2365 case RF_8258:
2366 ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
2367 break;
2368 default:
2369 ret = WIRELESS_MODE_B;
2370 break;
2371 }
2372 return ret;
2373}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002374void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002375{
2376 struct r8192_priv *priv = ieee80211_priv(dev);
2377 u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
2378
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002379 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode) == 0)) {
2380 if (bSupportMode & WIRELESS_MODE_N_24G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002381 wireless_mode = WIRELESS_MODE_N_24G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002382 } else if (bSupportMode & WIRELESS_MODE_N_5G) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002383 wireless_mode = WIRELESS_MODE_N_5G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002384 } else if ((bSupportMode & WIRELESS_MODE_A)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002385 wireless_mode = WIRELESS_MODE_A;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002386 } else if ((bSupportMode & WIRELESS_MODE_G)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002387 wireless_mode = WIRELESS_MODE_G;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002388 } else if ((bSupportMode & WIRELESS_MODE_B)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002389 wireless_mode = WIRELESS_MODE_B;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002390 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002391 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __func__, bSupportMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002392 wireless_mode = WIRELESS_MODE_B;
2393 }
2394 }
Adam Buchbinder39cfb972009-12-18 15:43:51 -05002395#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 +03002396 ActUpdateChannelAccessSetting(pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002397#endif
2398 priv->ieee80211->mode = wireless_mode;
2399
2400 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
2401 priv->ieee80211->pHTInfo->bEnableHT = 1;
2402 else
2403 priv->ieee80211->pHTInfo->bEnableHT = 0;
2404 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
2405 rtl8192_refresh_supportrate(priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002406
2407}
2408//init priv variables here. only non_zero value should be initialized here.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002409static void rtl8192_init_priv_variable(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002410{
2411 struct r8192_priv *priv = ieee80211_priv(dev);
2412 u8 i;
2413 priv->card_8192 = NIC_8192U;
2414 priv->chan = 1; //set to channel 1
2415 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
2416 priv->ieee80211->iw_mode = IW_MODE_INFRA;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002417 priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002418 priv->retry_rts = DEFAULT_RETRY_RTS;
2419 priv->retry_data = DEFAULT_RETRY_DATA;
2420 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
2421 priv->ieee80211->rate = 110; //11 mbps
2422 priv->ieee80211->short_slot = 1;
2423 priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0;
2424 priv->CckPwEnl = 6;
2425 //for silent reset
2426 priv->IrpPendingCount = 1;
2427 priv->ResetProgress = RESET_TYPE_NORESET;
2428 priv->bForcedSilentReset = 0;
2429 priv->bDisableNormalResetCheck = false;
2430 priv->force_reset = false;
2431
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002432 priv->ieee80211->FwRWRF = 0; //we don't use FW read/write RF until stable firmware is available.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002433 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2434 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2435 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2436 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2437 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002438 IEEE_SOFTMAC_BEACONS;//added by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002439
2440 priv->ieee80211->active_scan = 1;
2441 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
2442 priv->ieee80211->host_encrypt = 1;
2443 priv->ieee80211->host_decrypt = 1;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002444 priv->ieee80211->start_send_beacons = NULL; //-by amy 080604
2445 priv->ieee80211->stop_send_beacons = NULL; //-by amy 080604
Jerry Chuang8fc85982009-11-03 07:17:11 -02002446 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
2447 priv->ieee80211->set_chan = rtl8192_set_chan;
2448 priv->ieee80211->link_change = rtl8192_link_change;
2449 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
2450 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
2451 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
2452 priv->ieee80211->init_wmmparam_flag = 0;
2453 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2454 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
2455 priv->ieee80211->tx_headroom = TX_PACKET_SHIFT_BYTES;
2456 priv->ieee80211->qos_support = 1;
2457
2458 //added by WB
Jerry Chuang8fc85982009-11-03 07:17:11 -02002459 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
2460 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
2461 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
2462 //added by david
2463 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8192;
2464 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xUsb;
2465 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
2466 //added by amy
2467 priv->ieee80211->InitialGainHandler = InitialGain819xUsb;
2468 priv->card_type = USB;
2469#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002470 if (Adapter->bInHctTest) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002471 pHalData->ShortRetryLimit = 7;
2472 pHalData->LongRetryLimit = 7;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002473 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002474#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -02002475 priv->ShortRetryLimit = 0x30;
2476 priv->LongRetryLimit = 0x30;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002477 priv->EarlyRxThreshold = 7;
2478 priv->enable_gpio0 = 0;
2479 priv->TransmitConfig =
Justin P. Mattock589b3d02012-04-30 07:41:36 -07002480 (TCR_MXDMA_2048<<TCR_MXDMA_OFFSET)| // Max DMA Burst Size per Tx DMA Burst, 7: reserved.
Jerry Chuang8fc85982009-11-03 07:17:11 -02002481 (priv->ShortRetryLimit<<TCR_SRL_OFFSET)| // Short retry limit
2482 (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07002483 (false ? TCR_SAT: 0); // FALSE: HW provides PLCP length and LENGEXT, TRUE: SW provides them
Jerry Chuang8fc85982009-11-03 07:17:11 -02002484#ifdef TO_DO_LIST
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03002485 if (Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002486 pHalData->ReceiveConfig = pHalData->CSMethod |
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03002487 RCR_AMF | RCR_ADF | //accept management/data
Jerry Chuang8fc85982009-11-03 07:17:11 -02002488 //guangan200710
2489 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2490 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01002491 RCR_AICV | RCR_ACRC32 | //accept ICV/CRC error packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02002492 ((u32)7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2493 (pHalData->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
2494 (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt:0);
2495 else
2496
2497#endif
2498 priv->ReceiveConfig =
2499 RCR_AMF | RCR_ADF | //accept management/data
2500 RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
2501 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
Jerry Chuang8fc85982009-11-03 07:17:11 -02002502 ((u32)7<<RCR_MXDMA_OFFSET)| // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
2503 (priv->EarlyRxThreshold<<RX_FIFO_THRESHOLD_SHIFT) | // Rx FIFO Threshold, 7: No Rx threshold.
2504 (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT:0);
2505
2506 priv->AcmControl = 0;
Devendra Nagab7553422012-08-26 11:06:33 +05302507 priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002508
2509 /* rx related queue */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002510 skb_queue_head_init(&priv->rx_queue);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002511 skb_queue_head_init(&priv->skb_queue);
2512
2513 /* Tx related queue */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002514 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002515 skb_queue_head_init(&priv->ieee80211->skb_waitQ [i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002516 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002517 skb_queue_head_init(&priv->ieee80211->skb_aggQ [i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002518 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002519 skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ [i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002520 priv->rf_set_chan = rtl8192_phy_SwChnl;
2521}
2522
2523//init lock here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002524static void rtl8192_init_priv_lock(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002525{
2526 spin_lock_init(&priv->tx_lock);
2527 spin_lock_init(&priv->irq_lock);//added by thomas
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002528 sema_init(&priv->wx_sem, 1);
2529 sema_init(&priv->rf_sem, 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002530 mutex_init(&priv->mutex);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002531}
2532
Jerry Chuang8fc85982009-11-03 07:17:11 -02002533extern void rtl819x_watchdog_wqcallback(struct work_struct *work);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002534
2535void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
2536//init tasklet and wait_queue here. only 2.6 above kernel is considered
2537#define DRV_NAME "wlan0"
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002538static void rtl8192_init_priv_task(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002539{
2540 struct r8192_priv *priv = ieee80211_priv(dev);
2541
Jerry Chuang8fc85982009-11-03 07:17:11 -02002542 priv->priv_wq = create_workqueue(DRV_NAME);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002543
Jerry Chuang8fc85982009-11-03 07:17:11 -02002544 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2545
Jerry Chuang8fc85982009-11-03 07:17:11 -02002546 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2547 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002548 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2549 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2550 INIT_DELAYED_WORK(&priv->initialgain_operate_wq, InitialGainOperateWorkItemCallBack);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002551 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002552
2553 tasklet_init(&priv->irq_rx_tasklet,
2554 (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
2555 (unsigned long)priv);
2556}
2557
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002558static void rtl8192_get_eeprom_size(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002559{
2560 u16 curCR = 0;
2561 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002562 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002563 curCR = read_nic_word_E(dev, EPROM_CMD);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002564 RT_TRACE(COMP_EPROM, "read from Reg EPROM_CMD(%x):%x\n", EPROM_CMD, curCR);
2565 //whether need I consider BIT5?
2566 priv->epromtype = (curCR & Cmd9346CR_9356SEL) ? EPROM_93c56 : EPROM_93c46;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002567 RT_TRACE(COMP_EPROM, "<===========%s(), epromtype:%d\n", __func__, priv->epromtype);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002568}
2569
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002570//used to swap endian. as ntohl & htonl are not necessary to swap endian, so use this instead.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002571static inline u16 endian_swap(u16 *data)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002572{
2573 u16 tmp = *data;
2574 *data = (tmp >> 8) | (tmp << 8);
2575 return *data;
2576}
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002577static void rtl8192_read_eeprom_info(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002578{
2579 u16 wEPROM_ID = 0;
2580 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x02};
2581 u8 bLoad_From_EEPOM = false;
2582 struct r8192_priv *priv = ieee80211_priv(dev);
2583 u16 tmpValue = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002584 int i;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002585 RT_TRACE(COMP_EPROM, "===========>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002586 wEPROM_ID = eprom_read(dev, 0); //first read EEPROM ID out;
2587 RT_TRACE(COMP_EPROM, "EEPROM ID is 0x%x\n", wEPROM_ID);
2588
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002589 if (wEPROM_ID != RTL8190_EEPROM_ID) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002590 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 +03002591 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002592 bLoad_From_EEPOM = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002593 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002594
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002595 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002596 tmpValue = eprom_read(dev, (EEPROM_VID>>1));
2597 priv->eeprom_vid = endian_swap(&tmpValue);
2598 priv->eeprom_pid = eprom_read(dev, (EEPROM_PID>>1));
2599 tmpValue = eprom_read(dev, (EEPROM_ChannelPlan>>1));
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002600 priv->eeprom_ChannelPlan = ((tmpValue&0xff00)>>8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002601 priv->btxpowerdata_readfromEEPORM = true;
2602 priv->eeprom_CustomerID = eprom_read(dev, (EEPROM_Customer_ID>>1)) >>8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002603 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002604 priv->eeprom_vid = 0;
2605 priv->eeprom_pid = 0;
2606 priv->card_8192_version = VERSION_819xU_B;
2607 priv->eeprom_ChannelPlan = 0;
2608 priv->eeprom_CustomerID = 0;
2609 }
2610 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);
2611 //set channelplan from eeprom
2612 priv->ChannelPlan = priv->eeprom_ChannelPlan;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002613 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002614 int i;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002615 for (i = 0; i < 6; i += 2) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002616 u16 tmp = 0;
2617 tmp = eprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i)>>1));
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002618 *(u16 *)(&dev->dev_addr[i]) = tmp;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002619 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002620 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002621 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2622 //should I set IDR0 here?
2623 }
Joe Perches0ee9f672009-12-06 11:34:52 -08002624 RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002625 priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
2626 priv->rf_chip = RF_8256;
2627
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002628 if (priv->card_8192_version == (u8)VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002629 //read Tx power gain offset of legacy OFDM to HT rate
2630 if (bLoad_From_EEPOM)
2631 priv->EEPROMTxPowerDiff = (eprom_read(dev, (EEPROM_TxPowerDiff>>1))&0xff00) >> 8;
2632 else
2633 priv->EEPROMTxPowerDiff = EEPROM_Default_TxPower;
2634 RT_TRACE(COMP_EPROM, "TxPowerDiff:%d\n", priv->EEPROMTxPowerDiff);
2635 //read ThermalMeter from EEPROM
2636 if (bLoad_From_EEPOM)
2637 priv->EEPROMThermalMeter = (u8)(eprom_read(dev, (EEPROM_ThermalMeter>>1))&0x00ff);
2638 else
2639 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2640 RT_TRACE(COMP_EPROM, "ThermalMeter:%d\n", priv->EEPROMThermalMeter);
2641 //vivi, for tx power track
2642 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2643 //read antenna tx power offset of B/C/D to A from EEPROM
2644 if (bLoad_From_EEPOM)
2645 priv->EEPROMPwDiff = (eprom_read(dev, (EEPROM_PwDiff>>1))&0x0f00)>>8;
2646 else
2647 priv->EEPROMPwDiff = EEPROM_Default_PwDiff;
2648 RT_TRACE(COMP_EPROM, "TxPwDiff:%d\n", priv->EEPROMPwDiff);
2649 // Read CrystalCap from EEPROM
2650 if (bLoad_From_EEPOM)
2651 priv->EEPROMCrystalCap = (eprom_read(dev, (EEPROM_CrystalCap>>1))&0x0f);
2652 else
2653 priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
2654 RT_TRACE(COMP_EPROM, "CrystalCap = %d\n", priv->EEPROMCrystalCap);
2655 //get per-channel Tx power level
2656 if (bLoad_From_EEPOM)
2657 priv->EEPROM_Def_Ver = (eprom_read(dev, (EEPROM_TxPwIndex_Ver>>1))&0xff00)>>8;
2658 else
2659 priv->EEPROM_Def_Ver = 1;
2660 RT_TRACE(COMP_EPROM, "EEPROM_DEF_VER:%d\n", priv->EEPROM_Def_Ver);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002661 if (priv->EEPROM_Def_Ver == 0) { //old eeprom definition
Jerry Chuang8fc85982009-11-03 07:17:11 -02002662 int i;
2663 if (bLoad_From_EEPOM)
2664 priv->EEPROMTxPowerLevelCCK = (eprom_read(dev, (EEPROM_TxPwIndex_CCK>>1))&0xff) >> 8;
2665 else
2666 priv->EEPROMTxPowerLevelCCK = 0x10;
2667 RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002668 for (i = 0; i < 3; i++) {
2669 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002670 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G+i)>>1);
2671 if (((EEPROM_TxPwIndex_OFDM_24G+i) % 2) == 0)
2672 tmpValue = tmpValue & 0x00ff;
2673 else
2674 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002675 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002676 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002677 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002678 priv->EEPROMTxPowerLevelOFDM24G[i] = (u8) tmpValue;
2679 RT_TRACE(COMP_EPROM, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK);
2680 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002681 } else if (priv->EEPROM_Def_Ver == 1) {
2682 if (bLoad_From_EEPOM) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002683 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1>>1));
2684 tmpValue = (tmpValue & 0xff00) >> 8;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002685 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002686 tmpValue = 0x10;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002687 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002688 priv->EEPROMTxPowerLevelCCK_V1[0] = (u8)tmpValue;
2689
2690 if (bLoad_From_EEPOM)
2691 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_CCK_V1 + 2)>>1);
2692 else
2693 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002694 *((u16 *)(&priv->EEPROMTxPowerLevelCCK_V1[1])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002695 if (bLoad_From_EEPOM)
2696 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1>>1));
2697 else
2698 tmpValue = 0x1010;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002699 *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[0])) = tmpValue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002700 if (bLoad_From_EEPOM)
2701 tmpValue = eprom_read(dev, (EEPROM_TxPwIndex_OFDM_24G_V1+2)>>1);
2702 else
2703 tmpValue = 0x10;
2704 priv->EEPROMTxPowerLevelOFDM24G[2] = (u8)tmpValue;
2705 }//endif EEPROM_Def_Ver == 1
2706
2707 //update HAL variables
2708 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002709 for (i = 0; i < 14; i++) {
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002710 if (i <= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002711 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[0];
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002712 else if (i >= 4 && i <= 9)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002713 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[1];
2714 else
2715 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[2];
2716 }
2717
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002718 for (i = 0; i < 14; i++) {
2719 if (priv->EEPROM_Def_Ver == 0) {
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002720 if (i <= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002721 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[0] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002722 else if (i >= 4 && i <= 9)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002723 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK;
2724 else
2725 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelOFDM24G[2] + (priv->EEPROMTxPowerLevelCCK - priv->EEPROMTxPowerLevelOFDM24G[1]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002726 } else if (priv->EEPROM_Def_Ver == 1) {
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002727 if (i <= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002728 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[0];
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03002729 else if (i >= 4 && i <= 9)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002730 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[1];
2731 else
2732 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK_V1[2];
2733 }
2734 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02002735 priv->TxPowerDiff = priv->EEPROMPwDiff;
2736// Antenna B gain offset to antenna A, bit0~3
2737 priv->AntennaTxPwDiff[0] = (priv->EEPROMTxPowerDiff & 0xf);
2738 // Antenna C gain offset to antenna A, bit4~7
2739 priv->AntennaTxPwDiff[1] = ((priv->EEPROMTxPowerDiff & 0xf0)>>4);
2740 // CrystalCap, bit12~15
2741 priv->CrystalCap = priv->EEPROMCrystalCap;
2742 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
2743 // 92U does not enable TX power tracking.
2744 priv->ThermalMeter[0] = priv->EEPROMThermalMeter;
2745 }//end if VersionID == VERSION_819xU_A
2746
2747//added by vivi, for dlink led, 20080416
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002748 switch (priv->eeprom_CustomerID) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002749 case EEPROM_CID_RUNTOP:
2750 priv->CustomerID = RT_CID_819x_RUNTOP;
2751 break;
2752
2753 case EEPROM_CID_DLINK:
2754 priv->CustomerID = RT_CID_DLINK;
2755 break;
2756
2757 default:
2758 priv->CustomerID = RT_CID_DEFAULT;
2759 break;
2760
2761 }
2762
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002763 switch (priv->CustomerID) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002764 case RT_CID_819x_RUNTOP:
2765 priv->LedStrategy = SW_LED_MODE2;
2766 break;
2767
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02002768 case RT_CID_DLINK:
Jerry Chuang8fc85982009-11-03 07:17:11 -02002769 priv->LedStrategy = SW_LED_MODE4;
2770 break;
2771
2772 default:
2773 priv->LedStrategy = SW_LED_MODE0;
2774 break;
2775
2776 }
2777
2778
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002779 if (priv->rf_type == RF_1T2R) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002780 RT_TRACE(COMP_EPROM, "\n1T2R config\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002781 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002782 RT_TRACE(COMP_EPROM, "\n2T4R config\n");
2783 }
2784
2785 // 2008/01/16 MH We can only know RF type in the function. So we have to init
2786 // DIG RATR table again.
2787 init_rate_adaptive(dev);
2788 //we need init DIG RATR table here again.
2789
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002790 RT_TRACE(COMP_EPROM, "<===========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002791 return;
2792}
2793
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002794short rtl8192_get_channel_map(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002795{
2796 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002797 if (priv->ChannelPlan > COUNTRY_CODE_GLOBAL_DOMAIN) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03002798 netdev_err(dev, "rtl8180_init: Error channel plan! Set to default.\n");
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002799 priv->ChannelPlan = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002800 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002801 RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002802
2803 rtl819x_set_channel_map(priv->ChannelPlan, priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002804 return 0;
2805}
2806
2807short rtl8192_init(struct net_device *dev)
2808{
2809
2810 struct r8192_priv *priv = ieee80211_priv(dev);
2811
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002812 memset(&(priv->stats), 0, sizeof(struct Stats));
2813 memset(priv->txqueue_to_outpipemap, 0, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002814#ifdef PIPE12
2815 {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03002816 int i = 0;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002817 u8 queuetopipe[] = {3, 2, 1, 0, 4, 8, 7, 6, 5};
2818 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002819 }
2820#else
2821 {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03002822 u8 queuetopipe[] = {3, 2, 1, 0, 4, 4, 0, 4, 4};
2823 memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002824 }
2825#endif
2826 rtl8192_init_priv_variable(dev);
2827 rtl8192_init_priv_lock(priv);
2828 rtl8192_init_priv_task(dev);
2829 rtl8192_get_eeprom_size(dev);
2830 rtl8192_read_eeprom_info(dev);
2831 rtl8192_get_channel_map(dev);
2832 init_hal_dm(dev);
2833 init_timer(&priv->watch_dog_timer);
2834 priv->watch_dog_timer.data = (unsigned long)dev;
2835 priv->watch_dog_timer.function = watch_dog_timer_callback;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002836 if (rtl8192_usb_initendpoints(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002837 DMESG("Endopoints initialization failed");
2838 return -ENOMEM;
2839 }
2840
Jerry Chuang8fc85982009-11-03 07:17:11 -02002841#ifdef DEBUG_EPROM
2842 dump_eprom(dev);
2843#endif
2844 return 0;
2845}
2846
2847/******************************************************************************
2848 *function: This function actually only set RRSR, RATR and BW_OPMODE registers
2849 * not to do all the hw config as its name says
2850 * input: net_device dev
2851 * output: none
2852 * return: none
2853 * notice: This part need to modified according to the rate set we filtered
2854 * ****************************************************************************/
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002855void rtl8192_hwconfig(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002856{
2857 u32 regRATR = 0, regRRSR = 0;
2858 u8 regBwOpMode = 0, regTmp = 0;
2859 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002860 u32 ratr_value = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002861
2862// Set RRSR, RATR, and BW_OPMODE registers
2863 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002864 switch (priv->ieee80211->mode) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002865 case WIRELESS_MODE_B:
2866 regBwOpMode = BW_OPMODE_20MHZ;
2867 regRATR = RATE_ALL_CCK;
2868 regRRSR = RATE_ALL_CCK;
2869 break;
2870 case WIRELESS_MODE_A:
2871 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
2872 regRATR = RATE_ALL_OFDM_AG;
2873 regRRSR = RATE_ALL_OFDM_AG;
2874 break;
2875 case WIRELESS_MODE_G:
2876 regBwOpMode = BW_OPMODE_20MHZ;
2877 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2878 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2879 break;
2880 case WIRELESS_MODE_AUTO:
2881#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002882 if (Adapter->bInHctTest) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02002883 regBwOpMode = BW_OPMODE_20MHZ;
2884 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2885 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2886 }
2887 else
2888#endif
2889 {
2890 regBwOpMode = BW_OPMODE_20MHZ;
2891 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2892 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2893 }
2894 break;
2895 case WIRELESS_MODE_N_24G:
2896 // It support CCK rate by default.
2897 // CCK rate will be filtered out only when associated AP does not support it.
2898 regBwOpMode = BW_OPMODE_20MHZ;
2899 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2900 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2901 break;
2902 case WIRELESS_MODE_N_5G:
2903 regBwOpMode = BW_OPMODE_5G;
2904 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2905 regRRSR = RATE_ALL_OFDM_AG;
2906 break;
2907 }
2908
2909 write_nic_byte(dev, BW_OPMODE, regBwOpMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002910 ratr_value = regRATR;
2911 if (priv->rf_type == RF_1T2R)
Jerry Chuang8fc85982009-11-03 07:17:11 -02002912 ratr_value &= ~(RATE_ALL_OFDM_2SS);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002913 write_nic_dword(dev, RATR0, ratr_value);
2914 write_nic_byte(dev, UFWP, 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002915 regTmp = read_nic_byte(dev, 0x313);
2916 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
2917 write_nic_dword(dev, RRSR, regRRSR);
2918
2919 //
2920 // Set Retry Limit here
2921 //
2922 write_nic_word(dev, RETRY_LIMIT,
2923 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT | \
2924 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
2925 // Set Contention Window here
2926
2927 // Set Tx AGC
2928
2929 // Set Tx Antenna including Feedback control
2930
2931 // Set Auto Rate fallback control
2932
2933
2934}
2935
2936
2937//InitializeAdapter and PhyCfg
2938bool rtl8192_adapter_start(struct net_device *dev)
2939{
2940 struct r8192_priv *priv = ieee80211_priv(dev);
2941 u32 dwRegRead = 0;
2942 bool init_status = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03002943 u8 SECR_value = 0x0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002944 RT_TRACE(COMP_INIT, "====>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002945 priv->Rf_Mode = RF_OP_By_SW_3wire;
2946 //for ASIC power on sequence
2947 write_nic_byte_E(dev, 0x5f, 0x80);
2948 mdelay(50);
2949 write_nic_byte_E(dev, 0x5f, 0xf0);
2950 write_nic_byte_E(dev, 0x5d, 0x00);
2951 write_nic_byte_E(dev, 0x5e, 0x80);
2952 write_nic_byte(dev, 0x17, 0x37);
2953 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002954 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
2955 //config CPUReset Register
2956 //Firmware Reset or not?
2957 dwRegRead = read_nic_dword(dev, CPU_GEN);
2958 if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
2959 dwRegRead |= CPU_GEN_SYSTEM_RESET; //do nothing here?
2960 else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
2961 dwRegRead |= CPU_GEN_FIRMWARE_RESET;
2962 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002963 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __func__, priv->pFirmware->firmware_status);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002964
2965 write_nic_dword(dev, CPU_GEN, dwRegRead);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002966 //config BB.
2967 rtl8192_BBConfig(dev);
2968
Jerry Chuang8fc85982009-11-03 07:17:11 -02002969 //Loopback mode or not
2970 priv->LoopbackMode = RTL819xU_NO_LOOPBACK;
Jerry Chuang8fc85982009-11-03 07:17:11 -02002971
2972 dwRegRead = read_nic_dword(dev, CPU_GEN);
2973 if (priv->LoopbackMode == RTL819xU_NO_LOOPBACK)
2974 dwRegRead = ((dwRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
2975 else if (priv->LoopbackMode == RTL819xU_MAC_LOOPBACK)
2976 dwRegRead |= CPU_CCK_LOOPBACK;
2977 else
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03002978 RT_TRACE(COMP_ERR, "Serious error in %s(): wrong loopback mode setting(%d)\n", __func__, priv->LoopbackMode);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002979
2980 write_nic_dword(dev, CPU_GEN, dwRegRead);
2981
2982 //after reset cpu, we need wait for a seconds to write in register.
2983 udelay(500);
2984
2985 //xiong add for new bitfile:usb suspend reset pin set to 1. //do we need?
2986 write_nic_byte_E(dev, 0x5f, (read_nic_byte_E(dev, 0x5f)|0x20));
2987
2988 //Set Hardware
2989 rtl8192_hwconfig(dev);
2990
2991 //turn on Tx/Rx
2992 write_nic_byte(dev, CMDR, CR_RE|CR_TE);
2993
2994 //set IDR0 here
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03002995 write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
2996 write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02002997
2998 //set RCR
2999 write_nic_dword(dev, RCR, priv->ReceiveConfig);
3000
3001 //Initialize Number of Reserved Pages in Firmware Queue
3002 write_nic_dword(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << RSVD_FW_QUEUE_PAGE_BK_SHIFT |\
3003 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT | \
3004 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT | \
3005 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
3006 write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT |\
3007 NUM_OF_PAGE_IN_FW_QUEUE_CMD << RSVD_FW_QUEUE_PAGE_CMD_SHIFT);
3008 write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW| \
3009 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT
Jerry Chuang8fc85982009-11-03 07:17:11 -02003010 );
3011 write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
3012
3013 //Set AckTimeout
3014 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
3015 write_nic_byte(dev, ACK_TIMEOUT, 0x30);
3016
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003017 if (priv->ResetProgress == RESET_TYPE_NORESET)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003018 rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003019 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003020 CamResetAllEntry(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003021 SECR_value |= SCR_TxEncEnable;
3022 SECR_value |= SCR_RxDecEnable;
3023 SECR_value |= SCR_NoSKMC;
3024 write_nic_byte(dev, SECR, SECR_value);
3025 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003026
3027 //Beacon related
3028 write_nic_word(dev, ATIMWND, 2);
3029 write_nic_word(dev, BCN_INTERVAL, 100);
3030
Jerry Chuang8fc85982009-11-03 07:17:11 -02003031#define DEFAULT_EDCA 0x005e4332
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003032 {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003033 int i;
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003034 for (i = 0; i < QOS_QUEUE_NUM; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003035 write_nic_dword(dev, WDCAPARA_ADD[i], DEFAULT_EDCA);
3036 }
3037#ifdef USB_RX_AGGREGATION_SUPPORT
3038 //3 For usb rx firmware aggregation control
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003039 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003040 u32 ulValue;
3041 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
3042 ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
3043 (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
3044 /*
3045 * If usb rx firmware aggregation is enabled,
3046 * when anyone of three threshold conditions above is reached,
3047 * firmware will send aggregated packet to driver.
3048 */
3049 write_nic_dword(dev, 0x1a8, ulValue);
3050 priv->bCurrentRxAggrEnable = true;
3051 }
3052#endif
3053
3054 rtl8192_phy_configmac(dev);
3055
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003056 if (priv->card_8192_version == (u8) VERSION_819xU_A) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003057 rtl8192_phy_getTxPower(dev);
3058 rtl8192_phy_setTxPower(dev, priv->chan);
3059 }
3060
3061 //Firmware download
3062 init_status = init_firmware(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003063 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003064 RT_TRACE(COMP_ERR, "ERR!!! %s(): Firmware download is failed\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003065 return init_status;
3066 }
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003067 RT_TRACE(COMP_INIT, "%s():after firmware download\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003068 //
3069#ifdef TO_DO_LIST
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003070if (Adapter->ResetProgress == RESET_TYPE_NORESET) {
3071 if (pMgntInfo->RegRfOff == TRUE) { // User disable RF via registry.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003072 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
3073 MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003074 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003075 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003076 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003077 } else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { // H/W or S/W RF OFF before sleep.
Jerry Chuang8fc85982009-11-03 07:17:11 -02003078 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", pMgntInfo->RfOffReason));
3079 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003080 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003081 pHalData->eRFPowerState = eRfOn;
3082 pMgntInfo->RfOffReason = 0;
3083 RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): RF is on ----------\n"));
3084 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003085 } else {
3086 if (pHalData->eRFPowerState == eRfOff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003087 MgntActSet_RF_State(Adapter, eRfOff, pMgntInfo->RfOffReason);
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07003088 // Those actions will be discard in MgntActSet_RF_State because of the same state
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003089 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003090 PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
3091 }
3092 }
3093#endif
3094 //config RF.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003095 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003096 rtl8192_phy_RFConfig(dev);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003097 RT_TRACE(COMP_INIT, "%s():after phy RF config\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003098 }
3099
3100
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003101 if (priv->ieee80211->FwRWRF)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003102 // We can force firmware to do RF-R/W
3103 priv->Rf_Mode = RF_OP_By_FW;
3104 else
3105 priv->Rf_Mode = RF_OP_By_SW_3wire;
3106
3107
3108 rtl8192_phy_updateInitGain(dev);
3109 /*--set CCK and OFDM Block "ON"--*/
3110 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
3111 rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
3112
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003113 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003114 //if D or C cut
3115 u8 tmpvalue = read_nic_byte(dev, 0x301);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003116 if (tmpvalue == 0x03) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003117 priv->bDcut = TRUE;
3118 RT_TRACE(COMP_POWER_TRACKING, "D-cut\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003119 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003120 priv->bDcut = FALSE;
3121 RT_TRACE(COMP_POWER_TRACKING, "C-cut\n");
3122 }
3123 dm_initialize_txpower_tracking(dev);
3124
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003125 if (priv->bDcut == TRUE) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003126 u32 i, TempCCk;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003127 u32 tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003128 for (i = 0; i < TxBBGainTableLength; i++) {
3129 if (tmpRegA == priv->txbbgain_table[i].txbbgain_value) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003130 priv->rfa_txpowertrackingindex = (u8)i;
3131 priv->rfa_txpowertrackingindex_real = (u8)i;
3132 priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003133 break;
3134 }
3135 }
3136
3137 TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
3138
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003139 for (i = 0; i < CCKTxBBGainTableLength; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003140
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003141 if (TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0]) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003142 priv->cck_present_attentuation_20Mdefault = (u8) i;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003143 break;
3144 }
3145 }
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003146 priv->cck_present_attentuation_40Mdefault = 0;
3147 priv->cck_present_attentuation_difference = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003148 priv->cck_present_attentuation = priv->cck_present_attentuation_20Mdefault;
3149
Jerry Chuang8fc85982009-11-03 07:17:11 -02003150 }
3151 }
3152 write_nic_byte(dev, 0x87, 0x0);
3153
3154
Jerry Chuang8fc85982009-11-03 07:17:11 -02003155 return init_status;
3156}
3157
3158/* this configures registers for beacon tx and enables it via
3159 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
3160 * be used to stop beacon transmission
3161 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02003162/***************************************************************************
3163 -------------------------------NET STUFF---------------------------
3164***************************************************************************/
3165
3166static struct net_device_stats *rtl8192_stats(struct net_device *dev)
3167{
3168 struct r8192_priv *priv = ieee80211_priv(dev);
3169
3170 return &priv->ieee80211->stats;
3171}
3172
3173bool
3174HalTxCheckStuck819xUsb(
3175 struct net_device *dev
3176 )
3177{
3178 struct r8192_priv *priv = ieee80211_priv(dev);
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003179 u16 RegTxCounter = read_nic_word(dev, 0x128);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003180 bool bStuck = FALSE;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003181 RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", __func__, RegTxCounter, priv->TxCounter);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003182 if (priv->TxCounter == RegTxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003183 bStuck = TRUE;
3184
3185 priv->TxCounter = RegTxCounter;
3186
3187 return bStuck;
3188}
3189
3190/*
3191* <Assumption: RT_TX_SPINLOCK is acquired.>
3192* First added: 2006.11.19 by emily
3193*/
3194RESET_TYPE
3195TxCheckStuck(struct net_device *dev)
3196{
3197 struct r8192_priv *priv = ieee80211_priv(dev);
3198 u8 QueueID;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003199 bool bCheckFwTxCnt = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003200
3201 //
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003202 // Decide such threshold according to current power save mode
Jerry Chuang8fc85982009-11-03 07:17:11 -02003203 //
3204
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003205 for (QueueID = 0; QueueID <= BEACON_QUEUE; QueueID ++) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003206 if (QueueID == TXCMD_QUEUE)
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01003207 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003208#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003209 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 -02003210#else
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003211 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 -02003212#endif
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003213 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003214
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01003215 bCheckFwTxCnt = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003216 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003217 if (bCheckFwTxCnt) {
3218 if (HalTxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003219 RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
3220 return RESET_TYPE_SILENT;
3221 }
3222 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003223 return RESET_TYPE_NORESET;
3224}
3225
3226bool
3227HalRxCheckStuck819xUsb(struct net_device *dev)
3228{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003229 u16 RegRxCounter = read_nic_word(dev, 0x130);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003230 struct r8192_priv *priv = ieee80211_priv(dev);
3231 bool bStuck = FALSE;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003232 static u8 rx_chk_cnt;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003233 RT_TRACE(COMP_RESET, "%s(): RegRxCounter is %d,RxCounter is %d\n", __func__, RegRxCounter, priv->RxCounter);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003234 // If rssi is small, we should check rx for long time because of bad rx.
3235 // or maybe it will continuous silent reset every 2 seconds.
3236 rx_chk_cnt++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003237 if (priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003238 rx_chk_cnt = 0; //high rssi, check rx stuck right now.
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003239 } else if (priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003240 ((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_40M) ||
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003241 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_20M))) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003242 if (rx_chk_cnt < 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003243 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003244 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003245 rx_chk_cnt = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003246 } else if (((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_40M) ||
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003247 (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_20M)) &&
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003248 priv->undecorated_smoothed_pwdb >= VeryLowRSSI) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003249 if (rx_chk_cnt < 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003250 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003251 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003252 rx_chk_cnt = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003253 } else {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003254 if (rx_chk_cnt < 8)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003255 return bStuck;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003256 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003257 rx_chk_cnt = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003258 }
3259
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003260 if (priv->RxCounter == RegRxCounter)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003261 bStuck = TRUE;
3262
3263 priv->RxCounter = RegRxCounter;
3264
3265 return bStuck;
3266}
3267
3268RESET_TYPE
3269RxCheckStuck(struct net_device *dev)
3270{
3271 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003272 bool bRxCheck = FALSE;
3273
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003274 if (priv->IrpPendingCount > 1)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003275 bRxCheck = TRUE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003276
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003277 if (bRxCheck) {
3278 if (HalRxCheckStuck819xUsb(dev)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003279 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
3280 return RESET_TYPE_SILENT;
3281 }
3282 }
3283 return RESET_TYPE_NORESET;
3284}
3285
3286
3287/**
3288* This function is called by Checkforhang to check whether we should ask OS to reset driver
3289*
3290* \param pAdapter The adapter context for this miniport
3291*
3292* Note:NIC with USB interface sholud not call this function because we cannot scan descriptor
3293* to judge whether there is tx stuck.
3294* Note: This function may be required to be rewrite for Vista OS.
3295* <<<Assumption: Tx spinlock has been acquired >>>
3296*
3297* 8185 and 8185b does not implement this function. This is added by Emily at 2006.11.24
3298*/
3299RESET_TYPE
3300rtl819x_ifcheck_resetornot(struct net_device *dev)
3301{
3302 struct r8192_priv *priv = ieee80211_priv(dev);
3303 RESET_TYPE TxResetType = RESET_TYPE_NORESET;
3304 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003305 RT_RF_POWER_STATE rfState;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003306
3307 rfState = priv->ieee80211->eRFPowerState;
3308
3309 TxResetType = TxCheckStuck(dev);
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003310 if (rfState != eRfOff ||
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003311 (priv->ieee80211->iw_mode != IW_MODE_ADHOC)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003312 // If driver is in the status of firmware download failure , driver skips RF initialization and RF is
3313 // in turned off state. Driver should check whether Rx stuck and do silent reset. And
3314 // if driver is in firmware download failure status, driver should initialize RF in the following
3315 // silent reset procedure Emily, 2008.01.21
3316
3317 // Driver should not check RX stuck in IBSS mode because it is required to
3318 // set Check BSSID in order to send beacon, however, if check BSSID is
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003319 // set, STA cannot hear any packet at all. Emily, 2008.04.12
Jerry Chuang8fc85982009-11-03 07:17:11 -02003320 RxResetType = RxCheckStuck(dev);
3321 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003322 if (TxResetType == RESET_TYPE_NORMAL || RxResetType == RESET_TYPE_NORMAL) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003323 return RESET_TYPE_NORMAL;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003324 } else if (TxResetType == RESET_TYPE_SILENT || RxResetType == RESET_TYPE_SILENT) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003325 RT_TRACE(COMP_RESET, "%s():silent reset\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003326 return RESET_TYPE_SILENT;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003327 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003328 return RESET_TYPE_NORESET;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003329 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003330
3331}
3332
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003333void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003334int _rtl8192_up(struct net_device *dev);
3335int rtl8192_close(struct net_device *dev);
3336
3337
3338
3339void
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003340CamRestoreAllEntry(struct net_device *dev)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003341{
3342 u8 EntryId = 0;
3343 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003344 u8 *MacAddr = priv->ieee80211->current_network.bssid;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003345
3346 static u8 CAM_CONST_ADDR[4][6] = {
3347 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3348 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
3349 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03003350 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003351 static u8 CAM_CONST_BROAD[] = {
3352 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003353
3354 RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
3355
3356
3357 if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40)||
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003358 (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003359
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003360 for (EntryId = 0; EntryId < 4; EntryId++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003361 MacAddr = CAM_CONST_ADDR[EntryId];
3362 setKey(dev,
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003363 EntryId,
Jerry Chuang8fc85982009-11-03 07:17:11 -02003364 EntryId,
3365 priv->ieee80211->pairwise_key_type,
3366 MacAddr,
3367 0,
3368 NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003369 }
3370
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003371 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003372
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003373 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003374 setKey(dev,
3375 4,
3376 0,
3377 priv->ieee80211->pairwise_key_type,
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003378 (u8 *)dev->dev_addr,
Jerry Chuang8fc85982009-11-03 07:17:11 -02003379 0,
3380 NULL);
3381 else
3382 setKey(dev,
3383 4,
3384 0,
3385 priv->ieee80211->pairwise_key_type,
3386 MacAddr,
3387 0,
3388 NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003389 } else if (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003390
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003391 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003392 setKey(dev,
3393 4,
3394 0,
3395 priv->ieee80211->pairwise_key_type,
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003396 (u8 *)dev->dev_addr,
Jerry Chuang8fc85982009-11-03 07:17:11 -02003397 0,
3398 NULL);
3399 else
3400 setKey(dev,
3401 4,
3402 0,
3403 priv->ieee80211->pairwise_key_type,
3404 MacAddr,
3405 0,
3406 NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003407 }
3408
3409
3410
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003411 if (priv->ieee80211->group_key_type == KEY_TYPE_TKIP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003412 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003413 for (EntryId = 1; EntryId < 4; EntryId++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003414 setKey(dev,
3415 EntryId,
3416 EntryId,
3417 priv->ieee80211->group_key_type,
3418 MacAddr,
3419 0,
3420 NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003421 }
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003422 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003423 setKey(dev,
3424 0,
3425 0,
3426 priv->ieee80211->group_key_type,
3427 CAM_CONST_ADDR[0],
3428 0,
3429 NULL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003430 } else if (priv->ieee80211->group_key_type == KEY_TYPE_CCMP) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003431 MacAddr = CAM_CONST_BROAD;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003432 for (EntryId = 1; EntryId < 4; EntryId++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003433 setKey(dev,
3434 EntryId ,
3435 EntryId,
3436 priv->ieee80211->group_key_type,
3437 MacAddr,
3438 0,
3439 NULL);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003440 }
3441
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003442 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003443 setKey(dev,
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003444 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02003445 0,
3446 priv->ieee80211->group_key_type,
3447 CAM_CONST_ADDR[0],
3448 0,
3449 NULL);
3450 }
3451}
3452//////////////////////////////////////////////////////////////
3453// This function is used to fix Tx/Rx stop bug temporarily.
3454// This function will do "system reset" to NIC when Tx or Rx is stuck.
3455// The method checking Tx/Rx stuck of this function is supported by FW,
3456// which reports Tx and Rx counter to register 0x128 and 0x130.
3457//////////////////////////////////////////////////////////////
3458void
3459rtl819x_ifsilentreset(struct net_device *dev)
3460{
Jerry Chuang8fc85982009-11-03 07:17:11 -02003461 struct r8192_priv *priv = ieee80211_priv(dev);
3462 u8 reset_times = 0;
3463 int reset_status = 0;
3464 struct ieee80211_device *ieee = priv->ieee80211;
3465
3466
3467 // 2007.07.20. If we need to check CCK stop, please uncomment this line.
3468 //bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
3469
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003470 if (priv->ResetProgress == RESET_TYPE_NORESET) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003471RESET_START:
3472
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003473 RT_TRACE(COMP_RESET, "=========>Reset progress!! \n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003474
3475 // Set the variable for reset.
3476 priv->ResetProgress = RESET_TYPE_SILENT;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003477 down(&priv->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003478 if (priv->up == 0) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003479 RT_TRACE(COMP_ERR, "%s():the driver is not up! return\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003480 up(&priv->wx_sem);
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003481 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003482 }
3483 priv->up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003484 RT_TRACE(COMP_RESET, "%s():======>start to down the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003485
3486 rtl8192_rtx_disable(dev);
3487 rtl8192_cancel_deferred_work(priv);
3488 deinit_hal_dm(dev);
3489 del_timer_sync(&priv->watch_dog_timer);
3490
3491 ieee->sync_scan_hurryup = 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003492 if (ieee->state == IEEE80211_LINKED) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003493 down(&ieee->wx_sem);
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003494 netdev_dbg(dev, "ieee->state is IEEE80211_LINKED\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02003495 ieee80211_stop_send_beacons(priv->ieee80211);
3496 del_timer_sync(&ieee->associate_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003497 cancel_delayed_work(&ieee->associate_retry_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003498 ieee80211_stop_scan(ieee);
3499 netif_carrier_off(dev);
3500 up(&ieee->wx_sem);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003501 } else {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003502 netdev_dbg(dev, "ieee->state is NOT LINKED\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003503 ieee80211_softmac_stop_protocol(priv->ieee80211);
3504 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003505 up(&priv->wx_sem);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003506 RT_TRACE(COMP_RESET, "%s():<==========down process is finished\n", __func__);
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003507 RT_TRACE(COMP_RESET, "%s():===========>start up the driver\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003508 reset_status = _rtl8192_up(dev);
3509
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003510 RT_TRACE(COMP_RESET, "%s():<===========up process is finished\n", __func__);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003511 if (reset_status == -EAGAIN) {
3512 if (reset_times < 3) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003513 reset_times++;
3514 goto RESET_START;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003515 } else {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003516 RT_TRACE(COMP_ERR, " ERR!!! %s(): Reset Failed!!\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003517 }
3518 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003519 ieee->is_silent_reset = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003520 EnableHWSecurityConfig8192(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003521 if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003522 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3523
Jerry Chuang8fc85982009-11-03 07:17:11 -02003524 queue_work(ieee->wq, &ieee->associate_complete_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003525
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003526 } else if (ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003527 ieee->set_chan(ieee->dev, ieee->current_network.channel);
3528 ieee->link_change(ieee->dev);
3529
Jerry Chuang8fc85982009-11-03 07:17:11 -02003530 ieee80211_start_send_beacons(ieee);
3531
3532 if (ieee->data_hard_resume)
3533 ieee->data_hard_resume(ieee->dev);
3534 netif_carrier_on(ieee->dev);
3535 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003536
3537 CamRestoreAllEntry(dev);
3538
3539 priv->ResetProgress = RESET_TYPE_NORESET;
3540 priv->reset_count++;
3541
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003542 priv->bForcedSilentReset = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003543 priv->bResetInProgress = false;
3544
3545 // For test --> force write UFWP.
3546 write_nic_byte(dev, UFWP, 1);
3547 RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003548 }
3549}
3550
3551void CAM_read_entry(
3552 struct net_device *dev,
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003553 u32 iIndex
Jerry Chuang8fc85982009-11-03 07:17:11 -02003554)
3555{
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003556 u32 target_command = 0;
3557 u32 target_content = 0;
3558 u8 entry_i = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003559 u32 ulStatus;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003560 s32 i = 100;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003561 for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003562 // polling bit, and No Write enable, and address
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003563 target_command = entry_i+CAM_CONTENT_COUNT*iIndex;
3564 target_command = target_command | BIT31;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003565
3566 //Check polling bit is clear
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003567 while ((i--) >= 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003568 ulStatus = read_nic_dword(dev, RWCAM);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003569 if (ulStatus & BIT31)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003570 continue;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003571 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02003572 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003573 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003574 write_nic_dword(dev, RWCAM, target_command);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003575 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x \n", target_command);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003576 target_content = read_nic_dword(dev, RCAMO);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003577 RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n", target_content);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003578 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003579 printk("\n");
3580}
3581
3582void rtl819x_update_rxcounts(
3583 struct r8192_priv *priv,
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003584 u32 *TotalRxBcnNum,
3585 u32 *TotalRxDataNum
Jerry Chuang8fc85982009-11-03 07:17:11 -02003586)
3587{
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003588 u16 SlotIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003589 u8 i;
3590
3591 *TotalRxBcnNum = 0;
3592 *TotalRxDataNum = 0;
3593
3594 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
3595 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
3596 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003597 for (i = 0; i < priv->ieee80211->LinkDetectInfo.SlotNum; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003598 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
3599 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
3600 }
3601}
3602
3603
Jerry Chuang8fc85982009-11-03 07:17:11 -02003604extern void rtl819x_watchdog_wqcallback(struct work_struct *work)
3605{
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003606 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
3607 struct r8192_priv *priv = container_of(dwork, struct r8192_priv, watch_dog_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003608 struct net_device *dev = priv->ieee80211->dev;
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003609 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003610 RESET_TYPE ResetType = RESET_TYPE_NORESET;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01003611 static u8 check_reset_cnt;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003612 bool bBusyTraffic = false;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003613 u32 TotalRxBcnNum = 0;
3614 u32 TotalRxDataNum = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003615
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003616 if (!priv->up)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003617 return;
3618 hal_dm_watchdog(dev);
3619
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003620 //to get busy traffic condition
3621 if (ieee->state == IEEE80211_LINKED) {
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003622 if (ieee->LinkDetectInfo.NumRxOkInPeriod > 666 ||
3623 ieee->LinkDetectInfo.NumTxOkInPeriod > 666 ) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003624 bBusyTraffic = true;
3625 }
3626 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
3627 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
3628 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
3629 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003630 //added by amy for AP roaming
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003631 if (priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->iw_mode == IW_MODE_INFRA) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003632
3633 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003634 if ((TotalRxBcnNum+TotalRxDataNum) == 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02003635 #ifdef TODO
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003636 if (rfState == eRfOff)
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003637 RT_TRACE(COMP_ERR, "========>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003638 #endif
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03003639 netdev_dbg(dev, "===>%s(): AP is power off, connect another one\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003640 priv->ieee80211->state = IEEE80211_ASSOCIATING;
3641 notify_wx_assoc_event(priv->ieee80211);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003642 RemovePeerTS(priv->ieee80211, priv->ieee80211->current_network.bssid);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003643 priv->ieee80211->link_change(dev);
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01003644 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003645
3646 }
3647 }
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003648 priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod = 0;
3649 priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003650 //check if reset the driver
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003651 if (check_reset_cnt++ >= 3) {
Sebastian Hahn35997ff2012-12-05 21:40:18 +01003652 ResetType = rtl819x_ifcheck_resetornot(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003653 check_reset_cnt = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003654 }
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003655 if ((priv->force_reset) || (priv->ResetProgress == RESET_TYPE_NORESET &&
Jerry Chuang8fc85982009-11-03 07:17:11 -02003656 (priv->bForcedSilentReset ||
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003657 (!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_SILENT)))) { // This is control by OID set in Pomelo
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003658 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 -02003659 rtl819x_ifsilentreset(dev);
3660 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003661 priv->force_reset = false;
3662 priv->bForcedSilentReset = false;
3663 priv->bResetInProgress = false;
3664 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
3665
3666}
3667
3668void watch_dog_timer_callback(unsigned long data)
3669{
3670 struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003671 queue_delayed_work(priv->priv_wq, &priv->watch_dog_wq, 0);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003672 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
Jerry Chuang8fc85982009-11-03 07:17:11 -02003673}
3674int _rtl8192_up(struct net_device *dev)
3675{
3676 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003677 int init_status = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003678 priv->up = 1;
3679 priv->ieee80211->ieee_up = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003680 RT_TRACE(COMP_INIT, "Bringing up iface");
3681 init_status = rtl8192_adapter_start(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003682 if (!init_status) {
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003683 RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization failed!\n", __func__);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003684 priv->up = priv->ieee80211->ieee_up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003685 return -EAGAIN;
3686 }
3687 RT_TRACE(COMP_INIT, "start adapter finished\n");
3688 rtl8192_rx_enable(dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003689 if (priv->ieee80211->state != IEEE80211_LINKED)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003690 ieee80211_softmac_start_protocol(priv->ieee80211);
3691 ieee80211_reset_queue(priv->ieee80211);
3692 watch_dog_timer_callback((unsigned long) dev);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003693 if (!netif_queue_stopped(dev))
Jerry Chuang8fc85982009-11-03 07:17:11 -02003694 netif_start_queue(dev);
3695 else
3696 netif_wake_queue(dev);
3697
3698 return 0;
3699}
3700
3701
3702int rtl8192_open(struct net_device *dev)
3703{
3704 struct r8192_priv *priv = ieee80211_priv(dev);
3705 int ret;
3706 down(&priv->wx_sem);
3707 ret = rtl8192_up(dev);
3708 up(&priv->wx_sem);
3709 return ret;
3710
3711}
3712
3713
3714int rtl8192_up(struct net_device *dev)
3715{
3716 struct r8192_priv *priv = ieee80211_priv(dev);
3717
3718 if (priv->up == 1) return -1;
3719
3720 return _rtl8192_up(dev);
3721}
3722
3723
3724int rtl8192_close(struct net_device *dev)
3725{
3726 struct r8192_priv *priv = ieee80211_priv(dev);
3727 int ret;
3728
3729 down(&priv->wx_sem);
3730
3731 ret = rtl8192_down(dev);
3732
3733 up(&priv->wx_sem);
3734
3735 return ret;
3736
3737}
3738
3739int rtl8192_down(struct net_device *dev)
3740{
3741 struct r8192_priv *priv = ieee80211_priv(dev);
3742 int i;
3743
3744 if (priv->up == 0) return -1;
3745
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003746 priv->up = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003747 priv->ieee80211->ieee_up = 0;
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003748 RT_TRACE(COMP_DOWN, "==========>%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003749/* FIXME */
3750 if (!netif_queue_stopped(dev))
3751 netif_stop_queue(dev);
3752
3753 rtl8192_rtx_disable(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003754
3755 /* Tx related queue release */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003756 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003757 skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003758 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003759 skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003760
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003761 for (i = 0; i < MAX_QUEUE_SIZE; i++)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003762 skb_queue_purge(&priv->ieee80211->skb_drv_aggQ [i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003763
Justin P. Mattock589b3d02012-04-30 07:41:36 -07003764 //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 -02003765 rtl8192_cancel_deferred_work(priv);
3766 deinit_hal_dm(dev);
3767 del_timer_sync(&priv->watch_dog_timer);
3768
3769
3770 ieee80211_softmac_stop_protocol(priv->ieee80211);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003771 memset(&priv->ieee80211->current_network, 0, offsetof(struct ieee80211_network, list));
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03003772 RT_TRACE(COMP_DOWN, "<==========%s()\n", __func__);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003773
3774 return 0;
3775}
3776
3777
3778void rtl8192_commit(struct net_device *dev)
3779{
3780 struct r8192_priv *priv = ieee80211_priv(dev);
3781 int reset_status = 0;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03003782 if (priv->up == 0) return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003783 priv->up = 0;
3784
3785 rtl8192_cancel_deferred_work(priv);
3786 del_timer_sync(&priv->watch_dog_timer);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003787
3788 ieee80211_softmac_stop_protocol(priv->ieee80211);
3789
Jerry Chuang8fc85982009-11-03 07:17:11 -02003790 rtl8192_rtx_disable(dev);
3791 reset_status = _rtl8192_up(dev);
3792
3793}
3794
Jerry Chuang8fc85982009-11-03 07:17:11 -02003795void rtl8192_restart(struct work_struct *work)
3796{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003797 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
3798 struct net_device *dev = priv->ieee80211->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003799
3800 down(&priv->wx_sem);
3801
3802 rtl8192_commit(dev);
3803
3804 up(&priv->wx_sem);
3805}
3806
3807static void r8192_set_multicast(struct net_device *dev)
3808{
3809 struct r8192_priv *priv = ieee80211_priv(dev);
3810 short promisc;
3811
Jerry Chuang8fc85982009-11-03 07:17:11 -02003812 /* FIXME FIXME */
3813
3814 promisc = (dev->flags & IFF_PROMISC) ? 1:0;
3815
3816 if (promisc != priv->promisc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02003817
3818 priv->promisc = promisc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003819}
3820
3821
3822int r8192_set_mac_adr(struct net_device *dev, void *mac)
3823{
3824 struct r8192_priv *priv = ieee80211_priv(dev);
3825 struct sockaddr *addr = mac;
3826
3827 down(&priv->wx_sem);
3828
3829 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
3830
Jerry Chuang8fc85982009-11-03 07:17:11 -02003831 schedule_work(&priv->reset_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003832 up(&priv->wx_sem);
3833
3834 return 0;
3835}
3836
3837/* based on ipw2200 driver */
3838int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3839{
3840 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3841 struct iwreq *wrq = (struct iwreq *)rq;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003842 int ret = -1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003843 struct ieee80211_device *ieee = priv->ieee80211;
3844 u32 key[4];
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003845 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
Jerry Chuang8fc85982009-11-03 07:17:11 -02003846 struct iw_point *p = &wrq->u.data;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03003847 struct ieee_param *ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003848
3849 down(&priv->wx_sem);
3850
3851
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003852 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003853 ret = -EINVAL;
3854 goto out;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003855 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003856
Julia Lawall32414872010-05-11 20:26:57 +02003857 ipw = kmalloc(p->length, GFP_KERNEL);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003858 if (ipw == NULL) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003859 ret = -ENOMEM;
3860 goto out;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003861 }
3862 if (copy_from_user(ipw, p->pointer, p->length)) {
3863 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003864 ret = -EFAULT;
3865 goto out;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003866 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003867
3868 switch (cmd) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003869 case RTL_IOCTL_WPA_SUPPLICANT:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003870 //parse here for HW security
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003871 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) {
3872 if (ipw->u.crypt.set_tx) {
3873 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003874 ieee->pairwise_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003875 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003876 ieee->pairwise_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003877 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003878 if (ipw->u.crypt.key_len == 13)
3879 ieee->pairwise_key_type = KEY_TYPE_WEP104;
3880 else if (ipw->u.crypt.key_len == 5)
3881 ieee->pairwise_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003882 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003883 ieee->pairwise_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003884 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003885
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003886 if (ieee->pairwise_key_type) {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003887 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003888 EnableHWSecurityConfig8192(dev);
3889 //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!
3890 //added by WB.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003891 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 +01003892 if (ieee->auth_mode != 2)
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003893 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 -02003894 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003895 } else {
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03003896 memcpy((u8 *)key, ipw->u.crypt.key, 16);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003897 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) {
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03003898 ieee->group_key_type = KEY_TYPE_CCMP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003899 } else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003900 ieee->group_key_type = KEY_TYPE_TKIP;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003901 } else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003902 if (ipw->u.crypt.key_len == 13)
3903 ieee->group_key_type = KEY_TYPE_WEP104;
3904 else if (ipw->u.crypt.key_len == 5)
3905 ieee->group_key_type = KEY_TYPE_WEP40;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003906 } else {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003907 ieee->group_key_type = KEY_TYPE_NA;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003908 }
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003909
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003910 if (ieee->group_key_type) {
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003911 setKey(dev,
3912 ipw->u.crypt.idx,
3913 ipw->u.crypt.idx, //KeyIndex
3914 ieee->group_key_type, //KeyType
3915 broadcast_addr, //MacAddr
3916 0, //DefaultKey
3917 key); //KeyContent
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003918 }
3919 }
3920 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02003921#ifdef JOHN_HWSEC_DEBUG
3922 //john's test 0711
3923 printk("@@ wrq->u pointer = ");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03003924 for (i = 0; i < wrq->u.data.length; i++) {
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03003925 if (i%10 == 0) printk("\n");
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03003926 printk("%8x|", ((u32 *)wrq->u.data.pointer)[i]);
Jerry Chuang8fc85982009-11-03 07:17:11 -02003927 }
3928 printk("\n");
3929#endif /*JOHN_HWSEC_DEBUG*/
3930 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
3931 break;
3932
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003933 default:
Jerry Chuang8fc85982009-11-03 07:17:11 -02003934 ret = -EOPNOTSUPP;
3935 break;
3936 }
3937 kfree(ipw);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02003938 ipw = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003939out:
3940 up(&priv->wx_sem);
3941 return ret;
3942}
3943
3944u8 HwRateToMRate90(bool bIsHT, u8 rate)
3945{
3946 u8 ret_rate = 0xff;
3947
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03003948 if (!bIsHT) {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003949 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003950 case DESC90_RATE1M: ret_rate = MGN_1M; break;
3951 case DESC90_RATE2M: ret_rate = MGN_2M; break;
3952 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
3953 case DESC90_RATE11M: ret_rate = MGN_11M; break;
3954 case DESC90_RATE6M: ret_rate = MGN_6M; break;
3955 case DESC90_RATE9M: ret_rate = MGN_9M; break;
3956 case DESC90_RATE12M: ret_rate = MGN_12M; break;
3957 case DESC90_RATE18M: ret_rate = MGN_18M; break;
3958 case DESC90_RATE24M: ret_rate = MGN_24M; break;
3959 case DESC90_RATE36M: ret_rate = MGN_36M; break;
3960 case DESC90_RATE48M: ret_rate = MGN_48M; break;
3961 case DESC90_RATE54M: ret_rate = MGN_54M; break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003962
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003963 default:
3964 ret_rate = 0xff;
3965 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
3966 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003967 }
3968
3969 } else {
Xenia Ragiadakouad638452013-05-12 03:15:08 +03003970 switch (rate) {
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003971 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
3972 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
3973 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
3974 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
3975 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
3976 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
3977 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
3978 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
3979 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
3980 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
3981 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
3982 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
3983 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
3984 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
3985 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
3986 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
3987 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003988
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003989 default:
3990 ret_rate = 0xff;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03003991 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
Sebastian Hahn24fbe872012-12-05 21:40:22 +01003992 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02003993 }
3994 }
3995
3996 return ret_rate;
3997}
3998
3999/**
4000 * Function: UpdateRxPktTimeStamp
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004001 * Overview: Record the TSF time stamp when receiving a packet
Jerry Chuang8fc85982009-11-03 07:17:11 -02004002 *
4003 * Input:
4004 * PADAPTER Adapter
4005 * PRT_RFD pRfd,
4006 *
4007 * Output:
4008 * PRT_RFD pRfd
4009 * (pRfd->Status.TimeStampHigh is updated)
4010 * (pRfd->Status.TimeStampLow is updated)
4011 * Return:
4012 * None
4013 */
Xenia Ragiadakoue6367212013-05-23 05:14:46 +03004014void UpdateRxPktTimeStamp8190(struct net_device *dev, struct ieee80211_rx_stats *stats)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004015{
4016 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4017
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004018 if (stats->bIsAMPDU && !stats->bFirstMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004019 stats->mac_time[0] = priv->LastRxDescTSFLow;
4020 stats->mac_time[1] = priv->LastRxDescTSFHigh;
4021 } else {
4022 priv->LastRxDescTSFLow = stats->mac_time[0];
4023 priv->LastRxDescTSFHigh = stats->mac_time[1];
4024 }
4025}
4026
4027//by amy 080606
4028
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004029long rtl819x_translate_todbm(u8 signal_strength_index)// 0-100 index.
Jerry Chuang8fc85982009-11-03 07:17:11 -02004030{
4031 long signal_power; // in dBm.
4032
4033 // Translate to dBm (x=0.5y-95).
4034 signal_power = (long)((signal_strength_index + 1) >> 1);
4035 signal_power -= 95;
4036
4037 return signal_power;
4038}
4039
4040
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004041/* 2008/01/22 MH We can not declare RSSI/EVM total value of sliding window to
Jerry Chuang8fc85982009-11-03 07:17:11 -02004042 be a local static. Otherwise, it may increase when we return from S3/S4. The
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004043 value will be kept in memory or disk. Declare the value in the adaptor
4044 and it will be reinitialized when returned from S3/S4. */
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004045void 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 -02004046{
4047 bool bcheck = false;
4048 u8 rfpath;
4049 u32 nspatial_stream, tmp_val;
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01004050 static u32 slide_rssi_index, slide_rssi_statistics;
4051 static u32 slide_evm_index, slide_evm_statistics;
4052 static u32 last_rssi, last_evm;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004053
Sebastian Hahnde13a3d2012-12-05 21:40:23 +01004054 static u32 slide_beacon_adc_pwdb_index, slide_beacon_adc_pwdb_statistics;
4055 static u32 last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004056
4057 struct ieee80211_hdr_3addr *hdr;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004058 u16 sc;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004059 unsigned int frag, seq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004060 hdr = (struct ieee80211_hdr_3addr *)buffer;
4061 sc = le16_to_cpu(hdr->seq_ctl);
4062 frag = WLAN_GET_SEQ_FRAG(sc);
4063 seq = WLAN_GET_SEQ_SEQ(sc);
4064 //cosa add 04292008 to record the sequence number
4065 pcurrent_stats->Seq_Num = seq;
4066 //
4067 // Check whether we should take the previous packet into accounting
4068 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004069 if (!pprevious_stats->bIsAMPDU) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004070 // if previous packet is not aggregated packet
4071 bcheck = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004072 }
4073
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004074 if (slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004075 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
4076 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
4077 priv->stats.slide_rssi_total -= last_rssi;
4078 }
4079 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
4080
4081 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004082 if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004083 slide_rssi_index = 0;
4084
4085 // <1> Showed on UI for user, in dbm
4086 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
4087 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
4088 pcurrent_stats->rssi = priv->stats.signal_strength;
4089 //
4090 // If the previous packet does not match the criteria, neglect it
4091 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004092 if (!pprevious_stats->bPacketMatchBSSID) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004093 if (!pprevious_stats->bToSelfBA)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004094 return;
4095 }
4096
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004097 if (!bcheck)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004098 return;
4099
4100
4101 //rtl8190_process_cck_rxpathsel(priv,pprevious_stats);//only rtl8190 supported
4102
4103 //
4104 // Check RSSI
4105 //
4106 priv->stats.num_process_phyinfo++;
4107
4108 /* record the general signal strength to the sliding window. */
4109
4110
4111 // <2> Showed on UI for engineering
4112 // hardware does not provide rssi information for each rf path in CCK
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004113 if (!pprevious_stats->bIsCCK && (pprevious_stats->bPacketToSelf || pprevious_stats->bToSelfBA)) {
4114 for (rfpath = RF90_PATH_A; rfpath < priv->NumTotalRFPath; rfpath++) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004115 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
4116 continue;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004117
4118 //Fixed by Jacken 2008-03-20
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004119 if (priv->stats.rx_rssi_percentage[rfpath] == 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004120 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004121 if (pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath]) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004122 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004123 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Jerry Chuang8fc85982009-11-03 07:17:11 -02004124 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
4125 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004126 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004127 priv->stats.rx_rssi_percentage[rfpath] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004128 ((priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
Jerry Chuang8fc85982009-11-03 07:17:11 -02004129 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
4130 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004131 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 -02004132 }
4133 }
4134
4135
4136 //
4137 // Check PWDB.
4138 //
4139 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
4140 pprevious_stats->bIsCCK? "CCK": "OFDM",
4141 pprevious_stats->RxPWDBAll);
4142
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004143 if (pprevious_stats->bPacketBeacon) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004144/* record the beacon pwdb to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004145 if (slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004146 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
4147 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
4148 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004149 }
4150 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
4151 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004152 slide_beacon_adc_pwdb_index++;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004153 if (slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004154 slide_beacon_adc_pwdb_index = 0;
4155 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004156 if (pprevious_stats->RxPWDBAll >= 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004157 pprevious_stats->RxPWDBAll -= 3;
4158 }
4159
4160 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
4161 pprevious_stats->bIsCCK? "CCK": "OFDM",
4162 pprevious_stats->RxPWDBAll);
4163
4164
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004165 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004166 if (priv->undecorated_smoothed_pwdb < 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004167 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004168 if (pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004169 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004170 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
Jerry Chuang8fc85982009-11-03 07:17:11 -02004171 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
4172 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004173 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004174 priv->undecorated_smoothed_pwdb =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004175 (((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
Jerry Chuang8fc85982009-11-03 07:17:11 -02004176 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
4177 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004178
4179 }
4180
4181 //
4182 // Check EVM
4183 //
4184 /* record the general EVM to the sliding window. */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004185 if (pprevious_stats->SignalQuality) {
4186 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4187 if (slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004188 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
4189 last_evm = priv->stats.slide_evm[slide_evm_index];
4190 priv->stats.slide_evm_total -= last_evm;
4191 }
4192
4193 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
4194
4195 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004196 if (slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004197 slide_evm_index = 0;
4198
4199 // <1> Showed on UI for user, in percentage.
4200 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
4201 priv->stats.signal_quality = tmp_val;
4202 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
4203 priv->stats.last_signal_strength_inpercent = tmp_val;
4204 }
4205
4206 // <2> Showed on UI for engineering
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004207 if (pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) {
4208 for (nspatial_stream = 0; nspatial_stream < 2; nspatial_stream++) { // 2 spatial stream
4209 if (pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1) {
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004210 if (priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
Jerry Chuang8fc85982009-11-03 07:17:11 -02004211 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
Jerry Chuang8fc85982009-11-03 07:17:11 -02004212 priv->stats.rx_evm_percentage[nspatial_stream] =
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004213 ((priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
Jerry Chuang8fc85982009-11-03 07:17:11 -02004214 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
4215 }
4216 }
4217 }
4218 }
4219
4220
4221}
4222
4223/*-----------------------------------------------------------------------------
4224 * Function: rtl819x_query_rxpwrpercentage()
4225 *
4226 * Overview:
4227 *
4228 * Input: char antpower
4229 *
4230 * Output: NONE
4231 *
4232 * Return: 0-100 percentage
4233 *
4234 * Revised History:
4235 * When Who Remark
4236 * 05/26/2008 amy Create Version 0 porting from windows code.
4237 *
4238 *---------------------------------------------------------------------------*/
4239static u8 rtl819x_query_rxpwrpercentage(
4240 char antpower
4241 )
4242{
4243 if ((antpower <= -100) || (antpower >= 20))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004244 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004245 else if (antpower >= 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004246 return 100;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004247 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004248 return (100+antpower);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004249
4250} /* QueryRxPwrPercentage */
4251
4252static u8
4253rtl819x_evm_dbtopercentage(
4254 char value
4255 )
4256{
4257 char ret_val;
4258
4259 ret_val = value;
4260
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004261 if (ret_val >= 0)
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01004262 ret_val = 0;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004263 if (ret_val <= -33)
Sebastian Hahnfdc64a92012-12-06 12:23:03 +01004264 ret_val = -33;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004265 ret_val = 0 - ret_val;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004266 ret_val *= 3;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004267 if (ret_val == 99)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004268 ret_val = 100;
4269 return(ret_val);
4270}
4271//
4272// Description:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004273// We want good-looking for signal strength/quality
Jerry Chuang8fc85982009-11-03 07:17:11 -02004274// 2007/7/19 01:09, by cosa.
4275//
4276long
4277rtl819x_signal_scale_mapping(
4278 long currsig
4279 )
4280{
4281 long retsig;
4282
4283 // Step 1. Scale mapping.
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004284 if (currsig >= 61 && currsig <= 100)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004285 retsig = 90 + ((currsig - 60) / 4);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004286 else if (currsig >= 41 && currsig <= 60)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004287 retsig = 78 + ((currsig - 40) / 2);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004288 else if (currsig >= 31 && currsig <= 40)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004289 retsig = 66 + (currsig - 30);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004290 else if (currsig >= 21 && currsig <= 30)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004291 retsig = 54 + (currsig - 20);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004292 else if (currsig >= 5 && currsig <= 20)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004293 retsig = 42 + (((currsig - 5) * 2) / 3);
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004294 else if (currsig == 4)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004295 retsig = 36;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004296 else if (currsig == 3)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004297 retsig = 27;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004298 else if (currsig == 2)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004299 retsig = 18;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004300 else if (currsig == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004301 retsig = 9;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004302 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004303 retsig = currsig;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004304
4305 return retsig;
4306}
4307
4308static void rtl8192_query_rxphystatus(
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004309 struct r8192_priv *priv,
4310 struct ieee80211_rx_stats *pstats,
4311 rx_drvinfo_819x_usb *pdrvinfo,
4312 struct ieee80211_rx_stats *precord_stats,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004313 bool bpacket_match_bssid,
4314 bool bpacket_toself,
4315 bool bPacketBeacon,
4316 bool bToSelfBA
4317 )
4318{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004319 phy_sts_ofdm_819xusb_t *pofdm_buf;
4320 phy_sts_cck_819xusb_t *pcck_buf;
4321 phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004322 u8 *prxpkt;
4323 u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004324 char rx_pwr[4], rx_pwr_all = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004325 char rx_snrX, rx_evmX;
4326 u8 evm, pwdb_all;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004327 u32 RSSI, total_rssi = 0;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004328 u8 is_cck_rate = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004329 u8 rf_rx_num = 0;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004330 u8 sq;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004331
4332
4333 priv->stats.numqry_phystatus++;
4334
4335 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4336
4337 // Record it for next packet processing
4338 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4339 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4340 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004341 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004342 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4343 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4344
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004345 prxpkt = (u8 *)pdrvinfo;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004346
4347 /* Move pointer to the 16th bytes. Phy status start address. */
4348 prxpkt += sizeof(rx_drvinfo_819x_usb);
4349
4350 /* Initial the cck and ofdm buffer pointer */
4351 pcck_buf = (phy_sts_cck_819xusb_t *)prxpkt;
4352 pofdm_buf = (phy_sts_ofdm_819xusb_t *)prxpkt;
4353
4354 pstats->RxMIMOSignalQuality[0] = -1;
4355 pstats->RxMIMOSignalQuality[1] = -1;
4356 precord_stats->RxMIMOSignalQuality[0] = -1;
4357 precord_stats->RxMIMOSignalQuality[1] = -1;
4358
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004359 if (is_cck_rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004360 //
4361 // (1)Hardware does not provide RSSI for CCK
4362 //
4363
4364 //
4365 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4366 //
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004367 u8 report;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004368
4369 priv->stats.numqry_phystatusCCK++;
4370
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004371 if (!priv->bCckHighPower) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004372 report = pcck_buf->cck_agc_rpt & 0xc0;
4373 report = report>>6;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004374 switch (report) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004375 //Fixed by Jacken from Bryant 2008-03-20
4376 //Original value is -38 , -26 , -14 , -2
4377 //Fixed value is -35 , -23 , -11 , 6
4378 case 0x3:
4379 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4380 break;
4381 case 0x2:
4382 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4383 break;
4384 case 0x1:
4385 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4386 break;
4387 case 0x0:
4388 rx_pwr_all = 6 - (pcck_buf->cck_agc_rpt & 0x3e);
4389 break;
4390 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004391 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004392 report = pcck_buf->cck_agc_rpt & 0x60;
4393 report = report>>5;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004394 switch (report) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004395 case 0x3:
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004396 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004397 break;
4398 case 0x2:
4399 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4400 break;
4401 case 0x1:
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004402 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004403 break;
4404 case 0x0:
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004405 rx_pwr_all = 6 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004406 break;
4407 }
4408 }
4409
4410 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4411 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4412 pstats->RecvSignalPower = pwdb_all;
4413
4414 //
4415 // (3) Get Signal Quality (EVM)
4416 //
Jerry Chuang8fc85982009-11-03 07:17:11 -02004417
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004418 if (pstats->RxPWDBAll > 40) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004419 sq = 100;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004420 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004421 sq = pcck_buf->sq_rpt;
4422
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004423 if (pcck_buf->sq_rpt > 64)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004424 sq = 0;
4425 else if (pcck_buf->sq_rpt < 20)
4426 sq = 100;
4427 else
4428 sq = ((64-sq) * 100) / 44;
4429 }
4430 pstats->SignalQuality = precord_stats->SignalQuality = sq;
4431 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
4432 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004433
4434 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004435 priv->stats.numqry_phystatusHT++;
4436 //
4437 // (1)Get RSSI for HT rate
4438 //
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004439 for (i = RF90_PATH_A; i < priv->NumTotalRFPath; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004440 // 2008/01/30 MH we will judge RF RX path now.
4441 if (priv->brfpath_rxenable[i])
4442 rf_rx_num++;
4443 else
4444 continue;
4445
4446 if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, i))
4447 continue;
4448
4449 //Fixed by Jacken from Bryant 2008-03-20
4450 //Original value is 106
4451 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
4452
4453 //Get Rx snr value in DB
4454 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
4455 rx_snrX = (char)(tmp_rxsnr);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004456 rx_snrX /= 2;
4457 priv->stats.rxSNRdB[i] = (long)rx_snrX;
4458
4459 /* Translate DBM to percentage. */
4460 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
4461 total_rssi += RSSI;
4462
4463 /* Record Signal Strength for next packet */
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004464 pstats->RxMIMOSignalStrength[i] = (u8) RSSI;
4465 precord_stats->RxMIMOSignalStrength[i] = (u8) RSSI;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004466 }
4467
4468
4469 //
4470 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4471 //
4472 //Fixed by Jacken from Bryant 2008-03-20
4473 //Original value is 106
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004474 rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1)& 0x7f) -106;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004475 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4476
4477 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4478 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
4479
4480 //
4481 // (3)EVM of HT rate
4482 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004483 if (pdrvinfo->RxHT && pdrvinfo->RxRate >= DESC90_RATEMCS8 &&
4484 pdrvinfo->RxRate <= DESC90_RATEMCS15)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004485 max_spatial_stream = 2; //both spatial stream make sense
4486 else
4487 max_spatial_stream = 1; //only spatial stream 1 makes sense
4488
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004489 for (i = 0; i < max_spatial_stream; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004490 tmp_rxevm = pofdm_buf->rxevm_X[i];
4491 rx_evmX = (char)(tmp_rxevm);
4492
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004493 // Do not use shift operation like "rx_evmX >>= 1" because the compiler of free build environment
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004494 // will set the most significant bit to "zero" when doing shifting operation which may change a negative
Jerry Chuang8fc85982009-11-03 07:17:11 -02004495 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
4496 rx_evmX /= 2; //dbm
4497
4498 evm = rtl819x_evm_dbtopercentage(rx_evmX);
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004499 if (i == 0) // Fill value in RFD, Get the first spatial stream only
Jerry Chuang8fc85982009-11-03 07:17:11 -02004500 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
4501 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004502 }
4503
4504
4505 /* record rx statistics for debug */
4506 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
4507 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004508 if (pdrvinfo->BW) //40M channel
Jerry Chuang8fc85982009-11-03 07:17:11 -02004509 priv->stats.received_bwtype[1+prxsc->rxsc]++;
4510 else //20M channel
4511 priv->stats.received_bwtype[0]++;
4512 }
4513
4514 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
4515 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004516 if (is_cck_rate) {
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004517 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004518 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004519 // We can judge RX path number now.
4520 if (rf_rx_num != 0)
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004521 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi /= rf_rx_num)));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004522 }
4523} /* QueryRxPhyStatus8190Pci */
4524
4525void
4526rtl8192_record_rxdesc_forlateruse(
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004527 struct ieee80211_rx_stats *psrc_stats,
4528 struct ieee80211_rx_stats *ptarget_stats
Jerry Chuang8fc85982009-11-03 07:17:11 -02004529)
4530{
4531 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
4532 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
4533 ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
4534}
4535
4536
4537void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004538 struct ieee80211_rx_stats *pstats,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004539 rx_drvinfo_819x_usb *pdrvinfo)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004540{
4541 // TODO: We must only check packet for current MAC address. Not finish
4542 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004543 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004544 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4545 bool bpacket_match_bssid, bpacket_toself;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004546 bool bPacketBeacon = FALSE, bToSelfBA = FALSE;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004547 static struct ieee80211_rx_stats previous_stats;
4548 struct ieee80211_hdr_3addr *hdr;//by amy
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004549 u16 fc, type;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004550
4551 // Get Signal Quality for only RX data queue (but not command queue)
4552
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004553 u8 *tmp_buf;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004554 u8 *praddr;
4555
4556 /* Get MAC frame start address. */
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004557 tmp_buf = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004558
4559 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
4560 fc = le16_to_cpu(hdr->frame_ctl);
4561 type = WLAN_FC_GET_TYPE(fc);
4562 praddr = hdr->addr1;
4563
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004564 /* Check if the received packet is acceptable. */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004565 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03004566 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS)? hdr->addr2 : hdr->addr3))
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004567 && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004568 bpacket_toself = bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
4569
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004570 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004571 bPacketBeacon = true;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004572 if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK) {
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004573 if ((eqMacAddr(praddr, dev->dev_addr)))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004574 bToSelfBA = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004575 }
4576
Jerry Chuang8fc85982009-11-03 07:17:11 -02004577
4578
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004579 if (bpacket_match_bssid)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004580 priv->stats.numpacket_matchbssid++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004581 if (bpacket_toself)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004582 priv->stats.numpacket_toself++;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004583 //
4584 // Process PHY information for previous packet (RSSI/PWDB/EVM)
4585 //
4586 // Because phy information is contained in the last packet of AMPDU only, so driver
4587 // should process phy information of previous packet
4588 rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004589 rtl8192_query_rxphystatus(priv, pstats, pdrvinfo, &previous_stats, bpacket_match_bssid, bpacket_toself, bPacketBeacon, bToSelfBA);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004590 rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
4591
4592}
4593
4594/**
4595* Function: UpdateReceivedRateHistogramStatistics
Justin P. Mattock8ef3a7e2012-04-30 14:39:21 -07004596* Overview: Record the received data rate
Jerry Chuang8fc85982009-11-03 07:17:11 -02004597*
4598* Input:
Sebastian Hahn35997ff2012-12-05 21:40:18 +01004599* struct net_device *dev
Jerry Chuang8fc85982009-11-03 07:17:11 -02004600* struct ieee80211_rx_stats *stats
4601*
4602* Output:
4603*
4604* (priv->stats.ReceivedRateHistogram[] is updated)
4605* Return:
4606* None
4607*/
4608void
4609UpdateReceivedRateHistogramStatistics8190(
4610 struct net_device *dev,
4611 struct ieee80211_rx_stats *stats
4612 )
4613{
4614 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004615 u32 rcvType = 1; //0: Total, 1:OK, 2:CRC, 3:ICV
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004616 u32 rateIndex;
4617 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
Jerry Chuang8fc85982009-11-03 07:17:11 -02004618
4619
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004620 if (stats->bCRC)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004621 rcvType = 2;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004622 else if (stats->bICV)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004623 rcvType = 3;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004624
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004625 if (stats->bShortPreamble)
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02004626 preamble_guardinterval = 1;// short
4627 else
4628 preamble_guardinterval = 0;// long
Jerry Chuang8fc85982009-11-03 07:17:11 -02004629
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004630 switch (stats->rate) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004631 //
4632 // CCK rate
4633 //
4634 case MGN_1M: rateIndex = 0; break;
4635 case MGN_2M: rateIndex = 1; break;
4636 case MGN_5_5M: rateIndex = 2; break;
4637 case MGN_11M: rateIndex = 3; break;
4638 //
4639 // Legacy OFDM rate
4640 //
4641 case MGN_6M: rateIndex = 4; break;
4642 case MGN_9M: rateIndex = 5; break;
4643 case MGN_12M: rateIndex = 6; break;
4644 case MGN_18M: rateIndex = 7; break;
4645 case MGN_24M: rateIndex = 8; break;
4646 case MGN_36M: rateIndex = 9; break;
4647 case MGN_48M: rateIndex = 10; break;
4648 case MGN_54M: rateIndex = 11; break;
4649 //
4650 // 11n High throughput rate
4651 //
4652 case MGN_MCS0: rateIndex = 12; break;
4653 case MGN_MCS1: rateIndex = 13; break;
4654 case MGN_MCS2: rateIndex = 14; break;
4655 case MGN_MCS3: rateIndex = 15; break;
4656 case MGN_MCS4: rateIndex = 16; break;
4657 case MGN_MCS5: rateIndex = 17; break;
4658 case MGN_MCS6: rateIndex = 18; break;
4659 case MGN_MCS7: rateIndex = 19; break;
4660 case MGN_MCS8: rateIndex = 20; break;
4661 case MGN_MCS9: rateIndex = 21; break;
4662 case MGN_MCS10: rateIndex = 22; break;
4663 case MGN_MCS11: rateIndex = 23; break;
4664 case MGN_MCS12: rateIndex = 24; break;
4665 case MGN_MCS13: rateIndex = 25; break;
4666 case MGN_MCS14: rateIndex = 26; break;
4667 case MGN_MCS15: rateIndex = 27; break;
4668 default: rateIndex = 28; break;
4669 }
4670 priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
4671 priv->stats.received_rate_histogram[0][rateIndex]++; //total
4672 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
4673}
4674
4675
4676void query_rxdesc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats, bool bIsRxAggrSubframe)
4677{
4678 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004679 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004680 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004681 rx_drvinfo_819x_usb *driver_info = NULL;
4682
4683 //
4684 //Get Rx Descriptor Information
4685 //
4686#ifdef USB_RX_AGGREGATION_SUPPORT
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004687 if (bIsRxAggrSubframe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004688 rx_desc_819x_usb_aggr_subframe *desc = (rx_desc_819x_usb_aggr_subframe *)skb->data;
Xenia Ragiadakou3db37642013-05-22 18:22:38 +03004689 stats->Length = desc->Length;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004690 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
4691 stats->RxBufShift = 0; //RxBufShift = 2 in RxDesc, but usb didn't shift bytes in fact.
4692 stats->bICV = desc->ICV;
4693 stats->bCRC = desc->CRC32;
4694 stats->bHwError = stats->bCRC|stats->bICV;
4695 stats->Decrypted = !desc->SWDec;//RTL8190 set this bit to indicate that Hw does not decrypt packet
4696 } else
4697#endif
4698 {
4699 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
4700
4701 stats->Length = desc->Length;
4702 stats->RxDrvInfoSize = desc->RxDrvInfoSize;
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03004703 stats->RxBufShift = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004704 stats->bICV = desc->ICV;
4705 stats->bCRC = desc->CRC32;
4706 stats->bHwError = stats->bCRC|stats->bICV;
4707 //RTL8190 set this bit to indicate that Hw does not decrypt packet
4708 stats->Decrypted = !desc->SWDec;
4709 }
4710
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004711 if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004712 stats->bHwError = false;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004713 else
Jerry Chuang8fc85982009-11-03 07:17:11 -02004714 stats->bHwError = stats->bCRC|stats->bICV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004715
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004716 if (stats->Length < 24 || stats->Length > MAX_8192U_RX_SIZE)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004717 stats->bHwError |= 1;
4718 //
4719 //Get Driver Info
4720 //
4721 // TODO: Need to verify it on FGPA platform
4722 //Driver info are written to the RxBuffer following rx desc
4723 if (stats->RxDrvInfoSize != 0) {
4724 driver_info = (rx_drvinfo_819x_usb *)(skb->data + sizeof(rx_desc_819x_usb) + \
4725 stats->RxBufShift);
4726 /* unit: 0.5M */
4727 /* TODO */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004728 if (!stats->bHwError) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004729 u8 ret_rate;
4730 ret_rate = HwRateToMRate90(driver_info->RxHT, driver_info->RxRate);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004731 if (ret_rate == 0xff) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004732 // Abnormal Case: Receive CRC OK packet with Rx descriptor indicating non supported rate.
4733 // Special Error Handling here, 2008.05.16, by Emily
4734
4735 stats->bHwError = 1;
4736 stats->rate = MGN_1M; //Set 1M rate by default
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004737 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004738 stats->rate = ret_rate;
4739 }
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004740 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004741 stats->rate = 0x02;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004742 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02004743
4744 stats->bShortPreamble = driver_info->SPLCP;
4745
4746
4747 UpdateReceivedRateHistogramStatistics8190(dev, stats);
4748
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004749 stats->bIsAMPDU = (driver_info->PartAggr == 1);
4750 stats->bFirstMPDU = (driver_info->PartAggr == 1) && (driver_info->FirstAGGR == 1);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004751 stats->TimeStampLow = driver_info->TSFL;
4752 // xiong mask it, 070514
Jerry Chuang8fc85982009-11-03 07:17:11 -02004753
4754 UpdateRxPktTimeStamp8190(dev, stats);
4755
4756 //
4757 // Rx A-MPDU
4758 //
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004759 if (driver_info->FirstAGGR == 1 || driver_info->PartAggr == 1)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004760 RT_TRACE(COMP_RXDESC, "driver_info->FirstAGGR = %d, driver_info->PartAggr = %d\n",
4761 driver_info->FirstAGGR, driver_info->PartAggr);
4762
4763 }
4764
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004765 skb_pull(skb, sizeof(rx_desc_819x_usb));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004766 //
4767 // Get Total offset of MPDU Frame Body
4768 //
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004769 if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004770 stats->bShift = 1;
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004771 skb_pull(skb, stats->RxBufShift + stats->RxDrvInfoSize);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004772 }
4773
4774#ifdef USB_RX_AGGREGATION_SUPPORT
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004775 /* for the rx aggregated sub frame, the redundant space truly contained in the packet */
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004776 if (bIsRxAggrSubframe)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004777 skb_pull(skb, 8);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004778#endif
4779 /* for debug 2008.5.29 */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004780
4781 //added by vivi, for MP, 20080108
4782 stats->RxIs40MHzPacket = driver_info->BW;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004783 if (stats->RxDrvInfoSize != 0)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004784 TranslateRxSignalStuff819xUsb(skb, stats, driver_info);
4785
4786}
4787
4788u32 GetRxPacketShiftBytes819xUsb(struct ieee80211_rx_stats *Status, bool bIsRxAggrSubframe)
4789{
4790#ifdef USB_RX_AGGREGATION_SUPPORT
4791 if (bIsRxAggrSubframe)
4792 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
4793 + Status->RxBufShift + 8);
4794 else
4795#endif
4796 return (sizeof(rx_desc_819x_usb) + Status->RxDrvInfoSize
4797 + Status->RxBufShift);
4798}
4799
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004800void rtl8192_rx_nomal(struct sk_buff *skb)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004801{
4802 rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004803 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004804 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
4805 struct ieee80211_rx_stats stats = {
4806 .signal = 0,
4807 .noise = -98,
4808 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02004809 .freq = IEEE80211_24GHZ_BAND,
4810 };
4811 u32 rx_pkt_len = 0;
4812 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
4813 bool unicast_packet = false;
4814#ifdef USB_RX_AGGREGATION_SUPPORT
4815 struct sk_buff *agg_skb = NULL;
4816 u32 TotalLength = 0;
4817 u32 TempDWord = 0;
4818 u32 PacketLength = 0;
4819 u32 PacketOccupiedLendth = 0;
4820 u8 TempByte = 0;
4821 u32 PacketShiftBytes = 0;
4822 rx_desc_819x_usb_aggr_subframe *RxDescr = NULL;
4823 u8 PaddingBytes = 0;
4824 //add just for testing
4825 u8 testing;
4826
4827#endif
4828
4829 /* 20 is for ps-poll */
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004830 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004831#ifdef USB_RX_AGGREGATION_SUPPORT
4832 TempByte = *(skb->data + sizeof(rx_desc_819x_usb));
4833#endif
4834 /* first packet should not contain Rx aggregation header */
4835 query_rxdesc_status(skb, &stats, false);
4836 /* TODO */
4837 /* hardware related info */
4838#ifdef USB_RX_AGGREGATION_SUPPORT
4839 if (TempByte & BIT0) {
4840 agg_skb = skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004841 TotalLength = stats.Length - 4; /*sCrcLng*/
Jerry Chuang8fc85982009-11-03 07:17:11 -02004842 /* though the head pointer has passed this position */
4843 TempDWord = *(u32 *)(agg_skb->data - 4);
4844 PacketLength = (u16)(TempDWord & 0x3FFF); /*sCrcLng*/
4845 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004846 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004847 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, false);
4848 }
4849#endif
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004850 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004851 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4852
4853 rx_pkt_len = skb->len;
4854 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4855 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004856 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004857 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004858 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004859 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004860 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004861 /* unicast packet */
4862 unicast_packet = true;
4863 }
4864
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004865 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004866 dev_kfree_skb_any(skb);
4867 } else {
4868 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004869 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004870 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004871 }
4872#ifdef USB_RX_AGGREGATION_SUPPORT
4873 testing = 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004874 if (TotalLength > 0) {
4875 PacketOccupiedLendth = PacketLength + (PacketShiftBytes + 8);
4876 if ((PacketOccupiedLendth & 0xFF) != 0)
4877 PacketOccupiedLendth = (PacketOccupiedLendth & 0xFFFFFF00) + 256;
4878 PacketOccupiedLendth -= 8;
4879 TempDWord = PacketOccupiedLendth - PacketShiftBytes; /*- PacketLength */
4880 if (agg_skb->len > TempDWord)
4881 skb_pull(agg_skb, TempDWord);
4882 else
4883 agg_skb->len = 0;
4884
Xenia Ragiadakou204ecd32013-05-22 18:22:37 +03004885 while (agg_skb->len >= GetRxPacketShiftBytes819xUsb(&stats, true)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004886 u8 tmpCRC = 0, tmpICV = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004887 RxDescr = (rx_desc_819x_usb_aggr_subframe *)(agg_skb->data);
4888 tmpCRC = RxDescr->CRC32;
4889 tmpICV = RxDescr->ICV;
4890 memcpy(agg_skb->data, &agg_skb->data[44], 2);
4891 RxDescr->CRC32 = tmpCRC;
4892 RxDescr->ICV = tmpICV;
4893
4894 memset(&stats, 0, sizeof(struct ieee80211_rx_stats));
4895 stats.signal = 0;
4896 stats.noise = -98;
4897 stats.rate = 0;
4898 stats.freq = IEEE80211_24GHZ_BAND;
4899 query_rxdesc_status(agg_skb, &stats, true);
4900 PacketLength = stats.Length;
4901
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004902 if (PacketLength > agg_skb->len)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004903 break;
Justin P. Mattock589b3d02012-04-30 07:41:36 -07004904 /* Process the MPDU received */
Jerry Chuang8fc85982009-11-03 07:17:11 -02004905 skb = dev_alloc_skb(PacketLength);
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004906 memcpy(skb_put(skb, PacketLength), agg_skb->data, PacketLength);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004907 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4908
4909 rx_pkt_len = skb->len;
4910 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4911 unicast_packet = false;
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004912 if (is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004913 //TODO
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004914 } else if (is_multicast_ether_addr(ieee80211_hdr->addr1)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004915 //TODO
Xenia Ragiadakou972ff922013-05-23 05:14:47 +03004916 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004917 /* unicast packet */
4918 unicast_packet = true;
4919 }
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03004920 if (!ieee80211_rx(priv->ieee80211, skb, &stats)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02004921 dev_kfree_skb_any(skb);
4922 } else {
4923 priv->stats.rxoktotal++;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03004924 if (unicast_packet)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004925 priv->stats.rxbytesunicast += rx_pkt_len;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004926 }
4927 /* should trim the packet which has been copied to target skb */
4928 skb_pull(agg_skb, PacketLength);
4929 PacketShiftBytes = GetRxPacketShiftBytes819xUsb(&stats, true);
4930 PacketOccupiedLendth = PacketLength + PacketShiftBytes;
4931 if ((PacketOccupiedLendth & 0xFF) != 0) {
4932 PaddingBytes = 256 - (PacketOccupiedLendth & 0xFF);
4933 if (agg_skb->len > PaddingBytes)
4934 skb_pull(agg_skb, PaddingBytes);
4935 else
4936 agg_skb->len = 0;
4937 }
4938 }
4939 dev_kfree_skb(agg_skb);
4940 }
4941#endif
4942 } else {
4943 priv->stats.rxurberr++;
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03004944 netdev_dbg(dev, "actual_length: %d\n", skb->len);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004945 dev_kfree_skb_any(skb);
4946 }
4947
4948}
4949
4950void
4951rtl819xusb_process_received_packet(
4952 struct net_device *dev,
4953 struct ieee80211_rx_stats *pstats
4954 )
4955{
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004956 u8 *frame;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03004957 u16 frame_len = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004958 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02004959
4960 // Get shifted bytes of Starting address of 802.11 header. 2006.09.28, by Emily
4961 //porting by amy 080508
4962 pstats->virtual_address += get_rxpacket_shiftbytes_819xusb(pstats);
4963 frame = pstats->virtual_address;
4964 frame_len = pstats->packetlength;
4965#ifdef TODO // by amy about HCT
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03004966 if (!Adapter->bInHctTest)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004967 CountRxErrStatistics(Adapter, pRfd);
4968#endif
Jerry Chuang8fc85982009-11-03 07:17:11 -02004969 #ifdef ENABLE_PS //by amy for adding ps function in future
4970 RT_RF_POWER_STATE rtState;
4971 // When RF is off, we should not count the packet for hw/sw synchronize
4972 // reason, ie. there may be a duration while sw switch is changed and hw
4973 // switch is being changed. 2006.12.04, by shien chang.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03004974 Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RF_STATE, (u8 *)(&rtState));
Jerry Chuang8fc85982009-11-03 07:17:11 -02004975 if (rtState == eRfOff)
Jerry Chuang8fc85982009-11-03 07:17:11 -02004976 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004977 #endif
4978 priv->stats.rxframgment++;
4979
Jerry Chuang8fc85982009-11-03 07:17:11 -02004980#ifdef TODO
4981 RmMonitorSignalStrength(Adapter, pRfd);
4982#endif
4983 /* 2007/01/16 MH Add RX command packet handle here. */
4984 /* 2007/03/01 MH We have to release RFD and return if rx pkt is cmd pkt. */
4985 if (rtl819xusb_rx_command_packet(dev, pstats))
Jerry Chuang8fc85982009-11-03 07:17:11 -02004986 return;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004987
4988#ifdef SW_CRC_CHECK
4989 SwCrcCheck();
4990#endif
4991
4992
4993}
4994
4995void query_rx_cmdpkt_desc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats)
4996{
Jerry Chuang8fc85982009-11-03 07:17:11 -02004997 rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02004998
4999 //
5000 //Get Rx Descriptor Information
5001 //
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005002 stats->virtual_address = (u8 *)skb->data;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005003 stats->Length = desc->Length;
5004 stats->RxDrvInfoSize = 0;
5005 stats->RxBufShift = 0;
5006 stats->packetlength = stats->Length-scrclng;
5007 stats->fraglength = stats->packetlength;
5008 stats->fragoffset = 0;
5009 stats->ntotalfrag = 1;
5010}
5011
5012
5013void rtl8192_rx_cmd(struct sk_buff *skb)
5014{
5015 struct rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
5016 struct net_device *dev = info->dev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005017 /* TODO */
5018 struct ieee80211_rx_stats stats = {
5019 .signal = 0,
5020 .noise = -98,
5021 .rate = 0,
Jerry Chuang8fc85982009-11-03 07:17:11 -02005022 .freq = IEEE80211_24GHZ_BAND,
5023 };
5024
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005025 if ((skb->len >= (20 + sizeof(rx_desc_819x_usb))) && (skb->len < RX_URB_SIZE)) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005026
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005027 query_rx_cmdpkt_desc_status(skb, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005028 // this is to be done by amy 080508 prfd->queue_id = 1;
5029
5030
5031 //
5032 // Process the command packet received.
5033 //
5034
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005035 rtl819xusb_process_received_packet(dev, &stats);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005036
5037 dev_kfree_skb_any(skb);
5038 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005039}
5040
5041void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
5042{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005043 struct sk_buff *skb;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005044 struct rtl8192_rx_info *info;
5045
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005046 while (NULL != (skb = skb_dequeue(&priv->skb_queue))) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005047 info = (struct rtl8192_rx_info *)skb->cb;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005048 switch (info->out_pipe) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005049 /* Nomal packet pipe */
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005050 case 3:
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005051 priv->IrpPendingCount--;
5052 rtl8192_rx_nomal(skb);
5053 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005054
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005055 /* Command packet pipe */
5056 case 9:
5057 RT_TRACE(COMP_RECV, "command in-pipe index(%d)\n",\
5058 info->out_pipe);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005059
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005060 rtl8192_rx_cmd(skb);
5061 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005062
Sebastian Hahn24fbe872012-12-05 21:40:22 +01005063 default: /* should never get here! */
5064 RT_TRACE(COMP_ERR, "Unknown in-pipe index(%d)\n",\
5065 info->out_pipe);
5066 dev_kfree_skb(skb);
5067 break;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005068
5069 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005070 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005071}
5072
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005073static const struct net_device_ops rtl8192_netdev_ops = {
5074 .ndo_open = rtl8192_open,
5075 .ndo_stop = rtl8192_close,
5076 .ndo_get_stats = rtl8192_stats,
5077 .ndo_tx_timeout = tx_timeout,
5078 .ndo_do_ioctl = rtl8192_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00005079 .ndo_set_rx_mode = r8192_set_multicast,
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005080 .ndo_set_mac_address = r8192_set_mac_adr,
5081 .ndo_validate_addr = eth_validate_addr,
5082 .ndo_change_mtu = eth_change_mtu,
5083 .ndo_start_xmit = ieee80211_xmit,
5084};
Jerry Chuang8fc85982009-11-03 07:17:11 -02005085
5086
5087/****************************************************************************
5088 ---------------------------- USB_STUFF---------------------------
5089*****************************************************************************/
5090
Bill Pemberton25794522012-11-19 13:22:04 -05005091static int rtl8192_usb_probe(struct usb_interface *intf,
Jerry Chuang8fc85982009-11-03 07:17:11 -02005092 const struct usb_device_id *id)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005093{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005094 struct net_device *dev = NULL;
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005095 struct r8192_priv *priv = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005096 struct usb_device *udev = interface_to_usbdev(intf);
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005097 int ret;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005098 RT_TRACE(COMP_INIT, "Oops: i'm coming\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005099
5100 dev = alloc_ieee80211(sizeof(struct r8192_priv));
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005101 if (dev == NULL)
5102 return -ENOMEM;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005103
Jerry Chuang8fc85982009-11-03 07:17:11 -02005104 usb_set_intfdata(intf, dev);
5105 SET_NETDEV_DEV(dev, &intf->dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005106 priv = ieee80211_priv(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005107 priv->ieee80211 = netdev_priv(dev);
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005108 priv->udev = udev;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005109
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005110 dev->netdev_ops = &rtl8192_netdev_ops;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005111
Jerry Chuang8fc85982009-11-03 07:17:11 -02005112#if WIRELESS_EXT >= 12
5113#if WIRELESS_EXT < 17
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005114 dev->get_wireless_stats = r8192_get_wireless_stats;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005115#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005116 dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005117#endif
Xenia Ragiadakou2d39b002013-05-22 18:22:36 +03005118 dev->type = ARPHRD_ETHER;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005119
5120 dev->watchdog_timeo = HZ*3; //modified by john, 0805
5121
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005122 if (dev_alloc_name(dev, ifname) < 0) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005123 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005124 ifname = "wlan%d";
5125 dev_alloc_name(dev, ifname);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005126 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005127
5128 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005129 if (rtl8192_init(dev) != 0) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005130 RT_TRACE(COMP_ERR, "Initialization failed");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005131 ret = -ENODEV;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005132 goto fail;
5133 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005134 netif_carrier_off(dev);
5135 netif_stop_queue(dev);
5136
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005137 ret = register_netdev(dev);
5138 if (ret)
5139 goto fail2;
5140
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005141 RT_TRACE(COMP_INIT, "dev name=======> %s\n", dev->name);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005142 rtl8192_proc_init_one(dev);
5143
5144
5145 RT_TRACE(COMP_INIT, "Driver probe completed\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005146 return 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005147
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005148fail2:
5149 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005150 kfree(priv->pFirmware);
5151 priv->pFirmware = NULL;
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005152 rtl8192_usb_deleteendpoints(dev);
5153 destroy_workqueue(priv->priv_wq);
5154 mdelay(10);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005155fail:
5156 free_ieee80211(dev);
5157
5158 RT_TRACE(COMP_ERR, "wlan driver load failed\n");
Vasiliy Kulikov2fac6c22010-09-05 22:32:41 +04005159 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005160}
5161
5162//detach all the work and timer structure declared or inititialize in r8192U_init function.
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005163void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005164{
5165
Jerry Chuang8fc85982009-11-03 07:17:11 -02005166 cancel_work_sync(&priv->reset_wq);
5167 cancel_delayed_work(&priv->watch_dog_wq);
5168 cancel_delayed_work(&priv->update_beacon_wq);
5169 cancel_work_sync(&priv->qos_activate);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005170}
5171
5172
Bill Pembertona4a557e2012-11-19 13:26:46 -05005173static void rtl8192_usb_disconnect(struct usb_interface *intf)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005174{
Jerry Chuang8fc85982009-11-03 07:17:11 -02005175 struct net_device *dev = usb_get_intfdata(intf);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005176
5177 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005178 if (dev) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005179
5180 unregister_netdev(dev);
5181
5182 RT_TRACE(COMP_DOWN, "=============>wlan driver to be removed\n");
5183 rtl8192_proc_remove_one(dev);
5184
5185 rtl8192_down(dev);
Ilia Mirkine72714f2011-03-13 00:29:07 -05005186 kfree(priv->pFirmware);
5187 priv->pFirmware = NULL;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005188 rtl8192_usb_deleteendpoints(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005189 destroy_workqueue(priv->priv_wq);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005190 mdelay(10);
5191
5192 }
5193 free_ieee80211(dev);
5194 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
5195}
5196
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005197/* fun with the built-in ieee80211 stack... */
5198extern int ieee80211_debug_init(void);
5199extern void ieee80211_debug_exit(void);
5200extern int ieee80211_crypto_init(void);
5201extern void ieee80211_crypto_deinit(void);
5202extern int ieee80211_crypto_tkip_init(void);
5203extern void ieee80211_crypto_tkip_exit(void);
5204extern int ieee80211_crypto_ccmp_init(void);
5205extern void ieee80211_crypto_ccmp_exit(void);
5206extern int ieee80211_crypto_wep_init(void);
5207extern void ieee80211_crypto_wep_exit(void);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005208
5209static int __init rtl8192_usb_module_init(void)
5210{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005211 int ret;
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005212
5213#ifdef CONFIG_IEEE80211_DEBUG
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005214 ret = ieee80211_debug_init();
5215 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005216 pr_err("ieee80211_debug_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005217 return ret;
5218 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005219#endif
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005220 ret = ieee80211_crypto_init();
5221 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005222 pr_err("ieee80211_crypto_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005223 return ret;
5224 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005225
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005226 ret = ieee80211_crypto_tkip_init();
5227 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005228 pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005229 return ret;
5230 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005231
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005232 ret = ieee80211_crypto_ccmp_init();
5233 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005234 pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005235 return ret;
5236 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005237
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005238 ret = ieee80211_crypto_wep_init();
5239 if (ret) {
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005240 pr_err("ieee80211_crypto_wep_init() failed %d\n", ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005241 return ret;
5242 }
Mauro Carvalho Chehabf61fb932009-11-03 07:17:24 -02005243
Xenia Ragiadakoud6bbce02013-05-26 22:42:44 +03005244 pr_info("\nLinux kernel driver for RTL8192 based WLAN cards\n");
5245 pr_info("Copyright (c) 2007-2008, Realsil Wlan\n");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005246 RT_TRACE(COMP_INIT, "Initializing module");
5247 RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
5248 rtl8192_proc_module_init();
5249 return usb_register(&rtl8192_usb_driver);
5250}
5251
5252
5253static void __exit rtl8192_usb_module_exit(void)
5254{
5255 usb_deregister(&rtl8192_usb_driver);
5256
5257 RT_TRACE(COMP_DOWN, "Exiting");
Jerry Chuang8fc85982009-11-03 07:17:11 -02005258}
5259
5260
5261void rtl8192_try_wake_queue(struct net_device *dev, int pri)
5262{
5263 unsigned long flags;
5264 short enough_desc;
5265 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
5266
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005267 spin_lock_irqsave(&priv->tx_lock, flags);
5268 enough_desc = check_nic_enough_desc(dev, pri);
5269 spin_unlock_irqrestore(&priv->tx_lock, flags);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005270
Xenia Ragiadakou34fc4382013-05-22 18:22:33 +03005271 if (enough_desc)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005272 ieee80211_wake_queue(priv->ieee80211);
5273}
5274
5275void EnableHWSecurityConfig8192(struct net_device *dev)
5276{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005277 u8 SECR_value = 0x0;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005278 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
Xenia Ragiadakou9f7b8302013-05-09 01:08:25 +03005279 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005280 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005281 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 -02005282 SECR_value |= SCR_RxUseDK;
5283 SECR_value |= SCR_TxUseDK;
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005284 } 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 -02005285 SECR_value |= SCR_RxUseDK;
5286 SECR_value |= SCR_TxUseDK;
5287 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005288 //add HWSec active enable here.
Jerry Chuang8fc85982009-11-03 07:17:11 -02005289//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
5290
5291 ieee->hwsec_active = 1;
5292
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005293 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 -02005294 ieee->hwsec_active = 0;
5295 SECR_value &= ~SCR_RxDecEnable;
5296 }
Xenia Ragiadakou5b3b2152013-05-23 05:14:48 +03005297 RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __func__, \
Jerry Chuang8fc85982009-11-03 07:17:11 -02005298 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
Xenia Ragiadakou57c259f2013-06-03 23:58:44 +03005299 write_nic_byte(dev, SECR, SECR_value);
Jerry Chuang8fc85982009-11-03 07:17:11 -02005300}
5301
5302
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03005303void setKey(struct net_device *dev,
5304 u8 EntryNo,
5305 u8 KeyIndex,
5306 u16 KeyType,
5307 u8 *MacAddr,
5308 u8 DefaultKey,
5309 u32 *KeyContent)
Jerry Chuang8fc85982009-11-03 07:17:11 -02005310{
5311 u32 TargetCommand = 0;
5312 u32 TargetContent = 0;
5313 u16 usConfig = 0;
5314 u8 i;
5315 if (EntryNo >= TOTAL_CAM_ENTRY)
5316 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
5317
Xenia Ragiadakou3ab31c72013-05-22 18:22:40 +03005318 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 -02005319
5320 if (DefaultKey)
5321 usConfig |= BIT15 | (KeyType<<2);
5322 else
5323 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005324
5325
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005326 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005327 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
5328 TargetCommand |= BIT31|BIT16;
5329
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005330 if (i == 0) { //MAC|Config
Jerry Chuang8fc85982009-11-03 07:17:11 -02005331 TargetContent = (u32)(*(MacAddr+0)) << 16|
5332 (u32)(*(MacAddr+1)) << 24|
5333 (u32)usConfig;
5334
5335 write_nic_dword(dev, WCAMI, TargetContent);
5336 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005337 } else if (i == 1) { //MAC
Sebastian Hahn35997ff2012-12-05 21:40:18 +01005338 TargetContent = (u32)(*(MacAddr+2)) |
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02005339 (u32)(*(MacAddr+3)) << 8|
5340 (u32)(*(MacAddr+4)) << 16|
5341 (u32)(*(MacAddr+5)) << 24;
Jerry Chuang8fc85982009-11-03 07:17:11 -02005342 write_nic_dword(dev, WCAMI, TargetContent);
5343 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005344 } else {
Jerry Chuang8fc85982009-11-03 07:17:11 -02005345 //Key Material
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005346 if (KeyContent != NULL) {
Xenia Ragiadakou9f6bd882013-05-22 18:22:39 +03005347 write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)));
Jerry Chuang8fc85982009-11-03 07:17:11 -02005348 write_nic_dword(dev, RWCAM, TargetCommand);
Xenia Ragiadakou27161412013-06-03 23:58:45 +03005349 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005350 }
5351 }
Jerry Chuang8fc85982009-11-03 07:17:11 -02005352
5353}
5354
5355/***************************************************************************
5356 ------------------- module init / exit stubs ----------------
5357****************************************************************************/
5358module_init(rtl8192_usb_module_init);
5359module_exit(rtl8192_usb_module_exit);