/* SPDX-License-Identifier: GPL-2.0-only
 *
 * Copyright (c) 2021, MediaTek Inc.
 * Copyright (c) 2021-2022, Intel Corporation.
 *
 * Authors:
 *  Amir Hanania <amir.hanania@intel.com>
 *  Haijun Liu <haijun.liu@mediatek.com>
 *  Moises Veleta <moises.veleta@intel.com>
 *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
 *
 * Contributors:
 *  Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
 *  Eliot Lee <eliot.lee@intel.com>
 *  Sreehari Kancharla <sreehari.kancharla@intel.com>
 */

#ifndef __T7XX_HIF_DPMAIF_H__
#define __T7XX_HIF_DPMAIF_H__

#include <linux/bitmap.h>
#include <linux/mm_types.h>
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/workqueue.h>

#include "t7xx_dpmaif.h"
#include "t7xx_pci.h"
#include "t7xx_state_monitor.h"

/* SKB control buffer */
struct t7xx_skb_cb {
	u8	netif_idx;
	u8	txq_number;
	u8	rx_pkt_type;
};

#define T7XX_SKB_CB(__skb)	((struct t7xx_skb_cb *)(__skb)->cb)

enum dpmaif_rdwr {
	DPMAIF_READ,
	DPMAIF_WRITE,
};

/* Structure of DL BAT */
struct dpmaif_cur_rx_skb_info {
	bool			msg_pit_received;
	struct sk_buff		*cur_skb;
	unsigned int		cur_chn_idx;
	unsigned int		check_sum;
	unsigned int		pit_dp;
	unsigned int		pkt_type;
	int			err_payload;
};

struct dpmaif_bat {
	unsigned int		p_buffer_addr;
	unsigned int		buffer_addr_ext;
};

struct dpmaif_bat_skb {
	struct sk_buff		*skb;
	dma_addr_t		data_bus_addr;
	unsigned int		data_len;
};

struct dpmaif_bat_page {
	struct page		*page;
	dma_addr_t		data_bus_addr;
	unsigned int		offset;
	unsigned int		data_len;
};

enum bat_type {
	BAT_TYPE_NORMAL,
	BAT_TYPE_FRAG,
};

struct dpmaif_bat_request {
	void			*bat_base;
	dma_addr_t		bat_bus_addr;
	unsigned int		bat_size_cnt;
	unsigned int		bat_wr_idx;
	unsigned int		bat_release_rd_idx;
	void			*bat_skb;
	unsigned int		pkt_buf_sz;
	unsigned long		*bat_bitmap;
	atomic_t		refcnt;
	spinlock_t		mask_lock; /* Protects BAT mask */
	enum bat_type		type;
};

struct dpmaif_rx_queue {
	unsigned int		index;
	bool			que_started;
	unsigned int		budget;

	void			*pit_base;
	dma_addr_t		pit_bus_addr;
	unsigned int		pit_size_cnt;

	unsigned int		pit_rd_idx;
	unsigned int		pit_wr_idx;
	unsigned int		pit_release_rd_idx;

	struct dpmaif_bat_request *bat_req;
	struct dpmaif_bat_request *bat_frag;

	wait_queue_head_t	rx_wq;
	struct task_struct	*rx_thread;
	struct sk_buff_head	skb_list;
	unsigned int		skb_list_max_len;

	struct workqueue_struct	*worker;
	struct work_struct	dpmaif_rxq_work;

	atomic_t		rx_processing;

	struct dpmaif_ctrl	*dpmaif_ctrl;
	unsigned int		expect_pit_seq;
	unsigned int		pit_remain_release_cnt;
	struct dpmaif_cur_rx_skb_info rx_data_info;
};

struct dpmaif_tx_queue {
	unsigned int		index;
	bool			que_started;
	atomic_t		tx_budget;
	void			*drb_base;
	dma_addr_t		drb_bus_addr;
	unsigned int		drb_size_cnt;
	unsigned int		drb_wr_idx;
	unsigned int		drb_rd_idx;
	unsigned int		drb_release_rd_idx;
	void			*drb_skb_base;
	wait_queue_head_t	req_wq;
	struct workqueue_struct	*worker;
	struct work_struct	dpmaif_tx_work;
	spinlock_t		tx_lock; /* Protects txq DRB */
	atomic_t		tx_processing;

	struct dpmaif_ctrl	*dpmaif_ctrl;
	struct sk_buff_head	tx_skb_head;
};

struct dpmaif_isr_para {
	struct dpmaif_ctrl	*dpmaif_ctrl;
	unsigned char		pcie_int;
	unsigned char		dlq_id;
};

enum dpmaif_state {
	DPMAIF_STATE_MIN,
	DPMAIF_STATE_PWROFF,
	DPMAIF_STATE_PWRON,
	DPMAIF_STATE_EXCEPTION,
	DPMAIF_STATE_MAX
};

enum dpmaif_txq_state {
	DMPAIF_TXQ_STATE_IRQ,
	DMPAIF_TXQ_STATE_FULL,
};

struct dpmaif_callbacks {
	void (*state_notify)(struct t7xx_pci_dev *t7xx_dev,
			     enum dpmaif_txq_state state, int txq_number);
	void (*recv_skb)(struct t7xx_pci_dev *t7xx_dev, struct sk_buff *skb);
};

struct dpmaif_ctrl {
	struct device			*dev;
	struct t7xx_pci_dev		*t7xx_dev;
	struct md_pm_entity		dpmaif_pm_entity;
	enum dpmaif_state		state;
	bool				dpmaif_sw_init_done;
	struct dpmaif_hw_info		hw_info;
	struct dpmaif_tx_queue		txq[DPMAIF_TXQ_NUM];
	struct dpmaif_rx_queue		rxq[DPMAIF_RXQ_NUM];

	unsigned char			rxq_int_mapping[DPMAIF_RXQ_NUM];
	struct dpmaif_isr_para		isr_para[DPMAIF_RXQ_NUM];

	struct dpmaif_bat_request	bat_req;
	struct dpmaif_bat_request	bat_frag;
	struct workqueue_struct		*bat_release_wq;
	struct work_struct		bat_release_work;

	wait_queue_head_t		tx_wq;
	struct task_struct		*tx_thread;

	struct dpmaif_callbacks		*callbacks;
};

struct dpmaif_ctrl *t7xx_dpmaif_hif_init(struct t7xx_pci_dev *t7xx_dev,
					 struct dpmaif_callbacks *callbacks);
void t7xx_dpmaif_hif_exit(struct dpmaif_ctrl *dpmaif_ctrl);
int t7xx_dpmaif_md_state_callback(struct dpmaif_ctrl *dpmaif_ctrl, enum md_state state);
unsigned int t7xx_ring_buf_get_next_wr_idx(unsigned int buf_len, unsigned int buf_idx);
unsigned int t7xx_ring_buf_rd_wr_count(unsigned int total_cnt, unsigned int rd_idx,
				       unsigned int wr_idx, enum dpmaif_rdwr);

#endif /* __T7XX_HIF_DPMAIF_H__ */
