// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
 * Copyright (C) 2024-2025 Intel Corporation
 */

#include <net/cfg80211.h>
#include <net/mac80211.h>

#include <fw/dbg.h>
#include <iwl-nvm-parse.h>

#include "mld.h"
#include "hcmd.h"
#include "mcc.h"

/* It is the caller's responsibility to free the pointer returned here */
static struct iwl_mcc_update_resp_v8 *
iwl_mld_copy_mcc_resp(const struct iwl_rx_packet *pkt)
{
	const struct iwl_mcc_update_resp_v8 *mcc_resp_v8 = (const void *)pkt->data;
	int n_channels = __le32_to_cpu(mcc_resp_v8->n_channels);
	struct iwl_mcc_update_resp_v8 *resp_cp;
	int notif_len = struct_size(resp_cp, channels, n_channels);

	if (iwl_rx_packet_payload_len(pkt) != notif_len)
		return ERR_PTR(-EINVAL);

	resp_cp = kmemdup(mcc_resp_v8, notif_len, GFP_KERNEL);
	if (!resp_cp)
		return ERR_PTR(-ENOMEM);

	return resp_cp;
}

/* It is the caller's responsibility to free the pointer returned here */
static struct iwl_mcc_update_resp_v8 *
iwl_mld_update_mcc(struct iwl_mld *mld, const char *alpha2,
		   enum iwl_mcc_source src_id)
{
	struct iwl_mcc_update_cmd mcc_update_cmd = {
		.mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]),
		.source_id = (u8)src_id,
	};
	struct iwl_mcc_update_resp_v8 *resp_cp;
	struct iwl_rx_packet *pkt;
	struct iwl_host_cmd cmd = {
		.id = MCC_UPDATE_CMD,
		.flags = CMD_WANT_SKB,
		.data = { &mcc_update_cmd },
		.len[0] = sizeof(mcc_update_cmd),
	};
	int ret;
	u16 mcc;

	IWL_DEBUG_LAR(mld, "send MCC update to FW with '%c%c' src = %d\n",
		      alpha2[0], alpha2[1], src_id);

	ret = iwl_mld_send_cmd(mld, &cmd);
	if (ret)
		return ERR_PTR(ret);

	pkt = cmd.resp_pkt;

	resp_cp = iwl_mld_copy_mcc_resp(pkt);
	if (IS_ERR(resp_cp))
		goto exit;

	mcc = le16_to_cpu(resp_cp->mcc);

	IWL_FW_CHECK(mld, !mcc, "mcc can't be 0: %d\n", mcc);

	IWL_DEBUG_LAR(mld,
		      "MCC response status: 0x%x. new MCC: 0x%x ('%c%c')\n",
		      le32_to_cpu(resp_cp->status), mcc, mcc >> 8, mcc & 0xff);

exit:
	iwl_free_resp(&cmd);
	return resp_cp;
}

/* It is the caller's responsibility to free the pointer returned here */
struct ieee80211_regdomain *
iwl_mld_get_regdomain(struct iwl_mld *mld,
		      const char *alpha2,
		      enum iwl_mcc_source src_id,
		      bool *changed)
{
	struct ieee80211_regdomain *regd = NULL;
	struct iwl_mcc_update_resp_v8 *resp;
	u8 resp_ver = iwl_fw_lookup_notif_ver(mld->fw, IWL_ALWAYS_LONG_GROUP,
					      MCC_UPDATE_CMD, 0);

	IWL_DEBUG_LAR(mld, "Getting regdomain data for %s from FW\n", alpha2);

	lockdep_assert_wiphy(mld->wiphy);

	resp = iwl_mld_update_mcc(mld, alpha2, src_id);
	if (IS_ERR(resp)) {
		IWL_DEBUG_LAR(mld, "Could not get update from FW %ld\n",
			      PTR_ERR(resp));
		resp = NULL;
		goto out;
	}

	if (changed) {
		u32 status = le32_to_cpu(resp->status);

		*changed = (status == MCC_RESP_NEW_CHAN_PROFILE ||
			    status == MCC_RESP_ILLEGAL);
	}
	IWL_DEBUG_LAR(mld, "MCC update response version: %d\n", resp_ver);

	regd = iwl_parse_nvm_mcc_info(mld->trans,
				      __le32_to_cpu(resp->n_channels),
				      resp->channels,
				      __le16_to_cpu(resp->mcc),
				      __le16_to_cpu(resp->geo_info),
				      le32_to_cpu(resp->cap), resp_ver);

	if (IS_ERR(regd)) {
		IWL_DEBUG_LAR(mld, "Could not get parse update from FW %ld\n",
			      PTR_ERR(regd));
		goto out;
	}

	IWL_DEBUG_LAR(mld, "setting alpha2 from FW to %s (0x%x, 0x%x) src=%d\n",
		      regd->alpha2, regd->alpha2[0],
		      regd->alpha2[1], resp->source_id);

	mld->mcc_src = resp->source_id;

	/* FM is the earliest supported and later always do puncturing */
	if (CSR_HW_RFID_TYPE(mld->trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_FM) {
		if (!iwl_puncturing_is_allowed_in_bios(mld->bios_enable_puncturing,
						       le16_to_cpu(resp->mcc)))
			ieee80211_hw_set(mld->hw, DISALLOW_PUNCTURING);
		else
			__clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING,
				    mld->hw->flags);
	}

out:
	kfree(resp);
	return regd;
}

/* It is the caller's responsibility to free the pointer returned here */
static struct ieee80211_regdomain *
iwl_mld_get_current_regdomain(struct iwl_mld *mld,
			      bool *changed)
{
	return iwl_mld_get_regdomain(mld, "ZZ",
				     MCC_SOURCE_GET_CURRENT, changed);
}

void iwl_mld_update_changed_regdomain(struct iwl_mld *mld)
{
	struct ieee80211_regdomain *regd;
	bool changed;

	regd = iwl_mld_get_current_regdomain(mld, &changed);

	if (IS_ERR_OR_NULL(regd))
		return;

	if (changed)
		regulatory_set_wiphy_regd(mld->wiphy, regd);
	kfree(regd);
}

static int iwl_mld_apply_last_mcc(struct iwl_mld *mld,
				  const char *alpha2)
{
	struct ieee80211_regdomain *regd;
	u32 used_src;
	bool changed;
	int ret;

	/* save the last source in case we overwrite it below */
	used_src = mld->mcc_src;

	/* Notify the firmware we support wifi location updates */
	regd = iwl_mld_get_current_regdomain(mld, NULL);
	if (!IS_ERR_OR_NULL(regd))
		kfree(regd);

	/* Now set our last stored MCC and source */
	regd = iwl_mld_get_regdomain(mld, alpha2, used_src,
				     &changed);
	if (IS_ERR_OR_NULL(regd))
		return -EIO;

	/* update cfg80211 if the regdomain was changed */
	if (changed)
		ret = regulatory_set_wiphy_regd_sync(mld->wiphy, regd);
	else
		ret = 0;

	kfree(regd);
	return ret;
}

int iwl_mld_init_mcc(struct iwl_mld *mld)
{
	const struct ieee80211_regdomain *r;
	struct ieee80211_regdomain *regd;
	char mcc[3];
	int retval;

	/* try to replay the last set MCC to FW */
	r = wiphy_dereference(mld->wiphy, mld->wiphy->regd);

	if (r)
		return iwl_mld_apply_last_mcc(mld, r->alpha2);

	regd = iwl_mld_get_current_regdomain(mld, NULL);
	if (IS_ERR_OR_NULL(regd))
		return -EIO;

	if (!iwl_bios_get_mcc(&mld->fwrt, mcc)) {
		kfree(regd);
		regd = iwl_mld_get_regdomain(mld, mcc, MCC_SOURCE_BIOS, NULL);
		if (IS_ERR_OR_NULL(regd))
			return -EIO;
	}

	retval = regulatory_set_wiphy_regd_sync(mld->wiphy, regd);

	kfree(regd);
	return retval;
}

static void iwl_mld_find_assoc_vif_iterator(void *data, u8 *mac,
					    struct ieee80211_vif *vif)
{
	bool *assoc = data;

	if (vif->type == NL80211_IFTYPE_STATION &&
	    vif->cfg.assoc)
		*assoc = true;
}

static bool iwl_mld_is_a_vif_assoc(struct iwl_mld *mld)
{
	bool assoc = false;

	ieee80211_iterate_active_interfaces_atomic(mld->hw,
						   IEEE80211_IFACE_ITER_NORMAL,
						   iwl_mld_find_assoc_vif_iterator,
						   &assoc);
	return assoc;
}

void iwl_mld_handle_update_mcc(struct iwl_mld *mld, struct iwl_rx_packet *pkt)
{
	struct iwl_mcc_chub_notif *notif = (void *)pkt->data;
	enum iwl_mcc_source src;
	char mcc[3];
	struct ieee80211_regdomain *regd;
	bool changed;

	lockdep_assert_wiphy(mld->wiphy);

	if (iwl_mld_is_a_vif_assoc(mld) &&
	    notif->source_id == MCC_SOURCE_WIFI) {
		IWL_DEBUG_LAR(mld, "Ignore mcc update while associated\n");
		return;
	}

	mcc[0] = le16_to_cpu(notif->mcc) >> 8;
	mcc[1] = le16_to_cpu(notif->mcc) & 0xff;
	mcc[2] = '\0';
	src = notif->source_id;

	IWL_DEBUG_LAR(mld,
		      "RX: received chub update mcc cmd (mcc '%s' src %d)\n",
		      mcc, src);
	regd = iwl_mld_get_regdomain(mld, mcc, src, &changed);
	if (IS_ERR_OR_NULL(regd))
		return;

	if (changed)
		regulatory_set_wiphy_regd(mld->hw->wiphy, regd);
	kfree(regd);
}
