diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
| -rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 353 |
1 files changed, 284 insertions, 69 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8b3c8d196b03..0c69e959d0de 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
| 31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/wl12xx.h> | ||
| 33 | 34 | ||
| 34 | #include "wl12xx.h" | 35 | #include "wl12xx.h" |
| 35 | #include "wl12xx_80211.h" | 36 | #include "wl12xx_80211.h" |
| @@ -54,7 +55,7 @@ static struct conf_drv_settings default_conf = { | |||
| 54 | [CONF_SG_BT_PER_THRESHOLD] = 7500, | 55 | [CONF_SG_BT_PER_THRESHOLD] = 7500, |
| 55 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, | 56 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, |
| 56 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, | 57 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, |
| 57 | [CONF_SG_BT_LOAD_RATIO] = 50, | 58 | [CONF_SG_BT_LOAD_RATIO] = 200, |
| 58 | [CONF_SG_AUTO_PS_MODE] = 1, | 59 | [CONF_SG_AUTO_PS_MODE] = 1, |
| 59 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, | 60 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, |
| 60 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, | 61 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, |
| @@ -191,7 +192,8 @@ static struct conf_drv_settings default_conf = { | |||
| 191 | .long_retry_limit = 10, | 192 | .long_retry_limit = 10, |
| 192 | .aflags = 0, | 193 | .aflags = 0, |
| 193 | }, | 194 | }, |
| 194 | .ap_max_tx_retries = 100, | 195 | .max_tx_retries = 100, |
| 196 | .ap_aging_period = 300, | ||
| 195 | .tid_conf_count = 4, | 197 | .tid_conf_count = 4, |
| 196 | .tid_conf = { | 198 | .tid_conf = { |
| 197 | [CONF_TX_AC_BE] = { | 199 | [CONF_TX_AC_BE] = { |
| @@ -254,7 +256,7 @@ static struct conf_drv_settings default_conf = { | |||
| 254 | .ps_poll_threshold = 10, | 256 | .ps_poll_threshold = 10, |
| 255 | .ps_poll_recovery_period = 700, | 257 | .ps_poll_recovery_period = 700, |
| 256 | .bet_enable = CONF_BET_MODE_ENABLE, | 258 | .bet_enable = CONF_BET_MODE_ENABLE, |
| 257 | .bet_max_consecutive = 10, | 259 | .bet_max_consecutive = 50, |
| 258 | .psm_entry_retries = 5, | 260 | .psm_entry_retries = 5, |
| 259 | .psm_exit_retries = 255, | 261 | .psm_exit_retries = 255, |
| 260 | .psm_entry_nullfunc_retries = 3, | 262 | .psm_entry_nullfunc_retries = 3, |
| @@ -298,7 +300,7 @@ static struct conf_drv_settings default_conf = { | |||
| 298 | .tx_ba_win_size = 64, | 300 | .tx_ba_win_size = 64, |
| 299 | .inactivity_timeout = 10000, | 301 | .inactivity_timeout = 10000, |
| 300 | }, | 302 | }, |
| 301 | .mem = { | 303 | .mem_wl127x = { |
| 302 | .num_stations = 1, | 304 | .num_stations = 1, |
| 303 | .ssid_profiles = 1, | 305 | .ssid_profiles = 1, |
| 304 | .rx_block_num = 70, | 306 | .rx_block_num = 70, |
| @@ -307,7 +309,18 @@ static struct conf_drv_settings default_conf = { | |||
| 307 | .min_req_tx_blocks = 100, | 309 | .min_req_tx_blocks = 100, |
| 308 | .min_req_rx_blocks = 22, | 310 | .min_req_rx_blocks = 22, |
| 309 | .tx_min = 27, | 311 | .tx_min = 27, |
| 310 | } | 312 | }, |
| 313 | .mem_wl128x = { | ||
| 314 | .num_stations = 1, | ||
| 315 | .ssid_profiles = 1, | ||
| 316 | .rx_block_num = 40, | ||
| 317 | .tx_min_block_num = 40, | ||
| 318 | .dynamic_memory = 1, | ||
| 319 | .min_req_tx_blocks = 45, | ||
| 320 | .min_req_rx_blocks = 22, | ||
| 321 | .tx_min = 27, | ||
| 322 | }, | ||
| 323 | .hci_io_ds = HCI_IO_DS_6MA, | ||
| 311 | }; | 324 | }; |
| 312 | 325 | ||
| 313 | static void __wl1271_op_remove_interface(struct wl1271 *wl); | 326 | static void __wl1271_op_remove_interface(struct wl1271 *wl); |
| @@ -329,6 +342,7 @@ static struct platform_device wl1271_device = { | |||
| 329 | }, | 342 | }, |
| 330 | }; | 343 | }; |
| 331 | 344 | ||
| 345 | static DEFINE_MUTEX(wl_list_mutex); | ||
| 332 | static LIST_HEAD(wl_list); | 346 | static LIST_HEAD(wl_list); |
| 333 | 347 | ||
| 334 | static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | 348 | static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, |
| @@ -359,10 +373,12 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | |||
| 359 | return NOTIFY_DONE; | 373 | return NOTIFY_DONE; |
| 360 | 374 | ||
| 361 | wl_temp = hw->priv; | 375 | wl_temp = hw->priv; |
| 376 | mutex_lock(&wl_list_mutex); | ||
| 362 | list_for_each_entry(wl, &wl_list, list) { | 377 | list_for_each_entry(wl, &wl_list, list) { |
| 363 | if (wl == wl_temp) | 378 | if (wl == wl_temp) |
| 364 | break; | 379 | break; |
| 365 | } | 380 | } |
| 381 | mutex_unlock(&wl_list_mutex); | ||
| 366 | if (wl != wl_temp) | 382 | if (wl != wl_temp) |
| 367 | return NOTIFY_DONE; | 383 | return NOTIFY_DONE; |
| 368 | 384 | ||
| @@ -438,15 +454,30 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
| 438 | struct conf_tx_tid *conf_tid; | 454 | struct conf_tx_tid *conf_tid; |
| 439 | int ret, i; | 455 | int ret, i; |
| 440 | 456 | ||
| 441 | ret = wl1271_cmd_general_parms(wl); | 457 | if (wl->chip.id == CHIP_ID_1283_PG20) |
| 458 | ret = wl128x_cmd_general_parms(wl); | ||
| 459 | else | ||
| 460 | ret = wl1271_cmd_general_parms(wl); | ||
| 442 | if (ret < 0) | 461 | if (ret < 0) |
| 443 | return ret; | 462 | return ret; |
| 444 | 463 | ||
| 445 | ret = wl1271_cmd_radio_parms(wl); | 464 | if (wl->chip.id == CHIP_ID_1283_PG20) |
| 465 | ret = wl128x_cmd_radio_parms(wl); | ||
| 466 | else | ||
| 467 | ret = wl1271_cmd_radio_parms(wl); | ||
| 468 | if (ret < 0) | ||
| 469 | return ret; | ||
| 470 | |||
| 471 | if (wl->chip.id != CHIP_ID_1283_PG20) { | ||
| 472 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
| 473 | if (ret < 0) | ||
| 474 | return ret; | ||
| 475 | } | ||
| 446 | if (ret < 0) | 476 | if (ret < 0) |
| 447 | return ret; | 477 | return ret; |
| 448 | 478 | ||
| 449 | ret = wl1271_cmd_ext_radio_parms(wl); | 479 | /* Chip-specific initializations */ |
| 480 | ret = wl1271_chip_specific_init(wl); | ||
| 450 | if (ret < 0) | 481 | if (ret < 0) |
| 451 | return ret; | 482 | return ret; |
| 452 | 483 | ||
| @@ -593,15 +624,17 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
| 593 | { | 624 | { |
| 594 | struct wl1271_fw_common_status *status = &full_status->common; | 625 | struct wl1271_fw_common_status *status = &full_status->common; |
| 595 | struct timespec ts; | 626 | struct timespec ts; |
| 596 | u32 total = 0; | 627 | u32 old_tx_blk_count = wl->tx_blocks_available; |
| 628 | u32 freed_blocks = 0; | ||
| 597 | int i; | 629 | int i; |
| 598 | 630 | ||
| 599 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 631 | if (wl->bss_type == BSS_TYPE_AP_BSS) { |
| 600 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, | 632 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, |
| 601 | sizeof(struct wl1271_fw_ap_status), false); | 633 | sizeof(struct wl1271_fw_ap_status), false); |
| 602 | else | 634 | } else { |
| 603 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, | 635 | wl1271_raw_read(wl, FW_STATUS_ADDR, status, |
| 604 | sizeof(struct wl1271_fw_sta_status), false); | 636 | sizeof(struct wl1271_fw_sta_status), false); |
| 637 | } | ||
| 605 | 638 | ||
| 606 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 639 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
| 607 | "drv_rx_counter = %d, tx_results_counter = %d)", | 640 | "drv_rx_counter = %d, tx_results_counter = %d)", |
| @@ -612,22 +645,37 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
| 612 | 645 | ||
| 613 | /* update number of available TX blocks */ | 646 | /* update number of available TX blocks */ |
| 614 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 647 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
| 615 | u32 cnt = le32_to_cpu(status->tx_released_blks[i]) - | 648 | freed_blocks += le32_to_cpu(status->tx_released_blks[i]) - |
| 616 | wl->tx_blocks_freed[i]; | 649 | wl->tx_blocks_freed[i]; |
| 617 | 650 | ||
| 618 | wl->tx_blocks_freed[i] = | 651 | wl->tx_blocks_freed[i] = |
| 619 | le32_to_cpu(status->tx_released_blks[i]); | 652 | le32_to_cpu(status->tx_released_blks[i]); |
| 620 | wl->tx_blocks_available += cnt; | ||
| 621 | total += cnt; | ||
| 622 | } | 653 | } |
| 623 | 654 | ||
| 624 | /* if more blocks are available now, tx work can be scheduled */ | 655 | wl->tx_allocated_blocks -= freed_blocks; |
| 625 | if (total) | ||
| 626 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | ||
| 627 | 656 | ||
| 628 | /* for AP update num of allocated TX blocks per link and ps status */ | 657 | if (wl->bss_type == BSS_TYPE_AP_BSS) { |
| 629 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 658 | /* Update num of allocated TX blocks per link and ps status */ |
| 630 | wl1271_irq_update_links_status(wl, &full_status->ap); | 659 | wl1271_irq_update_links_status(wl, &full_status->ap); |
| 660 | wl->tx_blocks_available += freed_blocks; | ||
| 661 | } else { | ||
| 662 | int avail = full_status->sta.tx_total - wl->tx_allocated_blocks; | ||
| 663 | |||
| 664 | /* | ||
| 665 | * The FW might change the total number of TX memblocks before | ||
| 666 | * we get a notification about blocks being released. Thus, the | ||
| 667 | * available blocks calculation might yield a temporary result | ||
| 668 | * which is lower than the actual available blocks. Keeping in | ||
| 669 | * mind that only blocks that were allocated can be moved from | ||
| 670 | * TX to RX, tx_blocks_available should never decrease here. | ||
| 671 | */ | ||
| 672 | wl->tx_blocks_available = max((int)wl->tx_blocks_available, | ||
| 673 | avail); | ||
| 674 | } | ||
| 675 | |||
| 676 | /* if more blocks are available now, tx work can be scheduled */ | ||
| 677 | if (wl->tx_blocks_available > old_tx_blk_count) | ||
| 678 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | ||
| 631 | 679 | ||
| 632 | /* update the host-chipset time offset */ | 680 | /* update the host-chipset time offset */ |
| 633 | getnstimeofday(&ts); | 681 | getnstimeofday(&ts); |
| @@ -674,6 +722,13 @@ irqreturn_t wl1271_irq(int irq, void *cookie) | |||
| 674 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | 722 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); |
| 675 | cancel_work_sync(&wl->tx_work); | 723 | cancel_work_sync(&wl->tx_work); |
| 676 | 724 | ||
| 725 | /* | ||
| 726 | * In case edge triggered interrupt must be used, we cannot iterate | ||
| 727 | * more than once without introducing race conditions with the hardirq. | ||
| 728 | */ | ||
| 729 | if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) | ||
| 730 | loopcount = 1; | ||
| 731 | |||
| 677 | mutex_lock(&wl->mutex); | 732 | mutex_lock(&wl->mutex); |
| 678 | 733 | ||
| 679 | wl1271_debug(DEBUG_IRQ, "IRQ work"); | 734 | wl1271_debug(DEBUG_IRQ, "IRQ work"); |
| @@ -785,11 +840,17 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) | |||
| 785 | 840 | ||
| 786 | switch (wl->bss_type) { | 841 | switch (wl->bss_type) { |
| 787 | case BSS_TYPE_AP_BSS: | 842 | case BSS_TYPE_AP_BSS: |
| 788 | fw_name = WL1271_AP_FW_NAME; | 843 | if (wl->chip.id == CHIP_ID_1283_PG20) |
| 844 | fw_name = WL128X_AP_FW_NAME; | ||
| 845 | else | ||
| 846 | fw_name = WL127X_AP_FW_NAME; | ||
| 789 | break; | 847 | break; |
| 790 | case BSS_TYPE_IBSS: | 848 | case BSS_TYPE_IBSS: |
| 791 | case BSS_TYPE_STA_BSS: | 849 | case BSS_TYPE_STA_BSS: |
| 792 | fw_name = WL1271_FW_NAME; | 850 | if (wl->chip.id == CHIP_ID_1283_PG20) |
| 851 | fw_name = WL128X_FW_NAME; | ||
| 852 | else | ||
| 853 | fw_name = WL1271_FW_NAME; | ||
| 793 | break; | 854 | break; |
| 794 | default: | 855 | default: |
| 795 | wl1271_error("no compatible firmware for bss_type %d", | 856 | wl1271_error("no compatible firmware for bss_type %d", |
| @@ -838,14 +899,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
| 838 | const struct firmware *fw; | 899 | const struct firmware *fw; |
| 839 | int ret; | 900 | int ret; |
| 840 | 901 | ||
| 841 | ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl)); | 902 | ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); |
| 842 | 903 | ||
| 843 | if (ret < 0) { | 904 | if (ret < 0) { |
| 844 | wl1271_error("could not get nvs file: %d", ret); | 905 | wl1271_error("could not get nvs file: %d", ret); |
| 845 | return ret; | 906 | return ret; |
| 846 | } | 907 | } |
| 847 | 908 | ||
| 848 | wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL); | 909 | wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); |
| 849 | 910 | ||
| 850 | if (!wl->nvs) { | 911 | if (!wl->nvs) { |
| 851 | wl1271_error("could not allocate memory for the nvs file"); | 912 | wl1271_error("could not allocate memory for the nvs file"); |
| @@ -954,6 +1015,17 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
| 954 | if (ret < 0) | 1015 | if (ret < 0) |
| 955 | goto out; | 1016 | goto out; |
| 956 | break; | 1017 | break; |
| 1018 | case CHIP_ID_1283_PG20: | ||
| 1019 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", | ||
| 1020 | wl->chip.id); | ||
| 1021 | |||
| 1022 | ret = wl1271_setup(wl); | ||
| 1023 | if (ret < 0) | ||
| 1024 | goto out; | ||
| 1025 | if (wl1271_set_block_size(wl)) | ||
| 1026 | wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT; | ||
| 1027 | break; | ||
| 1028 | case CHIP_ID_1283_PG10: | ||
| 957 | default: | 1029 | default: |
| 958 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); | 1030 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); |
| 959 | ret = -ENODEV; | 1031 | ret = -ENODEV; |
| @@ -978,6 +1050,24 @@ out: | |||
| 978 | return ret; | 1050 | return ret; |
| 979 | } | 1051 | } |
| 980 | 1052 | ||
| 1053 | static unsigned int wl1271_get_fw_ver_quirks(struct wl1271 *wl) | ||
| 1054 | { | ||
| 1055 | unsigned int quirks = 0; | ||
| 1056 | unsigned int *fw_ver = wl->chip.fw_ver; | ||
| 1057 | |||
| 1058 | /* Only for wl127x */ | ||
| 1059 | if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) && | ||
| 1060 | /* Check STA version */ | ||
| 1061 | (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && | ||
| 1062 | (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) || | ||
| 1063 | /* Check AP version */ | ||
| 1064 | ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) && | ||
| 1065 | (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN)))) | ||
| 1066 | quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS; | ||
| 1067 | |||
| 1068 | return quirks; | ||
| 1069 | } | ||
| 1070 | |||
| 981 | int wl1271_plt_start(struct wl1271 *wl) | 1071 | int wl1271_plt_start(struct wl1271 *wl) |
| 982 | { | 1072 | { |
| 983 | int retries = WL1271_BOOT_RETRIES; | 1073 | int retries = WL1271_BOOT_RETRIES; |
| @@ -1013,6 +1103,9 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
| 1013 | wl->state = WL1271_STATE_PLT; | 1103 | wl->state = WL1271_STATE_PLT; |
| 1014 | wl1271_notice("firmware booted in PLT mode (%s)", | 1104 | wl1271_notice("firmware booted in PLT mode (%s)", |
| 1015 | wl->chip.fw_ver_str); | 1105 | wl->chip.fw_ver_str); |
| 1106 | |||
| 1107 | /* Check if any quirks are needed with older fw versions */ | ||
| 1108 | wl->quirks |= wl1271_get_fw_ver_quirks(wl); | ||
| 1016 | goto out; | 1109 | goto out; |
| 1017 | 1110 | ||
| 1018 | irq_disable: | 1111 | irq_disable: |
| @@ -1040,7 +1133,7 @@ out: | |||
| 1040 | return ret; | 1133 | return ret; |
| 1041 | } | 1134 | } |
| 1042 | 1135 | ||
| 1043 | int __wl1271_plt_stop(struct wl1271 *wl) | 1136 | static int __wl1271_plt_stop(struct wl1271 *wl) |
| 1044 | { | 1137 | { |
| 1045 | int ret = 0; | 1138 | int ret = 0; |
| 1046 | 1139 | ||
| @@ -1124,6 +1217,69 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 1124 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1217 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
| 1125 | } | 1218 | } |
| 1126 | 1219 | ||
| 1220 | int wl1271_tx_dummy_packet(struct wl1271 *wl) | ||
| 1221 | { | ||
| 1222 | unsigned long flags; | ||
| 1223 | |||
| 1224 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
| 1225 | set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); | ||
| 1226 | wl->tx_queue_count++; | ||
| 1227 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
| 1228 | |||
| 1229 | /* The FW is low on RX memory blocks, so send the dummy packet asap */ | ||
| 1230 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) | ||
| 1231 | wl1271_tx_work_locked(wl); | ||
| 1232 | |||
| 1233 | /* | ||
| 1234 | * If the FW TX is busy, TX work will be scheduled by the threaded | ||
| 1235 | * interrupt handler function | ||
| 1236 | */ | ||
| 1237 | return 0; | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | /* | ||
| 1241 | * The size of the dummy packet should be at least 1400 bytes. However, in | ||
| 1242 | * order to minimize the number of bus transactions, aligning it to 512 bytes | ||
| 1243 | * boundaries could be beneficial, performance wise | ||
| 1244 | */ | ||
| 1245 | #define TOTAL_TX_DUMMY_PACKET_SIZE (ALIGN(1400, 512)) | ||
| 1246 | |||
| 1247 | static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) | ||
| 1248 | { | ||
| 1249 | struct sk_buff *skb; | ||
| 1250 | struct ieee80211_hdr_3addr *hdr; | ||
| 1251 | unsigned int dummy_packet_size; | ||
| 1252 | |||
| 1253 | dummy_packet_size = TOTAL_TX_DUMMY_PACKET_SIZE - | ||
| 1254 | sizeof(struct wl1271_tx_hw_descr) - sizeof(*hdr); | ||
| 1255 | |||
| 1256 | skb = dev_alloc_skb(TOTAL_TX_DUMMY_PACKET_SIZE); | ||
| 1257 | if (!skb) { | ||
| 1258 | wl1271_warning("Failed to allocate a dummy packet skb"); | ||
| 1259 | return NULL; | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr)); | ||
| 1263 | |||
| 1264 | hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr)); | ||
| 1265 | memset(hdr, 0, sizeof(*hdr)); | ||
| 1266 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
| 1267 | IEEE80211_STYPE_NULLFUNC | | ||
| 1268 | IEEE80211_FCTL_TODS); | ||
| 1269 | |||
| 1270 | memset(skb_put(skb, dummy_packet_size), 0, dummy_packet_size); | ||
| 1271 | |||
| 1272 | /* Dummy packets require the TID to be management */ | ||
| 1273 | skb->priority = WL1271_TID_MGMT; | ||
| 1274 | |||
| 1275 | /* Initialize all fields that might be used */ | ||
| 1276 | skb->queue_mapping = 0; | ||
| 1277 | memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); | ||
| 1278 | |||
| 1279 | return skb; | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | |||
| 1127 | static struct notifier_block wl1271_dev_notifier = { | 1283 | static struct notifier_block wl1271_dev_notifier = { |
| 1128 | .notifier_call = wl1271_dev_notify, | 1284 | .notifier_call = wl1271_dev_notify, |
| 1129 | }; | 1285 | }; |
| @@ -1174,6 +1330,16 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
| 1174 | goto out; | 1330 | goto out; |
| 1175 | } | 1331 | } |
| 1176 | 1332 | ||
| 1333 | /* | ||
| 1334 | * in some very corner case HW recovery scenarios its possible to | ||
| 1335 | * get here before __wl1271_op_remove_interface is complete, so | ||
| 1336 | * opt out if that is the case. | ||
| 1337 | */ | ||
| 1338 | if (test_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags)) { | ||
| 1339 | ret = -EBUSY; | ||
| 1340 | goto out; | ||
| 1341 | } | ||
| 1342 | |||
| 1177 | switch (vif->type) { | 1343 | switch (vif->type) { |
| 1178 | case NL80211_IFTYPE_STATION: | 1344 | case NL80211_IFTYPE_STATION: |
| 1179 | wl->bss_type = BSS_TYPE_STA_BSS; | 1345 | wl->bss_type = BSS_TYPE_STA_BSS; |
| @@ -1242,6 +1408,7 @@ power_off: | |||
| 1242 | 1408 | ||
| 1243 | wl->vif = vif; | 1409 | wl->vif = vif; |
| 1244 | wl->state = WL1271_STATE_ON; | 1410 | wl->state = WL1271_STATE_ON; |
| 1411 | set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); | ||
| 1245 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); | 1412 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); |
| 1246 | 1413 | ||
| 1247 | /* update hw/fw version info in wiphy struct */ | 1414 | /* update hw/fw version info in wiphy struct */ |
| @@ -1249,6 +1416,9 @@ power_off: | |||
| 1249 | strncpy(wiphy->fw_version, wl->chip.fw_ver_str, | 1416 | strncpy(wiphy->fw_version, wl->chip.fw_ver_str, |
| 1250 | sizeof(wiphy->fw_version)); | 1417 | sizeof(wiphy->fw_version)); |
| 1251 | 1418 | ||
| 1419 | /* Check if any quirks are needed with older fw versions */ | ||
| 1420 | wl->quirks |= wl1271_get_fw_ver_quirks(wl); | ||
| 1421 | |||
| 1252 | /* | 1422 | /* |
| 1253 | * Now we know if 11a is supported (info from the NVS), so disable | 1423 | * Now we know if 11a is supported (info from the NVS), so disable |
| 1254 | * 11a channels if not supported | 1424 | * 11a channels if not supported |
| @@ -1262,8 +1432,10 @@ power_off: | |||
| 1262 | out: | 1432 | out: |
| 1263 | mutex_unlock(&wl->mutex); | 1433 | mutex_unlock(&wl->mutex); |
| 1264 | 1434 | ||
| 1435 | mutex_lock(&wl_list_mutex); | ||
| 1265 | if (!ret) | 1436 | if (!ret) |
| 1266 | list_add(&wl->list, &wl_list); | 1437 | list_add(&wl->list, &wl_list); |
| 1438 | mutex_unlock(&wl_list_mutex); | ||
| 1267 | 1439 | ||
| 1268 | return ret; | 1440 | return ret; |
| 1269 | } | 1441 | } |
| @@ -1274,11 +1446,15 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
| 1274 | 1446 | ||
| 1275 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | 1447 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); |
| 1276 | 1448 | ||
| 1449 | /* because of hardware recovery, we may get here twice */ | ||
| 1450 | if (wl->state != WL1271_STATE_ON) | ||
| 1451 | return; | ||
| 1452 | |||
| 1277 | wl1271_info("down"); | 1453 | wl1271_info("down"); |
| 1278 | 1454 | ||
| 1455 | mutex_lock(&wl_list_mutex); | ||
| 1279 | list_del(&wl->list); | 1456 | list_del(&wl->list); |
| 1280 | 1457 | mutex_unlock(&wl_list_mutex); | |
| 1281 | WARN_ON(wl->state != WL1271_STATE_ON); | ||
| 1282 | 1458 | ||
| 1283 | /* enable dyn ps just in case (if left on due to fw crash etc) */ | 1459 | /* enable dyn ps just in case (if left on due to fw crash etc) */ |
| 1284 | if (wl->bss_type == BSS_TYPE_STA_BSS) | 1460 | if (wl->bss_type == BSS_TYPE_STA_BSS) |
| @@ -1286,12 +1462,15 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
| 1286 | 1462 | ||
| 1287 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { | 1463 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { |
| 1288 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | 1464 | wl->scan.state = WL1271_SCAN_STATE_IDLE; |
| 1289 | kfree(wl->scan.scanned_ch); | 1465 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); |
| 1290 | wl->scan.scanned_ch = NULL; | ||
| 1291 | wl->scan.req = NULL; | 1466 | wl->scan.req = NULL; |
| 1292 | ieee80211_scan_completed(wl->hw, true); | 1467 | ieee80211_scan_completed(wl->hw, true); |
| 1293 | } | 1468 | } |
| 1294 | 1469 | ||
| 1470 | /* | ||
| 1471 | * this must be before the cancel_work calls below, so that the work | ||
| 1472 | * functions don't perform further work. | ||
| 1473 | */ | ||
| 1295 | wl->state = WL1271_STATE_OFF; | 1474 | wl->state = WL1271_STATE_OFF; |
| 1296 | 1475 | ||
| 1297 | mutex_unlock(&wl->mutex); | 1476 | mutex_unlock(&wl->mutex); |
| @@ -1321,6 +1500,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
| 1321 | wl->psm_entry_retry = 0; | 1500 | wl->psm_entry_retry = 0; |
| 1322 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1501 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
| 1323 | wl->tx_blocks_available = 0; | 1502 | wl->tx_blocks_available = 0; |
| 1503 | wl->tx_allocated_blocks = 0; | ||
| 1324 | wl->tx_results_count = 0; | 1504 | wl->tx_results_count = 0; |
| 1325 | wl->tx_packets_count = 0; | 1505 | wl->tx_packets_count = 0; |
| 1326 | wl->tx_security_last_seq = 0; | 1506 | wl->tx_security_last_seq = 0; |
| @@ -1328,7 +1508,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
| 1328 | wl->time_offset = 0; | 1508 | wl->time_offset = 0; |
| 1329 | wl->session_counter = 0; | 1509 | wl->session_counter = 0; |
| 1330 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1510 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
| 1331 | wl->flags = 0; | ||
| 1332 | wl->vif = NULL; | 1511 | wl->vif = NULL; |
| 1333 | wl->filters = 0; | 1512 | wl->filters = 0; |
| 1334 | wl1271_free_ap_keys(wl); | 1513 | wl1271_free_ap_keys(wl); |
| @@ -1336,6 +1515,13 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
| 1336 | wl->ap_fw_ps_map = 0; | 1515 | wl->ap_fw_ps_map = 0; |
| 1337 | wl->ap_ps_map = 0; | 1516 | wl->ap_ps_map = 0; |
| 1338 | 1517 | ||
| 1518 | /* | ||
| 1519 | * this is performed after the cancel_work calls and the associated | ||
| 1520 | * mutex_lock, so that wl1271_op_add_interface does not accidentally | ||
| 1521 | * get executed before all these vars have been reset. | ||
| 1522 | */ | ||
| 1523 | wl->flags = 0; | ||
| 1524 | |||
| 1339 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1525 | for (i = 0; i < NUM_TX_QUEUES; i++) |
| 1340 | wl->tx_blocks_freed[i] = 0; | 1526 | wl->tx_blocks_freed[i] = 0; |
| 1341 | 1527 | ||
| @@ -1368,7 +1554,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
| 1368 | cancel_work_sync(&wl->recovery_work); | 1554 | cancel_work_sync(&wl->recovery_work); |
| 1369 | } | 1555 | } |
| 1370 | 1556 | ||
| 1371 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) | 1557 | void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) |
| 1372 | { | 1558 | { |
| 1373 | wl1271_set_default_filters(wl); | 1559 | wl1271_set_default_filters(wl); |
| 1374 | 1560 | ||
| @@ -1431,10 +1617,10 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc) | |||
| 1431 | * One of the side effects of the JOIN command is that is clears | 1617 | * One of the side effects of the JOIN command is that is clears |
| 1432 | * WPA/WPA2 keys from the chipset. Performing a JOIN while associated | 1618 | * WPA/WPA2 keys from the chipset. Performing a JOIN while associated |
| 1433 | * to a WPA/WPA2 access point will therefore kill the data-path. | 1619 | * to a WPA/WPA2 access point will therefore kill the data-path. |
| 1434 | * Currently there is no supported scenario for JOIN during | 1620 | * Currently the only valid scenario for JOIN during association |
| 1435 | * association - if it becomes a supported scenario, the WPA/WPA2 keys | 1621 | * is on roaming, in which case we will also be given new keys. |
| 1436 | * must be handled somehow. | 1622 | * Keep the below message for now, unless it starts bothering |
| 1437 | * | 1623 | * users who really like to roam a lot :) |
| 1438 | */ | 1624 | */ |
| 1439 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 1625 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
| 1440 | wl1271_info("JOIN while associated."); | 1626 | wl1271_info("JOIN while associated."); |
| @@ -1490,7 +1676,7 @@ static int wl1271_unjoin(struct wl1271 *wl) | |||
| 1490 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | 1676 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); |
| 1491 | memset(wl->bssid, 0, ETH_ALEN); | 1677 | memset(wl->bssid, 0, ETH_ALEN); |
| 1492 | 1678 | ||
| 1493 | /* stop filterting packets based on bssid */ | 1679 | /* stop filtering packets based on bssid */ |
| 1494 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | 1680 | wl1271_configure_filters(wl, FIF_OTHER_BSS); |
| 1495 | 1681 | ||
| 1496 | out: | 1682 | out: |
| @@ -1569,7 +1755,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
| 1569 | mutex_lock(&wl->mutex); | 1755 | mutex_lock(&wl->mutex); |
| 1570 | 1756 | ||
| 1571 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | 1757 | if (unlikely(wl->state == WL1271_STATE_OFF)) { |
| 1572 | ret = -EAGAIN; | 1758 | /* we support configuring the channel and band while off */ |
| 1759 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL)) { | ||
| 1760 | wl->band = conf->channel->band; | ||
| 1761 | wl->channel = channel; | ||
| 1762 | } | ||
| 1763 | |||
| 1573 | goto out; | 1764 | goto out; |
| 1574 | } | 1765 | } |
| 1575 | 1766 | ||
| @@ -2650,32 +2841,31 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
| 2650 | conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY; | 2841 | conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY; |
| 2651 | conf_tid->apsd_conf[0] = 0; | 2842 | conf_tid->apsd_conf[0] = 0; |
| 2652 | conf_tid->apsd_conf[1] = 0; | 2843 | conf_tid->apsd_conf[1] = 0; |
| 2653 | } else { | 2844 | goto out; |
| 2654 | ret = wl1271_ps_elp_wakeup(wl); | 2845 | } |
| 2655 | if (ret < 0) | ||
| 2656 | goto out; | ||
| 2657 | 2846 | ||
| 2658 | /* | 2847 | ret = wl1271_ps_elp_wakeup(wl); |
| 2659 | * the txop is confed in units of 32us by the mac80211, | 2848 | if (ret < 0) |
| 2660 | * we need us | 2849 | goto out; |
| 2661 | */ | ||
| 2662 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | ||
| 2663 | params->cw_min, params->cw_max, | ||
| 2664 | params->aifs, params->txop << 5); | ||
| 2665 | if (ret < 0) | ||
| 2666 | goto out_sleep; | ||
| 2667 | 2850 | ||
| 2668 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | 2851 | /* |
| 2669 | CONF_CHANNEL_TYPE_EDCF, | 2852 | * the txop is confed in units of 32us by the mac80211, |
| 2670 | wl1271_tx_get_queue(queue), | 2853 | * we need us |
| 2671 | ps_scheme, CONF_ACK_POLICY_LEGACY, | 2854 | */ |
| 2672 | 0, 0); | 2855 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), |
| 2673 | if (ret < 0) | 2856 | params->cw_min, params->cw_max, |
| 2674 | goto out_sleep; | 2857 | params->aifs, params->txop << 5); |
| 2858 | if (ret < 0) | ||
| 2859 | goto out_sleep; | ||
| 2860 | |||
| 2861 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | ||
| 2862 | CONF_CHANNEL_TYPE_EDCF, | ||
| 2863 | wl1271_tx_get_queue(queue), | ||
| 2864 | ps_scheme, CONF_ACK_POLICY_LEGACY, | ||
| 2865 | 0, 0); | ||
| 2675 | 2866 | ||
| 2676 | out_sleep: | 2867 | out_sleep: |
| 2677 | wl1271_ps_elp_sleep(wl); | 2868 | wl1271_ps_elp_sleep(wl); |
| 2678 | } | ||
| 2679 | 2869 | ||
| 2680 | out: | 2870 | out: |
| 2681 | mutex_unlock(&wl->mutex); | 2871 | mutex_unlock(&wl->mutex); |
| @@ -2764,6 +2954,12 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) | |||
| 2764 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 2954 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
| 2765 | } | 2955 | } |
| 2766 | 2956 | ||
| 2957 | bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) | ||
| 2958 | { | ||
| 2959 | int id = hlid - WL1271_AP_STA_HLID_START; | ||
| 2960 | return test_bit(id, wl->ap_hlid_map); | ||
| 2961 | } | ||
| 2962 | |||
| 2767 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, | 2963 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, |
| 2768 | struct ieee80211_vif *vif, | 2964 | struct ieee80211_vif *vif, |
| 2769 | struct ieee80211_sta *sta) | 2965 | struct ieee80211_sta *sta) |
| @@ -2847,10 +3043,11 @@ out: | |||
| 2847 | return ret; | 3043 | return ret; |
| 2848 | } | 3044 | } |
| 2849 | 3045 | ||
| 2850 | int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 3046 | static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, |
| 2851 | enum ieee80211_ampdu_mlme_action action, | 3047 | struct ieee80211_vif *vif, |
| 2852 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | 3048 | enum ieee80211_ampdu_mlme_action action, |
| 2853 | u8 buf_size) | 3049 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
| 3050 | u8 buf_size) | ||
| 2854 | { | 3051 | { |
| 2855 | struct wl1271 *wl = hw->priv; | 3052 | struct wl1271 *wl = hw->priv; |
| 2856 | int ret; | 3053 | int ret; |
| @@ -3003,7 +3200,8 @@ static const u8 wl1271_rate_to_idx_2ghz[] = { | |||
| 3003 | 3200 | ||
| 3004 | #ifdef CONFIG_WL12XX_HT | 3201 | #ifdef CONFIG_WL12XX_HT |
| 3005 | #define WL12XX_HT_CAP { \ | 3202 | #define WL12XX_HT_CAP { \ |
| 3006 | .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20, \ | 3203 | .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \ |
| 3204 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \ | ||
| 3007 | .ht_supported = true, \ | 3205 | .ht_supported = true, \ |
| 3008 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ | 3206 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ |
| 3009 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ | 3207 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \ |
| @@ -3207,8 +3405,7 @@ static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, | |||
| 3207 | unsigned long res; | 3405 | unsigned long res; |
| 3208 | int ret; | 3406 | int ret; |
| 3209 | 3407 | ||
| 3210 | ret = strict_strtoul(buf, 10, &res); | 3408 | ret = kstrtoul(buf, 10, &res); |
| 3211 | |||
| 3212 | if (ret < 0) { | 3409 | if (ret < 0) { |
| 3213 | wl1271_warning("incorrect value written to bt_coex_mode"); | 3410 | wl1271_warning("incorrect value written to bt_coex_mode"); |
| 3214 | return count; | 3411 | return count; |
| @@ -3273,7 +3470,11 @@ int wl1271_register_hw(struct wl1271 *wl) | |||
| 3273 | 3470 | ||
| 3274 | ret = wl1271_fetch_nvs(wl); | 3471 | ret = wl1271_fetch_nvs(wl); |
| 3275 | if (ret == 0) { | 3472 | if (ret == 0) { |
| 3276 | u8 *nvs_ptr = (u8 *)wl->nvs->nvs; | 3473 | /* NOTE: The wl->nvs->nvs element must be first, in |
| 3474 | * order to simplify the casting, we assume it is at | ||
| 3475 | * the beginning of the wl->nvs structure. | ||
| 3476 | */ | ||
| 3477 | u8 *nvs_ptr = (u8 *)wl->nvs; | ||
| 3277 | 3478 | ||
| 3278 | wl->mac_addr[0] = nvs_ptr[11]; | 3479 | wl->mac_addr[0] = nvs_ptr[11]; |
| 3279 | wl->mac_addr[1] = nvs_ptr[10]; | 3480 | wl->mac_addr[1] = nvs_ptr[10]; |
| @@ -3341,7 +3542,6 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
| 3341 | IEEE80211_HW_HAS_RATE_CONTROL | | 3542 | IEEE80211_HW_HAS_RATE_CONTROL | |
| 3342 | IEEE80211_HW_CONNECTION_MONITOR | | 3543 | IEEE80211_HW_CONNECTION_MONITOR | |
| 3343 | IEEE80211_HW_SUPPORTS_CQM_RSSI | | 3544 | IEEE80211_HW_SUPPORTS_CQM_RSSI | |
| 3344 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | ||
| 3345 | IEEE80211_HW_AP_LINK_PS; | 3545 | IEEE80211_HW_AP_LINK_PS; |
| 3346 | 3546 | ||
| 3347 | wl->hw->wiphy->cipher_suites = cipher_suites; | 3547 | wl->hw->wiphy->cipher_suites = cipher_suites; |
| @@ -3358,6 +3558,10 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
| 3358 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - | 3558 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - |
| 3359 | sizeof(struct ieee80211_header); | 3559 | sizeof(struct ieee80211_header); |
| 3360 | 3560 | ||
| 3561 | /* make sure all our channels fit in the scanned_ch bitmask */ | ||
| 3562 | BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) + | ||
| 3563 | ARRAY_SIZE(wl1271_channels_5ghz) > | ||
| 3564 | WL1271_MAX_CHANNELS); | ||
| 3361 | /* | 3565 | /* |
| 3362 | * We keep local copies of the band structs because we need to | 3566 | * We keep local copies of the band structs because we need to |
| 3363 | * modify them on a per-device basis. | 3567 | * modify them on a per-device basis. |
| @@ -3458,6 +3662,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
| 3458 | wl->ap_ps_map = 0; | 3662 | wl->ap_ps_map = 0; |
| 3459 | wl->ap_fw_ps_map = 0; | 3663 | wl->ap_fw_ps_map = 0; |
| 3460 | wl->quirks = 0; | 3664 | wl->quirks = 0; |
| 3665 | wl->platform_quirks = 0; | ||
| 3461 | 3666 | ||
| 3462 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); | 3667 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); |
| 3463 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 3668 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
| @@ -3478,11 +3683,17 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
| 3478 | goto err_hw; | 3683 | goto err_hw; |
| 3479 | } | 3684 | } |
| 3480 | 3685 | ||
| 3686 | wl->dummy_packet = wl12xx_alloc_dummy_packet(wl); | ||
| 3687 | if (!wl->dummy_packet) { | ||
| 3688 | ret = -ENOMEM; | ||
| 3689 | goto err_aggr; | ||
| 3690 | } | ||
| 3691 | |||
| 3481 | /* Register platform device */ | 3692 | /* Register platform device */ |
| 3482 | ret = platform_device_register(wl->plat_dev); | 3693 | ret = platform_device_register(wl->plat_dev); |
| 3483 | if (ret) { | 3694 | if (ret) { |
| 3484 | wl1271_error("couldn't register platform device"); | 3695 | wl1271_error("couldn't register platform device"); |
| 3485 | goto err_aggr; | 3696 | goto err_dummy_packet; |
| 3486 | } | 3697 | } |
| 3487 | dev_set_drvdata(&wl->plat_dev->dev, wl); | 3698 | dev_set_drvdata(&wl->plat_dev->dev, wl); |
| 3488 | 3699 | ||
| @@ -3508,6 +3719,9 @@ err_bt_coex_state: | |||
| 3508 | err_platform: | 3719 | err_platform: |
| 3509 | platform_device_unregister(wl->plat_dev); | 3720 | platform_device_unregister(wl->plat_dev); |
| 3510 | 3721 | ||
| 3722 | err_dummy_packet: | ||
| 3723 | dev_kfree_skb(wl->dummy_packet); | ||
| 3724 | |||
| 3511 | err_aggr: | 3725 | err_aggr: |
| 3512 | free_pages((unsigned long)wl->aggr_buf, order); | 3726 | free_pages((unsigned long)wl->aggr_buf, order); |
| 3513 | 3727 | ||
| @@ -3527,6 +3741,7 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw); | |||
| 3527 | int wl1271_free_hw(struct wl1271 *wl) | 3741 | int wl1271_free_hw(struct wl1271 *wl) |
| 3528 | { | 3742 | { |
| 3529 | platform_device_unregister(wl->plat_dev); | 3743 | platform_device_unregister(wl->plat_dev); |
| 3744 | dev_kfree_skb(wl->dummy_packet); | ||
| 3530 | free_pages((unsigned long)wl->aggr_buf, | 3745 | free_pages((unsigned long)wl->aggr_buf, |
| 3531 | get_order(WL1271_AGGR_BUFFER_SIZE)); | 3746 | get_order(WL1271_AGGR_BUFFER_SIZE)); |
| 3532 | kfree(wl->plat_dev); | 3747 | kfree(wl->plat_dev); |
