aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
diff options
context:
space:
mode:
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}