/*
 * 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 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");
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");

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;
}

