root/drivers/net/wwan/t7xx/t7xx_hif_dpmaif.h
/* 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/netdevice.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;

        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 napi_struct      napi;
        bool                    sleep_lock_pending;
};

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_ccmni_ctrl *ccmni_ctlb, struct sk_buff *skb,
                         struct napi_struct *napi);
};

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__ */