diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-03-05 14:24:26 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-03-06 15:16:09 -0500 |
commit | 4ff70fcdf3c424c3fdca253e7b7556f77eaf39be (patch) | |
tree | d60d5343463c3dcdc2969dc2df273716b2145927 /drivers | |
parent | fa23cb04b38a9950b21ee756e4419a737d496371 (diff) |
iwlwifi: introduce statistics lock
The statistics are currently only half-heartedly
locked against concurrent reading & modification
so introduce a lock to really protect them.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debugfs.c | 21 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 1 |
6 files changed, 40 insertions, 9 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 988ee454a944..12acc81ed419 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c | |||
@@ -655,7 +655,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) | |||
655 | struct iwl_sensitivity_data *data = NULL; | 655 | struct iwl_sensitivity_data *data = NULL; |
656 | struct statistics_rx_non_phy *rx_info; | 656 | struct statistics_rx_non_phy *rx_info; |
657 | struct statistics_rx_phy *ofdm, *cck; | 657 | struct statistics_rx_phy *ofdm, *cck; |
658 | unsigned long flags; | ||
659 | struct statistics_general_data statis; | 658 | struct statistics_general_data statis; |
660 | 659 | ||
661 | if (priv->disable_sens_cal) | 660 | if (priv->disable_sens_cal) |
@@ -668,13 +667,13 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) | |||
668 | return; | 667 | return; |
669 | } | 668 | } |
670 | 669 | ||
671 | spin_lock_irqsave(&priv->shrd->lock, flags); | 670 | spin_lock_bh(&priv->statistics.lock); |
672 | rx_info = &priv->statistics.rx_non_phy; | 671 | rx_info = &priv->statistics.rx_non_phy; |
673 | ofdm = &priv->statistics.rx_ofdm; | 672 | ofdm = &priv->statistics.rx_ofdm; |
674 | cck = &priv->statistics.rx_cck; | 673 | cck = &priv->statistics.rx_cck; |
675 | if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { | 674 | if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { |
676 | IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); | 675 | IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); |
677 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 676 | spin_unlock_bh(&priv->statistics.lock); |
678 | return; | 677 | return; |
679 | } | 678 | } |
680 | 679 | ||
@@ -698,7 +697,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) | |||
698 | statis.beacon_energy_c = | 697 | statis.beacon_energy_c = |
699 | le32_to_cpu(rx_info->beacon_energy_c); | 698 | le32_to_cpu(rx_info->beacon_energy_c); |
700 | 699 | ||
701 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 700 | spin_unlock_bh(&priv->statistics.lock); |
702 | 701 | ||
703 | IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); | 702 | IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); |
704 | 703 | ||
@@ -958,7 +957,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
958 | u16 stat_chnum = INITIALIZATION_VALUE; | 957 | u16 stat_chnum = INITIALIZATION_VALUE; |
959 | u8 rxon_band24; | 958 | u8 rxon_band24; |
960 | u8 stat_band24; | 959 | u8 stat_band24; |
961 | unsigned long flags; | ||
962 | struct statistics_rx_non_phy *rx_info; | 960 | struct statistics_rx_non_phy *rx_info; |
963 | 961 | ||
964 | /* | 962 | /* |
@@ -983,13 +981,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
983 | return; | 981 | return; |
984 | } | 982 | } |
985 | 983 | ||
986 | spin_lock_irqsave(&priv->shrd->lock, flags); | 984 | spin_lock_bh(&priv->statistics.lock); |
987 | 985 | ||
988 | rx_info = &priv->statistics.rx_non_phy; | 986 | rx_info = &priv->statistics.rx_non_phy; |
989 | 987 | ||
990 | if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { | 988 | if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { |
991 | IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); | 989 | IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); |
992 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 990 | spin_unlock_bh(&priv->statistics.lock); |
993 | return; | 991 | return; |
994 | } | 992 | } |
995 | 993 | ||
@@ -1004,7 +1002,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1004 | if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) { | 1002 | if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) { |
1005 | IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n", | 1003 | IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n", |
1006 | rxon_chnum, rxon_band24); | 1004 | rxon_chnum, rxon_band24); |
1007 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 1005 | spin_unlock_bh(&priv->statistics.lock); |
1008 | return; | 1006 | return; |
1009 | } | 1007 | } |
1010 | 1008 | ||
@@ -1023,7 +1021,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | |||
1023 | chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER; | 1021 | chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER; |
1024 | chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER; | 1022 | chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER; |
1025 | 1023 | ||
1026 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 1024 | spin_unlock_bh(&priv->statistics.lock); |
1027 | 1025 | ||
1028 | data->beacon_count++; | 1026 | data->beacon_count++; |
1029 | 1027 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 5be0d3695d03..0f8dd0f96fa6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -88,6 +88,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | |||
88 | 88 | ||
89 | void iwlagn_temperature(struct iwl_priv *priv) | 89 | void iwlagn_temperature(struct iwl_priv *priv) |
90 | { | 90 | { |
91 | lockdep_assert_held(&priv->statistics.lock); | ||
92 | |||
91 | /* store temperature from correct statistics (in Celsius) */ | 93 | /* store temperature from correct statistics (in Celsius) */ |
92 | priv->temperature = le32_to_cpu(priv->statistics.common.temperature); | 94 | priv->temperature = le32_to_cpu(priv->statistics.common.temperature); |
93 | iwl_tt_handler(priv); | 95 | iwl_tt_handler(priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 30bb5bbb0cd7..bc21586aed63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c | |||
@@ -266,6 +266,8 @@ static bool iwlagn_good_ack_health(struct iwl_priv *priv, | |||
266 | if (priv->agg_tids_count) | 266 | if (priv->agg_tids_count) |
267 | return true; | 267 | return true; |
268 | 268 | ||
269 | lockdep_assert_held(&priv->statistics.lock); | ||
270 | |||
269 | old = &priv->statistics.tx; | 271 | old = &priv->statistics.tx; |
270 | 272 | ||
271 | actual_delta = le32_to_cpu(cur->actual_ack_cnt) - | 273 | actual_delta = le32_to_cpu(cur->actual_ack_cnt) - |
@@ -509,6 +511,8 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, | |||
509 | IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n", | 511 | IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n", |
510 | len); | 512 | len); |
511 | 513 | ||
514 | spin_lock(&priv->statistics.lock); | ||
515 | |||
512 | if (len == sizeof(struct iwl_bt_notif_statistics)) { | 516 | if (len == sizeof(struct iwl_bt_notif_statistics)) { |
513 | struct iwl_bt_notif_statistics *stats; | 517 | struct iwl_bt_notif_statistics *stats; |
514 | stats = &pkt->u.stats_bt; | 518 | stats = &pkt->u.stats_bt; |
@@ -542,6 +546,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, | |||
542 | WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n", | 546 | WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n", |
543 | len, sizeof(struct iwl_bt_notif_statistics), | 547 | len, sizeof(struct iwl_bt_notif_statistics), |
544 | sizeof(struct iwl_notif_statistics)); | 548 | sizeof(struct iwl_notif_statistics)); |
549 | spin_unlock(&priv->statistics.lock); | ||
545 | return 0; | 550 | return 0; |
546 | } | 551 | } |
547 | 552 | ||
@@ -585,6 +590,9 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, | |||
585 | } | 590 | } |
586 | if (cfg(priv)->lib->temperature && change) | 591 | if (cfg(priv)->lib->temperature && change) |
587 | cfg(priv)->lib->temperature(priv); | 592 | cfg(priv)->lib->temperature(priv); |
593 | |||
594 | spin_unlock(&priv->statistics.lock); | ||
595 | |||
588 | return 0; | 596 | return 0; |
589 | } | 597 | } |
590 | 598 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0090fab3aacb..47c788607024 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -1233,6 +1233,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans) | |||
1233 | */ | 1233 | */ |
1234 | spin_lock_init(&trans(priv)->reg_lock); | 1234 | spin_lock_init(&trans(priv)->reg_lock); |
1235 | spin_lock_init(&priv->shrd->lock); | 1235 | spin_lock_init(&priv->shrd->lock); |
1236 | spin_lock_init(&priv->statistics.lock); | ||
1236 | 1237 | ||
1237 | /*********************** | 1238 | /*********************** |
1238 | * 3. Read REV register | 1239 | * 3. Read REV register |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index ad74138e1c70..628af563e4e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -920,6 +920,8 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | |||
920 | int p = 0; | 920 | int p = 0; |
921 | u32 flag; | 921 | u32 flag; |
922 | 922 | ||
923 | lockdep_assert_held(&priv->statistics.lock); | ||
924 | |||
923 | flag = le32_to_cpu(priv->statistics.flag); | 925 | flag = le32_to_cpu(priv->statistics.flag); |
924 | 926 | ||
925 | p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag); | 927 | p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag); |
@@ -967,6 +969,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | |||
967 | * the last statistics notification from uCode | 969 | * the last statistics notification from uCode |
968 | * might not reflect the current uCode activity | 970 | * might not reflect the current uCode activity |
969 | */ | 971 | */ |
972 | spin_lock_bh(&priv->statistics.lock); | ||
970 | ofdm = &priv->statistics.rx_ofdm; | 973 | ofdm = &priv->statistics.rx_ofdm; |
971 | cck = &priv->statistics.rx_cck; | 974 | cck = &priv->statistics.rx_cck; |
972 | general = &priv->statistics.rx_non_phy; | 975 | general = &priv->statistics.rx_non_phy; |
@@ -1363,6 +1366,8 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | |||
1363 | accum_ht->unsupport_mcs, | 1366 | accum_ht->unsupport_mcs, |
1364 | delta_ht->unsupport_mcs, max_ht->unsupport_mcs); | 1367 | delta_ht->unsupport_mcs, max_ht->unsupport_mcs); |
1365 | 1368 | ||
1369 | spin_unlock_bh(&priv->statistics.lock); | ||
1370 | |||
1366 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1371 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1367 | kfree(buf); | 1372 | kfree(buf); |
1368 | return ret; | 1373 | return ret; |
@@ -1392,6 +1397,8 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1392 | * the last statistics notification from uCode | 1397 | * the last statistics notification from uCode |
1393 | * might not reflect the current uCode activity | 1398 | * might not reflect the current uCode activity |
1394 | */ | 1399 | */ |
1400 | spin_lock_bh(&priv->statistics.lock); | ||
1401 | |||
1395 | tx = &priv->statistics.tx; | 1402 | tx = &priv->statistics.tx; |
1396 | accum_tx = &priv->accum_stats.tx; | 1403 | accum_tx = &priv->accum_stats.tx; |
1397 | delta_tx = &priv->delta_stats.tx; | 1404 | delta_tx = &priv->delta_stats.tx; |
@@ -1554,6 +1561,9 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1554 | fmt_hex, "antenna C:", | 1561 | fmt_hex, "antenna C:", |
1555 | tx->tx_power.ant_c); | 1562 | tx->tx_power.ant_c); |
1556 | } | 1563 | } |
1564 | |||
1565 | spin_unlock_bh(&priv->statistics.lock); | ||
1566 | |||
1557 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1567 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1558 | kfree(buf); | 1568 | kfree(buf); |
1559 | return ret; | 1569 | return ret; |
@@ -1586,6 +1596,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | |||
1586 | * the last statistics notification from uCode | 1596 | * the last statistics notification from uCode |
1587 | * might not reflect the current uCode activity | 1597 | * might not reflect the current uCode activity |
1588 | */ | 1598 | */ |
1599 | |||
1600 | spin_lock_bh(&priv->statistics.lock); | ||
1601 | |||
1589 | general = &priv->statistics.common; | 1602 | general = &priv->statistics.common; |
1590 | dbg = &priv->statistics.common.dbg; | 1603 | dbg = &priv->statistics.common.dbg; |
1591 | div = &priv->statistics.common.div; | 1604 | div = &priv->statistics.common.div; |
@@ -1670,6 +1683,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | |||
1670 | accum_general->num_of_sos_states, | 1683 | accum_general->num_of_sos_states, |
1671 | delta_general->num_of_sos_states, | 1684 | delta_general->num_of_sos_states, |
1672 | max_general->num_of_sos_states); | 1685 | max_general->num_of_sos_states); |
1686 | |||
1687 | spin_unlock_bh(&priv->statistics.lock); | ||
1688 | |||
1673 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1689 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1674 | kfree(buf); | 1690 | kfree(buf); |
1675 | return ret; | 1691 | return ret; |
@@ -1713,6 +1729,9 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, | |||
1713 | * the last statistics notification from uCode | 1729 | * the last statistics notification from uCode |
1714 | * might not reflect the current uCode activity | 1730 | * might not reflect the current uCode activity |
1715 | */ | 1731 | */ |
1732 | |||
1733 | spin_lock_bh(&priv->statistics.lock); | ||
1734 | |||
1716 | bt = &priv->statistics.bt_activity; | 1735 | bt = &priv->statistics.bt_activity; |
1717 | accum_bt = &priv->accum_stats.bt_activity; | 1736 | accum_bt = &priv->accum_stats.bt_activity; |
1718 | 1737 | ||
@@ -1758,6 +1777,8 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, | |||
1758 | le32_to_cpu(priv->statistics.num_bt_kills), | 1777 | le32_to_cpu(priv->statistics.num_bt_kills), |
1759 | priv->statistics.accum_num_bt_kills); | 1778 | priv->statistics.accum_num_bt_kills); |
1760 | 1779 | ||
1780 | spin_unlock_bh(&priv->statistics.lock); | ||
1781 | |||
1761 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1782 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1762 | kfree(buf); | 1783 | kfree(buf); |
1763 | return ret; | 1784 | return ret; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index dc57522594a6..daf233026b5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -851,6 +851,7 @@ struct iwl_priv { | |||
851 | struct statistics_bt_activity bt_activity; | 851 | struct statistics_bt_activity bt_activity; |
852 | __le32 num_bt_kills, accum_num_bt_kills; | 852 | __le32 num_bt_kills, accum_num_bt_kills; |
853 | #endif | 853 | #endif |
854 | spinlock_t lock; | ||
854 | } statistics; | 855 | } statistics; |
855 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 856 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
856 | struct { | 857 | struct { |