/*
 * Copyright (c) 2016 The Linux Foundation. All rights reserved.
 *
 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
 *
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * This file was originally distributed by Qualcomm Atheros, Inc.
 * under proprietary terms before Copyright ownership was assigned
 * to the Linux Foundation.
 */

/**
 * wlan_hdd_tsf.c - WLAN Host Device Driver tsf related implementation
 */

#include "wlan_hdd_main.h"
#include "wma_api.h"

static struct completion tsf_sync_get_completion_evt;
#define WLAN_TSF_SYNC_GET_TIMEOUT 2000
/**
 * hdd_capture_tsf() - capture tsf
 * @adapter: pointer to adapter
 * @buf: pointer to uplayer buf
 * @len : the length of buf
 *
 * This function returns tsf value to uplayer.
 *
 * Return: 0 for success or non-zero negative failure code
 */
int hdd_capture_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len)
{
	int ret = 0;
	hdd_station_ctx_t *hdd_sta_ctx;

	if (adapter == NULL || buf == NULL) {
		hdd_err("invalid pointer");
		return -EINVAL;
	}
	if (len != 1)
		return -EINVAL;

	/* Reset TSF value for new capture */
	adapter->tsf_high = 0;
	adapter->tsf_low = 0;
	adapter->tsf_sync_soc_timer = 0;

	if (adapter->device_mode == QDF_STA_MODE ||
		adapter->device_mode == QDF_P2P_CLIENT_MODE) {
		hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
		if (hdd_sta_ctx->conn_info.connState !=
				eConnectionState_Associated) {
			hdd_err("failed to cap tsf, not connect with ap");
			buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
			return ret;
		}
	}
	if ((adapter->device_mode == QDF_SAP_MODE ||
		adapter->device_mode == QDF_P2P_GO_MODE) &&
		!(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
		hdd_err("Soft AP / P2p GO not beaconing");
		buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
		return ret;
	}
	if (adapter->tsf_state == TSF_CAP_STATE) {
		hdd_err("current in capture state, pls reset");
		buf[0] = TSF_CURRENT_IN_CAP_STATE;
	} else {
		hdd_info("Send TSF capture to FW");
		buf[0] = TSF_RETURN;
		adapter->tsf_state = TSF_CAP_STATE;
		init_completion(&tsf_sync_get_completion_evt);
		ret = wma_cli_set_command((int)adapter->sessionId,
				(int)GEN_PARAM_CAPTURE_TSF,
				adapter->sessionId,
				GEN_CMD);

		if (ret != QDF_STATUS_SUCCESS) {
			hdd_err("capture fail");
			buf[0] = TSF_CAPTURE_FAIL;
			adapter->tsf_state = TSF_IDLE;
		}
	}
	return ret;
}

/**
 * hdd_tsf_reset_gpio() - Reset TSF GPIO used for host timer sync
 * @adapter: pointer to adapter
 *
 * This function send WMI command to reset GPIO configured in FW after
 * TSF get operation.
 *
 * Return: TSF_RETURN on Success, TSF_RESET_GPIO_FAIL on failure
 */
#ifdef QCA_WIFI_3_0
int hdd_tsf_reset_gpio(struct hdd_adapter_s *adapter)
{
	/* No GPIO Host timer sync for integrated WIFI Device */
	return TSF_RETURN;
}
#else
int hdd_tsf_reset_gpio(struct hdd_adapter_s *adapter)
{
	int ret;
	ret = wma_cli_set_command((int)adapter->sessionId,
			(int)GEN_PARAM_RESET_TSF_GPIO, adapter->sessionId,
			GEN_CMD);

	if (ret != 0) {
		hdd_err("tsf reset GPIO fail ");
		ret = TSF_RESET_GPIO_FAIL;
	} else {
		ret = TSF_RETURN;
	}
	return ret;
}
#endif

/**
 * hdd_indicate_tsf() - return tsf to uplayer
 * @adapter: pointer to adapter
 * @buf: pointer to uplayer buf
 * @len : the length of buf
 *
 * This function returns tsf value to upper layer.
 *
 * Return: 0 for success or non-zero negative failure code
 */
int hdd_indicate_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len)
{
	hdd_station_ctx_t *hdd_sta_ctx;

	if (adapter == NULL || buf == NULL) {
		hdd_err("invalid pointer");
		return -EINVAL;
	}

	if (len != 3)
		return -EINVAL;

	buf[1] = 0;
	buf[2] = 0;
	if (adapter->device_mode == QDF_STA_MODE ||
		adapter->device_mode == QDF_P2P_CLIENT_MODE) {
		hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
		if (hdd_sta_ctx->conn_info.connState !=
				eConnectionState_Associated) {
			hdd_info("fail to get tsf, sta in disconnected");
			buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
			return 0;
		}
	}
	if ((adapter->device_mode == QDF_SAP_MODE ||
			adapter->device_mode == QDF_P2P_GO_MODE) &&
			!(test_bit(SOFTAP_BSS_STARTED,
			&adapter->event_flags))) {
		hdd_err("Soft AP / P2p GO not beaconing");
		buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
		return 0;
	}
	if (adapter->tsf_high == 0 && adapter->tsf_low == 0) {
		hdd_info("TSF value not received");
		buf[0] = TSF_NOT_RETURNED_BY_FW;
	} else {
		buf[0] = hdd_tsf_reset_gpio(adapter);
		buf[1] = adapter->tsf_low;
		buf[2] = adapter->tsf_high;
		adapter->tsf_state = TSF_IDLE;
		hdd_info("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u",
			buf[0], buf[1], buf[2]);
	}
	return 0;
}

/**
 * hdd_get_tsf_cb() - handle tsf callback
 * @pcb_cxt: pointer to the hdd_contex
 * @ptsf: pointer to struct stsf
 *
 * This function handle the event that reported by firmware at first.
 * The event contains the vdev_id, current tsf value of this vdev,
 * tsf value is 64bits, discripted in two varaible tsf_low and tsf_high.
 * These two values each is uint32.
 *
 * Return: 0 for success or non-zero negative failure code
 */
static int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf)
{
	struct hdd_context_s *hddctx;
	struct hdd_adapter_s *adapter;
	int status;

	if (pcb_cxt == NULL || ptsf == NULL) {
		hdd_err("HDD context is not valid");
			return -EINVAL;
	}

	hddctx = (struct hdd_context_s *)pcb_cxt;
	status = wlan_hdd_validate_context(hddctx);
	if (0 != status) {
		return -EINVAL;
	}

	adapter = hdd_get_adapter_by_vdev(hddctx, ptsf->vdev_id);

	if (NULL == adapter) {
		hdd_err("failed to find adapter");
		return -EINVAL;
	}
	hdd_info("tsf cb handle event, device_mode is %d",
		adapter->device_mode);

	adapter->tsf_low = ptsf->tsf_low;
	adapter->tsf_high = ptsf->tsf_high;
	adapter->tsf_sync_soc_timer = ((uint64_t) ptsf->soc_timer_high << 32 |
						  ptsf->soc_timer_low);

	complete(&tsf_sync_get_completion_evt);
	hdd_info("Vdev=%u, tsf_low=%u, tsf_high=%u soc_timer=%llu",
		ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high,
		adapter->tsf_sync_soc_timer);
	return 0;
}

/**
 * __wlan_hdd_cfg80211_handle_tsf_cmd(): Setup TSF operations
 * @wiphy: Pointer to wireless phy
 * @wdev: Pointer to wireless device
 * @data: Pointer to data
 * @data_len: Data length
 *
 * Handle TSF SET / GET operation from userspace
 *
 * Return: 0 on success, negative errno on failure
 */
static int __wlan_hdd_cfg80211_handle_tsf_cmd(struct wiphy *wiphy,
					struct wireless_dev *wdev,
					const void *data,
					int data_len)
{
	struct net_device *dev = wdev->netdev;
	hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
	hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
	struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_TSF_MAX + 1];
	int status, ret;
	struct sk_buff *reply_skb;
	uint32_t tsf_op_resp[3], tsf_cmd;

	ENTER_DEV(wdev->netdev);

	status = wlan_hdd_validate_context(hdd_ctx);
	if (0 != status)
		return -EINVAL;

	if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_TSF_MAX, data,
		      data_len, NULL)) {
		hdd_err("Invalid TSF cmd");
		return -EINVAL;
	}

	if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_TSF_CMD]) {
		hdd_err("Invalid TSF cmd");
		return -EINVAL;
	}
	tsf_cmd = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_TSF_CMD]);

	if (tsf_cmd == QCA_TSF_CAPTURE || tsf_cmd == QCA_TSF_SYNC_GET) {
		hdd_capture_tsf(adapter, tsf_op_resp, 1);
		switch (tsf_op_resp[0]) {
		case TSF_RETURN:
			status = 0;
			break;
		case TSF_CURRENT_IN_CAP_STATE:
			status = -EALREADY;
			break;
		case TSF_STA_NOT_CONNECTED_NO_TSF:
		case TSF_SAP_NOT_STARTED_NO_TSF:
			status = -EPERM;
			break;
		default:
		case TSF_CAPTURE_FAIL:
			status = -EINVAL;
			break;
		}
	}
	if (status < 0)
		goto end;

	if (tsf_cmd == QCA_TSF_SYNC_GET) {
		ret = wait_for_completion_timeout(&tsf_sync_get_completion_evt,
			msecs_to_jiffies(WLAN_TSF_SYNC_GET_TIMEOUT));
		if (ret == 0) {
			status = -ETIMEDOUT;
			goto end;
		}
	}

	if (tsf_cmd == QCA_TSF_GET || tsf_cmd == QCA_TSF_SYNC_GET) {
		hdd_indicate_tsf(adapter, tsf_op_resp, 3);
		switch (tsf_op_resp[0]) {
		case TSF_RETURN:
			status = 0;
			break;
		case TSF_NOT_RETURNED_BY_FW:
			status = -EINPROGRESS;
			break;
		case TSF_STA_NOT_CONNECTED_NO_TSF:
		case TSF_SAP_NOT_STARTED_NO_TSF:
			status = -EPERM;
			break;
		default:
			status = -EINVAL;
			break;
		}
		if (status != 0)
			goto end;

		reply_skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
					sizeof(uint64_t) * 2 + NLMSG_HDRLEN,
					QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX,
					GFP_KERNEL);
		if (!reply_skb) {
			hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
			status = -ENOMEM;
			goto end;
		}
		if (nla_put_u64(reply_skb, QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE,
				((uint64_t) adapter->tsf_high << 32 |
				adapter->tsf_low)) ||
				nla_put_u64(reply_skb,
				QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE,
				adapter->tsf_sync_soc_timer)){
			hdd_err("nla put fail");
			kfree_skb(reply_skb);
			status = -EINVAL;
			goto end;
		}
		status = cfg80211_vendor_cmd_reply(reply_skb);
	}

end:
	hdd_info("TSF operation %d Status: %d", tsf_cmd, status);
	return status;
}

/**
 * wlan_hdd_cfg80211_handle_tsf_cmd(): Setup TSF operations
 * @wiphy: Pointer to wireless phy
 * @wdev: Pointer to wireless device
 * @data: Pointer to data
 * @data_len: Data length
 *
 * Handle TSF SET / GET operation from userspace
 *
 * Return: 0 on success, negative errno on failure
 */
int wlan_hdd_cfg80211_handle_tsf_cmd(struct wiphy *wiphy,
					struct wireless_dev *wdev,
					const void *data,
					int data_len)
{
	int ret;

	cds_ssr_protect(__func__);
	ret = __wlan_hdd_cfg80211_handle_tsf_cmd(wiphy, wdev, data, data_len);
	cds_ssr_unprotect(__func__);

	return ret;
}

/**
 * wlan_hdd_tsf_init() - set callback to handle tsf value.
 * @hdd_ctx: pointer to the struct hdd_context_s
 *
 * This function set the callback to sme module, the callback will be
 * called when a tsf event is reported by firmware
 *
 * Return: none
 */
void wlan_hdd_tsf_init(struct hdd_context_s *hdd_ctx)
{
	sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
}
