// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
 * Copyright (C) 2013-2014, 2018-2019, 2022-2024 Intel Corporation
 * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
 */
#include "mvm.h"

/* For counting bound interfaces */
struct iwl_mvm_active_iface_iterator_data {
	struct ieee80211_vif *ignore_vif;
	struct ieee80211_sta *sta_vif_ap_sta;
	enum iwl_sf_state sta_vif_state;
	u32 num_active_macs;
};

/*
 * Count bound interfaces which are not p2p, besides data->ignore_vif.
 * data->station_vif will point to one bound vif of type station, if exists.
 */
static void iwl_mvm_bound_iface_iterator(void *_data, u8 *mac,
					 struct ieee80211_vif *vif)
{
	struct iwl_mvm_active_iface_iterator_data *data = _data;
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);

	if (vif == data->ignore_vif || !mvmvif->deflink.phy_ctxt ||
	    vif->type == NL80211_IFTYPE_P2P_DEVICE ||
	    vif->type == NL80211_IFTYPE_NAN)
		return;

	data->num_active_macs++;

	if (vif->type == NL80211_IFTYPE_STATION) {
		data->sta_vif_ap_sta = mvmvif->ap_sta;
		if (vif->cfg.assoc)
			data->sta_vif_state = SF_FULL_ON;
		else
			data->sta_vif_state = SF_INIT_OFF;
	}
}

/*
 * Aging and idle timeouts for the different possible scenarios
 * in default configuration
 */
static const
__le32 sf_full_timeout_def[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = {
	{
		cpu_to_le32(SF_SINGLE_UNICAST_AGING_TIMER_DEF),
		cpu_to_le32(SF_SINGLE_UNICAST_IDLE_TIMER_DEF)
	},
	{
		cpu_to_le32(SF_AGG_UNICAST_AGING_TIMER_DEF),
		cpu_to_le32(SF_AGG_UNICAST_IDLE_TIMER_DEF)
	},
	{
		cpu_to_le32(SF_MCAST_AGING_TIMER_DEF),
		cpu_to_le32(SF_MCAST_IDLE_TIMER_DEF)
	},
	{
		cpu_to_le32(SF_BA_AGING_TIMER_DEF),
		cpu_to_le32(SF_BA_IDLE_TIMER_DEF)
	},
	{
		cpu_to_le32(SF_TX_RE_AGING_TIMER_DEF),
		cpu_to_le32(SF_TX_RE_IDLE_TIMER_DEF)
	},
};

/*
 * Aging and idle timeouts for the different possible scenarios
 * in single BSS MAC configuration.
 */
static const __le32 sf_full_timeout[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = {
	{
		cpu_to_le32(SF_SINGLE_UNICAST_AGING_TIMER),
		cpu_to_le32(SF_SINGLE_UNICAST_IDLE_TIMER)
	},
	{
		cpu_to_le32(SF_AGG_UNICAST_AGING_TIMER),
		cpu_to_le32(SF_AGG_UNICAST_IDLE_TIMER)
	},
	{
		cpu_to_le32(SF_MCAST_AGING_TIMER),
		cpu_to_le32(SF_MCAST_IDLE_TIMER)
	},
	{
		cpu_to_le32(SF_BA_AGING_TIMER),
		cpu_to_le32(SF_BA_IDLE_TIMER)
	},
	{
		cpu_to_le32(SF_TX_RE_AGING_TIMER),
		cpu_to_le32(SF_TX_RE_IDLE_TIMER)
	},
};

static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm,
				    struct iwl_sf_cfg_cmd *sf_cmd,
				    struct ieee80211_sta *sta)
{
	int i, j, watermark;
	u8 max_rx_nss = 0;
	bool is_legacy = true;
	struct ieee80211_link_sta *link_sta;
	unsigned int link_id;

	sf_cmd->watermark[SF_LONG_DELAY_ON] = cpu_to_le32(SF_W_MARK_SCAN);

	/*
	 * If we are in association flow - check antenna configuration
	 * capabilities of the AP station, and choose the watermark accordingly.
	 */
	if (sta) {
		/* find the maximal NSS number among all links (if relevant) */
		rcu_read_lock();
		for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) {
			link_sta = rcu_dereference(sta->link[link_id]);
			if (!link_sta)
				continue;

			if (link_sta->ht_cap.ht_supported ||
			    link_sta->vht_cap.vht_supported ||
			    cfg_eht_cap_has_eht(link_sta) ||
			    link_sta->he_cap.has_he) {
				is_legacy = false;
				max_rx_nss = max(max_rx_nss, link_sta->rx_nss);
			}
		}
		rcu_read_unlock();

		if (!is_legacy) {
			switch (max_rx_nss) {
			case 1:
				watermark = SF_W_MARK_SISO;
				break;
			case 2:
				watermark = SF_W_MARK_MIMO2;
				break;
			default:
				watermark = SF_W_MARK_MIMO3;
				break;
			}
		} else {
			watermark = SF_W_MARK_LEGACY;
		}
	/* default watermark value for unassociated mode. */
	} else {
		watermark = SF_W_MARK_MIMO2;
	}
	sf_cmd->watermark[SF_FULL_ON] = cpu_to_le32(watermark);

	for (i = 0; i < SF_NUM_SCENARIO; i++) {
		for (j = 0; j < SF_NUM_TIMEOUT_TYPES; j++) {
			sf_cmd->long_delay_timeouts[i][j] =
					cpu_to_le32(SF_LONG_DELAY_AGING_TIMER);
		}
	}

	if (sta) {
		BUILD_BUG_ON(sizeof(sf_full_timeout) !=
			     sizeof(__le32) * SF_NUM_SCENARIO *
			     SF_NUM_TIMEOUT_TYPES);

		memcpy(sf_cmd->full_on_timeouts, sf_full_timeout,
		       sizeof(sf_full_timeout));
	} else {
		BUILD_BUG_ON(sizeof(sf_full_timeout_def) !=
			     sizeof(__le32) * SF_NUM_SCENARIO *
			     SF_NUM_TIMEOUT_TYPES);

		memcpy(sf_cmd->full_on_timeouts, sf_full_timeout_def,
		       sizeof(sf_full_timeout_def));
	}
}

static int iwl_mvm_sf_config(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
			     enum iwl_sf_state new_state)
{
	struct iwl_sf_cfg_cmd sf_cmd = {
		.state = cpu_to_le32(new_state),
	};
	int ret = 0;

	/*
	 * If an associated AP sta changed its antenna configuration, the state
	 * will remain FULL_ON but SF parameters need to be reconsidered.
	 */
	if (new_state != SF_FULL_ON && mvm->sf_state == new_state)
		return 0;

	switch (new_state) {
	case SF_UNINIT:
		iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL);
		break;
	case SF_FULL_ON:
		if (!sta) {
			IWL_ERR(mvm,
				"No station: Cannot switch SF to FULL_ON\n");
			return -EINVAL;
		}
		iwl_mvm_fill_sf_command(mvm, &sf_cmd, sta);
		break;
	case SF_INIT_OFF:
		iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL);
		break;
	default:
		WARN_ONCE(1, "Invalid state: %d. not sending Smart Fifo cmd\n",
			  new_state);
		return -EINVAL;
	}

	ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_SF_CFG_CMD, CMD_ASYNC,
				   sizeof(sf_cmd), &sf_cmd);
	if (!ret)
		mvm->sf_state = new_state;

	return ret;
}

/*
 * Update Smart fifo:
 * Count bound interfaces that are not to be removed, ignoring p2p devices,
 * and set new state accordingly.
 */
int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
		      bool remove_vif)
{
	enum iwl_sf_state new_state;
	struct iwl_mvm_vif *mvmvif = NULL;
	struct iwl_mvm_active_iface_iterator_data data = {
		.ignore_vif = changed_vif,
		.sta_vif_state = SF_UNINIT,
	};
	struct ieee80211_sta *sta = NULL;

	if (fw_has_api(&mvm->fw->ucode_capa,
		       IWL_UCODE_TLV_API_SMART_FIFO_OFFLOAD))
		return 0;
	/*
	 * Ignore the call if we are in HW Restart flow, or if the handled
	 * vif is a p2p device.
	 */
	if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
	    (changed_vif && (changed_vif->type == NL80211_IFTYPE_P2P_DEVICE ||
			     changed_vif->type == NL80211_IFTYPE_NAN)))
		return 0;

	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
						   IEEE80211_IFACE_ITER_NORMAL,
						   iwl_mvm_bound_iface_iterator,
						   &data);

	/* If changed_vif exists and is not to be removed, add to the count */
	if (changed_vif && !remove_vif)
		data.num_active_macs++;

	switch (data.num_active_macs) {
	case 0:
		/* If there are no active macs - change state to SF_INIT_OFF */
		new_state = SF_INIT_OFF;
		break;
	case 1:
		if (remove_vif) {
			/* The one active mac left is of type station
			 * and we filled the relevant data during iteration
			 */
			new_state = data.sta_vif_state;
			sta = data.sta_vif_ap_sta;
		} else {
			if (WARN_ON(!changed_vif))
				return -EINVAL;
			if (changed_vif->type != NL80211_IFTYPE_STATION) {
				new_state = SF_UNINIT;
			} else if (changed_vif->cfg.assoc &&
				   changed_vif->bss_conf.dtim_period) {
				mvmvif = iwl_mvm_vif_from_mac80211(changed_vif);
				sta = mvmvif->ap_sta;
				new_state = SF_FULL_ON;
			} else {
				new_state = SF_INIT_OFF;
			}
		}
		break;
	default:
		/* If there are multiple active macs - change to SF_UNINIT */
		new_state = SF_UNINIT;
	}

	return iwl_mvm_sf_config(mvm, sta, new_state);
}
