/*
 * 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.
 */

#include <linux/kernel.h>
#include "wlan_hdd_request_manager.h"
#include "wlan_hdd_main.h"
#include "qdf_list.h"
#include "qdf_event.h"
#include "qdf_mem.h"

/* arbitrary value */
#define MAX_NUM_REQUESTS 20

static bool is_initialized;
static qdf_list_t requests;
static qdf_spinlock_t spinlock;
static void *cookie;

struct hdd_request {
	qdf_list_node_t node;
	void *cookie;
	uint32_t reference_count;
	struct hdd_request_params params;
	qdf_event_t completed;
};

/* must be called with spinlock held */
static void hdd_request_unlink(struct hdd_request *request)
{
	qdf_list_remove_node(&requests, &request->node);
}

static void hdd_request_destroy(struct hdd_request *request)
{
	struct hdd_request_params *params;

	params = &request->params;
	if (params->dealloc) {
		void *priv = hdd_request_priv(request);

		params->dealloc(priv);
	}
	qdf_event_destroy(&request->completed);
	qdf_mem_free(request);
}

/* must be called with spinlock held */
static struct hdd_request *hdd_request_find(void *cookie)
{
	QDF_STATUS status;
	struct hdd_request *request;
	qdf_list_node_t *node;

	status = qdf_list_peek_front(&requests, &node);
	while (QDF_IS_STATUS_SUCCESS(status)) {
		request = qdf_container_of(node, struct hdd_request, node);
		if (request->cookie == cookie)
			return request;
		status = qdf_list_peek_next(&requests, node, &node);
	}

	return NULL;
}

struct hdd_request *hdd_request_alloc(const struct hdd_request_params *params)
{
	size_t length;
	struct hdd_request *request;

	if (!is_initialized) {
		hdd_err("invoked when not initialized");
		return NULL;
	}

	length = sizeof(*request) + params->priv_size;
	request = qdf_mem_malloc(length);
	if (!request) {
		hdd_err("allocation failed");
		return NULL;
	}
	request->reference_count = 1;
	request->params = *params;
	qdf_event_create(&request->completed);
	qdf_spin_lock_bh(&spinlock);
	request->cookie = cookie++;
	qdf_list_insert_back(&requests, &request->node);
	qdf_spin_unlock_bh(&spinlock);
	hdd_debug("request %pK, cookie %pK", request, request->cookie);

	return request;
}

void *hdd_request_priv(struct hdd_request *request)
{
	/* private data area immediately follows the struct hdd_request */
	return request + 1;
}

void *hdd_request_cookie(struct hdd_request *request)
{
	return request->cookie;
}

struct hdd_request *hdd_request_get(void *cookie)
{
	struct hdd_request *request;

	if (!is_initialized) {
		hdd_err("invoked when not initialized");
		return NULL;
	}
	qdf_spin_lock_bh(&spinlock);
	request = hdd_request_find(cookie);
	if (request)
		request->reference_count++;
	qdf_spin_unlock_bh(&spinlock);
	hdd_debug("cookie %pK, request %pK", cookie, request);

	return request;
}

void hdd_request_put(struct hdd_request *request)
{
	bool unlinked = false;

	hdd_debug("request %pK, cookie %pK", request, request->cookie);
	qdf_spin_lock_bh(&spinlock);
	request->reference_count--;
	if (0 == request->reference_count) {
		hdd_request_unlink(request);
		unlinked = true;
	}
	qdf_spin_unlock_bh(&spinlock);
	if (unlinked)
		hdd_request_destroy(request);
}

int hdd_request_wait_for_response(struct hdd_request *request)
{
	QDF_STATUS status;

	status = qdf_wait_for_event_completion(&request->completed,
				       request->params.timeout_ms);

	return qdf_status_to_os_return(status);
}

void hdd_request_complete(struct hdd_request *request)
{
	(void) qdf_event_set(&request->completed);
}

void hdd_request_manager_init(void)
{
	if (is_initialized)
		return;

	qdf_list_create(&requests, MAX_NUM_REQUESTS);
	qdf_spinlock_create(&spinlock);
	is_initialized = true;
}

/*
 * hdd_request_manager_deinit implementation note:
 * It is intentional that we do not destroy the list or the spinlock.
 * This allows threads to still access the infrastructure even when it
 * has been deinitialized. Since neither lists nor spinlocks consume
 * resources this does not result in a resource leak.
 */
void hdd_request_manager_deinit(void)
{
	is_initialized = false;
}
