diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-3945.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 147 |
1 files changed, 101 insertions, 46 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 99b876a2feb9..068f7f8435c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -391,6 +391,67 @@ static void iwl3945_accumulative_statistics(struct iwl_priv *priv, | |||
391 | } | 391 | } |
392 | #endif | 392 | #endif |
393 | 393 | ||
394 | /** | ||
395 | * iwl3945_good_plcp_health - checks for plcp error. | ||
396 | * | ||
397 | * When the plcp error is exceeding the thresholds, reset the radio | ||
398 | * to improve the throughput. | ||
399 | */ | ||
400 | static bool iwl3945_good_plcp_health(struct iwl_priv *priv, | ||
401 | struct iwl_rx_packet *pkt) | ||
402 | { | ||
403 | bool rc = true; | ||
404 | struct iwl3945_notif_statistics current_stat; | ||
405 | int combined_plcp_delta; | ||
406 | unsigned int plcp_msec; | ||
407 | unsigned long plcp_received_jiffies; | ||
408 | |||
409 | memcpy(¤t_stat, pkt->u.raw, sizeof(struct | ||
410 | iwl3945_notif_statistics)); | ||
411 | /* | ||
412 | * check for plcp_err and trigger radio reset if it exceeds | ||
413 | * the plcp error threshold plcp_delta. | ||
414 | */ | ||
415 | plcp_received_jiffies = jiffies; | ||
416 | plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - | ||
417 | (long) priv->plcp_jiffies); | ||
418 | priv->plcp_jiffies = plcp_received_jiffies; | ||
419 | /* | ||
420 | * check to make sure plcp_msec is not 0 to prevent division | ||
421 | * by zero. | ||
422 | */ | ||
423 | if (plcp_msec) { | ||
424 | combined_plcp_delta = | ||
425 | (le32_to_cpu(current_stat.rx.ofdm.plcp_err) - | ||
426 | le32_to_cpu(priv->_3945.statistics.rx.ofdm.plcp_err)); | ||
427 | |||
428 | if ((combined_plcp_delta > 0) && | ||
429 | ((combined_plcp_delta * 100) / plcp_msec) > | ||
430 | priv->cfg->plcp_delta_threshold) { | ||
431 | /* | ||
432 | * if plcp_err exceed the threshold, the following | ||
433 | * data is printed in csv format: | ||
434 | * Text: plcp_err exceeded %d, | ||
435 | * Received ofdm.plcp_err, | ||
436 | * Current ofdm.plcp_err, | ||
437 | * combined_plcp_delta, | ||
438 | * plcp_msec | ||
439 | */ | ||
440 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " | ||
441 | "%u, %d, %u mSecs\n", | ||
442 | priv->cfg->plcp_delta_threshold, | ||
443 | le32_to_cpu(current_stat.rx.ofdm.plcp_err), | ||
444 | combined_plcp_delta, plcp_msec); | ||
445 | /* | ||
446 | * Reset the RF radio due to the high plcp | ||
447 | * error rate | ||
448 | */ | ||
449 | rc = false; | ||
450 | } | ||
451 | } | ||
452 | return rc; | ||
453 | } | ||
454 | |||
394 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | 455 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, |
395 | struct iwl_rx_mem_buffer *rxb) | 456 | struct iwl_rx_mem_buffer *rxb) |
396 | { | 457 | { |
@@ -402,6 +463,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | |||
402 | #ifdef CONFIG_IWLWIFI_DEBUG | 463 | #ifdef CONFIG_IWLWIFI_DEBUG |
403 | iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); | 464 | iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); |
404 | #endif | 465 | #endif |
466 | iwl_recover_from_statistics(priv, pkt); | ||
405 | 467 | ||
406 | memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics)); | 468 | memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics)); |
407 | } | 469 | } |
@@ -885,7 +947,8 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
885 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); | 947 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); |
886 | } | 948 | } |
887 | 949 | ||
888 | u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) | 950 | static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, |
951 | u16 tx_rate, u8 flags) | ||
889 | { | 952 | { |
890 | unsigned long flags_spin; | 953 | unsigned long flags_spin; |
891 | struct iwl_station_entry *station; | 954 | struct iwl_station_entry *station; |
@@ -1715,6 +1778,11 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) | |||
1715 | int ref_temp; | 1778 | int ref_temp; |
1716 | int temperature = priv->temperature; | 1779 | int temperature = priv->temperature; |
1717 | 1780 | ||
1781 | if (priv->disable_tx_power_cal || | ||
1782 | test_bit(STATUS_SCANNING, &priv->status)) { | ||
1783 | /* do not perform tx power calibration */ | ||
1784 | return 0; | ||
1785 | } | ||
1718 | /* set up new Tx power info for each and every channel, 2.4 and 5.x */ | 1786 | /* set up new Tx power info for each and every channel, 2.4 and 5.x */ |
1719 | for (i = 0; i < priv->channel_count; i++) { | 1787 | for (i = 0; i < priv->channel_count; i++) { |
1720 | ch_info = &priv->channel_info[i]; | 1788 | ch_info = &priv->channel_info[i]; |
@@ -1925,7 +1993,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
1925 | "configuration (%d).\n", rc); | 1993 | "configuration (%d).\n", rc); |
1926 | return rc; | 1994 | return rc; |
1927 | } | 1995 | } |
1928 | iwl_clear_ucode_stations(priv, false); | 1996 | iwl_clear_ucode_stations(priv); |
1929 | iwl_restore_stations(priv); | 1997 | iwl_restore_stations(priv); |
1930 | } | 1998 | } |
1931 | 1999 | ||
@@ -1958,7 +2026,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
1958 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); | 2026 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); |
1959 | 2027 | ||
1960 | if (!new_assoc) { | 2028 | if (!new_assoc) { |
1961 | iwl_clear_ucode_stations(priv, false); | 2029 | iwl_clear_ucode_stations(priv); |
1962 | iwl_restore_stations(priv); | 2030 | iwl_restore_stations(priv); |
1963 | } | 2031 | } |
1964 | 2032 | ||
@@ -2391,6 +2459,30 @@ static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | |||
2391 | return (u16)sizeof(struct iwl3945_addsta_cmd); | 2459 | return (u16)sizeof(struct iwl3945_addsta_cmd); |
2392 | } | 2460 | } |
2393 | 2461 | ||
2462 | static int iwl3945_manage_ibss_station(struct iwl_priv *priv, | ||
2463 | struct ieee80211_vif *vif, bool add) | ||
2464 | { | ||
2465 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
2466 | int ret; | ||
2467 | |||
2468 | if (add) { | ||
2469 | ret = iwl_add_bssid_station(priv, vif->bss_conf.bssid, false, | ||
2470 | &vif_priv->ibss_bssid_sta_id); | ||
2471 | if (ret) | ||
2472 | return ret; | ||
2473 | |||
2474 | iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id, | ||
2475 | (priv->band == IEEE80211_BAND_5GHZ) ? | ||
2476 | IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, | ||
2477 | CMD_ASYNC); | ||
2478 | iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id); | ||
2479 | |||
2480 | return 0; | ||
2481 | } | ||
2482 | |||
2483 | return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, | ||
2484 | vif->bss_conf.bssid); | ||
2485 | } | ||
2394 | 2486 | ||
2395 | /** | 2487 | /** |
2396 | * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table | 2488 | * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table |
@@ -2720,51 +2812,12 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) | |||
2720 | return 0; | 2812 | return 0; |
2721 | } | 2813 | } |
2722 | 2814 | ||
2723 | #define IWL3945_UCODE_GET(item) \ | ||
2724 | static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | ||
2725 | u32 api_ver) \ | ||
2726 | { \ | ||
2727 | return le32_to_cpu(ucode->u.v1.item); \ | ||
2728 | } | ||
2729 | |||
2730 | static u32 iwl3945_ucode_get_header_size(u32 api_ver) | ||
2731 | { | ||
2732 | return UCODE_HEADER_SIZE(1); | ||
2733 | } | ||
2734 | static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
2735 | u32 api_ver) | ||
2736 | { | ||
2737 | return 0; | ||
2738 | } | ||
2739 | static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode, | ||
2740 | u32 api_ver) | ||
2741 | { | ||
2742 | return (u8 *) ucode->u.v1.data; | ||
2743 | } | ||
2744 | |||
2745 | IWL3945_UCODE_GET(inst_size); | ||
2746 | IWL3945_UCODE_GET(data_size); | ||
2747 | IWL3945_UCODE_GET(init_size); | ||
2748 | IWL3945_UCODE_GET(init_data_size); | ||
2749 | IWL3945_UCODE_GET(boot_size); | ||
2750 | |||
2751 | static struct iwl_hcmd_ops iwl3945_hcmd = { | 2815 | static struct iwl_hcmd_ops iwl3945_hcmd = { |
2752 | .rxon_assoc = iwl3945_send_rxon_assoc, | 2816 | .rxon_assoc = iwl3945_send_rxon_assoc, |
2753 | .commit_rxon = iwl3945_commit_rxon, | 2817 | .commit_rxon = iwl3945_commit_rxon, |
2754 | .send_bt_config = iwl_send_bt_config, | 2818 | .send_bt_config = iwl_send_bt_config, |
2755 | }; | 2819 | }; |
2756 | 2820 | ||
2757 | static struct iwl_ucode_ops iwl3945_ucode = { | ||
2758 | .get_header_size = iwl3945_ucode_get_header_size, | ||
2759 | .get_build = iwl3945_ucode_get_build, | ||
2760 | .get_inst_size = iwl3945_ucode_get_inst_size, | ||
2761 | .get_data_size = iwl3945_ucode_get_data_size, | ||
2762 | .get_init_size = iwl3945_ucode_get_init_size, | ||
2763 | .get_init_data_size = iwl3945_ucode_get_init_data_size, | ||
2764 | .get_boot_size = iwl3945_ucode_get_boot_size, | ||
2765 | .get_data = iwl3945_ucode_get_data, | ||
2766 | }; | ||
2767 | |||
2768 | static struct iwl_lib_ops iwl3945_lib = { | 2821 | static struct iwl_lib_ops iwl3945_lib = { |
2769 | .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, | 2822 | .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, |
2770 | .txq_free_tfd = iwl3945_hw_txq_free_tfd, | 2823 | .txq_free_tfd = iwl3945_hw_txq_free_tfd, |
@@ -2798,7 +2851,8 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2798 | .post_associate = iwl3945_post_associate, | 2851 | .post_associate = iwl3945_post_associate, |
2799 | .isr = iwl_isr_legacy, | 2852 | .isr = iwl_isr_legacy, |
2800 | .config_ap = iwl3945_config_ap, | 2853 | .config_ap = iwl3945_config_ap, |
2801 | .add_bcast_station = iwl3945_add_bcast_station, | 2854 | .manage_ibss_station = iwl3945_manage_ibss_station, |
2855 | .check_plcp_health = iwl3945_good_plcp_health, | ||
2802 | 2856 | ||
2803 | .debugfs_ops = { | 2857 | .debugfs_ops = { |
2804 | .rx_stats_read = iwl3945_ucode_rx_stats_read, | 2858 | .rx_stats_read = iwl3945_ucode_rx_stats_read, |
@@ -2815,7 +2869,6 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | |||
2815 | }; | 2869 | }; |
2816 | 2870 | ||
2817 | static const struct iwl_ops iwl3945_ops = { | 2871 | static const struct iwl_ops iwl3945_ops = { |
2818 | .ucode = &iwl3945_ucode, | ||
2819 | .lib = &iwl3945_lib, | 2872 | .lib = &iwl3945_lib, |
2820 | .hcmd = &iwl3945_hcmd, | 2873 | .hcmd = &iwl3945_hcmd, |
2821 | .utils = &iwl3945_hcmd_utils, | 2874 | .utils = &iwl3945_hcmd_utils, |
@@ -2840,9 +2893,10 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2840 | .ht_greenfield_support = false, | 2893 | .ht_greenfield_support = false, |
2841 | .led_compensation = 64, | 2894 | .led_compensation = 64, |
2842 | .broken_powersave = true, | 2895 | .broken_powersave = true, |
2843 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2896 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
2844 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 2897 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
2845 | .max_event_log_size = 512, | 2898 | .max_event_log_size = 512, |
2899 | .tx_power_by_driver = true, | ||
2846 | }; | 2900 | }; |
2847 | 2901 | ||
2848 | static struct iwl_cfg iwl3945_abg_cfg = { | 2902 | static struct iwl_cfg iwl3945_abg_cfg = { |
@@ -2860,9 +2914,10 @@ static struct iwl_cfg iwl3945_abg_cfg = { | |||
2860 | .ht_greenfield_support = false, | 2914 | .ht_greenfield_support = false, |
2861 | .led_compensation = 64, | 2915 | .led_compensation = 64, |
2862 | .broken_powersave = true, | 2916 | .broken_powersave = true, |
2863 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2917 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
2864 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 2918 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
2865 | .max_event_log_size = 512, | 2919 | .max_event_log_size = 512, |
2920 | .tx_power_by_driver = true, | ||
2866 | }; | 2921 | }; |
2867 | 2922 | ||
2868 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { | 2923 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { |