// SPDX-License-Identifier: GPL-2.0-only
/*
 * Implementation of chip-to-host event (aka indications) of WFxxx Split Mac
 * (WSM) API.
 *
 * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
 * Copyright (c) 2010, ST-Ericsson
 */
#include <linux/skbuff.h>
#include <linux/etherdevice.h>

#include "hif_rx.h"
#include "wfx.h"
#include "scan.h"
#include "bh.h"
#include "sta.h"
#include "data_rx.h"
#include "secure_link.h"
#include "hif_api_cmd.h"

static int hif_generic_confirm(struct wfx_dev *wdev,
			       const struct hif_msg *hif, const void *buf)
{
	// All confirm messages start with status
	int status = le32_to_cpup((__le32 *)buf);
	int cmd = hif->id;
	int len = le16_to_cpu(hif->len) - 4; // drop header

	WARN(!mutex_is_locked(&wdev->hif_cmd.lock), "data locking error");

	if (!wdev->hif_cmd.buf_send) {
		dev_warn(wdev->dev, "unexpected confirmation: 0x%.2x\n", cmd);
		return -EINVAL;
	}

	if (cmd != wdev->hif_cmd.buf_send->id) {
		dev_warn(wdev->dev,
			 "chip response mismatch request: 0x%.2x vs 0x%.2x\n",
			 cmd, wdev->hif_cmd.buf_send->id);
		return -EINVAL;
	}

	if (wdev->hif_cmd.buf_recv) {
		if (wdev->hif_cmd.len_recv >= len)
			memcpy(wdev->hif_cmd.buf_recv, buf, len);
		else
			status = -ENOMEM;
	}
	wdev->hif_cmd.ret = status;

	if (!wdev->hif_cmd.async) {
		complete(&wdev->hif_cmd.done);
	} else {
		wdev->hif_cmd.buf_send = NULL;
		mutex_unlock(&wdev->hif_cmd.lock);
		if (cmd != HIF_REQ_ID_SL_EXCHANGE_PUB_KEYS)
			mutex_unlock(&wdev->hif_cmd.key_renew_lock);
	}
	return status;
}

static int hif_tx_confirm(struct wfx_dev *wdev,
			  const struct hif_msg *hif, const void *buf)
{
	const struct hif_cnf_tx *body = buf;

	wfx_tx_confirm_cb(wdev, body);
	return 0;
}

static int hif_multi_tx_confirm(struct wfx_dev *wdev,
				const struct hif_msg *hif, const void *buf)
{
	const struct hif_cnf_multi_transmit *body = buf;
	int i;

	WARN(body->num_tx_confs <= 0, "corrupted message");
	for (i = 0; i < body->num_tx_confs; i++)
		wfx_tx_confirm_cb(wdev, &body->tx_conf_payload[i]);
	return 0;
}

static int hif_startup_indication(struct wfx_dev *wdev,
				  const struct hif_msg *hif, const void *buf)
{
	const struct hif_ind_startup *body = buf;

	if (body->status || body->firmware_type > 4) {
		dev_err(wdev->dev, "received invalid startup indication");
		return -EINVAL;
	}
	memcpy(&wdev->hw_caps, body, sizeof(struct hif_ind_startup));
	le16_to_cpus((__le16 *)&wdev->hw_caps.hardware_id);
	le16_to_cpus((__le16 *)&wdev->hw_caps.num_inp_ch_bufs);
	le16_to_cpus((__le16 *)&wdev->hw_caps.size_inp_ch_buf);
	le32_to_cpus((__le32 *)&wdev->hw_caps.supported_rate_mask);

	complete(&wdev->firmware_ready);
	return 0;
}

static int hif_wakeup_indication(struct wfx_dev *wdev,
				 const struct hif_msg *hif, const void *buf)
{
	if (!wdev->pdata.gpio_wakeup
	    || !gpiod_get_value(wdev->pdata.gpio_wakeup)) {
		dev_warn(wdev->dev, "unexpected wake-up indication\n");
		return -EIO;
	}
	return 0;
}

static int hif_keys_indication(struct wfx_dev *wdev,
			       const struct hif_msg *hif, const void *buf)
{
	const struct hif_ind_sl_exchange_pub_keys *body = buf;
	u8 pubkey[API_NCP_PUB_KEY_SIZE];

	// SL_PUB_KEY_EXCHANGE_STATUS_SUCCESS is used by legacy secure link
	if (body->status && body->status != HIF_STATUS_SLK_NEGO_SUCCESS)
		dev_warn(wdev->dev, "secure link negociation error\n");
	memcpy(pubkey, body->ncp_pub_key, sizeof(pubkey));
	memreverse(pubkey, sizeof(pubkey));
	wfx_sl_check_pubkey(wdev, pubkey, body->ncp_pub_key_mac);
	return 0;
}

static int hif_receive_indication(struct wfx_dev *wdev,
				  const struct hif_msg *hif,
				  const void *buf, struct sk_buff *skb)
{
	struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
	const struct hif_ind_rx *body = buf;

	if (!wvif) {
		dev_warn(wdev->dev, "ignore rx data for non-existent vif %d\n",
			 hif->interface);
		return 0;
	}
	skb_pull(skb, sizeof(struct hif_msg) + sizeof(struct hif_ind_rx));
	wfx_rx_cb(wvif, body, skb);

	return 0;
}

static int hif_event_indication(struct wfx_dev *wdev,
				const struct hif_msg *hif, const void *buf)
{
	struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
	const struct hif_ind_event *body = buf;
	int type = le32_to_cpu(body->event_id);

	if (!wvif) {
		dev_warn(wdev->dev, "received event for non-existent vif\n");
		return 0;
	}

	switch (type) {
	case HIF_EVENT_IND_RCPI_RSSI:
		wfx_event_report_rssi(wvif, body->event_data.rcpi_rssi);
		break;
	case HIF_EVENT_IND_BSSLOST:
		schedule_delayed_work(&wvif->beacon_loss_work, 0);
		break;
	case HIF_EVENT_IND_BSSREGAINED:
		cancel_delayed_work(&wvif->beacon_loss_work);
		dev_dbg(wdev->dev, "ignore BSSREGAINED indication\n");
		break;
	case HIF_EVENT_IND_PS_MODE_ERROR:
		dev_warn(wdev->dev, "error while processing power save request: %d\n",
			 le32_to_cpu(body->event_data.ps_mode_error));
		break;
	default:
		dev_warn(wdev->dev, "unhandled event indication: %.2x\n",
			 type);
		break;
	}
	return 0;
}

static int hif_pm_mode_complete_indication(struct wfx_dev *wdev,
					   const struct hif_msg *hif,
					   const void *buf)
{
	struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);

	WARN_ON(!wvif);
	complete(&wvif->set_pm_mode_complete);

	return 0;
}

static int hif_scan_complete_indication(struct wfx_dev *wdev,
					const struct hif_msg *hif,
					const void *buf)
{
	struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);

	WARN_ON(!wvif);
	wfx_scan_complete(wvif);

	return 0;
}

static int hif_join_complete_indication(struct wfx_dev *wdev,
					const struct hif_msg *hif,
					const void *buf)
{
	struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);

	WARN_ON(!wvif);
	dev_warn(wdev->dev, "unattended JoinCompleteInd\n");

	return 0;
}

static int hif_suspend_resume_indication(struct wfx_dev *wdev,
					 const struct hif_msg *hif,
					 const void *buf)
{
	struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface);
	const struct hif_ind_suspend_resume_tx *body = buf;

	if (body->suspend_resume_flags.bc_mc_only) {
		WARN_ON(!wvif);
		if (body->suspend_resume_flags.resume)
			wfx_suspend_resume_mc(wvif, STA_NOTIFY_AWAKE);
		else
			wfx_suspend_resume_mc(wvif, STA_NOTIFY_SLEEP);
	} else {
		WARN(body->peer_sta_set, "misunderstood indication");
		WARN(hif->interface != 2, "misunderstood indication");
		if (body->suspend_resume_flags.resume)
			wfx_suspend_hot_dev(wdev, STA_NOTIFY_AWAKE);
		else
			wfx_suspend_hot_dev(wdev, STA_NOTIFY_SLEEP);
	}

	return 0;
}

static int hif_generic_indication(struct wfx_dev *wdev,
				  const struct hif_msg *hif, const void *buf)
{
	const struct hif_ind_generic *body = buf;
	int type = le32_to_cpu(body->indication_type);

	switch (type) {
	case HIF_GENERIC_INDICATION_TYPE_RAW:
		return 0;
	case HIF_GENERIC_INDICATION_TYPE_STRING:
		dev_info(wdev->dev, "firmware says: %s\n",
			 (char *)body->indication_data.raw_data);
		return 0;
	case HIF_GENERIC_INDICATION_TYPE_RX_STATS:
		mutex_lock(&wdev->rx_stats_lock);
		// Older firmware send a generic indication beside RxStats
		if (!wfx_api_older_than(wdev, 1, 4))
			dev_info(wdev->dev, "Rx test ongoing. Temperature: %d°C\n",
				 body->indication_data.rx_stats.current_temp);
		memcpy(&wdev->rx_stats, &body->indication_data.rx_stats,
		       sizeof(wdev->rx_stats));
		mutex_unlock(&wdev->rx_stats_lock);
		return 0;
	case HIF_GENERIC_INDICATION_TYPE_TX_POWER_LOOP_INFO:
		mutex_lock(&wdev->tx_power_loop_info_lock);
		memcpy(&wdev->tx_power_loop_info,
		       &body->indication_data.tx_power_loop_info,
		       sizeof(wdev->tx_power_loop_info));
		mutex_unlock(&wdev->tx_power_loop_info_lock);
		return 0;
	default:
		dev_err(wdev->dev, "generic_indication: unknown indication type: %#.8x\n",
			type);
		return -EIO;
	}
}

static const struct {
	int val;
	const char *str;
	bool has_param;
} hif_errors[] = {
	{ HIF_ERROR_FIRMWARE_ROLLBACK,
		"rollback status" },
	{ HIF_ERROR_FIRMWARE_DEBUG_ENABLED,
		"debug feature enabled" },
	{ HIF_ERROR_PDS_PAYLOAD,
		"PDS version is not supported" },
	{ HIF_ERROR_PDS_TESTFEATURE,
		"PDS ask for an unknown test mode" },
	{ HIF_ERROR_OOR_VOLTAGE,
		"out-of-range power supply voltage", true },
	{ HIF_ERROR_OOR_TEMPERATURE,
		"out-of-range temperature", true },
	{ HIF_ERROR_SLK_REQ_DURING_KEY_EXCHANGE,
		"secure link does not expect request during key exchange" },
	{ HIF_ERROR_SLK_SESSION_KEY,
		"secure link session key is invalid" },
	{ HIF_ERROR_SLK_OVERFLOW,
		"secure link overflow" },
	{ HIF_ERROR_SLK_WRONG_ENCRYPTION_STATE,
		"secure link messages list does not match message encryption" },
	{ HIF_ERROR_HIF_BUS_FREQUENCY_TOO_LOW,
		"bus clock is too slow (<1kHz)" },
	{ HIF_ERROR_HIF_RX_DATA_TOO_LARGE,
		"HIF message too large" },
	// Following errors only exists in old firmware versions:
	{ HIF_ERROR_HIF_TX_QUEUE_FULL,
		"HIF messages queue is full" },
	{ HIF_ERROR_HIF_BUS,
		"HIF bus" },
	{ HIF_ERROR_SLK_MULTI_TX_UNSUPPORTED,
		"secure link does not support multi-tx confirmations" },
	{ HIF_ERROR_SLK_OUTDATED_SESSION_KEY,
		"secure link session key is outdated" },
	{ HIF_ERROR_SLK_DECRYPTION,
		"secure link params (nonce or tag) mismatch" },
};

static int hif_error_indication(struct wfx_dev *wdev,
				const struct hif_msg *hif, const void *buf)
{
	const struct hif_ind_error *body = buf;
	int type = le32_to_cpu(body->type);
	int param = (s8)body->data[0];
	int i;

	for (i = 0; i < ARRAY_SIZE(hif_errors); i++)
		if (type == hif_errors[i].val)
			break;
	if (i < ARRAY_SIZE(hif_errors))
		if (hif_errors[i].has_param)
			dev_err(wdev->dev, "asynchronous error: %s: %d\n",
				hif_errors[i].str, param);
		else
			dev_err(wdev->dev, "asynchronous error: %s\n",
				hif_errors[i].str);
	else
		dev_err(wdev->dev, "asynchronous error: unknown: %08x\n", type);
	print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET,
		       16, 1, hif, le16_to_cpu(hif->len), false);
	wdev->chip_frozen = true;

	return 0;
};

static int hif_exception_indication(struct wfx_dev *wdev,
				    const struct hif_msg *hif, const void *buf)
{
	const struct hif_ind_exception *body = buf;
	int type = le32_to_cpu(body->type);

	if (type == 4)
		dev_err(wdev->dev, "firmware assert %d\n",
			le32_to_cpup((__le32 *)body->data));
	else
		dev_err(wdev->dev, "firmware exception\n");
	print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET,
		       16, 1, hif, le16_to_cpu(hif->len), false);
	wdev->chip_frozen = true;

	return -1;
}

static const struct {
	int msg_id;
	int (*handler)(struct wfx_dev *wdev,
		       const struct hif_msg *hif, const void *buf);
} hif_handlers[] = {
	/* Confirmations */
	{ HIF_CNF_ID_TX,                   hif_tx_confirm },
	{ HIF_CNF_ID_MULTI_TRANSMIT,       hif_multi_tx_confirm },
	/* Indications */
	{ HIF_IND_ID_STARTUP,              hif_startup_indication },
	{ HIF_IND_ID_WAKEUP,               hif_wakeup_indication },
	{ HIF_IND_ID_JOIN_COMPLETE,        hif_join_complete_indication },
	{ HIF_IND_ID_SET_PM_MODE_CMPL,     hif_pm_mode_complete_indication },
	{ HIF_IND_ID_SCAN_CMPL,            hif_scan_complete_indication },
	{ HIF_IND_ID_SUSPEND_RESUME_TX,    hif_suspend_resume_indication },
	{ HIF_IND_ID_SL_EXCHANGE_PUB_KEYS, hif_keys_indication },
	{ HIF_IND_ID_EVENT,                hif_event_indication },
	{ HIF_IND_ID_GENERIC,              hif_generic_indication },
	{ HIF_IND_ID_ERROR,                hif_error_indication },
	{ HIF_IND_ID_EXCEPTION,            hif_exception_indication },
	// FIXME: allocate skb_p from hif_receive_indication and make it generic
	//{ HIF_IND_ID_RX,                 hif_receive_indication },
};

void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb)
{
	int i;
	const struct hif_msg *hif = (const struct hif_msg *)skb->data;
	int hif_id = hif->id;

	if (hif_id == HIF_IND_ID_RX) {
		// hif_receive_indication take care of skb lifetime
		hif_receive_indication(wdev, hif, hif->body, skb);
		return;
	}
	// Note: mutex_is_lock cause an implicit memory barrier that protect
	// buf_send
	if (mutex_is_locked(&wdev->hif_cmd.lock)
	    && wdev->hif_cmd.buf_send
	    && wdev->hif_cmd.buf_send->id == hif_id) {
		hif_generic_confirm(wdev, hif, hif->body);
		goto free;
	}
	for (i = 0; i < ARRAY_SIZE(hif_handlers); i++) {
		if (hif_handlers[i].msg_id == hif_id) {
			if (hif_handlers[i].handler)
				hif_handlers[i].handler(wdev, hif, hif->body);
			goto free;
		}
	}
	if (hif_id & 0x80)
		dev_err(wdev->dev, "unsupported HIF indication: ID %02x\n",
			hif_id);
	else
		dev_err(wdev->dev, "unexpected HIF confirmation: ID %02x\n",
			hif_id);
free:
	dev_kfree_skb(skb);
}
