kernel_samsung_a53x/drivers/soc/samsung/cpif/dit/dit_common.h
2024-06-15 16:02:09 -03:00

343 lines
9 KiB
C
Executable file

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* EXYNOS DIT(Direct IP Translator) Driver support
*
*/
#ifndef __DIT_COMMON_H__
#define __DIT_COMMON_H__
#ifndef DIT_DEBUG
#define DIT_DEBUG
#endif
#ifdef DIT_DEBUG
#define DIT_DEBUG_LOW
#endif
#include "dit.h"
#include "cpif_page.h"
#define DIT_VERSION(x, y, z) \
((((x) & 0xFF) << 24) | (((y) & 0xFF) << 16) | (((z) & 0xFF) << 8))
#if defined(CONFIG_EXYNOS_DIT_VERSION) && (DIT_VERSION(2, 2, 0) == CONFIG_EXYNOS_DIT_VERSION)
#include "dit_2_2_0.h"
#else
#include "dit_2_1_0.h"
#endif
#define DIT_REG_SW_COMMAND 0x0000
/* total: DIT_REG_CLAT_ADDR_MAX, interval: DIT_REG_CLAT_TX_FILTER_INTERVAL */
#define DIT_REG_CLAT_TX_FILTER 0x2000
/* total: DIT_REG_CLAT_ADDR_MAX, interval: DIT_REG_CLAT_TX_PLAT_PREFIX_INTERVAL */
#define DIT_REG_CLAT_TX_PLAT_PREFIX_0 0x2020
#define DIT_REG_CLAT_TX_PLAT_PREFIX_1 0x2024
#define DIT_REG_CLAT_TX_PLAT_PREFIX_2 0x2028
/* total: DIT_REG_CLAT_ADDR_MAX, interval: DIT_REG_CLAT_TX_CLAT_SRC_INTERVAL */
#define DIT_REG_CLAT_TX_CLAT_SRC_0 0x2080
#define DIT_REG_CLAT_TX_CLAT_SRC_1 0x2084
#define DIT_REG_CLAT_TX_CLAT_SRC_2 0x2088
#define DIT_REG_CLAT_TX_CLAT_SRC_3 0x208C
/* total: DIT_REG_NAT_LOCAL_ADDR_MAX, interval: DIT_REG_NAT_LOCAL_INTERVAL */
#define DIT_REG_NAT_LOCAL_ADDR 0x4100
#define DIT_REG_NAT_ZERO_CHK_OFF 0x4144
#define DIT_REG_NAT_ETHERNET_EN 0x414C
/* total: DIT_REG_NAT_LOCAL_ADDR_MAX, interval: DIT_REG_ETHERNET_MAC_INTERVAL */
#define DIT_REG_NAT_ETHERNET_DST_MAC_ADDR_0 0x6000 /* 32 bit */
#define DIT_REG_NAT_ETHERNET_DST_MAC_ADDR_1 0x6004 /* 16 bit */
#define DIT_REG_NAT_ETHERNET_SRC_MAC_ADDR_0 0x6008 /* 32 bit */
#define DIT_REG_NAT_ETHERNET_SRC_MAC_ADDR_1 0x600C /* 16 bit */
#define DIT_REG_NAT_ETHERNET_TYPE 0x6010 /* 16 bit */
#define DIT_REG_NAT_TX_PORT_INIT_START 0x6210
#define DIT_REG_NAT_TX_PORT_INIT_DONE 0x6214
#define DIT_REG_NAT_RX_PORT_INIT_START 0x6228
#define DIT_REG_NAT_RX_PORT_INIT_DONE 0x622C
/* total: DIT_REG_NAT_LOCAL_PORT_MAX, interval: DIT_REG_NAT_LOCAL_INTERVAL */
#define DIT_REG_NAT_RX_PORT_TABLE_SLOT 0xC000
/* total numbers and intervals */
#define DIT_REG_NAT_LOCAL_ADDR_MAX (16)
#define DIT_REG_NAT_LOCAL_PORT_MAX (2048)
#define DIT_REG_NAT_LOCAL_INTERVAL (4)
#define DIT_REG_ETHERNET_MAC_INTERVAL (0x20)
#define DIT_REG_CLAT_ADDR_MAX (8)
#define DIT_REG_CLAT_TX_FILTER_INTERVAL (4)
#define DIT_REG_CLAT_TX_PLAT_PREFIX_INTERVAL (12)
#define DIT_REG_CLAT_TX_CLAT_SRC_INTERVAL (16)
/* macro for DIT register operation */
#define WRITE_REG_PADDR_LO(dc, paddr, offset) \
writel(PADDR_LO(paddr), dc->register_base + offset)
#define WRITE_REG_PADDR_HI(dc, paddr, offset) \
writel(PADDR_HI(paddr), dc->register_base + offset)
#define WRITE_REG_VALUE(dc, value, offset) \
writel(value, dc->register_base + offset)
#define READ_REG_VALUE(dc, offset) \
readl(dc->register_base + offset)
#define WRITE_SHR_VALUE(dc, value) \
({ \
if (!IS_ERR_OR_NULL(dc->sharability_base)) \
writel(value, dc->sharability_base + dc->sharability_offset); \
})
#define BACKUP_REG_VALUE(dc, dst, offset, size) \
memcpy_fromio(dst, dc->register_base + offset, size)
#define RESTORE_REG_VALUE(dc, src, offset, size) \
memcpy_toio(dc->register_base + offset, src, size)
/* macro for DIT function pointer */
#define DIT_INDIRECT_CALL(dc, f, ...) \
({ \
dc->f ? dc->f(__VA_ARGS__) : -EOPNOTSUPP; \
})
#define DIT_RX_BURST_16BEAT (0)
enum dit_desc_ring {
DIT_DST_DESC_RING_0,
DIT_DST_DESC_RING_1,
DIT_DST_DESC_RING_2,
DIT_DST_DESC_RING_MAX,
DIT_SRC_DESC_RING = DIT_DST_DESC_RING_MAX,
DIT_DESC_RING_MAX
};
enum dit_desc_control_bits {
DIT_DESC_C_RESERVED, /* Reserved */
DIT_DESC_C_END, /* end packet of LRO */
DIT_DESC_C_START, /* first packet of LRO */
DIT_DESC_C_RINGEND, /* End of descriptor */
DIT_DESC_C_INT, /* Interrupt enabled */
DIT_DESC_C_CSUM, /* csum enabled */
DIT_DESC_C_TAIL, /* last buffer */
DIT_DESC_C_HEAD /* first buffer */
};
#define DIT_SRC_KICK_CONTROL_MASK \
(BIT(DIT_DESC_C_HEAD) | BIT(DIT_DESC_C_TAIL) | \
BIT(DIT_DESC_C_INT) | BIT(DIT_DESC_C_RINGEND))
enum dit_desc_status_bits {
DIT_DESC_S_DONE, /* DMA done */
DIT_DESC_S_RESERVED, /* Reserved */
DIT_DESC_S_TCPCF, /* Failed TCP csum */
DIT_DESC_S_IPCSF, /* Failed IP csum */
DIT_DESC_S_IGNR, /* Ignore csum */
DIT_DESC_S_TCPC, /* TCP/UDP csum done: should be 0 if IGNR */
DIT_DESC_S_IPCS, /* IP header csum done: should be 0 if IGNR */
DIT_DESC_S_PFD /* passed packet filter */
};
#define DIT_CHECKSUM_FAILED_STATUS_MASK \
(BIT(DIT_DESC_S_TCPCF) | BIT(DIT_DESC_S_IPCSF) | BIT(DIT_DESC_S_IGNR))
enum dit_sw_command_bits {
DMA_INIT_COMMAND_BIT,
TX_COMMAND_BIT,
RX_COMMAND_BIT,
};
enum dit_nat_ethernet_en_bits {
TX_ETHERNET_EN_BIT,
RX_ETHERNET_EN_BIT,
};
#define DIT_ALL_INT_PENDING_MASK \
(DIT_TX_INT_PENDING_MASK | DIT_RX_INT_PENDING_MASK)
/* DIT_STATUS
* zero means idle
*/
enum dit_status_mask {
TX_STATUS_MASK = 0x0F,
RX_STATUS_MASK = 0xF0,
};
enum dit_packet_info_bits {
DIT_PACKET_INFO_UDP_BIT = 6,
DIT_PACKET_INFO_TCP_BIT,
DIT_PACKET_INFO_IPV6_BIT = 10,
DIT_PACKET_INFO_IPV4_BIT,
};
struct dit_dst_desc {
u64 dst_addr:36,
packet_info:12,
/* the below 16 bits are "private info" on the document */
ch_id:8,
pre_csum:1,
udp_csum_zero:1,
_reserved_2:6;
u64 length:16,
org_port:16,
trans_port:16,
control:8,
status:8;
} __packed;
struct dit_desc_info {
unsigned int src_wp;
unsigned int src_rp;
unsigned int dst_wp[DIT_DST_DESC_RING_MAX];
unsigned int dst_rp[DIT_DST_DESC_RING_MAX];
unsigned int src_desc_ring_len;
struct dit_src_desc *src_desc_ring;
struct sk_buff **src_skb_buf;
u32 buf_size;
phys_addr_t pktproc_pbase;
u32 pktproc_queue_num;
u32 pktproc_desc_len;
u32 *pktproc_fore_ptr;
unsigned int dst_desc_ring_len;
struct dit_dst_desc *dst_desc_ring[DIT_DST_DESC_RING_MAX];
struct sk_buff **dst_skb_buf[DIT_DST_DESC_RING_MAX];
bool dst_skb_buf_filled[DIT_DST_DESC_RING_MAX];
/* use_dma_map */
dma_addr_t src_desc_ring_daddr;
dma_addr_t dst_desc_ring_daddr[DIT_DST_DESC_RING_MAX];
dma_addr_t *dst_skb_buf_daddr[DIT_DST_DESC_RING_MAX];
/* page pool */
struct cpif_page_pool *dst_page_pool[DIT_DST_DESC_RING_MAX];
};
struct dit_ctrl_t {
spinlock_t rx_buf_lock;
struct device *dev;
struct link_device *ld;
struct net_device *netdev;
struct napi_struct napi;
int *irq_pending_bit;
char const **irq_name;
int *irq_buf;
int irq_len;
int irq_affinity;
int irq_num_tx;
int irq_affinity_tx;
int idle_ip_index;
void __iomem *register_base;
void __iomem *sharability_base;
u32 sharability_offset;
u32 sharability_value;
bool use_dma_map;
u32 hw_version;
u32 reg_version;
u32 hw_capabilities;
bool use_dir[DIT_DIR_MAX];
bool stop_enqueue[DIT_DIR_MAX];
bool use_clat;
bool hal_support;
bool hal_enqueue_rx;
u32 rx_extra_desc_ring_len;
struct dit_desc_info desc_info[DIT_DIR_MAX];
/* for kicked flag, reg_value_q and init_done */
spinlock_t src_lock;
bool kicked[DIT_DIR_MAX];
bool kick_reserved[DIT_DIR_MAX];
struct list_head reg_value_q;
bool init_done;
bool init_reserved;
atomic_t init_running;
atomic_t stop_napi_poll;
bool use_page_recycling_rx;
u32 page_recycling_skb_padding;
#if defined(DIT_DEBUG_LOW)
int pktgen_ch;
int force_bypass;
#endif
/* every functions should return int for DIT_INDIRECT_CALL */
int (*get_reg_version)(u32 *version);
int (*set_reg_upstream)(struct net_device *netdev);
int (*set_desc_filter_bypass)(enum dit_direction dir, struct dit_src_desc *src_desc,
u8 *src, bool *is_upstream_pkt);
int (*set_src_desc_tail)(enum dit_direction dir, struct dit_desc_info *desc_info,
unsigned int tail);
int (*do_init_hw)(void);
int (*do_init_desc)(enum dit_direction dir);
};
struct dit_snapshot_t {
char *name;
int head;
int tail;
u64 packets;
/* cumulative amount */
u64 total_packets;
u64 clat_packets;
u32 max_usage;
u32 alloc_skbs;
u32 dma_maps;
};
struct dit_reg_value_item {
struct list_head list;
u32 value;
u32 offset;
};
struct dit_iface {
u8 upstream_ch;
};
enum dit_dump_bits {
DIT_DUMP_SNAPSHOT_BIT,
DIT_DUMP_DESC_BIT,
DIT_DUMP_PORT_TABLE_BIT,
DIT_DUMP_MAX,
};
#define DIT_DUMP_ALL \
(BIT(DIT_DUMP_SNAPSHOT_BIT) | BIT(DIT_DUMP_DESC_BIT) | \
BIT(DIT_DUMP_PORT_TABLE_BIT))
enum dit_idle_ip {
DIT_IDLE_IP_ACTIVE = 0,
DIT_IDLE_IP_IDLE,
};
/*
* if there is 1 src desc and it is at the ring_end,
* DIT will reads 3 descs from the ring_end.
* for the safety, add additional 2 descs.
*/
#define DIT_SRC_DESC_RING_LEN_PADDING (2)
/* prevent zero size alloc */
#define DIT_DST_DESC_RING_LEN_PADDING (1)
bool dit_is_kicked_any(void);
int dit_check_dst_ready(enum dit_direction dir, enum dit_desc_ring ring_num);
int dit_enqueue_reg_value_with_ext_lock(u32 value, u32 offset);
int dit_enqueue_reg_value(u32 value, u32 offset);
int dit_read_rx_dst_poll(struct napi_struct *napi, int budget);
int dit_manage_rx_dst_data_buffers(bool fill);
bool dit_is_busy(enum dit_direction dir);
int dit_stop_napi_poll(void);
int dit_ver_create(struct dit_ctrl_t *dc_ptr);
#endif /* __DIT_COMMON_H__ */