Commit | Line | Data |
---|---|---|
2f01a1f5 | 1 | /* |
80301cdc | 2 | * This file is part of wl1251 |
2f01a1f5 KV |
3 | * |
4 | * Copyright (c) 1998-2007 Texas Instruments Incorporated | |
5 | * Copyright (C) 2008 Nokia Corporation | |
6 | * | |
2f01a1f5 KV |
7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License | |
9 | * version 2 as published by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | |
19 | * 02110-1301 USA | |
20 | * | |
21 | */ | |
22 | ||
13674118 | 23 | #include "wl1251.h" |
9bc6772e KV |
24 | #include "reg.h" |
25 | #include "io.h" | |
26 | #include "event.h" | |
27 | #include "ps.h" | |
2f01a1f5 | 28 | |
80301cdc | 29 | static int wl1251_event_scan_complete(struct wl1251 *wl, |
2f01a1f5 KV |
30 | struct event_mailbox *mbox) |
31 | { | |
80301cdc | 32 | wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d", |
2f01a1f5 KV |
33 | mbox->scheduled_scan_status, |
34 | mbox->scheduled_scan_channels); | |
35 | ||
36 | if (wl->scanning) { | |
2f01a1f5 | 37 | ieee80211_scan_completed(wl->hw, false); |
2789da9e | 38 | wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed"); |
2f01a1f5 KV |
39 | wl->scanning = false; |
40 | } | |
41 | ||
42 | return 0; | |
43 | } | |
44 | ||
80301cdc | 45 | static void wl1251_event_mbox_dump(struct event_mailbox *mbox) |
2f01a1f5 | 46 | { |
80301cdc KV |
47 | wl1251_debug(DEBUG_EVENT, "MBOX DUMP:"); |
48 | wl1251_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector); | |
49 | wl1251_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask); | |
2f01a1f5 KV |
50 | } |
51 | ||
80301cdc | 52 | static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) |
2f01a1f5 KV |
53 | { |
54 | int ret; | |
55 | u32 vector; | |
56 | ||
80301cdc | 57 | wl1251_event_mbox_dump(mbox); |
2f01a1f5 KV |
58 | |
59 | vector = mbox->events_vector & ~(mbox->events_mask); | |
80301cdc | 60 | wl1251_debug(DEBUG_EVENT, "vector: 0x%x", vector); |
2f01a1f5 KV |
61 | |
62 | if (vector & SCAN_COMPLETE_EVENT_ID) { | |
80301cdc | 63 | ret = wl1251_event_scan_complete(wl, mbox); |
2f01a1f5 KV |
64 | if (ret < 0) |
65 | return ret; | |
66 | } | |
67 | ||
68 | if (vector & BSS_LOSE_EVENT_ID) { | |
80301cdc | 69 | wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); |
2f01a1f5 | 70 | |
a0bbb58b JN |
71 | if (wl->psm_requested && |
72 | wl->station_mode != STATION_ACTIVE_MODE) { | |
80301cdc | 73 | ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); |
2f01a1f5 KV |
74 | if (ret < 0) |
75 | return ret; | |
76 | } | |
77 | } | |
78 | ||
0d776fcd | 79 | if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) { |
287f6f96 JO |
80 | wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); |
81 | ||
82 | /* indicate to the stack, that beacons have been lost */ | |
83 | ieee80211_beacon_loss(wl->vif); | |
84 | } | |
85 | ||
33d51fac VG |
86 | if (vector & REGAINED_BSS_EVENT_ID) { |
87 | if (wl->psm_requested) { | |
88 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | |
89 | if (ret < 0) | |
90 | return ret; | |
91 | } | |
92 | } | |
93 | ||
8964e492 DG |
94 | if (wl->vif && wl->rssi_thold) { |
95 | if (vector & ROAMING_TRIGGER_LOW_RSSI_EVENT_ID) { | |
96 | wl1251_debug(DEBUG_EVENT, | |
97 | "ROAMING_TRIGGER_LOW_RSSI_EVENT"); | |
98 | ieee80211_cqm_rssi_notify(wl->vif, | |
99 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, | |
100 | GFP_KERNEL); | |
101 | } | |
102 | ||
103 | if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID) { | |
104 | wl1251_debug(DEBUG_EVENT, | |
105 | "ROAMING_TRIGGER_REGAINED_RSSI_EVENT"); | |
106 | ieee80211_cqm_rssi_notify(wl->vif, | |
107 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, | |
108 | GFP_KERNEL); | |
109 | } | |
110 | } | |
111 | ||
2f01a1f5 KV |
112 | return 0; |
113 | } | |
114 | ||
7273b970 GI |
115 | /* |
116 | * Poll the mailbox event field until any of the bits in the mask is set or a | |
117 | * timeout occurs (WL1251_EVENT_TIMEOUT in msecs) | |
118 | */ | |
119 | int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms) | |
120 | { | |
121 | u32 events_vector, event; | |
122 | unsigned long timeout; | |
123 | ||
124 | timeout = jiffies + msecs_to_jiffies(timeout_ms); | |
125 | ||
126 | do { | |
127 | if (time_after(jiffies, timeout)) | |
128 | return -ETIMEDOUT; | |
129 | ||
130 | msleep(1); | |
131 | ||
132 | /* read from both event fields */ | |
133 | wl1251_mem_read(wl, wl->mbox_ptr[0], &events_vector, | |
134 | sizeof(events_vector)); | |
135 | event = events_vector & mask; | |
136 | wl1251_mem_read(wl, wl->mbox_ptr[1], &events_vector, | |
137 | sizeof(events_vector)); | |
138 | event |= events_vector & mask; | |
139 | } while (!event); | |
140 | ||
141 | return 0; | |
142 | } | |
143 | ||
80301cdc | 144 | int wl1251_event_unmask(struct wl1251 *wl) |
2f01a1f5 KV |
145 | { |
146 | int ret; | |
147 | ||
80301cdc | 148 | ret = wl1251_acx_event_mbox_mask(wl, ~(wl->event_mask)); |
2f01a1f5 KV |
149 | if (ret < 0) |
150 | return ret; | |
151 | ||
152 | return 0; | |
153 | } | |
154 | ||
80301cdc | 155 | void wl1251_event_mbox_config(struct wl1251 *wl) |
2f01a1f5 | 156 | { |
80301cdc | 157 | wl->mbox_ptr[0] = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR); |
2f01a1f5 KV |
158 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); |
159 | ||
80301cdc | 160 | wl1251_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", |
2f01a1f5 KV |
161 | wl->mbox_ptr[0], wl->mbox_ptr[1]); |
162 | } | |
163 | ||
80301cdc | 164 | int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num) |
2f01a1f5 KV |
165 | { |
166 | struct event_mailbox mbox; | |
167 | int ret; | |
168 | ||
80301cdc | 169 | wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num); |
2f01a1f5 KV |
170 | |
171 | if (mbox_num > 1) | |
172 | return -EINVAL; | |
173 | ||
174 | /* first we read the mbox descriptor */ | |
0764de64 | 175 | wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox, |
2f01a1f5 KV |
176 | sizeof(struct event_mailbox)); |
177 | ||
178 | /* process the descriptor */ | |
80301cdc | 179 | ret = wl1251_event_process(wl, &mbox); |
2f01a1f5 KV |
180 | if (ret < 0) |
181 | return ret; | |
182 | ||
183 | /* then we let the firmware know it can go on...*/ | |
80301cdc | 184 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); |
2f01a1f5 KV |
185 | |
186 | return 0; | |
187 | } |