/*
 * Broadcom Dongle Host Driver (DHD), Generic work queue framework
 * Generic interface to handle dhd deferred work events
 *
 * Copyright (C) 2024, Broadcom.
 *
 *      Unless you and Broadcom execute a separate written software license
 * agreement governing use of this software, this software is licensed to you
 * under the terms of the GNU General Public License version 2 (the "GPL"),
 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
 * following added to such license:
 *
 *      As a special exception, the copyright holders of this software give you
 * permission to link this software with independent modules, and to copy and
 * distribute the resulting executable under terms of your choice, provided that
 * you also meet, for each linked independent module, the terms and conditions of
 * the license of that module.  An independent module is a module which is not
 * derived from this software.  The special exception does not apply to any
 * modifications of the software.
 *
 *
 * <<Broadcom-WL-IPTag/Dual:>>
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/ip.h>
#include <linux/kfifo.h>

#include <linuxver.h>
#include <osl.h>
#include <bcmutils.h>
#include <bcmendian.h>
#include <bcmdevs.h>
#include <dngl_stats.h>
#include <dhd.h>
#include <dhd_dbg.h>
#include <dhd_linux_wq.h>

/*
 * always make sure that the size of this structure is aligned to
 * the power of 2 (2^n) i.e, if any new variable has to be added then
 * modify the padding accordingly
 */
typedef struct dhd_deferred_event {
	u8 event;		/* holds the event */
	void *event_data;	/* holds event specific data */
	event_handler_t event_handler;
	unsigned long pad;	/* for memory alignment to power of 2 */
} dhd_deferred_event_t;

#define DEFRD_EVT_SIZE	(sizeof(dhd_deferred_event_t))

/*
 * work events may occur simultaneously.
 * can hold upto 64 low priority events and 16 high priority events
 */
#define DHD_PRIO_WORK_FIFO_SIZE	(16 * DEFRD_EVT_SIZE)
#define DHD_WORK_FIFO_SIZE	(64 * DEFRD_EVT_SIZE)

#define DHD_FIFO_HAS_FREE_SPACE(fifo) \
	((fifo) && (kfifo_avail(fifo) >= DEFRD_EVT_SIZE))
#define DHD_FIFO_HAS_ENOUGH_DATA(fifo) \
	((fifo) && (kfifo_len(fifo) >= DEFRD_EVT_SIZE))

struct dhd_deferred_wq {
	struct work_struct deferred_work; /* should be the first member */

	struct kfifo *prio_fifo;
	struct kfifo			*work_fifo;
	u8				*prio_fifo_buf;
	u8				*work_fifo_buf;
	spinlock_t			work_lock;
	void				*dhd_info; /* review: does it require */
	u32				event_skip_mask;
};

static inline struct kfifo*
dhd_kfifo_init(u8 *buf, int size, spinlock_t *lock)
{
	struct kfifo *fifo;
	gfp_t flags = CAN_SLEEP()? GFP_KERNEL : GFP_ATOMIC;

	fifo = (struct kfifo *)kzalloc(sizeof(struct kfifo), flags);
	if (!fifo) {
		return NULL;
	}
	kfifo_init(fifo, buf, size);
	return fifo;
}

static inline void
dhd_kfifo_free(struct kfifo *fifo)
{
	kfifo_free(fifo);
	kfree(fifo);
}

/* deferred work functions */
static void dhd_deferred_work_handler(struct work_struct *data);

void*
dhd_deferred_work_init(void *dhd_info)
{
	struct dhd_deferred_wq	*work = NULL;
	u8*	buf;
	unsigned long	fifo_size = 0;
	gfp_t	flags = CAN_SLEEP()? GFP_KERNEL : GFP_ATOMIC;

	if (!dhd_info) {
		DHD_ERROR(("%s: dhd info not initialized\n", __FUNCTION__));
		goto return_null;
	}

	work = (struct dhd_deferred_wq *)kzalloc(sizeof(struct dhd_deferred_wq),
		flags);
	if (!work) {
		DHD_ERROR(("%s: work queue creation failed\n", __FUNCTION__));
		goto return_null;
	}

	INIT_WORK((struct work_struct *)work, dhd_deferred_work_handler);

	/* initialize event fifo */
	spin_lock_init(&work->work_lock);

	/* allocate buffer to hold prio events */
	fifo_size = DHD_PRIO_WORK_FIFO_SIZE;
	fifo_size = is_power_of_2(fifo_size) ? fifo_size :
			roundup_pow_of_two(fifo_size);
	buf = (u8*)kzalloc(fifo_size, flags);
	if (!buf) {
		DHD_ERROR(("%s: prio work fifo allocation failed\n",
			__FUNCTION__));
		goto return_null;
	}

	/* Initialize prio event fifo */
	work->prio_fifo = dhd_kfifo_init(buf, fifo_size, &work->work_lock);
	if (!work->prio_fifo) {
		kfree(buf);
		goto return_null;
	}

	/* allocate buffer to hold work events */
	fifo_size = DHD_WORK_FIFO_SIZE;
	fifo_size = is_power_of_2(fifo_size) ? fifo_size :
			roundup_pow_of_two(fifo_size);
	buf = (u8*)kzalloc(fifo_size, flags);
	if (!buf) {
		DHD_ERROR(("%s: work fifo allocation failed\n", __FUNCTION__));
		goto return_null;
	}

	/* Initialize event fifo */
	work->work_fifo = dhd_kfifo_init(buf, fifo_size, &work->work_lock);
	if (!work->work_fifo) {
		kfree(buf);
		goto return_null;
	}

	work->dhd_info = dhd_info;
	work->event_skip_mask = 0;
	DHD_PRINT(("%s: work queue initialized\n", __FUNCTION__));
	return work;

return_null:
	if (work) {
		dhd_deferred_work_deinit(work);
	}

	return NULL;
}

void
dhd_deferred_work_deinit(void *work)
{
	struct dhd_deferred_wq *deferred_work = work;


	if (!deferred_work) {
		DHD_ERROR(("%s: deferred work has been freed already\n",
			__FUNCTION__));
		return;
	}

	/* cancel the deferred work handling */
	dhd_cancel_work_sync((struct work_struct *)deferred_work);

	/*
	 * free work event fifo.
	 * kfifo_free frees locally allocated fifo buffer
	 */
	if (deferred_work->prio_fifo) {
		dhd_kfifo_free(deferred_work->prio_fifo);
	}

	if (deferred_work->work_fifo) {
		dhd_kfifo_free(deferred_work->work_fifo);
	}

	kfree(deferred_work);
}

/* select kfifo according to priority */
static inline struct kfifo *
dhd_deferred_work_select_kfifo(struct dhd_deferred_wq *deferred_wq,
	u8 priority)
{
	if (priority == DHD_WQ_WORK_PRIORITY_HIGH) {
		return deferred_wq->prio_fifo;
	} else if (priority == DHD_WQ_WORK_PRIORITY_LOW) {
		return deferred_wq->work_fifo;
	} else {
		return NULL;
	}
}

/*
 *	Prepares event to be queued
 *	Schedules the event
 */
int
dhd_deferred_schedule_work(void *workq, void *event_data, u8 event,
	event_handler_t event_handler, u8 priority)
{
	struct dhd_deferred_wq *deferred_wq = (struct dhd_deferred_wq *)workq;
	struct kfifo *fifo;
	dhd_deferred_event_t deferred_event;
	int bytes_copied = 0;

	if (!deferred_wq) {
		DHD_ERROR(("%s: work queue not initialized\n", __FUNCTION__));
		ASSERT(0);
		return DHD_WQ_STS_UNINITIALIZED;
	}

	if (!event || (event >= DHD_MAX_WQ_EVENTS)) {
		DHD_ERROR(("%s: unknown event, event=%d\n", __FUNCTION__,
			event));
		return DHD_WQ_STS_UNKNOWN_EVENT;
	}

	if (!priority || (priority >= DHD_WQ_MAX_PRIORITY)) {
		DHD_ERROR(("%s: unknown priority, priority=%d\n",
			__FUNCTION__, priority));
		return DHD_WQ_STS_UNKNOWN_PRIORITY;
	}

	if ((deferred_wq->event_skip_mask & (1 << event))) {
		DHD_ERROR(("%s: Skip event requested. Mask = 0x%x\n",
			__FUNCTION__, deferred_wq->event_skip_mask));
		return DHD_WQ_STS_EVENT_SKIPPED;
	}

	/*
	 * default element size is 1, which can be changed
	 * using kfifo_esize(). Older kernel(FC11) doesn't support
	 * changing element size. For compatibility changing
	 * element size is not prefered
	 */
	ASSERT(kfifo_esize(deferred_wq->prio_fifo) == 1);
	ASSERT(kfifo_esize(deferred_wq->work_fifo) == 1);

	deferred_event.event = event;
	deferred_event.event_data = event_data;
	deferred_event.event_handler = event_handler;

	fifo = dhd_deferred_work_select_kfifo(deferred_wq, priority);
	if (DHD_FIFO_HAS_FREE_SPACE(fifo)) {
		bytes_copied = kfifo_in_spinlocked(fifo, &deferred_event,
			DEFRD_EVT_SIZE, &deferred_wq->work_lock);
	}
	if (bytes_copied != DEFRD_EVT_SIZE) {
		DHD_ERROR(("%s: failed to schedule deferred work, "
			"priority=%d, bytes_copied=%d\n", __FUNCTION__,
			priority, bytes_copied));
		return DHD_WQ_STS_SCHED_FAILED;
	}
	schedule_work((struct work_struct *)deferred_wq);
	return DHD_WQ_STS_OK;
}

static bool
dhd_get_scheduled_work(struct dhd_deferred_wq *deferred_wq,
	dhd_deferred_event_t *event)
{
	int bytes_copied = 0;

	if (!deferred_wq) {
		DHD_ERROR(("%s: work queue not initialized\n", __FUNCTION__));
		return DHD_WQ_STS_UNINITIALIZED;
	}

	/*
	 * default element size is 1 byte, which can be changed
	 * using kfifo_esize(). Older kernel(FC11) doesn't support
	 * changing element size. For compatibility changing
	 * element size is not prefered
	 */
	ASSERT(kfifo_esize(deferred_wq->prio_fifo) == 1);
	ASSERT(kfifo_esize(deferred_wq->work_fifo) == 1);

	/* handle priority work */
	if (DHD_FIFO_HAS_ENOUGH_DATA(deferred_wq->prio_fifo)) {
		bytes_copied = kfifo_out_spinlocked(deferred_wq->prio_fifo,
			event, DEFRD_EVT_SIZE, &deferred_wq->work_lock);
	}

	/* handle normal work if priority work doesn't have enough data */
	if ((bytes_copied != DEFRD_EVT_SIZE) &&
		DHD_FIFO_HAS_ENOUGH_DATA(deferred_wq->work_fifo)) {
		bytes_copied = kfifo_out_spinlocked(deferred_wq->work_fifo,
			event, DEFRD_EVT_SIZE, &deferred_wq->work_lock);
	}

	return (bytes_copied == DEFRD_EVT_SIZE);
}

static inline void
dhd_deferred_dump_work_event(dhd_deferred_event_t *work_event)
{
	if (!work_event) {
		DHD_ERROR(("%s: work_event is null\n", __FUNCTION__));
		return;
	}

	DHD_PRINT(("%s: work_event->event = %d\n", __FUNCTION__,
		work_event->event));
	DHD_PRINT(("%s: work_event->event_data = %p\n", __FUNCTION__,
		work_event->event_data));
	DHD_PRINT(("%s: work_event->event_handler = %p\n", __FUNCTION__,
		work_event->event_handler));
}

/*
 *	Called when work is scheduled
 */
static void
dhd_deferred_work_handler(struct work_struct *work)
{
	struct dhd_deferred_wq *deferred_work = (struct dhd_deferred_wq *)work;
	dhd_deferred_event_t work_event;

	if (!deferred_work) {
		DHD_ERROR(("%s: work queue not initialized\n", __FUNCTION__));
		return;
	}

	do {
		if (!dhd_get_scheduled_work(deferred_work, &work_event)) {
			DHD_TRACE(("%s: no event to handle\n", __FUNCTION__));
			break;
		}

		if (work_event.event >= DHD_MAX_WQ_EVENTS) {
			DHD_ERROR(("%s: unknown event\n", __FUNCTION__));
			dhd_deferred_dump_work_event(&work_event);
			ASSERT(work_event.event < DHD_MAX_WQ_EVENTS);
			continue;
		}

		/*
		 * don't do NULL check for 'work_event.event_data'
		 * as for some events like DHD_WQ_WORK_DHD_LOG_DUMP the
		 * event data is always NULL even though rest of the
		 * event parameters are valid
		 */

		if (work_event.event_handler) {
			work_event.event_handler(deferred_work->dhd_info,
				work_event.event_data, work_event.event);
		} else {
			DHD_ERROR(("%s: event handler is null\n",
				__FUNCTION__));
			dhd_deferred_dump_work_event(&work_event);
			ASSERT(work_event.event_handler != NULL);
		}
	} while (1);

	return;
}

void
dhd_deferred_work_set_skip(void *work, u8 event, bool set)
{
	struct dhd_deferred_wq *deferred_wq = (struct dhd_deferred_wq *)work;

	if (!deferred_wq || !event || (event >= DHD_MAX_WQ_EVENTS)) {
		DHD_ERROR(("%s: Invalid!!\n", __FUNCTION__));
		return;
	}

	if (set) {
		/* Set */
		deferred_wq->event_skip_mask |= (1 << event);
	} else {
		/* Clear */
		deferred_wq->event_skip_mask &= ~(1 << event);
	}
}
