aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c78
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c75
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c6
9 files changed, 103 insertions, 85 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index ab5027345a01..1688803af582 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -555,8 +555,6 @@ out:
555 return ret; 555 return ret;
556} 556}
557 557
558#define REG_RECALIB_PERIOD (60)
559
560/* Reset differential Rx gains in NIC to prepare for chain noise calibration. 558/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
561 * Called after every association, but this runs only once! 559 * Called after every association, but this runs only once!
562 * ... once chain noise is calibrated the first time, it's good forever. */ 560 * ... once chain noise is calibrated the first time, it's good forever. */
@@ -1890,80 +1888,15 @@ static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
1890 return 1; 1888 return 1;
1891} 1889}
1892 1890
1893/* Calculate noise level, based on measurements during network silence just 1891static void iwl4965_temperature_calib(struct iwl_priv *priv,
1894 * before arriving beacon. This measurement can be done only if we know 1892 struct iwl_notif_statistics *stats)
1895 * exactly when to expect beacons, therefore only when we're associated. */
1896static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
1897{ 1893{
1898 struct statistics_rx_non_phy *rx_info
1899 = &(priv->statistics.rx.general);
1900 int num_active_rx = 0;
1901 int total_silence = 0;
1902 int bcn_silence_a =
1903 le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
1904 int bcn_silence_b =
1905 le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
1906 int bcn_silence_c =
1907 le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
1908
1909 if (bcn_silence_a) {
1910 total_silence += bcn_silence_a;
1911 num_active_rx++;
1912 }
1913 if (bcn_silence_b) {
1914 total_silence += bcn_silence_b;
1915 num_active_rx++;
1916 }
1917 if (bcn_silence_c) {
1918 total_silence += bcn_silence_c;
1919 num_active_rx++;
1920 }
1921
1922 /* Average among active antennas */
1923 if (num_active_rx)
1924 priv->last_rx_noise = (total_silence / num_active_rx) - 107;
1925 else
1926 priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
1927
1928 IWL_DEBUG_CALIB("inband silence a %u, b %u, c %u, dBm %d\n",
1929 bcn_silence_a, bcn_silence_b, bcn_silence_c,
1930 priv->last_rx_noise);
1931}
1932
1933void iwl4965_hw_rx_statistics(struct iwl_priv *priv,
1934 struct iwl_rx_mem_buffer *rxb)
1935{
1936 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
1937 int change;
1938 s32 temp; 1894 s32 temp;
1939 1895 int change = ((priv->statistics.general.temperature !=
1940 IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n", 1896 stats->general.temperature) ||
1941 (int)sizeof(priv->statistics), pkt->len);
1942
1943 change = ((priv->statistics.general.temperature !=
1944 pkt->u.stats.general.temperature) ||
1945 ((priv->statistics.flag & 1897 ((priv->statistics.flag &
1946 STATISTICS_REPLY_FLG_FAT_MODE_MSK) != 1898 STATISTICS_REPLY_FLG_FAT_MODE_MSK) !=
1947 (pkt->u.stats.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK))); 1899 (stats->flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK)));
1948
1949 memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
1950
1951 set_bit(STATUS_STATISTICS, &priv->status);
1952
1953 /* Reschedule the statistics timer to occur in
1954 * REG_RECALIB_PERIOD seconds to ensure we get a
1955 * thermal update even if the uCode doesn't give
1956 * us one */
1957 mod_timer(&priv->statistics_periodic, jiffies +
1958 msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
1959
1960 if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
1961 (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
1962 iwl4965_rx_calc_noise(priv);
1963 queue_work(priv->workqueue, &priv->run_time_calib_work);
1964 }
1965
1966 iwl_leds_background(priv);
1967 1900
1968 /* If the hardware hasn't reported a change in 1901 /* If the hardware hasn't reported a change in
1969 * temperature then don't bother computing a 1902 * temperature then don't bother computing a
@@ -3391,6 +3324,7 @@ static struct iwl_lib_ops iwl4965_lib = {
3391 .set_power = iwl4965_set_power, 3324 .set_power = iwl4965_set_power,
3392 .send_tx_power = iwl4965_send_tx_power, 3325 .send_tx_power = iwl4965_send_tx_power,
3393 .update_chain_flags = iwl4965_update_chain_flags, 3326 .update_chain_flags = iwl4965_update_chain_flags,
3327 .temperature = iwl4965_temperature_calib,
3394}; 3328};
3395 3329
3396static struct iwl_ops iwl4965_ops = { 3330static struct iwl_ops iwl4965_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 2b48f1b19140..5abfd56e9bb4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1433,6 +1433,12 @@ static int iwl5000_send_tx_power(struct iwl_priv *priv)
1433 NULL); 1433 NULL);
1434} 1434}
1435 1435
1436static void iwl5000_temperature(struct iwl_priv *priv,
1437 struct iwl_notif_statistics *stats)
1438{
1439 /* store temperature from statistics (in Celsius) */
1440 priv->temperature = le32_to_cpu(stats->general.temperature);
1441}
1436 1442
1437static struct iwl_hcmd_ops iwl5000_hcmd = { 1443static struct iwl_hcmd_ops iwl5000_hcmd = {
1438 .rxon_assoc = iwl5000_send_rxon_assoc, 1444 .rxon_assoc = iwl5000_send_rxon_assoc,
@@ -1462,6 +1468,7 @@ static struct iwl_lib_ops iwl5000_lib = {
1462 .init_alive_start = iwl5000_init_alive_start, 1468 .init_alive_start = iwl5000_init_alive_start,
1463 .alive_notify = iwl5000_alive_notify, 1469 .alive_notify = iwl5000_alive_notify,
1464 .send_tx_power = iwl5000_send_tx_power, 1470 .send_tx_power = iwl5000_send_tx_power,
1471 .temperature = iwl5000_temperature,
1465 .apm_ops = { 1472 .apm_ops = {
1466 .init = iwl5000_apm_init, 1473 .init = iwl5000_apm_init,
1467 .reset = iwl5000_apm_reset, 1474 .reset = iwl5000_apm_reset,
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index 48f58000b64b..ef49440bd7f6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -470,7 +470,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
470EXPORT_SYMBOL(iwl_init_sensitivity); 470EXPORT_SYMBOL(iwl_init_sensitivity);
471 471
472void iwl_sensitivity_calibration(struct iwl_priv *priv, 472void iwl_sensitivity_calibration(struct iwl_priv *priv,
473 struct iwl4965_notif_statistics *resp) 473 struct iwl_notif_statistics *resp)
474{ 474{
475 u32 rx_enable_time; 475 u32 rx_enable_time;
476 u32 fa_cck; 476 u32 fa_cck;
@@ -584,7 +584,7 @@ EXPORT_SYMBOL(iwl_sensitivity_calibration);
584 * 2) Differential rx gain settings to balance the 3 receivers. 584 * 2) Differential rx gain settings to balance the 3 receivers.
585 */ 585 */
586void iwl_chain_noise_calibration(struct iwl_priv *priv, 586void iwl_chain_noise_calibration(struct iwl_priv *priv,
587 struct iwl4965_notif_statistics *stat_resp) 587 struct iwl_notif_statistics *stat_resp)
588{ 588{
589 struct iwl_chain_noise_data *data = NULL; 589 struct iwl_chain_noise_data *data = NULL;
590 590
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h
index 5524a29e22d8..94c8e316382a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.h
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.h
@@ -67,9 +67,9 @@
67#include "iwl-commands.h" 67#include "iwl-commands.h"
68 68
69void iwl_chain_noise_calibration(struct iwl_priv *priv, 69void iwl_chain_noise_calibration(struct iwl_priv *priv,
70 struct iwl4965_notif_statistics *stat_resp); 70 struct iwl_notif_statistics *stat_resp);
71void iwl_sensitivity_calibration(struct iwl_priv *priv, 71void iwl_sensitivity_calibration(struct iwl_priv *priv,
72 struct iwl4965_notif_statistics *resp); 72 struct iwl_notif_statistics *resp);
73 73
74void iwl_init_sensitivity(struct iwl_priv *priv); 74void iwl_init_sensitivity(struct iwl_priv *priv);
75void iwl_reset_run_time_calib(struct iwl_priv *priv); 75void iwl_reset_run_time_calib(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 6957b2208240..9f8446c5a1bc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -2506,7 +2506,7 @@ struct statistics_general {
2506 */ 2506 */
2507#define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1) /* see above */ 2507#define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1) /* see above */
2508#define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */ 2508#define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */
2509struct iwl4965_statistics_cmd { 2509struct iwl_statistics_cmd {
2510 __le32 configuration_flags; /* IWL_STATS_CONF_* */ 2510 __le32 configuration_flags; /* IWL_STATS_CONF_* */
2511} __attribute__ ((packed)); 2511} __attribute__ ((packed));
2512 2512
@@ -2527,7 +2527,7 @@ struct iwl4965_statistics_cmd {
2527 */ 2527 */
2528#define STATISTICS_REPLY_FLG_BAND_24G_MSK __constant_cpu_to_le32(0x2) 2528#define STATISTICS_REPLY_FLG_BAND_24G_MSK __constant_cpu_to_le32(0x2)
2529#define STATISTICS_REPLY_FLG_FAT_MODE_MSK __constant_cpu_to_le32(0x8) 2529#define STATISTICS_REPLY_FLG_FAT_MODE_MSK __constant_cpu_to_le32(0x8)
2530struct iwl4965_notif_statistics { 2530struct iwl_notif_statistics {
2531 __le32 flag; 2531 __le32 flag;
2532 struct statistics_rx rx; 2532 struct statistics_rx rx;
2533 struct statistics_tx tx; 2533 struct statistics_tx tx;
@@ -3000,7 +3000,7 @@ struct iwl_rx_packet {
3000 struct iwl_rem_sta_resp rem_sta; 3000 struct iwl_rem_sta_resp rem_sta;
3001 struct iwl4965_sleep_notification sleep_notif; 3001 struct iwl4965_sleep_notification sleep_notif;
3002 struct iwl4965_spectrum_resp spectrum; 3002 struct iwl4965_spectrum_resp spectrum;
3003 struct iwl4965_notif_statistics stats; 3003 struct iwl_notif_statistics stats;
3004 struct iwl4965_compressed_ba_resp compressed_ba; 3004 struct iwl4965_compressed_ba_resp compressed_ba;
3005 struct iwl4965_missed_beacon_notif missed_beacon; 3005 struct iwl4965_missed_beacon_notif missed_beacon;
3006 struct iwl5000_calibration calib; 3006 struct iwl5000_calibration calib;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 2838093b4459..375afe15b54b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -140,6 +140,8 @@ struct iwl_lib_ops {
140 int (*set_power)(struct iwl_priv *priv, void *cmd); 140 int (*set_power)(struct iwl_priv *priv, void *cmd);
141 int (*send_tx_power) (struct iwl_priv *priv); 141 int (*send_tx_power) (struct iwl_priv *priv);
142 void (*update_chain_flags)(struct iwl_priv *priv); 142 void (*update_chain_flags)(struct iwl_priv *priv);
143 void (*temperature) (struct iwl_priv *priv,
144 struct iwl_notif_statistics *stats);
143 /* eeprom operations (as defined in iwl-eeprom.h) */ 145 /* eeprom operations (as defined in iwl-eeprom.h) */
144 struct iwl_eeprom_ops eeprom_ops; 146 struct iwl_eeprom_ops eeprom_ops;
145}; 147};
@@ -218,6 +220,8 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
218/* Handlers */ 220/* Handlers */
219void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, 221void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
220 struct iwl_rx_mem_buffer *rxb); 222 struct iwl_rx_mem_buffer *rxb);
223void iwl_rx_statistics(struct iwl_priv *priv,
224 struct iwl_rx_mem_buffer *rxb);
221 225
222/* TX helpers */ 226/* TX helpers */
223 227
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 81ff4c2c6a5a..fd008ab63bd9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -624,8 +624,6 @@ extern int iwl_rxq_stop(struct iwl_priv *priv);
624extern void iwl_txq_ctx_stop(struct iwl_priv *priv); 624extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
625extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, 625extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
626 struct iwl_frame *frame, u8 rate); 626 struct iwl_frame *frame, u8 rate);
627extern void iwl4965_hw_rx_statistics(struct iwl_priv *priv,
628 struct iwl_rx_mem_buffer *rxb);
629extern void iwl4965_disable_events(struct iwl_priv *priv); 627extern void iwl4965_disable_events(struct iwl_priv *priv);
630extern void iwl4965_rx_reply_rx(struct iwl_priv *priv, 628extern void iwl4965_rx_reply_rx(struct iwl_priv *priv,
631 struct iwl_rx_mem_buffer *rxb); 629 struct iwl_rx_mem_buffer *rxb);
@@ -994,7 +992,7 @@ struct iwl_priv {
994 992
995 struct iwl_power_mgr power_data; 993 struct iwl_power_mgr power_data;
996 994
997 struct iwl4965_notif_statistics statistics; 995 struct iwl_notif_statistics statistics;
998 unsigned long last_statistics_time; 996 unsigned long last_statistics_time;
999 997
1000 /* context information */ 998 /* context information */
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index c24844802a88..b3ca1375c01a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -466,3 +466,78 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
466 } 466 }
467} 467}
468EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); 468EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
469
470
471/* Calculate noise level, based on measurements during network silence just
472 * before arriving beacon. This measurement can be done only if we know
473 * exactly when to expect beacons, therefore only when we're associated. */
474static void iwl_rx_calc_noise(struct iwl_priv *priv)
475{
476 struct statistics_rx_non_phy *rx_info
477 = &(priv->statistics.rx.general);
478 int num_active_rx = 0;
479 int total_silence = 0;
480 int bcn_silence_a =
481 le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
482 int bcn_silence_b =
483 le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
484 int bcn_silence_c =
485 le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
486
487 if (bcn_silence_a) {
488 total_silence += bcn_silence_a;
489 num_active_rx++;
490 }
491 if (bcn_silence_b) {
492 total_silence += bcn_silence_b;
493 num_active_rx++;
494 }
495 if (bcn_silence_c) {
496 total_silence += bcn_silence_c;
497 num_active_rx++;
498 }
499
500 /* Average among active antennas */
501 if (num_active_rx)
502 priv->last_rx_noise = (total_silence / num_active_rx) - 107;
503 else
504 priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
505
506 IWL_DEBUG_CALIB("inband silence a %u, b %u, c %u, dBm %d\n",
507 bcn_silence_a, bcn_silence_b, bcn_silence_c,
508 priv->last_rx_noise);
509}
510
511#define REG_RECALIB_PERIOD (60)
512
513void iwl_rx_statistics(struct iwl_priv *priv,
514 struct iwl_rx_mem_buffer *rxb)
515{
516 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
517
518 IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n",
519 (int)sizeof(priv->statistics), pkt->len);
520
521 memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
522
523 set_bit(STATUS_STATISTICS, &priv->status);
524
525 /* Reschedule the statistics timer to occur in
526 * REG_RECALIB_PERIOD seconds to ensure we get a
527 * thermal update even if the uCode doesn't give
528 * us one */
529 mod_timer(&priv->statistics_periodic, jiffies +
530 msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
531
532 if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
533 (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
534 iwl_rx_calc_noise(priv);
535 queue_work(priv->workqueue, &priv->run_time_calib_work);
536 }
537
538 iwl_leds_background(priv);
539
540 if (priv->cfg->ops->lib->temperature)
541 priv->cfg->ops->lib->temperature(priv, &pkt->u.stats);
542}
543EXPORT_SYMBOL(iwl_rx_statistics);
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 0a279d15e058..13d53f3009d8 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1387,8 +1387,8 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
1387 * statistics request from the host as well as for the periodic 1387 * statistics request from the host as well as for the periodic
1388 * statistics notifications (after received beacons) from the uCode. 1388 * statistics notifications (after received beacons) from the uCode.
1389 */ 1389 */
1390 priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_hw_rx_statistics; 1390 priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics;
1391 priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_hw_rx_statistics; 1391 priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
1392 1392
1393 iwl_setup_rx_scan_handlers(priv); 1393 iwl_setup_rx_scan_handlers(priv);
1394 1394
@@ -4130,7 +4130,7 @@ static ssize_t show_statistics(struct device *d,
4130 struct device_attribute *attr, char *buf) 4130 struct device_attribute *attr, char *buf)
4131{ 4131{
4132 struct iwl_priv *priv = dev_get_drvdata(d); 4132 struct iwl_priv *priv = dev_get_drvdata(d);
4133 u32 size = sizeof(struct iwl4965_notif_statistics); 4133 u32 size = sizeof(struct iwl_notif_statistics);
4134 u32 len = 0, ofs = 0; 4134 u32 len = 0, ofs = 0;
4135 u8 *data = (u8 *) & priv->statistics; 4135 u8 *data = (u8 *) & priv->statistics;
4136 int rc = 0; 4136 int rc = 0;