aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
diff options
context:
space:
mode:
authorAviya Erenfeld <aviya.erenfeld@intel.com>2016-02-18 07:09:33 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2016-03-30 09:21:07 -0400
commit03098268a30d75188f15dd8fda8f0c896d2846e5 (patch)
tree3b702f12076d1b5ce32d96966697d5992769b565 /drivers/net/wireless/intel/iwlwifi/mvm/utils.c
parent5b086414293f906d8c5692cbbfa3500458982e5d (diff)
iwlwifi: mvm: add LQM vendor command and notification
LQM stands for Link Quality Measurement. The firmware will collect a defined set of statitics (see the notification for details) that allow to know how busy the medium is. The driver issues a request to the firmware that includes the duration of the measurement (the firmware needs to be on channel for that amount of time) and the timeout (in case the firmware has a lot of offchannel activities). If the timeout elapses, the firmware will send partial results which are still valuable. In case of disassociation / channel switch and alike, the driver is in charge of stopping the measurements and the firmware will reply with partial results. The user space API for now is debugfs only and will be implmemented in an upcoming patch. Signed-off-by: Aviya Erenfeld <aviya.erenfeld@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/utils.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index 53cdc5760f68..2440248c8e69 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -1079,3 +1079,74 @@ void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1079out: 1079out:
1080 ieee80211_connection_loss(vif); 1080 ieee80211_connection_loss(vif);
1081} 1081}
1082
1083int iwl_mvm_send_lqm_cmd(struct ieee80211_vif *vif,
1084 enum iwl_lqm_cmd_operatrions operation,
1085 u32 duration, u32 timeout)
1086{
1087 struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif);
1088 struct iwl_link_qual_msrmnt_cmd cmd = {
1089 .cmd_operation = cpu_to_le32(operation),
1090 .mac_id = cpu_to_le32(mvm_vif->id),
1091 .measurement_time = cpu_to_le32(duration),
1092 .timeout = cpu_to_le32(timeout),
1093 };
1094 u32 cmdid =
1095 iwl_cmd_id(LINK_QUALITY_MEASUREMENT_CMD, MAC_CONF_GROUP, 0);
1096 int ret;
1097
1098 if (!fw_has_capa(&mvm_vif->mvm->fw->ucode_capa,
1099 IWL_UCODE_TLV_CAPA_LQM_SUPPORT))
1100 return -EOPNOTSUPP;
1101
1102 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
1103 return -EINVAL;
1104
1105 switch (operation) {
1106 case LQM_CMD_OPERATION_START_MEASUREMENT:
1107 if (iwl_mvm_lqm_active(mvm_vif->mvm))
1108 return -EBUSY;
1109 if (!vif->bss_conf.assoc)
1110 return -EINVAL;
1111 mvm_vif->lqm_active = true;
1112 break;
1113 case LQM_CMD_OPERATION_STOP_MEASUREMENT:
1114 if (!iwl_mvm_lqm_active(mvm_vif->mvm))
1115 return -EINVAL;
1116 break;
1117 default:
1118 return -EINVAL;
1119 }
1120
1121 ret = iwl_mvm_send_cmd_pdu(mvm_vif->mvm, cmdid, 0, sizeof(cmd),
1122 &cmd);
1123
1124 /* command failed - roll back lqm_active state */
1125 if (ret) {
1126 mvm_vif->lqm_active =
1127 operation == LQM_CMD_OPERATION_STOP_MEASUREMENT;
1128 }
1129
1130 return ret;
1131}
1132
1133static void iwl_mvm_lqm_active_iterator(void *_data, u8 *mac,
1134 struct ieee80211_vif *vif)
1135{
1136 struct iwl_mvm_vif *mvm_vif = iwl_mvm_vif_from_mac80211(vif);
1137 bool *lqm_active = _data;
1138
1139 *lqm_active = *lqm_active || mvm_vif->lqm_active;
1140}
1141
1142bool iwl_mvm_lqm_active(struct iwl_mvm *mvm)
1143{
1144 bool ret = false;
1145
1146 lockdep_assert_held(&mvm->mutex);
1147 ieee80211_iterate_active_interfaces_atomic(
1148 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
1149 iwl_mvm_lqm_active_iterator, &ret);
1150
1151 return ret;
1152}