diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 336 |
1 files changed, 84 insertions, 252 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 2a864b24291d..0a4ff7b02f59 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -22,22 +22,17 @@ | |||
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> |
36 | 32 | ||
37 | #include "wl1271.h" | 33 | #include "wl1271.h" |
38 | #include "wl12xx_80211.h" | 34 | #include "wl12xx_80211.h" |
39 | #include "wl1271_reg.h" | 35 | #include "wl1271_reg.h" |
40 | #include "wl1271_spi.h" | ||
41 | #include "wl1271_io.h" | 36 | #include "wl1271_io.h" |
42 | #include "wl1271_event.h" | 37 | #include "wl1271_event.h" |
43 | #include "wl1271_tx.h" | 38 | #include "wl1271_tx.h" |
@@ -364,11 +359,6 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
364 | return ret; | 359 | return ret; |
365 | } | 360 | } |
366 | 361 | ||
367 | static void wl1271_disable_interrupts(struct wl1271 *wl) | ||
368 | { | ||
369 | disable_irq(wl->irq); | ||
370 | } | ||
371 | |||
372 | static void wl1271_power_off(struct wl1271 *wl) | 362 | static void wl1271_power_off(struct wl1271 *wl) |
373 | { | 363 | { |
374 | wl->set_power(false); | 364 | wl->set_power(false); |
@@ -384,10 +374,11 @@ static void wl1271_power_on(struct wl1271 *wl) | |||
384 | static void wl1271_fw_status(struct wl1271 *wl, | 374 | static void wl1271_fw_status(struct wl1271 *wl, |
385 | struct wl1271_fw_status *status) | 375 | struct wl1271_fw_status *status) |
386 | { | 376 | { |
377 | struct timespec ts; | ||
387 | u32 total = 0; | 378 | u32 total = 0; |
388 | int i; | 379 | int i; |
389 | 380 | ||
390 | wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); | 381 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); |
391 | 382 | ||
392 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 383 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
393 | "drv_rx_counter = %d, tx_results_counter = %d)", | 384 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -412,14 +403,19 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
412 | ieee80211_queue_work(wl->hw, &wl->tx_work); | 403 | ieee80211_queue_work(wl->hw, &wl->tx_work); |
413 | 404 | ||
414 | /* update the host-chipset time offset */ | 405 | /* update the host-chipset time offset */ |
415 | wl->time_offset = jiffies_to_usecs(jiffies) - | 406 | getnstimeofday(&ts); |
416 | le32_to_cpu(status->fw_localtime); | 407 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
408 | (s64)le32_to_cpu(status->fw_localtime); | ||
417 | } | 409 | } |
418 | 410 | ||
411 | #define WL1271_IRQ_MAX_LOOPS 10 | ||
412 | |||
419 | static void wl1271_irq_work(struct work_struct *work) | 413 | static void wl1271_irq_work(struct work_struct *work) |
420 | { | 414 | { |
421 | int ret; | 415 | int ret; |
422 | u32 intr; | 416 | u32 intr; |
417 | int loopcount = WL1271_IRQ_MAX_LOOPS; | ||
418 | unsigned long flags; | ||
423 | struct wl1271 *wl = | 419 | struct wl1271 *wl = |
424 | container_of(work, struct wl1271, irq_work); | 420 | container_of(work, struct wl1271, irq_work); |
425 | 421 | ||
@@ -427,91 +423,77 @@ static void wl1271_irq_work(struct work_struct *work) | |||
427 | 423 | ||
428 | wl1271_debug(DEBUG_IRQ, "IRQ work"); | 424 | wl1271_debug(DEBUG_IRQ, "IRQ work"); |
429 | 425 | ||
430 | if (wl->state == WL1271_STATE_OFF) | 426 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
431 | goto out; | 427 | goto out; |
432 | 428 | ||
433 | ret = wl1271_ps_elp_wakeup(wl, true); | 429 | ret = wl1271_ps_elp_wakeup(wl, true); |
434 | if (ret < 0) | 430 | if (ret < 0) |
435 | goto out; | 431 | goto out; |
436 | 432 | ||
437 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 433 | spin_lock_irqsave(&wl->wl_lock, flags); |
438 | 434 | while (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags) && loopcount) { | |
439 | wl1271_fw_status(wl, wl->fw_status); | 435 | clear_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags); |
440 | intr = le32_to_cpu(wl->fw_status->intr); | 436 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
441 | if (!intr) { | 437 | loopcount--; |
442 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); | 438 | |
443 | goto out_sleep; | 439 | wl1271_fw_status(wl, wl->fw_status); |
444 | } | 440 | intr = le32_to_cpu(wl->fw_status->intr); |
441 | if (!intr) { | ||
442 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); | ||
443 | continue; | ||
444 | } | ||
445 | 445 | ||
446 | intr &= WL1271_INTR_MASK; | 446 | intr &= WL1271_INTR_MASK; |
447 | 447 | ||
448 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 448 | if (intr & WL1271_ACX_INTR_DATA) { |
449 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 449 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); |
450 | wl1271_event_handle(wl, 0); | ||
451 | } | ||
452 | 450 | ||
453 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 451 | /* check for tx results */ |
454 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 452 | if (wl->fw_status->tx_results_counter != |
455 | wl1271_event_handle(wl, 1); | 453 | (wl->tx_results_count & 0xff)) |
456 | } | 454 | wl1271_tx_complete(wl); |
457 | 455 | ||
458 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 456 | wl1271_rx(wl, wl->fw_status); |
459 | wl1271_debug(DEBUG_IRQ, | 457 | } |
460 | "WL1271_ACX_INTR_INIT_COMPLETE"); | ||
461 | 458 | ||
462 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) | 459 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
463 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); | 460 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
461 | wl1271_event_handle(wl, 0); | ||
462 | } | ||
464 | 463 | ||
465 | if (intr & WL1271_ACX_INTR_DATA) { | 464 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
466 | u8 tx_res_cnt = wl->fw_status->tx_results_counter - | 465 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
467 | wl->tx_results_count; | 466 | wl1271_event_handle(wl, 1); |
467 | } | ||
468 | 468 | ||
469 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); | 469 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
470 | wl1271_debug(DEBUG_IRQ, | ||
471 | "WL1271_ACX_INTR_INIT_COMPLETE"); | ||
470 | 472 | ||
471 | /* check for tx results */ | 473 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) |
472 | if (tx_res_cnt) | 474 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); |
473 | wl1271_tx_complete(wl, tx_res_cnt); | ||
474 | 475 | ||
475 | wl1271_rx(wl, wl->fw_status); | 476 | spin_lock_irqsave(&wl->wl_lock, flags); |
476 | } | 477 | } |
477 | 478 | ||
478 | out_sleep: | 479 | if (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags)) |
479 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, | 480 | ieee80211_queue_work(wl->hw, &wl->irq_work); |
480 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 481 | else |
482 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | ||
483 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
484 | |||
481 | wl1271_ps_elp_sleep(wl); | 485 | wl1271_ps_elp_sleep(wl); |
482 | 486 | ||
483 | out: | 487 | out: |
484 | mutex_unlock(&wl->mutex); | 488 | mutex_unlock(&wl->mutex); |
485 | } | 489 | } |
486 | 490 | ||
487 | static irqreturn_t wl1271_irq(int irq, void *cookie) | ||
488 | { | ||
489 | struct wl1271 *wl; | ||
490 | unsigned long flags; | ||
491 | |||
492 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
493 | |||
494 | wl = cookie; | ||
495 | |||
496 | /* complete the ELP completion */ | ||
497 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
498 | if (wl->elp_compl) { | ||
499 | complete(wl->elp_compl); | ||
500 | wl->elp_compl = NULL; | ||
501 | } | ||
502 | |||
503 | ieee80211_queue_work(wl->hw, &wl->irq_work); | ||
504 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
505 | |||
506 | return IRQ_HANDLED; | ||
507 | } | ||
508 | |||
509 | static int wl1271_fetch_firmware(struct wl1271 *wl) | 491 | static int wl1271_fetch_firmware(struct wl1271 *wl) |
510 | { | 492 | { |
511 | const struct firmware *fw; | 493 | const struct firmware *fw; |
512 | int ret; | 494 | int ret; |
513 | 495 | ||
514 | ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev); | 496 | ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); |
515 | 497 | ||
516 | if (ret < 0) { | 498 | if (ret < 0) { |
517 | wl1271_error("could not get firmware: %d", ret); | 499 | wl1271_error("could not get firmware: %d", ret); |
@@ -583,7 +565,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
583 | const struct firmware *fw; | 565 | const struct firmware *fw; |
584 | int ret; | 566 | int ret; |
585 | 567 | ||
586 | ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev); | 568 | ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); |
587 | 569 | ||
588 | if (ret < 0) { | 570 | if (ret < 0) { |
589 | wl1271_error("could not get nvs file: %d", ret); | 571 | wl1271_error("could not get nvs file: %d", ret); |
@@ -825,15 +807,13 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
825 | * The workqueue is slow to process the tx_queue and we need stop | 807 | * The workqueue is slow to process the tx_queue and we need stop |
826 | * the queue here, otherwise the queue will get too long. | 808 | * the queue here, otherwise the queue will get too long. |
827 | */ | 809 | */ |
828 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) { | 810 | if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_HIGH_WATERMARK) { |
829 | ieee80211_stop_queues(wl->hw); | 811 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); |
830 | 812 | ||
831 | /* | 813 | spin_lock_irqsave(&wl->wl_lock, flags); |
832 | * FIXME: this is racy, the variable is not properly | 814 | ieee80211_stop_queues(wl->hw); |
833 | * protected. Maybe fix this by removing the stupid | ||
834 | * variable altogether and checking the real queue state? | ||
835 | */ | ||
836 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | 815 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
816 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
837 | } | 817 | } |
838 | 818 | ||
839 | return NETDEV_TX_OK; | 819 | return NETDEV_TX_OK; |
@@ -1040,8 +1020,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1040 | wl->tx_results_count = 0; | 1020 | wl->tx_results_count = 0; |
1041 | wl->tx_packets_count = 0; | 1021 | wl->tx_packets_count = 0; |
1042 | wl->tx_security_last_seq = 0; | 1022 | wl->tx_security_last_seq = 0; |
1043 | wl->tx_security_seq_16 = 0; | 1023 | wl->tx_security_seq = 0; |
1044 | wl->tx_security_seq_32 = 0; | ||
1045 | wl->time_offset = 0; | 1024 | wl->time_offset = 0; |
1046 | wl->session_counter = 0; | 1025 | wl->session_counter = 0; |
1047 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1026 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
@@ -1127,7 +1106,7 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw, | |||
1127 | 1106 | ||
1128 | memcpy(wl->bssid, conf->bssid, ETH_ALEN); | 1107 | memcpy(wl->bssid, conf->bssid, ETH_ALEN); |
1129 | 1108 | ||
1130 | ret = wl1271_cmd_join(wl); | 1109 | ret = wl1271_cmd_join(wl, wl->bss_type); |
1131 | if (ret < 0) | 1110 | if (ret < 0) |
1132 | goto out_sleep; | 1111 | goto out_sleep; |
1133 | 1112 | ||
@@ -1176,17 +1155,16 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel) | |||
1176 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | 1155 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, |
1177 | 0xad, 0xbe, 0xef }; | 1156 | 0xad, 0xbe, 0xef }; |
1178 | 1157 | ||
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 */ | 1158 | /* disable mac filter, so we hear everything */ |
1184 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | 1159 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; |
1185 | 1160 | ||
1186 | wl->channel = channel; | 1161 | wl->channel = channel; |
1187 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | 1162 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); |
1188 | 1163 | ||
1189 | ret = wl1271_cmd_join(wl); | 1164 | /* the dummy join is performed always with STATION BSS type to allow |
1165 | also ad-hoc mode to listen to the surroundings without sending any | ||
1166 | beacons yet. */ | ||
1167 | ret = wl1271_cmd_join(wl, BSS_TYPE_STA_BSS); | ||
1190 | if (ret < 0) | 1168 | if (ret < 0) |
1191 | goto out; | 1169 | goto out; |
1192 | 1170 | ||
@@ -1255,7 +1233,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1255 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | 1233 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { |
1256 | wl->channel = channel; | 1234 | wl->channel = channel; |
1257 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ | 1235 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ |
1258 | ret = wl1271_cmd_join(wl); | 1236 | ret = wl1271_cmd_join(wl, wl->bss_type); |
1259 | if (ret < 0) | 1237 | if (ret < 0) |
1260 | wl1271_warning("cmd join to update channel failed %d", | 1238 | wl1271_warning("cmd join to update channel failed %d", |
1261 | ret); | 1239 | ret); |
@@ -1272,13 +1250,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1272 | * through the bss_info_changed() hook. | 1250 | * through the bss_info_changed() hook. |
1273 | */ | 1251 | */ |
1274 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | 1252 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1275 | wl1271_info("psm enabled"); | 1253 | wl1271_debug(DEBUG_PSM, "psm enabled"); |
1276 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 1254 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
1277 | true); | 1255 | true); |
1278 | } | 1256 | } |
1279 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1257 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1280 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1258 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1281 | wl1271_info("psm disabled"); | 1259 | wl1271_debug(DEBUG_PSM, "psm disabled"); |
1282 | 1260 | ||
1283 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1261 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
1284 | 1262 | ||
@@ -1449,15 +1427,15 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1449 | key_type = KEY_TKIP; | 1427 | key_type = KEY_TKIP; |
1450 | 1428 | ||
1451 | key_conf->hw_key_idx = key_conf->keyidx; | 1429 | key_conf->hw_key_idx = key_conf->keyidx; |
1452 | tx_seq_32 = wl->tx_security_seq_32; | 1430 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1453 | tx_seq_16 = wl->tx_security_seq_16; | 1431 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1454 | break; | 1432 | break; |
1455 | case ALG_CCMP: | 1433 | case ALG_CCMP: |
1456 | key_type = KEY_AES; | 1434 | key_type = KEY_AES; |
1457 | 1435 | ||
1458 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1436 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1459 | tx_seq_32 = wl->tx_security_seq_32; | 1437 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1460 | tx_seq_16 = wl->tx_security_seq_16; | 1438 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1461 | break; | 1439 | break; |
1462 | default: | 1440 | default: |
1463 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); | 1441 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); |
@@ -1738,7 +1716,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1738 | } | 1716 | } |
1739 | 1717 | ||
1740 | if (do_join) { | 1718 | if (do_join) { |
1741 | ret = wl1271_cmd_join(wl); | 1719 | ret = wl1271_cmd_join(wl, wl->bss_type); |
1742 | if (ret < 0) { | 1720 | if (ret < 0) { |
1743 | wl1271_warning("cmd join failed %d", ret); | 1721 | wl1271_warning("cmd join failed %d", ret); |
1744 | goto out_sleep; | 1722 | goto out_sleep; |
@@ -1959,7 +1937,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1959 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 1937 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
1960 | }; | 1938 | }; |
1961 | 1939 | ||
1962 | static int wl1271_register_hw(struct wl1271 *wl) | 1940 | int wl1271_register_hw(struct wl1271 *wl) |
1963 | { | 1941 | { |
1964 | int ret; | 1942 | int ret; |
1965 | 1943 | ||
@@ -1980,8 +1958,9 @@ static int wl1271_register_hw(struct wl1271 *wl) | |||
1980 | 1958 | ||
1981 | return 0; | 1959 | return 0; |
1982 | } | 1960 | } |
1961 | EXPORT_SYMBOL_GPL(wl1271_register_hw); | ||
1983 | 1962 | ||
1984 | static int wl1271_init_ieee80211(struct wl1271 *wl) | 1963 | int wl1271_init_ieee80211(struct wl1271 *wl) |
1985 | { | 1964 | { |
1986 | /* The tx descriptor buffer and the TKIP space. */ | 1965 | /* The tx descriptor buffer and the TKIP space. */ |
1987 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + | 1966 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + |
@@ -1994,7 +1973,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
1994 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 1973 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1995 | IEEE80211_HW_NOISE_DBM | | 1974 | IEEE80211_HW_NOISE_DBM | |
1996 | IEEE80211_HW_BEACON_FILTER | | 1975 | IEEE80211_HW_BEACON_FILTER | |
1997 | IEEE80211_HW_SUPPORTS_PS; | 1976 | IEEE80211_HW_SUPPORTS_PS | |
1977 | IEEE80211_HW_HAS_RATE_CONTROL; | ||
1998 | 1978 | ||
1999 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 1979 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2000 | BIT(NL80211_IFTYPE_ADHOC); | 1980 | BIT(NL80211_IFTYPE_ADHOC); |
@@ -2004,29 +1984,15 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2004 | if (wl1271_11a_enabled()) | 1984 | if (wl1271_11a_enabled()) |
2005 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | 1985 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; |
2006 | 1986 | ||
2007 | SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); | 1987 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); |
2008 | 1988 | ||
2009 | return 0; | 1989 | return 0; |
2010 | } | 1990 | } |
2011 | 1991 | EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); | |
2012 | static void wl1271_device_release(struct device *dev) | ||
2013 | { | ||
2014 | |||
2015 | } | ||
2016 | |||
2017 | static struct platform_device wl1271_device = { | ||
2018 | .name = "wl1271", | ||
2019 | .id = -1, | ||
2020 | |||
2021 | /* device model insists to have a release function */ | ||
2022 | .dev = { | ||
2023 | .release = wl1271_device_release, | ||
2024 | }, | ||
2025 | }; | ||
2026 | 1992 | ||
2027 | #define WL1271_DEFAULT_CHANNEL 0 | 1993 | #define WL1271_DEFAULT_CHANNEL 0 |
2028 | 1994 | ||
2029 | static struct ieee80211_hw *wl1271_alloc_hw(void) | 1995 | struct ieee80211_hw *wl1271_alloc_hw(void) |
2030 | { | 1996 | { |
2031 | struct ieee80211_hw *hw; | 1997 | struct ieee80211_hw *hw; |
2032 | struct wl1271 *wl; | 1998 | struct wl1271 *wl; |
@@ -2073,8 +2039,11 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2073 | /* Apply default driver configuration. */ | 2039 | /* Apply default driver configuration. */ |
2074 | wl1271_conf_init(wl); | 2040 | wl1271_conf_init(wl); |
2075 | 2041 | ||
2042 | wl1271_debugfs_init(wl); | ||
2043 | |||
2076 | return hw; | 2044 | return hw; |
2077 | } | 2045 | } |
2046 | EXPORT_SYMBOL_GPL(wl1271_alloc_hw); | ||
2078 | 2047 | ||
2079 | int wl1271_free_hw(struct wl1271 *wl) | 2048 | int wl1271_free_hw(struct wl1271 *wl) |
2080 | { | 2049 | { |
@@ -2095,145 +2064,8 @@ int wl1271_free_hw(struct wl1271 *wl) | |||
2095 | 2064 | ||
2096 | return 0; | 2065 | return 0; |
2097 | } | 2066 | } |
2098 | 2067 | EXPORT_SYMBOL_GPL(wl1271_free_hw); | |
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 | |||
2121 | /* This is the only SPI value that we need to set here, the rest | ||
2122 | * comes from the board-peripherals file */ | ||
2123 | spi->bits_per_word = 32; | ||
2124 | |||
2125 | ret = spi_setup(spi); | ||
2126 | if (ret < 0) { | ||
2127 | wl1271_error("spi_setup failed"); | ||
2128 | goto out_free; | ||
2129 | } | ||
2130 | |||
2131 | wl->set_power = pdata->set_power; | ||
2132 | if (!wl->set_power) { | ||
2133 | wl1271_error("set power function missing in platform data"); | ||
2134 | ret = -ENODEV; | ||
2135 | goto out_free; | ||
2136 | } | ||
2137 | |||
2138 | wl->irq = spi->irq; | ||
2139 | if (wl->irq < 0) { | ||
2140 | wl1271_error("irq missing in platform data"); | ||
2141 | ret = -ENODEV; | ||
2142 | goto out_free; | ||
2143 | } | ||
2144 | |||
2145 | ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); | ||
2146 | if (ret < 0) { | ||
2147 | wl1271_error("request_irq() failed: %d", ret); | ||
2148 | goto out_free; | ||
2149 | } | ||
2150 | |||
2151 | set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); | ||
2152 | |||
2153 | disable_irq(wl->irq); | ||
2154 | |||
2155 | ret = platform_device_register(&wl1271_device); | ||
2156 | if (ret) { | ||
2157 | wl1271_error("couldn't register platform device"); | ||
2158 | goto out_irq; | ||
2159 | } | ||
2160 | dev_set_drvdata(&wl1271_device.dev, wl); | ||
2161 | |||
2162 | ret = wl1271_init_ieee80211(wl); | ||
2163 | if (ret) | ||
2164 | goto out_platform; | ||
2165 | |||
2166 | ret = wl1271_register_hw(wl); | ||
2167 | if (ret) | ||
2168 | goto out_platform; | ||
2169 | |||
2170 | wl1271_debugfs_init(wl); | ||
2171 | |||
2172 | wl1271_notice("initialized"); | ||
2173 | |||
2174 | return 0; | ||
2175 | |||
2176 | out_platform: | ||
2177 | platform_device_unregister(&wl1271_device); | ||
2178 | |||
2179 | out_irq: | ||
2180 | free_irq(wl->irq, wl); | ||
2181 | |||
2182 | out_free: | ||
2183 | ieee80211_free_hw(hw); | ||
2184 | |||
2185 | return ret; | ||
2186 | } | ||
2187 | |||
2188 | static int __devexit wl1271_remove(struct spi_device *spi) | ||
2189 | { | ||
2190 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | ||
2191 | |||
2192 | platform_device_unregister(&wl1271_device); | ||
2193 | free_irq(wl->irq, wl); | ||
2194 | |||
2195 | wl1271_free_hw(wl); | ||
2196 | |||
2197 | return 0; | ||
2198 | } | ||
2199 | |||
2200 | |||
2201 | static struct spi_driver wl1271_spi_driver = { | ||
2202 | .driver = { | ||
2203 | .name = "wl1271", | ||
2204 | .bus = &spi_bus_type, | ||
2205 | .owner = THIS_MODULE, | ||
2206 | }, | ||
2207 | |||
2208 | .probe = wl1271_probe, | ||
2209 | .remove = __devexit_p(wl1271_remove), | ||
2210 | }; | ||
2211 | |||
2212 | static int __init wl1271_init(void) | ||
2213 | { | ||
2214 | int ret; | ||
2215 | |||
2216 | ret = spi_register_driver(&wl1271_spi_driver); | ||
2217 | if (ret < 0) { | ||
2218 | wl1271_error("failed to register spi driver: %d", ret); | ||
2219 | goto out; | ||
2220 | } | ||
2221 | |||
2222 | out: | ||
2223 | return ret; | ||
2224 | } | ||
2225 | |||
2226 | static void __exit wl1271_exit(void) | ||
2227 | { | ||
2228 | spi_unregister_driver(&wl1271_spi_driver); | ||
2229 | |||
2230 | wl1271_notice("unloaded"); | ||
2231 | } | ||
2232 | |||
2233 | module_init(wl1271_init); | ||
2234 | module_exit(wl1271_exit); | ||
2235 | 2068 | ||
2236 | MODULE_LICENSE("GPL"); | 2069 | MODULE_LICENSE("GPL"); |
2237 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | 2070 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); |
2238 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 2071 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
2239 | MODULE_FIRMWARE(WL1271_FW_NAME); | ||