aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2012-11-22 11:06:19 -0500
committerLuciano Coelho <coelho@ti.com>2012-11-27 03:49:29 -0500
commitc50a282515dc7092f7318708a0f3ae7ca7342b9f (patch)
tree1e0f6973d6382a00c88f5a544f8672e1e50dc148 /drivers/net/wireless
parentfcab189027cdd68df7f97474d1419aaa4a82130c (diff)
wlcore: update events enum/struct to new fw api
The event mailbox in wl18xx has a different (non-compatible) structure. Create common functions in wlcore to handle the events, and call them from the chip-specific event mailbox parsers. This way, each driver (wl12xx/wl18xx) extracts the event mailbox by itself according to its own structure, and then calls the common wlcore functions to handle it. Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ti/wl12xx/Makefile2
-rw-r--r--drivers/net/wireless/ti/wl12xx/event.c112
-rw-r--r--drivers/net/wireless/ti/wl12xx/event.h111
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c24
-rw-r--r--drivers/net/wireless/ti/wl18xx/Makefile2
-rw-r--r--drivers/net/wireless/ti/wl18xx/event.c99
-rw-r--r--drivers/net/wireless/ti/wl18xx/event.h76
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c19
-rw-r--r--drivers/net/wireless/ti/wlcore/boot.c19
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c44
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.h2
-rw-r--r--drivers/net/wireless/ti/wlcore/event.c338
-rw-r--r--drivers/net/wireless/ti/wlcore/event.h100
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c133
-rw-r--r--drivers/net/wireless/ti/wlcore/scan.c8
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h15
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore_i.h3
17 files changed, 735 insertions, 372 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/Makefile b/drivers/net/wireless/ti/wl12xx/Makefile
index 8d9afd238adc..e6a24056b3c8 100644
--- a/drivers/net/wireless/ti/wl12xx/Makefile
+++ b/drivers/net/wireless/ti/wl12xx/Makefile
@@ -1,3 +1,3 @@
1wl12xx-objs = main.o cmd.o acx.o debugfs.o scan.o 1wl12xx-objs = main.o cmd.o acx.o debugfs.o scan.o event.o
2 2
3obj-$(CONFIG_WL12XX) += wl12xx.o 3obj-$(CONFIG_WL12XX) += wl12xx.o
diff --git a/drivers/net/wireless/ti/wl12xx/event.c b/drivers/net/wireless/ti/wl12xx/event.c
new file mode 100644
index 000000000000..6437dac12e70
--- /dev/null
+++ b/drivers/net/wireless/ti/wl12xx/event.c
@@ -0,0 +1,112 @@
1/*
2 * This file is part of wl12xx
3 *
4 * Copyright (C) 2012 Texas Instruments. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include "event.h"
23#include "scan.h"
24#include "../wlcore/cmd.h"
25#include "../wlcore/debug.h"
26
27int wl12xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
28 bool *timeout)
29{
30 u32 local_event;
31
32 switch (event) {
33 case WLCORE_EVENT_ROLE_STOP_COMPLETE:
34 local_event = ROLE_STOP_COMPLETE_EVENT_ID;
35 break;
36
37 case WLCORE_EVENT_PEER_REMOVE_COMPLETE:
38 local_event = PEER_REMOVE_COMPLETE_EVENT_ID;
39 break;
40
41 default:
42 /* event not implemented */
43 return 0;
44 }
45 return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout);
46}
47
48int wl12xx_process_mailbox_events(struct wl1271 *wl)
49{
50 struct wl12xx_event_mailbox *mbox = wl->mbox;
51 u32 vector;
52
53
54 vector = le32_to_cpu(mbox->events_vector);
55 vector &= ~(le32_to_cpu(mbox->events_mask));
56
57 wl1271_debug(DEBUG_EVENT, "MBOX vector: 0x%x", vector);
58
59 if (vector & SCAN_COMPLETE_EVENT_ID) {
60 wl1271_debug(DEBUG_EVENT, "status: 0x%x",
61 mbox->scheduled_scan_status);
62
63 if (wl->scan_wlvif)
64 wl12xx_scan_completed(wl, wl->scan_wlvif);
65 }
66
67 if (vector & PERIODIC_SCAN_REPORT_EVENT_ID)
68 wlcore_event_sched_scan_report(wl,
69 mbox->scheduled_scan_status);
70
71 if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID)
72 wlcore_event_sched_scan_completed(wl,
73 mbox->scheduled_scan_status);
74 if (vector & SOFT_GEMINI_SENSE_EVENT_ID)
75 wlcore_event_soft_gemini_sense(wl,
76 mbox->soft_gemini_sense_info);
77
78 if (vector & BSS_LOSE_EVENT_ID)
79 wlcore_event_beacon_loss(wl, 0xff);
80
81 if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID)
82 wlcore_event_rssi_trigger(wl, mbox->rssi_snr_trigger_metric);
83
84 if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)
85 wlcore_event_ba_rx_constraint(wl,
86 BIT(mbox->role_id),
87 mbox->rx_ba_allowed);
88
89 if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID)
90 wlcore_event_channel_switch(wl, 0xff,
91 mbox->channel_switch_status);
92
93 if (vector & DUMMY_PACKET_EVENT_ID)
94 wlcore_event_dummy_packet(wl);
95
96 /*
97 * "TX retries exceeded" has a different meaning according to mode.
98 * In AP mode the offending station is disconnected.
99 */
100 if (vector & MAX_TX_RETRY_EVENT_ID)
101 wlcore_event_max_tx_failure(wl,
102 le16_to_cpu(mbox->sta_tx_retry_exceeded));
103
104 if (vector & INACTIVE_STA_EVENT_ID)
105 wlcore_event_inactive_sta(wl,
106 le16_to_cpu(mbox->sta_aging_status));
107
108 if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID)
109 wlcore_event_roc_complete(wl);
110
111 return 0;
112}
diff --git a/drivers/net/wireless/ti/wl12xx/event.h b/drivers/net/wireless/ti/wl12xx/event.h
new file mode 100644
index 000000000000..a5cc3fcd9eea
--- /dev/null
+++ b/drivers/net/wireless/ti/wl12xx/event.h
@@ -0,0 +1,111 @@
1/*
2 * This file is part of wl12xx
3 *
4 * Copyright (C) 2012 Texas Instruments. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#ifndef __WL12XX_EVENT_H__
23#define __WL12XX_EVENT_H__
24
25#include "../wlcore/wlcore.h"
26
27enum {
28 MEASUREMENT_START_EVENT_ID = BIT(8),
29 MEASUREMENT_COMPLETE_EVENT_ID = BIT(9),
30 SCAN_COMPLETE_EVENT_ID = BIT(10),
31 WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11),
32 AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12),
33 RESERVED1 = BIT(13),
34 PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14),
35 ROLE_STOP_COMPLETE_EVENT_ID = BIT(15),
36 RADAR_DETECTED_EVENT_ID = BIT(16),
37 CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
38 BSS_LOSE_EVENT_ID = BIT(18),
39 REGAINED_BSS_EVENT_ID = BIT(19),
40 MAX_TX_RETRY_EVENT_ID = BIT(20),
41 DUMMY_PACKET_EVENT_ID = BIT(21),
42 SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
43 CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID = BIT(23),
44 SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
45 PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25),
46 INACTIVE_STA_EVENT_ID = BIT(26),
47 PEER_REMOVE_COMPLETE_EVENT_ID = BIT(27),
48 PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28),
49 PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29),
50 BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30),
51 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(31),
52};
53
54struct wl12xx_event_mailbox {
55 __le32 events_vector;
56 __le32 events_mask;
57 __le32 reserved_1;
58 __le32 reserved_2;
59
60 u8 number_of_scan_results;
61 u8 scan_tag;
62 u8 completed_scan_status;
63 u8 reserved_3;
64
65 u8 soft_gemini_sense_info;
66 u8 soft_gemini_protective_info;
67 s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
68 u8 change_auto_mode_timeout;
69 u8 scheduled_scan_status;
70 u8 reserved4;
71 /* tuned channel (roc) */
72 u8 roc_channel;
73
74 __le16 hlid_removed_bitmap;
75
76 /* bitmap of aged stations (by HLID) */
77 __le16 sta_aging_status;
78
79 /* bitmap of stations (by HLID) which exceeded max tx retries */
80 __le16 sta_tx_retry_exceeded;
81
82 /* discovery completed results */
83 u8 discovery_tag;
84 u8 number_of_preq_results;
85 u8 number_of_prsp_results;
86 u8 reserved_5;
87
88 /* rx ba constraint */
89 u8 role_id; /* 0xFF means any role. */
90 u8 rx_ba_allowed;
91 u8 reserved_6[2];
92
93 /* Channel switch results */
94
95 u8 channel_switch_role_id;
96 u8 channel_switch_status;
97 u8 reserved_7[2];
98
99 u8 ps_poll_delivery_failure_role_ids;
100 u8 stopped_role_ids;
101 u8 started_role_ids;
102
103 u8 reserved_8[9];
104} __packed;
105
106int wl12xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
107 bool *timeout);
108int wl12xx_process_mailbox_events(struct wl1271 *wl);
109
110#endif
111
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index b93de04ccd6a..7138fe49c63d 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -39,6 +39,7 @@
39#include "cmd.h" 39#include "cmd.h"
40#include "acx.h" 40#include "acx.h"
41#include "scan.h" 41#include "scan.h"
42#include "event.h"
42#include "debugfs.h" 43#include "debugfs.h"
43 44
44static char *fref_param; 45static char *fref_param;
@@ -1229,6 +1230,23 @@ static int wl12xx_boot(struct wl1271 *wl)
1229 if (ret < 0) 1230 if (ret < 0)
1230 goto out; 1231 goto out;
1231 1232
1233 wl->event_mask = BSS_LOSE_EVENT_ID |
1234 REGAINED_BSS_EVENT_ID |
1235 SCAN_COMPLETE_EVENT_ID |
1236 ROLE_STOP_COMPLETE_EVENT_ID |
1237 RSSI_SNR_TRIGGER_0_EVENT_ID |
1238 PSPOLL_DELIVERY_FAILURE_EVENT_ID |
1239 SOFT_GEMINI_SENSE_EVENT_ID |
1240 PERIODIC_SCAN_REPORT_EVENT_ID |
1241 PERIODIC_SCAN_COMPLETE_EVENT_ID |
1242 DUMMY_PACKET_EVENT_ID |
1243 PEER_REMOVE_COMPLETE_EVENT_ID |
1244 BA_SESSION_RX_CONSTRAINT_EVENT_ID |
1245 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
1246 INACTIVE_STA_EVENT_ID |
1247 MAX_TX_RETRY_EVENT_ID |
1248 CHANNEL_SWITCH_COMPLETE_EVENT_ID;
1249
1232 ret = wlcore_boot_run_firmware(wl); 1250 ret = wlcore_boot_run_firmware(wl);
1233 if (ret < 0) 1251 if (ret < 0)
1234 goto out; 1252 goto out;
@@ -1609,6 +1627,8 @@ static struct wlcore_ops wl12xx_ops = {
1609 .plt_init = wl12xx_plt_init, 1627 .plt_init = wl12xx_plt_init,
1610 .trigger_cmd = wl12xx_trigger_cmd, 1628 .trigger_cmd = wl12xx_trigger_cmd,
1611 .ack_event = wl12xx_ack_event, 1629 .ack_event = wl12xx_ack_event,
1630 .wait_for_event = wl12xx_wait_for_event,
1631 .process_mailbox_events = wl12xx_process_mailbox_events,
1612 .calc_tx_blocks = wl12xx_calc_tx_blocks, 1632 .calc_tx_blocks = wl12xx_calc_tx_blocks,
1613 .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks, 1633 .set_tx_desc_blocks = wl12xx_set_tx_desc_blocks,
1614 .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len, 1634 .set_tx_desc_data_len = wl12xx_set_tx_desc_data_len,
@@ -1627,7 +1647,6 @@ static struct wlcore_ops wl12xx_ops = {
1627 .debugfs_init = wl12xx_debugfs_add_files, 1647 .debugfs_init = wl12xx_debugfs_add_files,
1628 .scan_start = wl12xx_scan_start, 1648 .scan_start = wl12xx_scan_start,
1629 .scan_stop = wl12xx_scan_stop, 1649 .scan_stop = wl12xx_scan_stop,
1630 .scan_completed = wl12xx_scan_completed,
1631 .sched_scan_start = wl12xx_sched_scan_start, 1650 .sched_scan_start = wl12xx_sched_scan_start,
1632 .sched_scan_stop = wl12xx_scan_sched_scan_stop, 1651 .sched_scan_stop = wl12xx_scan_sched_scan_stop,
1633 .get_spare_blocks = wl12xx_get_spare_blocks, 1652 .get_spare_blocks = wl12xx_get_spare_blocks,
@@ -1719,7 +1738,8 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
1719 int ret; 1738 int ret;
1720 1739
1721 hw = wlcore_alloc_hw(sizeof(struct wl12xx_priv), 1740 hw = wlcore_alloc_hw(sizeof(struct wl12xx_priv),
1722 WL12XX_AGGR_BUFFER_SIZE); 1741 WL12XX_AGGR_BUFFER_SIZE,
1742 sizeof(struct wl12xx_event_mailbox));
1723 if (IS_ERR(hw)) { 1743 if (IS_ERR(hw)) {
1724 wl1271_error("can't allocate hw"); 1744 wl1271_error("can't allocate hw");
1725 ret = PTR_ERR(hw); 1745 ret = PTR_ERR(hw);
diff --git a/drivers/net/wireless/ti/wl18xx/Makefile b/drivers/net/wireless/ti/wl18xx/Makefile
index 81a864f3d793..ae2b81735785 100644
--- a/drivers/net/wireless/ti/wl18xx/Makefile
+++ b/drivers/net/wireless/ti/wl18xx/Makefile
@@ -1,3 +1,3 @@
1wl18xx-objs = main.o acx.o tx.o io.o debugfs.o scan.o cmd.o 1wl18xx-objs = main.o acx.o tx.o io.o debugfs.o scan.o cmd.o event.o
2 2
3obj-$(CONFIG_WL18XX) += wl18xx.o 3obj-$(CONFIG_WL18XX) += wl18xx.o
diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c
new file mode 100644
index 000000000000..bf4233c99028
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/event.c
@@ -0,0 +1,99 @@
1/*
2 * This file is part of wl12xx
3 *
4 * Copyright (C) 2012 Texas Instruments. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include "event.h"
23#include "scan.h"
24#include "../wlcore/cmd.h"
25#include "../wlcore/debug.h"
26
27int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
28 bool *timeout)
29{
30 u32 local_event;
31
32 switch (event) {
33 case WLCORE_EVENT_PEER_REMOVE_COMPLETE:
34 local_event = PEER_REMOVE_COMPLETE_EVENT_ID;
35 break;
36
37 default:
38 /* event not implemented */
39 return 0;
40 }
41 return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout);
42}
43
44int wl18xx_process_mailbox_events(struct wl1271 *wl)
45{
46 struct wl18xx_event_mailbox *mbox = wl->mbox;
47 u32 vector;
48
49 vector = le32_to_cpu(mbox->events_vector);
50 wl1271_debug(DEBUG_EVENT, "MBOX vector: 0x%x", vector);
51
52 if (vector & SCAN_COMPLETE_EVENT_ID) {
53 wl1271_debug(DEBUG_EVENT, "scan results: %d",
54 mbox->number_of_scan_results);
55
56 if (wl->scan_wlvif)
57 wl18xx_scan_completed(wl, wl->scan_wlvif);
58 }
59
60 if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID)
61 wlcore_event_sched_scan_completed(wl, 1);
62
63 if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID)
64 wlcore_event_rssi_trigger(wl, mbox->rssi_snr_trigger_metric);
65
66 if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)
67 wlcore_event_ba_rx_constraint(wl,
68 le16_to_cpu(mbox->rx_ba_role_id_bitmap),
69 le16_to_cpu(mbox->rx_ba_allowed_bitmap));
70
71 if (vector & BSS_LOSS_EVENT_ID)
72 wlcore_event_beacon_loss(wl,
73 le16_to_cpu(mbox->bss_loss_bitmap));
74
75 if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID)
76 wlcore_event_channel_switch(wl,
77 le16_to_cpu(mbox->channel_switch_role_id_bitmap),
78 true);
79
80 if (vector & DUMMY_PACKET_EVENT_ID)
81 wlcore_event_dummy_packet(wl);
82
83 /*
84 * "TX retries exceeded" has a different meaning according to mode.
85 * In AP mode the offending station is disconnected.
86 */
87 if (vector & MAX_TX_FAILURE_EVENT_ID)
88 wlcore_event_max_tx_failure(wl,
89 le32_to_cpu(mbox->tx_retry_exceeded_bitmap));
90
91 if (vector & INACTIVE_STA_EVENT_ID)
92 wlcore_event_inactive_sta(wl,
93 le32_to_cpu(mbox->inactive_sta_bitmap));
94
95 if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID)
96 wlcore_event_roc_complete(wl);
97
98 return 0;
99}
diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h
new file mode 100644
index 000000000000..b55fd31e471a
--- /dev/null
+++ b/drivers/net/wireless/ti/wl18xx/event.h
@@ -0,0 +1,76 @@
1/*
2 * This file is part of wl18xx
3 *
4 * Copyright (C) 2012 Texas Instruments. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#ifndef __WL18XX_EVENT_H__
23#define __WL18XX_EVENT_H__
24
25#include "../wlcore/wlcore.h"
26
27enum {
28 SCAN_COMPLETE_EVENT_ID = BIT(8),
29 RADAR_DETECTED_EVENT_ID = BIT(9),
30 CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(10),
31 BSS_LOSS_EVENT_ID = BIT(11),
32 MAX_TX_FAILURE_EVENT_ID = BIT(12),
33 DUMMY_PACKET_EVENT_ID = BIT(13),
34 INACTIVE_STA_EVENT_ID = BIT(14),
35 PEER_REMOVE_COMPLETE_EVENT_ID = BIT(15),
36 PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(16),
37 BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(17),
38 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(18),
39 DFS_CHANNELS_CONFIG_COMPLETE_EVENT = BIT(19),
40};
41
42struct wl18xx_event_mailbox {
43 __le32 events_vector;
44
45 u8 number_of_scan_results;
46 u8 number_of_sched_scan_results;
47
48 __le16 channel_switch_role_id_bitmap;
49
50 s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
51
52 /* bitmap of removed links */
53 __le32 hlid_removed_bitmap;
54
55 /* rx ba constraint */
56 __le16 rx_ba_role_id_bitmap; /* 0xfff means any role. */
57 __le16 rx_ba_allowed_bitmap;
58
59 /* bitmap of roc completed (by role id) */
60 __le16 roc_completed_bitmap;
61
62 /* bitmap of stations (by role id) with bss loss */
63 __le16 bss_loss_bitmap;
64
65 /* bitmap of stations (by HLID) which exceeded max tx retries */
66 __le32 tx_retry_exceeded_bitmap;
67
68 /* bitmap of inactive stations (by HLID) */
69 __le32 inactive_sta_bitmap;
70} __packed;
71
72int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
73 bool *timeout);
74int wl18xx_process_mailbox_events(struct wl1271 *wl);
75
76#endif
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 2e54a3ea813c..0895ffaad5a9 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -40,6 +40,7 @@
40#include "wl18xx.h" 40#include "wl18xx.h"
41#include "io.h" 41#include "io.h"
42#include "scan.h" 42#include "scan.h"
43#include "event.h"
43#include "debugfs.h" 44#include "debugfs.h"
44 45
45#define WL18XX_RX_CHECKSUM_MASK 0x40 46#define WL18XX_RX_CHECKSUM_MASK 0x40
@@ -851,6 +852,18 @@ static int wl18xx_boot(struct wl1271 *wl)
851 if (ret < 0) 852 if (ret < 0)
852 goto out; 853 goto out;
853 854
855 wl->event_mask = BSS_LOSS_EVENT_ID |
856 SCAN_COMPLETE_EVENT_ID |
857 RSSI_SNR_TRIGGER_0_EVENT_ID |
858 PERIODIC_SCAN_COMPLETE_EVENT_ID |
859 DUMMY_PACKET_EVENT_ID |
860 PEER_REMOVE_COMPLETE_EVENT_ID |
861 BA_SESSION_RX_CONSTRAINT_EVENT_ID |
862 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
863 INACTIVE_STA_EVENT_ID |
864 MAX_TX_FAILURE_EVENT_ID |
865 CHANNEL_SWITCH_COMPLETE_EVENT_ID;
866
854 ret = wlcore_boot_run_firmware(wl); 867 ret = wlcore_boot_run_firmware(wl);
855 if (ret < 0) 868 if (ret < 0)
856 goto out; 869 goto out;
@@ -1313,6 +1326,8 @@ static struct wlcore_ops wl18xx_ops = {
1313 .plt_init = wl18xx_plt_init, 1326 .plt_init = wl18xx_plt_init,
1314 .trigger_cmd = wl18xx_trigger_cmd, 1327 .trigger_cmd = wl18xx_trigger_cmd,
1315 .ack_event = wl18xx_ack_event, 1328 .ack_event = wl18xx_ack_event,
1329 .wait_for_event = wl18xx_wait_for_event,
1330 .process_mailbox_events = wl18xx_process_mailbox_events,
1316 .calc_tx_blocks = wl18xx_calc_tx_blocks, 1331 .calc_tx_blocks = wl18xx_calc_tx_blocks,
1317 .set_tx_desc_blocks = wl18xx_set_tx_desc_blocks, 1332 .set_tx_desc_blocks = wl18xx_set_tx_desc_blocks,
1318 .set_tx_desc_data_len = wl18xx_set_tx_desc_data_len, 1333 .set_tx_desc_data_len = wl18xx_set_tx_desc_data_len,
@@ -1330,7 +1345,6 @@ static struct wlcore_ops wl18xx_ops = {
1330 .debugfs_init = wl18xx_debugfs_add_files, 1345 .debugfs_init = wl18xx_debugfs_add_files,
1331 .scan_start = wl18xx_scan_start, 1346 .scan_start = wl18xx_scan_start,
1332 .scan_stop = wl18xx_scan_stop, 1347 .scan_stop = wl18xx_scan_stop,
1333 .scan_completed = wl18xx_scan_completed,
1334 .sched_scan_start = wl18xx_sched_scan_start, 1348 .sched_scan_start = wl18xx_sched_scan_start,
1335 .sched_scan_stop = wl18xx_scan_sched_scan_stop, 1349 .sched_scan_stop = wl18xx_scan_sched_scan_stop,
1336 .handle_static_data = wl18xx_handle_static_data, 1350 .handle_static_data = wl18xx_handle_static_data,
@@ -1524,7 +1538,8 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
1524 int ret; 1538 int ret;
1525 1539
1526 hw = wlcore_alloc_hw(sizeof(struct wl18xx_priv), 1540 hw = wlcore_alloc_hw(sizeof(struct wl18xx_priv),
1527 WL18XX_AGGR_BUFFER_SIZE); 1541 WL18XX_AGGR_BUFFER_SIZE,
1542 sizeof(struct wl18xx_event_mailbox));
1528 if (IS_ERR(hw)) { 1543 if (IS_ERR(hw)) {
1529 wl1271_error("can't allocate hw"); 1544 wl1271_error("can't allocate hw");
1530 ret = PTR_ERR(hw); 1545 ret = PTR_ERR(hw);
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c
index 375ea574eafb..230c765ab401 100644
--- a/drivers/net/wireless/ti/wlcore/boot.c
+++ b/drivers/net/wireless/ti/wlcore/boot.c
@@ -491,7 +491,7 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
491 if (ret < 0) 491 if (ret < 0)
492 return ret; 492 return ret;
493 493
494 wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); 494 wl->mbox_ptr[1] = wl->mbox_ptr[0] + wl->mbox_size;
495 495
496 wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", 496 wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x",
497 wl->mbox_ptr[0], wl->mbox_ptr[1]); 497 wl->mbox_ptr[0], wl->mbox_ptr[1]);
@@ -508,23 +508,6 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
508 */ 508 */
509 509
510 /* unmask required mbox events */ 510 /* unmask required mbox events */
511 wl->event_mask = BSS_LOSE_EVENT_ID |
512 REGAINED_BSS_EVENT_ID |
513 SCAN_COMPLETE_EVENT_ID |
514 ROLE_STOP_COMPLETE_EVENT_ID |
515 RSSI_SNR_TRIGGER_0_EVENT_ID |
516 PSPOLL_DELIVERY_FAILURE_EVENT_ID |
517 SOFT_GEMINI_SENSE_EVENT_ID |
518 PERIODIC_SCAN_REPORT_EVENT_ID |
519 PERIODIC_SCAN_COMPLETE_EVENT_ID |
520 DUMMY_PACKET_EVENT_ID |
521 PEER_REMOVE_COMPLETE_EVENT_ID |
522 BA_SESSION_RX_CONSTRAINT_EVENT_ID |
523 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
524 INACTIVE_STA_EVENT_ID |
525 MAX_TX_RETRY_EVENT_ID |
526 CHANNEL_SWITCH_COMPLETE_EVENT_ID;
527
528 ret = wl1271_event_unmask(wl); 511 ret = wl1271_event_unmask(wl);
529 if (ret < 0) { 512 if (ret < 0) {
530 wl1271_error("EVENT mask setting failed"); 513 wl1271_error("EVENT mask setting failed");
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 979676529ed0..63102f20df63 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -137,8 +137,8 @@ EXPORT_SYMBOL_GPL(wl1271_cmd_send);
137 * Poll the mailbox event field until any of the bits in the mask is set or a 137 * Poll the mailbox event field until any of the bits in the mask is set or a
138 * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) 138 * timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
139 */ 139 */
140static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, 140int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
141 u32 mask, bool *timeout) 141 u32 mask, bool *timeout)
142{ 142{
143 u32 *events_vector; 143 u32 *events_vector;
144 u32 event; 144 u32 event;
@@ -188,20 +188,7 @@ out:
188 kfree(events_vector); 188 kfree(events_vector);
189 return ret; 189 return ret;
190} 190}
191 191EXPORT_SYMBOL_GPL(wlcore_cmd_wait_for_event_or_timeout);
192static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
193{
194 int ret;
195 bool timeout = false;
196
197 ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask, &timeout);
198 if (ret != 0 || timeout) {
199 wl12xx_queue_recovery_work(wl);
200 return ret;
201 }
202
203 return 0;
204}
205 192
206int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, 193int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type,
207 u8 *role_id) 194 u8 *role_id)
@@ -423,12 +410,6 @@ static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl,
423 goto out_free; 410 goto out_free;
424 } 411 }
425 412
426 ret = wl1271_cmd_wait_for_event(wl, ROLE_STOP_COMPLETE_EVENT_ID);
427 if (ret < 0) {
428 wl1271_error("cmd role stop dev event completion error");
429 goto out_free;
430 }
431
432 wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid); 413 wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid);
433 414
434out_free: 415out_free:
@@ -516,7 +497,6 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
516{ 497{
517 struct wl12xx_cmd_role_stop *cmd; 498 struct wl12xx_cmd_role_stop *cmd;
518 int ret; 499 int ret;
519 bool timeout = false;
520 500
521 if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID)) 501 if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID))
522 return -EINVAL; 502 return -EINVAL;
@@ -539,17 +519,6 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
539 goto out_free; 519 goto out_free;
540 } 520 }
541 521
542 /*
543 * Sometimes the firmware doesn't send this event, so we just
544 * time out without failing. Queue recovery for other
545 * failures.
546 */
547 ret = wl1271_cmd_wait_for_event_or_timeout(wl,
548 ROLE_STOP_COMPLETE_EVENT_ID,
549 &timeout);
550 if (ret)
551 wl12xx_queue_recovery_work(wl);
552
553 wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); 522 wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid);
554 523
555out_free: 524out_free:
@@ -1505,9 +1474,10 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
1505 goto out_free; 1474 goto out_free;
1506 } 1475 }
1507 1476
1508 ret = wl1271_cmd_wait_for_event_or_timeout(wl, 1477 ret = wl->ops->wait_for_event(wl,
1509 PEER_REMOVE_COMPLETE_EVENT_ID, 1478 WLCORE_EVENT_PEER_REMOVE_COMPLETE,
1510 &timeout); 1479 &timeout);
1480
1511 /* 1481 /*
1512 * We are ok with a timeout here. The event is sometimes not sent 1482 * We are ok with a timeout here. The event is sometimes not sent
1513 * due to a firmware bug. In case of another error (like SDIO timeout) 1483 * due to a firmware bug. In case of another error (like SDIO timeout)
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index 96d53a730a31..46513dac5fb1 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -94,6 +94,8 @@ int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl,
94int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, 94int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif,
95 u8 *hlid); 95 u8 *hlid);
96void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid); 96void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid);
97int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
98 u32 mask, bool *timeout);
97 99
98enum wl1271_commands { 100enum wl1271_commands {
99 CMD_INTERROGATE = 1, /* use this to read information elements */ 101 CMD_INTERROGATE = 1, /* use this to read information elements */
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index d9353dad08d9..3c20393d255e 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -29,25 +29,29 @@
29#include "scan.h" 29#include "scan.h"
30#include "wl12xx_80211.h" 30#include "wl12xx_80211.h"
31 31
32static void wl1271_event_rssi_trigger(struct wl1271 *wl, 32void wlcore_event_rssi_trigger(struct wl1271 *wl, s8 *metric_arr)
33 struct wl12xx_vif *wlvif,
34 struct event_mailbox *mbox)
35{ 33{
36 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); 34 struct wl12xx_vif *wlvif;
35 struct ieee80211_vif *vif;
37 enum nl80211_cqm_rssi_threshold_event event; 36 enum nl80211_cqm_rssi_threshold_event event;
38 s8 metric = mbox->rssi_snr_trigger_metric[0]; 37 s8 metric = metric_arr[0];
39 38
40 wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric); 39 wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric);
41 40
42 if (metric <= wlvif->rssi_thold) 41 /* TODO: check actual multi-role support */
43 event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; 42 wl12xx_for_each_wlvif_sta(wl, wlvif) {
44 else 43 if (metric <= wlvif->rssi_thold)
45 event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; 44 event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
46 45 else
47 if (event != wlvif->last_rssi_event) 46 event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
48 ieee80211_cqm_rssi_notify(vif, event, GFP_KERNEL); 47
49 wlvif->last_rssi_event = event; 48 vif = wl12xx_wlvif_to_vif(wlvif);
49 if (event != wlvif->last_rssi_event)
50 ieee80211_cqm_rssi_notify(vif, event, GFP_KERNEL);
51 wlvif->last_rssi_event = event;
52 }
50} 53}
54EXPORT_SYMBOL_GPL(wlcore_event_rssi_trigger);
51 55
52static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) 56static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
53{ 57{
@@ -74,8 +78,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
74 } 78 }
75} 79}
76 80
77static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, 81void wlcore_event_soft_gemini_sense(struct wl1271 *wl, u8 enable)
78 u8 enable)
79{ 82{
80 struct wl12xx_vif *wlvif; 83 struct wl12xx_vif *wlvif;
81 84
@@ -87,210 +90,179 @@ static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
87 wl1271_recalc_rx_streaming(wl, wlvif); 90 wl1271_recalc_rx_streaming(wl, wlvif);
88 } 91 }
89 } 92 }
90
91} 93}
94EXPORT_SYMBOL_GPL(wlcore_event_soft_gemini_sense);
92 95
93static void wl1271_event_mbox_dump(struct event_mailbox *mbox) 96void wlcore_event_sched_scan_report(struct wl1271 *wl,
97 u8 status)
94{ 98{
95 wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); 99 wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_REPORT_EVENT (status 0x%0x)",
96 wl1271_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector); 100 status);
97 wl1271_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask); 101
102 wl1271_scan_sched_scan_results(wl);
98} 103}
104EXPORT_SYMBOL_GPL(wlcore_event_sched_scan_report);
99 105
100static int wl1271_event_process(struct wl1271 *wl) 106void wlcore_event_sched_scan_completed(struct wl1271 *wl,
107 u8 status)
101{ 108{
102 struct event_mailbox *mbox = wl->mbox; 109 wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT (status 0x%0x)",
103 struct ieee80211_vif *vif; 110 status);
104 struct wl12xx_vif *wlvif;
105 u32 vector;
106 bool disconnect_sta = false;
107 unsigned long sta_bitmap = 0;
108 int ret;
109 111
110 wl1271_event_mbox_dump(mbox); 112 if (wl->sched_scanning) {
113 ieee80211_sched_scan_stopped(wl->hw);
114 wl->sched_scanning = false;
115 }
116}
117EXPORT_SYMBOL_GPL(wlcore_event_sched_scan_completed);
111 118
112 vector = le32_to_cpu(mbox->events_vector); 119void wlcore_event_ba_rx_constraint(struct wl1271 *wl,
113 vector &= ~(le32_to_cpu(mbox->events_mask)); 120 unsigned long roles_bitmap,
114 wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); 121 unsigned long allowed_bitmap)
122{
123 struct wl12xx_vif *wlvif;
115 124
116 if (vector & SCAN_COMPLETE_EVENT_ID) { 125 wl1271_debug(DEBUG_EVENT, "%s: roles=0x%lx allowed=0x%lx",
117 wl1271_debug(DEBUG_EVENT, "status: 0x%x", 126 __func__, roles_bitmap, allowed_bitmap);
118 mbox->scheduled_scan_status);
119 127
120 if (wl->scan_vif) 128 wl12xx_for_each_wlvif(wl, wlvif) {
121 wl->ops->scan_completed(wl, 129 if (wlvif->role_id == WL12XX_INVALID_ROLE_ID ||
122 wl12xx_vif_to_data(wl->scan_vif)); 130 !test_bit(wlvif->role_id , &roles_bitmap))
123 } 131 continue;
124 132
125 if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { 133 wlvif->ba_allowed = !!test_bit(wlvif->role_id,
126 wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_REPORT_EVENT " 134 &allowed_bitmap);
127 "(status 0x%0x)", mbox->scheduled_scan_status); 135 if (!wlvif->ba_allowed)
128 136 wl1271_stop_ba_event(wl, wlvif);
129 wl1271_scan_sched_scan_results(wl);
130 } 137 }
138}
139EXPORT_SYMBOL_GPL(wlcore_event_ba_rx_constraint);
131 140
132 if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) { 141void wlcore_event_channel_switch(struct wl1271 *wl,
133 wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT " 142 unsigned long roles_bitmap,
134 "(status 0x%0x)", mbox->scheduled_scan_status); 143 bool success)
135 if (wl->sched_scanning) { 144{
136 ieee80211_sched_scan_stopped(wl->hw); 145 struct wl12xx_vif *wlvif;
137 wl->sched_scanning = false; 146 struct ieee80211_vif *vif;
138 }
139 }
140 147
141 if (vector & SOFT_GEMINI_SENSE_EVENT_ID) 148 wl1271_debug(DEBUG_EVENT, "%s: roles=0x%lx success=%d",
142 wl12xx_event_soft_gemini_sense(wl, 149 __func__, roles_bitmap, success);
143 mbox->soft_gemini_sense_info);
144 150
145 /* 151 wl12xx_for_each_wlvif_sta(wl, wlvif) {
146 * We are HW_MONITOR device. On beacon loss - queue 152 if (wlvif->role_id == WL12XX_INVALID_ROLE_ID ||
147 * connection loss work. Cancel it on REGAINED event. 153 !test_bit(wlvif->role_id , &roles_bitmap))
148 */ 154 continue;
149 if (vector & BSS_LOSE_EVENT_ID) {
150 /* TODO: check for multi-role */
151 int delay = wl->conf.conn.synch_fail_thold *
152 wl->conf.conn.bss_lose_timeout;
153 wl1271_info("Beacon loss detected.");
154 155
155 /* 156 if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS,
156 * if the work is already queued, it should take place. We 157 &wlvif->flags))
157 * don't want to delay the connection loss indication 158 continue;
158 * any more.
159 */
160 ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work,
161 msecs_to_jiffies(delay));
162 159
163 wl12xx_for_each_wlvif_sta(wl, wlvif) { 160 vif = wl12xx_wlvif_to_vif(wlvif);
164 vif = wl12xx_wlvif_to_vif(wlvif);
165 161
166 ieee80211_cqm_rssi_notify( 162 ieee80211_chswitch_done(vif, success);
167 vif, 163 cancel_delayed_work(&wlvif->channel_switch_work);
168 NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
169 GFP_KERNEL);
170 }
171 } 164 }
165}
166EXPORT_SYMBOL_GPL(wlcore_event_channel_switch);
172 167
173 if (vector & REGAINED_BSS_EVENT_ID) { 168void wlcore_event_dummy_packet(struct wl1271 *wl)
174 /* TODO: check for multi-role */ 169{
175 wl1271_info("Beacon regained."); 170 wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
176 cancel_delayed_work(&wl->connection_loss_work); 171 wl1271_tx_dummy_packet(wl);
177 172}
178 /* sanity check - we can't lose and gain the beacon together */ 173EXPORT_SYMBOL_GPL(wlcore_event_dummy_packet);
179 WARN(vector & BSS_LOSE_EVENT_ID,
180 "Concurrent beacon loss and gain from FW");
181 }
182 174
183 if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { 175static void wlcore_disconnect_sta(struct wl1271 *wl, unsigned long sta_bitmap)
184 /* TODO: check actual multi-role support */ 176{
185 wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); 177 u32 num_packets = wl->conf.tx.max_tx_retries;
186 wl12xx_for_each_wlvif_sta(wl, wlvif) { 178 struct wl12xx_vif *wlvif;
187 wl1271_event_rssi_trigger(wl, wlvif, mbox); 179 struct ieee80211_vif *vif;
180 struct ieee80211_sta *sta;
181 const u8 *addr;
182 int h;
183
184 for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) {
185 bool found = false;
186 /* find the ap vif connected to this sta */
187 wl12xx_for_each_wlvif_ap(wl, wlvif) {
188 if (!test_bit(h, wlvif->ap.sta_hlid_map))
189 continue;
190 found = true;
191 break;
188 } 192 }
189 } 193 if (!found)
190 194 continue;
191 if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) {
192 u8 role_id = mbox->role_id;
193 wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
194 "ba_allowed = 0x%x, role_id=%d",
195 mbox->rx_ba_allowed, role_id);
196 195
197 wl12xx_for_each_wlvif(wl, wlvif) { 196 vif = wl12xx_wlvif_to_vif(wlvif);
198 if (role_id != 0xff && role_id != wlvif->role_id) 197 addr = wl->links[h].addr;
199 continue;
200 198
201 wlvif->ba_allowed = !!mbox->rx_ba_allowed; 199 rcu_read_lock();
202 if (!wlvif->ba_allowed) 200 sta = ieee80211_find_sta(vif, addr);
203 wl1271_stop_ba_event(wl, wlvif); 201 if (sta) {
202 wl1271_debug(DEBUG_EVENT, "remove sta %d", h);
203 ieee80211_report_low_ack(sta, num_packets);
204 } 204 }
205 rcu_read_unlock();
205 } 206 }
207}
206 208
207 if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) { 209void wlcore_event_max_tx_failure(struct wl1271 *wl, unsigned long sta_bitmap)
208 wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. " 210{
209 "status = 0x%x", 211 wl1271_debug(DEBUG_EVENT, "MAX_TX_FAILURE_EVENT_ID");
210 mbox->channel_switch_status); 212 wlcore_disconnect_sta(wl, sta_bitmap);
211 /* 213}
212 * That event uses for two cases: 214EXPORT_SYMBOL_GPL(wlcore_event_max_tx_failure);
213 * 1) channel switch complete with status=0
214 * 2) channel switch failed status=1
215 */
216
217 /* TODO: configure only the relevant vif */
218 wl12xx_for_each_wlvif_sta(wl, wlvif) {
219 bool success;
220
221 if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS,
222 &wlvif->flags))
223 continue;
224
225 success = mbox->channel_switch_status ? false : true;
226 vif = wl12xx_wlvif_to_vif(wlvif);
227 215
228 ieee80211_chswitch_done(vif, success); 216void wlcore_event_inactive_sta(struct wl1271 *wl, unsigned long sta_bitmap)
229 } 217{
230 } 218 wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
219 wlcore_disconnect_sta(wl, sta_bitmap);
220}
221EXPORT_SYMBOL_GPL(wlcore_event_inactive_sta);
231 222
232 if ((vector & DUMMY_PACKET_EVENT_ID)) { 223void wlcore_event_roc_complete(struct wl1271 *wl)
233 wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); 224{
234 ret = wl1271_tx_dummy_packet(wl); 225 wl1271_debug(DEBUG_EVENT, "REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID");
235 if (ret < 0) 226 if (wl->roc_vif)
236 return ret; 227 ieee80211_ready_on_channel(wl->hw);
237 } 228}
229EXPORT_SYMBOL_GPL(wlcore_event_roc_complete);
238 230
231void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap)
232{
239 /* 233 /*
240 * "TX retries exceeded" has a different meaning according to mode. 234 * We are HW_MONITOR device. On beacon loss - queue
241 * In AP mode the offending station is disconnected. 235 * connection loss work. Cancel it on REGAINED event.
242 */ 236 */
243 if (vector & MAX_TX_RETRY_EVENT_ID) { 237 struct wl12xx_vif *wlvif;
244 wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); 238 struct ieee80211_vif *vif;
245 sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); 239 int delay = wl->conf.conn.synch_fail_thold *
246 disconnect_sta = true; 240 wl->conf.conn.bss_lose_timeout;
247 }
248
249 if (vector & INACTIVE_STA_EVENT_ID) {
250 wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
251 sta_bitmap |= le16_to_cpu(mbox->sta_aging_status);
252 disconnect_sta = true;
253 }
254 241
255 if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID) { 242 wl1271_info("Beacon loss detected. roles:0x%lx", roles_bitmap);
256 wl1271_debug(DEBUG_EVENT,
257 "REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID");
258 if (wl->roc_vif)
259 ieee80211_ready_on_channel(wl->hw);
260 }
261 243
262 if (disconnect_sta) { 244 wl12xx_for_each_wlvif_sta(wl, wlvif) {
263 u32 num_packets = wl->conf.tx.max_tx_retries; 245 if (wlvif->role_id == WL12XX_INVALID_ROLE_ID ||
264 struct ieee80211_sta *sta; 246 !test_bit(wlvif->role_id , &roles_bitmap))
265 const u8 *addr; 247 continue;
266 int h;
267
268 for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) {
269 bool found = false;
270 /* find the ap vif connected to this sta */
271 wl12xx_for_each_wlvif_ap(wl, wlvif) {
272 if (!test_bit(h, wlvif->ap.sta_hlid_map))
273 continue;
274 found = true;
275 break;
276 }
277 if (!found)
278 continue;
279 248
280 vif = wl12xx_wlvif_to_vif(wlvif); 249 /*
281 addr = wl->links[h].addr; 250 * if the work is already queued, it should take place.
251 * We don't want to delay the connection loss
252 * indication any more.
253 */
254 ieee80211_queue_delayed_work(wl->hw,
255 &wlvif->connection_loss_work,
256 msecs_to_jiffies(delay));
282 257
283 rcu_read_lock(); 258 vif = wl12xx_wlvif_to_vif(wlvif);
284 sta = ieee80211_find_sta(vif, addr); 259 ieee80211_cqm_rssi_notify(
285 if (sta) { 260 vif,
286 wl1271_debug(DEBUG_EVENT, "remove sta %d", h); 261 NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
287 ieee80211_report_low_ack(sta, num_packets); 262 GFP_KERNEL);
288 }
289 rcu_read_unlock();
290 }
291 } 263 }
292 return 0;
293} 264}
265EXPORT_SYMBOL_GPL(wlcore_event_beacon_loss);
294 266
295int wl1271_event_unmask(struct wl1271 *wl) 267int wl1271_event_unmask(struct wl1271 *wl)
296{ 268{
@@ -314,12 +286,12 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
314 286
315 /* first we read the mbox descriptor */ 287 /* first we read the mbox descriptor */
316 ret = wlcore_read(wl, wl->mbox_ptr[mbox_num], wl->mbox, 288 ret = wlcore_read(wl, wl->mbox_ptr[mbox_num], wl->mbox,
317 sizeof(*wl->mbox), false); 289 wl->mbox_size, false);
318 if (ret < 0) 290 if (ret < 0)
319 return ret; 291 return ret;
320 292
321 /* process the descriptor */ 293 /* process the descriptor */
322 ret = wl1271_event_process(wl); 294 ret = wl->ops->process_mailbox_events(wl);
323 if (ret < 0) 295 if (ret < 0)
324 return ret; 296 return ret;
325 297
diff --git a/drivers/net/wireless/ti/wlcore/event.h b/drivers/net/wireless/ti/wlcore/event.h
index 8adf18d6c58f..766b02f15780 100644
--- a/drivers/net/wireless/ti/wlcore/event.h
+++ b/drivers/net/wireless/ti/wlcore/event.h
@@ -46,33 +46,16 @@ enum {
46 RSSI_SNR_TRIGGER_5_EVENT_ID = BIT(5), 46 RSSI_SNR_TRIGGER_5_EVENT_ID = BIT(5),
47 RSSI_SNR_TRIGGER_6_EVENT_ID = BIT(6), 47 RSSI_SNR_TRIGGER_6_EVENT_ID = BIT(6),
48 RSSI_SNR_TRIGGER_7_EVENT_ID = BIT(7), 48 RSSI_SNR_TRIGGER_7_EVENT_ID = BIT(7),
49 MEASUREMENT_START_EVENT_ID = BIT(8), 49
50 MEASUREMENT_COMPLETE_EVENT_ID = BIT(9),
51 SCAN_COMPLETE_EVENT_ID = BIT(10),
52 WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11),
53 AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12),
54 RESERVED1 = BIT(13),
55 PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14),
56 ROLE_STOP_COMPLETE_EVENT_ID = BIT(15),
57 RADAR_DETECTED_EVENT_ID = BIT(16),
58 CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
59 BSS_LOSE_EVENT_ID = BIT(18),
60 REGAINED_BSS_EVENT_ID = BIT(19),
61 MAX_TX_RETRY_EVENT_ID = BIT(20),
62 DUMMY_PACKET_EVENT_ID = BIT(21),
63 SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
64 CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID = BIT(23),
65 SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
66 PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25),
67 INACTIVE_STA_EVENT_ID = BIT(26),
68 PEER_REMOVE_COMPLETE_EVENT_ID = BIT(27),
69 PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28),
70 PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29),
71 BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30),
72 REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(31),
73 EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff, 50 EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff,
74}; 51};
75 52
53/* events the driver might want to wait for */
54enum wlcore_wait_event {
55 WLCORE_EVENT_ROLE_STOP_COMPLETE,
56 WLCORE_EVENT_PEER_REMOVE_COMPLETE,
57};
58
76enum { 59enum {
77 EVENT_ENTER_POWER_SAVE_FAIL = 0, 60 EVENT_ENTER_POWER_SAVE_FAIL = 0,
78 EVENT_ENTER_POWER_SAVE_SUCCESS, 61 EVENT_ENTER_POWER_SAVE_SUCCESS,
@@ -80,61 +63,26 @@ enum {
80 63
81#define NUM_OF_RSSI_SNR_TRIGGERS 8 64#define NUM_OF_RSSI_SNR_TRIGGERS 8
82 65
83struct event_mailbox {
84 __le32 events_vector;
85 __le32 events_mask;
86 __le32 reserved_1;
87 __le32 reserved_2;
88
89 u8 number_of_scan_results;
90 u8 scan_tag;
91 u8 completed_scan_status;
92 u8 reserved_3;
93
94 u8 soft_gemini_sense_info;
95 u8 soft_gemini_protective_info;
96 s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
97 u8 change_auto_mode_timeout;
98 u8 scheduled_scan_status;
99 u8 reserved4;
100 /* tuned channel (roc) */
101 u8 roc_channel;
102
103 __le16 hlid_removed_bitmap;
104
105 /* bitmap of aged stations (by HLID) */
106 __le16 sta_aging_status;
107
108 /* bitmap of stations (by HLID) which exceeded max tx retries */
109 __le16 sta_tx_retry_exceeded;
110
111 /* discovery completed results */
112 u8 discovery_tag;
113 u8 number_of_preq_results;
114 u8 number_of_prsp_results;
115 u8 reserved_5;
116
117 /* rx ba constraint */
118 u8 role_id; /* 0xFF means any role. */
119 u8 rx_ba_allowed;
120 u8 reserved_6[2];
121
122 /* Channel switch results */
123
124 u8 channel_switch_role_id;
125 u8 channel_switch_status;
126 u8 reserved_7[2];
127
128 u8 ps_poll_delivery_failure_role_ids;
129 u8 stopped_role_ids;
130 u8 started_role_ids;
131
132 u8 reserved_8[9];
133} __packed;
134
135struct wl1271; 66struct wl1271;
136 67
137int wl1271_event_unmask(struct wl1271 *wl); 68int wl1271_event_unmask(struct wl1271 *wl);
138int wl1271_event_handle(struct wl1271 *wl, u8 mbox); 69int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
139 70
71void wlcore_event_soft_gemini_sense(struct wl1271 *wl, u8 enable);
72void wlcore_event_sched_scan_report(struct wl1271 *wl,
73 u8 status);
74void wlcore_event_sched_scan_completed(struct wl1271 *wl,
75 u8 status);
76void wlcore_event_ba_rx_constraint(struct wl1271 *wl,
77 unsigned long roles_bitmap,
78 unsigned long allowed_bitmap);
79void wlcore_event_channel_switch(struct wl1271 *wl,
80 unsigned long roles_bitmap,
81 bool success);
82void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap);
83void wlcore_event_dummy_packet(struct wl1271 *wl);
84void wlcore_event_max_tx_failure(struct wl1271 *wl, unsigned long sta_bitmap);
85void wlcore_event_inactive_sta(struct wl1271 *wl, unsigned long sta_bitmap);
86void wlcore_event_roc_complete(struct wl1271 *wl);
87void wlcore_event_rssi_trigger(struct wl1271 *wl, s8 *metric_arr);
140#endif 88#endif
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index efb770a02822..043bf7f7c005 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1139,7 +1139,6 @@ int wl1271_plt_stop(struct wl1271 *wl)
1139 cancel_work_sync(&wl->recovery_work); 1139 cancel_work_sync(&wl->recovery_work);
1140 cancel_delayed_work_sync(&wl->elp_work); 1140 cancel_delayed_work_sync(&wl->elp_work);
1141 cancel_delayed_work_sync(&wl->tx_watchdog_work); 1141 cancel_delayed_work_sync(&wl->tx_watchdog_work);
1142 cancel_delayed_work_sync(&wl->connection_loss_work);
1143 1142
1144 mutex_lock(&wl->mutex); 1143 mutex_lock(&wl->mutex);
1145 wl1271_power_off(wl); 1144 wl1271_power_off(wl);
@@ -1841,7 +1840,6 @@ static void wlcore_op_stop_locked(struct wl1271 *wl)
1841 cancel_work_sync(&wl->tx_work); 1840 cancel_work_sync(&wl->tx_work);
1842 cancel_delayed_work_sync(&wl->elp_work); 1841 cancel_delayed_work_sync(&wl->elp_work);
1843 cancel_delayed_work_sync(&wl->tx_watchdog_work); 1842 cancel_delayed_work_sync(&wl->tx_watchdog_work);
1844 cancel_delayed_work_sync(&wl->connection_loss_work);
1845 1843
1846 /* let's notify MAC80211 about the remaining pending TX frames */ 1844 /* let's notify MAC80211 about the remaining pending TX frames */
1847 wl12xx_tx_reset(wl); 1845 wl12xx_tx_reset(wl);
@@ -1916,6 +1914,71 @@ static void wlcore_op_stop(struct ieee80211_hw *hw)
1916 mutex_unlock(&wl->mutex); 1914 mutex_unlock(&wl->mutex);
1917} 1915}
1918 1916
1917static void wlcore_channel_switch_work(struct work_struct *work)
1918{
1919 struct delayed_work *dwork;
1920 struct wl1271 *wl;
1921 struct ieee80211_vif *vif;
1922 struct wl12xx_vif *wlvif;
1923 int ret;
1924
1925 dwork = container_of(work, struct delayed_work, work);
1926 wlvif = container_of(dwork, struct wl12xx_vif, channel_switch_work);
1927 wl = wlvif->wl;
1928
1929 wl1271_info("channel switch failed (role_id: %d).", wlvif->role_id);
1930
1931 mutex_lock(&wl->mutex);
1932
1933 if (unlikely(wl->state != WLCORE_STATE_ON))
1934 goto out;
1935
1936 /* check the channel switch is still ongoing */
1937 if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags))
1938 goto out;
1939
1940 vif = wl12xx_wlvif_to_vif(wlvif);
1941 ieee80211_chswitch_done(vif, false);
1942
1943 ret = wl1271_ps_elp_wakeup(wl);
1944 if (ret < 0)
1945 goto out;
1946
1947 wl12xx_cmd_stop_channel_switch(wl, wlvif);
1948
1949 wl1271_ps_elp_sleep(wl);
1950out:
1951 mutex_unlock(&wl->mutex);
1952}
1953
1954static void wlcore_connection_loss_work(struct work_struct *work)
1955{
1956 struct delayed_work *dwork;
1957 struct wl1271 *wl;
1958 struct ieee80211_vif *vif;
1959 struct wl12xx_vif *wlvif;
1960
1961 dwork = container_of(work, struct delayed_work, work);
1962 wlvif = container_of(dwork, struct wl12xx_vif, connection_loss_work);
1963 wl = wlvif->wl;
1964
1965 wl1271_info("Connection loss work (role_id: %d).", wlvif->role_id);
1966
1967 mutex_lock(&wl->mutex);
1968
1969 if (unlikely(wl->state != WLCORE_STATE_ON))
1970 goto out;
1971
1972 /* Call mac80211 connection loss */
1973 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
1974 goto out;
1975
1976 vif = wl12xx_wlvif_to_vif(wlvif);
1977 ieee80211_connection_loss(vif);
1978out:
1979 mutex_unlock(&wl->mutex);
1980}
1981
1919static int wl12xx_allocate_rate_policy(struct wl1271 *wl, u8 *idx) 1982static int wl12xx_allocate_rate_policy(struct wl1271 *wl, u8 *idx)
1920{ 1983{
1921 u8 policy = find_first_zero_bit(wl->rate_policies_map, 1984 u8 policy = find_first_zero_bit(wl->rate_policies_map,
@@ -2063,6 +2126,10 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
2063 wl1271_rx_streaming_enable_work); 2126 wl1271_rx_streaming_enable_work);
2064 INIT_WORK(&wlvif->rx_streaming_disable_work, 2127 INIT_WORK(&wlvif->rx_streaming_disable_work,
2065 wl1271_rx_streaming_disable_work); 2128 wl1271_rx_streaming_disable_work);
2129 INIT_DELAYED_WORK(&wlvif->channel_switch_work,
2130 wlcore_channel_switch_work);
2131 INIT_DELAYED_WORK(&wlvif->connection_loss_work,
2132 wlcore_connection_loss_work);
2066 INIT_LIST_HEAD(&wlvif->list); 2133 INIT_LIST_HEAD(&wlvif->list);
2067 2134
2068 setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, 2135 setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer,
@@ -2312,7 +2379,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
2312 wl1271_info("down"); 2379 wl1271_info("down");
2313 2380
2314 if (wl->scan.state != WL1271_SCAN_STATE_IDLE && 2381 if (wl->scan.state != WL1271_SCAN_STATE_IDLE &&
2315 wl->scan_vif == vif) { 2382 wl->scan_wlvif == wlvif) {
2316 /* 2383 /*
2317 * Rearm the tx watchdog just before idling scan. This 2384 * Rearm the tx watchdog just before idling scan. This
2318 * prevents just-finished scans from triggering the watchdog 2385 * prevents just-finished scans from triggering the watchdog
@@ -2321,7 +2388,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
2321 2388
2322 wl->scan.state = WL1271_SCAN_STATE_IDLE; 2389 wl->scan.state = WL1271_SCAN_STATE_IDLE;
2323 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); 2390 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
2324 wl->scan_vif = NULL; 2391 wl->scan_wlvif = NULL;
2325 wl->scan.req = NULL; 2392 wl->scan.req = NULL;
2326 ieee80211_scan_completed(wl->hw, true); 2393 ieee80211_scan_completed(wl->hw, true);
2327 } 2394 }
@@ -2408,6 +2475,7 @@ unlock:
2408 del_timer_sync(&wlvif->rx_streaming_timer); 2475 del_timer_sync(&wlvif->rx_streaming_timer);
2409 cancel_work_sync(&wlvif->rx_streaming_enable_work); 2476 cancel_work_sync(&wlvif->rx_streaming_enable_work);
2410 cancel_work_sync(&wlvif->rx_streaming_disable_work); 2477 cancel_work_sync(&wlvif->rx_streaming_disable_work);
2478 cancel_delayed_work_sync(&wlvif->connection_loss_work);
2411 2479
2412 mutex_lock(&wl->mutex); 2480 mutex_lock(&wl->mutex);
2413} 2481}
@@ -2675,6 +2743,7 @@ static int wlcore_unset_assoc(struct wl1271 *wl, struct wl12xx_vif *wlvif)
2675 2743
2676 wl12xx_cmd_stop_channel_switch(wl, wlvif); 2744 wl12xx_cmd_stop_channel_switch(wl, wlvif);
2677 ieee80211_chswitch_done(vif, false); 2745 ieee80211_chswitch_done(vif, false);
2746 cancel_delayed_work(&wlvif->channel_switch_work);
2678 } 2747 }
2679 2748
2680 /* invalidate keep-alive template */ 2749 /* invalidate keep-alive template */
@@ -3296,7 +3365,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw,
3296 3365
3297 wl->scan.state = WL1271_SCAN_STATE_IDLE; 3366 wl->scan.state = WL1271_SCAN_STATE_IDLE;
3298 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); 3367 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
3299 wl->scan_vif = NULL; 3368 wl->scan_wlvif = NULL;
3300 wl->scan.req = NULL; 3369 wl->scan.req = NULL;
3301 ieee80211_scan_completed(wl->hw, true); 3370 ieee80211_scan_completed(wl->hw, true);
3302 3371
@@ -4087,7 +4156,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
4087 * state changed 4156 * state changed
4088 */ 4157 */
4089 if (!is_ap && (changed & BSS_CHANGED_ASSOC)) 4158 if (!is_ap && (changed & BSS_CHANGED_ASSOC))
4090 cancel_delayed_work_sync(&wl->connection_loss_work); 4159 cancel_delayed_work_sync(&wlvif->connection_loss_work);
4091 4160
4092 if (is_ap && (changed & BSS_CHANGED_BEACON_ENABLED) && 4161 if (is_ap && (changed & BSS_CHANGED_BEACON_ENABLED) &&
4093 !bss_conf->enable_beacon) 4162 !bss_conf->enable_beacon)
@@ -4680,11 +4749,23 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
4680 4749
4681 /* TODO: change mac80211 to pass vif as param */ 4750 /* TODO: change mac80211 to pass vif as param */
4682 wl12xx_for_each_wlvif_sta(wl, wlvif) { 4751 wl12xx_for_each_wlvif_sta(wl, wlvif) {
4752 unsigned long delay_usec;
4753
4683 ret = wl->ops->channel_switch(wl, wlvif, ch_switch); 4754 ret = wl->ops->channel_switch(wl, wlvif, ch_switch);
4684 if (!ret) 4755 if (ret)
4685 set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags); 4756 goto out_sleep;
4757
4758 set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags);
4759
4760 /* indicate failure 5 seconds after channel switch time */
4761 delay_usec = ieee80211_tu_to_usec(wlvif->beacon_int) *
4762 ch_switch->count;
4763 ieee80211_queue_delayed_work(hw, &wlvif->channel_switch_work,
4764 usecs_to_jiffies(delay_usec) +
4765 msecs_to_jiffies(5000));
4686 } 4766 }
4687 4767
4768out_sleep:
4688 wl1271_ps_elp_sleep(wl); 4769 wl1271_ps_elp_sleep(wl);
4689 4770
4690out: 4771out:
@@ -5193,34 +5274,6 @@ static struct bin_attribute fwlog_attr = {
5193 .read = wl1271_sysfs_read_fwlog, 5274 .read = wl1271_sysfs_read_fwlog,
5194}; 5275};
5195 5276
5196static void wl1271_connection_loss_work(struct work_struct *work)
5197{
5198 struct delayed_work *dwork;
5199 struct wl1271 *wl;
5200 struct ieee80211_vif *vif;
5201 struct wl12xx_vif *wlvif;
5202
5203 dwork = container_of(work, struct delayed_work, work);
5204 wl = container_of(dwork, struct wl1271, connection_loss_work);
5205
5206 wl1271_info("Connection loss work.");
5207
5208 mutex_lock(&wl->mutex);
5209
5210 if (unlikely(wl->state != WLCORE_STATE_ON))
5211 goto out;
5212
5213 /* Call mac80211 connection loss */
5214 wl12xx_for_each_wlvif_sta(wl, wlvif) {
5215 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
5216 goto out;
5217 vif = wl12xx_wlvif_to_vif(wlvif);
5218 ieee80211_connection_loss(vif);
5219 }
5220out:
5221 mutex_unlock(&wl->mutex);
5222}
5223
5224static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic) 5277static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic)
5225{ 5278{
5226 int i; 5279 int i;
@@ -5478,7 +5531,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
5478 5531
5479#define WL1271_DEFAULT_CHANNEL 0 5532#define WL1271_DEFAULT_CHANNEL 0
5480 5533
5481struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size) 5534struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size,
5535 u32 mbox_size)
5482{ 5536{
5483 struct ieee80211_hw *hw; 5537 struct ieee80211_hw *hw;
5484 struct wl1271 *wl; 5538 struct wl1271 *wl;
@@ -5522,8 +5576,6 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size)
5522 INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); 5576 INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
5523 INIT_DELAYED_WORK(&wl->roc_complete_work, wlcore_roc_complete_work); 5577 INIT_DELAYED_WORK(&wl->roc_complete_work, wlcore_roc_complete_work);
5524 INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work); 5578 INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work);
5525 INIT_DELAYED_WORK(&wl->connection_loss_work,
5526 wl1271_connection_loss_work);
5527 5579
5528 wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); 5580 wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");
5529 if (!wl->freezable_wq) { 5581 if (!wl->freezable_wq) {
@@ -5586,7 +5638,8 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size)
5586 goto err_dummy_packet; 5638 goto err_dummy_packet;
5587 } 5639 }
5588 5640
5589 wl->mbox = kmalloc(sizeof(*wl->mbox), GFP_KERNEL | GFP_DMA); 5641 wl->mbox_size = mbox_size;
5642 wl->mbox = kmalloc(wl->mbox_size, GFP_KERNEL | GFP_DMA);
5590 if (!wl->mbox) { 5643 if (!wl->mbox) {
5591 ret = -ENOMEM; 5644 ret = -ENOMEM;
5592 goto err_fwlog; 5645 goto err_fwlog;
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c
index e7d0a02be5b0..eeb61889833f 100644
--- a/drivers/net/wireless/ti/wlcore/scan.c
+++ b/drivers/net/wireless/ti/wlcore/scan.c
@@ -35,7 +35,6 @@ void wl1271_scan_complete_work(struct work_struct *work)
35{ 35{
36 struct delayed_work *dwork; 36 struct delayed_work *dwork;
37 struct wl1271 *wl; 37 struct wl1271 *wl;
38 struct ieee80211_vif *vif;
39 struct wl12xx_vif *wlvif; 38 struct wl12xx_vif *wlvif;
40 int ret; 39 int ret;
41 40
@@ -52,8 +51,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
52 if (wl->scan.state == WL1271_SCAN_STATE_IDLE) 51 if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
53 goto out; 52 goto out;
54 53
55 vif = wl->scan_vif; 54 wlvif = wl->scan_wlvif;
56 wlvif = wl12xx_vif_to_data(vif);
57 55
58 /* 56 /*
59 * Rearm the tx watchdog just before idling scan. This 57 * Rearm the tx watchdog just before idling scan. This
@@ -64,7 +62,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
64 wl->scan.state = WL1271_SCAN_STATE_IDLE; 62 wl->scan.state = WL1271_SCAN_STATE_IDLE;
65 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); 63 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
66 wl->scan.req = NULL; 64 wl->scan.req = NULL;
67 wl->scan_vif = NULL; 65 wl->scan_wlvif = NULL;
68 66
69 ret = wl1271_ps_elp_wakeup(wl); 67 ret = wl1271_ps_elp_wakeup(wl);
70 if (ret < 0) 68 if (ret < 0)
@@ -295,7 +293,7 @@ int wlcore_scan(struct wl1271 *wl, struct ieee80211_vif *vif,
295 wl->scan.ssid_len = 0; 293 wl->scan.ssid_len = 0;
296 } 294 }
297 295
298 wl->scan_vif = vif; 296 wl->scan_wlvif = wlvif;
299 wl->scan.req = req; 297 wl->scan.req = req;
300 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); 298 memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
301 299
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 1ad49c9ea7a4..d47eb6c19b0a 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -51,6 +51,9 @@ struct wlcore_ops {
51 int (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, 51 int (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr,
52 void *buf, size_t len); 52 void *buf, size_t len);
53 int (*ack_event)(struct wl1271 *wl); 53 int (*ack_event)(struct wl1271 *wl);
54 int (*wait_for_event)(struct wl1271 *wl, enum wlcore_wait_event event,
55 bool *timeout);
56 int (*process_mailbox_events)(struct wl1271 *wl);
54 u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); 57 u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks);
55 void (*set_tx_desc_blocks)(struct wl1271 *wl, 58 void (*set_tx_desc_blocks)(struct wl1271 *wl,
56 struct wl1271_tx_hw_descr *desc, 59 struct wl1271_tx_hw_descr *desc,
@@ -85,7 +88,6 @@ struct wlcore_ops {
85 int (*scan_start)(struct wl1271 *wl, struct wl12xx_vif *wlvif, 88 int (*scan_start)(struct wl1271 *wl, struct wl12xx_vif *wlvif,
86 struct cfg80211_scan_request *req); 89 struct cfg80211_scan_request *req);
87 int (*scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif); 90 int (*scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
88 void (*scan_completed)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
89 int (*sched_scan_start)(struct wl1271 *wl, struct wl12xx_vif *wlvif, 91 int (*sched_scan_start)(struct wl1271 *wl, struct wl12xx_vif *wlvif,
90 struct cfg80211_sched_scan_request *req, 92 struct cfg80211_sched_scan_request *req,
91 struct ieee80211_sched_scan_ies *ies); 93 struct ieee80211_sched_scan_ies *ies);
@@ -281,22 +283,20 @@ struct wl1271 {
281 bool watchdog_recovery; 283 bool watchdog_recovery;
282 284
283 /* Pointer that holds DMA-friendly block for the mailbox */ 285 /* Pointer that holds DMA-friendly block for the mailbox */
284 struct event_mailbox *mbox; 286 void *mbox;
285 287
286 /* The mbox event mask */ 288 /* The mbox event mask */
287 u32 event_mask; 289 u32 event_mask;
288 290
289 /* Mailbox pointers */ 291 /* Mailbox pointers */
292 u32 mbox_size;
290 u32 mbox_ptr[2]; 293 u32 mbox_ptr[2];
291 294
292 /* Are we currently scanning */ 295 /* Are we currently scanning */
293 struct ieee80211_vif *scan_vif; 296 struct wl12xx_vif *scan_wlvif;
294 struct wl1271_scan scan; 297 struct wl1271_scan scan;
295 struct delayed_work scan_complete_work; 298 struct delayed_work scan_complete_work;
296 299
297 /* Connection loss work */
298 struct delayed_work connection_loss_work;
299
300 struct ieee80211_vif *roc_vif; 300 struct ieee80211_vif *roc_vif;
301 struct delayed_work roc_complete_work; 301 struct delayed_work roc_complete_work;
302 302
@@ -436,7 +436,8 @@ struct wl1271 {
436 436
437int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); 437int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
438int __devexit wlcore_remove(struct platform_device *pdev); 438int __devexit wlcore_remove(struct platform_device *pdev);
439struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size); 439struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size,
440 u32 mbox_size);
440int wlcore_free_hw(struct wl1271 *wl); 441int wlcore_free_hw(struct wl1271 *wl);
441int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, 442int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
442 struct ieee80211_vif *vif, 443 struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 6678d4b18611..bc3b5f4d1b44 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -421,6 +421,9 @@ struct wl12xx_vif {
421 struct work_struct rx_streaming_disable_work; 421 struct work_struct rx_streaming_disable_work;
422 struct timer_list rx_streaming_timer; 422 struct timer_list rx_streaming_timer;
423 423
424 struct delayed_work channel_switch_work;
425 struct delayed_work connection_loss_work;
426
424 /* 427 /*
425 * This struct must be last! 428 * This struct must be last!
426 * data that has to be saved acrossed reconfigs (e.g. recovery) 429 * data that has to be saved acrossed reconfigs (e.g. recovery)