File Index
Files and directories
Sign in
FILE

utils.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/intel/iwlwifi/mvm/utils.c C
   1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2/*
   3 * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
   4 * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
   5 * Copyright (C) 2015-2017 Intel Deutschland GmbH
   6 */
   7#include <net/mac80211.h>
   8
   9#include "iwl-debug.h"
  10#include "iwl-io.h"
  11#include "iwl-prph.h"
  12#include "iwl-csr.h"
  13#include "mvm.h"
  14#include "fw/api/rs.h"
  15#include "fw/img.h"
  16
  17/*
  18 * Will return 0 even if the cmd failed when RFKILL is asserted unless
  19 * CMD_WANT_SKB is set in cmd->flags.
  20 */
  21int iwl_mvm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd)
  22{
  23	int ret;
  24
  25	/*
  26	 * Synchronous commands from this op-mode must hold
  27	 * the mutex, this ensures we don't try to send two
  28	 * (or more) synchronous commands at a time.
  29	 */
  30	if (!(cmd->flags & CMD_ASYNC))
  31		lockdep_assert_held(&mvm->mutex);
  32
  33	ret = iwl_trans_send_cmd(mvm->trans, cmd);
  34
  35	/*
  36	 * If the caller wants the SKB, then don't hide any problems, the
  37	 * caller might access the response buffer which will be NULL if
  38	 * the command failed.
  39	 */
  40	if (cmd->flags & CMD_WANT_SKB)
  41		return ret;
  42
  43	/*
  44	 * Silently ignore failures if RFKILL is asserted or
  45	 * we are in suspend\resume process
  46	 */
  47	if (!ret || ret == -ERFKILL || ret == -EHOSTDOWN)
  48		return 0;
  49	return ret;
  50}
  51
  52int iwl_mvm_send_cmd_pdu(struct iwl_mvm *mvm, u32 id,
  53			 u32 flags, u16 len, const void *data)
  54{
  55	struct iwl_host_cmd cmd = {
  56		.id = id,
  57		.len = { len, },
  58		.data = { data, },
  59		.flags = flags,
  60	};
  61
  62	return iwl_mvm_send_cmd(mvm, &cmd);
  63}
  64
  65/*
  66 * We assume that the caller set the status to the success value
  67 */
  68int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd,
  69			    u32 *status)
  70{
  71	struct iwl_rx_packet *pkt;
  72	struct iwl_cmd_response *resp;
  73	int ret, resp_len;
  74
  75	lockdep_assert_held(&mvm->mutex);
  76
  77	/*
  78	 * Only synchronous commands can wait for status,
  79	 * we use WANT_SKB so the caller can't.
  80	 */
  81	if (WARN_ONCE(cmd->flags & (CMD_ASYNC | CMD_WANT_SKB),
  82		      "cmd flags %x", cmd->flags))
  83		return -EINVAL;
  84
  85	cmd->flags |= CMD_WANT_SKB;
  86
  87	ret = iwl_trans_send_cmd(mvm->trans, cmd);
  88	if (ret == -ERFKILL) {
  89		/*
  90		 * The command failed because of RFKILL, don't update
  91		 * the status, leave it as success and return 0.
  92		 */
  93		return 0;
  94	} else if (ret) {
  95		return ret;
  96	}
  97
  98	pkt = cmd->resp_pkt;
  99
 100	resp_len = iwl_rx_packet_payload_len(pkt);
 101	if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {
 102		ret = -EIO;
 103		goto out_free_resp;
 104	}
 105
 106	resp = (void *)pkt->data;
 107	*status = le32_to_cpu(resp->status);
 108 out_free_resp:
 109	iwl_free_resp(cmd);
 110	return ret;
 111}
 112
 113/*
 114 * We assume that the caller set the status to the sucess value
 115 */
 116int iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id, u16 len,
 117				const void *data, u32 *status)
 118{
 119	struct iwl_host_cmd cmd = {
 120		.id = id,
 121		.len = { len, },
 122		.data = { data, },
 123	};
 124
 125	return iwl_mvm_send_cmd_status(mvm, &cmd, status);
 126}
 127
 128int iwl_mvm_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags,
 129					  enum nl80211_band band)
 130{
 131	int format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
 132	int rate = rate_n_flags & RATE_LEGACY_RATE_MSK;
 133	bool is_LB = band == NL80211_BAND_2GHZ;
 134
 135	if (format == RATE_MCS_MOD_TYPE_LEGACY_OFDM)
 136		return is_LB ? rate + IWL_FIRST_OFDM_RATE :
 137			rate;
 138
 139	/* CCK is not allowed in HB */
 140	return is_LB ? rate : -1;
 141}
 142
 143int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
 144					enum nl80211_band band)
 145{
 146	int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1;
 147	int idx;
 148	int band_offset = 0;
 149
 150	/* Legacy rate format, search for match in table */
 151	if (band != NL80211_BAND_2GHZ)
 152		band_offset = IWL_FIRST_OFDM_RATE;
 153	for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)
 154		if (iwl_fw_rate_idx_to_plcp(idx) == rate)
 155			return idx - band_offset;
 156
 157	return -1;
 158}
 159
 160u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx)
 161{
 162	if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8)
 163		/* In the new rate legacy rates are indexed:
 164		 * 0 - 3 for CCK and 0 - 7 for OFDM.
 165		 */
 166		return (rate_idx >= IWL_FIRST_OFDM_RATE ?
 167			rate_idx - IWL_FIRST_OFDM_RATE :
 168			rate_idx);
 169
 170	return iwl_fw_rate_idx_to_plcp(rate_idx);
 171}
 172
 173u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac)
 174{
 175	static const u8 mac80211_ac_to_ucode_ac[] = {
 176		AC_VO,
 177		AC_VI,
 178		AC_BE,
 179		AC_BK
 180	};
 181
 182	return mac80211_ac_to_ucode_ac[ac];
 183}
 184
 185void iwl_mvm_rx_fw_error(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
 186{
 187	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 188	struct iwl_error_resp *err_resp = (void *)pkt->data;
 189
 190	IWL_ERR(mvm, "FW Error notification: type 0x%08X cmd_id 0x%02X\n",
 191		le32_to_cpu(err_resp->error_type), err_resp->cmd_id);
 192	IWL_ERR(mvm, "FW Error notification: seq 0x%04X service 0x%08X\n",
 193		le16_to_cpu(err_resp->bad_cmd_seq_num),
 194		le32_to_cpu(err_resp->error_service));
 195	IWL_ERR(mvm, "FW Error notification: timestamp 0x%016llX\n",
 196		le64_to_cpu(err_resp->timestamp));
 197}
 198
 199/*
 200 * Returns the first antenna as ANT_[ABC], as defined in iwl-config.h.
 201 * The parameter should also be a combination of ANT_[ABC].
 202 */
 203u8 first_antenna(u8 mask)
 204{
 205	BUILD_BUG_ON(ANT_A != BIT(0)); /* using ffs is wrong if not */
 206	if (WARN_ON_ONCE(!mask)) /* ffs will return 0 if mask is zeroed */
 207		return BIT(0);
 208	return BIT(ffs(mask) - 1);
 209}
 210
 211#define MAX_ANT_NUM 2
 212/*
 213 * Toggles between TX antennas to send the probe request on.
 214 * Receives the bitmask of valid TX antennas and the *index* used
 215 * for the last TX, and returns the next valid *index* to use.
 216 * In order to set it in the tx_cmd, must do BIT(idx).
 217 */
 218u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx)
 219{
 220	u8 ind = last_idx;
 221	int i;
 222
 223	for (i = 0; i < MAX_ANT_NUM; i++) {
 224		ind = (ind + 1) % MAX_ANT_NUM;
 225		if (valid & BIT(ind))
 226			return ind;
 227	}
 228
 229	WARN_ONCE(1, "Failed to toggle between antennas 0x%x", valid);
 230	return last_idx;
 231}
 232
 233/**
 234 * iwl_mvm_send_lq_cmd() - Send link quality command
 235 * @mvm: Driver data.
 236 * @lq: Link quality command to send.
 237 *
 238 * The link quality command is sent as the last step of station creation.
 239 * This is the special case in which init is set and we call a callback in
 240 * this case to clear the state indicating that station creation is in
 241 * progress.
 242 *
 243 * Returns: an error code indicating success or failure
 244 */
 245int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq)
 246{
 247	struct iwl_host_cmd cmd = {
 248		.id = LQ_CMD,
 249		.len = { sizeof(struct iwl_lq_cmd), },
 250		.flags = CMD_ASYNC,
 251		.data = { lq, },
 252	};
 253
 254	if (WARN_ON(lq->sta_id == IWL_INVALID_STA ||
 255		    iwl_mvm_has_tlc_offload(mvm)))
 256		return -EINVAL;
 257
 258	return iwl_mvm_send_cmd(mvm, &cmd);
 259}
 260
 261/**
 262 * iwl_mvm_update_smps - Get a request to change the SMPS mode
 263 * @mvm: Driver data.
 264 * @vif: Pointer to the ieee80211_vif structure
 265 * @req_type: The part of the driver who call for a change.
 266 * @smps_request: The request to change the SMPS mode.
 267 * @link_id: for MLO link_id, otherwise 0 (deflink)
 268 *
 269 * Get a requst to change the SMPS mode,
 270 * and change it according to all other requests in the driver.
 271 */
 272void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 273			 enum iwl_mvm_smps_type_request req_type,
 274			 enum ieee80211_smps_mode smps_request,
 275			 unsigned int link_id)
 276{
 277	struct iwl_mvm_vif *mvmvif;
 278	enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC;
 279	int i;
 280
 281	lockdep_assert_held(&mvm->mutex);
 282
 283	/* SMPS is irrelevant for NICs that don't have at least 2 RX antenna */
 284	if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1)
 285		return;
 286
 287	if (vif->type != NL80211_IFTYPE_STATION)
 288		return;
 289
 290	/* SMPS is handled by firmware */
 291	if (iwl_mvm_has_rlc_offload(mvm))
 292		return;
 293
 294	mvmvif = iwl_mvm_vif_from_mac80211(vif);
 295
 296	if (WARN_ON_ONCE(!mvmvif->link[link_id]))
 297		return;
 298
 299	mvmvif->link[link_id]->smps_requests[req_type] = smps_request;
 300	for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
 301		if (mvmvif->link[link_id]->smps_requests[i] ==
 302		    IEEE80211_SMPS_STATIC) {
 303			smps_mode = IEEE80211_SMPS_STATIC;
 304			break;
 305		}
 306		if (mvmvif->link[link_id]->smps_requests[i] ==
 307		    IEEE80211_SMPS_DYNAMIC)
 308			smps_mode = IEEE80211_SMPS_DYNAMIC;
 309	}
 310
 311	/* SMPS is disabled in eSR */
 312	if (mvmvif->esr_active)
 313		smps_mode = IEEE80211_SMPS_OFF;
 314
 315	ieee80211_request_smps(vif, link_id, smps_mode);
 316}
 317
 318void iwl_mvm_update_smps_on_active_links(struct iwl_mvm *mvm,
 319					 struct ieee80211_vif *vif,
 320					 enum iwl_mvm_smps_type_request req_type,
 321					 enum ieee80211_smps_mode smps_request)
 322{
 323	struct ieee80211_bss_conf *link_conf;
 324	unsigned int link_id;
 325
 326	rcu_read_lock();
 327	for_each_vif_active_link(vif, link_conf, link_id)
 328		iwl_mvm_update_smps(mvm, vif, req_type, smps_request,
 329				    link_id);
 330	rcu_read_unlock();
 331}
 332
 333static bool iwl_wait_stats_complete(struct iwl_notif_wait_data *notif_wait,
 334				    struct iwl_rx_packet *pkt, void *data)
 335{
 336	WARN_ON(pkt->hdr.cmd != STATISTICS_NOTIFICATION);
 337
 338	return true;
 339}
 340
 341#define PERIODIC_STAT_RATE 5
 342
 343int iwl_mvm_request_periodic_system_statistics(struct iwl_mvm *mvm, bool enable)
 344{
 345	u32 flags = enable ? 0 : IWL_STATS_CFG_FLG_DISABLE_NTFY_MSK;
 346	u32 type = enable ? (IWL_STATS_NTFY_TYPE_ID_OPER |
 347			     IWL_STATS_NTFY_TYPE_ID_OPER_PART1) : 0;
 348	struct iwl_system_statistics_cmd system_cmd = {
 349		.cfg_mask = cpu_to_le32(flags),
 350		.config_time_sec = cpu_to_le32(enable ?
 351					       PERIODIC_STAT_RATE : 0),
 352		.type_id_mask = cpu_to_le32(type),
 353	};
 354
 355	return iwl_mvm_send_cmd_pdu(mvm,
 356				    WIDE_ID(SYSTEM_GROUP,
 357					    SYSTEM_STATISTICS_CMD),
 358				    0, sizeof(system_cmd), &system_cmd);
 359}
 360
 361static int iwl_mvm_request_system_statistics(struct iwl_mvm *mvm, bool clear,
 362					     u8 cmd_ver)
 363{
 364	struct iwl_system_statistics_cmd system_cmd = {
 365		.cfg_mask = clear ?
 366			    cpu_to_le32(IWL_STATS_CFG_FLG_ON_DEMAND_NTFY_MSK) :
 367			    cpu_to_le32(IWL_STATS_CFG_FLG_RESET_MSK |
 368					IWL_STATS_CFG_FLG_ON_DEMAND_NTFY_MSK),
 369		.type_id_mask = cpu_to_le32(IWL_STATS_NTFY_TYPE_ID_OPER |
 370					    IWL_STATS_NTFY_TYPE_ID_OPER_PART1),
 371	};
 372	struct iwl_host_cmd cmd = {
 373		.id = WIDE_ID(SYSTEM_GROUP, SYSTEM_STATISTICS_CMD),
 374		.len[0] = sizeof(system_cmd),
 375		.data[0] = &system_cmd,
 376	};
 377	struct iwl_notification_wait stats_wait;
 378	static const u16 stats_complete[] = {
 379		WIDE_ID(SYSTEM_GROUP, SYSTEM_STATISTICS_END_NOTIF),
 380	};
 381	int ret;
 382
 383	if (cmd_ver != 1) {
 384		IWL_FW_CHECK_FAILED(mvm,
 385				    "Invalid system statistics command version:%d\n",
 386				    cmd_ver);
 387		return -EOPNOTSUPP;
 388	}
 389
 390	iwl_init_notification_wait(&mvm->notif_wait, &stats_wait,
 391				   stats_complete, ARRAY_SIZE(stats_complete),
 392				   NULL, NULL);
 393
 394	mvm->statistics_clear = clear;
 395	ret = iwl_mvm_send_cmd(mvm, &cmd);
 396	if (ret) {
 397		iwl_remove_notification(&mvm->notif_wait, &stats_wait);
 398		return ret;
 399	}
 400
 401	/* 500ms for OPERATIONAL, PART1 and END notification should be enough
 402	 * for FW to collect data from all LMACs and send
 403	 * STATISTICS_NOTIFICATION to host
 404	 */
 405	ret = iwl_wait_notification(&mvm->notif_wait, &stats_wait, HZ / 2);
 406	if (ret)
 407		return ret;
 408
 409	if (clear)
 410		iwl_mvm_accu_radio_stats(mvm);
 411
 412	return ret;
 413}
 414
 415int iwl_mvm_request_statistics(struct iwl_mvm *mvm, bool clear)
 416{
 417	struct iwl_statistics_cmd scmd = {
 418		.flags = clear ? cpu_to_le32(IWL_STATISTICS_FLG_CLEAR) : 0,
 419	};
 420
 421	struct iwl_host_cmd cmd = {
 422		.id = STATISTICS_CMD,
 423		.len[0] = sizeof(scmd),
 424		.data[0] = &scmd,
 425	};
 426	u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
 427					   WIDE_ID(SYSTEM_GROUP,
 428						   SYSTEM_STATISTICS_CMD),
 429					   IWL_FW_CMD_VER_UNKNOWN);
 430	int ret;
 431
 432	/*
 433	 * Don't request statistics during restart, they'll not have any useful
 434	 * information right after restart, nor is clearing needed
 435	 */
 436	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
 437		return 0;
 438
 439	if (cmd_ver != IWL_FW_CMD_VER_UNKNOWN)
 440		return iwl_mvm_request_system_statistics(mvm, clear, cmd_ver);
 441
 442	/* From version 15 - STATISTICS_NOTIFICATION, the reply for
 443	 * STATISTICS_CMD is empty, and the response is with
 444	 * STATISTICS_NOTIFICATION notification
 445	 */
 446	if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
 447				    STATISTICS_NOTIFICATION, 0) < 15) {
 448		cmd.flags = CMD_WANT_SKB;
 449
 450		ret = iwl_mvm_send_cmd(mvm, &cmd);
 451		if (ret)
 452			return ret;
 453
 454		iwl_mvm_handle_rx_statistics(mvm, cmd.resp_pkt);
 455		iwl_free_resp(&cmd);
 456	} else {
 457		struct iwl_notification_wait stats_wait;
 458		static const u16 stats_complete[] = {
 459			STATISTICS_NOTIFICATION,
 460		};
 461
 462		iwl_init_notification_wait(&mvm->notif_wait, &stats_wait,
 463					   stats_complete, ARRAY_SIZE(stats_complete),
 464					   iwl_wait_stats_complete, NULL);
 465
 466		ret = iwl_mvm_send_cmd(mvm, &cmd);
 467		if (ret) {
 468			iwl_remove_notification(&mvm->notif_wait, &stats_wait);
 469			return ret;
 470		}
 471
 472		/* 200ms should be enough for FW to collect data from all
 473		 * LMACs and send STATISTICS_NOTIFICATION to host
 474		 */
 475		ret = iwl_wait_notification(&mvm->notif_wait, &stats_wait, HZ / 5);
 476		if (ret)
 477			return ret;
 478	}
 479
 480	if (clear)
 481		iwl_mvm_accu_radio_stats(mvm);
 482
 483	return 0;
 484}
 485
 486void iwl_mvm_accu_radio_stats(struct iwl_mvm *mvm)
 487{
 488	mvm->accu_radio_stats.rx_time += mvm->radio_stats.rx_time;
 489	mvm->accu_radio_stats.tx_time += mvm->radio_stats.tx_time;
 490	mvm->accu_radio_stats.on_time_rf += mvm->radio_stats.on_time_rf;
 491	mvm->accu_radio_stats.on_time_scan += mvm->radio_stats.on_time_scan;
 492}
 493
 494struct iwl_mvm_diversity_iter_data {
 495	struct iwl_mvm_phy_ctxt *ctxt;
 496	bool result;
 497};
 498
 499static void iwl_mvm_diversity_iter(void *_data, u8 *mac,
 500				   struct ieee80211_vif *vif)
 501{
 502	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 503	struct iwl_mvm_diversity_iter_data *data = _data;
 504	int i, link_id;
 505
 506	for_each_mvm_vif_valid_link(mvmvif, link_id) {
 507		struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
 508
 509		if (link_info->phy_ctxt != data->ctxt)
 510			continue;
 511
 512		for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
 513			if (link_info->smps_requests[i] == IEEE80211_SMPS_STATIC ||
 514			    link_info->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) {
 515				data->result = false;
 516				break;
 517			}
 518		}
 519	}
 520}
 521
 522bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm,
 523				  struct iwl_mvm_phy_ctxt *ctxt)
 524{
 525	struct iwl_mvm_diversity_iter_data data = {
 526		.ctxt = ctxt,
 527		.result = true,
 528	};
 529
 530	lockdep_assert_held(&mvm->mutex);
 531
 532	if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
 533		return false;
 534
 535	if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1)
 536		return false;
 537
 538	if (mvm->cfg->rx_with_siso_diversity)
 539		return false;
 540
 541	ieee80211_iterate_active_interfaces_atomic(
 542			mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
 543			iwl_mvm_diversity_iter, &data);
 544
 545	return data.result;
 546}
 547
 548void iwl_mvm_send_low_latency_cmd(struct iwl_mvm *mvm,
 549				  bool low_latency, u16 mac_id)
 550{
 551	struct iwl_mac_low_latency_cmd cmd = {
 552		.mac_id = cpu_to_le32(mac_id)
 553	};
 554
 555	if (!fw_has_capa(&mvm->fw->ucode_capa,
 556			 IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA))
 557		return;
 558
 559	if (low_latency) {
 560		/* currently we don't care about the direction */
 561		cmd.low_latency_rx = 1;
 562		cmd.low_latency_tx = 1;
 563	}
 564
 565	if (iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(MAC_CONF_GROUP, LOW_LATENCY_CMD),
 566				 0, sizeof(cmd), &cmd))
 567		IWL_ERR(mvm, "Failed to send low latency command\n");
 568}
 569
 570int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 571			       bool low_latency,
 572			       enum iwl_mvm_low_latency_cause cause)
 573{
 574	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 575	int res;
 576	bool prev;
 577
 578	lockdep_assert_held(&mvm->mutex);
 579
 580	prev = iwl_mvm_vif_low_latency(mvmvif);
 581	iwl_mvm_vif_set_low_latency(mvmvif, low_latency, cause);
 582
 583	low_latency = iwl_mvm_vif_low_latency(mvmvif);
 584
 585	if (low_latency == prev)
 586		return 0;
 587
 588	iwl_mvm_send_low_latency_cmd(mvm, low_latency, mvmvif->id);
 589
 590	res = iwl_mvm_update_quotas(mvm, false, NULL);
 591	if (res)
 592		return res;
 593
 594	iwl_mvm_bt_coex_vif_change(mvm);
 595
 596	return iwl_mvm_power_update_mac(mvm);
 597}
 598
 599struct iwl_mvm_low_latency_iter {
 600	bool result;
 601	bool result_per_band[NUM_NL80211_BANDS];
 602};
 603
 604static void iwl_mvm_ll_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
 605{
 606	struct iwl_mvm_low_latency_iter *result = _data;
 607	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 608	enum nl80211_band band;
 609
 610	if (iwl_mvm_vif_low_latency(mvmvif)) {
 611		result->result = true;
 612
 613		if (!mvmvif->deflink.phy_ctxt)
 614			return;
 615
 616		band = mvmvif->deflink.phy_ctxt->channel->band;
 617		result->result_per_band[band] = true;
 618	}
 619}
 620
 621bool iwl_mvm_low_latency(struct iwl_mvm *mvm)
 622{
 623	struct iwl_mvm_low_latency_iter data = {};
 624
 625	ieee80211_iterate_active_interfaces_atomic(
 626			mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
 627			iwl_mvm_ll_iter, &data);
 628
 629	return data.result;
 630}
 631
 632bool iwl_mvm_low_latency_band(struct iwl_mvm *mvm, enum nl80211_band band)
 633{
 634	struct iwl_mvm_low_latency_iter data = {};
 635
 636	ieee80211_iterate_active_interfaces_atomic(
 637			mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
 638			iwl_mvm_ll_iter, &data);
 639
 640	return data.result_per_band[band];
 641}
 642
 643struct iwl_bss_iter_data {
 644	struct ieee80211_vif *vif;
 645	bool error;
 646};
 647
 648static void iwl_mvm_bss_iface_iterator(void *_data, u8 *mac,
 649				       struct ieee80211_vif *vif)
 650{
 651	struct iwl_bss_iter_data *data = _data;
 652
 653	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
 654		return;
 655
 656	if (data->vif) {
 657		data->error = true;
 658		return;
 659	}
 660
 661	data->vif = vif;
 662}
 663
 664struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm)
 665{
 666	struct iwl_bss_iter_data bss_iter_data = {};
 667
 668	ieee80211_iterate_active_interfaces_atomic(
 669		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
 670		iwl_mvm_bss_iface_iterator, &bss_iter_data);
 671
 672	if (bss_iter_data.error)
 673		return ERR_PTR(-EINVAL);
 674
 675	return bss_iter_data.vif;
 676}
 677
 678struct iwl_bss_find_iter_data {
 679	struct ieee80211_vif *vif;
 680	u32 macid;
 681};
 682
 683static void iwl_mvm_bss_find_iface_iterator(void *_data, u8 *mac,
 684					    struct ieee80211_vif *vif)
 685{
 686	struct iwl_bss_find_iter_data *data = _data;
 687	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 688
 689	if (mvmvif->id == data->macid)
 690		data->vif = vif;
 691}
 692
 693struct ieee80211_vif *iwl_mvm_get_vif_by_macid(struct iwl_mvm *mvm, u32 macid)
 694{
 695	struct iwl_bss_find_iter_data data = {
 696		.macid = macid,
 697	};
 698
 699	lockdep_assert_held(&mvm->mutex);
 700
 701	ieee80211_iterate_active_interfaces_atomic(
 702		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
 703		iwl_mvm_bss_find_iface_iterator, &data);
 704
 705	return data.vif;
 706}
 707
 708struct iwl_sta_iter_data {
 709	bool assoc;
 710};
 711
 712static void iwl_mvm_sta_iface_iterator(void *_data, u8 *mac,
 713				       struct ieee80211_vif *vif)
 714{
 715	struct iwl_sta_iter_data *data = _data;
 716
 717	if (vif->type != NL80211_IFTYPE_STATION)
 718		return;
 719
 720	if (vif->cfg.assoc)
 721		data->assoc = true;
 722}
 723
 724bool iwl_mvm_is_vif_assoc(struct iwl_mvm *mvm)
 725{
 726	struct iwl_sta_iter_data data = {
 727		.assoc = false,
 728	};
 729
 730	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
 731						   IEEE80211_IFACE_ITER_NORMAL,
 732						   iwl_mvm_sta_iface_iterator,
 733						   &data);
 734	return data.assoc;
 735}
 736
 737unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
 738				    struct ieee80211_vif *vif)
 739{
 740	unsigned int default_timeout =
 741		mvm->trans->mac_cfg->base->wd_timeout;
 742
 743	/*
 744	 * We can't know when the station is asleep or awake, so we
 745	 * must disable the queue hang detection.
 746	 */
 747	if (fw_has_capa(&mvm->fw->ucode_capa,
 748			IWL_UCODE_TLV_CAPA_STA_PM_NOTIF) &&
 749	    vif->type == NL80211_IFTYPE_AP)
 750		return IWL_WATCHDOG_DISABLED;
 751	return default_timeout;
 752}
 753
 754void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 755			     const char *errmsg)
 756{
 757	struct iwl_fw_dbg_trigger_tlv *trig;
 758	struct iwl_fw_dbg_trigger_mlme *trig_mlme;
 759
 760	trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
 761				     FW_DBG_TRIGGER_MLME);
 762	if (!trig)
 763		goto out;
 764
 765	trig_mlme = (void *)trig->data;
 766
 767	if (trig_mlme->stop_connection_loss &&
 768	    --trig_mlme->stop_connection_loss)
 769		goto out;
 770
 771	iwl_fw_dbg_collect_trig(&mvm->fwrt, trig, "%s", errmsg);
 772
 773out:
 774	ieee80211_connection_loss(vif);
 775}
 776
 777void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,
 778					  struct ieee80211_vif *vif,
 779					  const struct ieee80211_sta *sta,
 780					  u16 tid)
 781{
 782	struct iwl_fw_dbg_trigger_tlv *trig;
 783	struct iwl_fw_dbg_trigger_ba *ba_trig;
 784
 785	trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
 786				     FW_DBG_TRIGGER_BA);
 787	if (!trig)
 788		return;
 789
 790	ba_trig = (void *)trig->data;
 791
 792	if (!(le16_to_cpu(ba_trig->frame_timeout) & BIT(tid)))
 793		return;
 794
 795	iwl_fw_dbg_collect_trig(&mvm->fwrt, trig,
 796				"Frame from %pM timed out, tid %d",
 797				sta->addr, tid);
 798}
 799
 800u8 iwl_mvm_tcm_load_percentage(u32 airtime, u32 elapsed)
 801{
 802	if (!elapsed)
 803		return 0;
 804
 805	return (100 * airtime / elapsed) / USEC_PER_MSEC;
 806}
 807
 808static enum iwl_mvm_traffic_load
 809iwl_mvm_tcm_load(struct iwl_mvm *mvm, u32 airtime, unsigned long elapsed)
 810{
 811	u8 load = iwl_mvm_tcm_load_percentage(airtime, elapsed);
 812
 813	if (load > IWL_MVM_TCM_LOAD_HIGH_THRESH)
 814		return IWL_MVM_TRAFFIC_HIGH;
 815	if (load > IWL_MVM_TCM_LOAD_MEDIUM_THRESH)
 816		return IWL_MVM_TRAFFIC_MEDIUM;
 817
 818	return IWL_MVM_TRAFFIC_LOW;
 819}
 820
 821static void iwl_mvm_tcm_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
 822{
 823	struct iwl_mvm *mvm = _data;
 824	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 825	bool low_latency, prev = mvmvif->low_latency & LOW_LATENCY_TRAFFIC;
 826
 827	if (mvmvif->id >= NUM_MAC_INDEX_DRIVER)
 828		return;
 829
 830	low_latency = mvm->tcm.result.low_latency[mvmvif->id];
 831
 832	if (!mvm->tcm.result.change[mvmvif->id] &&
 833	    prev == low_latency) {
 834		iwl_mvm_update_quotas(mvm, false, NULL);
 835		return;
 836	}
 837
 838	if (prev != low_latency) {
 839		/* this sends traffic load and updates quota as well */
 840		iwl_mvm_update_low_latency(mvm, vif, low_latency,
 841					   LOW_LATENCY_TRAFFIC);
 842	} else {
 843		iwl_mvm_update_quotas(mvm, false, NULL);
 844	}
 845}
 846
 847static void iwl_mvm_tcm_results(struct iwl_mvm *mvm)
 848{
 849	guard(mvm)(mvm);
 850
 851	ieee80211_iterate_active_interfaces(
 852		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
 853		iwl_mvm_tcm_iter, mvm);
 854
 855	if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN))
 856		iwl_mvm_config_scan(mvm);
 857}
 858
 859static void iwl_mvm_tcm_uapsd_nonagg_detected_wk(struct work_struct *wk)
 860{
 861	struct iwl_mvm *mvm;
 862	struct iwl_mvm_vif *mvmvif;
 863	struct ieee80211_vif *vif;
 864
 865	mvmvif = container_of(wk, struct iwl_mvm_vif,
 866			      uapsd_nonagg_detected_wk.work);
 867	vif = container_of((void *)mvmvif, struct ieee80211_vif, drv_priv);
 868	mvm = mvmvif->mvm;
 869
 870	if (mvm->tcm.data[mvmvif->id].opened_rx_ba_sessions)
 871		return;
 872
 873	/* remember that this AP is broken */
 874	memcpy(mvm->uapsd_noagg_bssids[mvm->uapsd_noagg_bssid_write_idx].addr,
 875	       vif->bss_conf.bssid, ETH_ALEN);
 876	mvm->uapsd_noagg_bssid_write_idx++;
 877	if (mvm->uapsd_noagg_bssid_write_idx >= IWL_MVM_UAPSD_NOAGG_LIST_LEN)
 878		mvm->uapsd_noagg_bssid_write_idx = 0;
 879
 880	iwl_mvm_connection_loss(mvm, vif,
 881				"AP isn't using AMPDU with uAPSD enabled");
 882}
 883
 884static void iwl_mvm_uapsd_agg_disconnect(struct iwl_mvm *mvm,
 885					 struct ieee80211_vif *vif)
 886{
 887	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 888
 889	if (vif->type != NL80211_IFTYPE_STATION)
 890		return;
 891
 892	if (!vif->cfg.assoc)
 893		return;
 894
 895	if (!mvmvif->deflink.queue_params[IEEE80211_AC_VO].uapsd &&
 896	    !mvmvif->deflink.queue_params[IEEE80211_AC_VI].uapsd &&
 897	    !mvmvif->deflink.queue_params[IEEE80211_AC_BE].uapsd &&
 898	    !mvmvif->deflink.queue_params[IEEE80211_AC_BK].uapsd)
 899		return;
 900
 901	if (mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected)
 902		return;
 903
 904	mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected = true;
 905	IWL_INFO(mvm,
 906		 "detected AP should do aggregation but isn't, likely due to U-APSD\n");
 907	schedule_delayed_work(&mvmvif->uapsd_nonagg_detected_wk,
 908			      15 * HZ);
 909}
 910
 911static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm,
 912						 unsigned int elapsed,
 913						 int mac)
 914{
 915	u64 bytes = mvm->tcm.data[mac].uapsd_nonagg_detect.rx_bytes;
 916	u64 tpt;
 917	unsigned long rate;
 918	struct ieee80211_vif *vif;
 919
 920	rate = ewma_rate_read(&mvm->tcm.data[mac].uapsd_nonagg_detect.rate);
 921
 922	if (!rate || mvm->tcm.data[mac].opened_rx_ba_sessions ||
 923	    mvm->tcm.data[mac].uapsd_nonagg_detect.detected)
 924		return;
 925
 926	if (iwl_mvm_has_new_rx_api(mvm)) {
 927		tpt = 8 * bytes; /* kbps */
 928		do_div(tpt, elapsed);
 929		rate *= 1000; /* kbps */
 930		if (tpt < 22 * rate / 100)
 931			return;
 932	} else {
 933		/*
 934		 * the rate here is actually the threshold, in 100Kbps units,
 935		 * so do the needed conversion from bytes to 100Kbps:
 936		 * 100kb = bits / (100 * 1000),
 937		 * 100kbps = 100kb / (msecs / 1000) ==
 938		 *           (bits / (100 * 1000)) / (msecs / 1000) ==
 939		 *           bits / (100 * msecs)
 940		 */
 941		tpt = (8 * bytes);
 942		do_div(tpt, elapsed * 100);
 943		if (tpt < rate)
 944			return;
 945	}
 946
 947	rcu_read_lock();
 948	vif = rcu_dereference(mvm->vif_id_to_mac[mac]);
 949	if (vif)
 950		iwl_mvm_uapsd_agg_disconnect(mvm, vif);
 951	rcu_read_unlock();
 952}
 953
 954static void iwl_mvm_tcm_iterator(void *_data, u8 *mac,
 955				 struct ieee80211_vif *vif)
 956{
 957	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 958	u32 *band = _data;
 959
 960	if (!mvmvif->deflink.phy_ctxt)
 961		return;
 962
 963	band[mvmvif->id] = mvmvif->deflink.phy_ctxt->channel->band;
 964}
 965
 966static unsigned long iwl_mvm_calc_tcm_stats(struct iwl_mvm *mvm,
 967					    unsigned long ts,
 968					    bool handle_uapsd)
 969{
 970	unsigned int elapsed = jiffies_to_msecs(ts - mvm->tcm.ts);
 971	unsigned int uapsd_elapsed =
 972		jiffies_to_msecs(ts - mvm->tcm.uapsd_nonagg_ts);
 973	u32 total_airtime = 0;
 974	u32 band_airtime[NUM_NL80211_BANDS] = {0};
 975	u32 band[NUM_MAC_INDEX_DRIVER] = {0};
 976	int ac, mac, i;
 977	bool low_latency = false;
 978	enum iwl_mvm_traffic_load load, band_load;
 979	bool handle_ll = time_after(ts, mvm->tcm.ll_ts + MVM_LL_PERIOD);
 980
 981	if (handle_ll)
 982		mvm->tcm.ll_ts = ts;
 983	if (handle_uapsd)
 984		mvm->tcm.uapsd_nonagg_ts = ts;
 985
 986	mvm->tcm.result.elapsed = elapsed;
 987
 988	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
 989						   IEEE80211_IFACE_ITER_NORMAL,
 990						   iwl_mvm_tcm_iterator,
 991						   &band);
 992
 993	for (mac = 0; mac < NUM_MAC_INDEX_DRIVER; mac++) {
 994		struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[mac];
 995		u32 vo_vi_pkts = 0;
 996		u32 airtime = mdata->rx.airtime + mdata->tx.airtime;
 997
 998		total_airtime += airtime;
 999		band_airtime[band[mac]] += airtime;
1000
1001		load = iwl_mvm_tcm_load(mvm, airtime, elapsed);
1002		mvm->tcm.result.change[mac] = load != mvm->tcm.result.load[mac];
1003		mvm->tcm.result.load[mac] = load;
1004		mvm->tcm.result.airtime[mac] = airtime;
1005
1006		for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_VI; ac++)
1007			vo_vi_pkts += mdata->rx.pkts[ac] +
1008				      mdata->tx.pkts[ac];
1009
1010		/* enable immediately with enough packets but defer disabling */
1011		if (vo_vi_pkts > IWL_MVM_TCM_LOWLAT_ENABLE_THRESH)
1012			mvm->tcm.result.low_latency[mac] = true;
1013		else if (handle_ll)
1014			mvm->tcm.result.low_latency[mac] = false;
1015
1016		if (handle_ll) {
1017			/* clear old data */
1018			memset(&mdata->rx.pkts, 0, sizeof(mdata->rx.pkts));
1019			memset(&mdata->tx.pkts, 0, sizeof(mdata->tx.pkts));
1020		}
1021		low_latency |= mvm->tcm.result.low_latency[mac];
1022
1023		if (!mvm->tcm.result.low_latency[mac] && handle_uapsd)
1024			iwl_mvm_check_uapsd_agg_expected_tpt(mvm, uapsd_elapsed,
1025							     mac);
1026		/* clear old data */
1027		if (handle_uapsd)
1028			mdata->uapsd_nonagg_detect.rx_bytes = 0;
1029		memset(&mdata->rx.airtime, 0, sizeof(mdata->rx.airtime));
1030		memset(&mdata->tx.airtime, 0, sizeof(mdata->tx.airtime));
1031	}
1032
1033	load = iwl_mvm_tcm_load(mvm, total_airtime, elapsed);
1034	mvm->tcm.result.global_load = load;
1035
1036	for (i = 0; i < NUM_NL80211_BANDS; i++) {
1037		band_load = iwl_mvm_tcm_load(mvm, band_airtime[i], elapsed);
1038		mvm->tcm.result.band_load[i] = band_load;
1039	}
1040
1041	/*
1042	 * If the current load isn't low we need to force re-evaluation
1043	 * in the TCM period, so that we can return to low load if there
1044	 * was no traffic at all (and thus iwl_mvm_recalc_tcm didn't get
1045	 * triggered by traffic).
1046	 */
1047	if (load != IWL_MVM_TRAFFIC_LOW)
1048		return MVM_TCM_PERIOD;
1049	/*
1050	 * If low-latency is active we need to force re-evaluation after
1051	 * (the longer) MVM_LL_PERIOD, so that we can disable low-latency
1052	 * when there's no traffic at all.
1053	 */
1054	if (low_latency)
1055		return MVM_LL_PERIOD;
1056	/*
1057	 * Otherwise, we don't need to run the work struct because we're
1058	 * in the default "idle" state - traffic indication is low (which
1059	 * also covers the "no traffic" case) and low-latency is disabled
1060	 * so there's no state that may need to be disabled when there's
1061	 * no traffic at all.
1062	 *
1063	 * Note that this has no impact on the regular scheduling of the
1064	 * updates triggered by traffic - those happen whenever one of the
1065	 * two timeouts expire (if there's traffic at all.)
1066	 */
1067	return 0;
1068}
1069
1070void iwl_mvm_recalc_tcm(struct iwl_mvm *mvm)
1071{
1072	unsigned long ts = jiffies;
1073	bool handle_uapsd =
1074		time_after(ts, mvm->tcm.uapsd_nonagg_ts +
1075			       msecs_to_jiffies(IWL_MVM_UAPSD_NONAGG_PERIOD));
1076
1077	spin_lock(&mvm->tcm.lock);
1078	if (mvm->tcm.paused || !time_after(ts, mvm->tcm.ts + MVM_TCM_PERIOD)) {
1079		spin_unlock(&mvm->tcm.lock);
1080		return;
1081	}
1082	spin_unlock(&mvm->tcm.lock);
1083
1084	if (handle_uapsd && iwl_mvm_has_new_rx_api(mvm)) {
1085		guard(mvm)(mvm);
1086		if (iwl_mvm_request_statistics(mvm, true))
1087			handle_uapsd = false;
1088	}
1089
1090	spin_lock(&mvm->tcm.lock);
1091	/* re-check if somebody else won the recheck race */
1092	if (!mvm->tcm.paused && time_after(ts, mvm->tcm.ts + MVM_TCM_PERIOD)) {
1093		/* calculate statistics */
1094		unsigned long work_delay = iwl_mvm_calc_tcm_stats(mvm, ts,
1095								  handle_uapsd);
1096
1097		/* the memset needs to be visible before the timestamp */
1098		smp_mb();
1099		mvm->tcm.ts = ts;
1100		if (work_delay)
1101			schedule_delayed_work(&mvm->tcm.work, work_delay);
1102	}
1103	spin_unlock(&mvm->tcm.lock);
1104
1105	iwl_mvm_tcm_results(mvm);
1106}
1107
1108void iwl_mvm_tcm_work(struct work_struct *work)
1109{
1110	struct delayed_work *delayed_work = to_delayed_work(work);
1111	struct iwl_mvm *mvm = container_of(delayed_work, struct iwl_mvm,
1112					   tcm.work);
1113
1114	iwl_mvm_recalc_tcm(mvm);
1115}
1116
1117void iwl_mvm_pause_tcm(struct iwl_mvm *mvm, bool with_cancel)
1118{
1119	spin_lock_bh(&mvm->tcm.lock);
1120	mvm->tcm.paused = true;
1121	spin_unlock_bh(&mvm->tcm.lock);
1122	if (with_cancel)
1123		cancel_delayed_work_sync(&mvm->tcm.work);
1124}
1125
1126void iwl_mvm_resume_tcm(struct iwl_mvm *mvm)
1127{
1128	int mac;
1129	bool low_latency = false;
1130
1131	spin_lock_bh(&mvm->tcm.lock);
1132	mvm->tcm.ts = jiffies;
1133	mvm->tcm.ll_ts = jiffies;
1134	for (mac = 0; mac < NUM_MAC_INDEX_DRIVER; mac++) {
1135		struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[mac];
1136
1137		memset(&mdata->rx.pkts, 0, sizeof(mdata->rx.pkts));
1138		memset(&mdata->tx.pkts, 0, sizeof(mdata->tx.pkts));
1139		memset(&mdata->rx.airtime, 0, sizeof(mdata->rx.airtime));
1140		memset(&mdata->tx.airtime, 0, sizeof(mdata->tx.airtime));
1141
1142		if (mvm->tcm.result.low_latency[mac])
1143			low_latency = true;
1144	}
1145	/* The TCM data needs to be reset before "paused" flag changes */
1146	smp_mb();
1147	mvm->tcm.paused = false;
1148
1149	/*
1150	 * if the current load is not low or low latency is active, force
1151	 * re-evaluation to cover the case of no traffic.
1152	 */
1153	if (mvm->tcm.result.global_load > IWL_MVM_TRAFFIC_LOW)
1154		schedule_delayed_work(&mvm->tcm.work, MVM_TCM_PERIOD);
1155	else if (low_latency)
1156		schedule_delayed_work(&mvm->tcm.work, MVM_LL_PERIOD);
1157
1158	spin_unlock_bh(&mvm->tcm.lock);
1159}
1160
1161void iwl_mvm_tcm_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1162{
1163	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1164
1165	INIT_DELAYED_WORK(&mvmvif->uapsd_nonagg_detected_wk,
1166			  iwl_mvm_tcm_uapsd_nonagg_detected_wk);
1167}
1168
1169void iwl_mvm_tcm_rm_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1170{
1171	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1172
1173	cancel_delayed_work_sync(&mvmvif->uapsd_nonagg_detected_wk);
1174}
1175
1176u32 iwl_mvm_get_systime(struct iwl_mvm *mvm)
1177{
1178	u32 reg_addr = DEVICE_SYSTEM_TIME_REG;
1179
1180	if (mvm->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000 &&
1181	    mvm->trans->mac_cfg->base->gp2_reg_addr)
1182		reg_addr = mvm->trans->mac_cfg->base->gp2_reg_addr;
1183
1184	return iwl_read_prph(mvm->trans, reg_addr);
1185}
1186
1187void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, int clock_type,
1188			   u32 *gp2, u64 *boottime, ktime_t *realtime)
1189{
1190	bool ps_disabled;
1191
1192	lockdep_assert_held(&mvm->mutex);
1193
1194	/* Disable power save when reading GP2 */
1195	ps_disabled = mvm->ps_disabled;
1196	if (!ps_disabled) {
1197		mvm->ps_disabled = true;
1198		iwl_mvm_power_update_device(mvm);
1199	}
1200
1201	*gp2 = iwl_mvm_get_systime(mvm);
1202
1203	if (clock_type == CLOCK_BOOTTIME && boottime)
1204		*boottime = ktime_get_boottime_ns();
1205	else if (clock_type == CLOCK_REALTIME && realtime)
1206		*realtime = ktime_get_real();
1207
1208	if (!ps_disabled) {
1209		mvm->ps_disabled = ps_disabled;
1210		iwl_mvm_power_update_device(mvm);
1211	}
1212}
1213
1214/* Find if at least two links from different vifs use same channel
1215 * FIXME: consider having a refcount array in struct iwl_mvm_vif for
1216 * used phy_ctxt ids.
1217 */
1218bool iwl_mvm_have_links_same_channel(struct iwl_mvm_vif *vif1,
1219				     struct iwl_mvm_vif *vif2)
1220{
1221	unsigned int i, j;
1222
1223	for_each_mvm_vif_valid_link(vif1, i) {
1224		for_each_mvm_vif_valid_link(vif2, j) {
1225			if (vif1->link[i]->phy_ctxt == vif2->link[j]->phy_ctxt)
1226				return true;
1227		}
1228	}
1229
1230	return false;
1231}
1232
1233bool iwl_mvm_vif_is_active(struct iwl_mvm_vif *mvmvif)
1234{
1235	unsigned int i;
1236
1237	/* FIXME: can it fail when phy_ctxt is assigned? */
1238	for_each_mvm_vif_valid_link(mvmvif, i) {
1239		if (mvmvif->link[i]->phy_ctxt &&
1240		    mvmvif->link[i]->phy_ctxt->id < NUM_PHY_CTX)
1241			return true;
1242	}
1243
1244	return false;
1245}
1246
1247static u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags)
1248{
1249	int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1;
1250	int idx;
1251	bool ofdm = !(rate_n_flags & RATE_MCS_CCK_MSK_V1);
1252	int offset = ofdm ? IWL_FIRST_OFDM_RATE : 0;
1253	int last = ofdm ? IWL_RATE_COUNT_LEGACY : IWL_FIRST_OFDM_RATE;
1254
1255	for (idx = offset; idx < last; idx++)
1256		if (iwl_fw_rate_idx_to_plcp(idx) == rate)
1257			return idx - offset;
1258	return IWL_RATE_INVALID;
1259}
1260
1261u32 iwl_mvm_v3_rate_from_fw(__le32 rate, u8 rate_ver)
1262{
1263	u32 rate_v3 = 0, rate_v1;
1264	u32 dup = 0;
1265
1266	if (rate_ver > 1)
1267		return iwl_v3_rate_from_v2_v3(rate, rate_ver >= 3);
1268
1269	rate_v1 = le32_to_cpu(rate);
1270	if (rate_v1 == 0)
1271		return rate_v1;
1272	/* convert rate */
1273	if (rate_v1 & RATE_MCS_HT_MSK_V1) {
1274		u32 nss;
1275
1276		rate_v3 |= RATE_MCS_MOD_TYPE_HT;
1277		rate_v3 |=
1278			rate_v1 & RATE_HT_MCS_RATE_CODE_MSK_V1;
1279		nss = u32_get_bits(rate_v1, RATE_HT_MCS_MIMO2_MSK);
1280		rate_v3 |= u32_encode_bits(nss, RATE_MCS_NSS_MSK);
1281	} else if (rate_v1 & RATE_MCS_VHT_MSK_V1 ||
1282		   rate_v1 & RATE_MCS_HE_MSK_V1) {
1283		u32 nss = u32_get_bits(rate_v1, RATE_VHT_MCS_NSS_MSK);
1284
1285		rate_v3 |= rate_v1 & RATE_VHT_MCS_RATE_CODE_MSK;
1286
1287		rate_v3 |= u32_encode_bits(nss, RATE_MCS_NSS_MSK);
1288
1289		if (rate_v1 & RATE_MCS_HE_MSK_V1) {
1290			u32 he_type_bits = rate_v1 & RATE_MCS_HE_TYPE_MSK_V1;
1291			u32 he_type = he_type_bits >> RATE_MCS_HE_TYPE_POS_V1;
1292			u32 he_106t = (rate_v1 & RATE_MCS_HE_106T_MSK_V1) >>
1293				RATE_MCS_HE_106T_POS_V1;
1294			u32 he_gi_ltf = (rate_v1 & RATE_MCS_HE_GI_LTF_MSK_V1) >>
1295				RATE_MCS_HE_GI_LTF_POS;
1296
1297			if ((he_type_bits == RATE_MCS_HE_TYPE_SU ||
1298			     he_type_bits == RATE_MCS_HE_TYPE_EXT_SU) &&
1299			    he_gi_ltf == RATE_MCS_HE_SU_4_LTF)
1300				/* the new rate have an additional bit to
1301				 * represent the value 4 rather then using SGI
1302				 * bit for this purpose - as it was done in the
1303				 * old rate
1304				 */
1305				he_gi_ltf += (rate_v1 & RATE_MCS_SGI_MSK_V1) >>
1306					RATE_MCS_SGI_POS_V1;
1307
1308			rate_v3 |= he_gi_ltf << RATE_MCS_HE_GI_LTF_POS;
1309			rate_v3 |= he_type << RATE_MCS_HE_TYPE_POS;
1310			rate_v3 |= he_106t << RATE_MCS_HE_106T_POS;
1311			rate_v3 |= rate_v1 & RATE_HE_DUAL_CARRIER_MODE_MSK;
1312			rate_v3 |= RATE_MCS_MOD_TYPE_HE;
1313		} else {
1314			rate_v3 |= RATE_MCS_MOD_TYPE_VHT;
1315		}
1316	/* if legacy format */
1317	} else {
1318		u32 legacy_rate = iwl_legacy_rate_to_fw_idx(rate_v1);
1319
1320		if (WARN_ON_ONCE(legacy_rate == IWL_RATE_INVALID))
1321			legacy_rate = (rate_v1 & RATE_MCS_CCK_MSK_V1) ?
1322				IWL_FIRST_CCK_RATE : IWL_FIRST_OFDM_RATE;
1323
1324		rate_v3 |= legacy_rate;
1325		if (!(rate_v1 & RATE_MCS_CCK_MSK_V1))
1326			rate_v3 |= RATE_MCS_MOD_TYPE_LEGACY_OFDM;
1327	}
1328
1329	/* convert flags */
1330	if (rate_v1 & RATE_MCS_LDPC_MSK_V1)
1331		rate_v3 |= RATE_MCS_LDPC_MSK;
1332	rate_v3 |= (rate_v1 & RATE_MCS_CHAN_WIDTH_MSK_V1) |
1333		(rate_v1 & RATE_MCS_ANT_AB_MSK) |
1334		(rate_v1 & RATE_MCS_STBC_MSK) |
1335		(rate_v1 & RATE_MCS_BF_MSK);
1336
1337	dup = (rate_v1 & RATE_MCS_DUP_MSK_V1) >> RATE_MCS_DUP_POS_V1;
1338	if (dup) {
1339		rate_v3 |= RATE_MCS_DUP_MSK;
1340		rate_v3 |= dup << RATE_MCS_CHAN_WIDTH_POS;
1341	}
1342
1343	if ((!(rate_v1 & RATE_MCS_HE_MSK_V1)) &&
1344	    (rate_v1 & RATE_MCS_SGI_MSK_V1))
1345		rate_v3 |= RATE_MCS_SGI_MSK;
1346
1347	return rate_v3;
1348}
1349
1350__le32 iwl_mvm_v3_rate_to_fw(u32 rate, u8 rate_ver)
1351{
1352	u32 result = 0;
1353	int rate_idx;
1354
1355	if (rate_ver > 1)
1356		return iwl_v3_rate_to_v2_v3(rate, rate_ver > 2);
1357
1358	switch (rate & RATE_MCS_MOD_TYPE_MSK) {
1359	case RATE_MCS_MOD_TYPE_CCK:
1360		result = RATE_MCS_CCK_MSK_V1;
1361		fallthrough;
1362	case RATE_MCS_MOD_TYPE_LEGACY_OFDM:
1363		rate_idx = u32_get_bits(rate, RATE_LEGACY_RATE_MSK);
1364		if (!(result & RATE_MCS_CCK_MSK_V1))
1365			rate_idx += IWL_FIRST_OFDM_RATE;
1366		result |= u32_encode_bits(iwl_fw_rate_idx_to_plcp(rate_idx),
1367					  RATE_LEGACY_RATE_MSK_V1);
1368		break;
1369	case RATE_MCS_MOD_TYPE_HT:
1370		result = RATE_MCS_HT_MSK_V1;
1371		result |= u32_encode_bits(u32_get_bits(rate,
1372						       RATE_HT_MCS_CODE_MSK),
1373					  RATE_HT_MCS_RATE_CODE_MSK_V1);
1374		result |= u32_encode_bits(u32_get_bits(rate,
1375						       RATE_MCS_NSS_MSK),
1376					  RATE_HT_MCS_MIMO2_MSK);
1377		break;
1378	case RATE_MCS_MOD_TYPE_VHT:
1379		result = RATE_MCS_VHT_MSK_V1;
1380		result |= u32_encode_bits(u32_get_bits(rate,
1381						       RATE_VHT_MCS_NSS_MSK),
1382					  RATE_MCS_CODE_MSK);
1383		result |= u32_encode_bits(u32_get_bits(rate, RATE_MCS_NSS_MSK),
1384					  RATE_VHT_MCS_NSS_MSK);
1385		break;
1386	case RATE_MCS_MOD_TYPE_HE: /* not generated */
1387	default:
1388		WARN_ONCE(1, "bad modulation type %d\n",
1389			  u32_get_bits(rate, RATE_MCS_MOD_TYPE_MSK));
1390		return 0;
1391	}
1392
1393	if (rate & RATE_MCS_LDPC_MSK)
1394		result |= RATE_MCS_LDPC_MSK_V1;
1395	WARN_ON_ONCE(u32_get_bits(rate, RATE_MCS_CHAN_WIDTH_MSK) >
1396			RATE_MCS_CHAN_WIDTH_160_VAL);
1397	result |= (rate & RATE_MCS_CHAN_WIDTH_MSK_V1) |
1398		  (rate & RATE_MCS_ANT_AB_MSK) |
1399		  (rate & RATE_MCS_STBC_MSK) |
1400		  (rate & RATE_MCS_BF_MSK);
1401
1402	/* not handling DUP since we don't use it */
1403	WARN_ON_ONCE(rate & RATE_MCS_DUP_MSK);
1404
1405	if (rate & RATE_MCS_SGI_MSK)
1406		result |= RATE_MCS_SGI_MSK_V1;
1407
1408	return cpu_to_le32(result);
1409}
~/ Read-only file preview.