aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-03-05 14:24:26 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-03-06 15:16:09 -0500
commit4ff70fcdf3c424c3fdca253e7b7556f77eaf39be (patch)
treed60d5343463c3dcdc2969dc2df273716b2145927 /drivers
parentfa23cb04b38a9950b21ee756e4419a737d496371 (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.c16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
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
89void iwlagn_temperature(struct iwl_priv *priv) 89void 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 {