blob: 04c23919f4d661d36ab9758401d03d9a55e5a57c [file] [log] [blame]
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001/*
2 This is part of rtl818x pci OpenSource driver - v 0.1
3 Copyright (C) Andrea Merello 2004-2005 <andreamrl@tiscali.it>
4 Released under the terms of GPL (General Public License)
5
6 Parts of this driver are based on the GPL part of the official
7 Realtek driver.
8
9 Parts of this driver are based on the rtl8180 driver skeleton
10 from Patric Schenke & Andres Salomon.
11
12 Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
13
14 Parts of BB/RF code are derived from David Young rtl8180 netbsd driver.
15
16 RSSI calc function from 'The Deuce'
17
18 Some ideas borrowed from the 8139too.c driver included in linux kernel.
19
20 We (I?) want to thanks the Authors of those projecs and also the
21 Ndiswrapper's project Authors.
22
23 A big big thanks goes also to Realtek corp. for their help in my attempt to
24 add RTL8185 and RTL8225 support, and to David Young also.
Bartlomiej Zolnierkiewiczb6d11c02009-06-28 16:20:10 +020025
26 Power management interface routines.
27 Written by Mariusz Matuszek.
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080028*/
29
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080030#undef RX_DONT_PASS_UL
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080031#undef DUMMY_RX
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080032
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090033#include <linux/slab.h>
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080034#include <linux/syscalls.h>
Larry Finger742821c2010-02-11 12:07:35 -060035#include <linux/eeprom_93cx6.h>
Stephen Rothwell219eb472011-06-19 22:41:59 -070036#include <linux/interrupt.h>
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +020037
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080038#include "r8180_hw.h"
39#include "r8180.h"
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080040#include "r8180_rtl8225.h" /* RTL8225 Radio frontend */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080041#include "r8180_93cx6.h" /* Card EEPROM */
42#include "r8180_wx.h"
43#include "r8180_dm.h"
44
Bartlomiej Zolnierkiewiczfd9b8d62009-06-12 18:28:35 +020045#include "ieee80211/dot11d.h"
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080046
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080047static struct pci_device_id rtl8180_pci_id_tbl[] __devinitdata = {
John Churchcb73da22010-04-08 16:04:17 -050048 {
49 .vendor = PCI_VENDOR_ID_REALTEK,
50 .device = 0x8199,
51 .subvendor = PCI_ANY_ID,
52 .subdevice = PCI_ANY_ID,
53 .driver_data = 0,
54 },
55 {
56 .vendor = 0,
57 .device = 0,
58 .subvendor = 0,
59 .subdevice = 0,
60 .driver_data = 0,
61 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080062};
63
64
Rusty Russelldca41302010-08-11 23:04:21 -060065static char ifname[IFNAMSIZ] = "wlan%d";
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080066static int hwseqnum = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080067static int hwwep = 0;
68static int channels = 0x3fff;
69
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080070MODULE_LICENSE("GPL");
71MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl);
72MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
73MODULE_DESCRIPTION("Linux driver for Realtek RTL8180 / RTL8185 WiFi cards");
74
75
Rusty Russelldca41302010-08-11 23:04:21 -060076module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +053077module_param(hwseqnum, int, S_IRUGO|S_IWUSR);
78module_param(hwwep, int, S_IRUGO|S_IWUSR);
79module_param(channels, int, S_IRUGO|S_IWUSR);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080080
Prashant P. Shahbbfb5652010-05-13 23:08:43 +053081MODULE_PARM_DESC(devname, " Net interface name, wlan%d=default");
82MODULE_PARM_DESC(hwseqnum, " Try to use hardware 802.11 header sequence numbers. Zero=default");
83MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support. Still broken and not available on all cards");
84MODULE_PARM_DESC(channels, " Channel bitmask for specific locales. NYI");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080085
86
87static int __devinit rtl8180_pci_probe(struct pci_dev *pdev,
88 const struct pci_device_id *id);
89
90static void __devexit rtl8180_pci_remove(struct pci_dev *pdev);
91
Prashant P. Shahbbfb5652010-05-13 23:08:43 +053092static void rtl8180_shutdown(struct pci_dev *pdev)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080093{
94 struct net_device *dev = pci_get_drvdata(pdev);
Alexander Beregalov727ae302009-05-10 03:06:54 +040095 if (dev->netdev_ops->ndo_stop)
96 dev->netdev_ops->ndo_stop(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -080097 pci_disable_device(pdev);
98}
99
Bartlomiej Zolnierkiewiczb6d11c02009-06-28 16:20:10 +0200100static int rtl8180_suspend(struct pci_dev *pdev, pm_message_t state)
101{
102 struct net_device *dev = pci_get_drvdata(pdev);
103
104 if (!netif_running(dev))
105 goto out_pci_suspend;
106
107 if (dev->netdev_ops->ndo_stop)
108 dev->netdev_ops->ndo_stop(dev);
109
110 netif_device_detach(dev);
111
112out_pci_suspend:
113 pci_save_state(pdev);
114 pci_disable_device(pdev);
115 pci_set_power_state(pdev, pci_choose_state(pdev, state));
116 return 0;
117}
118
119static int rtl8180_resume(struct pci_dev *pdev)
120{
121 struct net_device *dev = pci_get_drvdata(pdev);
122 int err;
123 u32 val;
124
125 pci_set_power_state(pdev, PCI_D0);
126
127 err = pci_enable_device(pdev);
128 if (err) {
129 printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
130 dev->name);
131
132 return err;
133 }
134
135 pci_restore_state(pdev);
136
137 /*
138 * Suspend/Resume resets the PCI configuration space, so we have to
139 * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
140 * from interfering with C3 CPU state. pci_restore_state won't help
141 * here since it only restores the first 64 bytes pci config header.
142 */
143 pci_read_config_dword(pdev, 0x40, &val);
144 if ((val & 0x0000ff00) != 0)
145 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
146
147 if (!netif_running(dev))
148 goto out;
149
150 if (dev->netdev_ops->ndo_open)
151 dev->netdev_ops->ndo_open(dev);
152
153 netif_device_attach(dev);
154out:
155 return 0;
156}
157
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800158static struct pci_driver rtl8180_pci_driver = {
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200159 .name = RTL8180_MODULE_NAME,
160 .id_table = rtl8180_pci_id_tbl,
161 .probe = rtl8180_pci_probe,
162 .remove = __devexit_p(rtl8180_pci_remove),
163 .suspend = rtl8180_suspend,
164 .resume = rtl8180_resume,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800165 .shutdown = rtl8180_shutdown,
166};
167
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800168u8 read_nic_byte(struct net_device *dev, int x)
169{
John Churchcb73da22010-04-08 16:04:17 -0500170 return 0xff&readb((u8 *)dev->mem_start + x);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800171}
172
173u32 read_nic_dword(struct net_device *dev, int x)
174{
John Churchcb73da22010-04-08 16:04:17 -0500175 return readl((u8 *)dev->mem_start + x);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800176}
177
178u16 read_nic_word(struct net_device *dev, int x)
179{
John Churchcb73da22010-04-08 16:04:17 -0500180 return readw((u8 *)dev->mem_start + x);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800181}
182
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530183void write_nic_byte(struct net_device *dev, int x, u8 y)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800184{
John Churchcb73da22010-04-08 16:04:17 -0500185 writeb(y, (u8 *)dev->mem_start + x);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800186 udelay(20);
187}
188
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530189void write_nic_dword(struct net_device *dev, int x, u32 y)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800190{
John Churchcb73da22010-04-08 16:04:17 -0500191 writel(y, (u8 *)dev->mem_start + x);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800192 udelay(20);
193}
194
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530195void write_nic_word(struct net_device *dev, int x, u16 y)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800196{
John Churchcb73da22010-04-08 16:04:17 -0500197 writew(y, (u8 *)dev->mem_start + x);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800198 udelay(20);
199}
200
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800201inline void force_pci_posting(struct net_device *dev)
202{
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530203 read_nic_byte(dev, EPROM_CMD);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800204 mb();
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800205}
206
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800207irqreturn_t rtl8180_interrupt(int irq, void *netdev, struct pt_regs *regs);
208void set_nic_rxring(struct net_device *dev);
209void set_nic_txring(struct net_device *dev);
210static struct net_device_stats *rtl8180_stats(struct net_device *dev);
211void rtl8180_commit(struct net_device *dev);
212void rtl8180_start_tx_beacon(struct net_device *dev);
213
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800214static struct proc_dir_entry *rtl8180_proc = NULL;
215
216static int proc_get_registers(char *page, char **start,
217 off_t offset, int count,
218 int *eof, void *data)
219{
220 struct net_device *dev = data;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800221 int len = 0;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530222 int i, n;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200223 int max = 0xff;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800224
225 /* This dump the current register page */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200226 for (n = 0; n <= max;) {
227 len += snprintf(page + len, count - len, "\nD: %2x > ", n);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800228
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200229 for (i = 0; i < 16 && n <= max; i++, n++)
230 len += snprintf(page + len, count - len, "%2x ",
231 read_nic_byte(dev, n));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800232 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530233 len += snprintf(page + len, count - len, "\n");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800234
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800235 *eof = 1;
236 return len;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800237}
238
239int get_curr_tx_free_desc(struct net_device *dev, int priority);
240
241static int proc_get_stats_hw(char *page, char **start,
242 off_t offset, int count,
243 int *eof, void *data)
244{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800245 int len = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800246
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800247 *eof = 1;
248 return len;
249}
250
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800251static int proc_get_stats_rx(char *page, char **start,
252 off_t offset, int count,
253 int *eof, void *data)
254{
255 struct net_device *dev = data;
256 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
257
258 int len = 0;
259
260 len += snprintf(page + len, count - len,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800261 "RX OK: %lu\n"
262 "RX Retry: %lu\n"
263 "RX CRC Error(0-500): %lu\n"
264 "RX CRC Error(500-1000): %lu\n"
265 "RX CRC Error(>1000): %lu\n"
266 "RX ICV Error: %lu\n",
267 priv->stats.rxint,
268 priv->stats.rxerr,
269 priv->stats.rxcrcerrmin,
270 priv->stats.rxcrcerrmid,
271 priv->stats.rxcrcerrmax,
272 priv->stats.rxicverr
273 );
274
275 *eof = 1;
276 return len;
277}
278
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800279static int proc_get_stats_tx(char *page, char **start,
280 off_t offset, int count,
281 int *eof, void *data)
282{
283 struct net_device *dev = data;
284 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
285
286 int len = 0;
287 unsigned long totalOK;
288
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530289 totalOK = priv->stats.txnpokint+priv->stats.txhpokint+priv->stats.txlpokint;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800290 len += snprintf(page + len, count - len,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800291 "TX OK: %lu\n"
292 "TX Error: %lu\n"
293 "TX Retry: %lu\n"
294 "TX beacon OK: %lu\n"
295 "TX beacon error: %lu\n",
296 totalOK,
297 priv->stats.txnperr+priv->stats.txhperr+priv->stats.txlperr,
298 priv->stats.txretry,
299 priv->stats.txbeacon,
300 priv->stats.txbeaconerr
301 );
302
303 *eof = 1;
304 return len;
305}
306
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800307void rtl8180_proc_module_init(void)
308{
309 DMESG("Initializing proc filesystem");
Al Viroe55d92b2011-07-24 02:07:46 -0400310 rtl8180_proc = proc_mkdir(RTL8180_MODULE_NAME, init_net.proc_net);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800311}
312
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800313void rtl8180_proc_module_remove(void)
314{
John Churchcb73da22010-04-08 16:04:17 -0500315 remove_proc_entry(RTL8180_MODULE_NAME, init_net.proc_net);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800316}
317
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800318void rtl8180_proc_remove_one(struct net_device *dev)
319{
320 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
321 if (priv->dir_dev) {
322 remove_proc_entry("stats-hw", priv->dir_dev);
323 remove_proc_entry("stats-tx", priv->dir_dev);
324 remove_proc_entry("stats-rx", priv->dir_dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800325 remove_proc_entry("registers", priv->dir_dev);
326 remove_proc_entry(dev->name, rtl8180_proc);
327 priv->dir_dev = NULL;
328 }
329}
330
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800331void rtl8180_proc_init_one(struct net_device *dev)
332{
333 struct proc_dir_entry *e;
334 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200335
Larry Fingerbe286fd2009-04-18 21:09:08 -0500336 priv->dir_dev = rtl8180_proc;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800337 if (!priv->dir_dev) {
Larry Fingerbe286fd2009-04-18 21:09:08 -0500338 DMESGE("Unable to initialize /proc/net/r8180/%s\n",
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800339 dev->name);
340 return;
341 }
342
343 e = create_proc_read_entry("stats-hw", S_IFREG | S_IRUGO,
344 priv->dir_dev, proc_get_stats_hw, dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800345 if (!e) {
346 DMESGE("Unable to initialize "
Larry Fingerbe286fd2009-04-18 21:09:08 -0500347 "/proc/net/r8180/%s/stats-hw\n",
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800348 dev->name);
349 }
350
351 e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
352 priv->dir_dev, proc_get_stats_rx, dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800353 if (!e) {
354 DMESGE("Unable to initialize "
Larry Fingerbe286fd2009-04-18 21:09:08 -0500355 "/proc/net/r8180/%s/stats-rx\n",
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800356 dev->name);
357 }
358
359
360 e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
361 priv->dir_dev, proc_get_stats_tx, dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800362 if (!e) {
363 DMESGE("Unable to initialize "
Larry Fingerbe286fd2009-04-18 21:09:08 -0500364 "/proc/net/r8180/%s/stats-tx\n",
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800365 dev->name);
366 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800367
368 e = create_proc_read_entry("registers", S_IFREG | S_IRUGO,
369 priv->dir_dev, proc_get_registers, dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800370 if (!e) {
371 DMESGE("Unable to initialize "
Larry Fingerbe286fd2009-04-18 21:09:08 -0500372 "/proc/net/r8180/%s/registers\n",
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800373 dev->name);
374 }
375}
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200376
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800377/*
378 FIXME: check if we can use some standard already-existent
379 data type+functions in kernel
380*/
381
382short buffer_add(struct buffer **buffer, u32 *buf, dma_addr_t dma,
383 struct buffer **bufferhead)
384{
John Churchcb73da22010-04-08 16:04:17 -0500385 struct buffer *tmp;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800386
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530387 if (!*buffer) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800388
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530389 *buffer = kmalloc(sizeof(struct buffer), GFP_KERNEL);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800390
391 if (*buffer == NULL) {
392 DMESGE("Failed to kmalloc head of TX/RX struct");
393 return -1;
394 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530395 (*buffer)->next = *buffer;
396 (*buffer)->buf = buf;
397 (*buffer)->dma = dma;
398 if (bufferhead != NULL)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800399 (*bufferhead) = (*buffer);
400 return 0;
401 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530402 tmp = *buffer;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800403
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530404 while (tmp->next != (*buffer))
405 tmp = tmp->next;
406 tmp->next = kmalloc(sizeof(struct buffer), GFP_KERNEL);
Joe Perches53756de2010-03-24 22:17:01 -0700407 if (tmp->next == NULL) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800408 DMESGE("Failed to kmalloc TX/RX struct");
409 return -1;
410 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530411 tmp->next->buf = buf;
412 tmp->next->dma = dma;
413 tmp->next->next = *buffer;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800414
415 return 0;
416}
417
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530418void buffer_free(struct net_device *dev, struct buffer **buffer, int len, short consistent)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800419{
420
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530421 struct buffer *tmp, *next;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800422 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530423 struct pci_dev *pdev = priv->pdev;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800424
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200425 if (!*buffer)
426 return;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800427
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200428 tmp = *buffer;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800429
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530430 do {
431 next = tmp->next;
432 if (consistent) {
433 pci_free_consistent(pdev, len,
434 tmp->buf, tmp->dma);
435 } else {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800436 pci_unmap_single(pdev, tmp->dma,
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530437 len, PCI_DMA_FROMDEVICE);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800438 kfree(tmp->buf);
439 }
440 kfree(tmp);
441 tmp = next;
442 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530443 while (next != *buffer);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800444
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530445 *buffer = NULL;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800446}
447
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800448void print_buffer(u32 *buffer, int len)
449{
450 int i;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530451 u8 *buf = (u8 *)buffer;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800452
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530453 printk("ASCII BUFFER DUMP (len: %x):\n", len);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800454
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530455 for (i = 0; i < len; i++)
456 printk("%c", buf[i]);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800457
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530458 printk("\nBINARY BUFFER DUMP (len: %x):\n", len);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800459
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530460 for (i = 0; i < len; i++)
461 printk("%02x", buf[i]);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800462
463 printk("\n");
464}
465
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800466int get_curr_tx_free_desc(struct net_device *dev, int priority)
467{
468 struct r8180_priv *priv = ieee80211_priv(dev);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530469 u32 *tail;
470 u32 *head;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800471 int ret;
472
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530473 switch (priority) {
474 case MANAGE_PRIORITY:
475 head = priv->txmapringhead;
476 tail = priv->txmapringtail;
477 break;
478 case BK_PRIORITY:
479 head = priv->txbkpringhead;
480 tail = priv->txbkpringtail;
481 break;
482 case BE_PRIORITY:
483 head = priv->txbepringhead;
484 tail = priv->txbepringtail;
485 break;
486 case VI_PRIORITY:
487 head = priv->txvipringhead;
488 tail = priv->txvipringtail;
489 break;
490 case VO_PRIORITY:
491 head = priv->txvopringhead;
492 tail = priv->txvopringtail;
493 break;
494 case HI_PRIORITY:
495 head = priv->txhpringhead;
496 tail = priv->txhpringtail;
497 break;
498 default:
499 return -1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800500 }
501
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200502 if (head <= tail)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800503 ret = priv->txringcount - (tail - head)/8;
504 else
505 ret = (head - tail)/8;
506
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200507 if (ret > priv->txringcount)
508 DMESG("BUG");
509
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800510 return ret;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800511}
512
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800513short check_nic_enought_desc(struct net_device *dev, int priority)
514{
515 struct r8180_priv *priv = ieee80211_priv(dev);
516 struct ieee80211_device *ieee = netdev_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800517 int requiredbyte, required;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200518
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800519 requiredbyte = priv->ieee80211->fts + sizeof(struct ieee80211_header_data);
520
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200521 if (ieee->current_network.QoS_Enable)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800522 requiredbyte += 2;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800523
524 required = requiredbyte / (priv->txbuffsize-4);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200525
526 if (requiredbyte % priv->txbuffsize)
527 required++;
528
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800529 /* for now we keep two free descriptor as a safety boundary
530 * between the tail and the head
531 */
532
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530533 return (required+2 < get_curr_tx_free_desc(dev, priority));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800534}
535
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800536void fix_tx_fifo(struct net_device *dev)
537{
538 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
539 u32 *tmp;
540 int i;
Bartlomiej Zolnierkiewiczff954852009-06-28 16:19:38 +0200541
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530542 for (tmp = priv->txmapring, i = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800543 i < priv->txringcount;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530544 tmp += 8, i++) {
545 *tmp = *tmp & ~(1<<31);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800546 }
547
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530548 for (tmp = priv->txbkpring, i = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800549 i < priv->txringcount;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530550 tmp += 8, i++) {
551 *tmp = *tmp & ~(1<<31);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800552 }
553
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530554 for (tmp = priv->txbepring, i = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800555 i < priv->txringcount;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530556 tmp += 8, i++) {
557 *tmp = *tmp & ~(1<<31);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800558 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530559 for (tmp = priv->txvipring, i = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800560 i < priv->txringcount;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530561 tmp += 8, i++) {
562 *tmp = *tmp & ~(1<<31);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800563 }
564
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530565 for (tmp = priv->txvopring, i = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800566 i < priv->txringcount;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530567 tmp += 8, i++) {
568 *tmp = *tmp & ~(1<<31);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800569 }
570
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530571 for (tmp = priv->txhpring, i = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800572 i < priv->txringcount;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530573 tmp += 8, i++) {
574 *tmp = *tmp & ~(1<<31);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800575 }
576
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530577 for (tmp = priv->txbeaconring, i = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800578 i < priv->txbeaconcount;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530579 tmp += 8, i++) {
580 *tmp = *tmp & ~(1<<31);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800581 }
Bartlomiej Zolnierkiewiczff954852009-06-28 16:19:38 +0200582
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800583 priv->txmapringtail = priv->txmapring;
584 priv->txmapringhead = priv->txmapring;
585 priv->txmapbufstail = priv->txmapbufs;
586
587 priv->txbkpringtail = priv->txbkpring;
588 priv->txbkpringhead = priv->txbkpring;
589 priv->txbkpbufstail = priv->txbkpbufs;
590
591 priv->txbepringtail = priv->txbepring;
592 priv->txbepringhead = priv->txbepring;
593 priv->txbepbufstail = priv->txbepbufs;
594
595 priv->txvipringtail = priv->txvipring;
596 priv->txvipringhead = priv->txvipring;
597 priv->txvipbufstail = priv->txvipbufs;
598
599 priv->txvopringtail = priv->txvopring;
600 priv->txvopringhead = priv->txvopring;
601 priv->txvopbufstail = priv->txvopbufs;
602
603 priv->txhpringtail = priv->txhpring;
604 priv->txhpringhead = priv->txhpring;
605 priv->txhpbufstail = priv->txhpbufs;
606
607 priv->txbeaconringtail = priv->txbeaconring;
608 priv->txbeaconbufstail = priv->txbeaconbufs;
609 set_nic_txring(dev);
610
611 ieee80211_reset_queue(priv->ieee80211);
612 priv->ack_tx_to_ieee = 0;
613}
614
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800615void fix_rx_fifo(struct net_device *dev)
616{
617 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
618 u32 *tmp;
619 struct buffer *rxbuf;
620 u8 rx_desc_size;
621
Prashant P. Shah3f56c102010-05-13 23:09:08 +0530622 rx_desc_size = 8; /* 4*8 = 32 bytes */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800623
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530624 for (tmp = priv->rxring, rxbuf = priv->rxbufferhead;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800625 (tmp < (priv->rxring)+(priv->rxringcount)*rx_desc_size);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530626 tmp += rx_desc_size, rxbuf = rxbuf->next) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800627 *(tmp+2) = rxbuf->dma;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530628 *tmp = *tmp & ~0xfff;
629 *tmp = *tmp | priv->rxbuffersize;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800630 *tmp |= (1<<31);
631 }
632
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530633 priv->rxringtail = priv->rxring;
634 priv->rxbuffer = priv->rxbufferhead;
635 priv->rx_skb_complete = 1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800636 set_nic_rxring(dev);
637}
638
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800639unsigned char QUALITY_MAP[] = {
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200640 0x64, 0x64, 0x64, 0x63, 0x63, 0x62, 0x62, 0x61,
641 0x61, 0x60, 0x60, 0x5f, 0x5f, 0x5e, 0x5d, 0x5c,
642 0x5b, 0x5a, 0x59, 0x57, 0x56, 0x54, 0x52, 0x4f,
643 0x4c, 0x49, 0x45, 0x41, 0x3c, 0x37, 0x31, 0x29,
644 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
645 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x20,
646 0x20, 0x20, 0x20, 0x1f, 0x1f, 0x1e, 0x1e, 0x1e,
647 0x1d, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a, 0x19, 0x19,
648 0x18, 0x17, 0x16, 0x15, 0x14, 0x12, 0x11, 0x0f,
649 0x0e, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x01, 0x00
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800650};
651
652unsigned char STRENGTH_MAP[] = {
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200653 0x64, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e,
654 0x5d, 0x5c, 0x5b, 0x5a, 0x57, 0x54, 0x52, 0x50,
655 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x41, 0x3f,
656 0x3c, 0x3a, 0x37, 0x36, 0x36, 0x1c, 0x1c, 0x1b,
657 0x1b, 0x1a, 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17,
658 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13,
659 0x13, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10, 0x0f,
660 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
661 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
662 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02, 0x00
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800663};
664
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200665void rtl8180_RSSI_calc(struct net_device *dev, u8 *rssi, u8 *qual)
666{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800667 u32 temp;
668 u32 temp2;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800669 u32 q;
670 u32 orig_qual;
671 u8 _rssi;
672
673 q = *qual;
674 orig_qual = *qual;
Prashant P. Shah3f56c102010-05-13 23:09:08 +0530675 _rssi = 0; /* avoid gcc complains.. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800676
677 if (q <= 0x4e) {
678 temp = QUALITY_MAP[q];
679 } else {
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530680 if (q & 0x80)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800681 temp = 0x32;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530682 else
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800683 temp = 1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800684 }
685
686 *qual = temp;
687 temp2 = *rssi;
688
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530689 if (_rssi < 0x64) {
690 if (_rssi == 0)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800691 *rssi = 1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800692 } else {
693 *rssi = 0x64;
694 }
695
696 return;
697}
698
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800699void rtl8180_irq_enable(struct net_device *dev)
700{
701 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200702
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800703 priv->irq_enabled = 1;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530704 write_nic_word(dev, INTA_MASK, priv->irq_mask);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800705}
706
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800707void rtl8180_irq_disable(struct net_device *dev)
708{
709 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
710
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530711 write_nic_dword(dev, IMR, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800712 force_pci_posting(dev);
713 priv->irq_enabled = 0;
714}
715
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530716void rtl8180_set_mode(struct net_device *dev, int mode)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800717{
718 u8 ecmd;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200719
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530720 ecmd = read_nic_byte(dev, EPROM_CMD);
721 ecmd = ecmd & ~EPROM_CMD_OPERATING_MODE_MASK;
722 ecmd = ecmd | (mode<<EPROM_CMD_OPERATING_MODE_SHIFT);
723 ecmd = ecmd & ~(1<<EPROM_CS_SHIFT);
724 ecmd = ecmd & ~(1<<EPROM_CK_SHIFT);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800725 write_nic_byte(dev, EPROM_CMD, ecmd);
726}
727
728void rtl8180_adapter_start(struct net_device *dev);
729void rtl8180_beacon_tx_enable(struct net_device *dev);
730
731void rtl8180_update_msr(struct net_device *dev)
732{
733 struct r8180_priv *priv = ieee80211_priv(dev);
734 u8 msr;
735 u32 rxconf;
736
737 msr = read_nic_byte(dev, MSR);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530738 msr &= ~MSR_LINK_MASK;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800739
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530740 rxconf = read_nic_dword(dev, RX_CONF);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800741
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530742 if (priv->ieee80211->state == IEEE80211_LINKED) {
743 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800744 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
745 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
746 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
747 else if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
748 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
749 else
750 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
751 rxconf |= (1<<RX_CHECK_BSSID_SHIFT);
752
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530753 } else {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800754 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
755 rxconf &= ~(1<<RX_CHECK_BSSID_SHIFT);
756 }
757
758 write_nic_byte(dev, MSR, msr);
759 write_nic_dword(dev, RX_CONF, rxconf);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800760}
761
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530762void rtl8180_set_chan(struct net_device *dev, short ch)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800763{
764 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
765
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200766 if ((ch > 14) || (ch < 1)) {
Harvey Harrisond599edc2009-01-07 14:31:57 -0800767 printk("In %s: Invalid chnanel %d\n", __func__, ch);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800768 return;
769 }
770
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530771 priv->chan = ch;
772 priv->rf_set_chan(dev, priv->chan);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800773}
774
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800775void rtl8180_rx_enable(struct net_device *dev)
776{
777 u8 cmd;
778 u32 rxconf;
779 /* for now we accept data, management & ctl frame*/
780 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
781
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530782 rxconf = read_nic_dword(dev, RX_CONF);
783 rxconf = rxconf & ~MAC_FILTER_MASK;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800784 rxconf = rxconf | (1<<ACCEPT_MNG_FRAME_SHIFT);
785 rxconf = rxconf | (1<<ACCEPT_DATA_FRAME_SHIFT);
786 rxconf = rxconf | (1<<ACCEPT_BCAST_FRAME_SHIFT);
787 rxconf = rxconf | (1<<ACCEPT_MCAST_FRAME_SHIFT);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200788 if (dev->flags & IFF_PROMISC)
789 DMESG("NIC in promisc mode");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800790
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530791 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || \
792 dev->flags & IFF_PROMISC) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800793 rxconf = rxconf | (1<<ACCEPT_ALLMAC_FRAME_SHIFT);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530794 } else {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800795 rxconf = rxconf | (1<<ACCEPT_NICMAC_FRAME_SHIFT);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800796 }
797
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530798 if (priv->ieee80211->iw_mode == IW_MODE_MONITOR) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800799 rxconf = rxconf | (1<<ACCEPT_CTL_FRAME_SHIFT);
800 rxconf = rxconf | (1<<ACCEPT_ICVERR_FRAME_SHIFT);
801 rxconf = rxconf | (1<<ACCEPT_PWR_FRAME_SHIFT);
802 }
803
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530804 if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800805 rxconf = rxconf | (1<<ACCEPT_CRCERR_FRAME_SHIFT);
806
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200807 rxconf = rxconf & ~RX_FIFO_THRESHOLD_MASK;
808 rxconf = rxconf | (RX_FIFO_THRESHOLD_NONE << RX_FIFO_THRESHOLD_SHIFT);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800809
810 rxconf = rxconf | (1<<RX_AUTORESETPHY_SHIFT);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530811 rxconf = rxconf & ~MAX_RX_DMA_MASK;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800812 rxconf = rxconf | (MAX_RX_DMA_2048<<MAX_RX_DMA_SHIFT);
813
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200814 rxconf = rxconf | RCR_ONLYERLPKT;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800815
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530816 rxconf = rxconf & ~RCR_CS_MASK;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200817
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800818 write_nic_dword(dev, RX_CONF, rxconf);
819
820 fix_rx_fifo(dev);
821
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530822 cmd = read_nic_byte(dev, CMD);
823 write_nic_byte(dev, CMD, cmd | (1<<CMD_RX_ENABLE_SHIFT));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800824}
825
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800826void set_nic_txring(struct net_device *dev)
827{
828 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800829
830 write_nic_dword(dev, TX_MANAGEPRIORITY_RING_ADDR, priv->txmapringdma);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800831 write_nic_dword(dev, TX_BKPRIORITY_RING_ADDR, priv->txbkpringdma);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800832 write_nic_dword(dev, TX_BEPRIORITY_RING_ADDR, priv->txbepringdma);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800833 write_nic_dword(dev, TX_VIPRIORITY_RING_ADDR, priv->txvipringdma);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800834 write_nic_dword(dev, TX_VOPRIORITY_RING_ADDR, priv->txvopringdma);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800835 write_nic_dword(dev, TX_HIGHPRIORITY_RING_ADDR, priv->txhpringdma);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800836 write_nic_dword(dev, TX_BEACON_RING_ADDR, priv->txbeaconringdma);
837}
838
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800839void rtl8180_conttx_enable(struct net_device *dev)
840{
841 u32 txconf;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200842
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530843 txconf = read_nic_dword(dev, TX_CONF);
844 txconf = txconf & ~TX_LOOPBACK_MASK;
845 txconf = txconf | (TX_LOOPBACK_CONTINUE<<TX_LOOPBACK_SHIFT);
846 write_nic_dword(dev, TX_CONF, txconf);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800847}
848
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800849void rtl8180_conttx_disable(struct net_device *dev)
850{
851 u32 txconf;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200852
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530853 txconf = read_nic_dword(dev, TX_CONF);
854 txconf = txconf & ~TX_LOOPBACK_MASK;
855 txconf = txconf | (TX_LOOPBACK_NONE<<TX_LOOPBACK_SHIFT);
856 write_nic_dword(dev, TX_CONF, txconf);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800857}
858
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800859void rtl8180_tx_enable(struct net_device *dev)
860{
861 u8 cmd;
862 u8 tx_agc_ctl;
863 u8 byte;
864 u32 txconf;
865 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800866
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200867 txconf = read_nic_dword(dev, TX_CONF);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800868
Larry Fingerd44eb882009-11-09 10:53:20 -0600869 byte = read_nic_byte(dev, CW_CONF);
870 byte &= ~(1<<CW_CONF_PERPACKET_CW_SHIFT);
871 byte &= ~(1<<CW_CONF_PERPACKET_RETRY_SHIFT);
872 write_nic_byte(dev, CW_CONF, byte);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800873
Larry Fingerd44eb882009-11-09 10:53:20 -0600874 tx_agc_ctl = read_nic_byte(dev, TX_AGC_CTL);
875 tx_agc_ctl &= ~(1<<TX_AGC_CTL_PERPACKET_GAIN_SHIFT);
876 tx_agc_ctl &= ~(1<<TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT);
877 tx_agc_ctl |= (1<<TX_AGC_CTL_FEEDBACK_ANT);
878 write_nic_byte(dev, TX_AGC_CTL, tx_agc_ctl);
879 write_nic_byte(dev, 0xec, 0x3f); /* Disable early TX */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800880
Larry Fingerd44eb882009-11-09 10:53:20 -0600881 txconf = txconf & ~(1<<TCR_PROBE_NOTIMESTAMP_SHIFT);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800882
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530883 txconf = txconf & ~TX_LOOPBACK_MASK;
884 txconf = txconf | (TX_LOOPBACK_NONE<<TX_LOOPBACK_SHIFT);
885 txconf = txconf & ~TCR_DPRETRY_MASK;
886 txconf = txconf & ~TCR_RTSRETRY_MASK;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800887 txconf = txconf | (priv->retry_data<<TX_DPRETRY_SHIFT);
888 txconf = txconf | (priv->retry_rts<<TX_RTSRETRY_SHIFT);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530889 txconf = txconf & ~(1<<TX_NOCRC_SHIFT);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800890
Larry Fingerd44eb882009-11-09 10:53:20 -0600891 if (priv->hw_plcp_len)
892 txconf = txconf & ~TCR_PLCP_LEN;
893 else
894 txconf = txconf | TCR_PLCP_LEN;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200895
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530896 txconf = txconf & ~TCR_MXDMA_MASK;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800897 txconf = txconf | (TCR_MXDMA_2048<<TCR_MXDMA_SHIFT);
898 txconf = txconf | TCR_CWMIN;
899 txconf = txconf | TCR_DISCW;
900
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200901 txconf = txconf | (1 << TX_NOICV_SHIFT);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800902
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530903 write_nic_dword(dev, TX_CONF, txconf);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800904
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800905 fix_tx_fifo(dev);
906
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530907 cmd = read_nic_byte(dev, CMD);
908 write_nic_byte(dev, CMD, cmd | (1<<CMD_TX_ENABLE_SHIFT));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800909
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530910 write_nic_dword(dev, TX_CONF, txconf);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800911}
912
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800913void rtl8180_beacon_tx_enable(struct net_device *dev)
914{
915 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
916
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530917 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800918 priv->dma_poll_stop_mask &= ~(TPPOLLSTOP_BQ);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530919 write_nic_byte(dev, TPPollStop, priv->dma_poll_mask);
920 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800921}
922
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800923void rtl8180_beacon_tx_disable(struct net_device *dev)
924{
925 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
926
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530927 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800928 priv->dma_poll_stop_mask |= TPPOLLSTOP_BQ;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530929 write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask);
930 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800931
932}
933
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800934void rtl8180_rtx_disable(struct net_device *dev)
935{
936 u8 cmd;
937 struct r8180_priv *priv = ieee80211_priv(dev);
938
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530939 cmd = read_nic_byte(dev, CMD);
940 write_nic_byte(dev, CMD, cmd & ~\
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800941 ((1<<CMD_RX_ENABLE_SHIFT)|(1<<CMD_TX_ENABLE_SHIFT)));
942 force_pci_posting(dev);
943 mdelay(10);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800944
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530945 if (!priv->rx_skb_complete)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800946 dev_kfree_skb_any(priv->rx_skb);
947}
948
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800949short alloc_tx_desc_ring(struct net_device *dev, int bufsize, int count,
950 int addr)
951{
952 int i;
953 u32 *desc;
954 u32 *tmp;
955 dma_addr_t dma_desc, dma_tmp;
956 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
957 struct pci_dev *pdev = priv->pdev;
958 void *buf;
959
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530960 if ((bufsize & 0xfff) != bufsize) {
961 DMESGE("TX buffer allocation too large");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800962 return 0;
963 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530964 desc = (u32 *)pci_alloc_consistent(pdev,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800965 sizeof(u32)*8*count+256, &dma_desc);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200966 if (desc == NULL)
967 return -1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800968
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200969 if (dma_desc & 0xff)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800970 /*
971 * descriptor's buffer must be 256 byte aligned
972 * we shouldn't be here, since we set DMA mask !
973 */
Larry Fingerbe286fd2009-04-18 21:09:08 -0500974 WARN(1, "DMA buffer is not aligned\n");
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +0200975
976 tmp = desc;
977
978 for (i = 0; i < count; i++) {
979 buf = (void *)pci_alloc_consistent(pdev, bufsize, &dma_tmp);
980 if (buf == NULL)
981 return -ENOMEM;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800982
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530983 switch (addr) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800984 case TX_MANAGEPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530985 if (-1 == buffer_add(&(priv->txmapbufs), buf, dma_tmp, NULL)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800986 DMESGE("Unable to allocate mem for buffer NP");
987 return -ENOMEM;
988 }
989 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800990 case TX_BKPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530991 if (-1 == buffer_add(&(priv->txbkpbufs), buf, dma_tmp, NULL)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800992 DMESGE("Unable to allocate mem for buffer LP");
993 return -ENOMEM;
994 }
995 break;
996 case TX_BEPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +0530997 if (-1 == buffer_add(&(priv->txbepbufs), buf, dma_tmp, NULL)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -0800998 DMESGE("Unable to allocate mem for buffer NP");
999 return -ENOMEM;
1000 }
1001 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001002 case TX_VIPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301003 if (-1 == buffer_add(&(priv->txvipbufs), buf, dma_tmp, NULL)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001004 DMESGE("Unable to allocate mem for buffer LP");
1005 return -ENOMEM;
1006 }
1007 break;
1008 case TX_VOPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301009 if (-1 == buffer_add(&(priv->txvopbufs), buf, dma_tmp, NULL)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001010 DMESGE("Unable to allocate mem for buffer NP");
1011 return -ENOMEM;
1012 }
1013 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001014 case TX_HIGHPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301015 if (-1 == buffer_add(&(priv->txhpbufs), buf, dma_tmp, NULL)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001016 DMESGE("Unable to allocate mem for buffer HP");
1017 return -ENOMEM;
1018 }
1019 break;
1020 case TX_BEACON_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301021 if (-1 == buffer_add(&(priv->txbeaconbufs), buf, dma_tmp, NULL)) {
1022 DMESGE("Unable to allocate mem for buffer BP");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001023 return -ENOMEM;
1024 }
1025 break;
1026 }
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301027 *tmp = *tmp & ~(1<<31); /* descriptor empty, owned by the drv */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001028 *(tmp+2) = (u32)dma_tmp;
1029 *(tmp+3) = bufsize;
1030
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301031 if (i+1 < count)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001032 *(tmp+4) = (u32)dma_desc+((i+1)*8*4);
1033 else
1034 *(tmp+4) = (u32)dma_desc;
1035
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301036 tmp = tmp+8;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001037 }
1038
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301039 switch (addr) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001040 case TX_MANAGEPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301041 priv->txmapringdma = dma_desc;
1042 priv->txmapring = desc;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001043 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001044 case TX_BKPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301045 priv->txbkpringdma = dma_desc;
1046 priv->txbkpring = desc;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001047 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001048 case TX_BEPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301049 priv->txbepringdma = dma_desc;
1050 priv->txbepring = desc;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001051 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001052 case TX_VIPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301053 priv->txvipringdma = dma_desc;
1054 priv->txvipring = desc;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001055 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001056 case TX_VOPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301057 priv->txvopringdma = dma_desc;
1058 priv->txvopring = desc;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001059 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001060 case TX_HIGHPRIORITY_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301061 priv->txhpringdma = dma_desc;
1062 priv->txhpring = desc;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001063 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001064 case TX_BEACON_RING_ADDR:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301065 priv->txbeaconringdma = dma_desc;
1066 priv->txbeaconring = desc;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001067 break;
1068
1069 }
1070
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001071 return 0;
1072}
1073
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001074void free_tx_desc_rings(struct net_device *dev)
1075{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001076 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301077 struct pci_dev *pdev = priv->pdev;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001078 int count = priv->txringcount;
1079
1080 pci_free_consistent(pdev, sizeof(u32)*8*count+256,
1081 priv->txmapring, priv->txmapringdma);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301082 buffer_free(dev, &(priv->txmapbufs), priv->txbuffsize, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001083
1084 pci_free_consistent(pdev, sizeof(u32)*8*count+256,
1085 priv->txbkpring, priv->txbkpringdma);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301086 buffer_free(dev, &(priv->txbkpbufs), priv->txbuffsize, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001087
1088 pci_free_consistent(pdev, sizeof(u32)*8*count+256,
1089 priv->txbepring, priv->txbepringdma);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301090 buffer_free(dev, &(priv->txbepbufs), priv->txbuffsize, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001091
1092 pci_free_consistent(pdev, sizeof(u32)*8*count+256,
1093 priv->txvipring, priv->txvipringdma);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301094 buffer_free(dev, &(priv->txvipbufs), priv->txbuffsize, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001095
1096 pci_free_consistent(pdev, sizeof(u32)*8*count+256,
1097 priv->txvopring, priv->txvopringdma);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301098 buffer_free(dev, &(priv->txvopbufs), priv->txbuffsize, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001099
1100 pci_free_consistent(pdev, sizeof(u32)*8*count+256,
1101 priv->txhpring, priv->txhpringdma);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301102 buffer_free(dev, &(priv->txhpbufs), priv->txbuffsize, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001103
1104 count = priv->txbeaconcount;
1105 pci_free_consistent(pdev, sizeof(u32)*8*count+256,
1106 priv->txbeaconring, priv->txbeaconringdma);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301107 buffer_free(dev, &(priv->txbeaconbufs), priv->txbuffsize, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001108}
1109
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001110void free_rx_desc_ring(struct net_device *dev)
1111{
1112 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1113 struct pci_dev *pdev = priv->pdev;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001114 int count = priv->rxringcount;
1115
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001116 pci_free_consistent(pdev, sizeof(u32)*8*count+256,
1117 priv->rxring, priv->rxringdma);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001118
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301119 buffer_free(dev, &(priv->rxbuffer), priv->rxbuffersize, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001120}
1121
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001122short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count)
1123{
1124 int i;
1125 u32 *desc;
1126 u32 *tmp;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301127 dma_addr_t dma_desc, dma_tmp;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001128 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301129 struct pci_dev *pdev = priv->pdev;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001130 void *buf;
1131 u8 rx_desc_size;
1132
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301133 rx_desc_size = 8; /* 4*8 = 32 bytes */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001134
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301135 if ((bufsize & 0xfff) != bufsize) {
1136 DMESGE("RX buffer allocation too large");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001137 return -1;
1138 }
1139
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301140 desc = (u32 *)pci_alloc_consistent(pdev, sizeof(u32)*rx_desc_size*count+256,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001141 &dma_desc);
1142
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001143 if (dma_desc & 0xff)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001144 /*
1145 * descriptor's buffer must be 256 byte aligned
1146 * should never happen since we specify the DMA mask
1147 */
Larry Fingerbe286fd2009-04-18 21:09:08 -05001148 WARN(1, "DMA buffer is not aligned\n");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001149
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301150 priv->rxring = desc;
1151 priv->rxringdma = dma_desc;
1152 tmp = desc;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001153
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001154 for (i = 0; i < count; i++) {
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301155 buf = kmalloc(bufsize * sizeof(u8), GFP_ATOMIC);
Joe Perches53756de2010-03-24 22:17:01 -07001156 if (buf == NULL) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001157 DMESGE("Failed to kmalloc RX buffer");
1158 return -1;
1159 }
1160
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301161 dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8),
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001162 PCI_DMA_FROMDEVICE);
1163
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301164 if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp,
1165 &(priv->rxbufferhead))) {
1166 DMESGE("Unable to allocate mem RX buf");
1167 return -1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001168 }
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301169 *tmp = 0; /* zero pads the header of the descriptor */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301170 *tmp = *tmp | (bufsize&0xfff);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001171 *(tmp+2) = (u32)dma_tmp;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301172 *tmp = *tmp | (1<<31); /* descriptor void, owned by the NIC */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001173
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301174 tmp = tmp+rx_desc_size;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001175 }
1176
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301177 *(tmp-rx_desc_size) = *(tmp-rx_desc_size) | (1<<30); /* this is the last descriptor */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001178
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001179 return 0;
1180}
1181
1182
1183void set_nic_rxring(struct net_device *dev)
1184{
1185 u8 pgreg;
1186 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1187
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301188 pgreg = read_nic_byte(dev, PGSELECT);
1189 write_nic_byte(dev, PGSELECT, pgreg & ~(1<<PGSELECT_PG_SHIFT));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001190
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301191 write_nic_dword(dev, RXRING_ADDR, priv->rxringdma);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001192}
1193
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001194void rtl8180_reset(struct net_device *dev)
1195{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001196 u8 cr;
1197
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001198 rtl8180_irq_disable(dev);
1199
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301200 cr = read_nic_byte(dev, CMD);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001201 cr = cr & 2;
1202 cr = cr | (1<<CMD_RST_SHIFT);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301203 write_nic_byte(dev, CMD, cr);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001204
1205 force_pci_posting(dev);
1206
1207 mdelay(200);
1208
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301209 if (read_nic_byte(dev, CMD) & (1<<CMD_RST_SHIFT))
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001210 DMESGW("Card reset timeout!");
1211 else
1212 DMESG("Card successfully reset");
1213
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301214 rtl8180_set_mode(dev, EPROM_CMD_LOAD);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001215 force_pci_posting(dev);
1216 mdelay(200);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001217}
1218
1219inline u16 ieeerate2rtlrate(int rate)
1220{
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301221 switch (rate) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001222 case 10:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001223 return 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001224 case 20:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001225 return 1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001226 case 55:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001227 return 2;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001228 case 110:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001229 return 3;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001230 case 60:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001231 return 4;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001232 case 90:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001233 return 5;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001234 case 120:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001235 return 6;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001236 case 180:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001237 return 7;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001238 case 240:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001239 return 8;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001240 case 360:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001241 return 9;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001242 case 480:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001243 return 10;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001244 case 540:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001245 return 11;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001246 default:
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001247 return 3;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001248 }
1249}
1250
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301251static u16 rtl_rate[] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540, 720};
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001252
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001253inline u16 rtl8180_rate2rate(short rate)
1254{
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001255 if (rate > 12)
1256 return 10;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001257 return rtl_rate[rate];
1258}
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001259
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001260inline u8 rtl8180_IsWirelessBMode(u16 rate)
1261{
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301262 if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220))
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001263 return 1;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001264 else
1265 return 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001266}
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001267
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001268u16 N_DBPSOfRate(u16 DataRate);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001269
1270u16 ComputeTxTime(u16 FrameLength, u16 DataRate, u8 bManagementFrame,
1271 u8 bShortPreamble)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001272{
1273 u16 FrameTime;
1274 u16 N_DBPS;
1275 u16 Ceiling;
1276
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001277 if (rtl8180_IsWirelessBMode(DataRate)) {
1278 if (bManagementFrame || !bShortPreamble || DataRate == 10)
1279 /* long preamble */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001280 FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10)));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001281 else
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001282 /* short preamble */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001283 FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10)));
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001284
1285 if ((FrameLength*8 % (DataRate/10)) != 0) /* get the ceilling */
1286 FrameTime++;
1287 } else { /* 802.11g DSSS-OFDM PLCP length field calculation. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001288 N_DBPS = N_DBPSOfRate(DataRate);
1289 Ceiling = (16 + 8*FrameLength + 6) / N_DBPS
1290 + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0);
1291 FrameTime = (u16)(16 + 4 + 4*Ceiling + 6);
1292 }
1293 return FrameTime;
1294}
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001295
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001296u16 N_DBPSOfRate(u16 DataRate)
1297{
1298 u16 N_DBPS = 24;
1299
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001300 switch (DataRate) {
1301 case 60:
1302 N_DBPS = 24;
1303 break;
1304 case 90:
1305 N_DBPS = 36;
1306 break;
1307 case 120:
1308 N_DBPS = 48;
1309 break;
1310 case 180:
1311 N_DBPS = 72;
1312 break;
1313 case 240:
1314 N_DBPS = 96;
1315 break;
1316 case 360:
1317 N_DBPS = 144;
1318 break;
1319 case 480:
1320 N_DBPS = 192;
1321 break;
1322 case 540:
1323 N_DBPS = 216;
1324 break;
1325 default:
1326 break;
1327 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001328
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001329 return N_DBPS;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001330}
1331
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301332/*
1333 * For Netgear case, they want good-looking singal strength.
1334 */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001335long NetgearSignalStrengthTranslate(long LastSS, long CurrSS)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001336{
1337 long RetSS;
1338
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301339 /* Step 1. Scale mapping. */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001340 if (CurrSS >= 71 && CurrSS <= 100)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001341 RetSS = 90 + ((CurrSS - 70) / 3);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001342 else if (CurrSS >= 41 && CurrSS <= 70)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001343 RetSS = 78 + ((CurrSS - 40) / 3);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001344 else if (CurrSS >= 31 && CurrSS <= 40)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001345 RetSS = 66 + (CurrSS - 30);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001346 else if (CurrSS >= 21 && CurrSS <= 30)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001347 RetSS = 54 + (CurrSS - 20);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001348 else if (CurrSS >= 5 && CurrSS <= 20)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001349 RetSS = 42 + (((CurrSS - 5) * 2) / 3);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001350 else if (CurrSS == 4)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001351 RetSS = 36;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001352 else if (CurrSS == 3)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001353 RetSS = 27;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001354 else if (CurrSS == 2)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001355 RetSS = 18;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001356 else if (CurrSS == 1)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001357 RetSS = 9;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001358 else
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001359 RetSS = CurrSS;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001360
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301361 /* Step 2. Smoothing. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301362 if (LastSS > 0)
1363 RetSS = ((LastSS * 5) + (RetSS) + 5) / 6;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001364
1365 return RetSS;
1366}
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001367
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301368/*
1369 * Translate 0-100 signal strength index into dBm.
1370 */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001371long TranslateToDbm8185(u8 SignalStrengthIndex)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001372{
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001373 long SignalPower;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001374
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301375 /* Translate to dBm (x=0.5y-95). */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001376 SignalPower = (long)((SignalStrengthIndex + 1) >> 1);
1377 SignalPower -= 95;
1378
1379 return SignalPower;
1380}
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001381
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301382/*
1383 * Perform signal smoothing for dynamic mechanism.
1384 * This is different with PerformSignalSmoothing8185 in smoothing fomula.
1385 * No dramatic adjustion is apply because dynamic mechanism need some degree
1386 * of correctness. Ported from 8187B.
1387 */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001388void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv,
1389 bool bCckRate)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001390{
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301391 /* Determin the current packet is CCK rate. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001392 priv->bCurCCKPkt = bCckRate;
1393
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001394 if (priv->UndecoratedSmoothedSS >= 0)
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301395 priv->UndecoratedSmoothedSS = ((priv->UndecoratedSmoothedSS * 5) + (priv->SignalStrength * 10)) / 6;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001396 else
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001397 priv->UndecoratedSmoothedSS = priv->SignalStrength * 10;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001398
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301399 priv->UndercorateSmoothedRxPower = ((priv->UndercorateSmoothedRxPower * 50) + (priv->RxPower * 11)) / 60;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001400
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001401 if (bCckRate)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001402 priv->CurCCKRSSI = priv->RSSI;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001403 else
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001404 priv->CurCCKRSSI = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001405}
1406
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001407
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301408/*
1409 * This is rough RX isr handling routine
1410 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001411void rtl8180_rx(struct net_device *dev)
1412{
1413 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1414 struct sk_buff *tmp_skb;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301415 short first, last;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001416 u32 len;
1417 int lastlen;
1418 unsigned char quality, signal;
1419 u8 rate;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301420 u32 *tmp, *tmp2;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001421 u8 rx_desc_size;
1422 u8 padding;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001423 char rxpower = 0;
1424 u32 RXAGC = 0;
1425 long RxAGC_dBm = 0;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301426 u8 LNA = 0, BB = 0;
John Churchcb73da22010-04-08 16:04:17 -05001427 u8 LNA_gain[4] = {02, 17, 29, 39};
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001428 u8 Antenna = 0;
Bartlomiej Zolnierkiewicz06043842009-07-13 20:01:44 +02001429 struct ieee80211_hdr_4addr *hdr;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301430 u16 fc, type;
1431 u8 bHwError = 0, bCRC = 0, bICV = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001432 bool bCckRate = false;
1433 u8 RSSI = 0;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001434 long SignalStrengthIndex = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001435 struct ieee80211_rx_stats stats = {
1436 .signal = 0,
1437 .noise = -98,
1438 .rate = 0,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001439 .freq = IEEE80211_24GHZ_BAND,
1440 };
1441
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001442 stats.nic_type = NIC_8185B;
1443 rx_desc_size = 8;
1444
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001445 if ((*(priv->rxringtail)) & (1<<31)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001446 /* we have got an RX int, but the descriptor
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301447 * we are pointing is empty */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001448
1449 priv->stats.rxnodata++;
1450 priv->ieee80211->stats.rx_errors++;
1451
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001452 tmp2 = NULL;
1453 tmp = priv->rxringtail;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301454 do {
1455 if (tmp == priv->rxring)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001456 tmp = priv->rxring + (priv->rxringcount - 1)*rx_desc_size;
1457 else
1458 tmp -= rx_desc_size;
1459
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301460 if (!(*tmp & (1<<31)))
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001461 tmp2 = tmp;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301462 } while (tmp != priv->rxring);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001463
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301464 if (tmp2)
1465 priv->rxringtail = tmp2;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001466 }
1467
1468 /* while there are filled descriptors */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301469 while (!(*(priv->rxringtail) & (1<<31))) {
1470 if (*(priv->rxringtail) & (1<<26))
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001471 DMESGW("RX buffer overflow");
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301472 if (*(priv->rxringtail) & (1<<12))
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001473 priv->stats.rxicverr++;
1474
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301475 if (*(priv->rxringtail) & (1<<27)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001476 priv->stats.rxdmafail++;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301477 /* DMESG("EE: RX DMA FAILED at buffer pointed by descriptor %x",(u32)priv->rxringtail); */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001478 goto drop;
1479 }
1480
1481 pci_dma_sync_single_for_cpu(priv->pdev,
1482 priv->rxbuffer->dma,
1483 priv->rxbuffersize * \
1484 sizeof(u8),
1485 PCI_DMA_FROMDEVICE);
1486
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301487 first = *(priv->rxringtail) & (1<<29) ? 1 : 0;
1488 if (first)
1489 priv->rx_prevlen = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001490
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301491 last = *(priv->rxringtail) & (1<<28) ? 1 : 0;
1492 if (last) {
1493 lastlen = ((*priv->rxringtail) & 0xfff);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001494
1495 /* if the last descriptor (that should
1496 * tell us the total packet len) tell
1497 * us something less than the descriptors
1498 * len we had until now, then there is some
1499 * problem..
1500 * workaround to prevent kernel panic
1501 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301502 if (lastlen < priv->rx_prevlen)
1503 len = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001504 else
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301505 len = lastlen-priv->rx_prevlen;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001506
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301507 if (*(priv->rxringtail) & (1<<13)) {
1508 if ((*(priv->rxringtail) & 0xfff) < 500)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001509 priv->stats.rxcrcerrmin++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301510 else if ((*(priv->rxringtail) & 0x0fff) > 1000)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001511 priv->stats.rxcrcerrmax++;
1512 else
1513 priv->stats.rxcrcerrmid++;
1514
1515 }
1516
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301517 } else {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001518 len = priv->rxbuffersize;
1519 }
1520
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301521 if (first && last) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001522 padding = ((*(priv->rxringtail+3))&(0x04000000))>>26;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301523 } else if (first) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001524 padding = ((*(priv->rxringtail+3))&(0x04000000))>>26;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301525 if (padding)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001526 len -= 2;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301527 } else {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001528 padding = 0;
1529 }
John Churchcb73da22010-04-08 16:04:17 -05001530 padding = 0;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301531 priv->rx_prevlen += len;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001532
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301533 if (priv->rx_prevlen > MAX_FRAG_THRESHOLD + 100) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001534 /* HW is probably passing several buggy frames
1535 * without FD or LD flag set.
1536 * Throw this garbage away to prevent skb
1537 * memory exausting
1538 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301539 if (!priv->rx_skb_complete)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001540 dev_kfree_skb_any(priv->rx_skb);
1541 priv->rx_skb_complete = 1;
1542 }
1543
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301544 signal = (unsigned char)(((*(priv->rxringtail+3)) & (0x00ff0000))>>16);
Larry Finger19941302010-01-25 13:11:49 -06001545 signal = (signal & 0xfe) >> 1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001546
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301547 quality = (unsigned char)((*(priv->rxringtail+3)) & (0xff));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001548
1549 stats.mac_time[0] = *(priv->rxringtail+1);
1550 stats.mac_time[1] = *(priv->rxringtail+2);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301551 rxpower = ((char)(((*(priv->rxringtail+4)) & (0x00ff0000))>>16))/2 - 42;
1552 RSSI = ((u8)(((*(priv->rxringtail+3)) & (0x0000ff00))>>8)) & (0x7f);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001553
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301554 rate = ((*(priv->rxringtail)) &
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001555 ((1<<23)|(1<<22)|(1<<21)|(1<<20)))>>20;
1556
1557 stats.rate = rtl8180_rate2rate(rate);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301558 Antenna = (((*(priv->rxringtail+3)) & (0x00008000)) == 0) ? 0 : 1;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301559 if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */
1560 RxAGC_dBm = rxpower+1; /* bias */
1561 } else { /* CCK rate. */
1562 RxAGC_dBm = signal; /* bit 0 discard */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001563
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301564 LNA = (u8) (RxAGC_dBm & 0x60) >> 5; /* bit 6~ bit 5 */
1565 BB = (u8) (RxAGC_dBm & 0x1F); /* bit 4 ~ bit 0 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001566
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301567 RxAGC_dBm = -(LNA_gain[LNA] + (BB*2)); /* Pin_11b=-(LNA_gain+BB_gain) (dBm) */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001568
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301569 RxAGC_dBm += 4; /* bias */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001570 }
1571
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301572 if (RxAGC_dBm & 0x80) /* absolute value */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301573 RXAGC = ~(RxAGC_dBm)+1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001574 bCckRate = rtl8180_IsWirelessBMode(stats.rate);
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301575 /* Translate RXAGC into 1-100. */
1576 if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301577 if (RXAGC > 90)
1578 RXAGC = 90;
1579 else if (RXAGC < 25)
1580 RXAGC = 25;
1581 RXAGC = (90-RXAGC)*100/65;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301582 } else { /* CCK rate. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301583 if (RXAGC > 95)
1584 RXAGC = 95;
1585 else if (RXAGC < 30)
1586 RXAGC = 30;
1587 RXAGC = (95-RXAGC)*100/65;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001588 }
1589 priv->SignalStrength = (u8)RXAGC;
Larry Finger19941302010-01-25 13:11:49 -06001590 priv->RecvSignalPower = RxAGC_dBm;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001591 priv->RxPower = rxpower;
1592 priv->RSSI = RSSI;
Larry Finger19941302010-01-25 13:11:49 -06001593 /* SQ translation formula is provided by SD3 DZ. 2006.06.27 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301594 if (quality >= 127)
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001595 quality = 1; /*0; */ /* 0 will cause epc to show signal zero , walk around now; */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301596 else if (quality < 27)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001597 quality = 100;
1598 else
1599 quality = 127 - quality;
1600 priv->SignalQuality = quality;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001601
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301602 stats.signal = (u8)quality; /*priv->wstats.qual.level = priv->SignalStrength; */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001603 stats.signalstrength = RXAGC;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301604 if (stats.signalstrength > 100)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001605 stats.signalstrength = 100;
1606 stats.signalstrength = (stats.signalstrength * 70)/100 + 30;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301607 /* printk("==========================>rx : RXAGC is %d,signalstrength is %d\n",RXAGC,stats.signalstrength); */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001608 stats.rssi = priv->wstats.qual.qual = priv->SignalQuality;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301609 stats.noise = priv->wstats.qual.noise = 100 - priv->wstats.qual.qual;
1610 bHwError = (((*(priv->rxringtail)) & (0x00000fff)) == 4080) | (((*(priv->rxringtail)) & (0x04000000)) != 0)
1611 | (((*(priv->rxringtail)) & (0x08000000)) != 0) | (((~(*(priv->rxringtail))) & (0x10000000)) != 0) | (((~(*(priv->rxringtail))) & (0x20000000)) != 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001612 bCRC = ((*(priv->rxringtail)) & (0x00002000)) >> 13;
1613 bICV = ((*(priv->rxringtail)) & (0x00001000)) >> 12;
Bartlomiej Zolnierkiewicz06043842009-07-13 20:01:44 +02001614 hdr = (struct ieee80211_hdr_4addr *)priv->rxbuffer->buf;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001615 fc = le16_to_cpu(hdr->frame_ctl);
John Churchcb73da22010-04-08 16:04:17 -05001616 type = WLAN_FC_GET_TYPE(fc);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001617
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301618 if ((IEEE80211_FTYPE_CTL != type) &&
1619 (eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
1620 && (!bHwError) && (!bCRC) && (!bICV)) {
Larry Finger19941302010-01-25 13:11:49 -06001621 /* Perform signal smoothing for dynamic
1622 * mechanism on demand. This is different
1623 * with PerformSignalSmoothing8185 in smoothing
1624 * fomula. No dramatic adjustion is apply
1625 * because dynamic mechanism need some degree
1626 * of correctness. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301627 PerformUndecoratedSignalSmoothing8185(priv, bCckRate);
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301628
1629 /* For good-looking singal strength. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001630 SignalStrengthIndex = NetgearSignalStrengthTranslate(
1631 priv->LastSignalStrengthInPercent,
1632 priv->SignalStrength);
1633
1634 priv->LastSignalStrengthInPercent = SignalStrengthIndex;
1635 priv->Stats_SignalStrength = TranslateToDbm8185((u8)SignalStrengthIndex);
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301636 /*
1637 * We need more correct power of received packets and the "SignalStrength" of RxStats is beautified,
1638 * so we record the correct power here.
1639 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301640 priv->Stats_SignalQuality = (long)(priv->Stats_SignalQuality * 5 + (long)priv->SignalQuality + 5) / 6;
1641 priv->Stats_RecvSignalPower = (long)(priv->Stats_RecvSignalPower * 5 + priv->RecvSignalPower - 1) / 6;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001642
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301643 /* Figure out which antenna that received the lasted packet. */
1644 priv->LastRxPktAntenna = Antenna ? 1 : 0; /* 0: aux, 1: main. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301645 SwAntennaDiversityRxOk8185(dev, priv->SignalStrength);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001646 }
1647
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301648 if (first) {
1649 if (!priv->rx_skb_complete) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001650 /* seems that HW sometimes fails to reiceve and
1651 doesn't provide the last descriptor */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001652 dev_kfree_skb_any(priv->rx_skb);
1653 priv->stats.rxnolast++;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001654 }
1655 /* support for prism header has been originally added by Christian */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301656 if (priv->prism_hdr && priv->ieee80211->iw_mode == IW_MODE_MONITOR) {
1657
1658 } else {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001659 priv->rx_skb = dev_alloc_skb(len+2);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301660 if (!priv->rx_skb)
1661 goto drop;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001662 }
1663
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301664 priv->rx_skb_complete = 0;
1665 priv->rx_skb->dev = dev;
1666 } else {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001667 /* if we are here we should have already RXed
1668 * the first frame.
1669 * If we get here and the skb is not allocated then
1670 * we have just throw out garbage (skb not allocated)
1671 * and we are still rxing garbage....
1672 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301673 if (!priv->rx_skb_complete) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001674
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301675 tmp_skb = dev_alloc_skb(priv->rx_skb->len+len+2);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001676
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301677 if (!tmp_skb)
1678 goto drop;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001679
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301680 tmp_skb->dev = dev;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001681
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301682 memcpy(skb_put(tmp_skb, priv->rx_skb->len),
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001683 priv->rx_skb->data,
1684 priv->rx_skb->len);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001685
1686 dev_kfree_skb_any(priv->rx_skb);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001687
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301688 priv->rx_skb = tmp_skb;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001689 }
1690 }
Bartlomiej Zolnierkiewiczff954852009-06-28 16:19:38 +02001691
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301692 if (!priv->rx_skb_complete) {
1693 if (padding) {
1694 memcpy(skb_put(priv->rx_skb, len),
1695 (((unsigned char *)priv->rxbuffer->buf) + 2), len);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001696 } else {
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301697 memcpy(skb_put(priv->rx_skb, len),
1698 priv->rxbuffer->buf, len);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001699 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001700 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001701
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301702 if (last && !priv->rx_skb_complete) {
1703 if (priv->rx_skb->len > 4)
1704 skb_trim(priv->rx_skb, priv->rx_skb->len-4);
1705 if (!ieee80211_rtl_rx(priv->ieee80211,
Larry Finger19941302010-01-25 13:11:49 -06001706 priv->rx_skb, &stats))
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001707 dev_kfree_skb_any(priv->rx_skb);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301708 priv->rx_skb_complete = 1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001709 }
1710
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001711 pci_dma_sync_single_for_device(priv->pdev,
1712 priv->rxbuffer->dma,
1713 priv->rxbuffersize * \
1714 sizeof(u8),
1715 PCI_DMA_FROMDEVICE);
1716
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301717drop: /* this is used when we have not enough mem */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001718 /* restore the descriptor */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301719 *(priv->rxringtail+2) = priv->rxbuffer->dma;
1720 *(priv->rxringtail) = *(priv->rxringtail) & ~0xfff;
1721 *(priv->rxringtail) =
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001722 *(priv->rxringtail) | priv->rxbuffersize;
1723
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301724 *(priv->rxringtail) =
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001725 *(priv->rxringtail) | (1<<31);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001726
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301727 priv->rxringtail += rx_desc_size;
1728 if (priv->rxringtail >=
1729 (priv->rxring)+(priv->rxringcount)*rx_desc_size)
1730 priv->rxringtail = priv->rxring;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001731
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301732 priv->rxbuffer = (priv->rxbuffer->next);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001733 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001734}
1735
1736
1737void rtl8180_dma_kick(struct net_device *dev, int priority)
1738{
1739 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1740
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301741 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001742 write_nic_byte(dev, TX_DMA_POLLING,
1743 (1 << (priority + 1)) | priv->dma_poll_mask);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301744 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001745
1746 force_pci_posting(dev);
1747}
1748
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001749void rtl8180_data_hard_stop(struct net_device *dev)
1750{
1751 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1752
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301753 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001754 priv->dma_poll_stop_mask |= TPPOLLSTOP_AC_VIQ;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301755 write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask);
1756 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001757}
1758
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001759void rtl8180_data_hard_resume(struct net_device *dev)
1760{
1761 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1762
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301763 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001764 priv->dma_poll_stop_mask &= ~(TPPOLLSTOP_AC_VIQ);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301765 write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask);
1766 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001767}
1768
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301769/*
1770 * This function TX data frames when the ieee80211 stack requires this.
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001771 * It checks also if we need to stop the ieee tx queue, eventually do it
1772 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301773void rtl8180_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int
1774rate) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001775 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
1776 int mode;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301777 struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *) skb->data;
Larry Fingerb6b1ac62010-01-14 13:13:47 -06001778 short morefrag = (h->frame_control) & IEEE80211_FCTL_MOREFRAGS;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001779 unsigned long flags;
1780 int priority;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001781
1782 mode = priv->ieee80211->iw_mode;
1783
1784 rate = ieeerate2rtlrate(rate);
1785 /*
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301786 * This function doesn't require lock because we make
1787 * sure it's called with the tx_lock already acquired.
1788 * this come from the kernel's hard_xmit callback (through
1789 * the ieee stack, or from the try_wake_queue (again through
1790 * the ieee stack.
1791 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001792 priority = AC2Q(skb->priority);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301793 spin_lock_irqsave(&priv->tx_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001794
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301795 if (priv->ieee80211->bHwRadioOff) {
1796 spin_unlock_irqrestore(&priv->tx_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001797
1798 return;
1799 }
1800
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301801 if (!check_nic_enought_desc(dev, priority)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001802 DMESGW("Error: no descriptor left by previous TX (avail %d) ",
1803 get_curr_tx_free_desc(dev, priority));
George Kadianakisdf574b82009-12-17 01:16:00 +02001804 ieee80211_rtl_stop_queue(priv->ieee80211);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001805 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301806 rtl8180_tx(dev, skb->data, skb->len, priority, morefrag, 0, rate);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001807 if (!check_nic_enought_desc(dev, priority))
George Kadianakisdf574b82009-12-17 01:16:00 +02001808 ieee80211_rtl_stop_queue(priv->ieee80211);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001809
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301810 spin_unlock_irqrestore(&priv->tx_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001811}
1812
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301813/*
1814 * This is a rough attempt to TX a frame
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001815 * This is called by the ieee 80211 stack to TX management frames.
1816 * If the ring is full packet are dropped (for data frame the queue
1817 * is stopped before this can happen). For this reason it is better
1818 * if the descriptors are larger than the largest management frame
1819 * we intend to TX: i'm unsure what the HW does if it will not found
1820 * the last fragment of a frame because it has been dropped...
1821 * Since queues for Management and Data frames are different we
1822 * might use a different lock than tx_lock (for example mgmt_tx_lock)
1823 */
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301824/* these function may loops if invoked with 0 descriptors or 0 len buffer */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301825int rtl8180_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001826{
1827 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001828 unsigned long flags;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001829 int priority;
1830
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001831 priority = MANAGE_PRIORITY;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001832
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301833 spin_lock_irqsave(&priv->tx_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001834
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02001835 if (priv->ieee80211->bHwRadioOff) {
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301836 spin_unlock_irqrestore(&priv->tx_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001837 dev_kfree_skb_any(skb);
Patrick McHardyec634fe2009-07-05 19:23:38 -07001838 return NETDEV_TX_OK;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001839 }
1840
1841 rtl8180_tx(dev, skb->data, skb->len, priority,
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301842 0, 0, ieeerate2rtlrate(priv->ieee80211->basic_rate));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001843
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301844 priv->ieee80211->stats.tx_bytes += skb->len;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001845 priv->ieee80211->stats.tx_packets++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301846 spin_unlock_irqrestore(&priv->tx_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001847
1848 dev_kfree_skb_any(skb);
Patrick McHardyec634fe2009-07-05 19:23:38 -07001849 return NETDEV_TX_OK;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001850}
1851
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301852/* longpre 144+48 shortpre 72+24 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301853u16 rtl8180_len2duration(u32 len, short rate, short *ext)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001854{
1855 u16 duration;
1856 u16 drift;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301857 *ext = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001858
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301859 switch (rate) {
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301860 case 0: /* 1mbps */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301861 *ext = 0;
1862 duration = ((len+4)<<4) / 0x2;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001863 drift = ((len+4)<<4) % 0x2;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301864 if (drift == 0)
1865 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001866 duration++;
1867 break;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301868 case 1: /* 2mbps */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301869 *ext = 0;
1870 duration = ((len+4)<<4) / 0x4;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001871 drift = ((len+4)<<4) % 0x4;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301872 if (drift == 0)
1873 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001874 duration++;
1875 break;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301876 case 2: /* 5.5mbps */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301877 *ext = 0;
1878 duration = ((len+4)<<4) / 0xb;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001879 drift = ((len+4)<<4) % 0xb;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301880 if (drift == 0)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001881 break;
1882 duration++;
1883 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001884 default:
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301885 case 3: /* 11mbps */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301886 *ext = 0;
1887 duration = ((len+4)<<4) / 0x16;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001888 drift = ((len+4)<<4) % 0x16;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301889 if (drift == 0)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001890 break;
1891 duration++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301892 if (drift > 6)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001893 break;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301894 *ext = 1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001895 break;
1896 }
1897
1898 return duration;
1899}
1900
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001901void rtl8180_prepare_beacon(struct net_device *dev)
1902{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001903 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001904 struct sk_buff *skb;
1905
1906 u16 word = read_nic_word(dev, BcnItv);
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301907 word &= ~BcnItv_BcnItv; /* clear Bcn_Itv */
1908 word |= cpu_to_le16(priv->ieee80211->current_network.beacon_interval); /* 0x64; */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001909 write_nic_word(dev, BcnItv, word);
1910
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001911 skb = ieee80211_get_beacon(priv->ieee80211);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301912 if (skb) {
1913 rtl8180_tx(dev, skb->data, skb->len, BEACON_PRIORITY,
1914 0, 0, ieeerate2rtlrate(priv->ieee80211->basic_rate));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001915 dev_kfree_skb_any(skb);
1916 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001917}
1918
Prashant P. Shah3f56c102010-05-13 23:09:08 +05301919/*
1920 * This function do the real dirty work: it enqueues a TX command
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001921 * descriptor in the ring buffer, copyes the frame in a TX buffer
1922 * and kicks the NIC to ensure it does the DMA transfer.
1923 */
1924short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority,
1925 short morefrag, short descfrag, int rate)
1926{
1927 struct r8180_priv *priv = ieee80211_priv(dev);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301928 u32 *tail, *temp_tail;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001929 u32 *begin;
1930 u32 *buf;
1931 int i;
1932 int remain;
1933 int buflen;
1934 int count;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001935 u16 duration;
1936 short ext;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301937 struct buffer *buflist;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001938 struct ieee80211_hdr_3addr *frag_hdr = (struct ieee80211_hdr_3addr *)txbuf;
1939 u8 dest[ETH_ALEN];
1940 u8 bUseShortPreamble = 0;
1941 u8 bCTSEnable = 0;
1942 u8 bRTSEnable = 0;
John Churchcb73da22010-04-08 16:04:17 -05001943 u16 Duration = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001944 u16 RtsDur = 0;
1945 u16 ThisFrameTime = 0;
1946 u16 TxDescDuration = 0;
John Churchcb73da22010-04-08 16:04:17 -05001947 u8 ownbit_flag = false;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001948
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301949 switch (priority) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001950 case MANAGE_PRIORITY:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301951 tail = priv->txmapringtail;
1952 begin = priv->txmapring;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001953 buflist = priv->txmapbufstail;
1954 count = priv->txringcount;
1955 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001956 case BK_PRIORITY:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301957 tail = priv->txbkpringtail;
1958 begin = priv->txbkpring;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001959 buflist = priv->txbkpbufstail;
1960 count = priv->txringcount;
1961 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001962 case BE_PRIORITY:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301963 tail = priv->txbepringtail;
1964 begin = priv->txbepring;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001965 buflist = priv->txbepbufstail;
1966 count = priv->txringcount;
1967 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001968 case VI_PRIORITY:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301969 tail = priv->txvipringtail;
1970 begin = priv->txvipring;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001971 buflist = priv->txvipbufstail;
1972 count = priv->txringcount;
1973 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001974 case VO_PRIORITY:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301975 tail = priv->txvopringtail;
1976 begin = priv->txvopring;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001977 buflist = priv->txvopbufstail;
1978 count = priv->txringcount;
1979 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001980 case HI_PRIORITY:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301981 tail = priv->txhpringtail;
1982 begin = priv->txhpring;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001983 buflist = priv->txhpbufstail;
1984 count = priv->txringcount;
1985 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001986 case BEACON_PRIORITY:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301987 tail = priv->txbeaconringtail;
1988 begin = priv->txbeaconring;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001989 buflist = priv->txbeaconbufstail;
1990 count = priv->txbeaconcount;
1991 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001992 default:
1993 return -1;
1994 break;
John Churchcb73da22010-04-08 16:04:17 -05001995 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001996
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08001997 memcpy(&dest, frag_hdr->addr1, ETH_ALEN);
1998 if (is_multicast_ether_addr(dest) ||
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05301999 is_broadcast_ether_addr(dest)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002000 Duration = 0;
2001 RtsDur = 0;
2002 bRTSEnable = 0;
2003 bCTSEnable = 0;
2004
2005 ThisFrameTime = ComputeTxTime(len + sCrcLng, rtl8180_rate2rate(rate), 0, bUseShortPreamble);
2006 TxDescDuration = ThisFrameTime;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302007 } else { /* Unicast packet */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002008 u16 AckTime;
2009
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302010 /* YJ,add,080828,for Keep alive */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002011 priv->NumTxUnicast++;
2012
Larry Finger19941302010-01-25 13:11:49 -06002013 /* Figure out ACK rate according to BSS basic rate
2014 * and Tx rate. */
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302015 AckTime = ComputeTxTime(14, 10, 0, 0); /* AckCTSLng = 14 use 1M bps send */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002016
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302017 if (((len + sCrcLng) > priv->rts) && priv->rts) { /* RTS/CTS. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002018 u16 RtsTime, CtsTime;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302019 /* u16 CtsRate; */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002020 bRTSEnable = 1;
2021 bCTSEnable = 0;
2022
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302023 /* Rate and time required for RTS. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302024 RtsTime = ComputeTxTime(sAckCtsLng/8, priv->ieee80211->basic_rate, 0, 0);
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302025 /* Rate and time required for CTS. */
2026 CtsTime = ComputeTxTime(14, 10, 0, 0); /* AckCTSLng = 14 use 1M bps send */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002027
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302028 /* Figure out time required to transmit this frame. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002029 ThisFrameTime = ComputeTxTime(len + sCrcLng,
2030 rtl8180_rate2rate(rate),
2031 0,
2032 bUseShortPreamble);
2033
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302034 /* RTS-CTS-ThisFrame-ACK. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002035 RtsDur = CtsTime + ThisFrameTime + AckTime + 3*aSifsTime;
2036
2037 TxDescDuration = RtsTime + RtsDur;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302038 } else { /* Normal case. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002039 bCTSEnable = 0;
2040 bRTSEnable = 0;
2041 RtsDur = 0;
2042
2043 ThisFrameTime = ComputeTxTime(len + sCrcLng, rtl8180_rate2rate(rate), 0, bUseShortPreamble);
2044 TxDescDuration = ThisFrameTime + aSifsTime + AckTime;
2045 }
2046
Larry Fingerb6b1ac62010-01-14 13:13:47 -06002047 if (!(frag_hdr->frame_control & IEEE80211_FCTL_MOREFRAGS)) {
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302048 /* ThisFrame-ACK. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002049 Duration = aSifsTime + AckTime;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302050 } else { /* One or more fragments remained. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002051 u16 NextFragTime;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302052 NextFragTime = ComputeTxTime(len + sCrcLng, /* pretend following packet length equal current packet */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002053 rtl8180_rate2rate(rate),
2054 0,
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302055 bUseShortPreamble);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002056
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302057 /* ThisFrag-ACk-NextFrag-ACK. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002058 Duration = NextFragTime + 3*aSifsTime + 2*AckTime;
2059 }
2060
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302061 } /* End of Unicast packet */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002062
2063 frag_hdr->duration_id = Duration;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002064
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302065 buflen = priv->txbuffsize;
2066 remain = len;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002067 temp_tail = tail;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002068
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302069 while (remain != 0) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002070 mb();
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302071 if (!buflist) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002072 DMESGE("TX buffer error, cannot TX frames. pri %d.", priority);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002073 return -1;
2074 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302075 buf = buflist->buf;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002076
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002077 if ((*tail & (1 << 31)) && (priority != BEACON_PRIORITY)) {
2078 DMESGW("No more TX desc, returning %x of %x",
2079 remain, len);
2080 priv->stats.txrdu++;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002081 return remain;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002082 }
2083
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302084 *tail = 0; /* zeroes header */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002085 *(tail+1) = 0;
2086 *(tail+3) = 0;
2087 *(tail+5) = 0;
2088 *(tail+6) = 0;
2089 *(tail+7) = 0;
2090
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302091 /* FIXME: this should be triggered by HW encryption parameters.*/
Larry Fingerd44eb882009-11-09 10:53:20 -06002092 *tail |= (1<<15); /* no encrypt */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002093
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302094 if (remain == len && !descfrag) {
Larry Finger19941302010-01-25 13:11:49 -06002095 ownbit_flag = false;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302096 *tail = *tail | (1<<29) ; /* fist segment of the packet */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302097 *tail = *tail | (len);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002098 } else {
2099 ownbit_flag = true;
2100 }
2101
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302102 for (i = 0; i < buflen && remain > 0; i++, remain--) {
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302103 ((u8 *)buf)[i] = txbuf[i]; /* copy data into descriptor pointed DMAble buffer */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302104 if (remain == 4 && i+4 >= buflen)
2105 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002106 /* ensure the last desc has at least 4 bytes payload */
2107
2108 }
2109 txbuf = txbuf + i;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302110 *(tail+3) = *(tail+3) & ~0xfff;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302111 *(tail+3) = *(tail+3) | i; /* buffer length */
2112 /* Use short preamble or not */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002113 if (priv->ieee80211->current_network.capability&WLAN_CAPABILITY_SHORT_PREAMBLE)
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302114 if (priv->plcp_preamble_mode == 1 && rate != 0) /* short mode now, not long! */
2115 ; /* *tail |= (1<<16); */ /* enable short preamble mode. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002116
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302117 if (bCTSEnable)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002118 *tail |= (1<<18);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002119
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302120 if (bRTSEnable) { /* rts enable */
2121 *tail |= ((ieeerate2rtlrate(priv->ieee80211->basic_rate))<<19); /* RTS RATE */
2122 *tail |= (1<<23); /* rts enable */
2123 *(tail+1) |= (RtsDur&0xffff); /* RTS Duration */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002124 }
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302125 *(tail+3) |= ((TxDescDuration&0xffff)<<16); /* DURATION */
2126 /* *(tail+3) |= (0xe6<<16); */
2127 *(tail+5) |= (11<<8); /* (priv->retry_data<<8); */ /* retry lim; */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002128
2129 *tail = *tail | ((rate&0xf) << 24);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002130
2131 /* hw_plcp_len is not used for rtl8180 chip */
2132 /* FIXME */
Larry Fingerd44eb882009-11-09 10:53:20 -06002133 if (!priv->hw_plcp_len) {
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002134 duration = rtl8180_len2duration(len, rate, &ext);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002135 *(tail+1) = *(tail+1) | ((duration & 0x7fff)<<16);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302136 if (ext)
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302137 *(tail+1) = *(tail+1) | (1<<31); /* plcp length extension */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002138 }
2139
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302140 if (morefrag)
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302141 *tail = (*tail) | (1<<17); /* more fragment */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302142 if (!remain)
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302143 *tail = (*tail) | (1<<28); /* last segment of frame */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002144
John Churchcb73da22010-04-08 16:04:17 -05002145 *(tail+5) = *(tail+5)|(2<<27);
2146 *(tail+7) = *(tail+7)|(1<<4);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002147
2148 wmb();
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302149 if (ownbit_flag)
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302150 *tail = *tail | (1<<31); /* descriptor ready to be txed */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002151
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302152 if ((tail - begin)/8 == count-1)
2153 tail = begin;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002154 else
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302155 tail = tail+8;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002156
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302157 buflist = buflist->next;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002158
2159 mb();
2160
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302161 switch (priority) {
2162 case MANAGE_PRIORITY:
2163 priv->txmapringtail = tail;
2164 priv->txmapbufstail = buflist;
2165 break;
2166 case BK_PRIORITY:
2167 priv->txbkpringtail = tail;
2168 priv->txbkpbufstail = buflist;
2169 break;
2170 case BE_PRIORITY:
2171 priv->txbepringtail = tail;
2172 priv->txbepbufstail = buflist;
2173 break;
2174 case VI_PRIORITY:
2175 priv->txvipringtail = tail;
2176 priv->txvipbufstail = buflist;
2177 break;
2178 case VO_PRIORITY:
2179 priv->txvopringtail = tail;
2180 priv->txvopbufstail = buflist;
2181 break;
2182 case HI_PRIORITY:
2183 priv->txhpringtail = tail;
2184 priv->txhpbufstail = buflist;
2185 break;
2186 case BEACON_PRIORITY:
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302187 /*
2188 * The HW seems to be happy with the 1st
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302189 * descriptor filled and the 2nd empty...
2190 * So always update descriptor 1 and never
2191 * touch 2nd
2192 */
2193 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002194 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002195 }
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302196 *temp_tail = *temp_tail | (1<<31); /* descriptor ready to be txed */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302197 rtl8180_dma_kick(dev, priority);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002198
2199 return 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002200}
2201
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302202void rtl8180_irq_rx_tasklet(struct r8180_priv *priv);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002203
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002204void rtl8180_link_change(struct net_device *dev)
2205{
2206 struct r8180_priv *priv = ieee80211_priv(dev);
2207 u16 beacon_interval;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002208 struct ieee80211_network *net = &priv->ieee80211->current_network;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002209
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002210 rtl8180_update_msr(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002211
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302212 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002213
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302214 write_nic_dword(dev, BSSID, ((u32 *)net->bssid)[0]);
2215 write_nic_word(dev, BSSID+4, ((u16 *)net->bssid)[2]);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002216
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302217 beacon_interval = read_nic_dword(dev, BEACON_INTERVAL);
2218 beacon_interval &= ~BEACON_INTERVAL_MASK;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002219 beacon_interval |= net->beacon_interval;
2220 write_nic_dword(dev, BEACON_INTERVAL, beacon_interval);
2221
2222 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
2223
Larry Fingerd44eb882009-11-09 10:53:20 -06002224 rtl8180_set_chan(dev, priv->chan);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002225}
2226
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302227void rtl8180_rq_tx_ack(struct net_device *dev)
2228{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002229
2230 struct r8180_priv *priv = ieee80211_priv(dev);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002231
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302232 write_nic_byte(dev, CONFIG4, read_nic_byte(dev, CONFIG4) | CONFIG4_PWRMGT);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002233 priv->ack_tx_to_ieee = 1;
2234}
2235
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302236short rtl8180_is_tx_queue_empty(struct net_device *dev)
2237{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002238
2239 struct r8180_priv *priv = ieee80211_priv(dev);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302240 u32 *d;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002241
2242 for (d = priv->txmapring;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302243 d < priv->txmapring + priv->txringcount; d += 8)
2244 if (*d & (1<<31))
2245 return 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002246
2247 for (d = priv->txbkpring;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302248 d < priv->txbkpring + priv->txringcount; d += 8)
2249 if (*d & (1<<31))
2250 return 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002251
2252 for (d = priv->txbepring;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302253 d < priv->txbepring + priv->txringcount; d += 8)
2254 if (*d & (1<<31))
2255 return 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002256
2257 for (d = priv->txvipring;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302258 d < priv->txvipring + priv->txringcount; d += 8)
2259 if (*d & (1<<31))
2260 return 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002261
2262 for (d = priv->txvopring;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302263 d < priv->txvopring + priv->txringcount; d += 8)
2264 if (*d & (1<<31))
2265 return 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002266
2267 for (d = priv->txhpring;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302268 d < priv->txhpring + priv->txringcount; d += 8)
2269 if (*d & (1<<31))
2270 return 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002271 return 1;
2272}
2273/* FIXME FIXME 5msecs is random */
2274#define HW_WAKE_DELAY 5
2275
2276void rtl8180_hw_wakeup(struct net_device *dev)
2277{
2278 unsigned long flags;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002279 struct r8180_priv *priv = ieee80211_priv(dev);
2280
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302281 spin_lock_irqsave(&priv->ps_lock, flags);
2282 write_nic_byte(dev, CONFIG4, read_nic_byte(dev, CONFIG4) & ~CONFIG4_PWRMGT);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002283 if (priv->rf_wakeup)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002284 priv->rf_wakeup(dev);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302285 spin_unlock_irqrestore(&priv->ps_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002286}
2287
2288void rtl8180_hw_sleep_down(struct net_device *dev)
2289{
John Churchcb73da22010-04-08 16:04:17 -05002290 unsigned long flags;
2291 struct r8180_priv *priv = ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002292
John Churchcb73da22010-04-08 16:04:17 -05002293 spin_lock_irqsave(&priv->ps_lock, flags);
2294 if (priv->rf_sleep)
2295 priv->rf_sleep(dev);
2296 spin_unlock_irqrestore(&priv->ps_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002297}
2298
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002299void rtl8180_hw_sleep(struct net_device *dev, u32 th, u32 tl)
2300{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002301 struct r8180_priv *priv = ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002302 u32 rb = jiffies;
2303 unsigned long flags;
2304
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302305 spin_lock_irqsave(&priv->ps_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002306
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302307 /*
2308 * Writing HW register with 0 equals to disable
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002309 * the timer, that is not really what we want
2310 */
2311 tl -= MSECS(4+16+7);
2312
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302313 /*
2314 * If the interval in witch we are requested to sleep is too
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002315 * short then give up and remain awake
2316 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302317 if (((tl >= rb) && (tl-rb) <= MSECS(MIN_SLEEP_TIME))
2318 || ((rb > tl) && (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
2319 spin_unlock_irqrestore(&priv->ps_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002320 printk("too short to sleep\n");
2321 return;
2322 }
2323
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002324 {
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302325 u32 tmp = (tl > rb) ? (tl-rb) : (rb-tl);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002326
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002327 priv->DozePeriodInPast2Sec += jiffies_to_msecs(tmp);
2328
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302329 queue_delayed_work(priv->ieee80211->wq, &priv->ieee80211->hw_wakeup_wq, tmp); /* as tl may be less than rb */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002330 }
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302331 /*
2332 * If we suspect the TimerInt is gone beyond tl
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002333 * while setting it, then give up
2334 */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002335
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302336 if (((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME))) ||
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002337 ((tl < rb) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))) {
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302338 spin_unlock_irqrestore(&priv->ps_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002339 return;
2340 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002341
2342 queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_sleep_wq);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302343 spin_unlock_irqrestore(&priv->ps_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002344}
2345
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302346void rtl8180_wmm_param_update(struct work_struct *work)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002347{
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302348 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wmm_param_update_wq);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002349 struct net_device *dev = ieee->dev;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002350 u8 *ac_param = (u8 *)(ieee->current_network.wmm_param);
2351 u8 mode = ieee->current_network.mode;
2352 AC_CODING eACI;
2353 AC_PARAM AcParam;
2354 PAC_PARAM pAcParam;
2355 u8 i;
2356
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302357 if (!ieee->current_network.QoS_Enable) {
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302358 /* legacy ac_xx_param update */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002359 AcParam.longData = 0;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302360 AcParam.f.AciAifsn.f.AIFSN = 2; /* Follow 802.11 DIFS. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002361 AcParam.f.AciAifsn.f.ACM = 0;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302362 AcParam.f.Ecw.f.ECWmin = 3; /* Follow 802.11 CWmin. */
2363 AcParam.f.Ecw.f.ECWmax = 7; /* Follow 802.11 CWmax. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002364 AcParam.f.TXOPLimit = 0;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302365 for (eACI = 0; eACI < AC_MAX; eACI++) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002366 AcParam.f.AciAifsn.f.ACI = (u8)eACI;
2367 {
2368 u8 u1bAIFS;
2369 u32 u4bAcParam;
2370 pAcParam = (PAC_PARAM)(&AcParam);
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302371 /* Retrive paramters to udpate. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302372 u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002373 u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit))<<AC_PARAM_TXOP_LIMIT_OFFSET)|
2374 (((u32)(pAcParam->f.Ecw.f.ECWmax))<<AC_PARAM_ECW_MAX_OFFSET)|
2375 (((u32)(pAcParam->f.Ecw.f.ECWmin))<<AC_PARAM_ECW_MIN_OFFSET)|
2376 (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET));
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302377 switch (eACI) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002378 case AC1_BK:
2379 write_nic_dword(dev, AC_BK_PARAM, u4bAcParam);
2380 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002381 case AC0_BE:
2382 write_nic_dword(dev, AC_BE_PARAM, u4bAcParam);
2383 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002384 case AC2_VI:
2385 write_nic_dword(dev, AC_VI_PARAM, u4bAcParam);
2386 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002387 case AC3_VO:
2388 write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
2389 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002390 default:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302391 printk(KERN_WARNING "SetHwReg8185():invalid ACI: %d!\n", eACI);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002392 break;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302393 }
2394 }
2395 }
2396 return;
2397 }
2398
2399 for (i = 0; i < AC_MAX; i++) {
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302400 /* AcParam.longData = 0; */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302401 pAcParam = (AC_PARAM *)ac_param;
2402 {
2403 AC_CODING eACI;
2404 u8 u1bAIFS;
2405 u32 u4bAcParam;
2406
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302407 /* Retrive paramters to udpate. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302408 eACI = pAcParam->f.AciAifsn.f.ACI;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302409 /* Mode G/A: slotTimeTimer = 9; Mode B: 20 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302410 u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime;
2411 u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit)) << AC_PARAM_TXOP_LIMIT_OFFSET) |
2412 (((u32)(pAcParam->f.Ecw.f.ECWmax)) << AC_PARAM_ECW_MAX_OFFSET) |
2413 (((u32)(pAcParam->f.Ecw.f.ECWmin)) << AC_PARAM_ECW_MIN_OFFSET) |
2414 (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET));
2415
2416 switch (eACI) {
2417 case AC1_BK:
2418 write_nic_dword(dev, AC_BK_PARAM, u4bAcParam);
2419 break;
2420 case AC0_BE:
2421 write_nic_dword(dev, AC_BE_PARAM, u4bAcParam);
2422 break;
2423 case AC2_VI:
2424 write_nic_dword(dev, AC_VI_PARAM, u4bAcParam);
2425 break;
2426 case AC3_VO:
2427 write_nic_dword(dev, AC_VO_PARAM, u4bAcParam);
2428 break;
2429 default:
2430 printk(KERN_WARNING "SetHwReg8185(): invalid ACI: %d !\n", eACI);
2431 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002432 }
2433 }
2434 ac_param += (sizeof(AC_PARAM));
2435 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002436}
2437
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002438void rtl8180_tx_irq_wq(struct work_struct *work);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002439void rtl8180_restart_wq(struct work_struct *work);
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302440/* void rtl8180_rq_tx_ack(struct work_struct *work); */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002441void rtl8180_watch_dog_wq(struct work_struct *work);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002442void rtl8180_hw_wakeup_wq(struct work_struct *work);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002443void rtl8180_hw_sleep_wq(struct work_struct *work);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002444void rtl8180_sw_antenna_wq(struct work_struct *work);
Bartlomiej Zolnierkiewicz03704532009-06-13 18:30:28 +02002445void rtl8180_watch_dog(struct net_device *dev);
2446
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002447void watch_dog_adaptive(unsigned long data)
2448{
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002449 struct r8180_priv* priv = ieee80211_priv((struct net_device *)data);
2450
2451 if (!priv->up) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002452 DMESG("<----watch_dog_adaptive():driver is not up!\n");
2453 return;
2454 }
2455
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302456 /* Tx High Power Mechanism. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302457 if (CheckHighPower((struct net_device *)data))
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002458 queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->tx_pw_wq);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002459
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302460 /* Tx Power Tracking on 87SE. */
Dan Carpentercffd4e12010-01-18 14:23:20 +03002461 if (CheckTxPwrTracking((struct net_device *)data))
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002462 TxPwrTracking87SE((struct net_device *)data);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002463
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302464 /* Perform DIG immediately. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302465 if (CheckDig((struct net_device *)data) == true)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002466 queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_dig_wq);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302467 rtl8180_watch_dog((struct net_device *)data);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002468
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002469 queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->GPIOChangeRFWorkItem);
2470
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302471 priv->watch_dog_timer.expires = jiffies + MSECS(IEEE80211_WATCH_DOG_TIME);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002472 add_timer(&priv->watch_dog_timer);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002473}
2474
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002475static CHANNEL_LIST ChannelPlan[] = {
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302476 {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64},19}, /* FCC */
2477 {{1,2,3,4,5,6,7,8,9,10,11},11}, /* IC */
2478 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, /* ETSI */
2479 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, /* Spain. Change to ETSI. */
2480 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, /* France. Change to ETSI. */
2481 {{14,36,40,44,48,52,56,60,64},9}, /* MKK */
2482 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14, 36,40,44,48,52,56,60,64},22},/* MKK1 */
2483 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, /* Israel. */
2484 {{1,2,3,4,5,6,7,8,9,10,11,12,13,34,38,42,46},17}, /* For 11a , TELEC */
2485 {{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 */
2486 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13} /* world wide 13: ch1~ch11 active scan, ch12~13 passive //lzm add 080826 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002487};
2488
2489static void rtl8180_set_channel_map(u8 channel_plan, struct ieee80211_device *ieee)
2490{
2491 int i;
2492
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302493 /* lzm add 080826 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302494 ieee->MinPassiveChnlNum = MAX_CHANNEL_NUMBER+1;
2495 ieee->IbssStartChnl = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002496
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302497 switch (channel_plan) {
2498 case COUNTRY_CODE_FCC:
2499 case COUNTRY_CODE_IC:
2500 case COUNTRY_CODE_ETSI:
2501 case COUNTRY_CODE_SPAIN:
2502 case COUNTRY_CODE_FRANCE:
2503 case COUNTRY_CODE_MKK:
2504 case COUNTRY_CODE_MKK1:
2505 case COUNTRY_CODE_ISRAEL:
2506 case COUNTRY_CODE_TELEC:
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002507 {
2508 Dot11d_Init(ieee);
2509 ieee->bGlobalDomain = false;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302510 if (ChannelPlan[channel_plan].Len != 0) {
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302511 /* Clear old channel map */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002512 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302513 /* Set new channel map */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302514 for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
2515 if (ChannelPlan[channel_plan].Channel[i] <= 14)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002516 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
2517 }
2518 }
2519 break;
2520 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302521 case COUNTRY_CODE_GLOBAL_DOMAIN:
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002522 {
2523 GET_DOT11D_INFO(ieee)->bEnabled = 0;
2524 Dot11d_Reset(ieee);
2525 ieee->bGlobalDomain = true;
2526 break;
2527 }
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302528 case COUNTRY_CODE_WORLD_WIDE_13_INDEX:/* lzm add 080826 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002529 {
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302530 ieee->MinPassiveChnlNum = 12;
2531 ieee->IbssStartChnl = 10;
2532 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002533 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302534 default:
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002535 {
2536 Dot11d_Init(ieee);
2537 ieee->bGlobalDomain = false;
2538 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302539 for (i = 1; i <= 14; i++)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002540 GET_DOT11D_INFO(ieee)->channel_map[i] = 1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002541 break;
2542 }
2543 }
2544}
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002545
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002546void GPIOChangeRFWorkItemCallBack(struct work_struct *work);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002547
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302548/* YJ,add,080828 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002549static void rtl8180_statistics_init(struct Stats *pstats)
2550{
2551 memset(pstats, 0, sizeof(struct Stats));
2552}
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002553
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002554static void rtl8180_link_detect_init(plink_detect_t plink_detect)
2555{
2556 memset(plink_detect, 0, sizeof(link_detect_t));
2557 plink_detect->SlotNum = DEFAULT_SLOT_NUM;
2558}
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002559
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302560/* YJ,add,080828,end */
Larry Finger742821c2010-02-11 12:07:35 -06002561static void rtl8187se_eeprom_register_read(struct eeprom_93cx6 *eeprom)
2562{
2563 struct net_device *dev = eeprom->data;
2564 u8 reg = read_nic_byte(dev, EPROM_CMD);
2565
2566 eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
2567 eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
2568 eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
2569 eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
2570}
2571
2572static void rtl8187se_eeprom_register_write(struct eeprom_93cx6 *eeprom)
2573{
2574 struct net_device *dev = eeprom->data;
2575 u8 reg = 2 << 6;
2576
2577 if (eeprom->reg_data_in)
2578 reg |= RTL818X_EEPROM_CMD_WRITE;
2579 if (eeprom->reg_data_out)
2580 reg |= RTL818X_EEPROM_CMD_READ;
2581 if (eeprom->reg_data_clock)
2582 reg |= RTL818X_EEPROM_CMD_CK;
2583 if (eeprom->reg_chip_select)
2584 reg |= RTL818X_EEPROM_CMD_CS;
2585
2586 write_nic_byte(dev, EPROM_CMD, reg);
2587 read_nic_byte(dev, EPROM_CMD);
2588 udelay(10);
2589}
2590
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002591short rtl8180_init(struct net_device *dev)
2592{
2593 struct r8180_priv *priv = ieee80211_priv(dev);
2594 u16 word;
2595 u16 version;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002596 u32 usValue;
2597 u16 tmpu16;
2598 int i, j;
Larry Finger742821c2010-02-11 12:07:35 -06002599 struct eeprom_93cx6 eeprom;
2600 u16 eeprom_val;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002601
Larry Finger742821c2010-02-11 12:07:35 -06002602 eeprom.data = dev;
2603 eeprom.register_read = rtl8187se_eeprom_register_read;
2604 eeprom.register_write = rtl8187se_eeprom_register_write;
2605 eeprom.width = PCI_EEPROM_WIDTH_93C46;
2606
2607 eeprom_93cx6_read(&eeprom, EEPROM_COUNTRY_CODE>>1, &eeprom_val);
2608 priv->channel_plan = eeprom_val & 0xFF;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302609 if (priv->channel_plan > COUNTRY_CODE_GLOBAL_DOMAIN) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002610 printk("rtl8180_init:Error channel plan! Set to default.\n");
2611 priv->channel_plan = 0;
2612 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002613
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302614 DMESG("Channel plan is %d\n", priv->channel_plan);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002615 rtl8180_set_channel_map(priv->channel_plan, priv->ieee80211);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002616
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302617 /* FIXME: these constants are placed in a bad pleace. */
2618 priv->txbuffsize = 2048; /* 1024; */
2619 priv->txringcount = 32; /* 32; */
2620 priv->rxbuffersize = 2048; /* 1024; */
2621 priv->rxringcount = 64; /* 32; */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002622 priv->txbeaconcount = 2;
2623 priv->rx_skb_complete = 1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002624
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002625 priv->RFChangeInProgress = false;
2626 priv->SetRFPowerStateInProgress = false;
2627 priv->RFProgType = 0;
2628 priv->bInHctTest = false;
2629
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302630 priv->irq_enabled = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002631
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002632 rtl8180_statistics_init(&priv->stats);
2633 rtl8180_link_detect_init(&priv->link_detect);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002634
2635 priv->ack_tx_to_ieee = 0;
2636 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
2637 priv->ieee80211->iw_mode = IW_MODE_INFRA;
2638 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
2639 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
2640 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE;
2641 priv->ieee80211->active_scan = 1;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302642 priv->ieee80211->rate = 110; /* 11 mbps */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002643 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION;
2644 priv->ieee80211->host_encrypt = 1;
2645 priv->ieee80211->host_decrypt = 1;
2646 priv->ieee80211->sta_wake_up = rtl8180_hw_wakeup;
2647 priv->ieee80211->ps_request_tx_ack = rtl8180_rq_tx_ack;
2648 priv->ieee80211->enter_sleep_state = rtl8180_hw_sleep;
2649 priv->ieee80211->ps_is_queue_empty = rtl8180_is_tx_queue_empty;
2650
2651 priv->hw_wep = hwwep;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302652 priv->prism_hdr = 0;
2653 priv->dev = dev;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002654 priv->retry_rts = DEFAULT_RETRY_RTS;
2655 priv->retry_data = DEFAULT_RETRY_DATA;
2656 priv->RFChangeInProgress = false;
2657 priv->SetRFPowerStateInProgress = false;
2658 priv->RFProgType = 0;
2659 priv->bInHctTest = false;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302660 priv->bInactivePs = true; /* false; */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002661 priv->ieee80211->bInactivePs = priv->bInactivePs;
2662 priv->bSwRfProcessing = false;
2663 priv->eRFPowerState = eRfOff;
2664 priv->RfOffReason = 0;
2665 priv->LedStrategy = SW_LED_MODE0;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302666 priv->TxPollingTimes = 0; /* lzm add 080826 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002667 priv->bLeisurePs = true;
2668 priv->dot11PowerSaveMode = eActive;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002669 priv->AdMinCheckPeriod = 5;
2670 priv->AdMaxCheckPeriod = 10;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302671 priv->AdMaxRxSsThreshold = 30; /* 60->30 */
2672 priv->AdRxSsThreshold = 20; /* 50->20 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002673 priv->AdCheckPeriod = priv->AdMinCheckPeriod;
2674 priv->AdTickCount = 0;
2675 priv->AdRxSignalStrength = -1;
2676 priv->RegSwAntennaDiversityMechanism = 0;
2677 priv->RegDefaultAntenna = 0;
2678 priv->SignalStrength = 0;
2679 priv->AdRxOkCnt = 0;
2680 priv->CurrAntennaIndex = 0;
2681 priv->AdRxSsBeforeSwitched = 0;
2682 init_timer(&priv->SwAntennaDiversityTimer);
2683 priv->SwAntennaDiversityTimer.data = (unsigned long)dev;
2684 priv->SwAntennaDiversityTimer.function = (void *)SwAntennaDiversityTimerCallback;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002685 priv->bDigMechanism = 1;
2686 priv->InitialGain = 6;
2687 priv->bXtalCalibration = false;
2688 priv->XtalCal_Xin = 0;
2689 priv->XtalCal_Xout = 0;
2690 priv->bTxPowerTrack = false;
2691 priv->ThermalMeter = 0;
2692 priv->FalseAlarmRegValue = 0;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302693 priv->RegDigOfdmFaUpTh = 0xc; /* Upper threhold of OFDM false alarm, which is used in DIG. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002694 priv->DIG_NumberFallbackVote = 0;
2695 priv->DIG_NumberUpgradeVote = 0;
2696 priv->LastSignalStrengthInPercent = 0;
2697 priv->Stats_SignalStrength = 0;
2698 priv->LastRxPktAntenna = 0;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302699 priv->SignalQuality = 0; /* in 0-100 index. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002700 priv->Stats_SignalQuality = 0;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302701 priv->RecvSignalPower = 0; /* in dBm. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002702 priv->Stats_RecvSignalPower = 0;
2703 priv->AdMainAntennaRxOkCnt = 0;
2704 priv->AdAuxAntennaRxOkCnt = 0;
2705 priv->bHWAdSwitched = false;
2706 priv->bRegHighPowerMechanism = true;
2707 priv->RegHiPwrUpperTh = 77;
2708 priv->RegHiPwrLowerTh = 75;
2709 priv->RegRSSIHiPwrUpperTh = 70;
2710 priv->RegRSSIHiPwrLowerTh = 20;
2711 priv->bCurCCKPkt = false;
2712 priv->UndecoratedSmoothedSS = -1;
2713 priv->bToUpdateTxPwr = false;
2714 priv->CurCCKRSSI = 0;
2715 priv->RxPower = 0;
2716 priv->RSSI = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002717 priv->NumTxOkTotal = 0;
2718 priv->NumTxUnicast = 0;
2719 priv->keepAliveLevel = DEFAULT_KEEP_ALIVE_LEVEL;
2720 priv->PowerProfile = POWER_PROFILE_AC;
Larry Finger19941302010-01-25 13:11:49 -06002721 priv->CurrRetryCnt = 0;
2722 priv->LastRetryCnt = 0;
2723 priv->LastTxokCnt = 0;
2724 priv->LastRxokCnt = 0;
2725 priv->LastRetryRate = 0;
2726 priv->bTryuping = 0;
2727 priv->CurrTxRate = 0;
2728 priv->CurrRetryRate = 0;
2729 priv->TryupingCount = 0;
2730 priv->TryupingCountNoData = 0;
2731 priv->TryDownCountLowData = 0;
2732 priv->LastTxOKBytes = 0;
2733 priv->LastFailTxRate = 0;
2734 priv->LastFailTxRateSS = 0;
2735 priv->FailTxRateCount = 0;
2736 priv->LastTxThroughput = 0;
2737 priv->NumTxOkBytesTotal = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002738 priv->ForcedDataRate = 0;
2739 priv->RegBModeGainStage = 1;
2740
Larry Finger19941302010-01-25 13:11:49 -06002741 priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002742 spin_lock_init(&priv->irq_lock);
2743 spin_lock_init(&priv->irq_th_lock);
2744 spin_lock_init(&priv->tx_lock);
2745 spin_lock_init(&priv->ps_lock);
2746 spin_lock_init(&priv->rf_ps_lock);
Larry Finger19941302010-01-25 13:11:49 -06002747 sema_init(&priv->wx_sem, 1);
2748 sema_init(&priv->rf_state, 1);
2749 INIT_WORK(&priv->reset_wq, (void *)rtl8180_restart_wq);
2750 INIT_WORK(&priv->tx_irq_wq, (void *)rtl8180_tx_irq_wq);
2751 INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq,
2752 (void *)rtl8180_hw_wakeup_wq);
2753 INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq,
2754 (void *)rtl8180_hw_sleep_wq);
2755 INIT_WORK(&priv->ieee80211->wmm_param_update_wq,
2756 (void *)rtl8180_wmm_param_update);
2757 INIT_DELAYED_WORK(&priv->ieee80211->rate_adapter_wq,
2758 (void *)rtl8180_rate_adapter);
2759 INIT_DELAYED_WORK(&priv->ieee80211->hw_dig_wq,
2760 (void *)rtl8180_hw_dig_wq);
2761 INIT_DELAYED_WORK(&priv->ieee80211->tx_pw_wq,
2762 (void *)rtl8180_tx_pw_wq);
2763 INIT_DELAYED_WORK(&priv->ieee80211->GPIOChangeRFWorkItem,
2764 (void *) GPIOChangeRFWorkItemCallBack);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002765 tasklet_init(&priv->irq_rx_tasklet,
2766 (void(*)(unsigned long)) rtl8180_irq_rx_tasklet,
2767 (unsigned long)priv);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002768
Larry Finger19941302010-01-25 13:11:49 -06002769 init_timer(&priv->watch_dog_timer);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002770 priv->watch_dog_timer.data = (unsigned long)dev;
2771 priv->watch_dog_timer.function = watch_dog_adaptive;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002772
Larry Finger19941302010-01-25 13:11:49 -06002773 init_timer(&priv->rateadapter_timer);
2774 priv->rateadapter_timer.data = (unsigned long)dev;
2775 priv->rateadapter_timer.function = timer_rate_adaptive;
2776 priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD;
2777 priv->bEnhanceTxPwr = false;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002778
2779 priv->ieee80211->softmac_hard_start_xmit = rtl8180_hard_start_xmit;
2780 priv->ieee80211->set_chan = rtl8180_set_chan;
2781 priv->ieee80211->link_change = rtl8180_link_change;
2782 priv->ieee80211->softmac_data_hard_start_xmit = rtl8180_hard_data_xmit;
2783 priv->ieee80211->data_hard_stop = rtl8180_data_hard_stop;
2784 priv->ieee80211->data_hard_resume = rtl8180_data_hard_resume;
2785
John Churchcb73da22010-04-08 16:04:17 -05002786 priv->ieee80211->init_wmmparam_flag = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002787
2788 priv->ieee80211->start_send_beacons = rtl8180_start_tx_beacon;
2789 priv->ieee80211->stop_send_beacons = rtl8180_beacon_tx_disable;
2790 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
2791
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002792 priv->MWIEnable = 0;
2793
2794 priv->ShortRetryLimit = 7;
2795 priv->LongRetryLimit = 7;
2796 priv->EarlyRxThreshold = 7;
2797
2798 priv->CSMethod = (0x01 << 29);
2799
Larry Finger19941302010-01-25 13:11:49 -06002800 priv->TransmitConfig = TCR_DurProcMode_OFFSET |
2801 (7<<TCR_MXDMA_OFFSET) |
2802 (priv->ShortRetryLimit<<TCR_SRL_OFFSET) |
2803 (priv->LongRetryLimit<<TCR_LRL_OFFSET) |
2804 (0 ? TCR_SAT : 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002805
Larry Finger19941302010-01-25 13:11:49 -06002806 priv->ReceiveConfig = RCR_AMF | RCR_ADF | RCR_ACF |
2807 RCR_AB | RCR_AM | RCR_APM |
2808 (7<<RCR_MXDMA_OFFSET) |
2809 (priv->EarlyRxThreshold<<RCR_FIFO_OFFSET) |
2810 (priv->EarlyRxThreshold == 7 ?
2811 RCR_ONLYERLPKT : 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002812
2813 priv->IntrMask = IMR_TMGDOK | IMR_TBDER | IMR_THPDER |
Larry Finger19941302010-01-25 13:11:49 -06002814 IMR_THPDER | IMR_THPDOK |
2815 IMR_TVODER | IMR_TVODOK |
2816 IMR_TVIDER | IMR_TVIDOK |
2817 IMR_TBEDER | IMR_TBEDOK |
2818 IMR_TBKDER | IMR_TBKDOK |
2819 IMR_RDU |
2820 IMR_RER | IMR_ROK |
2821 IMR_RQoSOK;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002822
2823 priv->InitialGain = 6;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002824
Larry Fingerd44eb882009-11-09 10:53:20 -06002825 DMESG("MAC controller is a RTL8187SE b/g");
2826 priv->phy_ver = 2;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002827
Larry Fingerd44eb882009-11-09 10:53:20 -06002828 priv->ieee80211->modulation |= IEEE80211_OFDM_MODULATION;
2829 priv->ieee80211->short_slot = 1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002830
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302831 /* just for sync 85 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002832 priv->enable_gpio0 = 0;
2833
Larry Finger742821c2010-02-11 12:07:35 -06002834 eeprom_93cx6_read(&eeprom, EEPROM_SW_REVD_OFFSET, &eeprom_val);
2835 usValue = eeprom_val;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302836 DMESG("usValue is 0x%x\n", usValue);
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302837 /* 3Read AntennaDiversity */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002838
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302839 /* SW Antenna Diversity. */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002840 if ((usValue & EEPROM_SW_AD_MASK) != EEPROM_SW_AD_ENABLE)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002841 priv->EEPROMSwAntennaDiversity = false;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002842 else
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002843 priv->EEPROMSwAntennaDiversity = true;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002844
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302845 /* Default Antenna to use. */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002846 if ((usValue & EEPROM_DEF_ANT_MASK) != EEPROM_DEF_ANT_1)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002847 priv->EEPROMDefaultAntenna1 = false;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002848 else
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002849 priv->EEPROMDefaultAntenna1 = true;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002850
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302851 if (priv->RegSwAntennaDiversityMechanism == 0) /* Auto */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002852 /* 0: default from EEPROM. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002853 priv->bSwAntennaDiverity = priv->EEPROMSwAntennaDiversity;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002854 else
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002855 /* 1:disable antenna diversity, 2: enable antenna diversity. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302856 priv->bSwAntennaDiverity = ((priv->RegSwAntennaDiversityMechanism == 1) ? false : true);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002857
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002858 if (priv->RegDefaultAntenna == 0)
2859 /* 0: default from EEPROM. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002860 priv->bDefaultAntenna1 = priv->EEPROMDefaultAntenna1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002861 else
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002862 /* 1: main, 2: aux. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302863 priv->bDefaultAntenna1 = ((priv->RegDefaultAntenna == 2) ? true : false);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002864
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302865 /* rtl8185 can calc plcp len in HW. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002866 priv->hw_plcp_len = 1;
2867
2868 priv->plcp_preamble_mode = 2;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05302869 /* the eeprom type is stored in RCR register bit #6 */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002870 if (RCR_9356SEL & read_nic_dword(dev, RCR))
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302871 priv->epromtype = EPROM_93c56;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002872 else
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302873 priv->epromtype = EPROM_93c46;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002874
Larry Finger742821c2010-02-11 12:07:35 -06002875 eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)
2876 dev->dev_addr, 3);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002877
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302878 for (i = 1, j = 0; i < 14; i += 2, j++) {
Larry Finger742821c2010-02-11 12:07:35 -06002879 eeprom_93cx6_read(&eeprom, EPROM_TXPW_CH1_2 + j, &word);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302880 priv->chtxpwr[i] = word & 0xff;
2881 priv->chtxpwr[i+1] = (word & 0xff00)>>8;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002882 }
Larry Fingerd44eb882009-11-09 10:53:20 -06002883 for (i = 1, j = 0; i < 14; i += 2, j++) {
Larry Finger742821c2010-02-11 12:07:35 -06002884 eeprom_93cx6_read(&eeprom, EPROM_TXPW_OFDM_CH1_2 + j, &word);
Larry Fingerd44eb882009-11-09 10:53:20 -06002885 priv->chtxpwr_ofdm[i] = word & 0xff;
Larry Finger19941302010-01-25 13:11:49 -06002886 priv->chtxpwr_ofdm[i+1] = (word & 0xff00) >> 8;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002887 }
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02002888
Larry Finger19941302010-01-25 13:11:49 -06002889 /* 3Read crystal calibtration and thermal meter indication on 87SE. */
Larry Finger742821c2010-02-11 12:07:35 -06002890 eeprom_93cx6_read(&eeprom, EEPROM_RSV>>1, &tmpu16);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002891
Larry Finger19941302010-01-25 13:11:49 -06002892 /* Crystal calibration for Xin and Xout resp. */
2893 priv->XtalCal_Xout = tmpu16 & EEPROM_XTAL_CAL_XOUT_MASK;
2894 priv->XtalCal_Xin = (tmpu16 & EEPROM_XTAL_CAL_XIN_MASK) >> 4;
2895 if ((tmpu16 & EEPROM_XTAL_CAL_ENABLE) >> 12)
2896 priv->bXtalCalibration = true;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002897
Larry Finger19941302010-01-25 13:11:49 -06002898 /* Thermal meter reference indication. */
2899 priv->ThermalMeter = (u8)((tmpu16 & EEPROM_THERMAL_METER_MASK) >> 8);
2900 if ((tmpu16 & EEPROM_THERMAL_METER_ENABLE) >> 13)
2901 priv->bTxPowerTrack = true;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002902
Larry Finger742821c2010-02-11 12:07:35 -06002903 eeprom_93cx6_read(&eeprom, EPROM_TXPW_BASE, &word);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002904 priv->cck_txpwr_base = word & 0xf;
2905 priv->ofdm_txpwr_base = (word>>4) & 0xf;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002906
Larry Finger742821c2010-02-11 12:07:35 -06002907 eeprom_93cx6_read(&eeprom, EPROM_VERSION, &version);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302908 DMESG("EEPROM version %x", version);
Larry Fingerd44eb882009-11-09 10:53:20 -06002909 priv->rcr_csense = 3;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002910
Larry Finger742821c2010-02-11 12:07:35 -06002911 eeprom_93cx6_read(&eeprom, ENERGY_TRESHOLD, &eeprom_val);
2912 priv->cs_treshold = (eeprom_val & 0xff00) >> 8;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002913
Larry Finger742821c2010-02-11 12:07:35 -06002914 eeprom_93cx6_read(&eeprom, RFCHIPID, &eeprom_val);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002915 priv->rf_sleep = rtl8225z4_rf_sleep;
2916 priv->rf_wakeup = rtl8225z4_rf_wakeup;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002917 DMESGW("**PLEASE** REPORT SUCCESSFUL/UNSUCCESSFUL TO Realtek!");
2918
2919 priv->rf_close = rtl8225z2_rf_close;
2920 priv->rf_init = rtl8225z2_rf_init;
2921 priv->rf_set_chan = rtl8225z2_rf_set_chan;
2922 priv->rf_set_sens = NULL;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002923
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302924 if (0 != alloc_rx_desc_ring(dev, priv->rxbuffersize, priv->rxringcount))
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002925 return -ENOMEM;
2926
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302927 if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002928 TX_MANAGEPRIORITY_RING_ADDR))
2929 return -ENOMEM;
2930
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302931 if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002932 TX_BKPRIORITY_RING_ADDR))
2933 return -ENOMEM;
2934
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302935 if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002936 TX_BEPRIORITY_RING_ADDR))
2937 return -ENOMEM;
2938
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302939 if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002940 TX_VIPRIORITY_RING_ADDR))
2941 return -ENOMEM;
2942
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302943 if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002944 TX_VOPRIORITY_RING_ADDR))
2945 return -ENOMEM;
2946
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302947 if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002948 TX_HIGHPRIORITY_RING_ADDR))
2949 return -ENOMEM;
2950
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302951 if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txbeaconcount,
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002952 TX_BEACON_RING_ADDR))
2953 return -ENOMEM;
2954
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302955 if (request_irq(dev->irq, (void *)rtl8180_interrupt, IRQF_SHARED, dev->name, dev)) {
John Churchcb73da22010-04-08 16:04:17 -05002956 DMESGE("Error allocating IRQ %d", dev->irq);
2957 return -1;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302958 } else {
2959 priv->irq = dev->irq;
2960 DMESG("IRQ %d", dev->irq);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002961 }
2962
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002963 return 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002964}
2965
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002966void rtl8180_no_hw_wep(struct net_device *dev)
2967{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002968}
2969
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002970void rtl8180_set_hw_wep(struct net_device *dev)
2971{
2972 struct r8180_priv *priv = ieee80211_priv(dev);
2973 u8 pgreg;
2974 u8 security;
2975 u32 key0_word4;
2976
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302977 pgreg = read_nic_byte(dev, PGSELECT);
2978 write_nic_byte(dev, PGSELECT, pgreg & ~(1<<PGSELECT_PG_SHIFT));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002979
2980 key0_word4 = read_nic_dword(dev, KEY0+4+4+4);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302981 key0_word4 &= ~0xff;
2982 key0_word4 |= priv->key0[3] & 0xff;
2983 write_nic_dword(dev, KEY0, (priv->key0[0]));
2984 write_nic_dword(dev, KEY0+4, (priv->key0[1]));
2985 write_nic_dword(dev, KEY0+4+4, (priv->key0[2]));
2986 write_nic_dword(dev, KEY0+4+4+4, (key0_word4));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002987
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302988 security = read_nic_byte(dev, SECURITY);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002989 security |= (1<<SECURITY_WEP_TX_ENABLE_SHIFT);
2990 security |= (1<<SECURITY_WEP_RX_ENABLE_SHIFT);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302991 security &= ~SECURITY_ENCRYP_MASK;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002992 security |= (SECURITY_ENCRYP_104<<SECURITY_ENCRYP_SHIFT);
2993
2994 write_nic_byte(dev, SECURITY, security);
2995
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05302996 DMESG("key %x %x %x %x", read_nic_dword(dev, KEY0+4+4+4),
2997 read_nic_dword(dev, KEY0+4+4), read_nic_dword(dev, KEY0+4),
2998 read_nic_dword(dev, KEY0));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08002999}
3000
3001
3002void rtl8185_rf_pins_enable(struct net_device *dev)
3003{
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303004 /* u16 tmp; */
3005 /* tmp = read_nic_word(dev, RFPinsEnable); */
3006 write_nic_word(dev, RFPinsEnable, 0x1fff); /* | tmp); */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003007}
3008
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003009void rtl8185_set_anaparam2(struct net_device *dev, u32 a)
3010{
3011 u8 conf3;
3012
3013 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
3014
3015 conf3 = read_nic_byte(dev, CONFIG3);
3016 write_nic_byte(dev, CONFIG3, conf3 | (1<<CONFIG3_ANAPARAM_W_SHIFT));
3017 write_nic_dword(dev, ANAPARAM2, a);
3018
3019 conf3 = read_nic_byte(dev, CONFIG3);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303020 write_nic_byte(dev, CONFIG3, conf3 & ~(1<<CONFIG3_ANAPARAM_W_SHIFT));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003021 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003022}
3023
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003024void rtl8180_set_anaparam(struct net_device *dev, u32 a)
3025{
3026 u8 conf3;
3027
3028 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
3029
3030 conf3 = read_nic_byte(dev, CONFIG3);
3031 write_nic_byte(dev, CONFIG3, conf3 | (1<<CONFIG3_ANAPARAM_W_SHIFT));
3032 write_nic_dword(dev, ANAPARAM, a);
3033
3034 conf3 = read_nic_byte(dev, CONFIG3);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303035 write_nic_byte(dev, CONFIG3, conf3 & ~(1<<CONFIG3_ANAPARAM_W_SHIFT));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003036 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
3037}
3038
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003039void rtl8185_tx_antenna(struct net_device *dev, u8 ant)
3040{
3041 write_nic_byte(dev, TX_ANTENNA, ant);
3042 force_pci_posting(dev);
3043 mdelay(1);
3044}
3045
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003046void rtl8185_write_phy(struct net_device *dev, u8 adr, u32 data)
3047{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003048 u32 phyw;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003049
3050 adr |= 0x80;
3051
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303052 phyw = ((data<<8) | adr);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003053
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303054 /* Note that, we must write 0xff7c after 0x7d-0x7f to write BB register. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003055 write_nic_byte(dev, 0x7f, ((phyw & 0xff000000) >> 24));
3056 write_nic_byte(dev, 0x7e, ((phyw & 0x00ff0000) >> 16));
3057 write_nic_byte(dev, 0x7d, ((phyw & 0x0000ff00) >> 8));
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303058 write_nic_byte(dev, 0x7c, ((phyw & 0x000000ff)));
Bartlomiej Zolnierkiewicz5521a512009-06-28 16:19:23 +02003059
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003060 /* this is ok to fail when we write AGC table. check for AGC table might be
3061 * done by masking with 0x7f instead of 0xff
3062 */
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303063 /* if (phyr != (data&0xff)) DMESGW("Phy write timeout %x %x %x", phyr, data, adr); */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003064}
3065
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303066inline void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003067{
3068 data = data & 0xff;
3069 rtl8185_write_phy(dev, adr, data);
3070}
3071
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303072void write_phy_cck(struct net_device *dev, u8 adr, u32 data)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003073{
3074 data = data & 0xff;
3075 rtl8185_write_phy(dev, adr, data | 0x10000);
3076}
3077
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003078void rtl8185_set_rate(struct net_device *dev)
3079{
3080 int i;
3081 u16 word;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303082 int basic_rate, min_rr_rate, max_rr_rate;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003083
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003084 basic_rate = ieeerate2rtlrate(240);
3085 min_rr_rate = ieeerate2rtlrate(60);
3086 max_rr_rate = ieeerate2rtlrate(240);
3087
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003088 write_nic_byte(dev, RESP_RATE,
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303089 max_rr_rate<<MAX_RESP_RATE_SHIFT | min_rr_rate<<MIN_RESP_RATE_SHIFT);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003090
3091 word = read_nic_word(dev, BRSR);
3092 word &= ~BRSR_MBR_8185;
3093
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303094 for (i = 0; i <= basic_rate; i++)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003095 word |= (1<<i);
3096
3097 write_nic_word(dev, BRSR, word);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003098}
3099
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003100void rtl8180_adapter_start(struct net_device *dev)
3101{
John Churchcb73da22010-04-08 16:04:17 -05003102 struct r8180_priv *priv = ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003103
3104 rtl8180_rtx_disable(dev);
3105 rtl8180_reset(dev);
3106
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003107 /* enable beacon timeout, beacon TX ok and err
3108 * LP tx ok and err, HP TX ok and err, NP TX ok and err,
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303109 * RX ok and ERR, and GP timer
3110 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003111 priv->irq_mask = 0x6fcf;
3112
3113 priv->dma_poll_mask = 0;
3114
3115 rtl8180_beacon_tx_disable(dev);
3116
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003117 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303118 write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
3119 write_nic_word(dev, MAC4, ((u32 *)dev->dev_addr)[1] & 0xffff);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003120 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
3121
3122 rtl8180_update_msr(dev);
3123
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003124 /* These might be unnecessary since we do in rx_enable / tx_enable */
3125 fix_rx_fifo(dev);
3126 fix_tx_fifo(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003127
3128 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
3129
3130 /*
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303131 * The following is very strange. seems to be that 1 means test mode,
3132 * but we need to acknolwledges the nic when a packet is ready
3133 * although we set it to 0
3134 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003135
3136 write_nic_byte(dev,
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303137 CONFIG2, read_nic_byte(dev, CONFIG2) & ~\
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003138 (1<<CONFIG2_DMA_POLLING_MODE_SHIFT));
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303139 /* ^the nic isn't in test mode */
Larry Fingerd44eb882009-11-09 10:53:20 -06003140 write_nic_byte(dev,
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303141 CONFIG2, read_nic_byte(dev, CONFIG2)|(1<<4));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003142
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303143 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003144
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303145 write_nic_dword(dev, INT_TIMEOUT, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003146
Larry Fingerd44eb882009-11-09 10:53:20 -06003147 write_nic_byte(dev, WPA_CONFIG, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003148
3149 rtl8180_no_hw_wep(dev);
3150
Larry Fingerd44eb882009-11-09 10:53:20 -06003151 rtl8185_set_rate(dev);
3152 write_nic_byte(dev, RATE_FALLBACK, 0x81);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003153
Larry Fingerd44eb882009-11-09 10:53:20 -06003154 write_nic_byte(dev, GP_ENABLE, read_nic_byte(dev, GP_ENABLE) & ~(1<<6));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003155
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303156 /* FIXME cfg 3 ClkRun enable - isn't it ReadOnly ? */
Larry Fingerd44eb882009-11-09 10:53:20 -06003157 rtl8180_set_mode(dev, EPROM_CMD_CONFIG);
3158 write_nic_byte(dev, CONFIG3, read_nic_byte(dev, CONFIG3)
3159 | (1 << CONFIG3_CLKRUN_SHIFT));
3160 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003161
3162 priv->rf_init(dev);
3163
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303164 if (priv->rf_set_sens != NULL)
3165 priv->rf_set_sens(dev, priv->sens);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003166 rtl8180_irq_enable(dev);
3167
3168 netif_start_queue(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003169}
3170
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303171/*
3172 * This configures registers for beacon tx and enables it via
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003173 * rtl8180_beacon_tx_enable(). rtl8180_beacon_tx_disable() might
3174 * be used to stop beacon transmission
3175 */
3176void rtl8180_start_tx_beacon(struct net_device *dev)
3177{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003178 u16 word;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003179
3180 DMESG("Enabling beacon TX");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003181 rtl8180_prepare_beacon(dev);
3182 rtl8180_irq_disable(dev);
3183 rtl8180_beacon_tx_enable(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003184
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303185 word = read_nic_word(dev, AtimWnd) & ~AtimWnd_AtimWnd;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303186 write_nic_word(dev, AtimWnd, word); /* word |= */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003187
3188 word = read_nic_word(dev, BintrItv);
3189 word &= ~BintrItv_BintrItv;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303190 word |= 1000; /* priv->ieee80211->current_network.beacon_interval *
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003191 ((priv->txbeaconcount > 1)?(priv->txbeaconcount-1):1);
3192 // FIXME: check if correct ^^ worked with 0x3e8;
3193 */
3194 write_nic_word(dev, BintrItv, word);
3195
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003196 rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
3197
John Churchcb73da22010-04-08 16:04:17 -05003198 rtl8185b_irq_enable(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003199}
3200
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003201static struct net_device_stats *rtl8180_stats(struct net_device *dev)
3202{
3203 struct r8180_priv *priv = ieee80211_priv(dev);
3204
3205 return &priv->ieee80211->stats;
3206}
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303207
3208/*
3209 * Change current and default preamble mode.
3210 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003211bool
3212MgntActSet_802_11_PowerSaveMode(
3213 struct r8180_priv *priv,
3214 RT_PS_MODE rtPsMode
3215)
3216{
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303217 /* Currently, we do not change power save mode on IBSS mode. */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303218 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003219 return false;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003220
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003221 priv->ieee80211->ps = rtPsMode;
Bartlomiej Zolnierkiewicz5521a512009-06-28 16:19:23 +02003222
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003223 return true;
3224}
3225
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003226void LeisurePSEnter(struct r8180_priv *priv)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003227{
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003228 if (priv->bLeisurePs) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003229 if (priv->ieee80211->ps == IEEE80211_PS_DISABLED)
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303230 MgntActSet_802_11_PowerSaveMode(priv, IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST); /* IEEE80211_PS_ENABLE */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003231 }
3232}
3233
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003234void LeisurePSLeave(struct r8180_priv *priv)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003235{
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003236 if (priv->bLeisurePs) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003237 if (priv->ieee80211->ps != IEEE80211_PS_DISABLED)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003238 MgntActSet_802_11_PowerSaveMode(priv, IEEE80211_PS_DISABLED);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003239 }
3240}
Bartlomiej Zolnierkiewicz03704532009-06-13 18:30:28 +02003241
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303242void rtl8180_hw_wakeup_wq(struct work_struct *work)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003243{
Jean Delvarebf6aede2009-04-02 16:56:54 -07003244 struct delayed_work *dwork = to_delayed_work(work);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303245 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_wakeup_wq);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003246 struct net_device *dev = ieee->dev;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003247
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003248 rtl8180_hw_wakeup(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003249}
3250
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303251void rtl8180_hw_sleep_wq(struct work_struct *work)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003252{
Jean Delvarebf6aede2009-04-02 16:56:54 -07003253 struct delayed_work *dwork = to_delayed_work(work);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303254 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_sleep_wq);
John Churchcb73da22010-04-08 16:04:17 -05003255 struct net_device *dev = ieee->dev;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003256
John Churchcb73da22010-04-08 16:04:17 -05003257 rtl8180_hw_sleep_down(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003258}
3259
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303260static void MgntLinkKeepAlive(struct r8180_priv *priv)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003261{
3262 if (priv->keepAliveLevel == 0)
3263 return;
3264
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303265 if (priv->ieee80211->state == IEEE80211_LINKED) {
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303266 /*
3267 * Keep-Alive.
3268 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003269
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303270 if ((priv->keepAliveLevel == 2) ||
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003271 (priv->link_detect.LastNumTxUnicast == priv->NumTxUnicast &&
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303272 priv->link_detect.LastNumRxUnicast == priv->ieee80211->NumRxUnicast)
3273 ) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003274 priv->link_detect.IdleCount++;
3275
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303276 /*
3277 * Send a Keep-Alive packet packet to AP if we had been idle for a while.
3278 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303279 if (priv->link_detect.IdleCount >= ((KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD)-1)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003280 priv->link_detect.IdleCount = 0;
3281 ieee80211_sta_ps_send_null_frame(priv->ieee80211, false);
3282 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303283 } else {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003284 priv->link_detect.IdleCount = 0;
3285 }
3286 priv->link_detect.LastNumTxUnicast = priv->NumTxUnicast;
3287 priv->link_detect.LastNumRxUnicast = priv->ieee80211->NumRxUnicast;
3288 }
3289}
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003290
3291static u8 read_acadapter_file(char *filename);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003292
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003293void rtl8180_watch_dog(struct net_device *dev)
3294{
3295 struct r8180_priv *priv = ieee80211_priv(dev);
3296 bool bEnterPS = false;
3297 bool bBusyTraffic = false;
3298 u32 TotalRxNum = 0;
3299 u16 SlotIndex = 0;
3300 u16 i = 0;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303301 if (priv->ieee80211->actscanning == false) {
3302 if ((priv->ieee80211->iw_mode != IW_MODE_ADHOC) && (priv->ieee80211->state == IEEE80211_NOLINK) && (priv->ieee80211->beinretry == false) && (priv->eRFPowerState == eRfOn))
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003303 IPSEnter(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003304 }
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303305 /* YJ,add,080828,for link state check */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303306 if ((priv->ieee80211->state == IEEE80211_LINKED) && (priv->ieee80211->iw_mode == IW_MODE_INFRA)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003307 SlotIndex = (priv->link_detect.SlotIndex++) % priv->link_detect.SlotNum;
3308 priv->link_detect.RxFrameNum[SlotIndex] = priv->ieee80211->NumRxDataInPeriod + priv->ieee80211->NumRxBcnInPeriod;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303309 for (i = 0; i < priv->link_detect.SlotNum; i++)
3310 TotalRxNum += priv->link_detect.RxFrameNum[i];
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003311
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303312 if (TotalRxNum == 0) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003313 priv->ieee80211->state = IEEE80211_ASSOCIATING;
3314 queue_work(priv->ieee80211->wq, &priv->ieee80211->associate_procedure_wq);
3315 }
3316 }
3317
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303318 /* YJ,add,080828,for KeepAlive */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003319 MgntLinkKeepAlive(priv);
3320
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303321 /* YJ,add,080828,for LPS */
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003322 if (priv->PowerProfile == POWER_PROFILE_BATTERY)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003323 priv->bLeisurePs = true;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003324 else if (priv->PowerProfile == POWER_PROFILE_AC) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003325 LeisurePSLeave(priv);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303326 priv->bLeisurePs = false;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003327 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003328
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303329 if (priv->ieee80211->state == IEEE80211_LINKED) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003330 priv->link_detect.NumRxOkInPeriod = priv->ieee80211->NumRxDataInPeriod;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303331 if (priv->link_detect.NumRxOkInPeriod > 666 ||
3332 priv->link_detect.NumTxOkInPeriod > 666) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003333 bBusyTraffic = true;
3334 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303335 if (((priv->link_detect.NumRxOkInPeriod + priv->link_detect.NumTxOkInPeriod) > 8)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003336 || (priv->link_detect.NumRxOkInPeriod > 2)) {
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303337 bEnterPS = false;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003338 } else
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303339 bEnterPS = true;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003340
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003341 if (bEnterPS)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003342 LeisurePSEnter(priv);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003343 else
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003344 LeisurePSLeave(priv);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003345 } else
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003346 LeisurePSLeave(priv);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003347 priv->link_detect.bBusyTraffic = bBusyTraffic;
3348 priv->link_detect.NumRxOkInPeriod = 0;
3349 priv->link_detect.NumTxOkInPeriod = 0;
3350 priv->ieee80211->NumRxDataInPeriod = 0;
3351 priv->ieee80211->NumRxBcnInPeriod = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003352}
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003353
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003354int _rtl8180_up(struct net_device *dev)
3355{
3356 struct r8180_priv *priv = ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003357
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303358 priv->up = 1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003359
3360 DMESG("Bringing up iface");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003361 rtl8185b_adapter_start(dev);
3362 rtl8185b_rx_enable(dev);
3363 rtl8185b_tx_enable(dev);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303364 if (priv->bInactivePs) {
3365 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003366 IPSLeave(dev);
3367 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303368 timer_rate_adaptive((unsigned long)dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003369 watch_dog_adaptive((unsigned long)dev);
John Churchcb73da22010-04-08 16:04:17 -05003370 if (priv->bSwAntennaDiverity)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003371 SwAntennaDiversityTimerCallback(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003372 ieee80211_softmac_start_protocol(priv->ieee80211);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003373 return 0;
3374}
3375
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003376int rtl8180_open(struct net_device *dev)
3377{
3378 struct r8180_priv *priv = ieee80211_priv(dev);
3379 int ret;
3380
3381 down(&priv->wx_sem);
3382 ret = rtl8180_up(dev);
3383 up(&priv->wx_sem);
3384 return ret;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003385}
3386
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003387int rtl8180_up(struct net_device *dev)
3388{
3389 struct r8180_priv *priv = ieee80211_priv(dev);
3390
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303391 if (priv->up == 1)
3392 return -1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003393
3394 return _rtl8180_up(dev);
3395}
3396
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003397int rtl8180_close(struct net_device *dev)
3398{
3399 struct r8180_priv *priv = ieee80211_priv(dev);
3400 int ret;
3401
3402 down(&priv->wx_sem);
3403 ret = rtl8180_down(dev);
3404 up(&priv->wx_sem);
3405
3406 return ret;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003407}
3408
3409int rtl8180_down(struct net_device *dev)
3410{
3411 struct r8180_priv *priv = ieee80211_priv(dev);
3412
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003413 if (priv->up == 0)
3414 return -1;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003415
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303416 priv->up = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003417
3418 ieee80211_softmac_stop_protocol(priv->ieee80211);
3419 /* FIXME */
3420 if (!netif_queue_stopped(dev))
3421 netif_stop_queue(dev);
3422 rtl8180_rtx_disable(dev);
3423 rtl8180_irq_disable(dev);
3424 del_timer_sync(&priv->watch_dog_timer);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003425 del_timer_sync(&priv->rateadapter_timer);
3426 cancel_delayed_work(&priv->ieee80211->rate_adapter_wq);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003427 cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq);
3428 cancel_delayed_work(&priv->ieee80211->hw_sleep_wq);
3429 cancel_delayed_work(&priv->ieee80211->hw_dig_wq);
3430 cancel_delayed_work(&priv->ieee80211->tx_pw_wq);
3431 del_timer_sync(&priv->SwAntennaDiversityTimer);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303432 SetZebraRFPowerState8185(dev, eRfOff);
3433 memset(&(priv->ieee80211->current_network), 0, sizeof(struct ieee80211_network));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003434 priv->ieee80211->state = IEEE80211_NOLINK;
3435 return 0;
3436}
3437
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003438void rtl8180_restart_wq(struct work_struct *work)
3439{
3440 struct r8180_priv *priv = container_of(work, struct r8180_priv, reset_wq);
3441 struct net_device *dev = priv->dev;
Bartlomiej Zolnierkiewicz03704532009-06-13 18:30:28 +02003442
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003443 down(&priv->wx_sem);
3444
3445 rtl8180_commit(dev);
3446
3447 up(&priv->wx_sem);
3448}
3449
3450void rtl8180_restart(struct net_device *dev)
3451{
3452 struct r8180_priv *priv = ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003453
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003454 schedule_work(&priv->reset_wq);
3455}
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003456
3457void rtl8180_commit(struct net_device *dev)
3458{
3459 struct r8180_priv *priv = ieee80211_priv(dev);
3460
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003461 if (priv->up == 0)
3462 return ;
3463
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003464 del_timer_sync(&priv->watch_dog_timer);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003465 del_timer_sync(&priv->rateadapter_timer);
3466 cancel_delayed_work(&priv->ieee80211->rate_adapter_wq);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003467 cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq);
3468 cancel_delayed_work(&priv->ieee80211->hw_sleep_wq);
3469 cancel_delayed_work(&priv->ieee80211->hw_dig_wq);
3470 cancel_delayed_work(&priv->ieee80211->tx_pw_wq);
3471 del_timer_sync(&priv->SwAntennaDiversityTimer);
3472 ieee80211_softmac_stop_protocol(priv->ieee80211);
3473 rtl8180_irq_disable(dev);
3474 rtl8180_rtx_disable(dev);
3475 _rtl8180_up(dev);
3476}
3477
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003478static void r8180_set_multicast(struct net_device *dev)
3479{
3480 struct r8180_priv *priv = ieee80211_priv(dev);
3481 short promisc;
3482
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303483 promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003484
3485 if (promisc != priv->promisc)
3486 rtl8180_restart(dev);
3487
3488 priv->promisc = promisc;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003489}
3490
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003491int r8180_set_mac_adr(struct net_device *dev, void *mac)
3492{
3493 struct r8180_priv *priv = ieee80211_priv(dev);
3494 struct sockaddr *addr = mac;
3495
3496 down(&priv->wx_sem);
3497
3498 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
3499
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303500 if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003501 memcpy(priv->ieee80211->current_network.bssid, dev->dev_addr, ETH_ALEN);
3502
3503 if (priv->up) {
3504 rtl8180_down(dev);
3505 rtl8180_up(dev);
3506 }
3507
3508 up(&priv->wx_sem);
3509
3510 return 0;
3511}
3512
3513/* based on ipw2200 driver */
3514int rtl8180_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3515{
3516 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003517 struct iwreq *wrq = (struct iwreq *) rq;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303518 int ret = -1;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003519
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003520 switch (cmd) {
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003521 case RTL_IOCTL_WPA_SUPPLICANT:
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003522 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
3523 return ret;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003524 default:
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003525 return -EOPNOTSUPP;
3526 }
3527
3528 return -EOPNOTSUPP;
3529}
3530
Alexander Beregalov727ae302009-05-10 03:06:54 +04003531static const struct net_device_ops rtl8180_netdev_ops = {
3532 .ndo_open = rtl8180_open,
3533 .ndo_stop = rtl8180_close,
3534 .ndo_get_stats = rtl8180_stats,
3535 .ndo_tx_timeout = rtl8180_restart,
3536 .ndo_do_ioctl = rtl8180_ioctl,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00003537 .ndo_set_rx_mode = r8180_set_multicast,
Alexander Beregalov727ae302009-05-10 03:06:54 +04003538 .ndo_set_mac_address = r8180_set_mac_adr,
3539 .ndo_validate_addr = eth_validate_addr,
3540 .ndo_change_mtu = eth_change_mtu,
George Kadianakisdf574b82009-12-17 01:16:00 +02003541 .ndo_start_xmit = ieee80211_rtl_xmit,
Alexander Beregalov727ae302009-05-10 03:06:54 +04003542};
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003543
3544static int __devinit rtl8180_pci_probe(struct pci_dev *pdev,
3545 const struct pci_device_id *id)
3546{
3547 unsigned long ioaddr = 0;
3548 struct net_device *dev = NULL;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303549 struct r8180_priv *priv = NULL;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003550 u8 unit = 0;
Kulikov Vasiliybeef9692010-08-09 23:51:52 +04003551 int ret = -ENODEV;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003552
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003553 unsigned long pmem_start, pmem_len, pmem_flags;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003554
3555 DMESG("Configuring chip resources");
3556
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303557 if (pci_enable_device(pdev)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003558 DMESG("Failed to enable PCI device");
3559 return -EIO;
3560 }
3561
3562 pci_set_master(pdev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003563 pci_set_dma_mask(pdev, 0xffffff00ULL);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303564 pci_set_consistent_dma_mask(pdev, 0xffffff00ULL);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003565 dev = alloc_ieee80211(sizeof(struct r8180_priv));
Kulikov Vasiliybeef9692010-08-09 23:51:52 +04003566 if (!dev) {
3567 ret = -ENOMEM;
3568 goto fail_free;
3569 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003570 priv = ieee80211_priv(dev);
3571 priv->ieee80211 = netdev_priv(dev);
3572
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003573 pci_set_drvdata(pdev, dev);
3574 SET_NETDEV_DEV(dev, &pdev->dev);
3575
3576 priv = ieee80211_priv(dev);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003577 priv->pdev = pdev;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003578
3579 pmem_start = pci_resource_start(pdev, 1);
3580 pmem_len = pci_resource_len(pdev, 1);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303581 pmem_flags = pci_resource_flags(pdev, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003582
3583 if (!(pmem_flags & IORESOURCE_MEM)) {
3584 DMESG("region #1 not a MMIO resource, aborting");
3585 goto fail;
3586 }
3587
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303588 if (!request_mem_region(pmem_start, pmem_len, RTL8180_MODULE_NAME)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003589 DMESG("request_mem_region failed!");
3590 goto fail;
3591 }
3592
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303593 ioaddr = (unsigned long)ioremap_nocache(pmem_start, pmem_len);
3594 if (ioaddr == (unsigned long)NULL) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003595 DMESG("ioremap failed!");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003596 goto fail1;
3597 }
3598
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303599 dev->mem_start = ioaddr; /* shared mem start */
3600 dev->mem_end = ioaddr + pci_resource_len(pdev, 0); /* shared mem end */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003601
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003602 pci_read_config_byte(pdev, 0x05, &unit);
3603 pci_write_config_byte(pdev, 0x05, unit & (~0x04));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003604
3605 dev->irq = pdev->irq;
3606 priv->irq = 0;
3607
Alexander Beregalov727ae302009-05-10 03:06:54 +04003608 dev->netdev_ops = &rtl8180_netdev_ops;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003609 dev->wireless_handlers = &r8180_wx_handlers_def;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003610
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303611 dev->type = ARPHRD_ETHER;
Larry Finger19941302010-01-25 13:11:49 -06003612 dev->watchdog_timeo = HZ*3;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003613
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303614 if (dev_alloc_name(dev, ifname) < 0) {
John Churchcb73da22010-04-08 16:04:17 -05003615 DMESG("Oops: devname already taken! Trying wlan%%d...\n");
Rusty Russelldca41302010-08-11 23:04:21 -06003616 strcpy(ifname, "wlan%d");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003617 dev_alloc_name(dev, ifname);
John Churchcb73da22010-04-08 16:04:17 -05003618 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003619
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303620 if (rtl8180_init(dev) != 0) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003621 DMESG("Initialization failed");
3622 goto fail1;
3623 }
3624
3625 netif_carrier_off(dev);
3626
3627 register_netdev(dev);
3628
3629 rtl8180_proc_init_one(dev);
3630
3631 DMESG("Driver probe completed\n");
3632 return 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003633fail1:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303634 if (dev->mem_start != (unsigned long)NULL) {
3635 iounmap((void *)dev->mem_start);
3636 release_mem_region(pci_resource_start(pdev, 1),
3637 pci_resource_len(pdev, 1));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003638 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003639fail:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303640 if (dev) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003641 if (priv->irq) {
3642 free_irq(dev->irq, dev);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303643 dev->irq = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003644 }
3645 free_ieee80211(dev);
3646 }
3647
Kulikov Vasiliybeef9692010-08-09 23:51:52 +04003648fail_free:
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003649 pci_disable_device(pdev);
3650
3651 DMESG("wlan driver load failed\n");
3652 pci_set_drvdata(pdev, NULL);
Kulikov Vasiliybeef9692010-08-09 23:51:52 +04003653 return ret;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003654}
3655
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003656static void __devexit rtl8180_pci_remove(struct pci_dev *pdev)
3657{
3658 struct r8180_priv *priv;
3659 struct net_device *dev = pci_get_drvdata(pdev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003660
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003661 if (dev) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003662 unregister_netdev(dev);
3663
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003664 priv = ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003665
3666 rtl8180_proc_remove_one(dev);
3667 rtl8180_down(dev);
3668 priv->rf_close(dev);
3669 rtl8180_reset(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003670 mdelay(10);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003671
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303672 if (priv->irq) {
3673 DMESG("Freeing irq %d", dev->irq);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003674 free_irq(dev->irq, dev);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303675 priv->irq = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003676 }
3677
3678 free_rx_desc_ring(dev);
3679 free_tx_desc_rings(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003680
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303681 if (dev->mem_start != (unsigned long)NULL) {
3682 iounmap((void *)dev->mem_start);
3683 release_mem_region(pci_resource_start(pdev, 1),
3684 pci_resource_len(pdev, 1));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003685 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003686
3687 free_ieee80211(dev);
3688 }
3689 pci_disable_device(pdev);
3690
3691 DMESG("wlan driver removed\n");
3692}
3693
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003694/* fun with the built-in ieee80211 stack... */
3695extern int ieee80211_crypto_init(void);
3696extern void ieee80211_crypto_deinit(void);
3697extern int ieee80211_crypto_tkip_init(void);
3698extern void ieee80211_crypto_tkip_exit(void);
3699extern int ieee80211_crypto_ccmp_init(void);
3700extern void ieee80211_crypto_ccmp_exit(void);
3701extern int ieee80211_crypto_wep_init(void);
3702extern void ieee80211_crypto_wep_exit(void);
3703
3704static int __init rtl8180_pci_module_init(void)
3705{
3706 int ret;
3707
3708 ret = ieee80211_crypto_init();
3709 if (ret) {
3710 printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret);
3711 return ret;
3712 }
3713 ret = ieee80211_crypto_tkip_init();
3714 if (ret) {
3715 printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n", ret);
3716 return ret;
3717 }
3718 ret = ieee80211_crypto_ccmp_init();
3719 if (ret) {
3720 printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n", ret);
3721 return ret;
3722 }
3723 ret = ieee80211_crypto_wep_init();
3724 if (ret) {
3725 printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret);
3726 return ret;
3727 }
3728
Joe Perchesbc568942010-01-31 12:02:08 -08003729 printk(KERN_INFO "\nLinux kernel driver for RTL8180 / RTL8185 based WLAN cards\n");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003730 printk(KERN_INFO "Copyright (c) 2004-2005, Andrea Merello\n");
3731 DMESG("Initializing module");
3732 DMESG("Wireless extensions version %d", WIRELESS_EXT);
3733 rtl8180_proc_module_init();
3734
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003735 if (pci_register_driver(&rtl8180_pci_driver)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003736 DMESG("No device found");
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003737 return -ENODEV;
3738 }
3739 return 0;
3740}
3741
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003742static void __exit rtl8180_pci_module_exit(void)
3743{
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303744 pci_unregister_driver(&rtl8180_pci_driver);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003745 rtl8180_proc_module_remove();
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003746 ieee80211_crypto_tkip_exit();
3747 ieee80211_crypto_ccmp_exit();
3748 ieee80211_crypto_wep_exit();
leandro Costantino096c55d2009-02-17 11:16:26 -05003749 ieee80211_crypto_deinit();
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003750 DMESG("Exiting");
3751}
3752
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003753void rtl8180_try_wake_queue(struct net_device *dev, int pri)
3754{
3755 unsigned long flags;
3756 short enough_desc;
3757 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
3758
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303759 spin_lock_irqsave(&priv->tx_lock, flags);
3760 enough_desc = check_nic_enought_desc(dev, pri);
3761 spin_unlock_irqrestore(&priv->tx_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003762
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303763 if (enough_desc)
George Kadianakisdf574b82009-12-17 01:16:00 +02003764 ieee80211_rtl_wake_queue(priv->ieee80211);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003765}
3766
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303767void rtl8180_tx_isr(struct net_device *dev, int pri, short error)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003768{
3769 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303770 u32 *tail; /* tail virtual addr */
3771 u32 *head; /* head virtual addr */
3772 u32 *begin; /* start of ring virtual addr */
3773 u32 *nicv; /* nic pointer virtual addr */
3774 u32 nic; /* nic pointer physical addr */
3775 u32 nicbegin; /* start of ring physical addr */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003776 unsigned long flag;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303777 /* physical addr are ok on 32 bits since we set DMA mask */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003778 int offs;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303779 int j, i;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003780 int hd;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303781 if (error)
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303782 priv->stats.txretry++; /* tony 20060601 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303783 spin_lock_irqsave(&priv->tx_lock, flag);
3784 switch (pri) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003785 case MANAGE_PRIORITY:
3786 tail = priv->txmapringtail;
3787 begin = priv->txmapring;
3788 head = priv->txmapringhead;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303789 nic = read_nic_dword(dev, TX_MANAGEPRIORITY_RING_ADDR);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003790 nicbegin = priv->txmapringdma;
3791 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003792 case BK_PRIORITY:
3793 tail = priv->txbkpringtail;
3794 begin = priv->txbkpring;
3795 head = priv->txbkpringhead;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303796 nic = read_nic_dword(dev, TX_BKPRIORITY_RING_ADDR);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003797 nicbegin = priv->txbkpringdma;
3798 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003799 case BE_PRIORITY:
3800 tail = priv->txbepringtail;
3801 begin = priv->txbepring;
3802 head = priv->txbepringhead;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303803 nic = read_nic_dword(dev, TX_BEPRIORITY_RING_ADDR);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003804 nicbegin = priv->txbepringdma;
3805 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003806 case VI_PRIORITY:
3807 tail = priv->txvipringtail;
3808 begin = priv->txvipring;
3809 head = priv->txvipringhead;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303810 nic = read_nic_dword(dev, TX_VIPRIORITY_RING_ADDR);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003811 nicbegin = priv->txvipringdma;
3812 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003813 case VO_PRIORITY:
3814 tail = priv->txvopringtail;
3815 begin = priv->txvopring;
3816 head = priv->txvopringhead;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303817 nic = read_nic_dword(dev, TX_VOPRIORITY_RING_ADDR);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003818 nicbegin = priv->txvopringdma;
3819 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003820 case HI_PRIORITY:
3821 tail = priv->txhpringtail;
3822 begin = priv->txhpring;
3823 head = priv->txhpringhead;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303824 nic = read_nic_dword(dev, TX_HIGHPRIORITY_RING_ADDR);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003825 nicbegin = priv->txhpringdma;
3826 break;
3827
3828 default:
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303829 spin_unlock_irqrestore(&priv->tx_lock, flag);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003830 return ;
3831 }
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003832
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303833 nicv = (u32 *)((nic - nicbegin) + (u8*)begin);
3834 if ((head <= tail && (nicv > tail || nicv < head)) ||
3835 (head > tail && (nicv > tail && nicv < head))) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003836 DMESGW("nic has lost pointer");
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303837 spin_unlock_irqrestore(&priv->tx_lock, flag);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003838 rtl8180_restart(dev);
3839 return;
3840 }
3841
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303842 /*
3843 * We check all the descriptors between the head and the nic,
André Goddard Rosabbc9a992009-11-14 13:09:06 -02003844 * but not the currently pointed by the nic (the next to be txed)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003845 * and the previous of the pointed (might be in process ??)
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303846 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003847 offs = (nic - nicbegin);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303848 offs = offs / 8 / 4;
3849 hd = (head - begin) / 8;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003850
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303851 if (offs >= hd)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003852 j = offs - hd;
3853 else
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303854 j = offs + (priv->txringcount-1-hd);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003855
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303856 j -= 2;
3857 if (j < 0)
3858 j = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003859
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303860 for (i = 0; i < j; i++) {
3861 if ((*head) & (1<<31))
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003862 break;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303863 if (((*head)&(0x10000000)) != 0) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003864 priv->CurrRetryCnt += (u16)((*head) & (0x000000ff));
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003865 if (!error)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003866 priv->NumTxOkTotal++;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003867 }
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003868
3869 if (!error)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003870 priv->NumTxOkBytesTotal += (*(head+3)) & (0x00000fff);
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003871
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303872 *head = *head & ~(1<<31);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003873
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303874 if ((head - begin)/8 == priv->txringcount-1)
3875 head = begin;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003876 else
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303877 head += 8;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003878 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003879
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303880 /*
3881 * The head has been moved to the last certainly TXed
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003882 * (or at least processed by the nic) packet.
3883 * The driver take forcefully owning of all these packets
3884 * If the packet previous of the nic pointer has been
3885 * processed this doesn't matter: it will be checked
3886 * here at the next round. Anyway if no more packet are
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003887 * TXed no memory leak occur at all.
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003888 */
3889
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303890 switch (pri) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003891 case MANAGE_PRIORITY:
3892 priv->txmapringhead = head;
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003893
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303894 if (priv->ack_tx_to_ieee) {
3895 if (rtl8180_is_tx_queue_empty(dev)) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003896 priv->ack_tx_to_ieee = 0;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303897 ieee80211_ps_tx_ack(priv->ieee80211, !error);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003898 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003899 }
3900 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003901 case BK_PRIORITY:
3902 priv->txbkpringhead = head;
3903 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003904 case BE_PRIORITY:
3905 priv->txbepringhead = head;
3906 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003907 case VI_PRIORITY:
3908 priv->txvipringhead = head;
3909 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003910 case VO_PRIORITY:
3911 priv->txvopringhead = head;
3912 break;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003913 case HI_PRIORITY:
3914 priv->txhpringhead = head;
3915 break;
3916 }
3917
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303918 spin_unlock_irqrestore(&priv->tx_lock, flag);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003919}
3920
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003921void rtl8180_tx_irq_wq(struct work_struct *work)
3922{
Jean Delvarebf6aede2009-04-02 16:56:54 -07003923 struct delayed_work *dwork = to_delayed_work(work);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303924 struct ieee80211_device * ieee = (struct ieee80211_device *)
3925 container_of(dwork, struct ieee80211_device, watch_dog_wq);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003926 struct net_device *dev = ieee->dev;
Bartlomiej Zolnierkiewicz03704532009-06-13 18:30:28 +02003927
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303928 rtl8180_tx_isr(dev, MANAGE_PRIORITY, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003929}
3930irqreturn_t rtl8180_interrupt(int irq, void *netdev, struct pt_regs *regs)
3931{
3932 struct net_device *dev = (struct net_device *) netdev;
3933 struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
3934 unsigned long flags;
3935 u32 inta;
3936
3937 /* We should return IRQ_NONE, but for now let me keep this */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303938 if (priv->irq_enabled == 0)
3939 return IRQ_HANDLED;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003940
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303941 spin_lock_irqsave(&priv->irq_th_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003942
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303943 /* ISR: 4bytes */
3944 inta = read_nic_dword(dev, ISR); /* & priv->IntrMask; */
3945 write_nic_dword(dev, ISR, inta); /* reset int situation */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003946
3947 priv->stats.shints++;
3948
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303949 if (!inta) {
3950 spin_unlock_irqrestore(&priv->irq_th_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003951 return IRQ_HANDLED;
3952 /*
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303953 * most probably we can safely return IRQ_NONE,
3954 * but for now is better to avoid problems
3955 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003956 }
3957
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003958 if (inta == 0xffff) {
3959 /* HW disappared */
3960 spin_unlock_irqrestore(&priv->irq_th_lock, flags);
3961 return IRQ_HANDLED;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003962 }
3963
3964 priv->stats.ints++;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003965
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303966 if (!netif_running(dev)) {
3967 spin_unlock_irqrestore(&priv->irq_th_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003968 return IRQ_HANDLED;
3969 }
3970
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003971 if (inta & ISR_TimeOut)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003972 write_nic_dword(dev, TimerInt, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003973
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003974 if (inta & ISR_TBDOK)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003975 priv->stats.txbeacon++;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003976
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003977 if (inta & ISR_TBDER)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003978 priv->stats.txbeaconerr++;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003979
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02003980 if (inta & IMR_TMGDOK)
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303981 rtl8180_tx_isr(dev, MANAGE_PRIORITY, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003982
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303983 if (inta & ISR_THPDER) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003984 priv->stats.txhperr++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303985 rtl8180_tx_isr(dev, HI_PRIORITY, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003986 priv->ieee80211->stats.tx_errors++;
3987 }
3988
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303989 if (inta & ISR_THPDOK) { /* High priority tx ok */
3990 priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003991 priv->stats.txhpokint++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303992 rtl8180_tx_isr(dev, HI_PRIORITY, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003993 }
3994
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303995 if (inta & ISR_RER)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003996 priv->stats.rxerr++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05303997
Prashant P. Shah3f56c102010-05-13 23:09:08 +05303998 if (inta & ISR_TBKDER) { /* corresponding to BK_PRIORITY */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08003999 priv->stats.txbkperr++;
4000 priv->ieee80211->stats.tx_errors++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304001 rtl8180_tx_isr(dev, BK_PRIORITY, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004002 rtl8180_try_wake_queue(dev, BE_PRIORITY);
4003 }
4004
Prashant P. Shah3f56c102010-05-13 23:09:08 +05304005 if (inta & ISR_TBEDER) { /* corresponding to BE_PRIORITY */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004006 priv->stats.txbeperr++;
4007 priv->ieee80211->stats.tx_errors++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304008 rtl8180_tx_isr(dev, BE_PRIORITY, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004009 rtl8180_try_wake_queue(dev, BE_PRIORITY);
4010 }
Prashant P. Shah3f56c102010-05-13 23:09:08 +05304011 if (inta & ISR_TNPDER) { /* corresponding to VO_PRIORITY */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004012 priv->stats.txnperr++;
4013 priv->ieee80211->stats.tx_errors++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304014 rtl8180_tx_isr(dev, NORM_PRIORITY, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004015 rtl8180_try_wake_queue(dev, NORM_PRIORITY);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004016 }
4017
Prashant P. Shah3f56c102010-05-13 23:09:08 +05304018 if (inta & ISR_TLPDER) { /* corresponding to VI_PRIORITY */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004019 priv->stats.txlperr++;
4020 priv->ieee80211->stats.tx_errors++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304021 rtl8180_tx_isr(dev, LOW_PRIORITY, 1);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004022 rtl8180_try_wake_queue(dev, LOW_PRIORITY);
4023 }
4024
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304025 if (inta & ISR_ROK) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004026 priv->stats.rxint++;
4027 tasklet_schedule(&priv->irq_rx_tasklet);
4028 }
4029
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304030 if (inta & ISR_RQoSOK) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004031 priv->stats.rxint++;
4032 tasklet_schedule(&priv->irq_rx_tasklet);
4033 }
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304034
4035 if (inta & ISR_BcnInt)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004036 rtl8180_prepare_beacon(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004037
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304038 if (inta & ISR_RDU) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004039 DMESGW("No RX descriptor available");
4040 priv->stats.rxrdu++;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004041 tasklet_schedule(&priv->irq_rx_tasklet);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004042 }
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02004043
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304044 if (inta & ISR_RXFOVW) {
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004045 priv->stats.rxoverflow++;
4046 tasklet_schedule(&priv->irq_rx_tasklet);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004047 }
4048
Bartlomiej Zolnierkiewiczfd882782009-06-28 16:20:38 +02004049 if (inta & ISR_TXFOVW)
4050 priv->stats.txoverflow++;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004051
Prashant P. Shah3f56c102010-05-13 23:09:08 +05304052 if (inta & ISR_TNPDOK) { /* Normal priority tx ok */
4053 priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004054 priv->stats.txnpokint++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304055 rtl8180_tx_isr(dev, NORM_PRIORITY, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004056 }
4057
Prashant P. Shah3f56c102010-05-13 23:09:08 +05304058 if (inta & ISR_TLPDOK) { /* Low priority tx ok */
4059 priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004060 priv->stats.txlpokint++;
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304061 rtl8180_tx_isr(dev, LOW_PRIORITY, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004062 rtl8180_try_wake_queue(dev, LOW_PRIORITY);
4063 }
4064
Prashant P. Shah3f56c102010-05-13 23:09:08 +05304065 if (inta & ISR_TBKDOK) { /* corresponding to BK_PRIORITY */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004066 priv->stats.txbkpokint++;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05304067 priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304068 rtl8180_tx_isr(dev, BK_PRIORITY, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004069 rtl8180_try_wake_queue(dev, BE_PRIORITY);
4070 }
4071
Prashant P. Shah3f56c102010-05-13 23:09:08 +05304072 if (inta & ISR_TBEDOK) { /* corresponding to BE_PRIORITY */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004073 priv->stats.txbeperr++;
Prashant P. Shah3f56c102010-05-13 23:09:08 +05304074 priv->link_detect.NumTxOkInPeriod++; /* YJ,add,080828 */
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304075 rtl8180_tx_isr(dev, BE_PRIORITY, 0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004076 rtl8180_try_wake_queue(dev, BE_PRIORITY);
4077 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004078 force_pci_posting(dev);
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304079 spin_unlock_irqrestore(&priv->irq_th_lock, flags);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004080
4081 return IRQ_HANDLED;
4082}
4083
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304084void rtl8180_irq_rx_tasklet(struct r8180_priv *priv)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004085{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004086 rtl8180_rx(priv->dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004087}
4088
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004089void GPIOChangeRFWorkItemCallBack(struct work_struct *work)
4090{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004091 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, GPIOChangeRFWorkItem.work);
4092 struct net_device *dev = ieee->dev;
4093 struct r8180_priv *priv = ieee80211_priv(dev);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004094 u8 btPSR;
4095 u8 btConfig0;
4096 RT_RF_POWER_STATE eRfPowerStateToSet;
John Churchcb73da22010-04-08 16:04:17 -05004097 bool bActuallySet = false;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004098
4099 char *argv[3];
John Churchcb73da22010-04-08 16:04:17 -05004100 static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh";
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304101 static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL};
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004102 static int readf_count = 0;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004103
Prashant P. Shahbbfb5652010-05-13 23:08:43 +05304104 if (readf_count % 10 == 0)
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004105 priv->PowerProfile = read_acadapter_file("/proc/acpi/ac_adapter/AC0/state");
4106
4107 readf_count = (readf_count+1)%0xffff;
Larry Finger19941302010-01-25 13:11:49 -06004108 /* We should turn off LED before polling FF51[4]. */
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004109
Larry Finger19941302010-01-25 13:11:49 -06004110 /* Turn off LED. */
4111 btPSR = read_nic_byte(dev, PSR);
4112 write_nic_byte(dev, PSR, (btPSR & ~BIT3));
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004113
Larry Finger19941302010-01-25 13:11:49 -06004114 /* It need to delay 4us suggested by Jong, 2008-01-16 */
4115 udelay(4);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004116
Larry Finger19941302010-01-25 13:11:49 -06004117 /* HW radio On/Off according to the value of FF51[4](config0) */
4118 btConfig0 = btPSR = read_nic_byte(dev, CONFIG0);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004119
Larry Finger19941302010-01-25 13:11:49 -06004120 eRfPowerStateToSet = (btConfig0 & BIT4) ? eRfOn : eRfOff;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004121
Larry Finger6de92dd2010-02-11 14:41:24 -06004122 /* Turn LED back on when radio enabled */
4123 if (eRfPowerStateToSet == eRfOn)
4124 write_nic_byte(dev, PSR, btPSR | BIT3);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004125
Larry Finger19941302010-01-25 13:11:49 -06004126 if ((priv->ieee80211->bHwRadioOff == true) &&
4127 (eRfPowerStateToSet == eRfOn)) {
4128 priv->ieee80211->bHwRadioOff = false;
4129 bActuallySet = true;
4130 } else if ((priv->ieee80211->bHwRadioOff == false) &&
4131 (eRfPowerStateToSet == eRfOff)) {
4132 priv->ieee80211->bHwRadioOff = true;
4133 bActuallySet = true;
4134 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004135
Larry Finger19941302010-01-25 13:11:49 -06004136 if (bActuallySet) {
4137 MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004138
Larry Finger19941302010-01-25 13:11:49 -06004139 /* To update the UI status for Power status changed */
4140 if (priv->ieee80211->bHwRadioOff == true)
4141 argv[1] = "RFOFF";
4142 else
4143 argv[1] = "RFON";
4144 argv[0] = RadioPowerPath;
4145 argv[2] = NULL;
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004146
Larry Finger19941302010-01-25 13:11:49 -06004147 call_usermodehelper(RadioPowerPath, argv, envp, 1);
4148 }
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004149}
4150
4151static u8 read_acadapter_file(char *filename)
4152{
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004153 return 0;
4154}
4155
Greg Kroah-Hartmanc8d86be2008-12-04 20:01:41 -08004156module_init(rtl8180_pci_module_init);
4157module_exit(rtl8180_pci_module_exit);