// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/*
 * Copyright (c) 2020 MediaTek Inc.
 */

#include <linux/kernel.h>

#include "mdrv_demux_debug.h"
#include "mdrv_demux_fh.h"
#include "mdrv_demux_event.h"

int mdrv_demux_fh_init(struct dmx_fh *fh, struct dmx_fh_mgr *mgr)
{
	if (!mgr) {
		DEMUX_DEBUG_ERR("[%s][%d] mgr is NULL\n", __func__, __LINE__);
		return -EINVAL;
	}

	fh->mgr = mgr;
	INIT_LIST_HEAD(&fh->list);
	init_waitqueue_head(&fh->wait);
	INIT_LIST_HEAD(&fh->available);
	INIT_LIST_HEAD(&fh->subscribed);
	fh->navailable = 0;
	fh->sequence = -1;
	mutex_init(&fh->subscribe_lock);

	return 0;
}

void mdrv_demux_fh_add(struct dmx_fh *fh)
{
	spin_lock(&fh->mgr->fh_lock);
	list_add(&fh->list, &fh->mgr->fh_list);
	spin_unlock(&fh->mgr->fh_lock);
}

void mdrv_demux_fh_del(struct dmx_fh *fh)
{
	spin_lock(&fh->mgr->fh_lock);
	list_del_init(&fh->list);
	spin_unlock(&fh->mgr->fh_lock);
}

int mdrv_demux_fh_exit(struct dmx_fh *fh)
{
	int ret;

	if (fh->mgr == NULL) {
		DEMUX_DEBUG_ERR("[%s][%d] fh->mgr is NULL\n", __func__, __LINE__);
		return -EFAULT;
	}

	ret = mdrv_demux_event_unsubscribe_all(fh);
	if (ret < 0) {
		DEMUX_DEBUG_ERR("[%s][%d] unscuscribe events fail !\n", __func__, __LINE__);
		return -EFAULT;
	}

	mutex_destroy(&fh->subscribe_lock);
	fh->mgr = NULL;
	return 0;
}
