diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2015-04-15 05:43:46 -0400 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2015-05-28 06:36:54 -0400 |
commit | 4203263d8302be20c5fa8a2ceb1ca3527808ad4e (patch) | |
tree | cf2a4eaae168d4bfdb02f9bc3e094da3cf336bbf /drivers/net/wireless/iwlwifi/mvm/mac80211.c | |
parent | 31eb07f5f8febab3d68b9d1a350d9e5a4bdf6780 (diff) |
iwlwifi: mvm: implement the BlockAck related debug triggers
BlockAck sessions can have events that are interesting to
debug. When we send or receive a BAR, it is may indicate
that something bad is happening. Even more so when mac80211
tells us that a frame timed out in the reodering buffer.
Add a few triggers for BlockAck session debugging.
Allow per-TID debugging.
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/mac80211.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 140 |
1 files changed, 136 insertions, 4 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index cea2366fc72e..71b66cb6ff12 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -737,6 +737,60 @@ static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg) | |||
737 | return true; | 737 | return true; |
738 | } | 738 | } |
739 | 739 | ||
740 | #define CHECK_BA_TRIGGER(_mvm, _trig, _tid_bm, _tid, _fmt...) \ | ||
741 | do { \ | ||
742 | if (!(le16_to_cpu(_tid_bm) & BIT(_tid))) \ | ||
743 | break; \ | ||
744 | iwl_mvm_fw_dbg_collect_trig(_mvm, _trig, _fmt); \ | ||
745 | } while (0) | ||
746 | |||
747 | static void | ||
748 | iwl_mvm_ampdu_check_trigger(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | ||
749 | struct ieee80211_sta *sta, u16 tid, u16 rx_ba_ssn, | ||
750 | enum ieee80211_ampdu_mlme_action action) | ||
751 | { | ||
752 | struct iwl_fw_dbg_trigger_tlv *trig; | ||
753 | struct iwl_fw_dbg_trigger_ba *ba_trig; | ||
754 | |||
755 | if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA)) | ||
756 | return; | ||
757 | |||
758 | trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA); | ||
759 | ba_trig = (void *)trig->data; | ||
760 | |||
761 | if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig)) | ||
762 | return; | ||
763 | |||
764 | switch (action) { | ||
765 | case IEEE80211_AMPDU_TX_OPERATIONAL: { | ||
766 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
767 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; | ||
768 | |||
769 | CHECK_BA_TRIGGER(mvm, trig, ba_trig->tx_ba_start, tid, | ||
770 | "TX AGG START: MAC %pM tid %d ssn %d\n", | ||
771 | sta->addr, tid, tid_data->ssn); | ||
772 | break; | ||
773 | } | ||
774 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
775 | CHECK_BA_TRIGGER(mvm, trig, ba_trig->tx_ba_stop, tid, | ||
776 | "TX AGG STOP: MAC %pM tid %d\n", | ||
777 | sta->addr, tid); | ||
778 | break; | ||
779 | case IEEE80211_AMPDU_RX_START: | ||
780 | CHECK_BA_TRIGGER(mvm, trig, ba_trig->rx_ba_start, tid, | ||
781 | "RX AGG START: MAC %pM tid %d ssn %d\n", | ||
782 | sta->addr, tid, rx_ba_ssn); | ||
783 | break; | ||
784 | case IEEE80211_AMPDU_RX_STOP: | ||
785 | CHECK_BA_TRIGGER(mvm, trig, ba_trig->rx_ba_stop, tid, | ||
786 | "RX AGG STOP: MAC %pM tid %d\n", | ||
787 | sta->addr, tid); | ||
788 | break; | ||
789 | default: | ||
790 | break; | ||
791 | } | ||
792 | } | ||
793 | |||
740 | static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | 794 | static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, |
741 | struct ieee80211_vif *vif, | 795 | struct ieee80211_vif *vif, |
742 | enum ieee80211_ampdu_mlme_action action, | 796 | enum ieee80211_ampdu_mlme_action action, |
@@ -813,6 +867,16 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
813 | ret = -EINVAL; | 867 | ret = -EINVAL; |
814 | break; | 868 | break; |
815 | } | 869 | } |
870 | |||
871 | if (!ret) { | ||
872 | u16 rx_ba_ssn = 0; | ||
873 | |||
874 | if (action == IEEE80211_AMPDU_RX_START) | ||
875 | rx_ba_ssn = *ssn; | ||
876 | |||
877 | iwl_mvm_ampdu_check_trigger(mvm, vif, sta, tid, | ||
878 | rx_ba_ssn, action); | ||
879 | } | ||
816 | mutex_unlock(&mvm->mutex); | 880 | mutex_unlock(&mvm->mutex); |
817 | 881 | ||
818 | /* | 882 | /* |
@@ -3904,9 +3968,9 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw, | |||
3904 | mutex_unlock(&mvm->mutex); | 3968 | mutex_unlock(&mvm->mutex); |
3905 | } | 3969 | } |
3906 | 3970 | ||
3907 | static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw, | 3971 | static void iwl_mvm_event_mlme_callback(struct iwl_mvm *mvm, |
3908 | struct ieee80211_vif *vif, | 3972 | struct ieee80211_vif *vif, |
3909 | const struct ieee80211_event *event) | 3973 | const struct ieee80211_event *event) |
3910 | { | 3974 | { |
3911 | #define CHECK_MLME_TRIGGER(_mvm, _trig, _buf, _cnt, _fmt...) \ | 3975 | #define CHECK_MLME_TRIGGER(_mvm, _trig, _buf, _cnt, _fmt...) \ |
3912 | do { \ | 3976 | do { \ |
@@ -3915,7 +3979,6 @@ static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw, | |||
3915 | iwl_mvm_fw_dbg_collect_trig(_mvm, _trig, _fmt);\ | 3979 | iwl_mvm_fw_dbg_collect_trig(_mvm, _trig, _fmt);\ |
3916 | } while (0) | 3980 | } while (0) |
3917 | 3981 | ||
3918 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
3919 | struct iwl_fw_dbg_trigger_tlv *trig; | 3982 | struct iwl_fw_dbg_trigger_tlv *trig; |
3920 | struct iwl_fw_dbg_trigger_mlme *trig_mlme; | 3983 | struct iwl_fw_dbg_trigger_mlme *trig_mlme; |
3921 | 3984 | ||
@@ -3959,6 +4022,75 @@ static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw, | |||
3959 | #undef CHECK_MLME_TRIGGER | 4022 | #undef CHECK_MLME_TRIGGER |
3960 | } | 4023 | } |
3961 | 4024 | ||
4025 | static void iwl_mvm_event_bar_rx_callback(struct iwl_mvm *mvm, | ||
4026 | struct ieee80211_vif *vif, | ||
4027 | const struct ieee80211_event *event) | ||
4028 | { | ||
4029 | struct iwl_fw_dbg_trigger_tlv *trig; | ||
4030 | struct iwl_fw_dbg_trigger_ba *ba_trig; | ||
4031 | |||
4032 | if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA)) | ||
4033 | return; | ||
4034 | |||
4035 | trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA); | ||
4036 | ba_trig = (void *)trig->data; | ||
4037 | if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig)) | ||
4038 | return; | ||
4039 | |||
4040 | if (!(le16_to_cpu(ba_trig->rx_bar) & BIT(event->u.ba.tid))) | ||
4041 | return; | ||
4042 | |||
4043 | iwl_mvm_fw_dbg_collect_trig(mvm, trig, | ||
4044 | "BAR received from %pM, tid %d, ssn %d", | ||
4045 | event->u.ba.sta->addr, event->u.ba.tid, | ||
4046 | event->u.ba.ssn); | ||
4047 | } | ||
4048 | |||
4049 | static void | ||
4050 | iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm, | ||
4051 | struct ieee80211_vif *vif, | ||
4052 | const struct ieee80211_event *event) | ||
4053 | { | ||
4054 | struct iwl_fw_dbg_trigger_tlv *trig; | ||
4055 | struct iwl_fw_dbg_trigger_ba *ba_trig; | ||
4056 | |||
4057 | if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA)) | ||
4058 | return; | ||
4059 | |||
4060 | trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA); | ||
4061 | ba_trig = (void *)trig->data; | ||
4062 | if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig)) | ||
4063 | return; | ||
4064 | |||
4065 | if (!(le16_to_cpu(ba_trig->frame_timeout) & BIT(event->u.ba.tid))) | ||
4066 | return; | ||
4067 | |||
4068 | iwl_mvm_fw_dbg_collect_trig(mvm, trig, | ||
4069 | "Frame from %pM timed out, tid %d", | ||
4070 | event->u.ba.sta->addr, event->u.ba.tid); | ||
4071 | } | ||
4072 | |||
4073 | static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw, | ||
4074 | struct ieee80211_vif *vif, | ||
4075 | const struct ieee80211_event *event) | ||
4076 | { | ||
4077 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
4078 | |||
4079 | switch (event->type) { | ||
4080 | case MLME_EVENT: | ||
4081 | iwl_mvm_event_mlme_callback(mvm, vif, event); | ||
4082 | break; | ||
4083 | case BAR_RX_EVENT: | ||
4084 | iwl_mvm_event_bar_rx_callback(mvm, vif, event); | ||
4085 | break; | ||
4086 | case BA_FRAME_TIMEOUT: | ||
4087 | iwl_mvm_event_frame_timeout_callback(mvm, vif, event); | ||
4088 | break; | ||
4089 | default: | ||
4090 | break; | ||
4091 | } | ||
4092 | } | ||
4093 | |||
3962 | const struct ieee80211_ops iwl_mvm_hw_ops = { | 4094 | const struct ieee80211_ops iwl_mvm_hw_ops = { |
3963 | .tx = iwl_mvm_mac_tx, | 4095 | .tx = iwl_mvm_mac_tx, |
3964 | .ampdu_action = iwl_mvm_mac_ampdu_action, | 4096 | .ampdu_action = iwl_mvm_mac_ampdu_action, |