aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/wl1251_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1251_main.c')
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_main.c141
1 files changed, 119 insertions, 22 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 4c1aad33fb51..8c88fe279ec6 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -32,7 +32,6 @@
32#include "wl1251.h" 32#include "wl1251.h"
33#include "wl12xx_80211.h" 33#include "wl12xx_80211.h"
34#include "reg.h" 34#include "reg.h"
35#include "wl1251_ops.h"
36#include "wl1251_io.h" 35#include "wl1251_io.h"
37#include "wl1251_cmd.h" 36#include "wl1251_cmd.h"
38#include "wl1251_event.h" 37#include "wl1251_event.h"
@@ -41,6 +40,7 @@
41#include "wl1251_ps.h" 40#include "wl1251_ps.h"
42#include "wl1251_init.h" 41#include "wl1251_init.h"
43#include "wl1251_debugfs.h" 42#include "wl1251_debugfs.h"
43#include "wl1251_boot.h"
44 44
45void wl1251_enable_interrupts(struct wl1251 *wl) 45void wl1251_enable_interrupts(struct wl1251 *wl)
46{ 46{
@@ -68,7 +68,7 @@ static int wl1251_fetch_firmware(struct wl1251 *wl)
68 struct device *dev = wiphy_dev(wl->hw->wiphy); 68 struct device *dev = wiphy_dev(wl->hw->wiphy);
69 int ret; 69 int ret;
70 70
71 ret = request_firmware(&fw, wl->chip.fw_filename, dev); 71 ret = request_firmware(&fw, WL1251_FW_NAME, dev);
72 72
73 if (ret < 0) { 73 if (ret < 0) {
74 wl1251_error("could not get firmware: %d", ret); 74 wl1251_error("could not get firmware: %d", ret);
@@ -107,7 +107,7 @@ static int wl1251_fetch_nvs(struct wl1251 *wl)
107 struct device *dev = wiphy_dev(wl->hw->wiphy); 107 struct device *dev = wiphy_dev(wl->hw->wiphy);
108 int ret; 108 int ret;
109 109
110 ret = request_firmware(&fw, wl->chip.nvs_filename, dev); 110 ret = request_firmware(&fw, WL1251_NVS_NAME, dev);
111 111
112 if (ret < 0) { 112 if (ret < 0) {
113 wl1251_error("could not get nvs file: %d", ret); 113 wl1251_error("could not get nvs file: %d", ret);
@@ -157,7 +157,7 @@ static int wl1251_chip_wakeup(struct wl1251 *wl)
157 int ret = 0; 157 int ret = 0;
158 158
159 wl1251_power_on(wl); 159 wl1251_power_on(wl);
160 msleep(wl->chip.power_on_sleep); 160 msleep(WL1251_POWER_ON_SLEEP);
161 wl->if_ops->reset(wl); 161 wl->if_ops->reset(wl);
162 162
163 /* We don't need a real memory partition here, because we only want 163 /* We don't need a real memory partition here, because we only want
@@ -174,22 +174,19 @@ static int wl1251_chip_wakeup(struct wl1251 *wl)
174 /* whal_FwCtrl_BootSm() */ 174 /* whal_FwCtrl_BootSm() */
175 175
176 /* 0. read chip id from CHIP_ID */ 176 /* 0. read chip id from CHIP_ID */
177 wl->chip.id = wl1251_reg_read32(wl, CHIP_ID_B); 177 wl->chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
178 178
179 /* 1. check if chip id is valid */ 179 /* 1. check if chip id is valid */
180 180
181 switch (wl->chip.id) { 181 switch (wl->chip_id) {
182 case CHIP_ID_1251_PG12: 182 case CHIP_ID_1251_PG12:
183 wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)", 183 wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)",
184 wl->chip.id); 184 wl->chip_id);
185
186 wl1251_setup(wl);
187
188 break; 185 break;
189 case CHIP_ID_1251_PG10: 186 case CHIP_ID_1251_PG10:
190 case CHIP_ID_1251_PG11: 187 case CHIP_ID_1251_PG11:
191 default: 188 default:
192 wl1251_error("unsupported chip id: 0x%x", wl->chip.id); 189 wl1251_error("unsupported chip id: 0x%x", wl->chip_id);
193 ret = -ENODEV; 190 ret = -ENODEV;
194 goto out; 191 goto out;
195 } 192 }
@@ -211,6 +208,107 @@ out:
211 return ret; 208 return ret;
212} 209}
213 210
211static void wl1251_irq_work(struct work_struct *work)
212{
213 u32 intr;
214 struct wl1251 *wl =
215 container_of(work, struct wl1251, irq_work);
216 int ret;
217
218 mutex_lock(&wl->mutex);
219
220 wl1251_debug(DEBUG_IRQ, "IRQ work");
221
222 if (wl->state == WL1251_STATE_OFF)
223 goto out;
224
225 ret = wl1251_ps_elp_wakeup(wl);
226 if (ret < 0)
227 goto out;
228
229 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL);
230
231 intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
232 wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr);
233
234 if (wl->data_path) {
235 wl->rx_counter =
236 wl1251_mem_read32(wl, wl->data_path->rx_control_addr);
237
238 /* We handle a frmware bug here */
239 switch ((wl->rx_counter - wl->rx_handled) & 0xf) {
240 case 0:
241 wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync");
242 intr &= ~WL1251_ACX_INTR_RX0_DATA;
243 intr &= ~WL1251_ACX_INTR_RX1_DATA;
244 break;
245 case 1:
246 wl1251_debug(DEBUG_IRQ, "RX: FW +1");
247 intr |= WL1251_ACX_INTR_RX0_DATA;
248 intr &= ~WL1251_ACX_INTR_RX1_DATA;
249 break;
250 case 2:
251 wl1251_debug(DEBUG_IRQ, "RX: FW +2");
252 intr |= WL1251_ACX_INTR_RX0_DATA;
253 intr |= WL1251_ACX_INTR_RX1_DATA;
254 break;
255 default:
256 wl1251_warning("RX: FW and host out of sync: %d",
257 wl->rx_counter - wl->rx_handled);
258 break;
259 }
260
261 wl->rx_handled = wl->rx_counter;
262
263
264 wl1251_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter);
265 }
266
267 intr &= wl->intr_mask;
268
269 if (intr == 0) {
270 wl1251_debug(DEBUG_IRQ, "INTR is 0");
271 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
272 ~(wl->intr_mask));
273
274 goto out_sleep;
275 }
276
277 if (intr & WL1251_ACX_INTR_RX0_DATA) {
278 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA");
279 wl1251_rx(wl);
280 }
281
282 if (intr & WL1251_ACX_INTR_RX1_DATA) {
283 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA");
284 wl1251_rx(wl);
285 }
286
287 if (intr & WL1251_ACX_INTR_TX_RESULT) {
288 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT");
289 wl1251_tx_complete(wl);
290 }
291
292 if (intr & (WL1251_ACX_INTR_EVENT_A | WL1251_ACX_INTR_EVENT_B)) {
293 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", intr);
294 if (intr & WL1251_ACX_INTR_EVENT_A)
295 wl1251_event_handle(wl, 0);
296 else
297 wl1251_event_handle(wl, 1);
298 }
299
300 if (intr & WL1251_ACX_INTR_INIT_COMPLETE)
301 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE");
302
303 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
304
305out_sleep:
306 wl1251_ps_elp_sleep(wl);
307
308out:
309 mutex_unlock(&wl->mutex);
310}
311
214static void wl1251_filter_work(struct work_struct *work) 312static void wl1251_filter_work(struct work_struct *work)
215{ 313{
216 struct wl1251 *wl = 314 struct wl1251 *wl =
@@ -227,7 +325,7 @@ static void wl1251_filter_work(struct work_struct *work)
227 goto out; 325 goto out;
228 326
229 /* FIXME: replace the magic numbers with proper definitions */ 327 /* FIXME: replace the magic numbers with proper definitions */
230 ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0); 328 ret = wl1251_cmd_join(wl, wl->bss_type, 1, 100, 0);
231 if (ret < 0) 329 if (ret < 0)
232 goto out_sleep; 330 goto out_sleep;
233 331
@@ -289,11 +387,11 @@ static int wl1251_op_start(struct ieee80211_hw *hw)
289 if (ret < 0) 387 if (ret < 0)
290 goto out; 388 goto out;
291 389
292 ret = wl->chip.op_boot(wl); 390 ret = wl1251_boot(wl);
293 if (ret < 0) 391 if (ret < 0)
294 goto out; 392 goto out;
295 393
296 ret = wl->chip.op_hw_init(wl); 394 ret = wl1251_hw_init(wl);
297 if (ret < 0) 395 if (ret < 0)
298 goto out; 396 goto out;
299 397
@@ -303,7 +401,7 @@ static int wl1251_op_start(struct ieee80211_hw *hw)
303 401
304 wl->state = WL1251_STATE_ON; 402 wl->state = WL1251_STATE_ON;
305 403
306 wl1251_info("firmware booted (%s)", wl->chip.fw_ver); 404 wl1251_info("firmware booted (%s)", wl->fw_ver);
307 405
308out: 406out:
309 if (ret < 0) 407 if (ret < 0)
@@ -346,7 +444,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
346 mutex_lock(&wl->mutex); 444 mutex_lock(&wl->mutex);
347 445
348 /* let's notify MAC80211 about the remaining pending TX frames */ 446 /* let's notify MAC80211 about the remaining pending TX frames */
349 wl->chip.op_tx_flush(wl); 447 wl1251_tx_flush(wl);
350 wl1251_power_off(wl); 448 wl1251_power_off(wl);
351 449
352 memset(wl->bssid, 0, ETH_ALEN); 450 memset(wl->bssid, 0, ETH_ALEN);
@@ -467,7 +565,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
467 565
468 if (channel != wl->channel) { 566 if (channel != wl->channel) {
469 /* FIXME: use beacon interval provided by mac80211 */ 567 /* FIXME: use beacon interval provided by mac80211 */
470 ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0); 568 ret = wl1251_cmd_join(wl, wl->bss_type, 1, 100, 0);
471 if (ret < 0) 569 if (ret < 0)
472 goto out_sleep; 570 goto out_sleep;
473 571
@@ -1041,7 +1139,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
1041 if (ret < 0) 1139 if (ret < 0)
1042 goto out; 1140 goto out;
1043 1141
1044 ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0); 1142 ret = wl1251_cmd_join(wl, wl->bss_type, 1, 100, 0);
1045 1143
1046 if (ret < 0) 1144 if (ret < 0)
1047 goto out; 1145 goto out;
@@ -1232,15 +1330,14 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
1232 wl->tx_queue_stopped = false; 1330 wl->tx_queue_stopped = false;
1233 wl->power_level = WL1251_DEFAULT_POWER_LEVEL; 1331 wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
1234 1332
1235 /* We use the default power on sleep time until we know which chip
1236 * we're using */
1237 wl->chip.power_on_sleep = WL1251_DEFAULT_POWER_ON_SLEEP;
1238
1239 for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) 1333 for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
1240 wl->tx_frames[i] = NULL; 1334 wl->tx_frames[i] = NULL;
1241 1335
1242 wl->next_tx_complete = 0; 1336 wl->next_tx_complete = 0;
1243 1337
1338 INIT_WORK(&wl->irq_work, wl1251_irq_work);
1339 INIT_WORK(&wl->tx_work, wl1251_tx_work);
1340
1244 /* 1341 /*
1245 * In case our MAC address is not correctly set, 1342 * In case our MAC address is not correctly set,
1246 * we use a random but Nokia MAC. 1343 * we use a random but Nokia MAC.