1843200
  B   	ˆl–Ü4ý( ©³( 	Å€fàB¦-ÿ¿„�‰ÿ_†I|¥�+a–ßi~”*j"Tâ€ÆÁq–”Å£Ä ?÷     	/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/* QLogic qed NIC Driver
 * Copyright (c) 2015-2017  QLogic Corporation
 * Copyright (c) 2019-2020 Marvell International Ltd.
 */

#ifndef _QED_CHAIN_H
#define _QED_CHAIN_H

#include <linux/types.h>
#include <asm/byteorder.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/qed/common_hsi.h>

enum qed_chain_mode {
	/* Each Page contains a next pointer at its end */
	QED_CHAIN_MODE_NEXT_PTR,

	/* Chain is a single page (next ptr) is not required */
	QED_CHAIN_MODE_SINGLE,

	/* Page pointers are located in a side list */
	QED_CHAIN_MODE_PBL,
};

enum qed_chain_use_mode {
	QED_CHAIN_USE_TO_PRODUCE,			/* Chain starts empty */
	QED_CHAIN_USE_TO_CONSUME,			/* Chain starts full */
	QED_CHAIN_USE_TO_CONSUME_PRODUCE,		/* Chain starts empty */
};

enum qed_chain_cnt_type {
	/* The chain's size/prod/cons are kept in 16-bit variables */
	QED_CHAIN_CNT_TYPE_U16,

	/* The chain's size/prod/cons are kept in 32-bit variables  */
	QED_CHAIN_CNT_TYPE_U32,
};

struct qed_chain_next {
	struct regpair					next_phys;
	void						*next_virt;
};

struct qed_chain_pbl_u16 {
	u16						prod_page_idx;
	u16						cons_page_idx;
};

struct qed_chain_pbl_u32 {
	u32						prod_page_idx;
	u32						cons_page_idx;
};

struct qed_chain_u16 {
	/* Cyclic index of next element to produce/consume */
	u16						prod_idx;
	u16						cons_idx;
};

struct qed_chain_u32 {
	/* Cyclic index of next element to produce/consume */
	u32						prod_idx;
	u32						cons_idx;
};

struct addr_tbl_entry {
	void						*virt_addr;
	dma_addr_t					dma_map;
};

struct qed_chain {
	/* Fastpath portion of the chain - required for commands such
	 * as produce / consume.
	 */

	/* Point to next element to produce/consume */
	void						*p_prod_elem;
	void						*p_cons_elem;

	/* Fastpath portions of the PBL [if exists] */

	struct {
		/* Table for keeping the virtual and physical addresses of the
		 * chain pages, respectively to the physical addresses
		 * in the pbl table.
		 */
		struct addr_tbl_entry			*pp_addr_tbl;

		union {
			struct qed_chain_pbl_u16	u16;
			struct qed_chain_pbl_u32	u32;
		}					c;
	}						pbl;

	union {
		struct qed_chain_u16			chain16;
		struct qed_chain_u32			chain32;
	}						u;

	/* Capacity counts only usable elements */
	u32						capacity;
	u32						page_cnt;

	enum qed_chain_mode				mode;

	/* Elements information for fast calculations */
	u16						elem_per_page;
	u16						elem_per_page_mask;
	u16						elem_size;
	u16						next_page_mask;
	u16						usable_per_page;
	u8						elem_unusable;

	enum qed_chain_cnt_type				cnt_type;

	/* Slowpath of the chain - required for initialization and destruction,
	 * but isn't involved in regular functionality.
	 */

	u32						page_size;

	/* Base address of a pre-allocated buffer for pbl */
	struct {
		__le64					*table_virt;
		dma_addr_t				table_phys;
		size_t					table_size;
	}						pbl_sp;

	/* Address of first page of the chain - the address is required
	 * for fastpath operation [consume/produce] but only for the SINGLE
	 * flavour which isn't considered fastpath [== SPQ].
	 */
	void						*p_virt_addr;
	dma_addr_t					p_phys_addr;

	/* Total number of elements [for entire chain] */
	u32						size;

	enum qed_chain_use_mode				intended_use;

	bool						b_external_pbl;
};

struct qed_chain_init_params {
	enum qed_chain_mode				mode;
	enum qed_chain_use_mode				intended_use;
	enum qed_chain_cnt_type				cnt_type;

	u32						page_size;
	u32						num_elems;
	size_t						elem_size;

	void						*ext_pbl_virt;
	dma_addr_t					ext_pbl_phys;
};

#define QED_CHAIN_PAGE_SIZE				SZ_4K

#define ELEMS_PER_PAGE(elem_size, page_size)				     \
	((page_size) / (elem_size))

#define UNUSABLE_ELEMS_PER_PAGE(elem_size, mode)			     \
	(((mode) == QED_CHAIN_MODE_NEXT_PTR) ?				     \
	 (u8)(1 + ((sizeof(struct qed_chain_next) - 1) / (elem_size))) :     \
	 0)

#define USABLE_ELEMS_PER_PAGE(elem_size, page_size, mode)		     \