diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 1272 |
1 files changed, 751 insertions, 521 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 65a1aeba2419..b7d9137851ac 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -22,23 +22,19 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/firmware.h> | 25 | #include <linux/firmware.h> |
28 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
29 | #include <linux/irq.h> | ||
30 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
31 | #include <linux/crc32.h> | 28 | #include <linux/crc32.h> |
32 | #include <linux/etherdevice.h> | 29 | #include <linux/etherdevice.h> |
33 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
34 | #include <linux/spi/wl12xx.h> | ||
35 | #include <linux/inetdevice.h> | 31 | #include <linux/inetdevice.h> |
32 | #include <linux/platform_device.h> | ||
36 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
37 | 34 | ||
38 | #include "wl1271.h" | 35 | #include "wl1271.h" |
39 | #include "wl12xx_80211.h" | 36 | #include "wl12xx_80211.h" |
40 | #include "wl1271_reg.h" | 37 | #include "wl1271_reg.h" |
41 | #include "wl1271_spi.h" | ||
42 | #include "wl1271_io.h" | 38 | #include "wl1271_io.h" |
43 | #include "wl1271_event.h" | 39 | #include "wl1271_event.h" |
44 | #include "wl1271_tx.h" | 40 | #include "wl1271_tx.h" |
@@ -54,17 +50,57 @@ | |||
54 | 50 | ||
55 | static struct conf_drv_settings default_conf = { | 51 | static struct conf_drv_settings default_conf = { |
56 | .sg = { | 52 | .sg = { |
57 | .per_threshold = 7500, | 53 | .params = { |
58 | .max_scan_compensation_time = 120000, | 54 | [CONF_SG_BT_PER_THRESHOLD] = 7500, |
59 | .nfs_sample_interval = 400, | 55 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, |
60 | .load_ratio = 50, | 56 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, |
61 | .auto_ps_mode = 0, | 57 | [CONF_SG_BT_LOAD_RATIO] = 50, |
62 | .probe_req_compensation = 170, | 58 | [CONF_SG_AUTO_PS_MODE] = 0, |
63 | .scan_window_compensation = 50, | 59 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, |
64 | .antenna_config = 0, | 60 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, |
65 | .beacon_miss_threshold = 60, | 61 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, |
66 | .rate_adaptation_threshold = CONF_HW_BIT_RATE_12MBPS, | 62 | [CONF_SG_BEACON_MISS_PERCENT] = 60, |
67 | .rate_adaptation_snr = 0 | 63 | [CONF_SG_RATE_ADAPT_THRESH] = 12, |
64 | [CONF_SG_RATE_ADAPT_SNR] = 0, | ||
65 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, | ||
66 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 30, | ||
67 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 8, | ||
68 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, | ||
69 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 50, | ||
70 | /* Note: with UPSD, this should be 4 */ | ||
71 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 8, | ||
72 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, | ||
73 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, | ||
74 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 20, | ||
75 | /* Note: with UPDS, this should be 15 */ | ||
76 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
77 | /* Note: with UPDS, this should be 50 */ | ||
78 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 40, | ||
79 | /* Note: with UPDS, this should be 10 */ | ||
80 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 20, | ||
81 | [CONF_SG_RXT] = 1200, | ||
82 | [CONF_SG_TXT] = 1000, | ||
83 | [CONF_SG_ADAPTIVE_RXT_TXT] = 1, | ||
84 | [CONF_SG_PS_POLL_TIMEOUT] = 10, | ||
85 | [CONF_SG_UPSD_TIMEOUT] = 10, | ||
86 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, | ||
87 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, | ||
88 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, | ||
89 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
90 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, | ||
91 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, | ||
92 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, | ||
93 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, | ||
94 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, | ||
95 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, | ||
96 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, | ||
97 | [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, | ||
98 | [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, | ||
99 | [CONF_SG_HV3_MAX_SERVED] = 6, | ||
100 | [CONF_SG_DHCP_TIME] = 5000, | ||
101 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | ||
102 | }, | ||
103 | .state = CONF_SG_PROTECTIVE, | ||
68 | }, | 104 | }, |
69 | .rx = { | 105 | .rx = { |
70 | .rx_msdu_life_time = 512000, | 106 | .rx_msdu_life_time = 512000, |
@@ -81,8 +117,7 @@ static struct conf_drv_settings default_conf = { | |||
81 | .tx = { | 117 | .tx = { |
82 | .tx_energy_detection = 0, | 118 | .tx_energy_detection = 0, |
83 | .rc_conf = { | 119 | .rc_conf = { |
84 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS | | 120 | .enabled_rates = 0, |
85 | CONF_HW_BIT_RATE_2MBPS, | ||
86 | .short_retry_limit = 10, | 121 | .short_retry_limit = 10, |
87 | .long_retry_limit = 10, | 122 | .long_retry_limit = 10, |
88 | .aflags = 0 | 123 | .aflags = 0 |
@@ -179,11 +214,13 @@ static struct conf_drv_settings default_conf = { | |||
179 | }, | 214 | }, |
180 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 215 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
181 | .tx_compl_timeout = 700, | 216 | .tx_compl_timeout = 700, |
182 | .tx_compl_threshold = 4 | 217 | .tx_compl_threshold = 4, |
218 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, | ||
219 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, | ||
183 | }, | 220 | }, |
184 | .conn = { | 221 | .conn = { |
185 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 222 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
186 | .listen_interval = 0, | 223 | .listen_interval = 1, |
187 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | 224 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
188 | .bcn_filt_ie_count = 1, | 225 | .bcn_filt_ie_count = 1, |
189 | .bcn_filt_ie = { | 226 | .bcn_filt_ie = { |
@@ -198,38 +235,11 @@ static struct conf_drv_settings default_conf = { | |||
198 | .broadcast_timeout = 20000, | 235 | .broadcast_timeout = 20000, |
199 | .rx_broadcast_in_ps = 1, | 236 | .rx_broadcast_in_ps = 1, |
200 | .ps_poll_threshold = 20, | 237 | .ps_poll_threshold = 20, |
201 | .sig_trigger_count = 2, | ||
202 | .sig_trigger = { | ||
203 | [0] = { | ||
204 | .threshold = -75, | ||
205 | .pacing = 500, | ||
206 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
207 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
208 | .direction = CONF_TRIG_EVENT_DIR_LOW, | ||
209 | .hysteresis = 2, | ||
210 | .index = 0, | ||
211 | .enable = 1 | ||
212 | }, | ||
213 | [1] = { | ||
214 | .threshold = -75, | ||
215 | .pacing = 500, | ||
216 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
217 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
218 | .direction = CONF_TRIG_EVENT_DIR_HIGH, | ||
219 | .hysteresis = 2, | ||
220 | .index = 1, | ||
221 | .enable = 1 | ||
222 | } | ||
223 | }, | ||
224 | .sig_weights = { | ||
225 | .rssi_bcn_avg_weight = 10, | ||
226 | .rssi_pkt_avg_weight = 10, | ||
227 | .snr_bcn_avg_weight = 10, | ||
228 | .snr_pkt_avg_weight = 10 | ||
229 | }, | ||
230 | .bet_enable = CONF_BET_MODE_ENABLE, | 238 | .bet_enable = CONF_BET_MODE_ENABLE, |
231 | .bet_max_consecutive = 10, | 239 | .bet_max_consecutive = 10, |
232 | .psm_entry_retries = 3 | 240 | .psm_entry_retries = 3, |
241 | .keep_alive_interval = 55000, | ||
242 | .max_listen_interval = 20, | ||
233 | }, | 243 | }, |
234 | .init = { | 244 | .init = { |
235 | .radioparam = { | 245 | .radioparam = { |
@@ -243,9 +253,32 @@ static struct conf_drv_settings default_conf = { | |||
243 | .pm_config = { | 253 | .pm_config = { |
244 | .host_clk_settling_time = 5000, | 254 | .host_clk_settling_time = 5000, |
245 | .host_fast_wakeup_support = false | 255 | .host_fast_wakeup_support = false |
256 | }, | ||
257 | .roam_trigger = { | ||
258 | /* FIXME: due to firmware bug, must use value 1 for now */ | ||
259 | .trigger_pacing = 1, | ||
260 | .avg_weight_rssi_beacon = 20, | ||
261 | .avg_weight_rssi_data = 10, | ||
262 | .avg_weight_snr_beacon = 20, | ||
263 | .avg_weight_snr_data = 10 | ||
246 | } | 264 | } |
247 | }; | 265 | }; |
248 | 266 | ||
267 | static void wl1271_device_release(struct device *dev) | ||
268 | { | ||
269 | |||
270 | } | ||
271 | |||
272 | static struct platform_device wl1271_device = { | ||
273 | .name = "wl1271", | ||
274 | .id = -1, | ||
275 | |||
276 | /* device model insists to have a release function */ | ||
277 | .dev = { | ||
278 | .release = wl1271_device_release, | ||
279 | }, | ||
280 | }; | ||
281 | |||
249 | static LIST_HEAD(wl_list); | 282 | static LIST_HEAD(wl_list); |
250 | 283 | ||
251 | static void wl1271_conf_init(struct wl1271 *wl) | 284 | static void wl1271_conf_init(struct wl1271 *wl) |
@@ -298,7 +331,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
298 | goto out_free_memmap; | 331 | goto out_free_memmap; |
299 | 332 | ||
300 | /* Initialize connection monitoring thresholds */ | 333 | /* Initialize connection monitoring thresholds */ |
301 | ret = wl1271_acx_conn_monit_params(wl); | 334 | ret = wl1271_acx_conn_monit_params(wl, false); |
302 | if (ret < 0) | 335 | if (ret < 0) |
303 | goto out_free_memmap; | 336 | goto out_free_memmap; |
304 | 337 | ||
@@ -365,30 +398,14 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
365 | return ret; | 398 | return ret; |
366 | } | 399 | } |
367 | 400 | ||
368 | static void wl1271_disable_interrupts(struct wl1271 *wl) | ||
369 | { | ||
370 | disable_irq(wl->irq); | ||
371 | } | ||
372 | |||
373 | static void wl1271_power_off(struct wl1271 *wl) | ||
374 | { | ||
375 | wl->set_power(false); | ||
376 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
377 | } | ||
378 | |||
379 | static void wl1271_power_on(struct wl1271 *wl) | ||
380 | { | ||
381 | wl->set_power(true); | ||
382 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
383 | } | ||
384 | |||
385 | static void wl1271_fw_status(struct wl1271 *wl, | 401 | static void wl1271_fw_status(struct wl1271 *wl, |
386 | struct wl1271_fw_status *status) | 402 | struct wl1271_fw_status *status) |
387 | { | 403 | { |
404 | struct timespec ts; | ||
388 | u32 total = 0; | 405 | u32 total = 0; |
389 | int i; | 406 | int i; |
390 | 407 | ||
391 | wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); | 408 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); |
392 | 409 | ||
393 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 410 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
394 | "drv_rx_counter = %d, tx_results_counter = %d)", | 411 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -413,14 +430,19 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
413 | ieee80211_queue_work(wl->hw, &wl->tx_work); | 430 | ieee80211_queue_work(wl->hw, &wl->tx_work); |
414 | 431 | ||
415 | /* update the host-chipset time offset */ | 432 | /* update the host-chipset time offset */ |
416 | wl->time_offset = jiffies_to_usecs(jiffies) - | 433 | getnstimeofday(&ts); |
417 | le32_to_cpu(status->fw_localtime); | 434 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
435 | (s64)le32_to_cpu(status->fw_localtime); | ||
418 | } | 436 | } |
419 | 437 | ||
438 | #define WL1271_IRQ_MAX_LOOPS 10 | ||
439 | |||
420 | static void wl1271_irq_work(struct work_struct *work) | 440 | static void wl1271_irq_work(struct work_struct *work) |
421 | { | 441 | { |
422 | int ret; | 442 | int ret; |
423 | u32 intr; | 443 | u32 intr; |
444 | int loopcount = WL1271_IRQ_MAX_LOOPS; | ||
445 | unsigned long flags; | ||
424 | struct wl1271 *wl = | 446 | struct wl1271 *wl = |
425 | container_of(work, struct wl1271, irq_work); | 447 | container_of(work, struct wl1271, irq_work); |
426 | 448 | ||
@@ -428,91 +450,78 @@ static void wl1271_irq_work(struct work_struct *work) | |||
428 | 450 | ||
429 | wl1271_debug(DEBUG_IRQ, "IRQ work"); | 451 | wl1271_debug(DEBUG_IRQ, "IRQ work"); |
430 | 452 | ||
431 | if (wl->state == WL1271_STATE_OFF) | 453 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
432 | goto out; | 454 | goto out; |
433 | 455 | ||
434 | ret = wl1271_ps_elp_wakeup(wl, true); | 456 | ret = wl1271_ps_elp_wakeup(wl, true); |
435 | if (ret < 0) | 457 | if (ret < 0) |
436 | goto out; | 458 | goto out; |
437 | 459 | ||
438 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 460 | spin_lock_irqsave(&wl->wl_lock, flags); |
439 | 461 | while (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags) && loopcount) { | |
440 | wl1271_fw_status(wl, wl->fw_status); | 462 | clear_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); |
441 | intr = le32_to_cpu(wl->fw_status->intr); | 463 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
442 | if (!intr) { | 464 | loopcount--; |
443 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); | 465 | |
444 | goto out_sleep; | 466 | wl1271_fw_status(wl, wl->fw_status); |
445 | } | 467 | intr = le32_to_cpu(wl->fw_status->intr); |
468 | if (!intr) { | ||
469 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); | ||
470 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
471 | continue; | ||
472 | } | ||
446 | 473 | ||
447 | intr &= WL1271_INTR_MASK; | 474 | intr &= WL1271_INTR_MASK; |
448 | 475 | ||
449 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 476 | if (intr & WL1271_ACX_INTR_DATA) { |
450 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 477 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); |
451 | wl1271_event_handle(wl, 0); | ||
452 | } | ||
453 | 478 | ||
454 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 479 | /* check for tx results */ |
455 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 480 | if (wl->fw_status->tx_results_counter != |
456 | wl1271_event_handle(wl, 1); | 481 | (wl->tx_results_count & 0xff)) |
457 | } | 482 | wl1271_tx_complete(wl); |
458 | 483 | ||
459 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 484 | wl1271_rx(wl, wl->fw_status); |
460 | wl1271_debug(DEBUG_IRQ, | 485 | } |
461 | "WL1271_ACX_INTR_INIT_COMPLETE"); | ||
462 | 486 | ||
463 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) | 487 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
464 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); | 488 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
489 | wl1271_event_handle(wl, 0); | ||
490 | } | ||
465 | 491 | ||
466 | if (intr & WL1271_ACX_INTR_DATA) { | 492 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
467 | u8 tx_res_cnt = wl->fw_status->tx_results_counter - | 493 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
468 | wl->tx_results_count; | 494 | wl1271_event_handle(wl, 1); |
495 | } | ||
469 | 496 | ||
470 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); | 497 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
498 | wl1271_debug(DEBUG_IRQ, | ||
499 | "WL1271_ACX_INTR_INIT_COMPLETE"); | ||
471 | 500 | ||
472 | /* check for tx results */ | 501 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) |
473 | if (tx_res_cnt) | 502 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); |
474 | wl1271_tx_complete(wl, tx_res_cnt); | ||
475 | 503 | ||
476 | wl1271_rx(wl, wl->fw_status); | 504 | spin_lock_irqsave(&wl->wl_lock, flags); |
477 | } | 505 | } |
478 | 506 | ||
479 | out_sleep: | 507 | if (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags)) |
480 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | 508 | ieee80211_queue_work(wl->hw, &wl->irq_work); |
481 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 509 | else |
510 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | ||
511 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
512 | |||
482 | wl1271_ps_elp_sleep(wl); | 513 | wl1271_ps_elp_sleep(wl); |
483 | 514 | ||
484 | out: | 515 | out: |
485 | mutex_unlock(&wl->mutex); | 516 | mutex_unlock(&wl->mutex); |
486 | } | 517 | } |
487 | 518 | ||
488 | static irqreturn_t wl1271_irq(int irq, void *cookie) | ||
489 | { | ||
490 | struct wl1271 *wl; | ||
491 | unsigned long flags; | ||
492 | |||
493 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
494 | |||
495 | wl = cookie; | ||
496 | |||
497 | /* complete the ELP completion */ | ||
498 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
499 | if (wl->elp_compl) { | ||
500 | complete(wl->elp_compl); | ||
501 | wl->elp_compl = NULL; | ||
502 | } | ||
503 | |||
504 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
505 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
506 | |||
507 | return IRQ_HANDLED; | ||
508 | } | ||
509 | |||
510 | static int wl1271_fetch_firmware(struct wl1271 *wl) | 519 | static int wl1271_fetch_firmware(struct wl1271 *wl) |
511 | { | 520 | { |
512 | const struct firmware *fw; | 521 | const struct firmware *fw; |
513 | int ret; | 522 | int ret; |
514 | 523 | ||
515 | ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev); | 524 | ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); |
516 | 525 | ||
517 | if (ret < 0) { | 526 | if (ret < 0) { |
518 | wl1271_error("could not get firmware: %d", ret); | 527 | wl1271_error("could not get firmware: %d", ret); |
@@ -545,46 +554,12 @@ out: | |||
545 | return ret; | 554 | return ret; |
546 | } | 555 | } |
547 | 556 | ||
548 | static int wl1271_update_mac_addr(struct wl1271 *wl) | ||
549 | { | ||
550 | int ret = 0; | ||
551 | u8 *nvs_ptr = (u8 *)wl->nvs->nvs; | ||
552 | |||
553 | /* get mac address from the NVS */ | ||
554 | wl->mac_addr[0] = nvs_ptr[11]; | ||
555 | wl->mac_addr[1] = nvs_ptr[10]; | ||
556 | wl->mac_addr[2] = nvs_ptr[6]; | ||
557 | wl->mac_addr[3] = nvs_ptr[5]; | ||
558 | wl->mac_addr[4] = nvs_ptr[4]; | ||
559 | wl->mac_addr[5] = nvs_ptr[3]; | ||
560 | |||
561 | /* FIXME: if it is a zero-address, we should bail out. Now, instead, | ||
562 | we randomize an address */ | ||
563 | if (is_zero_ether_addr(wl->mac_addr)) { | ||
564 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
565 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
566 | get_random_bytes(wl->mac_addr + 3, 3); | ||
567 | |||
568 | /* update this address to the NVS */ | ||
569 | nvs_ptr[11] = wl->mac_addr[0]; | ||
570 | nvs_ptr[10] = wl->mac_addr[1]; | ||
571 | nvs_ptr[6] = wl->mac_addr[2]; | ||
572 | nvs_ptr[5] = wl->mac_addr[3]; | ||
573 | nvs_ptr[4] = wl->mac_addr[4]; | ||
574 | nvs_ptr[3] = wl->mac_addr[5]; | ||
575 | } | ||
576 | |||
577 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | ||
578 | |||
579 | return ret; | ||
580 | } | ||
581 | |||
582 | static int wl1271_fetch_nvs(struct wl1271 *wl) | 557 | static int wl1271_fetch_nvs(struct wl1271 *wl) |
583 | { | 558 | { |
584 | const struct firmware *fw; | 559 | const struct firmware *fw; |
585 | int ret; | 560 | int ret; |
586 | 561 | ||
587 | ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev); | 562 | ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); |
588 | 563 | ||
589 | if (ret < 0) { | 564 | if (ret < 0) { |
590 | wl1271_error("could not get nvs file: %d", ret); | 565 | wl1271_error("could not get nvs file: %d", ret); |
@@ -608,8 +583,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
608 | 583 | ||
609 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); | 584 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); |
610 | 585 | ||
611 | ret = wl1271_update_mac_addr(wl); | ||
612 | |||
613 | out: | 586 | out: |
614 | release_firmware(fw); | 587 | release_firmware(fw); |
615 | 588 | ||
@@ -826,15 +799,13 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
826 | * The workqueue is slow to process the tx_queue and we need stop | 799 | * The workqueue is slow to process the tx_queue and we need stop |
827 | * the queue here, otherwise the queue will get too long. | 800 | * the queue here, otherwise the queue will get too long. |
828 | */ | 801 | */ |
829 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) { | 802 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_HIGH_WATERMARK) { |
830 | ieee80211_stop_queues(wl->hw); | 803 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); |
831 | 804 | ||
832 | /* | 805 | spin_lock_irqsave(&wl->wl_lock, flags); |
833 | * FIXME: this is racy, the variable is not properly | 806 | ieee80211_stop_queues(wl->hw); |
834 | * protected. Maybe fix this by removing the stupid | ||
835 | * variable altogether and checking the real queue state? | ||
836 | */ | ||
837 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | 807 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
808 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
838 | } | 809 | } |
839 | 810 | ||
840 | return NETDEV_TX_OK; | 811 | return NETDEV_TX_OK; |
@@ -882,7 +853,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | |||
882 | if (wl == wl_temp) | 853 | if (wl == wl_temp) |
883 | break; | 854 | break; |
884 | } | 855 | } |
885 | if (wl == NULL) | 856 | if (wl != wl_temp) |
886 | return NOTIFY_DONE; | 857 | return NOTIFY_DONE; |
887 | 858 | ||
888 | /* Get the interface IP address for the device. "ifa" will become | 859 | /* Get the interface IP address for the device. "ifa" will become |
@@ -929,13 +900,60 @@ static struct notifier_block wl1271_dev_notifier = { | |||
929 | 900 | ||
930 | static int wl1271_op_start(struct ieee80211_hw *hw) | 901 | static int wl1271_op_start(struct ieee80211_hw *hw) |
931 | { | 902 | { |
903 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | ||
904 | |||
905 | /* | ||
906 | * We have to delay the booting of the hardware because | ||
907 | * we need to know the local MAC address before downloading and | ||
908 | * initializing the firmware. The MAC address cannot be changed | ||
909 | * after boot, and without the proper MAC address, the firmware | ||
910 | * will not function properly. | ||
911 | * | ||
912 | * The MAC address is first known when the corresponding interface | ||
913 | * is added. That is where we will initialize the hardware. | ||
914 | */ | ||
915 | |||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | static void wl1271_op_stop(struct ieee80211_hw *hw) | ||
920 | { | ||
921 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); | ||
922 | } | ||
923 | |||
924 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | ||
925 | struct ieee80211_vif *vif) | ||
926 | { | ||
932 | struct wl1271 *wl = hw->priv; | 927 | struct wl1271 *wl = hw->priv; |
933 | int retries = WL1271_BOOT_RETRIES; | 928 | int retries = WL1271_BOOT_RETRIES; |
934 | int ret = 0; | 929 | int ret = 0; |
935 | 930 | ||
936 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 931 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
932 | vif->type, vif->addr); | ||
937 | 933 | ||
938 | mutex_lock(&wl->mutex); | 934 | mutex_lock(&wl->mutex); |
935 | if (wl->vif) { | ||
936 | ret = -EBUSY; | ||
937 | goto out; | ||
938 | } | ||
939 | |||
940 | wl->vif = vif; | ||
941 | |||
942 | switch (vif->type) { | ||
943 | case NL80211_IFTYPE_STATION: | ||
944 | wl->bss_type = BSS_TYPE_STA_BSS; | ||
945 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
946 | break; | ||
947 | case NL80211_IFTYPE_ADHOC: | ||
948 | wl->bss_type = BSS_TYPE_IBSS; | ||
949 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
950 | break; | ||
951 | default: | ||
952 | ret = -EOPNOTSUPP; | ||
953 | goto out; | ||
954 | } | ||
955 | |||
956 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); | ||
939 | 957 | ||
940 | if (wl->state != WL1271_STATE_OFF) { | 958 | if (wl->state != WL1271_STATE_OFF) { |
941 | wl1271_error("cannot start because not in off state: %d", | 959 | wl1271_error("cannot start because not in off state: %d", |
@@ -991,19 +1009,20 @@ out: | |||
991 | return ret; | 1009 | return ret; |
992 | } | 1010 | } |
993 | 1011 | ||
994 | static void wl1271_op_stop(struct ieee80211_hw *hw) | 1012 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, |
1013 | struct ieee80211_vif *vif) | ||
995 | { | 1014 | { |
996 | struct wl1271 *wl = hw->priv; | 1015 | struct wl1271 *wl = hw->priv; |
997 | int i; | 1016 | int i; |
998 | 1017 | ||
999 | wl1271_info("down"); | ||
1000 | |||
1001 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); | ||
1002 | |||
1003 | unregister_inetaddr_notifier(&wl1271_dev_notifier); | 1018 | unregister_inetaddr_notifier(&wl1271_dev_notifier); |
1004 | list_del(&wl->list); | ||
1005 | 1019 | ||
1006 | mutex_lock(&wl->mutex); | 1020 | mutex_lock(&wl->mutex); |
1021 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | ||
1022 | |||
1023 | wl1271_info("down"); | ||
1024 | |||
1025 | list_del(&wl->list); | ||
1007 | 1026 | ||
1008 | WARN_ON(wl->state != WL1271_STATE_ON); | 1027 | WARN_ON(wl->state != WL1271_STATE_ON); |
1009 | 1028 | ||
@@ -1032,6 +1051,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1032 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); | 1051 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); |
1033 | wl->ssid_len = 0; | 1052 | wl->ssid_len = 0; |
1034 | wl->bss_type = MAX_BSS_TYPE; | 1053 | wl->bss_type = MAX_BSS_TYPE; |
1054 | wl->set_bss_type = MAX_BSS_TYPE; | ||
1035 | wl->band = IEEE80211_BAND_2GHZ; | 1055 | wl->band = IEEE80211_BAND_2GHZ; |
1036 | 1056 | ||
1037 | wl->rx_counter = 0; | 1057 | wl->rx_counter = 0; |
@@ -1041,163 +1061,142 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1041 | wl->tx_results_count = 0; | 1061 | wl->tx_results_count = 0; |
1042 | wl->tx_packets_count = 0; | 1062 | wl->tx_packets_count = 0; |
1043 | wl->tx_security_last_seq = 0; | 1063 | wl->tx_security_last_seq = 0; |
1044 | wl->tx_security_seq_16 = 0; | 1064 | wl->tx_security_seq = 0; |
1045 | wl->tx_security_seq_32 = 0; | ||
1046 | wl->time_offset = 0; | 1065 | wl->time_offset = 0; |
1047 | wl->session_counter = 0; | 1066 | wl->session_counter = 0; |
1048 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1067 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
1049 | wl->sta_rate_set = 0; | 1068 | wl->sta_rate_set = 0; |
1050 | wl->flags = 0; | 1069 | wl->flags = 0; |
1070 | wl->vif = NULL; | ||
1071 | wl->filters = 0; | ||
1051 | 1072 | ||
1052 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1073 | for (i = 0; i < NUM_TX_QUEUES; i++) |
1053 | wl->tx_blocks_freed[i] = 0; | 1074 | wl->tx_blocks_freed[i] = 0; |
1054 | 1075 | ||
1055 | wl1271_debugfs_reset(wl); | 1076 | wl1271_debugfs_reset(wl); |
1077 | |||
1078 | kfree(wl->fw_status); | ||
1079 | wl->fw_status = NULL; | ||
1080 | kfree(wl->tx_res_if); | ||
1081 | wl->tx_res_if = NULL; | ||
1082 | kfree(wl->target_mem_map); | ||
1083 | wl->target_mem_map = NULL; | ||
1084 | |||
1056 | mutex_unlock(&wl->mutex); | 1085 | mutex_unlock(&wl->mutex); |
1057 | } | 1086 | } |
1058 | 1087 | ||
1059 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 1088 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) |
1060 | struct ieee80211_vif *vif) | ||
1061 | { | 1089 | { |
1062 | struct wl1271 *wl = hw->priv; | 1090 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
1063 | int ret = 0; | 1091 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |
1064 | 1092 | ||
1065 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 1093 | /* combine requested filters with current filter config */ |
1066 | vif->type, vif->addr); | 1094 | filters = wl->filters | filters; |
1067 | 1095 | ||
1068 | mutex_lock(&wl->mutex); | 1096 | wl1271_debug(DEBUG_FILTERS, "RX filters set: "); |
1069 | if (wl->vif) { | 1097 | |
1070 | ret = -EBUSY; | 1098 | if (filters & FIF_PROMISC_IN_BSS) { |
1071 | goto out; | 1099 | wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS"); |
1100 | wl->rx_config &= ~CFG_UNI_FILTER_EN; | ||
1101 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1102 | } | ||
1103 | if (filters & FIF_BCN_PRBRESP_PROMISC) { | ||
1104 | wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC"); | ||
1105 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1106 | wl->rx_config &= ~CFG_SSID_FILTER_EN; | ||
1072 | } | 1107 | } |
1108 | if (filters & FIF_OTHER_BSS) { | ||
1109 | wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS"); | ||
1110 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1111 | } | ||
1112 | if (filters & FIF_CONTROL) { | ||
1113 | wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL"); | ||
1114 | wl->rx_filter |= CFG_RX_CTL_EN; | ||
1115 | } | ||
1116 | if (filters & FIF_FCSFAIL) { | ||
1117 | wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL"); | ||
1118 | wl->rx_filter |= CFG_RX_FCS_ERROR; | ||
1119 | } | ||
1120 | } | ||
1073 | 1121 | ||
1074 | wl->vif = vif; | 1122 | static int wl1271_dummy_join(struct wl1271 *wl) |
1123 | { | ||
1124 | int ret = 0; | ||
1125 | /* we need to use a dummy BSSID for now */ | ||
1126 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | ||
1127 | 0xad, 0xbe, 0xef }; | ||
1075 | 1128 | ||
1076 | switch (vif->type) { | 1129 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); |
1077 | case NL80211_IFTYPE_STATION: | 1130 | |
1078 | wl->bss_type = BSS_TYPE_STA_BSS; | 1131 | /* pass through frames from all BSS */ |
1079 | break; | 1132 | wl1271_configure_filters(wl, FIF_OTHER_BSS); |
1080 | case NL80211_IFTYPE_ADHOC: | 1133 | |
1081 | wl->bss_type = BSS_TYPE_IBSS; | 1134 | ret = wl1271_cmd_join(wl, wl->set_bss_type); |
1082 | break; | 1135 | if (ret < 0) |
1083 | default: | ||
1084 | ret = -EOPNOTSUPP; | ||
1085 | goto out; | 1136 | goto out; |
1086 | } | ||
1087 | 1137 | ||
1088 | /* FIXME: what if conf->mac_addr changes? */ | 1138 | set_bit(WL1271_FLAG_JOINED, &wl->flags); |
1089 | 1139 | ||
1090 | out: | 1140 | out: |
1091 | mutex_unlock(&wl->mutex); | ||
1092 | return ret; | 1141 | return ret; |
1093 | } | 1142 | } |
1094 | 1143 | ||
1095 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | 1144 | static int wl1271_join(struct wl1271 *wl, bool set_assoc) |
1096 | struct ieee80211_vif *vif) | ||
1097 | { | ||
1098 | struct wl1271 *wl = hw->priv; | ||
1099 | |||
1100 | mutex_lock(&wl->mutex); | ||
1101 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | ||
1102 | wl->vif = NULL; | ||
1103 | mutex_unlock(&wl->mutex); | ||
1104 | } | ||
1105 | |||
1106 | #if 0 | ||
1107 | static int wl1271_op_config_interface(struct ieee80211_hw *hw, | ||
1108 | struct ieee80211_vif *vif, | ||
1109 | struct ieee80211_if_conf *conf) | ||
1110 | { | 1145 | { |
1111 | struct wl1271 *wl = hw->priv; | ||
1112 | struct sk_buff *beacon; | ||
1113 | int ret; | 1146 | int ret; |
1114 | 1147 | ||
1115 | wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM", | 1148 | /* |
1116 | conf->bssid); | 1149 | * One of the side effects of the JOIN command is that is clears |
1117 | wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid, | 1150 | * WPA/WPA2 keys from the chipset. Performing a JOIN while associated |
1118 | conf->ssid_len); | 1151 | * to a WPA/WPA2 access point will therefore kill the data-path. |
1152 | * Currently there is no supported scenario for JOIN during | ||
1153 | * association - if it becomes a supported scenario, the WPA/WPA2 keys | ||
1154 | * must be handled somehow. | ||
1155 | * | ||
1156 | */ | ||
1157 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
1158 | wl1271_info("JOIN while associated."); | ||
1119 | 1159 | ||
1120 | mutex_lock(&wl->mutex); | 1160 | if (set_assoc) |
1161 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | ||
1121 | 1162 | ||
1122 | ret = wl1271_ps_elp_wakeup(wl, false); | 1163 | ret = wl1271_cmd_join(wl, wl->set_bss_type); |
1123 | if (ret < 0) | 1164 | if (ret < 0) |
1124 | goto out; | 1165 | goto out; |
1125 | 1166 | ||
1126 | if (memcmp(wl->bssid, conf->bssid, ETH_ALEN)) { | 1167 | set_bit(WL1271_FLAG_JOINED, &wl->flags); |
1127 | wl1271_debug(DEBUG_MAC80211, "bssid changed"); | ||
1128 | |||
1129 | memcpy(wl->bssid, conf->bssid, ETH_ALEN); | ||
1130 | |||
1131 | ret = wl1271_cmd_join(wl); | ||
1132 | if (ret < 0) | ||
1133 | goto out_sleep; | ||
1134 | |||
1135 | ret = wl1271_cmd_build_null_data(wl); | ||
1136 | if (ret < 0) | ||
1137 | goto out_sleep; | ||
1138 | } | ||
1139 | |||
1140 | wl->ssid_len = conf->ssid_len; | ||
1141 | if (wl->ssid_len) | ||
1142 | memcpy(wl->ssid, conf->ssid, wl->ssid_len); | ||
1143 | |||
1144 | if (conf->changed & IEEE80211_IFCC_BEACON) { | ||
1145 | beacon = ieee80211_beacon_get(hw, vif); | ||
1146 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | ||
1147 | beacon->data, beacon->len); | ||
1148 | |||
1149 | if (ret < 0) { | ||
1150 | dev_kfree_skb(beacon); | ||
1151 | goto out_sleep; | ||
1152 | } | ||
1153 | |||
1154 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, | ||
1155 | beacon->data, beacon->len); | ||
1156 | |||
1157 | dev_kfree_skb(beacon); | ||
1158 | |||
1159 | if (ret < 0) | ||
1160 | goto out_sleep; | ||
1161 | } | ||
1162 | |||
1163 | out_sleep: | ||
1164 | wl1271_ps_elp_sleep(wl); | ||
1165 | |||
1166 | out: | ||
1167 | mutex_unlock(&wl->mutex); | ||
1168 | |||
1169 | return ret; | ||
1170 | } | ||
1171 | #endif | ||
1172 | |||
1173 | static int wl1271_join_channel(struct wl1271 *wl, int channel) | ||
1174 | { | ||
1175 | int ret = 0; | ||
1176 | /* we need to use a dummy BSSID for now */ | ||
1177 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | ||
1178 | 0xad, 0xbe, 0xef }; | ||
1179 | 1168 | ||
1180 | /* the dummy join is not required for ad-hoc */ | 1169 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
1181 | if (wl->bss_type == BSS_TYPE_IBSS) | ||
1182 | goto out; | 1170 | goto out; |
1183 | 1171 | ||
1184 | /* disable mac filter, so we hear everything */ | 1172 | /* |
1185 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | 1173 | * The join command disable the keep-alive mode, shut down its process, |
1174 | * and also clear the template config, so we need to reset it all after | ||
1175 | * the join. The acx_aid starts the keep-alive process, and the order | ||
1176 | * of the commands below is relevant. | ||
1177 | */ | ||
1178 | ret = wl1271_acx_keep_alive_mode(wl, true); | ||
1179 | if (ret < 0) | ||
1180 | goto out; | ||
1186 | 1181 | ||
1187 | wl->channel = channel; | 1182 | ret = wl1271_acx_aid(wl, wl->aid); |
1188 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | 1183 | if (ret < 0) |
1184 | goto out; | ||
1189 | 1185 | ||
1190 | ret = wl1271_cmd_join(wl); | 1186 | ret = wl1271_cmd_build_klv_null_data(wl); |
1191 | if (ret < 0) | 1187 | if (ret < 0) |
1192 | goto out; | 1188 | goto out; |
1193 | 1189 | ||
1194 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | 1190 | ret = wl1271_acx_keep_alive_config(wl, CMD_TEMPL_KLV_IDX_NULL_DATA, |
1191 | ACX_KEEP_ALIVE_TPL_VALID); | ||
1192 | if (ret < 0) | ||
1193 | goto out; | ||
1195 | 1194 | ||
1196 | out: | 1195 | out: |
1197 | return ret; | 1196 | return ret; |
1198 | } | 1197 | } |
1199 | 1198 | ||
1200 | static int wl1271_unjoin_channel(struct wl1271 *wl) | 1199 | static int wl1271_unjoin(struct wl1271 *wl) |
1201 | { | 1200 | { |
1202 | int ret; | 1201 | int ret; |
1203 | 1202 | ||
@@ -1207,14 +1206,41 @@ static int wl1271_unjoin_channel(struct wl1271 *wl) | |||
1207 | goto out; | 1206 | goto out; |
1208 | 1207 | ||
1209 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | 1208 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); |
1210 | wl->channel = 0; | ||
1211 | memset(wl->bssid, 0, ETH_ALEN); | 1209 | memset(wl->bssid, 0, ETH_ALEN); |
1212 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 1210 | |
1211 | /* stop filterting packets based on bssid */ | ||
1212 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | ||
1213 | 1213 | ||
1214 | out: | 1214 | out: |
1215 | return ret; | 1215 | return ret; |
1216 | } | 1216 | } |
1217 | 1217 | ||
1218 | static void wl1271_set_band_rate(struct wl1271 *wl) | ||
1219 | { | ||
1220 | if (wl->band == IEEE80211_BAND_2GHZ) | ||
1221 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1222 | else | ||
1223 | wl->basic_rate_set = wl->conf.tx.basic_rate_5; | ||
1224 | } | ||
1225 | |||
1226 | static u32 wl1271_min_rate_get(struct wl1271 *wl) | ||
1227 | { | ||
1228 | int i; | ||
1229 | u32 rate = 0; | ||
1230 | |||
1231 | if (!wl->basic_rate_set) { | ||
1232 | WARN_ON(1); | ||
1233 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1234 | } | ||
1235 | |||
1236 | for (i = 0; !rate; i++) { | ||
1237 | if ((wl->basic_rate_set >> i) & 0x1) | ||
1238 | rate = 1 << i; | ||
1239 | } | ||
1240 | |||
1241 | return rate; | ||
1242 | } | ||
1243 | |||
1218 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1244 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1219 | { | 1245 | { |
1220 | struct wl1271 *wl = hw->priv; | 1246 | struct wl1271 *wl = hw->priv; |
@@ -1231,38 +1257,62 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1231 | 1257 | ||
1232 | mutex_lock(&wl->mutex); | 1258 | mutex_lock(&wl->mutex); |
1233 | 1259 | ||
1234 | wl->band = conf->channel->band; | 1260 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
1261 | goto out; | ||
1235 | 1262 | ||
1236 | ret = wl1271_ps_elp_wakeup(wl, false); | 1263 | ret = wl1271_ps_elp_wakeup(wl, false); |
1237 | if (ret < 0) | 1264 | if (ret < 0) |
1238 | goto out; | 1265 | goto out; |
1239 | 1266 | ||
1267 | /* if the channel changes while joined, join again */ | ||
1268 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL && | ||
1269 | ((wl->band != conf->channel->band) || | ||
1270 | (wl->channel != channel))) { | ||
1271 | wl->band = conf->channel->band; | ||
1272 | wl->channel = channel; | ||
1273 | |||
1274 | /* | ||
1275 | * FIXME: the mac80211 should really provide a fixed rate | ||
1276 | * to use here. for now, just use the smallest possible rate | ||
1277 | * for the band as a fixed rate for association frames and | ||
1278 | * other control messages. | ||
1279 | */ | ||
1280 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
1281 | wl1271_set_band_rate(wl); | ||
1282 | |||
1283 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1284 | ret = wl1271_acx_rate_policies(wl); | ||
1285 | if (ret < 0) | ||
1286 | wl1271_warning("rate policy for update channel " | ||
1287 | "failed %d", ret); | ||
1288 | |||
1289 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1290 | ret = wl1271_join(wl, false); | ||
1291 | if (ret < 0) | ||
1292 | wl1271_warning("cmd join to update channel " | ||
1293 | "failed %d", ret); | ||
1294 | } | ||
1295 | } | ||
1296 | |||
1240 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1297 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1241 | if (conf->flags & IEEE80211_CONF_IDLE && | 1298 | if (conf->flags & IEEE80211_CONF_IDLE && |
1242 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) | 1299 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
1243 | wl1271_unjoin_channel(wl); | 1300 | wl1271_unjoin(wl); |
1244 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) | 1301 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) |
1245 | wl1271_join_channel(wl, channel); | 1302 | wl1271_dummy_join(wl); |
1246 | 1303 | ||
1247 | if (conf->flags & IEEE80211_CONF_IDLE) { | 1304 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1248 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1305 | wl->rate_set = wl1271_min_rate_get(wl); |
1249 | wl->sta_rate_set = 0; | 1306 | wl->sta_rate_set = 0; |
1250 | wl1271_acx_rate_policies(wl); | 1307 | wl1271_acx_rate_policies(wl); |
1251 | } | 1308 | wl1271_acx_keep_alive_config( |
1309 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1310 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
1311 | set_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1312 | } else | ||
1313 | clear_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1252 | } | 1314 | } |
1253 | 1315 | ||
1254 | /* if the channel changes while joined, join again */ | ||
1255 | if (channel != wl->channel && | ||
1256 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1257 | wl->channel = channel; | ||
1258 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ | ||
1259 | ret = wl1271_cmd_join(wl); | ||
1260 | if (ret < 0) | ||
1261 | wl1271_warning("cmd join to update channel failed %d", | ||
1262 | ret); | ||
1263 | } else | ||
1264 | wl->channel = channel; | ||
1265 | |||
1266 | if (conf->flags & IEEE80211_CONF_PS && | 1316 | if (conf->flags & IEEE80211_CONF_PS && |
1267 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1317 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1268 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1318 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
@@ -1273,13 +1323,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1273 | * through the bss_info_changed() hook. | 1323 | * through the bss_info_changed() hook. |
1274 | */ | 1324 | */ |
1275 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | 1325 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1276 | wl1271_info("psm enabled"); | 1326 | wl1271_debug(DEBUG_PSM, "psm enabled"); |
1277 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 1327 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
1278 | true); | 1328 | true); |
1279 | } | 1329 | } |
1280 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1330 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1281 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1331 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1282 | wl1271_info("psm disabled"); | 1332 | wl1271_debug(DEBUG_PSM, "psm disabled"); |
1283 | 1333 | ||
1284 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1334 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
1285 | 1335 | ||
@@ -1311,11 +1361,15 @@ struct wl1271_filter_params { | |||
1311 | u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN]; | 1361 | u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN]; |
1312 | }; | 1362 | }; |
1313 | 1363 | ||
1314 | static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, | 1364 | static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, |
1315 | struct dev_addr_list *mc_list) | 1365 | struct netdev_hw_addr_list *mc_list) |
1316 | { | 1366 | { |
1317 | struct wl1271_filter_params *fp; | 1367 | struct wl1271_filter_params *fp; |
1318 | int i; | 1368 | struct netdev_hw_addr *ha; |
1369 | struct wl1271 *wl = hw->priv; | ||
1370 | |||
1371 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1372 | return 0; | ||
1319 | 1373 | ||
1320 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); | 1374 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); |
1321 | if (!fp) { | 1375 | if (!fp) { |
@@ -1324,21 +1378,16 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, | |||
1324 | } | 1378 | } |
1325 | 1379 | ||
1326 | /* update multicast filtering parameters */ | 1380 | /* update multicast filtering parameters */ |
1327 | fp->enabled = true; | ||
1328 | if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) { | ||
1329 | mc_count = 0; | ||
1330 | fp->enabled = false; | ||
1331 | } | ||
1332 | |||
1333 | fp->mc_list_length = 0; | 1381 | fp->mc_list_length = 0; |
1334 | for (i = 0; i < mc_count; i++) { | 1382 | if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) { |
1335 | if (mc_list->da_addrlen == ETH_ALEN) { | 1383 | fp->enabled = false; |
1384 | } else { | ||
1385 | fp->enabled = true; | ||
1386 | netdev_hw_addr_list_for_each(ha, mc_list) { | ||
1336 | memcpy(fp->mc_list[fp->mc_list_length], | 1387 | memcpy(fp->mc_list[fp->mc_list_length], |
1337 | mc_list->da_addr, ETH_ALEN); | 1388 | ha->addr, ETH_ALEN); |
1338 | fp->mc_list_length++; | 1389 | fp->mc_list_length++; |
1339 | } else | 1390 | } |
1340 | wl1271_warning("Unknown mc address length."); | ||
1341 | mc_list = mc_list->next; | ||
1342 | } | 1391 | } |
1343 | 1392 | ||
1344 | return (u64)(unsigned long)fp; | 1393 | return (u64)(unsigned long)fp; |
@@ -1363,15 +1412,16 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1363 | 1412 | ||
1364 | mutex_lock(&wl->mutex); | 1413 | mutex_lock(&wl->mutex); |
1365 | 1414 | ||
1366 | if (wl->state == WL1271_STATE_OFF) | 1415 | *total &= WL1271_SUPPORTED_FILTERS; |
1416 | changed &= WL1271_SUPPORTED_FILTERS; | ||
1417 | |||
1418 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1367 | goto out; | 1419 | goto out; |
1368 | 1420 | ||
1369 | ret = wl1271_ps_elp_wakeup(wl, false); | 1421 | ret = wl1271_ps_elp_wakeup(wl, false); |
1370 | if (ret < 0) | 1422 | if (ret < 0) |
1371 | goto out; | 1423 | goto out; |
1372 | 1424 | ||
1373 | *total &= WL1271_SUPPORTED_FILTERS; | ||
1374 | changed &= WL1271_SUPPORTED_FILTERS; | ||
1375 | 1425 | ||
1376 | if (*total & FIF_ALLMULTI) | 1426 | if (*total & FIF_ALLMULTI) |
1377 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); | 1427 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); |
@@ -1382,14 +1432,14 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1382 | if (ret < 0) | 1432 | if (ret < 0) |
1383 | goto out_sleep; | 1433 | goto out_sleep; |
1384 | 1434 | ||
1385 | kfree(fp); | ||
1386 | |||
1387 | /* FIXME: We still need to set our filters properly */ | ||
1388 | |||
1389 | /* determine, whether supported filter values have changed */ | 1435 | /* determine, whether supported filter values have changed */ |
1390 | if (changed == 0) | 1436 | if (changed == 0) |
1391 | goto out_sleep; | 1437 | goto out_sleep; |
1392 | 1438 | ||
1439 | /* configure filters */ | ||
1440 | wl->filters = *total; | ||
1441 | wl1271_configure_filters(wl, 0); | ||
1442 | |||
1393 | /* apply configured filters */ | 1443 | /* apply configured filters */ |
1394 | ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); | 1444 | ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); |
1395 | if (ret < 0) | 1445 | if (ret < 0) |
@@ -1400,6 +1450,7 @@ out_sleep: | |||
1400 | 1450 | ||
1401 | out: | 1451 | out: |
1402 | mutex_unlock(&wl->mutex); | 1452 | mutex_unlock(&wl->mutex); |
1453 | kfree(fp); | ||
1403 | } | 1454 | } |
1404 | 1455 | ||
1405 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 1456 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
@@ -1450,15 +1501,15 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1450 | key_type = KEY_TKIP; | 1501 | key_type = KEY_TKIP; |
1451 | 1502 | ||
1452 | key_conf->hw_key_idx = key_conf->keyidx; | 1503 | key_conf->hw_key_idx = key_conf->keyidx; |
1453 | tx_seq_32 = wl->tx_security_seq_32; | 1504 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1454 | tx_seq_16 = wl->tx_security_seq_16; | 1505 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1455 | break; | 1506 | break; |
1456 | case ALG_CCMP: | 1507 | case ALG_CCMP: |
1457 | key_type = KEY_AES; | 1508 | key_type = KEY_AES; |
1458 | 1509 | ||
1459 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1510 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1460 | tx_seq_32 = wl->tx_security_seq_32; | 1511 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1461 | tx_seq_16 = wl->tx_security_seq_16; | 1512 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1462 | break; | 1513 | break; |
1463 | default: | 1514 | default: |
1464 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); | 1515 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); |
@@ -1508,8 +1559,6 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1508 | default: | 1559 | default: |
1509 | wl1271_error("Unsupported key cmd 0x%x", cmd); | 1560 | wl1271_error("Unsupported key cmd 0x%x", cmd); |
1510 | ret = -EOPNOTSUPP; | 1561 | ret = -EOPNOTSUPP; |
1511 | goto out_sleep; | ||
1512 | |||
1513 | break; | 1562 | break; |
1514 | } | 1563 | } |
1515 | 1564 | ||
@@ -1524,6 +1573,7 @@ out: | |||
1524 | } | 1573 | } |
1525 | 1574 | ||
1526 | static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | 1575 | static int wl1271_op_hw_scan(struct ieee80211_hw *hw, |
1576 | struct ieee80211_vif *vif, | ||
1527 | struct cfg80211_scan_request *req) | 1577 | struct cfg80211_scan_request *req) |
1528 | { | 1578 | { |
1529 | struct wl1271 *wl = hw->priv; | 1579 | struct wl1271 *wl = hw->priv; |
@@ -1545,10 +1595,12 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
1545 | goto out; | 1595 | goto out; |
1546 | 1596 | ||
1547 | if (wl1271_11a_enabled()) | 1597 | if (wl1271_11a_enabled()) |
1548 | ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, | 1598 | ret = wl1271_cmd_scan(hw->priv, ssid, len, |
1599 | req->ie, req->ie_len, 1, 0, | ||
1549 | WL1271_SCAN_BAND_DUAL, 3); | 1600 | WL1271_SCAN_BAND_DUAL, 3); |
1550 | else | 1601 | else |
1551 | ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, | 1602 | ret = wl1271_cmd_scan(hw->priv, ssid, len, |
1603 | req->ie, req->ie_len, 1, 0, | ||
1552 | WL1271_SCAN_BAND_2_4_GHZ, 3); | 1604 | WL1271_SCAN_BAND_2_4_GHZ, 3); |
1553 | 1605 | ||
1554 | wl1271_ps_elp_sleep(wl); | 1606 | wl1271_ps_elp_sleep(wl); |
@@ -1562,10 +1614,13 @@ out: | |||
1562 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 1614 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
1563 | { | 1615 | { |
1564 | struct wl1271 *wl = hw->priv; | 1616 | struct wl1271 *wl = hw->priv; |
1565 | int ret; | 1617 | int ret = 0; |
1566 | 1618 | ||
1567 | mutex_lock(&wl->mutex); | 1619 | mutex_lock(&wl->mutex); |
1568 | 1620 | ||
1621 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1622 | goto out; | ||
1623 | |||
1569 | ret = wl1271_ps_elp_wakeup(wl, false); | 1624 | ret = wl1271_ps_elp_wakeup(wl, false); |
1570 | if (ret < 0) | 1625 | if (ret < 0) |
1571 | goto out; | 1626 | goto out; |
@@ -1607,6 +1662,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1607 | enum wl1271_cmd_ps_mode mode; | 1662 | enum wl1271_cmd_ps_mode mode; |
1608 | struct wl1271 *wl = hw->priv; | 1663 | struct wl1271 *wl = hw->priv; |
1609 | bool do_join = false; | 1664 | bool do_join = false; |
1665 | bool set_assoc = false; | ||
1610 | int ret; | 1666 | int ret; |
1611 | 1667 | ||
1612 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 1668 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1617,20 +1673,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1617 | if (ret < 0) | 1673 | if (ret < 0) |
1618 | goto out; | 1674 | goto out; |
1619 | 1675 | ||
1620 | if (wl->bss_type == BSS_TYPE_IBSS) { | 1676 | if ((changed && BSS_CHANGED_BEACON_INT) && |
1621 | /* FIXME: This implements rudimentary ad-hoc support - | 1677 | (wl->bss_type == BSS_TYPE_IBSS)) { |
1622 | proper templates are on the wish list and notification | 1678 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", |
1623 | on when they change. This patch will update the templates | 1679 | bss_conf->beacon_int); |
1624 | on every call to this function. */ | 1680 | |
1681 | wl->beacon_int = bss_conf->beacon_int; | ||
1682 | do_join = true; | ||
1683 | } | ||
1684 | |||
1685 | if ((changed && BSS_CHANGED_BEACON) && | ||
1686 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1625 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 1687 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
1626 | 1688 | ||
1689 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated"); | ||
1690 | |||
1627 | if (beacon) { | 1691 | if (beacon) { |
1628 | struct ieee80211_hdr *hdr; | 1692 | struct ieee80211_hdr *hdr; |
1629 | 1693 | ||
1630 | wl1271_ssid_set(wl, beacon); | 1694 | wl1271_ssid_set(wl, beacon); |
1631 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 1695 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, |
1632 | beacon->data, | 1696 | beacon->data, |
1633 | beacon->len); | 1697 | beacon->len, 0, |
1698 | wl1271_min_rate_get(wl)); | ||
1634 | 1699 | ||
1635 | if (ret < 0) { | 1700 | if (ret < 0) { |
1636 | dev_kfree_skb(beacon); | 1701 | dev_kfree_skb(beacon); |
@@ -1645,7 +1710,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1645 | ret = wl1271_cmd_template_set(wl, | 1710 | ret = wl1271_cmd_template_set(wl, |
1646 | CMD_TEMPL_PROBE_RESPONSE, | 1711 | CMD_TEMPL_PROBE_RESPONSE, |
1647 | beacon->data, | 1712 | beacon->data, |
1648 | beacon->len); | 1713 | beacon->len, 0, |
1714 | wl1271_min_rate_get(wl)); | ||
1649 | dev_kfree_skb(beacon); | 1715 | dev_kfree_skb(beacon); |
1650 | if (ret < 0) | 1716 | if (ret < 0) |
1651 | goto out_sleep; | 1717 | goto out_sleep; |
@@ -1655,20 +1721,48 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1655 | } | 1721 | } |
1656 | } | 1722 | } |
1657 | 1723 | ||
1724 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | ||
1725 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1726 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", | ||
1727 | bss_conf->enable_beacon ? "enabled" : "disabled"); | ||
1728 | |||
1729 | if (bss_conf->enable_beacon) | ||
1730 | wl->set_bss_type = BSS_TYPE_IBSS; | ||
1731 | else | ||
1732 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
1733 | do_join = true; | ||
1734 | } | ||
1735 | |||
1736 | if (changed & BSS_CHANGED_CQM) { | ||
1737 | bool enable = false; | ||
1738 | if (bss_conf->cqm_rssi_thold) | ||
1739 | enable = true; | ||
1740 | ret = wl1271_acx_rssi_snr_trigger(wl, enable, | ||
1741 | bss_conf->cqm_rssi_thold, | ||
1742 | bss_conf->cqm_rssi_hyst); | ||
1743 | if (ret < 0) | ||
1744 | goto out; | ||
1745 | wl->rssi_thold = bss_conf->cqm_rssi_thold; | ||
1746 | } | ||
1747 | |||
1658 | if ((changed & BSS_CHANGED_BSSID) && | 1748 | if ((changed & BSS_CHANGED_BSSID) && |
1659 | /* | 1749 | /* |
1660 | * Now we know the correct bssid, so we send a new join command | 1750 | * Now we know the correct bssid, so we send a new join command |
1661 | * and enable the BSSID filter | 1751 | * and enable the BSSID filter |
1662 | */ | 1752 | */ |
1663 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | 1753 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { |
1664 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1665 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | 1754 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); |
1755 | |||
1666 | ret = wl1271_cmd_build_null_data(wl); | 1756 | ret = wl1271_cmd_build_null_data(wl); |
1667 | if (ret < 0) { | 1757 | if (ret < 0) |
1668 | wl1271_warning("cmd buld null data failed %d", | 1758 | goto out_sleep; |
1669 | ret); | 1759 | |
1760 | ret = wl1271_build_qos_null_data(wl); | ||
1761 | if (ret < 0) | ||
1670 | goto out_sleep; | 1762 | goto out_sleep; |
1671 | } | 1763 | |
1764 | /* filter out all packets not from this BSSID */ | ||
1765 | wl1271_configure_filters(wl, 0); | ||
1672 | 1766 | ||
1673 | /* Need to update the BSSID (for filtering etc) */ | 1767 | /* Need to update the BSSID (for filtering etc) */ |
1674 | do_join = true; | 1768 | do_join = true; |
@@ -1676,8 +1770,21 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1676 | 1770 | ||
1677 | if (changed & BSS_CHANGED_ASSOC) { | 1771 | if (changed & BSS_CHANGED_ASSOC) { |
1678 | if (bss_conf->assoc) { | 1772 | if (bss_conf->assoc) { |
1773 | u32 rates; | ||
1679 | wl->aid = bss_conf->aid; | 1774 | wl->aid = bss_conf->aid; |
1680 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1775 | set_assoc = true; |
1776 | |||
1777 | /* | ||
1778 | * use basic rates from AP, and determine lowest rate | ||
1779 | * to use with control frames. | ||
1780 | */ | ||
1781 | rates = bss_conf->basic_rates; | ||
1782 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | ||
1783 | rates); | ||
1784 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1785 | ret = wl1271_acx_rate_policies(wl); | ||
1786 | if (ret < 0) | ||
1787 | goto out_sleep; | ||
1681 | 1788 | ||
1682 | /* | 1789 | /* |
1683 | * with wl1271, we don't need to update the | 1790 | * with wl1271, we don't need to update the |
@@ -1689,7 +1796,17 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1689 | if (ret < 0) | 1796 | if (ret < 0) |
1690 | goto out_sleep; | 1797 | goto out_sleep; |
1691 | 1798 | ||
1692 | ret = wl1271_acx_aid(wl, wl->aid); | 1799 | /* |
1800 | * The SSID is intentionally set to NULL here - the | ||
1801 | * firmware will set the probe request with a | ||
1802 | * broadcast SSID regardless of what we set in the | ||
1803 | * template. | ||
1804 | */ | ||
1805 | ret = wl1271_cmd_build_probe_req(wl, NULL, 0, | ||
1806 | NULL, 0, wl->band); | ||
1807 | |||
1808 | /* enable the connection monitoring feature */ | ||
1809 | ret = wl1271_acx_conn_monit_params(wl, true); | ||
1693 | if (ret < 0) | 1810 | if (ret < 0) |
1694 | goto out_sleep; | 1811 | goto out_sleep; |
1695 | 1812 | ||
@@ -1705,6 +1822,22 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1705 | /* use defaults when not associated */ | 1822 | /* use defaults when not associated */ |
1706 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1823 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1707 | wl->aid = 0; | 1824 | wl->aid = 0; |
1825 | |||
1826 | /* revert back to minimum rates for the current band */ | ||
1827 | wl1271_set_band_rate(wl); | ||
1828 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1829 | ret = wl1271_acx_rate_policies(wl); | ||
1830 | if (ret < 0) | ||
1831 | goto out_sleep; | ||
1832 | |||
1833 | /* disable connection monitor features */ | ||
1834 | ret = wl1271_acx_conn_monit_params(wl, false); | ||
1835 | |||
1836 | /* Disable the keep-alive feature */ | ||
1837 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
1838 | |||
1839 | if (ret < 0) | ||
1840 | goto out_sleep; | ||
1708 | } | 1841 | } |
1709 | 1842 | ||
1710 | } | 1843 | } |
@@ -1739,12 +1872,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1739 | } | 1872 | } |
1740 | 1873 | ||
1741 | if (do_join) { | 1874 | if (do_join) { |
1742 | ret = wl1271_cmd_join(wl); | 1875 | ret = wl1271_join(wl, set_assoc); |
1743 | if (ret < 0) { | 1876 | if (ret < 0) { |
1744 | wl1271_warning("cmd join failed %d", ret); | 1877 | wl1271_warning("cmd join failed %d", ret); |
1745 | goto out_sleep; | 1878 | goto out_sleep; |
1746 | } | 1879 | } |
1747 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1748 | } | 1880 | } |
1749 | 1881 | ||
1750 | out_sleep: | 1882 | out_sleep: |
@@ -1758,6 +1890,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1758 | const struct ieee80211_tx_queue_params *params) | 1890 | const struct ieee80211_tx_queue_params *params) |
1759 | { | 1891 | { |
1760 | struct wl1271 *wl = hw->priv; | 1892 | struct wl1271 *wl = hw->priv; |
1893 | u8 ps_scheme; | ||
1761 | int ret; | 1894 | int ret; |
1762 | 1895 | ||
1763 | mutex_lock(&wl->mutex); | 1896 | mutex_lock(&wl->mutex); |
@@ -1768,17 +1901,22 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1768 | if (ret < 0) | 1901 | if (ret < 0) |
1769 | goto out; | 1902 | goto out; |
1770 | 1903 | ||
1904 | /* the txop is confed in units of 32us by the mac80211, we need us */ | ||
1771 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | 1905 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), |
1772 | params->cw_min, params->cw_max, | 1906 | params->cw_min, params->cw_max, |
1773 | params->aifs, params->txop); | 1907 | params->aifs, params->txop << 5); |
1774 | if (ret < 0) | 1908 | if (ret < 0) |
1775 | goto out_sleep; | 1909 | goto out_sleep; |
1776 | 1910 | ||
1911 | if (params->uapsd) | ||
1912 | ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER; | ||
1913 | else | ||
1914 | ps_scheme = CONF_PS_SCHEME_LEGACY; | ||
1915 | |||
1777 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | 1916 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), |
1778 | CONF_CHANNEL_TYPE_EDCF, | 1917 | CONF_CHANNEL_TYPE_EDCF, |
1779 | wl1271_tx_get_queue(queue), | 1918 | wl1271_tx_get_queue(queue), |
1780 | CONF_PS_SCHEME_LEGACY_PSPOLL, | 1919 | ps_scheme, CONF_ACK_POLICY_LEGACY, 0, 0); |
1781 | CONF_ACK_POLICY_LEGACY, 0, 0); | ||
1782 | if (ret < 0) | 1920 | if (ret < 0) |
1783 | goto out_sleep; | 1921 | goto out_sleep; |
1784 | 1922 | ||
@@ -1852,6 +1990,36 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
1852 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, | 1990 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
1853 | }; | 1991 | }; |
1854 | 1992 | ||
1993 | /* mapping to indexes for wl1271_rates */ | ||
1994 | const static u8 wl1271_rate_to_idx_2ghz[] = { | ||
1995 | /* MCS rates are used only with 11n */ | ||
1996 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
1997 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
1998 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
1999 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
2000 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
2001 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
2002 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
2003 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
2004 | |||
2005 | 11, /* CONF_HW_RXTX_RATE_54 */ | ||
2006 | 10, /* CONF_HW_RXTX_RATE_48 */ | ||
2007 | 9, /* CONF_HW_RXTX_RATE_36 */ | ||
2008 | 8, /* CONF_HW_RXTX_RATE_24 */ | ||
2009 | |||
2010 | /* TI-specific rate */ | ||
2011 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
2012 | |||
2013 | 7, /* CONF_HW_RXTX_RATE_18 */ | ||
2014 | 6, /* CONF_HW_RXTX_RATE_12 */ | ||
2015 | 3, /* CONF_HW_RXTX_RATE_11 */ | ||
2016 | 5, /* CONF_HW_RXTX_RATE_9 */ | ||
2017 | 4, /* CONF_HW_RXTX_RATE_6 */ | ||
2018 | 2, /* CONF_HW_RXTX_RATE_5_5 */ | ||
2019 | 1, /* CONF_HW_RXTX_RATE_2 */ | ||
2020 | 0 /* CONF_HW_RXTX_RATE_1 */ | ||
2021 | }; | ||
2022 | |||
1855 | /* can't be const, mac80211 writes to this */ | 2023 | /* can't be const, mac80211 writes to this */ |
1856 | static struct ieee80211_supported_band wl1271_band_2ghz = { | 2024 | static struct ieee80211_supported_band wl1271_band_2ghz = { |
1857 | .channels = wl1271_channels, | 2025 | .channels = wl1271_channels, |
@@ -1934,6 +2102,35 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { | |||
1934 | { .hw_value = 165, .center_freq = 5825}, | 2102 | { .hw_value = 165, .center_freq = 5825}, |
1935 | }; | 2103 | }; |
1936 | 2104 | ||
2105 | /* mapping to indexes for wl1271_rates_5ghz */ | ||
2106 | const static u8 wl1271_rate_to_idx_5ghz[] = { | ||
2107 | /* MCS rates are used only with 11n */ | ||
2108 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
2109 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
2110 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
2111 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
2112 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
2113 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
2114 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
2115 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
2116 | |||
2117 | 7, /* CONF_HW_RXTX_RATE_54 */ | ||
2118 | 6, /* CONF_HW_RXTX_RATE_48 */ | ||
2119 | 5, /* CONF_HW_RXTX_RATE_36 */ | ||
2120 | 4, /* CONF_HW_RXTX_RATE_24 */ | ||
2121 | |||
2122 | /* TI-specific rate */ | ||
2123 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
2124 | |||
2125 | 3, /* CONF_HW_RXTX_RATE_18 */ | ||
2126 | 2, /* CONF_HW_RXTX_RATE_12 */ | ||
2127 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_11 */ | ||
2128 | 1, /* CONF_HW_RXTX_RATE_9 */ | ||
2129 | 0, /* CONF_HW_RXTX_RATE_6 */ | ||
2130 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_5_5 */ | ||
2131 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_2 */ | ||
2132 | CONF_HW_RXTX_RATE_UNSUPPORTED /* CONF_HW_RXTX_RATE_1 */ | ||
2133 | }; | ||
1937 | 2134 | ||
1938 | static struct ieee80211_supported_band wl1271_band_5ghz = { | 2135 | static struct ieee80211_supported_band wl1271_band_5ghz = { |
1939 | .channels = wl1271_channels_5ghz, | 2136 | .channels = wl1271_channels_5ghz, |
@@ -1942,13 +2139,17 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { | |||
1942 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), | 2139 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), |
1943 | }; | 2140 | }; |
1944 | 2141 | ||
2142 | const static u8 *wl1271_band_rate_to_idx[] = { | ||
2143 | [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz, | ||
2144 | [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz | ||
2145 | }; | ||
2146 | |||
1945 | static const struct ieee80211_ops wl1271_ops = { | 2147 | static const struct ieee80211_ops wl1271_ops = { |
1946 | .start = wl1271_op_start, | 2148 | .start = wl1271_op_start, |
1947 | .stop = wl1271_op_stop, | 2149 | .stop = wl1271_op_stop, |
1948 | .add_interface = wl1271_op_add_interface, | 2150 | .add_interface = wl1271_op_add_interface, |
1949 | .remove_interface = wl1271_op_remove_interface, | 2151 | .remove_interface = wl1271_op_remove_interface, |
1950 | .config = wl1271_op_config, | 2152 | .config = wl1271_op_config, |
1951 | /* .config_interface = wl1271_op_config_interface, */ | ||
1952 | .prepare_multicast = wl1271_op_prepare_multicast, | 2153 | .prepare_multicast = wl1271_op_prepare_multicast, |
1953 | .configure_filter = wl1271_op_configure_filter, | 2154 | .configure_filter = wl1271_op_configure_filter, |
1954 | .tx = wl1271_op_tx, | 2155 | .tx = wl1271_op_tx, |
@@ -1960,7 +2161,113 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1960 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 2161 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
1961 | }; | 2162 | }; |
1962 | 2163 | ||
1963 | static int wl1271_register_hw(struct wl1271 *wl) | 2164 | |
2165 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate) | ||
2166 | { | ||
2167 | u8 idx; | ||
2168 | |||
2169 | BUG_ON(wl->band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); | ||
2170 | |||
2171 | if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { | ||
2172 | wl1271_error("Illegal RX rate from HW: %d", rate); | ||
2173 | return 0; | ||
2174 | } | ||
2175 | |||
2176 | idx = wl1271_band_rate_to_idx[wl->band][rate]; | ||
2177 | if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { | ||
2178 | wl1271_error("Unsupported RX rate from HW: %d", rate); | ||
2179 | return 0; | ||
2180 | } | ||
2181 | |||
2182 | return idx; | ||
2183 | } | ||
2184 | |||
2185 | static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, | ||
2186 | struct device_attribute *attr, | ||
2187 | char *buf) | ||
2188 | { | ||
2189 | struct wl1271 *wl = dev_get_drvdata(dev); | ||
2190 | ssize_t len; | ||
2191 | |||
2192 | /* FIXME: what's the maximum length of buf? page size?*/ | ||
2193 | len = 500; | ||
2194 | |||
2195 | mutex_lock(&wl->mutex); | ||
2196 | len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n", | ||
2197 | wl->sg_enabled); | ||
2198 | mutex_unlock(&wl->mutex); | ||
2199 | |||
2200 | return len; | ||
2201 | |||
2202 | } | ||
2203 | |||
2204 | static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, | ||
2205 | struct device_attribute *attr, | ||
2206 | const char *buf, size_t count) | ||
2207 | { | ||
2208 | struct wl1271 *wl = dev_get_drvdata(dev); | ||
2209 | unsigned long res; | ||
2210 | int ret; | ||
2211 | |||
2212 | ret = strict_strtoul(buf, 10, &res); | ||
2213 | |||
2214 | if (ret < 0) { | ||
2215 | wl1271_warning("incorrect value written to bt_coex_mode"); | ||
2216 | return count; | ||
2217 | } | ||
2218 | |||
2219 | mutex_lock(&wl->mutex); | ||
2220 | |||
2221 | res = !!res; | ||
2222 | |||
2223 | if (res == wl->sg_enabled) | ||
2224 | goto out; | ||
2225 | |||
2226 | wl->sg_enabled = res; | ||
2227 | |||
2228 | if (wl->state == WL1271_STATE_OFF) | ||
2229 | goto out; | ||
2230 | |||
2231 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
2232 | if (ret < 0) | ||
2233 | goto out; | ||
2234 | |||
2235 | wl1271_acx_sg_enable(wl, wl->sg_enabled); | ||
2236 | wl1271_ps_elp_sleep(wl); | ||
2237 | |||
2238 | out: | ||
2239 | mutex_unlock(&wl->mutex); | ||
2240 | return count; | ||
2241 | } | ||
2242 | |||
2243 | static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR, | ||
2244 | wl1271_sysfs_show_bt_coex_state, | ||
2245 | wl1271_sysfs_store_bt_coex_state); | ||
2246 | |||
2247 | static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev, | ||
2248 | struct device_attribute *attr, | ||
2249 | char *buf) | ||
2250 | { | ||
2251 | struct wl1271 *wl = dev_get_drvdata(dev); | ||
2252 | ssize_t len; | ||
2253 | |||
2254 | /* FIXME: what's the maximum length of buf? page size?*/ | ||
2255 | len = 500; | ||
2256 | |||
2257 | mutex_lock(&wl->mutex); | ||
2258 | if (wl->hw_pg_ver >= 0) | ||
2259 | len = snprintf(buf, len, "%d\n", wl->hw_pg_ver); | ||
2260 | else | ||
2261 | len = snprintf(buf, len, "n/a\n"); | ||
2262 | mutex_unlock(&wl->mutex); | ||
2263 | |||
2264 | return len; | ||
2265 | } | ||
2266 | |||
2267 | static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR, | ||
2268 | wl1271_sysfs_show_hw_pg_ver, NULL); | ||
2269 | |||
2270 | int wl1271_register_hw(struct wl1271 *wl) | ||
1964 | { | 2271 | { |
1965 | int ret; | 2272 | int ret; |
1966 | 2273 | ||
@@ -1981,8 +2288,17 @@ static int wl1271_register_hw(struct wl1271 *wl) | |||
1981 | 2288 | ||
1982 | return 0; | 2289 | return 0; |
1983 | } | 2290 | } |
2291 | EXPORT_SYMBOL_GPL(wl1271_register_hw); | ||
2292 | |||
2293 | void wl1271_unregister_hw(struct wl1271 *wl) | ||
2294 | { | ||
2295 | ieee80211_unregister_hw(wl->hw); | ||
2296 | wl->mac80211_registered = false; | ||
2297 | |||
2298 | } | ||
2299 | EXPORT_SYMBOL_GPL(wl1271_unregister_hw); | ||
1984 | 2300 | ||
1985 | static int wl1271_init_ieee80211(struct wl1271 *wl) | 2301 | int wl1271_init_ieee80211(struct wl1271 *wl) |
1986 | { | 2302 | { |
1987 | /* The tx descriptor buffer and the TKIP space. */ | 2303 | /* The tx descriptor buffer and the TKIP space. */ |
1988 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + | 2304 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + |
@@ -1991,11 +2307,15 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
1991 | /* unit us */ | 2307 | /* unit us */ |
1992 | /* FIXME: find a proper value */ | 2308 | /* FIXME: find a proper value */ |
1993 | wl->hw->channel_change_time = 10000; | 2309 | wl->hw->channel_change_time = 10000; |
2310 | wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval; | ||
1994 | 2311 | ||
1995 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 2312 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1996 | IEEE80211_HW_NOISE_DBM | | ||
1997 | IEEE80211_HW_BEACON_FILTER | | 2313 | IEEE80211_HW_BEACON_FILTER | |
1998 | IEEE80211_HW_SUPPORTS_PS; | 2314 | IEEE80211_HW_SUPPORTS_PS | |
2315 | IEEE80211_HW_SUPPORTS_UAPSD | | ||
2316 | IEEE80211_HW_HAS_RATE_CONTROL | | ||
2317 | IEEE80211_HW_CONNECTION_MONITOR | | ||
2318 | IEEE80211_HW_SUPPORTS_CQM_RSSI; | ||
1999 | 2319 | ||
2000 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 2320 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2001 | BIT(NL80211_IFTYPE_ADHOC); | 2321 | BIT(NL80211_IFTYPE_ADHOC); |
@@ -2005,51 +2325,53 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2005 | if (wl1271_11a_enabled()) | 2325 | if (wl1271_11a_enabled()) |
2006 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | 2326 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; |
2007 | 2327 | ||
2008 | SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); | 2328 | wl->hw->queues = 4; |
2329 | wl->hw->max_rates = 1; | ||
2009 | 2330 | ||
2010 | return 0; | 2331 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); |
2011 | } | ||
2012 | |||
2013 | static void wl1271_device_release(struct device *dev) | ||
2014 | { | ||
2015 | 2332 | ||
2333 | return 0; | ||
2016 | } | 2334 | } |
2017 | 2335 | EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); | |
2018 | static struct platform_device wl1271_device = { | ||
2019 | .name = "wl1271", | ||
2020 | .id = -1, | ||
2021 | |||
2022 | /* device model insists to have a release function */ | ||
2023 | .dev = { | ||
2024 | .release = wl1271_device_release, | ||
2025 | }, | ||
2026 | }; | ||
2027 | 2336 | ||
2028 | #define WL1271_DEFAULT_CHANNEL 0 | 2337 | #define WL1271_DEFAULT_CHANNEL 0 |
2029 | 2338 | ||
2030 | static struct ieee80211_hw *wl1271_alloc_hw(void) | 2339 | struct ieee80211_hw *wl1271_alloc_hw(void) |
2031 | { | 2340 | { |
2032 | struct ieee80211_hw *hw; | 2341 | struct ieee80211_hw *hw; |
2342 | struct platform_device *plat_dev = NULL; | ||
2033 | struct wl1271 *wl; | 2343 | struct wl1271 *wl; |
2034 | int i; | 2344 | int i, ret; |
2035 | 2345 | ||
2036 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2346 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
2037 | if (!hw) { | 2347 | if (!hw) { |
2038 | wl1271_error("could not alloc ieee80211_hw"); | 2348 | wl1271_error("could not alloc ieee80211_hw"); |
2039 | return ERR_PTR(-ENOMEM); | 2349 | ret = -ENOMEM; |
2350 | goto err_hw_alloc; | ||
2351 | } | ||
2352 | |||
2353 | plat_dev = kmalloc(sizeof(wl1271_device), GFP_KERNEL); | ||
2354 | if (!plat_dev) { | ||
2355 | wl1271_error("could not allocate platform_device"); | ||
2356 | ret = -ENOMEM; | ||
2357 | goto err_plat_alloc; | ||
2040 | } | 2358 | } |
2041 | 2359 | ||
2360 | memcpy(plat_dev, &wl1271_device, sizeof(wl1271_device)); | ||
2361 | |||
2042 | wl = hw->priv; | 2362 | wl = hw->priv; |
2043 | memset(wl, 0, sizeof(*wl)); | 2363 | memset(wl, 0, sizeof(*wl)); |
2044 | 2364 | ||
2045 | INIT_LIST_HEAD(&wl->list); | 2365 | INIT_LIST_HEAD(&wl->list); |
2046 | 2366 | ||
2047 | wl->hw = hw; | 2367 | wl->hw = hw; |
2368 | wl->plat_dev = plat_dev; | ||
2048 | 2369 | ||
2049 | skb_queue_head_init(&wl->tx_queue); | 2370 | skb_queue_head_init(&wl->tx_queue); |
2050 | 2371 | ||
2051 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2372 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
2052 | wl->channel = WL1271_DEFAULT_CHANNEL; | 2373 | wl->channel = WL1271_DEFAULT_CHANNEL; |
2374 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | ||
2053 | wl->default_key = 0; | 2375 | wl->default_key = 0; |
2054 | wl->rx_counter = 0; | 2376 | wl->rx_counter = 0; |
2055 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 2377 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
@@ -2057,11 +2379,14 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2057 | wl->psm_entry_retry = 0; | 2379 | wl->psm_entry_retry = 0; |
2058 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 2380 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
2059 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; | 2381 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
2382 | wl->basic_rate = CONF_TX_RATE_MASK_BASIC; | ||
2060 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 2383 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
2061 | wl->sta_rate_set = 0; | 2384 | wl->sta_rate_set = 0; |
2062 | wl->band = IEEE80211_BAND_2GHZ; | 2385 | wl->band = IEEE80211_BAND_2GHZ; |
2063 | wl->vif = NULL; | 2386 | wl->vif = NULL; |
2064 | wl->flags = 0; | 2387 | wl->flags = 0; |
2388 | wl->sg_enabled = true; | ||
2389 | wl->hw_pg_ver = -1; | ||
2065 | 2390 | ||
2066 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 2391 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
2067 | wl->tx_frames[i] = NULL; | 2392 | wl->tx_frames[i] = NULL; |
@@ -2074,167 +2399,72 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2074 | /* Apply default driver configuration. */ | 2399 | /* Apply default driver configuration. */ |
2075 | wl1271_conf_init(wl); | 2400 | wl1271_conf_init(wl); |
2076 | 2401 | ||
2077 | return hw; | 2402 | wl1271_debugfs_init(wl); |
2078 | } | ||
2079 | |||
2080 | int wl1271_free_hw(struct wl1271 *wl) | ||
2081 | { | ||
2082 | ieee80211_unregister_hw(wl->hw); | ||
2083 | |||
2084 | wl1271_debugfs_exit(wl); | ||
2085 | |||
2086 | kfree(wl->target_mem_map); | ||
2087 | vfree(wl->fw); | ||
2088 | wl->fw = NULL; | ||
2089 | kfree(wl->nvs); | ||
2090 | wl->nvs = NULL; | ||
2091 | |||
2092 | kfree(wl->fw_status); | ||
2093 | kfree(wl->tx_res_if); | ||
2094 | |||
2095 | ieee80211_free_hw(wl->hw); | ||
2096 | |||
2097 | return 0; | ||
2098 | } | ||
2099 | |||
2100 | static int __devinit wl1271_probe(struct spi_device *spi) | ||
2101 | { | ||
2102 | struct wl12xx_platform_data *pdata; | ||
2103 | struct ieee80211_hw *hw; | ||
2104 | struct wl1271 *wl; | ||
2105 | int ret; | ||
2106 | 2403 | ||
2107 | pdata = spi->dev.platform_data; | 2404 | /* Register platform device */ |
2108 | if (!pdata) { | 2405 | ret = platform_device_register(wl->plat_dev); |
2109 | wl1271_error("no platform data"); | 2406 | if (ret) { |
2110 | return -ENODEV; | 2407 | wl1271_error("couldn't register platform device"); |
2408 | goto err_hw; | ||
2111 | } | 2409 | } |
2410 | dev_set_drvdata(&wl->plat_dev->dev, wl); | ||
2112 | 2411 | ||
2113 | hw = wl1271_alloc_hw(); | 2412 | /* Create sysfs file to control bt coex state */ |
2114 | if (IS_ERR(hw)) | 2413 | ret = device_create_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); |
2115 | return PTR_ERR(hw); | ||
2116 | |||
2117 | wl = hw->priv; | ||
2118 | |||
2119 | dev_set_drvdata(&spi->dev, wl); | ||
2120 | wl->spi = spi; | ||
2121 | |||
2122 | /* This is the only SPI value that we need to set here, the rest | ||
2123 | * comes from the board-peripherals file */ | ||
2124 | spi->bits_per_word = 32; | ||
2125 | |||
2126 | ret = spi_setup(spi); | ||
2127 | if (ret < 0) { | 2414 | if (ret < 0) { |
2128 | wl1271_error("spi_setup failed"); | 2415 | wl1271_error("failed to create sysfs file bt_coex_state"); |
2129 | goto out_free; | 2416 | goto err_platform; |
2130 | } | ||
2131 | |||
2132 | wl->set_power = pdata->set_power; | ||
2133 | if (!wl->set_power) { | ||
2134 | wl1271_error("set power function missing in platform data"); | ||
2135 | ret = -ENODEV; | ||
2136 | goto out_free; | ||
2137 | } | 2417 | } |
2138 | 2418 | ||
2139 | wl->irq = spi->irq; | 2419 | /* Create sysfs file to get HW PG version */ |
2140 | if (wl->irq < 0) { | 2420 | ret = device_create_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); |
2141 | wl1271_error("irq missing in platform data"); | ||
2142 | ret = -ENODEV; | ||
2143 | goto out_free; | ||
2144 | } | ||
2145 | |||
2146 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | ||
2147 | if (ret < 0) { | 2421 | if (ret < 0) { |
2148 | wl1271_error("request_irq() failed: %d", ret); | 2422 | wl1271_error("failed to create sysfs file hw_pg_ver"); |
2149 | goto out_free; | 2423 | goto err_bt_coex_state; |
2150 | } | ||
2151 | |||
2152 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
2153 | |||
2154 | disable_irq(wl->irq); | ||
2155 | |||
2156 | ret = platform_device_register(&wl1271_device); | ||
2157 | if (ret) { | ||
2158 | wl1271_error("couldn't register platform device"); | ||
2159 | goto out_irq; | ||
2160 | } | 2424 | } |
2161 | dev_set_drvdata(&wl1271_device.dev, wl); | ||
2162 | |||
2163 | ret = wl1271_init_ieee80211(wl); | ||
2164 | if (ret) | ||
2165 | goto out_platform; | ||
2166 | |||
2167 | ret = wl1271_register_hw(wl); | ||
2168 | if (ret) | ||
2169 | goto out_platform; | ||
2170 | |||
2171 | wl1271_debugfs_init(wl); | ||
2172 | 2425 | ||
2173 | wl1271_notice("initialized"); | 2426 | return hw; |
2174 | 2427 | ||
2175 | return 0; | 2428 | err_bt_coex_state: |
2429 | device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); | ||
2176 | 2430 | ||
2177 | out_platform: | 2431 | err_platform: |
2178 | platform_device_unregister(&wl1271_device); | 2432 | platform_device_unregister(wl->plat_dev); |
2179 | 2433 | ||
2180 | out_irq: | 2434 | err_hw: |
2181 | free_irq(wl->irq, wl); | 2435 | wl1271_debugfs_exit(wl); |
2436 | kfree(plat_dev); | ||
2182 | 2437 | ||
2183 | out_free: | 2438 | err_plat_alloc: |
2184 | ieee80211_free_hw(hw); | 2439 | ieee80211_free_hw(hw); |
2185 | 2440 | ||
2186 | return ret; | 2441 | err_hw_alloc: |
2187 | } | ||
2188 | |||
2189 | static int __devexit wl1271_remove(struct spi_device *spi) | ||
2190 | { | ||
2191 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | ||
2192 | 2442 | ||
2193 | platform_device_unregister(&wl1271_device); | 2443 | return ERR_PTR(ret); |
2194 | free_irq(wl->irq, wl); | ||
2195 | |||
2196 | wl1271_free_hw(wl); | ||
2197 | |||
2198 | return 0; | ||
2199 | } | 2444 | } |
2445 | EXPORT_SYMBOL_GPL(wl1271_alloc_hw); | ||
2200 | 2446 | ||
2201 | 2447 | int wl1271_free_hw(struct wl1271 *wl) | |
2202 | static struct spi_driver wl1271_spi_driver = { | ||
2203 | .driver = { | ||
2204 | .name = "wl1271", | ||
2205 | .bus = &spi_bus_type, | ||
2206 | .owner = THIS_MODULE, | ||
2207 | }, | ||
2208 | |||
2209 | .probe = wl1271_probe, | ||
2210 | .remove = __devexit_p(wl1271_remove), | ||
2211 | }; | ||
2212 | |||
2213 | static int __init wl1271_init(void) | ||
2214 | { | 2448 | { |
2215 | int ret; | 2449 | platform_device_unregister(wl->plat_dev); |
2450 | kfree(wl->plat_dev); | ||
2216 | 2451 | ||
2217 | ret = spi_register_driver(&wl1271_spi_driver); | 2452 | wl1271_debugfs_exit(wl); |
2218 | if (ret < 0) { | ||
2219 | wl1271_error("failed to register spi driver: %d", ret); | ||
2220 | goto out; | ||
2221 | } | ||
2222 | 2453 | ||
2223 | out: | 2454 | vfree(wl->fw); |
2224 | return ret; | 2455 | wl->fw = NULL; |
2225 | } | 2456 | kfree(wl->nvs); |
2457 | wl->nvs = NULL; | ||
2226 | 2458 | ||
2227 | static void __exit wl1271_exit(void) | 2459 | kfree(wl->fw_status); |
2228 | { | 2460 | kfree(wl->tx_res_if); |
2229 | spi_unregister_driver(&wl1271_spi_driver); | ||
2230 | 2461 | ||
2231 | wl1271_notice("unloaded"); | 2462 | ieee80211_free_hw(wl->hw); |
2232 | } | ||
2233 | 2463 | ||
2234 | module_init(wl1271_init); | 2464 | return 0; |
2235 | module_exit(wl1271_exit); | 2465 | } |
2466 | EXPORT_SYMBOL_GPL(wl1271_free_hw); | ||
2236 | 2467 | ||
2237 | MODULE_LICENSE("GPL"); | 2468 | MODULE_LICENSE("GPL"); |
2238 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | 2469 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); |
2239 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 2470 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
2240 | MODULE_FIRMWARE(WL1271_FW_NAME); | ||