aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r--drivers/net/wireless/wl12xx/wl1251.h5
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_acx.c68
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_acx.h36
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_boot.c55
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_event.c15
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_init.c8
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_main.c162
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_ps.c44
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_ps.h1
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_reg.h6
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_rx.c4
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_spi.c2
12 files changed, 310 insertions, 96 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
index 998e4b6252bd..054533f7a124 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl12xx/wl1251.h
@@ -269,6 +269,7 @@ struct wl1251 {
269 269
270 void (*set_power)(bool enable); 270 void (*set_power)(bool enable);
271 int irq; 271 int irq;
272 bool use_eeprom;
272 273
273 enum wl1251_state state; 274 enum wl1251_state state;
274 struct mutex mutex; 275 struct mutex mutex;
@@ -354,6 +355,8 @@ struct wl1251 {
354 /* is firmware in elp mode */ 355 /* is firmware in elp mode */
355 bool elp; 356 bool elp;
356 357
358 struct delayed_work elp_work;
359
357 /* we can be in psm, but not in elp, we have to differentiate */ 360 /* we can be in psm, but not in elp, we have to differentiate */
358 bool psm; 361 bool psm;
359 362
@@ -374,6 +377,8 @@ struct wl1251 {
374 u8 buffer_busyword[WL1251_BUSY_WORD_LEN]; 377 u8 buffer_busyword[WL1251_BUSY_WORD_LEN];
375 struct wl1251_rx_descriptor *rx_descriptor; 378 struct wl1251_rx_descriptor *rx_descriptor;
376 379
380 struct ieee80211_vif *vif;
381
377 u32 chip_id; 382 u32 chip_id;
378 char fw_ver[21]; 383 char fw_ver[21];
379}; 384};
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c
index 10b26c4532c9..acfa086dbfc5 100644
--- a/drivers/net/wireless/wl12xx/wl1251_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_acx.c
@@ -494,7 +494,7 @@ out:
494 return ret; 494 return ret;
495} 495}
496 496
497int wl1251_acx_beacon_filter_opt(struct wl1251 *wl) 497int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter)
498{ 498{
499 struct acx_beacon_filter_option *beacon_filter; 499 struct acx_beacon_filter_option *beacon_filter;
500 int ret; 500 int ret;
@@ -507,7 +507,7 @@ int wl1251_acx_beacon_filter_opt(struct wl1251 *wl)
507 goto out; 507 goto out;
508 } 508 }
509 509
510 beacon_filter->enable = 0; 510 beacon_filter->enable = enable_filter;
511 beacon_filter->max_num_beacons = 0; 511 beacon_filter->max_num_beacons = 0;
512 512
513 ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT, 513 ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
@@ -525,6 +525,7 @@ out:
525int wl1251_acx_beacon_filter_table(struct wl1251 *wl) 525int wl1251_acx_beacon_filter_table(struct wl1251 *wl)
526{ 526{
527 struct acx_beacon_filter_ie_table *ie_table; 527 struct acx_beacon_filter_ie_table *ie_table;
528 int idx = 0;
528 int ret; 529 int ret;
529 530
530 wl1251_debug(DEBUG_ACX, "acx beacon filter table"); 531 wl1251_debug(DEBUG_ACX, "acx beacon filter table");
@@ -535,8 +536,10 @@ int wl1251_acx_beacon_filter_table(struct wl1251 *wl)
535 goto out; 536 goto out;
536 } 537 }
537 538
538 ie_table->num_ie = 0; 539 /* configure default beacon pass-through rules */
539 memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE); 540 ie_table->num_ie = 1;
541 ie_table->table[idx++] = BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN;
542 ie_table->table[idx++] = BEACON_RULE_PASS_ON_APPEARANCE;
540 543
541 ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE, 544 ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
542 ie_table, sizeof(*ie_table)); 545 ie_table, sizeof(*ie_table));
@@ -550,6 +553,35 @@ out:
550 return ret; 553 return ret;
551} 554}
552 555
556int wl1251_acx_conn_monit_params(struct wl1251 *wl)
557{
558 struct acx_conn_monit_params *acx;
559 int ret;
560
561 wl1251_debug(DEBUG_ACX, "acx connection monitor parameters");
562
563 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
564 if (!acx) {
565 ret = -ENOMEM;
566 goto out;
567 }
568
569 acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD;
570 acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT;
571
572 ret = wl1251_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
573 acx, sizeof(*acx));
574 if (ret < 0) {
575 wl1251_warning("failed to set connection monitor "
576 "parameters: %d", ret);
577 goto out;
578 }
579
580out:
581 kfree(acx);
582 return ret;
583}
584
553int wl1251_acx_sg_enable(struct wl1251 *wl) 585int wl1251_acx_sg_enable(struct wl1251 *wl)
554{ 586{
555 struct acx_bt_wlan_coex *pta; 587 struct acx_bt_wlan_coex *pta;
@@ -916,3 +948,31 @@ out:
916 kfree(mem_conf); 948 kfree(mem_conf);
917 return ret; 949 return ret;
918} 950}
951
952int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim)
953{
954 struct wl1251_acx_wr_tbtt_and_dtim *acx;
955 int ret;
956
957 wl1251_debug(DEBUG_ACX, "acx tbtt and dtim");
958
959 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
960 if (!acx) {
961 ret = -ENOMEM;
962 goto out;
963 }
964
965 acx->tbtt = tbtt;
966 acx->dtim = dtim;
967
968 ret = wl1251_cmd_configure(wl, ACX_WR_TBTT_AND_DTIM,
969 acx, sizeof(*acx));
970 if (ret < 0) {
971 wl1251_warning("failed to set tbtt and dtim: %d", ret);
972 goto out;
973 }
974
975out:
976 kfree(acx);
977 return ret;
978}
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h
index cafb91459504..652371432cd8 100644
--- a/drivers/net/wireless/wl12xx/wl1251_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1251_acx.h
@@ -450,6 +450,11 @@ struct acx_beacon_filter_option {
450 (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \ 450 (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \
451 BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE)) 451 BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE))
452 452
453#define BEACON_RULE_PASS_ON_CHANGE BIT(0)
454#define BEACON_RULE_PASS_ON_APPEARANCE BIT(1)
455
456#define BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN (37)
457
453struct acx_beacon_filter_ie_table { 458struct acx_beacon_filter_ie_table {
454 struct acx_header header; 459 struct acx_header header;
455 460
@@ -458,6 +463,16 @@ struct acx_beacon_filter_ie_table {
458 u8 pad[3]; 463 u8 pad[3];
459} __attribute__ ((packed)); 464} __attribute__ ((packed));
460 465
466#define SYNCH_FAIL_DEFAULT_THRESHOLD 10 /* number of beacons */
467#define NO_BEACON_DEFAULT_TIMEOUT (500) /* in microseconds */
468
469struct acx_conn_monit_params {
470 struct acx_header header;
471
472 u32 synch_fail_thold; /* number of beacons missed */
473 u32 bss_lose_timeout; /* number of TU's from synch fail */
474};
475
461enum { 476enum {
462 SG_ENABLE = 0, 477 SG_ENABLE = 0,
463 SG_DISABLE, 478 SG_DISABLE,
@@ -1134,6 +1149,23 @@ struct wl1251_acx_mem_map {
1134 u32 num_rx_mem_blocks; 1149 u32 num_rx_mem_blocks;
1135} __attribute__ ((packed)); 1150} __attribute__ ((packed));
1136 1151
1152
1153struct wl1251_acx_wr_tbtt_and_dtim {
1154
1155 struct acx_header header;
1156
1157 /* Time in TUs between two consecutive beacons */
1158 u16 tbtt;
1159
1160 /*
1161 * DTIM period
1162 * For BSS: Number of TBTTs in a DTIM period (range: 1-10)
1163 * For IBSS: value shall be set to 1
1164 */
1165 u8 dtim;
1166 u8 padding;
1167} __attribute__ ((packed));
1168
1137/************************************************************************* 1169/*************************************************************************
1138 1170
1139 Host Interrupt Register (WiLink -> Host) 1171 Host Interrupt Register (WiLink -> Host)
@@ -1273,8 +1305,9 @@ int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time);
1273int wl1251_acx_group_address_tbl(struct wl1251 *wl); 1305int wl1251_acx_group_address_tbl(struct wl1251 *wl);
1274int wl1251_acx_service_period_timeout(struct wl1251 *wl); 1306int wl1251_acx_service_period_timeout(struct wl1251 *wl);
1275int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold); 1307int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
1276int wl1251_acx_beacon_filter_opt(struct wl1251 *wl); 1308int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter);
1277int wl1251_acx_beacon_filter_table(struct wl1251 *wl); 1309int wl1251_acx_beacon_filter_table(struct wl1251 *wl);
1310int wl1251_acx_conn_monit_params(struct wl1251 *wl);
1278int wl1251_acx_sg_enable(struct wl1251 *wl); 1311int wl1251_acx_sg_enable(struct wl1251 *wl);
1279int wl1251_acx_sg_cfg(struct wl1251 *wl); 1312int wl1251_acx_sg_cfg(struct wl1251 *wl);
1280int wl1251_acx_cca_threshold(struct wl1251 *wl); 1313int wl1251_acx_cca_threshold(struct wl1251 *wl);
@@ -1288,5 +1321,6 @@ int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats);
1288int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime); 1321int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime);
1289int wl1251_acx_rate_policies(struct wl1251 *wl); 1322int wl1251_acx_rate_policies(struct wl1251 *wl);
1290int wl1251_acx_mem_cfg(struct wl1251 *wl); 1323int wl1251_acx_mem_cfg(struct wl1251 *wl);
1324int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim);
1291 1325
1292#endif /* __WL1251_ACX_H__ */ 1326#endif /* __WL1251_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
index 452d748e42c6..2e733e7bdfd4 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -296,8 +296,12 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
296 WL1251_ACX_INTR_INIT_COMPLETE; 296 WL1251_ACX_INTR_INIT_COMPLETE;
297 wl1251_boot_target_enable_interrupts(wl); 297 wl1251_boot_target_enable_interrupts(wl);
298 298
299 /* unmask all mbox events */ 299 wl->event_mask = SCAN_COMPLETE_EVENT_ID | BSS_LOSE_EVENT_ID |
300 wl->event_mask = 0xffffffff; 300 SYNCHRONIZATION_TIMEOUT_EVENT_ID |
301 ROAMING_TRIGGER_LOW_RSSI_EVENT_ID |
302 ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID |
303 REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID |
304 BT_PTA_PREDICTION_EVENT_ID;
301 305
302 ret = wl1251_event_unmask(wl); 306 ret = wl1251_event_unmask(wl);
303 if (ret < 0) { 307 if (ret < 0) {
@@ -314,8 +318,8 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
314static int wl1251_boot_upload_firmware(struct wl1251 *wl) 318static int wl1251_boot_upload_firmware(struct wl1251 *wl)
315{ 319{
316 int addr, chunk_num, partition_limit; 320 int addr, chunk_num, partition_limit;
317 size_t fw_data_len; 321 size_t fw_data_len, len;
318 u8 *p; 322 u8 *p, *buf;
319 323
320 /* whal_FwCtrl_LoadFwImageSm() */ 324 /* whal_FwCtrl_LoadFwImageSm() */
321 325
@@ -334,6 +338,12 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl)
334 return -EIO; 338 return -EIO;
335 } 339 }
336 340
341 buf = kmalloc(CHUNK_SIZE, GFP_KERNEL);
342 if (!buf) {
343 wl1251_error("allocation for firmware upload chunk failed");
344 return -ENOMEM;
345 }
346
337 wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START, 347 wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START,
338 WL1251_PART_DOWN_MEM_SIZE, 348 WL1251_PART_DOWN_MEM_SIZE,
339 WL1251_PART_DOWN_REG_START, 349 WL1251_PART_DOWN_REG_START,
@@ -364,7 +374,11 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl)
364 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; 374 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
365 wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", 375 wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
366 p, addr); 376 p, addr);
367 wl1251_mem_write(wl, addr, p, CHUNK_SIZE); 377
378 /* need to copy the chunk for dma */
379 len = CHUNK_SIZE;
380 memcpy(buf, p, len);
381 wl1251_mem_write(wl, addr, buf, len);
368 382
369 chunk_num++; 383 chunk_num++;
370 } 384 }
@@ -372,9 +386,16 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl)
372 /* 10.4 upload the last chunk */ 386 /* 10.4 upload the last chunk */
373 addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; 387 addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
374 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; 388 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
389
390 /* need to copy the chunk for dma */
391 len = fw_data_len % CHUNK_SIZE;
392 memcpy(buf, p, len);
393
375 wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x", 394 wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
376 fw_data_len % CHUNK_SIZE, p, addr); 395 len, p, addr);
377 wl1251_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE); 396 wl1251_mem_write(wl, addr, buf, len);
397
398 kfree(buf);
378 399
379 return 0; 400 return 0;
380} 401}
@@ -473,13 +494,19 @@ int wl1251_boot(struct wl1251 *wl)
473 goto out; 494 goto out;
474 495
475 /* 2. start processing NVS file */ 496 /* 2. start processing NVS file */
476 ret = wl1251_boot_upload_nvs(wl); 497 if (wl->use_eeprom) {
477 if (ret < 0) 498 wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR);
478 goto out; 499 msleep(4000);
479 500 wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM);
480 /* write firmware's last address (ie. it's length) to 501 } else {
481 * ACX_EEPROMLESS_IND_REG */ 502 ret = wl1251_boot_upload_nvs(wl);
482 wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len); 503 if (ret < 0)
504 goto out;
505
506 /* write firmware's last address (ie. it's length) to
507 * ACX_EEPROMLESS_IND_REG */
508 wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len);
509 }
483 510
484 /* 6. read the EEPROM parameters */ 511 /* 6. read the EEPROM parameters */
485 tmp = wl1251_reg_read32(wl, SCR_PAD2); 512 tmp = wl1251_reg_read32(wl, SCR_PAD2);
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c
index 00076c4a8a21..020d764f9c13 100644
--- a/drivers/net/wireless/wl12xx/wl1251_event.c
+++ b/drivers/net/wireless/wl12xx/wl1251_event.c
@@ -79,6 +79,21 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
79 } 79 }
80 } 80 }
81 81
82 if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && wl->psm) {
83 wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");
84
85 /* indicate to the stack, that beacons have been lost */
86 ieee80211_beacon_loss(wl->vif);
87 }
88
89 if (vector & REGAINED_BSS_EVENT_ID) {
90 if (wl->psm_requested) {
91 ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
92 if (ret < 0)
93 return ret;
94 }
95 }
96
82 return 0; 97 return 0;
83} 98}
84 99
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c
index b2ee4f468fc4..5cb573383eeb 100644
--- a/drivers/net/wireless/wl12xx/wl1251_init.c
+++ b/drivers/net/wireless/wl12xx/wl1251_init.c
@@ -147,7 +147,8 @@ int wl1251_hw_init_beacon_filter(struct wl1251 *wl)
147{ 147{
148 int ret; 148 int ret;
149 149
150 ret = wl1251_acx_beacon_filter_opt(wl); 150 /* disable beacon filtering at this stage */
151 ret = wl1251_acx_beacon_filter_opt(wl, false);
151 if (ret < 0) 152 if (ret < 0)
152 return ret; 153 return ret;
153 154
@@ -364,6 +365,11 @@ int wl1251_hw_init(struct wl1251 *wl)
364 if (ret < 0) 365 if (ret < 0)
365 goto out_free_data_path; 366 goto out_free_data_path;
366 367
368 /* Initialize connection monitoring thresholds */
369 ret = wl1251_acx_conn_monit_params(wl);
370 if (ret < 0)
371 goto out_free_data_path;
372
367 /* Beacon filtering */ 373 /* Beacon filtering */
368 ret = wl1251_hw_init_beacon_filter(wl); 374 ret = wl1251_hw_init_beacon_filter(wl);
369 if (ret < 0) 375 if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index d03a07e1be7c..ff4be7bf5d36 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -28,6 +28,7 @@
28#include <linux/irq.h> 28#include <linux/irq.h>
29#include <linux/crc32.h> 29#include <linux/crc32.h>
30#include <linux/etherdevice.h> 30#include <linux/etherdevice.h>
31#include <linux/vmalloc.h>
31 32
32#include "wl1251.h" 33#include "wl1251.h"
33#include "wl12xx_80211.h" 34#include "wl12xx_80211.h"
@@ -83,7 +84,7 @@ static int wl1251_fetch_firmware(struct wl1251 *wl)
83 } 84 }
84 85
85 wl->fw_len = fw->size; 86 wl->fw_len = fw->size;
86 wl->fw = kmalloc(wl->fw_len, GFP_KERNEL); 87 wl->fw = vmalloc(wl->fw_len);
87 88
88 if (!wl->fw) { 89 if (!wl->fw) {
89 wl1251_error("could not allocate memory for the firmware"); 90 wl1251_error("could not allocate memory for the firmware");
@@ -211,9 +212,10 @@ out:
211 return ret; 212 return ret;
212} 213}
213 214
215#define WL1251_IRQ_LOOP_COUNT 10
214static void wl1251_irq_work(struct work_struct *work) 216static void wl1251_irq_work(struct work_struct *work)
215{ 217{
216 u32 intr; 218 u32 intr, ctr = WL1251_IRQ_LOOP_COUNT;
217 struct wl1251 *wl = 219 struct wl1251 *wl =
218 container_of(work, struct wl1251, irq_work); 220 container_of(work, struct wl1251, irq_work);
219 int ret; 221 int ret;
@@ -234,78 +236,86 @@ static void wl1251_irq_work(struct work_struct *work)
234 intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); 236 intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
235 wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr); 237 wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr);
236 238
237 if (wl->data_path) { 239 do {
238 wl->rx_counter = 240 if (wl->data_path) {
239 wl1251_mem_read32(wl, wl->data_path->rx_control_addr); 241 wl->rx_counter = wl1251_mem_read32(
240 242 wl, wl->data_path->rx_control_addr);
241 /* We handle a frmware bug here */ 243
242 switch ((wl->rx_counter - wl->rx_handled) & 0xf) { 244 /* We handle a frmware bug here */
243 case 0: 245 switch ((wl->rx_counter - wl->rx_handled) & 0xf) {
244 wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync"); 246 case 0:
245 intr &= ~WL1251_ACX_INTR_RX0_DATA; 247 wl1251_debug(DEBUG_IRQ,
246 intr &= ~WL1251_ACX_INTR_RX1_DATA; 248 "RX: FW and host in sync");
247 break; 249 intr &= ~WL1251_ACX_INTR_RX0_DATA;
248 case 1: 250 intr &= ~WL1251_ACX_INTR_RX1_DATA;
249 wl1251_debug(DEBUG_IRQ, "RX: FW +1"); 251 break;
250 intr |= WL1251_ACX_INTR_RX0_DATA; 252 case 1:
251 intr &= ~WL1251_ACX_INTR_RX1_DATA; 253 wl1251_debug(DEBUG_IRQ, "RX: FW +1");
252 break; 254 intr |= WL1251_ACX_INTR_RX0_DATA;
253 case 2: 255 intr &= ~WL1251_ACX_INTR_RX1_DATA;
254 wl1251_debug(DEBUG_IRQ, "RX: FW +2"); 256 break;
255 intr |= WL1251_ACX_INTR_RX0_DATA; 257 case 2:
256 intr |= WL1251_ACX_INTR_RX1_DATA; 258 wl1251_debug(DEBUG_IRQ, "RX: FW +2");
257 break; 259 intr |= WL1251_ACX_INTR_RX0_DATA;
258 default: 260 intr |= WL1251_ACX_INTR_RX1_DATA;
259 wl1251_warning("RX: FW and host out of sync: %d", 261 break;
260 wl->rx_counter - wl->rx_handled); 262 default:
261 break; 263 wl1251_warning(
262 } 264 "RX: FW and host out of sync: %d",
263 265 wl->rx_counter - wl->rx_handled);
264 wl->rx_handled = wl->rx_counter; 266 break;
267 }
265 268
269 wl->rx_handled = wl->rx_counter;
266 270
267 wl1251_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter); 271 wl1251_debug(DEBUG_IRQ, "RX counter: %d",
268 } 272 wl->rx_counter);
273 }
269 274
270 intr &= wl->intr_mask; 275 intr &= wl->intr_mask;
271 276
272 if (intr == 0) { 277 if (intr == 0) {
273 wl1251_debug(DEBUG_IRQ, "INTR is 0"); 278 wl1251_debug(DEBUG_IRQ, "INTR is 0");
274 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, 279 goto out_sleep;
275 ~(wl->intr_mask)); 280 }
276 281
277 goto out_sleep; 282 if (intr & WL1251_ACX_INTR_RX0_DATA) {
278 } 283 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA");
284 wl1251_rx(wl);
285 }
279 286
280 if (intr & WL1251_ACX_INTR_RX0_DATA) { 287 if (intr & WL1251_ACX_INTR_RX1_DATA) {
281 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA"); 288 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA");
282 wl1251_rx(wl); 289 wl1251_rx(wl);
283 } 290 }
284 291
285 if (intr & WL1251_ACX_INTR_RX1_DATA) { 292 if (intr & WL1251_ACX_INTR_TX_RESULT) {
286 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA"); 293 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT");
287 wl1251_rx(wl); 294 wl1251_tx_complete(wl);
288 } 295 }
289 296
290 if (intr & WL1251_ACX_INTR_TX_RESULT) { 297 if (intr & (WL1251_ACX_INTR_EVENT_A |
291 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT"); 298 WL1251_ACX_INTR_EVENT_B)) {
292 wl1251_tx_complete(wl); 299 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)",
293 } 300 intr);
301 if (intr & WL1251_ACX_INTR_EVENT_A)
302 wl1251_event_handle(wl, 0);
303 else
304 wl1251_event_handle(wl, 1);
305 }
294 306
295 if (intr & (WL1251_ACX_INTR_EVENT_A | WL1251_ACX_INTR_EVENT_B)) { 307 if (intr & WL1251_ACX_INTR_INIT_COMPLETE)
296 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", intr); 308 wl1251_debug(DEBUG_IRQ,
297 if (intr & WL1251_ACX_INTR_EVENT_A) 309 "WL1251_ACX_INTR_INIT_COMPLETE");
298 wl1251_event_handle(wl, 0);
299 else
300 wl1251_event_handle(wl, 1);
301 }
302 310
303 if (intr & WL1251_ACX_INTR_INIT_COMPLETE) 311 if (--ctr == 0)
304 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE"); 312 break;
305 313
306 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); 314 intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
315 } while (intr);
307 316
308out_sleep: 317out_sleep:
318 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
309 wl1251_ps_elp_sleep(wl); 319 wl1251_ps_elp_sleep(wl);
310 320
311out: 321out:
@@ -509,6 +519,12 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw,
509 conf->type, conf->mac_addr); 519 conf->type, conf->mac_addr);
510 520
511 mutex_lock(&wl->mutex); 521 mutex_lock(&wl->mutex);
522 if (wl->vif) {
523 ret = -EBUSY;
524 goto out;
525 }
526
527 wl->vif = conf->vif;
512 528
513 switch (conf->type) { 529 switch (conf->type) {
514 case NL80211_IFTYPE_STATION: 530 case NL80211_IFTYPE_STATION:
@@ -538,7 +554,12 @@ out:
538static void wl1251_op_remove_interface(struct ieee80211_hw *hw, 554static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
539 struct ieee80211_if_init_conf *conf) 555 struct ieee80211_if_init_conf *conf)
540{ 556{
557 struct wl1251 *wl = hw->priv;
558
559 mutex_lock(&wl->mutex);
541 wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface"); 560 wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface");
561 wl->vif = NULL;
562 mutex_unlock(&wl->mutex);
542} 563}
543 564
544static int wl1251_build_null_data(struct wl1251 *wl) 565static int wl1251_build_null_data(struct wl1251 *wl)
@@ -555,7 +576,8 @@ static int wl1251_build_null_data(struct wl1251 *wl)
555 576
556 memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); 577 memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
557 template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | 578 template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
558 IEEE80211_STYPE_NULLFUNC); 579 IEEE80211_STYPE_NULLFUNC |
580 IEEE80211_FCTL_TODS);
559 581
560 return wl1251_cmd_template_set(wl, CMD_NULL_DATA, &template, 582 return wl1251_cmd_template_set(wl, CMD_NULL_DATA, &template,
561 sizeof(template)); 583 sizeof(template));
@@ -568,7 +590,10 @@ static int wl1251_build_ps_poll(struct wl1251 *wl, u16 aid)
568 590
569 memcpy(template.bssid, wl->bssid, ETH_ALEN); 591 memcpy(template.bssid, wl->bssid, ETH_ALEN);
570 memcpy(template.ta, wl->mac_addr, ETH_ALEN); 592 memcpy(template.ta, wl->mac_addr, ETH_ALEN);
571 template.aid = aid; 593
594 /* aid in PS-Poll has its two MSBs each set to 1 */
595 template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid);
596
572 template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); 597 template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
573 598
574 return wl1251_cmd_template_set(wl, CMD_PS_POLL, &template, 599 return wl1251_cmd_template_set(wl, CMD_PS_POLL, &template,
@@ -1090,8 +1115,8 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
1090 wl->beacon_int = bss_conf->beacon_int; 1115 wl->beacon_int = bss_conf->beacon_int;
1091 wl->dtim_period = bss_conf->dtim_period; 1116 wl->dtim_period = bss_conf->dtim_period;
1092 1117
1093 /* FIXME: call join */ 1118 ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int,
1094 1119 wl->dtim_period);
1095 wl->aid = bss_conf->aid; 1120 wl->aid = bss_conf->aid;
1096 1121
1097 ret = wl1251_build_ps_poll(wl, wl->aid); 1122 ret = wl1251_build_ps_poll(wl, wl->aid);
@@ -1312,7 +1337,8 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
1312 1337
1313 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | 1338 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
1314 IEEE80211_HW_NOISE_DBM | 1339 IEEE80211_HW_NOISE_DBM |
1315 IEEE80211_HW_SUPPORTS_PS; 1340 IEEE80211_HW_SUPPORTS_PS |
1341 IEEE80211_HW_BEACON_FILTER;
1316 1342
1317 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); 1343 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1318 wl->hw->wiphy->max_scan_ssids = 1; 1344 wl->hw->wiphy->max_scan_ssids = 1;
@@ -1355,6 +1381,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
1355 skb_queue_head_init(&wl->tx_queue); 1381 skb_queue_head_init(&wl->tx_queue);
1356 1382
1357 INIT_WORK(&wl->filter_work, wl1251_filter_work); 1383 INIT_WORK(&wl->filter_work, wl1251_filter_work);
1384 INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work);
1358 wl->channel = WL1251_DEFAULT_CHANNEL; 1385 wl->channel = WL1251_DEFAULT_CHANNEL;
1359 wl->scanning = false; 1386 wl->scanning = false;
1360 wl->default_key = 0; 1387 wl->default_key = 0;
@@ -1372,6 +1399,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
1372 wl->power_level = WL1251_DEFAULT_POWER_LEVEL; 1399 wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
1373 wl->beacon_int = WL1251_DEFAULT_BEACON_INT; 1400 wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
1374 wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD; 1401 wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
1402 wl->vif = NULL;
1375 1403
1376 for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) 1404 for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
1377 wl->tx_frames[i] = NULL; 1405 wl->tx_frames[i] = NULL;
@@ -1413,7 +1441,7 @@ int wl1251_free_hw(struct wl1251 *wl)
1413 1441
1414 kfree(wl->target_mem_map); 1442 kfree(wl->target_mem_map);
1415 kfree(wl->data_path); 1443 kfree(wl->data_path);
1416 kfree(wl->fw); 1444 vfree(wl->fw);
1417 wl->fw = NULL; 1445 wl->fw = NULL;
1418 kfree(wl->nvs); 1446 kfree(wl->nvs);
1419 wl->nvs = NULL; 1447 wl->nvs = NULL;
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c
index c53e28727ed4..9931b197ff77 100644
--- a/drivers/net/wireless/wl12xx/wl1251_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1251_ps.c
@@ -28,17 +28,41 @@
28 28
29#define WL1251_WAKEUP_TIMEOUT 2000 29#define WL1251_WAKEUP_TIMEOUT 2000
30 30
31/* Routines to toggle sleep mode while in ELP */ 31void wl1251_elp_work(struct work_struct *work)
32void wl1251_ps_elp_sleep(struct wl1251 *wl)
33{ 32{
33 struct delayed_work *dwork;
34 struct wl1251 *wl;
35
36 dwork = container_of(work, struct delayed_work, work);
37 wl = container_of(dwork, struct wl1251, elp_work);
38
39 wl1251_debug(DEBUG_PSM, "elp work");
40
41 mutex_lock(&wl->mutex);
42
34 if (wl->elp || !wl->psm) 43 if (wl->elp || !wl->psm)
35 return; 44 goto out;
36 45
37 wl1251_debug(DEBUG_PSM, "chip to elp"); 46 wl1251_debug(DEBUG_PSM, "chip to elp");
38
39 wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); 47 wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
40
41 wl->elp = true; 48 wl->elp = true;
49
50out:
51 mutex_unlock(&wl->mutex);
52}
53
54#define ELP_ENTRY_DELAY 5
55
56/* Routines to toggle sleep mode while in ELP */
57void wl1251_ps_elp_sleep(struct wl1251 *wl)
58{
59 unsigned long delay;
60
61 if (wl->psm) {
62 cancel_delayed_work(&wl->elp_work);
63 delay = msecs_to_jiffies(ELP_ENTRY_DELAY);
64 ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay);
65 }
42} 66}
43 67
44int wl1251_ps_elp_wakeup(struct wl1251 *wl) 68int wl1251_ps_elp_wakeup(struct wl1251 *wl)
@@ -119,6 +143,11 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
119 case STATION_POWER_SAVE_MODE: 143 case STATION_POWER_SAVE_MODE:
120 wl1251_debug(DEBUG_PSM, "entering psm"); 144 wl1251_debug(DEBUG_PSM, "entering psm");
121 145
146 /* enable beacon filtering */
147 ret = wl1251_acx_beacon_filter_opt(wl, true);
148 if (ret < 0)
149 return ret;
150
122 ret = wl1251_acx_wake_up_conditions(wl, 151 ret = wl1251_acx_wake_up_conditions(wl,
123 WAKE_UP_EVENT_DTIM_BITMAP, 152 WAKE_UP_EVENT_DTIM_BITMAP,
124 wl->listen_int); 153 wl->listen_int);
@@ -142,6 +171,11 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
142 if (ret < 0) 171 if (ret < 0)
143 return ret; 172 return ret;
144 173
174 /* disable beacon filtering */
175 ret = wl1251_acx_beacon_filter_opt(wl, false);
176 if (ret < 0)
177 return ret;
178
145 ret = wl1251_acx_wake_up_conditions(wl, 179 ret = wl1251_acx_wake_up_conditions(wl,
146 WAKE_UP_EVENT_DTIM_BITMAP, 180 WAKE_UP_EVENT_DTIM_BITMAP,
147 wl->listen_int); 181 wl->listen_int);
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.h b/drivers/net/wireless/wl12xx/wl1251_ps.h
index db036fe12f25..c688ac57aee4 100644
--- a/drivers/net/wireless/wl12xx/wl1251_ps.h
+++ b/drivers/net/wireless/wl12xx/wl1251_ps.h
@@ -31,6 +31,7 @@
31int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode); 31int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode);
32void wl1251_ps_elp_sleep(struct wl1251 *wl); 32void wl1251_ps_elp_sleep(struct wl1251 *wl);
33int wl1251_ps_elp_wakeup(struct wl1251 *wl); 33int wl1251_ps_elp_wakeup(struct wl1251 *wl);
34void wl1251_elp_work(struct work_struct *work);
34 35
35 36
36#endif /* __WL1251_PS_H__ */ 37#endif /* __WL1251_PS_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h
index 06e1bd94a739..0ca3b4326056 100644
--- a/drivers/net/wireless/wl12xx/wl1251_reg.h
+++ b/drivers/net/wireless/wl12xx/wl1251_reg.h
@@ -370,6 +370,7 @@ enum wl12xx_acx_int_reg {
370 EEPROM location specified in the EE_ADDR register. 370 EEPROM location specified in the EE_ADDR register.
371 The Wlan hardware hardware clears this bit automatically. 371 The Wlan hardware hardware clears this bit automatically.
372*===============================================*/ 372*===============================================*/
373#define EE_CTL (REGISTERS_BASE + 0x2000)
373#define ACX_EE_CTL_REG EE_CTL 374#define ACX_EE_CTL_REG EE_CTL
374#define EE_WRITE 0x00000001ul 375#define EE_WRITE 0x00000001ul
375#define EE_READ 0x00000002ul 376#define EE_READ 0x00000002ul
@@ -380,6 +381,7 @@ enum wl12xx_acx_int_reg {
380 This register specifies the address 381 This register specifies the address
381 within the EEPROM from/to which to read/write data. 382 within the EEPROM from/to which to read/write data.
382 ===============================================*/ 383 ===============================================*/
384#define EE_ADDR (REGISTERS_BASE + 0x2008)
383#define ACX_EE_ADDR_REG EE_ADDR 385#define ACX_EE_ADDR_REG EE_ADDR
384 386
385/*=============================================== 387/*===============================================
@@ -389,8 +391,12 @@ enum wl12xx_acx_int_reg {
389 data from the EEPROM or the write data 391 data from the EEPROM or the write data
390 to be written to the EEPROM. 392 to be written to the EEPROM.
391 ===============================================*/ 393 ===============================================*/
394#define EE_DATA (REGISTERS_BASE + 0x2004)
392#define ACX_EE_DATA_REG EE_DATA 395#define ACX_EE_DATA_REG EE_DATA
393 396
397#define EEPROM_ACCESS_TO 10000 /* timeout counter */
398#define START_EEPROM_MGR 0x00000001
399
394/*=============================================== 400/*===============================================
395 EEPROM Base Address - 32bit RW 401 EEPROM Base Address - 32bit RW
396 ------------------------------------------ 402 ------------------------------------------
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c
index 601fe0d67827..f84cc89cbffc 100644
--- a/drivers/net/wireless/wl12xx/wl1251_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_rx.c
@@ -72,10 +72,6 @@ static void wl1251_rx_status(struct wl1251 *wl,
72 } 72 }
73 73
74 status->signal = desc->rssi; 74 status->signal = desc->rssi;
75 status->qual = (desc->rssi - WL1251_RX_MIN_RSSI) * 100 /
76 (WL1251_RX_MAX_RSSI - WL1251_RX_MIN_RSSI);
77 status->qual = min(status->qual, 100);
78 status->qual = max(status->qual, 0);
79 75
80 /* 76 /*
81 * FIXME: guessing that snr needs to be divided by two, otherwise 77 * FIXME: guessing that snr needs to be divided by two, otherwise
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
index 2cf8a2169d43..9cc8c323830f 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -270,6 +270,8 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)
270 return -ENODEV; 270 return -ENODEV;
271 } 271 }
272 272
273 wl->use_eeprom = pdata->use_eeprom;
274
273 ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl); 275 ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
274 if (ret < 0) { 276 if (ret < 0) {
275 wl1251_error("request_irq() failed: %d", ret); 277 wl1251_error("request_irq() failed: %d", ret);