diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 823 |
1 files changed, 539 insertions, 284 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b62c00ff42f..2a864b24291 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Nokia Corporation | 4 | * Copyright (C) 2008-2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
7 | * | 7 | * |
@@ -38,6 +38,7 @@ | |||
38 | #include "wl12xx_80211.h" | 38 | #include "wl12xx_80211.h" |
39 | #include "wl1271_reg.h" | 39 | #include "wl1271_reg.h" |
40 | #include "wl1271_spi.h" | 40 | #include "wl1271_spi.h" |
41 | #include "wl1271_io.h" | ||
41 | #include "wl1271_event.h" | 42 | #include "wl1271_event.h" |
42 | #include "wl1271_tx.h" | 43 | #include "wl1271_tx.h" |
43 | #include "wl1271_rx.h" | 44 | #include "wl1271_rx.h" |
@@ -46,6 +47,9 @@ | |||
46 | #include "wl1271_debugfs.h" | 47 | #include "wl1271_debugfs.h" |
47 | #include "wl1271_cmd.h" | 48 | #include "wl1271_cmd.h" |
48 | #include "wl1271_boot.h" | 49 | #include "wl1271_boot.h" |
50 | #include "wl1271_testmode.h" | ||
51 | |||
52 | #define WL1271_BOOT_RETRIES 3 | ||
49 | 53 | ||
50 | static struct conf_drv_settings default_conf = { | 54 | static struct conf_drv_settings default_conf = { |
51 | .sg = { | 55 | .sg = { |
@@ -67,16 +71,17 @@ static struct conf_drv_settings default_conf = { | |||
67 | .ps_poll_timeout = 15, | 71 | .ps_poll_timeout = 15, |
68 | .upsd_timeout = 15, | 72 | .upsd_timeout = 15, |
69 | .rts_threshold = 2347, | 73 | .rts_threshold = 2347, |
70 | .rx_cca_threshold = 0xFFEF, | 74 | .rx_cca_threshold = 0, |
71 | .irq_blk_threshold = 0, | 75 | .irq_blk_threshold = 0xFFFF, |
72 | .irq_pkt_threshold = USHORT_MAX, | 76 | .irq_pkt_threshold = 0, |
73 | .irq_timeout = 5, | 77 | .irq_timeout = 600, |
74 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, | 78 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, |
75 | }, | 79 | }, |
76 | .tx = { | 80 | .tx = { |
77 | .tx_energy_detection = 0, | 81 | .tx_energy_detection = 0, |
78 | .rc_conf = { | 82 | .rc_conf = { |
79 | .enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED, | 83 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS | |
84 | CONF_HW_BIT_RATE_2MBPS, | ||
80 | .short_retry_limit = 10, | 85 | .short_retry_limit = 10, |
81 | .long_retry_limit = 10, | 86 | .long_retry_limit = 10, |
82 | .aflags = 0 | 87 | .aflags = 0 |
@@ -172,8 +177,8 @@ static struct conf_drv_settings default_conf = { | |||
172 | } | 177 | } |
173 | }, | 178 | }, |
174 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 179 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
175 | .tx_compl_timeout = 5, | 180 | .tx_compl_timeout = 700, |
176 | .tx_compl_threshold = 5 | 181 | .tx_compl_threshold = 4 |
177 | }, | 182 | }, |
178 | .conn = { | 183 | .conn = { |
179 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 184 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
@@ -186,12 +191,12 @@ static struct conf_drv_settings default_conf = { | |||
186 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | 191 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, |
187 | } | 192 | } |
188 | }, | 193 | }, |
189 | .synch_fail_thold = 5, | 194 | .synch_fail_thold = 10, |
190 | .bss_lose_timeout = 100, | 195 | .bss_lose_timeout = 100, |
191 | .beacon_rx_timeout = 10000, | 196 | .beacon_rx_timeout = 10000, |
192 | .broadcast_timeout = 20000, | 197 | .broadcast_timeout = 20000, |
193 | .rx_broadcast_in_ps = 1, | 198 | .rx_broadcast_in_ps = 1, |
194 | .ps_poll_threshold = 4, | 199 | .ps_poll_threshold = 20, |
195 | .sig_trigger_count = 2, | 200 | .sig_trigger_count = 2, |
196 | .sig_trigger = { | 201 | .sig_trigger = { |
197 | [0] = { | 202 | [0] = { |
@@ -226,97 +231,17 @@ static struct conf_drv_settings default_conf = { | |||
226 | .psm_entry_retries = 3 | 231 | .psm_entry_retries = 3 |
227 | }, | 232 | }, |
228 | .init = { | 233 | .init = { |
229 | .sr_err_tbl = { | ||
230 | [0] = { | ||
231 | .len = 7, | ||
232 | .upper_limit = 0x03, | ||
233 | .values = { | ||
234 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
235 | 0x00 } | ||
236 | }, | ||
237 | [1] = { | ||
238 | .len = 7, | ||
239 | .upper_limit = 0x03, | ||
240 | .values = { | ||
241 | 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8, | ||
242 | 0x00 } | ||
243 | }, | ||
244 | [2] = { | ||
245 | .len = 7, | ||
246 | .upper_limit = 0x03, | ||
247 | .values = { | ||
248 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
249 | 0x00 } | ||
250 | } | ||
251 | }, | ||
252 | .sr_enable = 1, | ||
253 | .genparam = { | ||
254 | .ref_clk = CONF_REF_CLK_38_4_E, | ||
255 | .settling_time = 5, | ||
256 | .clk_valid_on_wakeup = 0, | ||
257 | .dc2dcmode = 0, | ||
258 | .single_dual_band = CONF_SINGLE_BAND, | ||
259 | .tx_bip_fem_autodetect = 0, | ||
260 | .tx_bip_fem_manufacturer = 1, | ||
261 | .settings = 1, | ||
262 | }, | ||
263 | .radioparam = { | 234 | .radioparam = { |
264 | .rx_trace_loss = 10, | 235 | .fem = 1, |
265 | .tx_trace_loss = 10, | ||
266 | .rx_rssi_and_proc_compens = { | ||
267 | 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, | ||
268 | 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8, | ||
269 | 0x00, 0x0a, 0x14 }, | ||
270 | .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | ||
271 | .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | ||
272 | .rx_rssi_and_proc_compens_5 = { | ||
273 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
274 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
275 | 0x00, 0x00, 0x00 }, | ||
276 | .tx_ref_pd_voltage = 0x24e, | ||
277 | .tx_ref_power = 0x78, | ||
278 | .tx_offset_db = 0x0, | ||
279 | .tx_rate_limits_normal = { | ||
280 | 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 }, | ||
281 | .tx_rate_limits_degraded = { | ||
282 | 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, | ||
283 | .tx_channel_limits_11b = { | ||
284 | 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
285 | 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, | ||
286 | 0x22, 0x50 }, | ||
287 | .tx_channel_limits_ofdm = { | ||
288 | 0x20, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
289 | 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, | ||
290 | 0x20, 0x50 }, | ||
291 | .tx_pdv_rate_offsets = { | ||
292 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, | ||
293 | .tx_ibias = { | ||
294 | 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 }, | ||
295 | .rx_fem_insertion_loss = 0x14, | ||
296 | .tx_ref_pd_voltage_5 = { | ||
297 | 0x0190, 0x01a4, 0x01c3, 0x01d8, | ||
298 | 0x020a, 0x021c }, | ||
299 | .tx_ref_power_5 = { | ||
300 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, | ||
301 | .tx_offset_db_5 = { | ||
302 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, | ||
303 | .tx_rate_limits_normal_5 = { | ||
304 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
305 | .tx_rate_limits_degraded_5 = { | ||
306 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
307 | .tx_channel_limits_ofdm_5 = { | ||
308 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
309 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
310 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
311 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
312 | 0x50, 0x50, 0x50 }, | ||
313 | .tx_pdv_rate_offsets_5 = { | ||
314 | 0x01, 0x02, 0x02, 0x02, 0x02, 0x00 }, | ||
315 | .tx_ibias_5 = { | ||
316 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, | ||
317 | .rx_fem_insertion_loss_5 = { | ||
318 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 } | ||
319 | } | 236 | } |
237 | }, | ||
238 | .itrim = { | ||
239 | .enable = false, | ||
240 | .timeout = 50000, | ||
241 | }, | ||
242 | .pm_config = { | ||
243 | .host_clk_settling_time = 5000, | ||
244 | .host_fast_wakeup_support = false | ||
320 | } | 245 | } |
321 | }; | 246 | }; |
322 | 247 | ||
@@ -337,15 +262,14 @@ static void wl1271_conf_init(struct wl1271 *wl) | |||
337 | 262 | ||
338 | /* apply driver default configuration */ | 263 | /* apply driver default configuration */ |
339 | memcpy(&wl->conf, &default_conf, sizeof(default_conf)); | 264 | memcpy(&wl->conf, &default_conf, sizeof(default_conf)); |
340 | |||
341 | if (wl1271_11a_enabled()) | ||
342 | wl->conf.init.genparam.single_dual_band = CONF_DUAL_BAND; | ||
343 | } | 265 | } |
344 | 266 | ||
345 | 267 | ||
346 | static int wl1271_plt_init(struct wl1271 *wl) | 268 | static int wl1271_plt_init(struct wl1271 *wl) |
347 | { | 269 | { |
348 | int ret; | 270 | struct conf_tx_ac_category *conf_ac; |
271 | struct conf_tx_tid *conf_tid; | ||
272 | int ret, i; | ||
349 | 273 | ||
350 | ret = wl1271_cmd_general_parms(wl); | 274 | ret = wl1271_cmd_general_parms(wl); |
351 | if (ret < 0) | 275 | if (ret < 0) |
@@ -355,15 +279,89 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
355 | if (ret < 0) | 279 | if (ret < 0) |
356 | return ret; | 280 | return ret; |
357 | 281 | ||
358 | ret = wl1271_acx_init_mem_config(wl); | 282 | ret = wl1271_init_templates_config(wl); |
359 | if (ret < 0) | 283 | if (ret < 0) |
360 | return ret; | 284 | return ret; |
361 | 285 | ||
362 | ret = wl1271_cmd_data_path(wl, wl->channel, 1); | 286 | ret = wl1271_acx_init_mem_config(wl); |
363 | if (ret < 0) | 287 | if (ret < 0) |
364 | return ret; | 288 | return ret; |
365 | 289 | ||
290 | /* PHY layer config */ | ||
291 | ret = wl1271_init_phy_config(wl); | ||
292 | if (ret < 0) | ||
293 | goto out_free_memmap; | ||
294 | |||
295 | ret = wl1271_acx_dco_itrim_params(wl); | ||
296 | if (ret < 0) | ||
297 | goto out_free_memmap; | ||
298 | |||
299 | /* Initialize connection monitoring thresholds */ | ||
300 | ret = wl1271_acx_conn_monit_params(wl); | ||
301 | if (ret < 0) | ||
302 | goto out_free_memmap; | ||
303 | |||
304 | /* Bluetooth WLAN coexistence */ | ||
305 | ret = wl1271_init_pta(wl); | ||
306 | if (ret < 0) | ||
307 | goto out_free_memmap; | ||
308 | |||
309 | /* Energy detection */ | ||
310 | ret = wl1271_init_energy_detection(wl); | ||
311 | if (ret < 0) | ||
312 | goto out_free_memmap; | ||
313 | |||
314 | /* Default fragmentation threshold */ | ||
315 | ret = wl1271_acx_frag_threshold(wl); | ||
316 | if (ret < 0) | ||
317 | goto out_free_memmap; | ||
318 | |||
319 | /* Default TID configuration */ | ||
320 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { | ||
321 | conf_tid = &wl->conf.tx.tid_conf[i]; | ||
322 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, | ||
323 | conf_tid->channel_type, | ||
324 | conf_tid->tsid, | ||
325 | conf_tid->ps_scheme, | ||
326 | conf_tid->ack_policy, | ||
327 | conf_tid->apsd_conf[0], | ||
328 | conf_tid->apsd_conf[1]); | ||
329 | if (ret < 0) | ||
330 | goto out_free_memmap; | ||
331 | } | ||
332 | |||
333 | /* Default AC configuration */ | ||
334 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
335 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
336 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
337 | conf_ac->cw_max, conf_ac->aifsn, | ||
338 | conf_ac->tx_op_limit); | ||
339 | if (ret < 0) | ||
340 | goto out_free_memmap; | ||
341 | } | ||
342 | |||
343 | /* Enable data path */ | ||
344 | ret = wl1271_cmd_data_path(wl, 1); | ||
345 | if (ret < 0) | ||
346 | goto out_free_memmap; | ||
347 | |||
348 | /* Configure for CAM power saving (ie. always active) */ | ||
349 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
350 | if (ret < 0) | ||
351 | goto out_free_memmap; | ||
352 | |||
353 | /* configure PM */ | ||
354 | ret = wl1271_acx_pm_config(wl); | ||
355 | if (ret < 0) | ||
356 | goto out_free_memmap; | ||
357 | |||
366 | return 0; | 358 | return 0; |
359 | |||
360 | out_free_memmap: | ||
361 | kfree(wl->target_mem_map); | ||
362 | wl->target_mem_map = NULL; | ||
363 | |||
364 | return ret; | ||
367 | } | 365 | } |
368 | 366 | ||
369 | static void wl1271_disable_interrupts(struct wl1271 *wl) | 367 | static void wl1271_disable_interrupts(struct wl1271 *wl) |
@@ -374,11 +372,13 @@ static void wl1271_disable_interrupts(struct wl1271 *wl) | |||
374 | static void wl1271_power_off(struct wl1271 *wl) | 372 | static void wl1271_power_off(struct wl1271 *wl) |
375 | { | 373 | { |
376 | wl->set_power(false); | 374 | wl->set_power(false); |
375 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
377 | } | 376 | } |
378 | 377 | ||
379 | static void wl1271_power_on(struct wl1271 *wl) | 378 | static void wl1271_power_on(struct wl1271 *wl) |
380 | { | 379 | { |
381 | wl->set_power(true); | 380 | wl->set_power(true); |
381 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
382 | } | 382 | } |
383 | 383 | ||
384 | static void wl1271_fw_status(struct wl1271 *wl, | 384 | static void wl1271_fw_status(struct wl1271 *wl, |
@@ -387,8 +387,7 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
387 | u32 total = 0; | 387 | u32 total = 0; |
388 | int i; | 388 | int i; |
389 | 389 | ||
390 | wl1271_spi_read(wl, FW_STATUS_ADDR, status, | 390 | wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); |
391 | sizeof(*status), false); | ||
392 | 391 | ||
393 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 392 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
394 | "drv_rx_counter = %d, tx_results_counter = %d)", | 393 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -435,7 +434,7 @@ static void wl1271_irq_work(struct work_struct *work) | |||
435 | if (ret < 0) | 434 | if (ret < 0) |
436 | goto out; | 435 | goto out; |
437 | 436 | ||
438 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 437 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
439 | 438 | ||
440 | wl1271_fw_status(wl, wl->fw_status); | 439 | wl1271_fw_status(wl, wl->fw_status); |
441 | intr = le32_to_cpu(wl->fw_status->intr); | 440 | intr = le32_to_cpu(wl->fw_status->intr); |
@@ -447,14 +446,13 @@ static void wl1271_irq_work(struct work_struct *work) | |||
447 | intr &= WL1271_INTR_MASK; | 446 | intr &= WL1271_INTR_MASK; |
448 | 447 | ||
449 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 448 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
450 | bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true; | ||
451 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 449 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
452 | wl1271_event_handle(wl, 0, do_ack); | 450 | wl1271_event_handle(wl, 0); |
453 | } | 451 | } |
454 | 452 | ||
455 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 453 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
456 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 454 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
457 | wl1271_event_handle(wl, 1, true); | 455 | wl1271_event_handle(wl, 1); |
458 | } | 456 | } |
459 | 457 | ||
460 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 458 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
@@ -478,8 +476,8 @@ static void wl1271_irq_work(struct work_struct *work) | |||
478 | } | 476 | } |
479 | 477 | ||
480 | out_sleep: | 478 | out_sleep: |
481 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, | 479 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
482 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 480 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); |
483 | wl1271_ps_elp_sleep(wl); | 481 | wl1271_ps_elp_sleep(wl); |
484 | 482 | ||
485 | out: | 483 | out: |
@@ -546,6 +544,40 @@ out: | |||
546 | return ret; | 544 | return ret; |
547 | } | 545 | } |
548 | 546 | ||
547 | static int wl1271_update_mac_addr(struct wl1271 *wl) | ||
548 | { | ||
549 | int ret = 0; | ||
550 | u8 *nvs_ptr = (u8 *)wl->nvs->nvs; | ||
551 | |||
552 | /* get mac address from the NVS */ | ||
553 | wl->mac_addr[0] = nvs_ptr[11]; | ||
554 | wl->mac_addr[1] = nvs_ptr[10]; | ||
555 | wl->mac_addr[2] = nvs_ptr[6]; | ||
556 | wl->mac_addr[3] = nvs_ptr[5]; | ||
557 | wl->mac_addr[4] = nvs_ptr[4]; | ||
558 | wl->mac_addr[5] = nvs_ptr[3]; | ||
559 | |||
560 | /* FIXME: if it is a zero-address, we should bail out. Now, instead, | ||
561 | we randomize an address */ | ||
562 | if (is_zero_ether_addr(wl->mac_addr)) { | ||
563 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
564 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
565 | get_random_bytes(wl->mac_addr + 3, 3); | ||
566 | |||
567 | /* update this address to the NVS */ | ||
568 | nvs_ptr[11] = wl->mac_addr[0]; | ||
569 | nvs_ptr[10] = wl->mac_addr[1]; | ||
570 | nvs_ptr[6] = wl->mac_addr[2]; | ||
571 | nvs_ptr[5] = wl->mac_addr[3]; | ||
572 | nvs_ptr[4] = wl->mac_addr[4]; | ||
573 | nvs_ptr[3] = wl->mac_addr[5]; | ||
574 | } | ||
575 | |||
576 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | ||
577 | |||
578 | return ret; | ||
579 | } | ||
580 | |||
549 | static int wl1271_fetch_nvs(struct wl1271 *wl) | 581 | static int wl1271_fetch_nvs(struct wl1271 *wl) |
550 | { | 582 | { |
551 | const struct firmware *fw; | 583 | const struct firmware *fw; |
@@ -558,15 +590,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
558 | return ret; | 590 | return ret; |
559 | } | 591 | } |
560 | 592 | ||
561 | if (fw->size % 4) { | 593 | if (fw->size != sizeof(struct wl1271_nvs_file)) { |
562 | wl1271_error("nvs size is not multiple of 32 bits: %zu", | 594 | wl1271_error("nvs size is not as expected: %zu != %zu", |
563 | fw->size); | 595 | fw->size, sizeof(struct wl1271_nvs_file)); |
564 | ret = -EILSEQ; | 596 | ret = -EILSEQ; |
565 | goto out; | 597 | goto out; |
566 | } | 598 | } |
567 | 599 | ||
568 | wl->nvs_len = fw->size; | 600 | wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); |
569 | wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL); | ||
570 | 601 | ||
571 | if (!wl->nvs) { | 602 | if (!wl->nvs) { |
572 | wl1271_error("could not allocate memory for the nvs file"); | 603 | wl1271_error("could not allocate memory for the nvs file"); |
@@ -574,9 +605,9 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
574 | goto out; | 605 | goto out; |
575 | } | 606 | } |
576 | 607 | ||
577 | memcpy(wl->nvs, fw->data, wl->nvs_len); | 608 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); |
578 | 609 | ||
579 | ret = 0; | 610 | ret = wl1271_update_mac_addr(wl); |
580 | 611 | ||
581 | out: | 612 | out: |
582 | release_firmware(fw); | 613 | release_firmware(fw); |
@@ -614,10 +645,11 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
614 | struct wl1271_partition_set partition; | 645 | struct wl1271_partition_set partition; |
615 | int ret = 0; | 646 | int ret = 0; |
616 | 647 | ||
648 | msleep(WL1271_PRE_POWER_ON_SLEEP); | ||
617 | wl1271_power_on(wl); | 649 | wl1271_power_on(wl); |
618 | msleep(WL1271_POWER_ON_SLEEP); | 650 | msleep(WL1271_POWER_ON_SLEEP); |
619 | wl1271_spi_reset(wl); | 651 | wl1271_io_reset(wl); |
620 | wl1271_spi_init(wl); | 652 | wl1271_io_init(wl); |
621 | 653 | ||
622 | /* We don't need a real memory partition here, because we only want | 654 | /* We don't need a real memory partition here, because we only want |
623 | * to use the registers at this point. */ | 655 | * to use the registers at this point. */ |
@@ -632,7 +664,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
632 | /* whal_FwCtrl_BootSm() */ | 664 | /* whal_FwCtrl_BootSm() */ |
633 | 665 | ||
634 | /* 0. read chip id from CHIP_ID */ | 666 | /* 0. read chip id from CHIP_ID */ |
635 | wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B); | 667 | wl->chip.id = wl1271_read32(wl, CHIP_ID_B); |
636 | 668 | ||
637 | /* 1. check if chip id is valid */ | 669 | /* 1. check if chip id is valid */ |
638 | 670 | ||
@@ -643,7 +675,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
643 | 675 | ||
644 | ret = wl1271_setup(wl); | 676 | ret = wl1271_setup(wl); |
645 | if (ret < 0) | 677 | if (ret < 0) |
646 | goto out_power_off; | 678 | goto out; |
647 | break; | 679 | break; |
648 | case CHIP_ID_1271_PG20: | 680 | case CHIP_ID_1271_PG20: |
649 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 681 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
@@ -651,38 +683,34 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
651 | 683 | ||
652 | ret = wl1271_setup(wl); | 684 | ret = wl1271_setup(wl); |
653 | if (ret < 0) | 685 | if (ret < 0) |
654 | goto out_power_off; | 686 | goto out; |
655 | break; | 687 | break; |
656 | default: | 688 | default: |
657 | wl1271_error("unsupported chip id: 0x%x", wl->chip.id); | 689 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); |
658 | ret = -ENODEV; | 690 | ret = -ENODEV; |
659 | goto out_power_off; | 691 | goto out; |
660 | } | 692 | } |
661 | 693 | ||
662 | if (wl->fw == NULL) { | 694 | if (wl->fw == NULL) { |
663 | ret = wl1271_fetch_firmware(wl); | 695 | ret = wl1271_fetch_firmware(wl); |
664 | if (ret < 0) | 696 | if (ret < 0) |
665 | goto out_power_off; | 697 | goto out; |
666 | } | 698 | } |
667 | 699 | ||
668 | /* No NVS from netlink, try to get it from the filesystem */ | 700 | /* No NVS from netlink, try to get it from the filesystem */ |
669 | if (wl->nvs == NULL) { | 701 | if (wl->nvs == NULL) { |
670 | ret = wl1271_fetch_nvs(wl); | 702 | ret = wl1271_fetch_nvs(wl); |
671 | if (ret < 0) | 703 | if (ret < 0) |
672 | goto out_power_off; | 704 | goto out; |
673 | } | 705 | } |
674 | 706 | ||
675 | goto out; | ||
676 | |||
677 | out_power_off: | ||
678 | wl1271_power_off(wl); | ||
679 | |||
680 | out: | 707 | out: |
681 | return ret; | 708 | return ret; |
682 | } | 709 | } |
683 | 710 | ||
684 | int wl1271_plt_start(struct wl1271 *wl) | 711 | int wl1271_plt_start(struct wl1271 *wl) |
685 | { | 712 | { |
713 | int retries = WL1271_BOOT_RETRIES; | ||
686 | int ret; | 714 | int ret; |
687 | 715 | ||
688 | mutex_lock(&wl->mutex); | 716 | mutex_lock(&wl->mutex); |
@@ -696,35 +724,43 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
696 | goto out; | 724 | goto out; |
697 | } | 725 | } |
698 | 726 | ||
699 | wl->state = WL1271_STATE_PLT; | 727 | while (retries) { |
700 | 728 | retries--; | |
701 | ret = wl1271_chip_wakeup(wl); | 729 | ret = wl1271_chip_wakeup(wl); |
702 | if (ret < 0) | 730 | if (ret < 0) |
703 | goto out; | 731 | goto power_off; |
704 | |||
705 | ret = wl1271_boot(wl); | ||
706 | if (ret < 0) | ||
707 | goto out_power_off; | ||
708 | |||
709 | wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); | ||
710 | |||
711 | ret = wl1271_plt_init(wl); | ||
712 | if (ret < 0) | ||
713 | goto out_irq_disable; | ||
714 | 732 | ||
715 | /* Make sure power saving is disabled */ | 733 | ret = wl1271_boot(wl); |
716 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | 734 | if (ret < 0) |
717 | if (ret < 0) | 735 | goto power_off; |
718 | goto out_irq_disable; | ||
719 | 736 | ||
720 | goto out; | 737 | ret = wl1271_plt_init(wl); |
738 | if (ret < 0) | ||
739 | goto irq_disable; | ||
721 | 740 | ||
722 | out_irq_disable: | 741 | wl->state = WL1271_STATE_PLT; |
723 | wl1271_disable_interrupts(wl); | 742 | wl1271_notice("firmware booted in PLT mode (%s)", |
743 | wl->chip.fw_ver); | ||
744 | goto out; | ||
724 | 745 | ||
725 | out_power_off: | 746 | irq_disable: |
726 | wl1271_power_off(wl); | 747 | wl1271_disable_interrupts(wl); |
748 | mutex_unlock(&wl->mutex); | ||
749 | /* Unlocking the mutex in the middle of handling is | ||
750 | inherently unsafe. In this case we deem it safe to do, | ||
751 | because we need to let any possibly pending IRQ out of | ||
752 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
753 | work function will not do anything.) Also, any other | ||
754 | possible concurrent operations will fail due to the | ||
755 | current state, hence the wl1271 struct should be safe. */ | ||
756 | cancel_work_sync(&wl->irq_work); | ||
757 | mutex_lock(&wl->mutex); | ||
758 | power_off: | ||
759 | wl1271_power_off(wl); | ||
760 | } | ||
727 | 761 | ||
762 | wl1271_error("firmware boot in PLT mode failed despite %d retries", | ||
763 | WL1271_BOOT_RETRIES); | ||
728 | out: | 764 | out: |
729 | mutex_unlock(&wl->mutex); | 765 | mutex_unlock(&wl->mutex); |
730 | 766 | ||
@@ -762,7 +798,20 @@ out: | |||
762 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 798 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
763 | { | 799 | { |
764 | struct wl1271 *wl = hw->priv; | 800 | struct wl1271 *wl = hw->priv; |
801 | struct ieee80211_conf *conf = &hw->conf; | ||
802 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
803 | struct ieee80211_sta *sta = txinfo->control.sta; | ||
804 | unsigned long flags; | ||
805 | |||
806 | /* peek into the rates configured in the STA entry */ | ||
807 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
808 | if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) { | ||
809 | wl->sta_rate_set = sta->supp_rates[conf->channel->band]; | ||
810 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); | ||
811 | } | ||
812 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
765 | 813 | ||
814 | /* queue the packet */ | ||
766 | skb_queue_tail(&wl->tx_queue, skb); | 815 | skb_queue_tail(&wl->tx_queue, skb); |
767 | 816 | ||
768 | /* | 817 | /* |
@@ -784,7 +833,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
784 | * protected. Maybe fix this by removing the stupid | 833 | * protected. Maybe fix this by removing the stupid |
785 | * variable altogether and checking the real queue state? | 834 | * variable altogether and checking the real queue state? |
786 | */ | 835 | */ |
787 | wl->tx_queue_stopped = true; | 836 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
788 | } | 837 | } |
789 | 838 | ||
790 | return NETDEV_TX_OK; | 839 | return NETDEV_TX_OK; |
@@ -880,6 +929,7 @@ static struct notifier_block wl1271_dev_notifier = { | |||
880 | static int wl1271_op_start(struct ieee80211_hw *hw) | 929 | static int wl1271_op_start(struct ieee80211_hw *hw) |
881 | { | 930 | { |
882 | struct wl1271 *wl = hw->priv; | 931 | struct wl1271 *wl = hw->priv; |
932 | int retries = WL1271_BOOT_RETRIES; | ||
883 | int ret = 0; | 933 | int ret = 0; |
884 | 934 | ||
885 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 935 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); |
@@ -893,30 +943,42 @@ static int wl1271_op_start(struct ieee80211_hw *hw) | |||
893 | goto out; | 943 | goto out; |
894 | } | 944 | } |
895 | 945 | ||
896 | ret = wl1271_chip_wakeup(wl); | 946 | while (retries) { |
897 | if (ret < 0) | 947 | retries--; |
898 | goto out; | 948 | ret = wl1271_chip_wakeup(wl); |
899 | 949 | if (ret < 0) | |
900 | ret = wl1271_boot(wl); | 950 | goto power_off; |
901 | if (ret < 0) | ||
902 | goto out_power_off; | ||
903 | |||
904 | ret = wl1271_hw_init(wl); | ||
905 | if (ret < 0) | ||
906 | goto out_irq_disable; | ||
907 | |||
908 | wl->state = WL1271_STATE_ON; | ||
909 | 951 | ||
910 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); | 952 | ret = wl1271_boot(wl); |
953 | if (ret < 0) | ||
954 | goto power_off; | ||
911 | 955 | ||
912 | goto out; | 956 | ret = wl1271_hw_init(wl); |
957 | if (ret < 0) | ||
958 | goto irq_disable; | ||
913 | 959 | ||
914 | out_irq_disable: | 960 | wl->state = WL1271_STATE_ON; |
915 | wl1271_disable_interrupts(wl); | 961 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); |
962 | goto out; | ||
916 | 963 | ||
917 | out_power_off: | 964 | irq_disable: |
918 | wl1271_power_off(wl); | 965 | wl1271_disable_interrupts(wl); |
966 | mutex_unlock(&wl->mutex); | ||
967 | /* Unlocking the mutex in the middle of handling is | ||
968 | inherently unsafe. In this case we deem it safe to do, | ||
969 | because we need to let any possibly pending IRQ out of | ||
970 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
971 | work function will not do anything.) Also, any other | ||
972 | possible concurrent operations will fail due to the | ||
973 | current state, hence the wl1271 struct should be safe. */ | ||
974 | cancel_work_sync(&wl->irq_work); | ||
975 | mutex_lock(&wl->mutex); | ||
976 | power_off: | ||
977 | wl1271_power_off(wl); | ||
978 | } | ||
919 | 979 | ||
980 | wl1271_error("firmware boot failed despite %d retries", | ||
981 | WL1271_BOOT_RETRIES); | ||
920 | out: | 982 | out: |
921 | mutex_unlock(&wl->mutex); | 983 | mutex_unlock(&wl->mutex); |
922 | 984 | ||
@@ -944,11 +1006,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
944 | 1006 | ||
945 | WARN_ON(wl->state != WL1271_STATE_ON); | 1007 | WARN_ON(wl->state != WL1271_STATE_ON); |
946 | 1008 | ||
947 | if (wl->scanning) { | 1009 | if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
948 | mutex_unlock(&wl->mutex); | 1010 | mutex_unlock(&wl->mutex); |
949 | ieee80211_scan_completed(wl->hw, true); | 1011 | ieee80211_scan_completed(wl->hw, true); |
950 | mutex_lock(&wl->mutex); | 1012 | mutex_lock(&wl->mutex); |
951 | wl->scanning = false; | ||
952 | } | 1013 | } |
953 | 1014 | ||
954 | wl->state = WL1271_STATE_OFF; | 1015 | wl->state = WL1271_STATE_OFF; |
@@ -973,10 +1034,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
973 | wl->band = IEEE80211_BAND_2GHZ; | 1034 | wl->band = IEEE80211_BAND_2GHZ; |
974 | 1035 | ||
975 | wl->rx_counter = 0; | 1036 | wl->rx_counter = 0; |
976 | wl->elp = false; | ||
977 | wl->psm = 0; | ||
978 | wl->psm_entry_retry = 0; | 1037 | wl->psm_entry_retry = 0; |
979 | wl->tx_queue_stopped = false; | ||
980 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1038 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
981 | wl->tx_blocks_available = 0; | 1039 | wl->tx_blocks_available = 0; |
982 | wl->tx_results_count = 0; | 1040 | wl->tx_results_count = 0; |
@@ -986,7 +1044,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
986 | wl->tx_security_seq_32 = 0; | 1044 | wl->tx_security_seq_32 = 0; |
987 | wl->time_offset = 0; | 1045 | wl->time_offset = 0; |
988 | wl->session_counter = 0; | 1046 | wl->session_counter = 0; |
989 | wl->joined = false; | 1047 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
1048 | wl->sta_rate_set = 0; | ||
1049 | wl->flags = 0; | ||
990 | 1050 | ||
991 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1051 | for (i = 0; i < NUM_TX_QUEUES; i++) |
992 | wl->tx_blocks_freed[i] = 0; | 1052 | wl->tx_blocks_freed[i] = 0; |
@@ -996,13 +1056,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
996 | } | 1056 | } |
997 | 1057 | ||
998 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 1058 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, |
999 | struct ieee80211_if_init_conf *conf) | 1059 | struct ieee80211_vif *vif) |
1000 | { | 1060 | { |
1001 | struct wl1271 *wl = hw->priv; | 1061 | struct wl1271 *wl = hw->priv; |
1002 | int ret = 0; | 1062 | int ret = 0; |
1003 | 1063 | ||
1004 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 1064 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
1005 | conf->type, conf->mac_addr); | 1065 | vif->type, vif->addr); |
1006 | 1066 | ||
1007 | mutex_lock(&wl->mutex); | 1067 | mutex_lock(&wl->mutex); |
1008 | if (wl->vif) { | 1068 | if (wl->vif) { |
@@ -1010,9 +1070,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1010 | goto out; | 1070 | goto out; |
1011 | } | 1071 | } |
1012 | 1072 | ||
1013 | wl->vif = conf->vif; | 1073 | wl->vif = vif; |
1014 | 1074 | ||
1015 | switch (conf->type) { | 1075 | switch (vif->type) { |
1016 | case NL80211_IFTYPE_STATION: | 1076 | case NL80211_IFTYPE_STATION: |
1017 | wl->bss_type = BSS_TYPE_STA_BSS; | 1077 | wl->bss_type = BSS_TYPE_STA_BSS; |
1018 | break; | 1078 | break; |
@@ -1032,7 +1092,7 @@ out: | |||
1032 | } | 1092 | } |
1033 | 1093 | ||
1034 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | 1094 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, |
1035 | struct ieee80211_if_init_conf *conf) | 1095 | struct ieee80211_vif *vif) |
1036 | { | 1096 | { |
1037 | struct wl1271 *wl = hw->priv; | 1097 | struct wl1271 *wl = hw->priv; |
1038 | 1098 | ||
@@ -1109,6 +1169,51 @@ out: | |||
1109 | } | 1169 | } |
1110 | #endif | 1170 | #endif |
1111 | 1171 | ||
1172 | static int wl1271_join_channel(struct wl1271 *wl, int channel) | ||
1173 | { | ||
1174 | int ret = 0; | ||
1175 | /* we need to use a dummy BSSID for now */ | ||
1176 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | ||
1177 | 0xad, 0xbe, 0xef }; | ||
1178 | |||
1179 | /* the dummy join is not required for ad-hoc */ | ||
1180 | if (wl->bss_type == BSS_TYPE_IBSS) | ||
1181 | goto out; | ||
1182 | |||
1183 | /* disable mac filter, so we hear everything */ | ||
1184 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1185 | |||
1186 | wl->channel = channel; | ||
1187 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | ||
1188 | |||
1189 | ret = wl1271_cmd_join(wl); | ||
1190 | if (ret < 0) | ||
1191 | goto out; | ||
1192 | |||
1193 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1194 | |||
1195 | out: | ||
1196 | return ret; | ||
1197 | } | ||
1198 | |||
1199 | static int wl1271_unjoin_channel(struct wl1271 *wl) | ||
1200 | { | ||
1201 | int ret; | ||
1202 | |||
1203 | /* to stop listening to a channel, we disconnect */ | ||
1204 | ret = wl1271_cmd_disconnect(wl); | ||
1205 | if (ret < 0) | ||
1206 | goto out; | ||
1207 | |||
1208 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1209 | wl->channel = 0; | ||
1210 | memset(wl->bssid, 0, ETH_ALEN); | ||
1211 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | ||
1212 | |||
1213 | out: | ||
1214 | return ret; | ||
1215 | } | ||
1216 | |||
1112 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1217 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1113 | { | 1218 | { |
1114 | struct wl1271 *wl = hw->priv; | 1219 | struct wl1271 *wl = hw->priv; |
@@ -1117,10 +1222,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1117 | 1222 | ||
1118 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | 1223 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); |
1119 | 1224 | ||
1120 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", | 1225 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s", |
1121 | channel, | 1226 | channel, |
1122 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | 1227 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", |
1123 | conf->power_level); | 1228 | conf->power_level, |
1229 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); | ||
1124 | 1230 | ||
1125 | mutex_lock(&wl->mutex); | 1231 | mutex_lock(&wl->mutex); |
1126 | 1232 | ||
@@ -1130,35 +1236,55 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1130 | if (ret < 0) | 1236 | if (ret < 0) |
1131 | goto out; | 1237 | goto out; |
1132 | 1238 | ||
1133 | if (channel != wl->channel) { | 1239 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1134 | /* | 1240 | if (conf->flags & IEEE80211_CONF_IDLE && |
1135 | * We assume that the stack will configure the right channel | 1241 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
1136 | * before associating, so we don't need to send a join | 1242 | wl1271_unjoin_channel(wl); |
1137 | * command here. We will join the right channel when the | 1243 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) |
1138 | * BSSID changes | 1244 | wl1271_join_channel(wl, channel); |
1139 | */ | 1245 | |
1140 | wl->channel = channel; | 1246 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1247 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1248 | wl->sta_rate_set = 0; | ||
1249 | wl1271_acx_rate_policies(wl); | ||
1250 | } | ||
1141 | } | 1251 | } |
1142 | 1252 | ||
1143 | if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { | 1253 | /* if the channel changes while joined, join again */ |
1144 | wl1271_info("psm enabled"); | 1254 | if (channel != wl->channel && |
1255 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1256 | wl->channel = channel; | ||
1257 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ | ||
1258 | ret = wl1271_cmd_join(wl); | ||
1259 | if (ret < 0) | ||
1260 | wl1271_warning("cmd join to update channel failed %d", | ||
1261 | ret); | ||
1262 | } else | ||
1263 | wl->channel = channel; | ||
1145 | 1264 | ||
1146 | wl->psm_requested = true; | 1265 | if (conf->flags & IEEE80211_CONF_PS && |
1266 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | ||
1267 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | ||
1147 | 1268 | ||
1148 | /* | 1269 | /* |
1149 | * We enter PSM only if we're already associated. | 1270 | * We enter PSM only if we're already associated. |
1150 | * If we're not, we'll enter it when joining an SSID, | 1271 | * If we're not, we'll enter it when joining an SSID, |
1151 | * through the bss_info_changed() hook. | 1272 | * through the bss_info_changed() hook. |
1152 | */ | 1273 | */ |
1153 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 1274 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1275 | wl1271_info("psm enabled"); | ||
1276 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | ||
1277 | true); | ||
1278 | } | ||
1154 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1279 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1155 | wl->psm_requested) { | 1280 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1156 | wl1271_info("psm disabled"); | 1281 | wl1271_info("psm disabled"); |
1157 | 1282 | ||
1158 | wl->psm_requested = false; | 1283 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
1159 | 1284 | ||
1160 | if (wl->psm) | 1285 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) |
1161 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); | 1286 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, |
1287 | true); | ||
1162 | } | 1288 | } |
1163 | 1289 | ||
1164 | if (conf->power_level != wl->power_level) { | 1290 | if (conf->power_level != wl->power_level) { |
@@ -1350,9 +1476,24 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1350 | wl1271_error("Could not add or replace key"); | 1476 | wl1271_error("Could not add or replace key"); |
1351 | goto out_sleep; | 1477 | goto out_sleep; |
1352 | } | 1478 | } |
1479 | |||
1480 | /* the default WEP key needs to be configured at least once */ | ||
1481 | if (key_type == KEY_WEP) { | ||
1482 | ret = wl1271_cmd_set_default_wep_key(wl, | ||
1483 | wl->default_key); | ||
1484 | if (ret < 0) | ||
1485 | goto out_sleep; | ||
1486 | } | ||
1353 | break; | 1487 | break; |
1354 | 1488 | ||
1355 | case DISABLE_KEY: | 1489 | case DISABLE_KEY: |
1490 | /* The wl1271 does not allow to remove unicast keys - they | ||
1491 | will be cleared automatically on next CMD_JOIN. Ignore the | ||
1492 | request silently, as we dont want the mac80211 to emit | ||
1493 | an error message. */ | ||
1494 | if (!is_broadcast_ether_addr(addr)) | ||
1495 | break; | ||
1496 | |||
1356 | ret = wl1271_cmd_set_key(wl, KEY_REMOVE, | 1497 | ret = wl1271_cmd_set_key(wl, KEY_REMOVE, |
1357 | key_conf->keyidx, key_type, | 1498 | key_conf->keyidx, key_type, |
1358 | key_conf->keylen, key_conf->key, | 1499 | key_conf->keylen, key_conf->key, |
@@ -1440,20 +1581,21 @@ out: | |||
1440 | return ret; | 1581 | return ret; |
1441 | } | 1582 | } |
1442 | 1583 | ||
1443 | static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set) | 1584 | static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *beacon) |
1444 | { | 1585 | { |
1445 | struct ieee80211_supported_band *band; | 1586 | u8 *ptr = beacon->data + |
1446 | u32 enabled_rates = 0; | 1587 | offsetof(struct ieee80211_mgmt, u.beacon.variable); |
1447 | int bit; | 1588 | |
1448 | 1589 | /* find the location of the ssid in the beacon */ | |
1449 | band = wl->hw->wiphy->bands[wl->band]; | 1590 | while (ptr < beacon->data + beacon->len) { |
1450 | for (bit = 0; bit < band->n_bitrates; bit++) { | 1591 | if (ptr[0] == WLAN_EID_SSID) { |
1451 | if (basic_rate_set & 0x1) | 1592 | wl->ssid_len = ptr[1]; |
1452 | enabled_rates |= band->bitrates[bit].hw_value; | 1593 | memcpy(wl->ssid, ptr+2, wl->ssid_len); |
1453 | basic_rate_set >>= 1; | 1594 | return; |
1595 | } | ||
1596 | ptr += ptr[1]; | ||
1454 | } | 1597 | } |
1455 | 1598 | wl1271_error("ad-hoc beacon template has no SSID!\n"); | |
1456 | return enabled_rates; | ||
1457 | } | 1599 | } |
1458 | 1600 | ||
1459 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | 1601 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, |
@@ -1463,6 +1605,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1463 | { | 1605 | { |
1464 | enum wl1271_cmd_ps_mode mode; | 1606 | enum wl1271_cmd_ps_mode mode; |
1465 | struct wl1271 *wl = hw->priv; | 1607 | struct wl1271 *wl = hw->priv; |
1608 | bool do_join = false; | ||
1466 | int ret; | 1609 | int ret; |
1467 | 1610 | ||
1468 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 1611 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1473,9 +1616,67 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1473 | if (ret < 0) | 1616 | if (ret < 0) |
1474 | goto out; | 1617 | goto out; |
1475 | 1618 | ||
1619 | if (wl->bss_type == BSS_TYPE_IBSS) { | ||
1620 | /* FIXME: This implements rudimentary ad-hoc support - | ||
1621 | proper templates are on the wish list and notification | ||
1622 | on when they change. This patch will update the templates | ||
1623 | on every call to this function. */ | ||
1624 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | ||
1625 | |||
1626 | if (beacon) { | ||
1627 | struct ieee80211_hdr *hdr; | ||
1628 | |||
1629 | wl1271_ssid_set(wl, beacon); | ||
1630 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | ||
1631 | beacon->data, | ||
1632 | beacon->len); | ||
1633 | |||
1634 | if (ret < 0) { | ||
1635 | dev_kfree_skb(beacon); | ||
1636 | goto out_sleep; | ||
1637 | } | ||
1638 | |||
1639 | hdr = (struct ieee80211_hdr *) beacon->data; | ||
1640 | hdr->frame_control = cpu_to_le16( | ||
1641 | IEEE80211_FTYPE_MGMT | | ||
1642 | IEEE80211_STYPE_PROBE_RESP); | ||
1643 | |||
1644 | ret = wl1271_cmd_template_set(wl, | ||
1645 | CMD_TEMPL_PROBE_RESPONSE, | ||
1646 | beacon->data, | ||
1647 | beacon->len); | ||
1648 | dev_kfree_skb(beacon); | ||
1649 | if (ret < 0) | ||
1650 | goto out_sleep; | ||
1651 | |||
1652 | /* Need to update the SSID (for filtering etc) */ | ||
1653 | do_join = true; | ||
1654 | } | ||
1655 | } | ||
1656 | |||
1657 | if ((changed & BSS_CHANGED_BSSID) && | ||
1658 | /* | ||
1659 | * Now we know the correct bssid, so we send a new join command | ||
1660 | * and enable the BSSID filter | ||
1661 | */ | ||
1662 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | ||
1663 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1664 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | ||
1665 | ret = wl1271_cmd_build_null_data(wl); | ||
1666 | if (ret < 0) { | ||
1667 | wl1271_warning("cmd buld null data failed %d", | ||
1668 | ret); | ||
1669 | goto out_sleep; | ||
1670 | } | ||
1671 | |||
1672 | /* Need to update the BSSID (for filtering etc) */ | ||
1673 | do_join = true; | ||
1674 | } | ||
1675 | |||
1476 | if (changed & BSS_CHANGED_ASSOC) { | 1676 | if (changed & BSS_CHANGED_ASSOC) { |
1477 | if (bss_conf->assoc) { | 1677 | if (bss_conf->assoc) { |
1478 | wl->aid = bss_conf->aid; | 1678 | wl->aid = bss_conf->aid; |
1679 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | ||
1479 | 1680 | ||
1480 | /* | 1681 | /* |
1481 | * with wl1271, we don't need to update the | 1682 | * with wl1271, we don't need to update the |
@@ -1492,15 +1693,16 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1492 | goto out_sleep; | 1693 | goto out_sleep; |
1493 | 1694 | ||
1494 | /* If we want to go in PSM but we're not there yet */ | 1695 | /* If we want to go in PSM but we're not there yet */ |
1495 | if (wl->psm_requested && !wl->psm) { | 1696 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && |
1697 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
1496 | mode = STATION_POWER_SAVE_MODE; | 1698 | mode = STATION_POWER_SAVE_MODE; |
1497 | ret = wl1271_ps_set_mode(wl, mode); | 1699 | ret = wl1271_ps_set_mode(wl, mode, true); |
1498 | if (ret < 0) | 1700 | if (ret < 0) |
1499 | goto out_sleep; | 1701 | goto out_sleep; |
1500 | } | 1702 | } |
1501 | } else { | 1703 | } else { |
1502 | /* use defaults when not associated */ | 1704 | /* use defaults when not associated */ |
1503 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | 1705 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1504 | wl->aid = 0; | 1706 | wl->aid = 0; |
1505 | } | 1707 | } |
1506 | 1708 | ||
@@ -1535,15 +1737,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1535 | } | 1737 | } |
1536 | } | 1738 | } |
1537 | 1739 | ||
1538 | if (changed & BSS_CHANGED_BASIC_RATES) { | 1740 | if (do_join) { |
1539 | wl->basic_rate_set = wl1271_enabled_rates_get( | 1741 | ret = wl1271_cmd_join(wl); |
1540 | wl, bss_conf->basic_rates); | ||
1541 | |||
1542 | ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set); | ||
1543 | if (ret < 0) { | 1742 | if (ret < 0) { |
1544 | wl1271_warning("Set rate policies failed %d", ret); | 1743 | wl1271_warning("cmd join failed %d", ret); |
1545 | goto out_sleep; | 1744 | goto out_sleep; |
1546 | } | 1745 | } |
1746 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1547 | } | 1747 | } |
1548 | 1748 | ||
1549 | out_sleep: | 1749 | out_sleep: |
@@ -1553,6 +1753,43 @@ out: | |||
1553 | mutex_unlock(&wl->mutex); | 1753 | mutex_unlock(&wl->mutex); |
1554 | } | 1754 | } |
1555 | 1755 | ||
1756 | static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
1757 | const struct ieee80211_tx_queue_params *params) | ||
1758 | { | ||
1759 | struct wl1271 *wl = hw->priv; | ||
1760 | int ret; | ||
1761 | |||
1762 | mutex_lock(&wl->mutex); | ||
1763 | |||
1764 | wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | ||
1765 | |||
1766 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
1767 | if (ret < 0) | ||
1768 | goto out; | ||
1769 | |||
1770 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | ||
1771 | params->cw_min, params->cw_max, | ||
1772 | params->aifs, params->txop); | ||
1773 | if (ret < 0) | ||
1774 | goto out_sleep; | ||
1775 | |||
1776 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | ||
1777 | CONF_CHANNEL_TYPE_EDCF, | ||
1778 | wl1271_tx_get_queue(queue), | ||
1779 | CONF_PS_SCHEME_LEGACY_PSPOLL, | ||
1780 | CONF_ACK_POLICY_LEGACY, 0, 0); | ||
1781 | if (ret < 0) | ||
1782 | goto out_sleep; | ||
1783 | |||
1784 | out_sleep: | ||
1785 | wl1271_ps_elp_sleep(wl); | ||
1786 | |||
1787 | out: | ||
1788 | mutex_unlock(&wl->mutex); | ||
1789 | |||
1790 | return ret; | ||
1791 | } | ||
1792 | |||
1556 | 1793 | ||
1557 | /* can't be const, mac80211 writes to this */ | 1794 | /* can't be const, mac80211 writes to this */ |
1558 | static struct ieee80211_rate wl1271_rates[] = { | 1795 | static struct ieee80211_rate wl1271_rates[] = { |
@@ -1599,19 +1836,19 @@ static struct ieee80211_rate wl1271_rates[] = { | |||
1599 | 1836 | ||
1600 | /* can't be const, mac80211 writes to this */ | 1837 | /* can't be const, mac80211 writes to this */ |
1601 | static struct ieee80211_channel wl1271_channels[] = { | 1838 | static struct ieee80211_channel wl1271_channels[] = { |
1602 | { .hw_value = 1, .center_freq = 2412}, | 1839 | { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, |
1603 | { .hw_value = 2, .center_freq = 2417}, | 1840 | { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, |
1604 | { .hw_value = 3, .center_freq = 2422}, | 1841 | { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, |
1605 | { .hw_value = 4, .center_freq = 2427}, | 1842 | { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, |
1606 | { .hw_value = 5, .center_freq = 2432}, | 1843 | { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, |
1607 | { .hw_value = 6, .center_freq = 2437}, | 1844 | { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, |
1608 | { .hw_value = 7, .center_freq = 2442}, | 1845 | { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, |
1609 | { .hw_value = 8, .center_freq = 2447}, | 1846 | { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, |
1610 | { .hw_value = 9, .center_freq = 2452}, | 1847 | { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, |
1611 | { .hw_value = 10, .center_freq = 2457}, | 1848 | { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, |
1612 | { .hw_value = 11, .center_freq = 2462}, | 1849 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, |
1613 | { .hw_value = 12, .center_freq = 2467}, | 1850 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, |
1614 | { .hw_value = 13, .center_freq = 2472}, | 1851 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
1615 | }; | 1852 | }; |
1616 | 1853 | ||
1617 | /* can't be const, mac80211 writes to this */ | 1854 | /* can't be const, mac80211 writes to this */ |
@@ -1718,6 +1955,8 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1718 | .hw_scan = wl1271_op_hw_scan, | 1955 | .hw_scan = wl1271_op_hw_scan, |
1719 | .bss_info_changed = wl1271_op_bss_info_changed, | 1956 | .bss_info_changed = wl1271_op_bss_info_changed, |
1720 | .set_rts_threshold = wl1271_op_set_rts_threshold, | 1957 | .set_rts_threshold = wl1271_op_set_rts_threshold, |
1958 | .conf_tx = wl1271_op_conf_tx, | ||
1959 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | ||
1721 | }; | 1960 | }; |
1722 | 1961 | ||
1723 | static int wl1271_register_hw(struct wl1271 *wl) | 1962 | static int wl1271_register_hw(struct wl1271 *wl) |
@@ -1757,7 +1996,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
1757 | IEEE80211_HW_BEACON_FILTER | | 1996 | IEEE80211_HW_BEACON_FILTER | |
1758 | IEEE80211_HW_SUPPORTS_PS; | 1997 | IEEE80211_HW_SUPPORTS_PS; |
1759 | 1998 | ||
1760 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1999 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2000 | BIT(NL80211_IFTYPE_ADHOC); | ||
1761 | wl->hw->wiphy->max_scan_ssids = 1; | 2001 | wl->hw->wiphy->max_scan_ssids = 1; |
1762 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; | 2002 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; |
1763 | 2003 | ||
@@ -1785,24 +2025,17 @@ static struct platform_device wl1271_device = { | |||
1785 | }; | 2025 | }; |
1786 | 2026 | ||
1787 | #define WL1271_DEFAULT_CHANNEL 0 | 2027 | #define WL1271_DEFAULT_CHANNEL 0 |
1788 | static int __devinit wl1271_probe(struct spi_device *spi) | 2028 | |
2029 | static struct ieee80211_hw *wl1271_alloc_hw(void) | ||
1789 | { | 2030 | { |
1790 | struct wl12xx_platform_data *pdata; | ||
1791 | struct ieee80211_hw *hw; | 2031 | struct ieee80211_hw *hw; |
1792 | struct wl1271 *wl; | 2032 | struct wl1271 *wl; |
1793 | int ret, i; | 2033 | int i; |
1794 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
1795 | |||
1796 | pdata = spi->dev.platform_data; | ||
1797 | if (!pdata) { | ||
1798 | wl1271_error("no platform data"); | ||
1799 | return -ENODEV; | ||
1800 | } | ||
1801 | 2034 | ||
1802 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2035 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
1803 | if (!hw) { | 2036 | if (!hw) { |
1804 | wl1271_error("could not alloc ieee80211_hw"); | 2037 | wl1271_error("could not alloc ieee80211_hw"); |
1805 | return -ENOMEM; | 2038 | return ERR_PTR(-ENOMEM); |
1806 | } | 2039 | } |
1807 | 2040 | ||
1808 | wl = hw->priv; | 2041 | wl = hw->priv; |
@@ -1811,44 +2044,80 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1811 | INIT_LIST_HEAD(&wl->list); | 2044 | INIT_LIST_HEAD(&wl->list); |
1812 | 2045 | ||
1813 | wl->hw = hw; | 2046 | wl->hw = hw; |
1814 | dev_set_drvdata(&spi->dev, wl); | ||
1815 | wl->spi = spi; | ||
1816 | 2047 | ||
1817 | skb_queue_head_init(&wl->tx_queue); | 2048 | skb_queue_head_init(&wl->tx_queue); |
1818 | 2049 | ||
1819 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2050 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
1820 | wl->channel = WL1271_DEFAULT_CHANNEL; | 2051 | wl->channel = WL1271_DEFAULT_CHANNEL; |
1821 | wl->scanning = false; | ||
1822 | wl->default_key = 0; | 2052 | wl->default_key = 0; |
1823 | wl->rx_counter = 0; | 2053 | wl->rx_counter = 0; |
1824 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 2054 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
1825 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | 2055 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |
1826 | wl->elp = false; | ||
1827 | wl->psm = 0; | ||
1828 | wl->psm_requested = false; | ||
1829 | wl->psm_entry_retry = 0; | 2056 | wl->psm_entry_retry = 0; |
1830 | wl->tx_queue_stopped = false; | ||
1831 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 2057 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
1832 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | 2058 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
2059 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
2060 | wl->sta_rate_set = 0; | ||
1833 | wl->band = IEEE80211_BAND_2GHZ; | 2061 | wl->band = IEEE80211_BAND_2GHZ; |
1834 | wl->vif = NULL; | 2062 | wl->vif = NULL; |
1835 | wl->joined = false; | 2063 | wl->flags = 0; |
1836 | 2064 | ||
1837 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 2065 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
1838 | wl->tx_frames[i] = NULL; | 2066 | wl->tx_frames[i] = NULL; |
1839 | 2067 | ||
1840 | spin_lock_init(&wl->wl_lock); | 2068 | spin_lock_init(&wl->wl_lock); |
1841 | 2069 | ||
1842 | /* | ||
1843 | * In case our MAC address is not correctly set, | ||
1844 | * we use a random but Nokia MAC. | ||
1845 | */ | ||
1846 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
1847 | get_random_bytes(wl->mac_addr + 3, 3); | ||
1848 | |||
1849 | wl->state = WL1271_STATE_OFF; | 2070 | wl->state = WL1271_STATE_OFF; |
1850 | mutex_init(&wl->mutex); | 2071 | mutex_init(&wl->mutex); |
1851 | 2072 | ||
2073 | /* Apply default driver configuration. */ | ||
2074 | wl1271_conf_init(wl); | ||
2075 | |||
2076 | return hw; | ||
2077 | } | ||
2078 | |||
2079 | int wl1271_free_hw(struct wl1271 *wl) | ||
2080 | { | ||
2081 | ieee80211_unregister_hw(wl->hw); | ||
2082 | |||
2083 | wl1271_debugfs_exit(wl); | ||
2084 | |||
2085 | kfree(wl->target_mem_map); | ||
2086 | vfree(wl->fw); | ||
2087 | wl->fw = NULL; | ||
2088 | kfree(wl->nvs); | ||
2089 | wl->nvs = NULL; | ||
2090 | |||
2091 | kfree(wl->fw_status); | ||
2092 | kfree(wl->tx_res_if); | ||
2093 | |||
2094 | ieee80211_free_hw(wl->hw); | ||
2095 | |||
2096 | return 0; | ||
2097 | } | ||
2098 | |||
2099 | static int __devinit wl1271_probe(struct spi_device *spi) | ||
2100 | { | ||
2101 | struct wl12xx_platform_data *pdata; | ||
2102 | struct ieee80211_hw *hw; | ||
2103 | struct wl1271 *wl; | ||
2104 | int ret; | ||
2105 | |||
2106 | pdata = spi->dev.platform_data; | ||
2107 | if (!pdata) { | ||
2108 | wl1271_error("no platform data"); | ||
2109 | return -ENODEV; | ||
2110 | } | ||
2111 | |||
2112 | hw = wl1271_alloc_hw(); | ||
2113 | if (IS_ERR(hw)) | ||
2114 | return PTR_ERR(hw); | ||
2115 | |||
2116 | wl = hw->priv; | ||
2117 | |||
2118 | dev_set_drvdata(&spi->dev, wl); | ||
2119 | wl->spi = spi; | ||
2120 | |||
1852 | /* This is the only SPI value that we need to set here, the rest | 2121 | /* This is the only SPI value that we need to set here, the rest |
1853 | * comes from the board-peripherals file */ | 2122 | * comes from the board-peripherals file */ |
1854 | spi->bits_per_word = 32; | 2123 | spi->bits_per_word = 32; |
@@ -1890,9 +2159,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1890 | } | 2159 | } |
1891 | dev_set_drvdata(&wl1271_device.dev, wl); | 2160 | dev_set_drvdata(&wl1271_device.dev, wl); |
1892 | 2161 | ||
1893 | /* Apply default driver configuration. */ | ||
1894 | wl1271_conf_init(wl); | ||
1895 | |||
1896 | ret = wl1271_init_ieee80211(wl); | 2162 | ret = wl1271_init_ieee80211(wl); |
1897 | if (ret) | 2163 | if (ret) |
1898 | goto out_platform; | 2164 | goto out_platform; |
@@ -1923,21 +2189,10 @@ static int __devexit wl1271_remove(struct spi_device *spi) | |||
1923 | { | 2189 | { |
1924 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | 2190 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); |
1925 | 2191 | ||
1926 | ieee80211_unregister_hw(wl->hw); | ||
1927 | |||
1928 | wl1271_debugfs_exit(wl); | ||
1929 | platform_device_unregister(&wl1271_device); | 2192 | platform_device_unregister(&wl1271_device); |
1930 | free_irq(wl->irq, wl); | 2193 | free_irq(wl->irq, wl); |
1931 | kfree(wl->target_mem_map); | ||
1932 | vfree(wl->fw); | ||
1933 | wl->fw = NULL; | ||
1934 | kfree(wl->nvs); | ||
1935 | wl->nvs = NULL; | ||
1936 | 2194 | ||
1937 | kfree(wl->fw_status); | 2195 | wl1271_free_hw(wl); |
1938 | kfree(wl->tx_res_if); | ||
1939 | |||
1940 | ieee80211_free_hw(wl->hw); | ||
1941 | 2196 | ||
1942 | return 0; | 2197 | return 0; |
1943 | } | 2198 | } |