/*
 * Copyright (c) 2017-2018 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.
 */

/**
 *  DOC: HDD object manager API source file to create/destroy PSOC,
 *  PDEV, VDEV and PEER objects.
 */

#include <wlan_hdd_object_manager.h>
#include <wlan_osif_priv.h>
#include <wlan_reg_ucfg_api.h>
#include <target_if.h>

#define LOW_2GHZ_FREQ 2312
#define HIGH_2GHZ_FREQ 2732
#define LOW_5GHZ_FREQ  4912
#define HIGH_5GHZ_FREQ 6100

static void hdd_init_pdev_os_priv(struct hdd_context *hdd_ctx,
	struct pdev_osif_priv *os_priv)
{
	/* Initialize the OS private structure*/
	os_priv->wiphy = hdd_ctx->wiphy;
	os_priv->legacy_osif_priv = hdd_ctx;
	wlan_cfg80211_scan_priv_init(hdd_ctx->hdd_pdev);
}

static void hdd_deinit_pdev_os_priv(struct wlan_objmgr_pdev *pdev)
{
	wlan_cfg80211_scan_priv_deinit(pdev);
}

static void hdd_init_vdev_os_priv(struct hdd_adapter *adapter,
	struct vdev_osif_priv *os_priv)
{
	/* Initialize the vdev OS private structure*/
	os_priv->wdev = adapter->dev->ieee80211_ptr;
	os_priv->legacy_osif_priv = adapter;
	wlan_cfg80211_tdls_priv_init(os_priv);
}

static void hdd_init_psoc_qdf_ctx(struct wlan_objmgr_psoc *psoc)
{
	qdf_device_t qdf_ctx;

	qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
	if (!qdf_ctx) {
		hdd_err("qdf ctx is null, can't set to soc object");
		return;
	}

	wlan_psoc_set_qdf_dev(psoc, qdf_ctx);
}

int hdd_objmgr_create_and_store_psoc(struct hdd_context *hdd_ctx,
				     uint8_t psoc_id)
{
	QDF_STATUS status;
	struct wlan_objmgr_psoc *psoc;

	psoc = wlan_objmgr_psoc_obj_create(psoc_id, WLAN_DEV_OL);
	if (!psoc)
		return -ENOMEM;

	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_HDD_ID_OBJ_MGR);
	if (QDF_IS_STATUS_ERROR(status)) {
		hdd_err("Failed to acquire psoc ref; status:%d", status);
		QDF_BUG(false);
		goto psoc_destroy;
	}

	hdd_init_psoc_qdf_ctx(psoc);
	hdd_ctx->hdd_psoc = psoc;

	return 0;

psoc_destroy:
	wlan_objmgr_psoc_obj_delete(psoc);

	return qdf_status_to_os_return(status);
}

int hdd_objmgr_release_and_destroy_psoc(struct hdd_context *hdd_ctx)
{
	QDF_STATUS status;
	struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;

	hdd_ctx->hdd_psoc = NULL;

	QDF_BUG(psoc);
	if (!psoc)
		return -EINVAL;

	wlan_objmgr_print_ref_all_objects_per_psoc(psoc);

	status = wlan_objmgr_psoc_obj_delete(psoc);
	wlan_objmgr_psoc_release_ref(psoc, WLAN_HDD_ID_OBJ_MGR);

	return qdf_status_to_os_return(status);
}

int hdd_objmgr_create_and_store_pdev(struct hdd_context *hdd_ctx)
{
	QDF_STATUS status;
	struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
	struct wlan_objmgr_pdev *pdev;
	struct pdev_osif_priv *priv;
	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap_ptr;

	if (!psoc) {
		hdd_err("Psoc NULL");
		return -EINVAL;
	}

	priv = qdf_mem_malloc(sizeof(*priv));
	if (priv == NULL) {
		hdd_err("pdev os obj create failed");
		return -ENOMEM;
	}

	reg_cap_ptr = ucfg_reg_get_hal_reg_cap(psoc);
	reg_cap_ptr->phy_id = 0;
	reg_cap_ptr->low_2ghz_chan = LOW_2GHZ_FREQ;
	reg_cap_ptr->high_2ghz_chan = HIGH_2GHZ_FREQ;
	reg_cap_ptr->low_5ghz_chan = LOW_5GHZ_FREQ;
	reg_cap_ptr->high_5ghz_chan = HIGH_5GHZ_FREQ;

	pdev = wlan_objmgr_pdev_obj_create(psoc, priv);
	if (!pdev) {
		hdd_err("pdev obj create failed");
		status = QDF_STATUS_E_NOMEM;
		goto free_priv;
	}

	status = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_HDD_ID_OBJ_MGR);
	if (QDF_IS_STATUS_ERROR(status)) {
		hdd_err("Failed to acquire pdev ref; status:%d", status);
		QDF_BUG(false);
		goto pdev_destroy;
	}

	status = target_if_alloc_pdev_tgt_info(pdev);
	if (status != QDF_STATUS_SUCCESS) {
		hdd_err("pdev tgt info alloc failed");
		goto pdev_destroy;
	}

	hdd_ctx->hdd_pdev = pdev;
	sme_store_pdev(hdd_ctx->hHal, hdd_ctx->hdd_pdev);
	hdd_init_pdev_os_priv(hdd_ctx, priv);
	return 0;

pdev_destroy:
	wlan_objmgr_pdev_obj_delete(pdev);
free_priv:
	qdf_mem_free(priv);

	return qdf_status_to_os_return(status);
}

int hdd_objmgr_release_and_destroy_pdev(struct hdd_context *hdd_ctx)
{
	QDF_STATUS status;
	struct wlan_objmgr_pdev *pdev = hdd_ctx->hdd_pdev;
	struct pdev_osif_priv *osif_priv;

	hdd_ctx->hdd_pdev = NULL;

	QDF_BUG(pdev);
	if (!pdev)
		return -EINVAL;

	target_if_free_pdev_tgt_info(pdev);

	hdd_deinit_pdev_os_priv(pdev);
	osif_priv = wlan_pdev_get_ospriv(pdev);
	wlan_pdev_reset_ospriv(pdev);
	qdf_mem_free(osif_priv);

	status = wlan_objmgr_pdev_obj_delete(pdev);
	wlan_objmgr_pdev_release_ref(pdev, WLAN_HDD_ID_OBJ_MGR);

	return qdf_status_to_os_return(status);
}

int hdd_objmgr_create_and_store_vdev(struct wlan_objmgr_pdev *pdev,
				     struct hdd_adapter *adapter)
{
	QDF_STATUS status;
	int errno;
	struct wlan_objmgr_vdev *vdev;
	struct wlan_objmgr_peer *peer;
	struct vdev_osif_priv *osif_priv;
	struct wlan_vdev_create_params vdev_params = {0};

	QDF_BUG(pdev);
	if (!pdev) {
		hdd_err("pdev is null");
		return -EINVAL;
	}

	osif_priv = qdf_mem_malloc(sizeof(*osif_priv));
	if (!osif_priv) {
		hdd_err("Failed to allocate osif_priv; out of memory");
		return -ENOMEM;
	}
	hdd_init_vdev_os_priv(adapter, osif_priv);

	vdev_params.opmode = adapter->device_mode;
	vdev_params.osifp = osif_priv;
	qdf_mem_copy(vdev_params.macaddr,
		     adapter->mac_addr.bytes,
		     QDF_NET_MAC_ADDR_MAX_LEN);

	vdev = wlan_objmgr_vdev_obj_create(pdev, &vdev_params);
	if (!vdev) {
		hdd_err("Failed to create vdev object");
		errno = -ENOMEM;
		goto osif_priv_free;
	}

	/*
	 * To enable legacy use cases, we need to delay physical vdev destroy
	 * until after the sme session has been closed. We accomplish this by
	 * getting a reference here.
	 */
	status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_HDD_ID_OBJ_MGR);
	if (QDF_IS_STATUS_ERROR(status)) {
		hdd_err("Failed to acquire vdev ref; status:%d", status);
		errno = qdf_status_to_os_return(status);
		goto vdev_destroy;
	}

	peer = wlan_objmgr_peer_obj_create(vdev, WLAN_PEER_SELF,
					   vdev_params.macaddr);
	if (!peer) {
		hdd_err("Failed to create self peer for adapter mode %d",
			adapter->device_mode);
		errno = -ENOMEM;
		goto vdev_put_ref;
	}

	adapter->hdd_vdev = vdev;
	adapter->session_id = wlan_vdev_get_id(vdev);

	return 0;

vdev_put_ref:
	wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR);

vdev_destroy:
	wlan_objmgr_vdev_obj_delete(vdev);

osif_priv_free:
	qdf_mem_free(osif_priv);

	return errno;
}

int hdd_objmgr_release_and_destroy_vdev(struct hdd_adapter *adapter)
{
	QDF_STATUS status;
	struct wlan_objmgr_vdev *vdev = adapter->hdd_vdev;
	struct vdev_osif_priv *osif_priv;
	uint8_t *self_mac_addr;

	adapter->hdd_vdev = NULL;
	adapter->session_id = HDD_SESSION_ID_INVALID;

	QDF_BUG(vdev);
	if (!vdev)
		return -EINVAL;

	osif_priv = wlan_vdev_get_ospriv(vdev);
	wlan_vdev_reset_ospriv(vdev);

	QDF_BUG(osif_priv);
	if (osif_priv) {
		wlan_cfg80211_tdls_priv_deinit(osif_priv);
		qdf_mem_free(osif_priv);
	}

	self_mac_addr = wlan_vdev_mlme_get_macaddr(vdev);
	if (hdd_objmgr_remove_peer_object(vdev, self_mac_addr))
		hdd_err("Self peer delete failed");

	status = wlan_objmgr_vdev_obj_delete(vdev);
	wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR);

	return qdf_status_to_os_return(status);
}

int hdd_objmgr_add_peer_object(struct wlan_objmgr_vdev *vdev,
			       enum QDF_OPMODE adapter_mode,
			       uint8_t *mac_addr,
			       bool is_p2p_type)
{
	enum wlan_peer_type peer_type;
	struct wlan_objmgr_peer *peer;

	if ((adapter_mode == QDF_STA_MODE) ||
		(adapter_mode == QDF_P2P_CLIENT_MODE)) {
		peer_type = WLAN_PEER_AP;
	} else if ((adapter_mode == QDF_SAP_MODE) ||
		(adapter_mode == QDF_P2P_GO_MODE)) {
		if (is_p2p_type) {
			peer_type = WLAN_PEER_P2P_CLI;
		} else {
			peer_type = WLAN_PEER_STA;
		}
	} else if (adapter_mode == QDF_IBSS_MODE) {
		peer_type = WLAN_PEER_IBSS;
	} else if (adapter_mode == QDF_NDI_MODE) {
		peer_type = WLAN_PEER_NDP;
	} else {
		hdd_err("Unsupported device mode %d", adapter_mode);
		return -EINVAL;
	}

	if (!vdev) {
		hdd_err("vdev NULL");
		QDF_ASSERT(0);
		return -EFAULT;
	}

	peer = wlan_objmgr_peer_obj_create(vdev, peer_type, mac_addr);
	if (!peer)
		return -ENOMEM;

	hdd_debug("Peer object "MAC_ADDRESS_STR" add success! Type: %d",
		 MAC_ADDR_ARRAY(mac_addr), peer_type);

	return 0;
}

int hdd_objmgr_remove_peer_object(struct wlan_objmgr_vdev *vdev,
				  uint8_t *mac_addr)
{
	struct wlan_objmgr_psoc *psoc;
	struct wlan_objmgr_peer *peer;

	if (!vdev) {
		hdd_err("vdev NULL");
		QDF_ASSERT(0);
		return -EINVAL;
	}

	psoc = wlan_vdev_get_psoc(vdev);
	if (!psoc) {
		hdd_err("Psoc NUll");
		QDF_ASSERT(0);
		return -EINVAL;
	}

	peer = wlan_objmgr_get_peer(psoc, mac_addr, WLAN_HDD_ID_OBJ_MGR);
	if (peer) {
		wlan_objmgr_peer_obj_delete(peer);

		/* Unref to decrement ref happened in find_peer */
		wlan_objmgr_peer_release_ref(peer, WLAN_HDD_ID_OBJ_MGR);

		hdd_info("Peer obj "MAC_ADDRESS_STR" deleted",
				MAC_ADDR_ARRAY(mac_addr));
		return 0;
	}

	hdd_err("Peer obj "MAC_ADDRESS_STR" not found",
				MAC_ADDR_ARRAY(mac_addr));

	return -EINVAL;
}

int hdd_objmgr_set_peer_mlme_auth_state(struct wlan_objmgr_vdev *vdev,
					bool is_authenticated)
{
	struct wlan_objmgr_peer *peer;
	QDF_STATUS status;

	wlan_vdev_obj_lock(vdev);
	peer = wlan_vdev_get_bsspeer(vdev);
	wlan_vdev_obj_unlock(vdev);

	if (!peer) {
		hdd_err("peer is null");

		return -EINVAL;
	}
	status = wlan_objmgr_peer_try_get_ref(peer, WLAN_TDLS_NB_ID);
	if (status != QDF_STATUS_SUCCESS)
		return -EINVAL;

	wlan_peer_obj_lock(peer);
	wlan_peer_mlme_set_auth_state(peer, is_authenticated);
	wlan_peer_obj_unlock(peer);

	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_NB_ID);
	return 0;
}

int hdd_objmgr_set_peer_mlme_state(struct wlan_objmgr_vdev *vdev,
	enum wlan_peer_state peer_state)
{
	struct wlan_objmgr_peer *peer;

	wlan_vdev_obj_lock(vdev);
	peer = wlan_vdev_get_bsspeer(vdev);
	wlan_vdev_obj_unlock(vdev);

	if (!peer) {
		hdd_err("peer is null");

		return -EINVAL;
	}

	wlan_peer_obj_lock(peer);
	wlan_peer_mlme_set_state(peer, WLAN_ASSOC_STATE);
	wlan_peer_obj_unlock(peer);

	return 0;
}

