/*
 * Copyright (c) 2017-2018 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 public API for pmo to interact with target/WMI
 */

#include "wlan_pmo_tgt_api.h"
#include "wlan_pmo_arp_public_struct.h"
#include "wlan_pmo_ns_public_struct.h"
#include "wlan_pmo_obj_mgmt_public_struct.h"
#include "wlan_pmo_main.h"

QDF_STATUS pmo_tgt_enable_arp_offload_req(struct wlan_objmgr_vdev *vdev,
		uint8_t vdev_id)
{
	struct pmo_arp_offload_params *arp_offload_req = NULL;
	struct pmo_ns_offload_params *ns_offload_req = NULL;
	struct pmo_vdev_priv_obj *vdev_ctx;
	struct wlan_objmgr_psoc *psoc;
	QDF_STATUS status;
	struct wlan_pmo_tx_ops pmo_tx_ops;

	pmo_enter();

	vdev_ctx = pmo_vdev_get_priv(vdev);

	psoc = pmo_vdev_get_psoc(vdev);

	arp_offload_req = qdf_mem_malloc(sizeof(*arp_offload_req));
	if (!arp_offload_req) {
		pmo_err("unable to allocate arp_offload_req");
		status = QDF_STATUS_E_NOMEM;
		goto out;
	}

	ns_offload_req = qdf_mem_malloc(sizeof(*ns_offload_req));
	if (!ns_offload_req) {
		pmo_err("unable to allocate ns_offload_req");
		status = QDF_STATUS_E_NOMEM;
		goto out;
	}

	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
	qdf_mem_copy(arp_offload_req, &vdev_ctx->vdev_arp_req,
		sizeof(*arp_offload_req));
	qdf_mem_copy(ns_offload_req, &vdev_ctx->vdev_ns_req,
		sizeof(*ns_offload_req));
	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);

	pmo_debug("ARP Offload vdev_id: %d enable: %d",
		vdev_id,
		arp_offload_req->enable);
	pmo_debug("NS Offload vdev_id: %d enable: %d ns_count: %u",
		vdev_id,
		ns_offload_req->enable,
		ns_offload_req->num_ns_offload_count);

	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
	if (!pmo_tx_ops.send_arp_offload_req) {
		pmo_err("send_arp_offload_req is null");
		status = QDF_STATUS_E_NULL_VALUE;
		goto out;
	}
	status = pmo_tx_ops.send_arp_offload_req(
			vdev, arp_offload_req, ns_offload_req);
	if (status != QDF_STATUS_SUCCESS) {
		pmo_err("Failed to send ARP offload");
		goto out;
	}

	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
	if (vdev_ctx->vdev_arp_req.enable)
		vdev_ctx->vdev_arp_req.is_offload_applied = true;
	if (vdev_ctx->vdev_ns_req.enable)
		vdev_ctx->vdev_ns_req.is_offload_applied = true;
	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);

out:
	if (arp_offload_req)
		qdf_mem_free(arp_offload_req);
	if (ns_offload_req)
		qdf_mem_free(ns_offload_req);
	pmo_exit();

	return status;
}

QDF_STATUS pmo_tgt_disable_arp_offload_req(struct wlan_objmgr_vdev *vdev,
		uint8_t vdev_id)
{
	struct pmo_arp_offload_params *arp_offload_req = NULL;
	struct pmo_ns_offload_params *ns_offload_req = NULL;
	struct pmo_vdev_priv_obj *vdev_ctx;
	struct wlan_objmgr_psoc *psoc;
	QDF_STATUS status;
	struct wlan_pmo_tx_ops pmo_tx_ops;

	pmo_enter();

	vdev_ctx = pmo_vdev_get_priv(vdev);

	psoc = pmo_vdev_get_psoc(vdev);

	arp_offload_req = qdf_mem_malloc(sizeof(*arp_offload_req));
	if (!arp_offload_req) {
		pmo_err("unable to allocate arp_offload_req");
		status = QDF_STATUS_E_NOMEM;
		goto out;
	}

	ns_offload_req = qdf_mem_malloc(sizeof(*ns_offload_req));
	if (!ns_offload_req) {
		pmo_err("unable to allocate ns_offload_req");
		status = QDF_STATUS_E_NOMEM;
		goto out;
	}

	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
	qdf_mem_copy(arp_offload_req, &vdev_ctx->vdev_arp_req,
		sizeof(*arp_offload_req));
	qdf_mem_copy(ns_offload_req, &vdev_ctx->vdev_ns_req,
		sizeof(*ns_offload_req));
	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);

	pmo_debug("ARP Offload vdev_id: %d enable: %d",
		vdev_id,
		arp_offload_req->enable);
	pmo_debug("NS Offload vdev_id: %d enable: %d ns_count: %u",
		vdev_id,
		ns_offload_req->enable,
		ns_offload_req->num_ns_offload_count);

	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
	if (!pmo_tx_ops.send_arp_offload_req) {
		pmo_err("send_arp_offload_req is null");
		status = QDF_STATUS_E_NULL_VALUE;
		goto out;
	}
	status = pmo_tx_ops.send_arp_offload_req(
			vdev, arp_offload_req, ns_offload_req);
	if (status != QDF_STATUS_SUCCESS)
		pmo_err("Failed to send ARP offload");

	qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
	vdev_ctx->vdev_arp_req.is_offload_applied = false;
	vdev_ctx->vdev_ns_req.is_offload_applied = false;
	qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);

out:
	if (arp_offload_req)
		qdf_mem_free(arp_offload_req);
	if (ns_offload_req)
		qdf_mem_free(ns_offload_req);
	pmo_exit();

	return status;
}

