/*
 * Copyright (c) 2017 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: Implements mc addr filtering offload feature API's
 */

#include "wlan_pmo_mc_addr_filtering.h"
#include "wlan_pmo_tgt_api.h"
#include "wlan_pmo_main.h"
#include "wlan_pmo_obj_mgmt_public_struct.h"


#define PMO_INVALID_MC_ADDR_COUNT (-1)

static void pmo_core_fill_mc_list(struct pmo_vdev_priv_obj **vdev_ctx,
	struct pmo_mc_addr_list_params *ip)
{
	struct pmo_mc_addr_list *op_list;
	int i;
	static const uint8_t ipv6_rs[] = {
		0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
	struct pmo_vdev_priv_obj *temp_ctx;
	uint8_t addr_fp;

	temp_ctx = *vdev_ctx;
	addr_fp = temp_ctx->addr_filter_pattern;
	op_list = &temp_ctx->vdev_mc_list_req;

	qdf_spin_lock_bh(&temp_ctx->pmo_vdev_lock);
	op_list->mc_cnt = ip->count;
	qdf_spin_unlock_bh(&temp_ctx->pmo_vdev_lock);

	for (i = 0; i < ip->count; i++) {
		pmo_debug("%pM", ip->mc_addr[i].bytes);
		/*
		 * Skip following addresses:
		 * 1)IPv6 router solicitation address
		 * 2)Any other address pattern if its set during
		 *  RXFILTER REMOVE driver command based on
		 *  addr_filter_pattern
		 */
		if ((!qdf_mem_cmp(ip->mc_addr[i].bytes, ipv6_rs,
			QDF_MAC_ADDR_SIZE)) ||
		   (addr_fp &&
		   (!qdf_mem_cmp(ip->mc_addr[i].bytes, &addr_fp, 1)))) {
			pmo_debug("MC/BC filtering Skip addr %pM",
				ip->mc_addr[i].bytes);
			qdf_spin_lock_bh(&temp_ctx->pmo_vdev_lock);
			op_list->mc_cnt--;
			qdf_spin_unlock_bh(&temp_ctx->pmo_vdev_lock);
			continue;
		}
		qdf_spin_lock_bh(&temp_ctx->pmo_vdev_lock);
		qdf_mem_set(&(op_list->mc_addr[i].bytes), 0,
			QDF_MAC_ADDR_SIZE);
		qdf_mem_copy(&(op_list->mc_addr[i].bytes),
			ip->mc_addr[i].bytes, QDF_MAC_ADDR_SIZE);
		qdf_spin_unlock_bh(&temp_ctx->pmo_vdev_lock);
		pmo_debug("mlist[%pM] = ", op_list->mc_addr[i].bytes);
	}
}

static QDF_STATUS pmo_core_cache_mc_addr_list_in_vdev_priv(
		struct pmo_mc_addr_list_params *mc_list_config,
		struct wlan_objmgr_vdev *vdev)
{
	struct pmo_vdev_priv_obj *vdev_ctx;

	vdev_ctx = pmo_vdev_get_priv(vdev);
	pmo_core_fill_mc_list(&vdev_ctx, mc_list_config);

	return QDF_STATUS_SUCCESS;
}

static QDF_STATUS pmo_core_flush_mc_addr_list_from_vdev_priv(
			struct wlan_objmgr_vdev *vdev)
{
	struct pmo_vdev_priv_obj *vdev_ctx;

	vdev_ctx = pmo_vdev_get_priv(vdev);

	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
	qdf_mem_zero(&vdev_ctx->vdev_mc_list_req,
		sizeof(vdev_ctx->vdev_mc_list_req));
	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);

	return QDF_STATUS_SUCCESS;
}

QDF_STATUS pmo_core_enhanced_mc_filter_enable(struct wlan_objmgr_vdev *vdev)
{
	QDF_STATUS status;

	PMO_ENTER();

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

	pmo_tgt_send_enhance_multicast_offload_req(vdev, true);

	pmo_vdev_put_ref(vdev);

exit_with_status:
	PMO_EXIT();

	return status;
}

QDF_STATUS pmo_core_enhanced_mc_filter_disable(struct wlan_objmgr_vdev *vdev)
{
	QDF_STATUS status;

	PMO_ENTER();

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

	pmo_tgt_send_enhance_multicast_offload_req(vdev, false);

	pmo_vdev_put_ref(vdev);

exit_with_status:
	PMO_EXIT();

	return status;
}

QDF_STATUS pmo_core_set_mc_filter_req(struct wlan_objmgr_vdev *vdev,
	struct pmo_mc_addr_list *mc_list)
{
	int i;

	PMO_ENTER();

	if (pmo_tgt_get_multiple_mc_filter_support(vdev)) {
		pmo_debug("FW supports multiple mcast filter");
		pmo_tgt_set_multiple_mc_filter_req(vdev, mc_list);
	} else {
		pmo_debug("FW does not support multiple mcast filter");
		for (i = 0; i < mc_list->mc_cnt; i++)
			pmo_tgt_set_mc_filter_req(vdev, mc_list->mc_addr[i]);
	}

	PMO_EXIT();

	return QDF_STATUS_SUCCESS;
}

QDF_STATUS pmo_core_clear_mc_filter_req(struct wlan_objmgr_vdev *vdev,
	struct pmo_mc_addr_list *mc_list)
{
	int i;

	PMO_ENTER();
	if (pmo_tgt_get_multiple_mc_filter_support(vdev)) {
		pmo_debug("FW supports multiple mcast filter");
		pmo_tgt_clear_multiple_mc_filter_req(vdev, mc_list);
	} else {
		pmo_debug("FW does not support multiple mcast filter");
		for (i = 0; i < mc_list->mc_cnt; i++)
			pmo_tgt_clear_mc_filter_req(vdev, mc_list->mc_addr[i]);
	}

	PMO_EXIT();

	return QDF_STATUS_SUCCESS;
}

static QDF_STATUS pmo_core_do_enable_mc_addr_list(struct wlan_objmgr_vdev *vdev,
	struct pmo_vdev_priv_obj *vdev_ctx,
	struct pmo_mc_addr_list *op_mc_list_req)
{
	QDF_STATUS status;

	PMO_ENTER();
	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
	if (!vdev_ctx->vdev_mc_list_req.mc_cnt) {
		qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
		pmo_err("mc_cnt is zero so skip to add mc list");
		status = QDF_STATUS_E_INVAL;
		goto out;
	}
	qdf_mem_copy(op_mc_list_req, &vdev_ctx->vdev_mc_list_req,
		sizeof(*op_mc_list_req));
	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);

	status = pmo_core_set_mc_filter_req(vdev, op_mc_list_req);
	if (status != QDF_STATUS_SUCCESS) {
		pmo_err("cannot apply mc filter request");
		status = QDF_STATUS_E_INVAL;
		goto out;
	}

	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
	vdev_ctx->vdev_mc_list_req.is_filter_applied = true;
	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
out:
	PMO_EXIT();

	return status;
}

static QDF_STATUS pmo_core_do_disable_mc_addr_list(
	struct wlan_objmgr_vdev *vdev,
	struct pmo_vdev_priv_obj *vdev_ctx,
	struct pmo_mc_addr_list *op_mc_list_req)
{
	QDF_STATUS status;

	PMO_ENTER();
	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
	/* validate filter is applied before clearing in fwr */
	if (!vdev_ctx->vdev_mc_list_req.is_filter_applied) {
		qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
		pmo_err("mc filter is not applied in fwr");
		status = QDF_STATUS_E_INVAL;
		goto out;
	}
	qdf_mem_copy(op_mc_list_req, &vdev_ctx->vdev_mc_list_req,
		sizeof(*op_mc_list_req));
	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);

	status = pmo_core_clear_mc_filter_req(vdev, op_mc_list_req);
	if (status != QDF_STATUS_SUCCESS) {
		pmo_err("cannot apply mc filter request");
		status = QDF_STATUS_E_INVAL;
		goto out;
	}

	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
	vdev_ctx->vdev_mc_list_req.is_filter_applied = false;
	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
out:
	PMO_EXIT();

	return status;
}

uint8_t pmo_core_max_mc_addr_supported(struct wlan_objmgr_psoc *psoc)
{
	return PMO_MAX_MC_ADDR_LIST;
}

int pmo_core_get_mc_addr_list_count(struct wlan_objmgr_psoc *psoc,
		uint8_t vdev_id)
{
	QDF_STATUS status;
	struct wlan_objmgr_vdev *vdev;
	struct pmo_vdev_priv_obj *vdev_ctx;
	uint8_t mc_cnt;

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

	status = pmo_vdev_get_ref(vdev);
	if (QDF_IS_STATUS_ERROR(status)) {
		pmo_warn("failed to get vdev reference");
		return PMO_INVALID_MC_ADDR_COUNT;
	}

	vdev_ctx = pmo_vdev_get_priv(vdev);
	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
	mc_cnt = vdev_ctx->vdev_mc_list_req.mc_cnt;
	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);

	pmo_vdev_put_ref(vdev);

	return mc_cnt;
}

void pmo_core_set_mc_addr_list_count(struct wlan_objmgr_psoc *psoc,
		uint8_t vdev_id, uint8_t count)
{
	QDF_STATUS status;
	struct pmo_vdev_priv_obj *vdev_ctx;
	struct wlan_objmgr_vdev *vdev;

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

	status = pmo_vdev_get_ref(vdev);
	if (QDF_IS_STATUS_ERROR(status)) {
		pmo_warn("failed to get vdev reference");
		return;
	}

	vdev_ctx = pmo_vdev_get_priv(vdev);
	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
	vdev_ctx->vdev_mc_list_req.mc_cnt = count;
	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);

	pmo_vdev_put_ref(vdev);
}

static QDF_STATUS pmo_core_mc_addr_flitering_sanity(
			struct wlan_objmgr_vdev *vdev)
{
	struct pmo_vdev_priv_obj *vdev_ctx;

	if (!vdev) {
		pmo_err("vdev is NULL");
		return QDF_STATUS_E_NULL_VALUE;
	}

	vdev_ctx = pmo_vdev_get_priv(vdev);

	/* Check if INI is enabled or not, otherwise just return */
	if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.enable_mc_list) {
		pmo_info("user disabled mc_addr_list using INI");
		return QDF_STATUS_E_INVAL;
	}

	if (!pmo_core_is_vdev_supports_offload(vdev)) {
		pmo_info("vdev in invalid opmode for mc addr filtering %d",
			pmo_get_vdev_opmode(vdev));
		return QDF_STATUS_E_INVAL;
	}

	if (!pmo_core_is_vdev_connected(vdev))
		return QDF_STATUS_E_INVAL;

	return QDF_STATUS_SUCCESS;
}
QDF_STATUS pmo_core_cache_mc_addr_list(
		struct pmo_mc_addr_list_params *mc_list_config)
{
	struct wlan_objmgr_vdev *vdev;
	QDF_STATUS status;

	PMO_ENTER();

	if (!mc_list_config->psoc) {
		pmo_err("psoc is NULL");
		status = QDF_STATUS_E_NULL_VALUE;
		goto out;
	}

	vdev = pmo_psoc_get_vdev(mc_list_config->psoc, mc_list_config->vdev_id);
	if (!vdev) {
		pmo_err("vdev is NULL");
		status = QDF_STATUS_E_NULL_VALUE;
		goto out;
	}

	status = pmo_vdev_get_ref(vdev);
	if (QDF_IS_STATUS_ERROR(status)) {
		pmo_warn("failed to get vdev reference");
		status = QDF_STATUS_E_INVAL;
		goto out;
	}

	status = pmo_core_mc_addr_flitering_sanity(vdev);
	if (status != QDF_STATUS_SUCCESS)
		goto dec_ref;

	pmo_info("Cache mc addr list for vdev id: %d psoc: %pK vdev: %pK",
			mc_list_config->vdev_id, mc_list_config->psoc, vdev);

	status = pmo_core_cache_mc_addr_list_in_vdev_priv(mc_list_config, vdev);
dec_ref:
	pmo_vdev_put_ref(vdev);
out:
	PMO_EXIT();

	return status;
}

QDF_STATUS pmo_core_flush_mc_addr_list(struct wlan_objmgr_psoc *psoc,
	uint8_t vdev_id)
{
	struct wlan_objmgr_vdev *vdev;
	QDF_STATUS status = QDF_STATUS_SUCCESS;

	PMO_ENTER();
	if (!psoc) {
		pmo_err("psoc is NULL");
		status = QDF_STATUS_E_NULL_VALUE;
		goto out;
	}

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

	status = pmo_vdev_get_ref(vdev);
	if (QDF_IS_STATUS_ERROR(status)) {
		pmo_warn("failed to get vdev reference");
		status = QDF_STATUS_E_INVAL;
		goto out;
	}

	status = pmo_core_mc_addr_flitering_sanity(vdev);
	if (status != QDF_STATUS_SUCCESS)
		goto dec_ref;

	pmo_info("Flush mc addr list for vdev id: %d psoc: %pK vdev: %pK",
			vdev_id, psoc, vdev);

	status = pmo_core_flush_mc_addr_list_from_vdev_priv(vdev);

dec_ref:
	pmo_vdev_put_ref(vdev);
out:
	PMO_EXIT();

	return status;
}

static QDF_STATUS pmo_core_handle_enable_mc_list_trigger(
			struct wlan_objmgr_vdev *vdev,
			enum pmo_offload_trigger trigger)
{
	struct pmo_vdev_priv_obj *vdev_ctx;
	QDF_STATUS status;
	struct pmo_mc_addr_list *op_mc_list_req;

	PMO_ENTER();

	vdev_ctx = pmo_vdev_get_priv(vdev);

	op_mc_list_req = qdf_mem_malloc(sizeof(*op_mc_list_req));
	if (!op_mc_list_req) {
		pmo_err("op_mc_list_req is NULL");
		status = QDF_STATUS_E_NOMEM;
		goto exit_with_status;
	}

	switch (trigger) {
	case pmo_mc_list_change_notify:
		if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) {
			pmo_info("active offload is disabled, skip in mode: %d",
				 trigger);
			status = QDF_STATUS_E_INVAL;
			goto free_req;
		}
		status = pmo_core_do_enable_mc_addr_list(vdev, vdev_ctx,
							 op_mc_list_req);
		break;
	case pmo_apps_suspend:
		if (vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) {
			pmo_info("active offload is enabled, skip in mode: %d",
				trigger);
			status = QDF_STATUS_E_INVAL;
			goto free_req;
		}
		status = pmo_core_do_enable_mc_addr_list(vdev, vdev_ctx,
							 op_mc_list_req);
		break;
	default:
		status = QDF_STATUS_E_INVAL;
		pmo_err("invalid pmo trigger for enable mc list");
		break;
	}

free_req:
	qdf_mem_free(op_mc_list_req);

exit_with_status:
	PMO_EXIT();

	return status;
}

QDF_STATUS pmo_core_enable_mc_addr_filtering_in_fwr(
		struct wlan_objmgr_psoc *psoc,
		uint8_t vdev_id,
		enum pmo_offload_trigger trigger)
{
	QDF_STATUS status;
	struct wlan_objmgr_vdev *vdev;

	PMO_ENTER();

	status = pmo_psoc_get_ref(psoc);
	if (QDF_IS_STATUS_ERROR(status))
		goto exit_with_status;

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

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

	status = pmo_core_mc_addr_flitering_sanity(vdev);
	if (status != QDF_STATUS_SUCCESS)
		goto put_vdev;

	pmo_info("enable mclist trigger: %d", trigger);
	status = pmo_core_handle_enable_mc_list_trigger(vdev, trigger);

put_vdev:
	pmo_vdev_put_ref(vdev);

put_psoc:
	pmo_psoc_put_ref(psoc);

exit_with_status:
	PMO_EXIT();

	return status;
}

static QDF_STATUS pmo_core_handle_disable_mc_list_trigger(
			struct wlan_objmgr_vdev *vdev,
			enum pmo_offload_trigger trigger)
{
	struct pmo_vdev_priv_obj *vdev_ctx;
	QDF_STATUS status;
	struct pmo_mc_addr_list *op_mc_list_req = NULL;

	vdev_ctx = pmo_vdev_get_priv(vdev);

	op_mc_list_req = qdf_mem_malloc(sizeof(*op_mc_list_req));
	if (!op_mc_list_req) {
		pmo_err("op_mc_list_req is NULL");
		status = QDF_STATUS_E_NULL_VALUE;
		goto out;
	}

	switch (trigger) {
	case pmo_peer_disconnect:
	case pmo_mc_list_change_notify:
		if (!vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) {
			pmo_info("active offload is disabled, skip in mode: %d",
				trigger);
			status = QDF_STATUS_E_INVAL;
			goto out;
		}
		status = pmo_core_do_disable_mc_addr_list(vdev, vdev_ctx,
				op_mc_list_req);
		break;
	case pmo_apps_resume:
		if (vdev_ctx->pmo_psoc_ctx->psoc_cfg.active_mode_offload) {
			pmo_info("active offload is enabled, skip in mode: %d",
				trigger);
			status = QDF_STATUS_E_INVAL;
			goto out;
		}
		status = pmo_core_do_disable_mc_addr_list(vdev, vdev_ctx,
				op_mc_list_req);
		break;
	default:
		status = QDF_STATUS_E_INVAL;
		pmo_err("invalid pmo trigger for disable mc list");
		break;
	}
out:
	if (op_mc_list_req)
		qdf_mem_free(op_mc_list_req);

	return status;
}

QDF_STATUS pmo_core_disable_mc_addr_filtering_in_fwr(
		struct wlan_objmgr_psoc *psoc,
		uint8_t vdev_id,
		enum pmo_offload_trigger trigger)
{
	QDF_STATUS status;
	struct wlan_objmgr_vdev *vdev;

	PMO_ENTER();
	if (!psoc) {
		pmo_err("psoc is NULL");
		status = QDF_STATUS_E_NULL_VALUE;
		goto out;
	}

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

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

	status = pmo_core_mc_addr_flitering_sanity(vdev);
	if (status != QDF_STATUS_SUCCESS)
		goto dec_ref;

	pmo_info("disable mclist trigger: %d", trigger);
	status = pmo_core_handle_disable_mc_list_trigger(vdev, trigger);
dec_ref:
	pmo_vdev_put_ref(vdev);
out:
	PMO_EXIT();

	return status;
}

