aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/mac80211.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-04-15 05:43:46 -0400
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-05-28 06:36:54 -0400
commit4203263d8302be20c5fa8a2ceb1ca3527808ad4e (patch)
treecf2a4eaae168d4bfdb02f9bc3e094da3cf336bbf /drivers/net/wireless/iwlwifi/mvm/mac80211.c
parent31eb07f5f8febab3d68b9d1a350d9e5a4bdf6780 (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.c140
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
747static void
748iwl_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
740static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, 794static 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
3907static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw, 3971static 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
4025static 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
4049static void
4050iwl_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
4073static 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
3962const struct ieee80211_ops iwl_mvm_hw_ops = { 4094const 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,