/*
 * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
 *
 * 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.
 */
/**
 * DOC: Define API's for wow pattern addition and deletion in fwr
 */

#include "wlan_pmo_wow.h"
#include "wlan_pmo_tgt_api.h"
#include "wlan_pmo_main.h"
#include "wlan_pmo_obj_mgmt_public_struct.h"
#include <wlan_scan_ucfg_api.h>
#include "wlan_pmo_static_config.h"
#include "wlan_reg_services_api.h"
#include "cfg_nan_api.h"
#include "wlan_utility.h"

void pmo_set_wow_event_bitmap(WOW_WAKE_EVENT_TYPE event,
			      uint32_t wow_bitmap_size,
			      uint32_t *bitmask)
{
	uint32_t bit_idx = 0, idx = 0;

	if (!bitmask || wow_bitmap_size < PMO_WOW_MAX_EVENT_BM_LEN) {
		pmo_err("wow bitmask length shorter than %d",
			PMO_WOW_MAX_EVENT_BM_LEN);
		return;
	}
	pmo_get_event_bitmap_idx(event, wow_bitmap_size, &bit_idx, &idx);
	bitmask[idx] |= 1 << bit_idx;
}

QDF_STATUS pmo_core_del_wow_pattern(struct wlan_objmgr_vdev *vdev)
{
	QDF_STATUS status;
	uint8_t id;
	uint8_t pattern_count;
	struct pmo_vdev_priv_obj *vdev_ctx;

	pmo_enter();
	status = pmo_vdev_get_ref(vdev);
	if (QDF_IS_STATUS_ERROR(status))
		goto out;

	vdev_ctx = pmo_vdev_get_priv(vdev);
	pattern_count = pmo_get_wow_default_ptrn(vdev_ctx);
	/* clear all default patterns cofigured by pmo */
	for (id = 0; id < pattern_count; id++)
		status = pmo_tgt_del_wow_pattern(vdev, id, false);

	/* clear all user patterns cofigured by pmo */
	pattern_count = pmo_get_wow_user_ptrn(vdev_ctx);
	for (id = 0; id < pattern_count; id++)
		status = pmo_tgt_del_wow_pattern(vdev, id, true);

	pmo_vdev_put_ref(vdev);
out:
	pmo_exit();
	return status;
}

QDF_STATUS pmo_core_add_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
		struct pmo_wow_add_pattern *ptrn)
{
	QDF_STATUS status;
	uint8_t id;
	uint8_t bit_to_check, pos;
	uint8_t new_mask[PMO_WOWL_BCAST_PATTERN_MAX_SIZE];
	struct pmo_vdev_priv_obj *vdev_ctx;

	status = pmo_vdev_get_ref(vdev);
	if (QDF_IS_STATUS_ERROR(status))
		goto out;

	vdev_ctx = pmo_vdev_get_priv(vdev);

	/* clear all default patterns cofigured by pmo */
	for (id = 0; id < pmo_get_wow_default_ptrn(vdev_ctx); id++)
		pmo_tgt_del_wow_pattern(vdev, id, false);

	pmo_set_wow_default_ptrn(vdev_ctx, 0);

	pmo_debug("Add user passed wow pattern id %d vdev id %d",
		  ptrn->pattern_id, ptrn->session_id);
	/*
	 * Convert received pattern mask value from bit representation
	 * to byte representation.
	 *
	 * For example, received value from umac,
	 *
	 *      Mask value    : A1 (equivalent binary is "1010 0001")
	 *      Pattern value : 12:00:13:00:00:00:00:44
	 *
	 * The value which goes to FW after the conversion from this
	 * function (1 in mask value will become FF and 0 will
	 * become 00),
	 *
	 *      Mask value    : FF:00:FF:00:00:00:00:FF
	 *      Pattern value : 12:00:13:00:00:00:00:44
	 */
	qdf_mem_zero(new_mask, sizeof(new_mask));
	for (pos = 0; pos < ptrn->pattern_size; pos++) {
		bit_to_check = (PMO_NUM_BITS_IN_BYTE - 1) -
			       (pos % PMO_NUM_BITS_IN_BYTE);
		bit_to_check = 0x1 << bit_to_check;
		if (ptrn->pattern_mask[pos / PMO_NUM_BITS_IN_BYTE] &
		    bit_to_check)
			new_mask[pos] = PMO_WOW_PTRN_MASK_VALID;
	}

	status = pmo_tgt_send_wow_patterns_to_fw(vdev,
						 ptrn->pattern_id,
						 ptrn->pattern,
						 ptrn->pattern_size,
						 ptrn->pattern_byte_offset,
						 new_mask,
						 ptrn->pattern_size, true);
	if (status != QDF_STATUS_SUCCESS)
		pmo_err("Failed to add wow pattern %d", ptrn->pattern_id);

	pmo_vdev_put_ref(vdev);
out:
	pmo_exit();

	return status;
}

QDF_STATUS pmo_core_del_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
		uint8_t pattern_id)
{
	QDF_STATUS status;
	struct pmo_vdev_priv_obj *vdev_ctx;

	status = pmo_vdev_get_ref(vdev);
	if (QDF_IS_STATUS_ERROR(status))
		goto out;

	vdev_ctx = pmo_vdev_get_priv(vdev);
	if (pmo_get_wow_user_ptrn(vdev_ctx) <= 0) {
		pmo_err("No valid user pattern. Num user pattern %u",
			pmo_get_wow_user_ptrn(vdev_ctx));
		status = QDF_STATUS_E_INVAL;
		goto rel_ref;
	}

	pmo_debug("Delete user passed wow pattern id %d total user pattern %d",
		  pattern_id, pmo_get_wow_user_ptrn(vdev_ctx));

	pmo_tgt_del_wow_pattern(vdev, pattern_id, true);

	/* configure default patterns once all user patterns are deleted */
	if (!pmo_get_wow_user_ptrn(vdev_ctx))
		pmo_register_wow_default_patterns(vdev);
rel_ref:
	pmo_vdev_put_ref(vdev);
out:
	pmo_exit();

	return status;
}

void pmo_core_enable_wakeup_event(struct wlan_objmgr_psoc *psoc,
				  uint32_t vdev_id,
				  WOW_WAKE_EVENT_TYPE wow_event)
{
	QDF_STATUS status;
	struct wlan_objmgr_vdev *vdev;
	uint32_t bitmap[PMO_WOW_MAX_EVENT_BM_LEN] = {0};

	pmo_enter();

	if (!psoc) {
		pmo_err("psoc is null");
		goto out;
	}

	vdev = pmo_psoc_get_vdev(psoc, vdev_id);
	if (!vdev) {
		pmo_err("vdev is NULL");
		goto out;
	}

	status = pmo_vdev_get_ref(vdev);
	if (QDF_IS_STATUS_ERROR(status))
		goto out;

	pmo_set_wow_event_bitmap(wow_event, PMO_WOW_MAX_EVENT_BM_LEN, bitmap);

	pmo_tgt_enable_wow_wakeup_event(vdev, bitmap);

	pmo_vdev_put_ref(vdev);

out:
	pmo_exit();
}

void pmo_core_disable_wakeup_event(struct wlan_objmgr_psoc *psoc,
				   uint32_t vdev_id,
				   WOW_WAKE_EVENT_TYPE wow_event)
{
	QDF_STATUS status;
	struct wlan_objmgr_vdev *vdev;
	uint32_t bitmap[PMO_WOW_MAX_EVENT_BM_LEN] = {0};

	pmo_enter();
	if (!psoc) {
		pmo_err("psoc is null");
		goto out;
	}

	vdev = pmo_psoc_get_vdev(psoc, vdev_id);
	if (!vdev) {
		pmo_err("vdev is NULL");
		goto out;
	}

	status = pmo_vdev_get_ref(vdev);
	if (QDF_IS_STATUS_ERROR(status))
		goto out;

	pmo_set_wow_event_bitmap(wow_event, PMO_WOW_MAX_EVENT_BM_LEN, bitmap);

	pmo_tgt_disable_wow_wakeup_event(vdev, bitmap);

	pmo_vdev_put_ref(vdev);

out:
	pmo_exit();
}

/**
 * pmo_is_beaconing_vdev_up(): check if a beaconning vdev is up
 * @psoc: objmgr psoc handle
 *
 * Return TRUE if beaconning vdev is up
 */
static
bool pmo_is_beaconing_vdev_up(struct wlan_objmgr_psoc *psoc)
{
	int vdev_id;
	struct wlan_objmgr_vdev *vdev;
	enum QDF_OPMODE vdev_opmode;
	bool is_beaconing;
	QDF_STATUS status;

	/* Iterate through VDEV list */
	for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) {
		vdev = pmo_psoc_get_vdev(psoc, vdev_id);
		if (!vdev)
			continue;

		status = pmo_vdev_get_ref(vdev);
		if (QDF_IS_STATUS_ERROR(status))
			continue;

		vdev_opmode = pmo_get_vdev_opmode(vdev);
		is_beaconing = pmo_is_vdev_in_beaconning_mode(vdev_opmode) &&
			       QDF_IS_STATUS_SUCCESS(wlan_vdev_is_up(vdev));

		pmo_vdev_put_ref(vdev);

		if (is_beaconing)
			return true;
	}

	return false;
}

/**
 * pmo_support_wow_for_beaconing: wow query for beaconning
 * @psoc: objmgr psoc handle
 *
 * Need to configure wow to enable beaconning offload when
 * a beaconing vdev is up and beaonning offload is configured.
 *
 * Return: true if we need to enable wow for beaconning offload
 */
static
bool pmo_support_wow_for_beaconing(struct wlan_objmgr_psoc *psoc)
{
	/*
	 * if (wmi_service_enabled(wma->wmi_handle,
	 *			wmi_service_beacon_offload))
	 */
	return pmo_is_beaconing_vdev_up(psoc);
}

bool pmo_core_is_wow_applicable(struct wlan_objmgr_psoc *psoc)
{
	int vdev_id;
	struct wlan_objmgr_vdev *vdev;
	bool is_wow_applicable = false;
	QDF_STATUS status;

	if (!psoc) {
		pmo_err("psoc is null");
		return false;
	}

	if (pmo_support_wow_for_beaconing(psoc)) {
		pmo_debug("one of vdev is in beaconning mode, enabling wow");
		return true;
	}

	if (wlan_reg_is_11d_scan_inprogress(psoc)) {
		pmo_debug("11d scan is in progress, enabling wow");
		return true;
	}

	if (pmo_core_is_lpass_enabled(psoc)) {
		pmo_info("lpass enabled, enabling wow");
		return true;
	}

	if (cfg_nan_get_enable(psoc)) {
		pmo_debug("nan enabled, enabling wow");
		return true;
	}

	/* Iterate through VDEV list */
	for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) {
		vdev = pmo_psoc_get_vdev(psoc, vdev_id);
		if (!vdev)
			continue;

		status = pmo_vdev_get_ref(vdev);
		if (QDF_IS_STATUS_ERROR(status))
			continue;

		if (pmo_core_is_vdev_connected(vdev)) {
			pmo_debug("STA is connected, enabling wow");
			is_wow_applicable = true;
		} else if (ucfg_scan_get_pno_in_progress(vdev)) {
			pmo_debug("NLO is in progress, enabling wow");
			is_wow_applicable = true;
		} else if (pmo_core_is_extscan_in_progress(vdev)) {
			pmo_debug("EXT is in progress, enabling wow");
			is_wow_applicable = true;
		} else if (pmo_core_is_p2plo_in_progress(vdev)) {
			pmo_debug("P2P LO is in progress, enabling wow");
			is_wow_applicable = true;
		} else if (pmo_core_get_vdev_op_mode(vdev) == QDF_NDI_MODE) {
			pmo_debug("vdev %d is in NAN data mode, enabling wow",
				  vdev_id);
			is_wow_applicable = true;
		}

		pmo_vdev_put_ref(vdev);

		if (is_wow_applicable)
			return true;
	}

	pmo_debug("All vdev are in disconnected state\n"
		  "and pno/extscan is not in progress, skipping wow");

	return false;
}

void pmo_set_sta_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmap_size)
{

	pmo_set_wow_event_bitmap(WOW_CSA_IE_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_CLIENT_KICKOUT_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_PATTERN_MATCH_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_MAGIC_PKT_RECVD_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_DEAUTH_RECVD_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_DISASSOC_RECVD_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_BMISS_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_GTK_ERR_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_BETTER_AP_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_HTT_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_RA_MATCH_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_NLO_DETECTED_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_EXTSCAN_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_OEM_RESPONSE_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_TDLS_CONN_TRACKER_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_11D_SCAN_EVENT,
				 wow_bitmap_size,
				 bitmask);
}

void pmo_set_sap_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmap_size)
{

	pmo_set_wow_event_bitmap(WOW_PROBE_REQ_WPS_IE_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_PATTERN_MATCH_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_AUTH_REQ_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_ASSOC_REQ_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_DEAUTH_RECVD_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_DISASSOC_RECVD_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_HTT_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_SAP_OBSS_DETECTION_EVENT,
				 wow_bitmap_size,
				 bitmask);
	pmo_set_wow_event_bitmap(WOW_BSS_COLOR_COLLISION_DETECT_EVENT,
				 wow_bitmap_size,
				 bitmask);
}

uint8_t pmo_get_num_wow_filters(struct wlan_objmgr_psoc *psoc)
{
	struct pmo_psoc_priv_obj *psoc_ctx;
	bool apf = false;
	bool arp_ns = false;
	bool pkt_filter = false;

	pmo_psoc_with_ctx(psoc, psoc_ctx) {
		apf = pmo_intersect_apf(psoc_ctx);
		arp_ns = pmo_intersect_arp_ns_offload(psoc_ctx);
		pkt_filter = pmo_intersect_packet_filter(psoc_ctx);
	}

	if (!apf && !pkt_filter)
		return PMO_WOW_FILTERS_MAX;

	if (arp_ns)
		return PMO_WOW_FILTERS_ARP_NS;

	return PMO_WOW_FILTERS_PKT_OR_APF;
}

