/* SPDX-License-Identifier: GPL-2.0 */


#ifndef _LINUX_LIVEUPDATE_H
#define _LINUX_LIVEUPDATE_H

#include <linux/bug.h>
#include <linux/compiler.h>
#include <linux/kho/abi/luo.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include <uapi/linux/liveupdate.h>

struct liveupdate_file_handler;
struct liveupdate_flb;
struct liveupdate_session;
struct file;


struct liveupdate_file_op_args {
	struct liveupdate_file_handler *handler;
	int retrieve_status;
	struct file *file;
	u64 serialized_data;
	void *private_data;
};


struct liveupdate_file_ops {
	bool (*can_preserve)(struct liveupdate_file_handler *handler,
			     struct file *file);
	int (*preserve)(struct liveupdate_file_op_args *args);
	void (*unpreserve)(struct liveupdate_file_op_args *args);
	int (*freeze)(struct liveupdate_file_op_args *args);
	void (*unfreeze)(struct liveupdate_file_op_args *args);
	int (*retrieve)(struct liveupdate_file_op_args *args);
	bool (*can_finish)(struct liveupdate_file_op_args *args);
	void (*finish)(struct liveupdate_file_op_args *args);
	struct module *owner;
};


struct liveupdate_file_handler {
	const struct liveupdate_file_ops *ops;
	const char compatible[LIVEUPDATE_HNDL_COMPAT_LENGTH];

	

	
	struct list_head __private list;
	
	struct list_head __private flb_list;
};


struct liveupdate_flb_op_args {
	struct liveupdate_flb *flb;
	u64 data;
	void *obj;
};


struct liveupdate_flb_ops {
	int (*preserve)(struct liveupdate_flb_op_args *argp);
	void (*unpreserve)(struct liveupdate_flb_op_args *argp);
	int (*retrieve)(struct liveupdate_flb_op_args *argp);
	void (*finish)(struct liveupdate_flb_op_args *argp);
	struct module *owner;
};


struct luo_flb_private_state {
	long count;
	u64 data;
	void *obj;
	struct mutex lock;
	bool finished;
	bool retrieved;
};


struct luo_flb_private {
	struct list_head list;
	struct luo_flb_private_state outgoing;
	struct luo_flb_private_state incoming;
	int users;
	bool initialized;
};


struct liveupdate_flb {
	const struct liveupdate_flb_ops *ops;
	const char compatible[LIVEUPDATE_FLB_COMPAT_LENGTH];

	
	struct luo_flb_private __private private;
};

#ifdef CONFIG_LIVEUPDATE


bool liveupdate_enabled(void);


int liveupdate_reboot(void);

int liveupdate_register_file_handler(struct liveupdate_file_handler *fh);
int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh);

int liveupdate_register_flb(struct liveupdate_file_handler *fh,
			    struct liveupdate_flb *flb);
int liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
			      struct liveupdate_flb *flb);

int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp);
int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp);

#else 

static inline bool liveupdate_enabled(void)
{
	return false;
}

static inline int liveupdate_reboot(void)
{
	return 0;
}

static inline int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
{
	return -EOPNOTSUPP;
}

static inline int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
{
	return -EOPNOTSUPP;
}

static inline int liveupdate_register_flb(struct liveupdate_file_handler *fh,
					  struct liveupdate_flb *flb)
{
	return -EOPNOTSUPP;
}

static inline int liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
					    struct liveupdate_flb *flb)
{
	return -EOPNOTSUPP;
}

static inline int liveupdate_flb_get_incoming(struct liveupdate_flb *flb,
					      void **objp)
{
	return -EOPNOTSUPP;
}

static inline int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb,
					      void **objp)
{
	return -EOPNOTSUPP;
}

#endif 
#endif 
