/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2021 Intel Corporation. All rights rsvd. */

#ifndef __IAA_CRYPTO_H__
#define __IAA_CRYPTO_H__

#include <linux/crypto.h>
#include <linux/idxd.h>
#include <uapi/linux/idxd.h>

#define IDXD_SUBDRIVER_NAME		"crypto"

#define IAA_DECOMP_ENABLE		BIT(0)
#define IAA_DECOMP_FLUSH_OUTPUT		BIT(1)
#define IAA_DECOMP_CHECK_FOR_EOB	BIT(2)
#define IAA_DECOMP_STOP_ON_EOB		BIT(3)
#define IAA_DECOMP_SUPPRESS_OUTPUT	BIT(9)

#define IAA_COMP_FLUSH_OUTPUT		BIT(1)
#define IAA_COMP_APPEND_EOB		BIT(2)

#define IAA_COMPLETION_TIMEOUT		1000000

#define IAA_ANALYTICS_ERROR		0x0a
#define IAA_ERROR_DECOMP_BUF_OVERFLOW	0x0b
#define IAA_ERROR_COMP_BUF_OVERFLOW	0x19
#define IAA_ERROR_WATCHDOG_EXPIRED	0x24

#define IAA_COMP_MODES_MAX		2

#define FIXED_HDR			0x2
#define FIXED_HDR_SIZE			3

#define IAA_COMP_FLAGS			(IAA_COMP_FLUSH_OUTPUT | \
					 IAA_COMP_APPEND_EOB)

#define IAA_DECOMP_FLAGS		(IAA_DECOMP_ENABLE |	   \
					 IAA_DECOMP_FLUSH_OUTPUT | \
					 IAA_DECOMP_CHECK_FOR_EOB | \
					 IAA_DECOMP_STOP_ON_EOB)

/* Representation of IAA workqueue */
struct iaa_wq {
	struct list_head	list;

	struct idxd_wq		*wq;
	int			ref;
	bool			remove;

	struct iaa_device	*iaa_device;

	atomic64_t		comp_calls;
	atomic64_t		comp_bytes;
	atomic64_t		decomp_calls;
	atomic64_t		decomp_bytes;
};

struct iaa_device_compression_mode {
	const char			*name;

	struct aecs_comp_table_record	*aecs_comp_table;

	dma_addr_t			aecs_comp_table_dma_addr;
};

/* Representation of IAA device with wqs, populated by probe */
struct iaa_device {
	struct list_head		list;
	struct idxd_device		*idxd;

	struct iaa_device_compression_mode	*compression_modes[IAA_COMP_MODES_MAX];

	int				n_wq;
	struct list_head		wqs;

	atomic64_t			comp_calls;
	atomic64_t			comp_bytes;
	atomic64_t			decomp_calls;
	atomic64_t			decomp_bytes;
};

struct wq_table_entry {
	struct idxd_wq **wqs;
	int	max_wqs;
	int	n_wqs;
	int	cur_wq;
};

#define IAA_AECS_ALIGN			32

/*
 * Analytics Engine Configuration and State (AECS) contains parameters and
 * internal state of the analytics engine.
 */
struct aecs_comp_table_record {
	u32 crc;
	u32 xor_checksum;
	u32 reserved0[5];
	u32 num_output_accum_bits;
	u8 output_accum[256];
	u32 ll_sym[286];
	u32 reserved1;
	u32 reserved2;
	u32 d_sym[30];
	u32 reserved_padding[2];
} __packed;

int iaa_aecs_init_fixed(void);
void iaa_aecs_cleanup_fixed(void);

typedef int (*iaa_dev_comp_init_fn_t) (struct iaa_device_compression_mode *mode);
typedef int (*iaa_dev_comp_free_fn_t) (struct iaa_device_compression_mode *mode);

struct iaa_compression_mode {
	const char		*name;
	u32			*ll_table;
	int			ll_table_size;
	u32			*d_table;
	int			d_table_size;
	iaa_dev_comp_init_fn_t	init;
	iaa_dev_comp_free_fn_t	free;
};

int add_iaa_compression_mode(const char *name,
			     const u32 *ll_table,
			     int ll_table_size,
			     const u32 *d_table,
			     int d_table_size,
			     iaa_dev_comp_init_fn_t init,
			     iaa_dev_comp_free_fn_t free);

void remove_iaa_compression_mode(const char *name);

enum iaa_mode {
	IAA_MODE_FIXED,
};

struct iaa_compression_ctx {
	enum iaa_mode	mode;
	bool		verify_compress;
	bool		async_mode;
	bool		use_irq;
};

extern struct list_head iaa_devices;
extern struct mutex iaa_devices_lock;

#endif
