summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/netronome/nfp/nfdk/nfdk.h
blob: fe55980348e9697d9b6ae9d6707f950d6c7a05fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/* Copyright (C) 2019 Netronome Systems, Inc. */

#ifndef _NFP_DP_NFDK_H_
#define _NFP_DP_NFDK_H_

#include <linux/bitops.h>
#include <linux/types.h>

#define NFDK_TX_DESC_PER_SIMPLE_PKT	2

#define NFDK_TX_MAX_DATA_PER_HEAD	SZ_4K
#define NFDK_TX_MAX_DATA_PER_DESC	SZ_16K
#define NFDK_TX_DESC_BLOCK_SZ		256
#define NFDK_TX_DESC_BLOCK_CNT		(NFDK_TX_DESC_BLOCK_SZ /	\
					 sizeof(struct nfp_nfdk_tx_desc))
#define NFDK_TX_DESC_STOP_CNT		(NFDK_TX_DESC_BLOCK_CNT *	\
					 NFDK_TX_DESC_PER_SIMPLE_PKT)
#define NFDK_TX_MAX_DATA_PER_BLOCK	SZ_64K
#define NFDK_TX_DESC_GATHER_MAX		17

/* TX descriptor format */

#define NFDK_DESC_TX_MSS_MASK		GENMASK(13, 0)

#define NFDK_DESC_TX_CHAIN_META		BIT(3)
#define NFDK_DESC_TX_ENCAP		BIT(2)
#define NFDK_DESC_TX_L4_CSUM		BIT(1)
#define NFDK_DESC_TX_L3_CSUM		BIT(0)

#define NFDK_DESC_TX_DMA_LEN_HEAD	GENMASK(11, 0)
#define NFDK_DESC_TX_TYPE_HEAD		GENMASK(15, 12)
#define NFDK_DESC_TX_DMA_LEN		GENMASK(13, 0)
#define NFDK_DESC_TX_TYPE_NOP		0
#define NFDK_DESC_TX_TYPE_GATHER	1
#define NFDK_DESC_TX_TYPE_TSO		2
#define NFDK_DESC_TX_TYPE_SIMPLE	8
#define NFDK_DESC_TX_EOP		BIT(14)

#define NFDK_META_LEN			GENMASK(7, 0)
#define NFDK_META_FIELDS		GENMASK(31, 8)

#define D_BLOCK_CPL(idx)		(NFDK_TX_DESC_BLOCK_CNT -	\
					 (idx) % NFDK_TX_DESC_BLOCK_CNT)

struct nfp_nfdk_tx_desc {
	union {
		struct {
			__le16 dma_addr_hi;  /* High bits of host buf address */
			__le16 dma_len_type; /* Length to DMA for this desc */
			__le32 dma_addr_lo;  /* Low 32bit of host buf addr */
		};

		struct {
			__le16 mss;	/* MSS to be used for LSO */
			u8 lso_hdrlen;  /* LSO, TCP payload offset */
			u8 lso_totsegs; /* LSO, total segments */
			u8 l3_offset;   /* L3 header offset */
			u8 l4_offset;   /* L4 header offset */
			__le16 lso_meta_res; /* Rsvd bits in TSO metadata */
		};

		struct {
			u8 flags;	/* TX Flags, see @NFDK_DESC_TX_* */
			u8 reserved[7];	/* meta byte placeholder */
		};

		__le32 vals[2];
		__le64 raw;
	};
};

/* The device don't make use of the 2 or 3 least significant bits of the address
 * due to alignment constraints. The driver can make use of those bits to carry
 * information about the buffer before giving it to the device.
 *
 * NOTE: The driver must clear the lower bits before handing the buffer to the
 * device.
 *
 * - NFDK_TX_BUF_INFO_SOP - Start of a packet
 *   Mark the buffer as a start of a packet. This is used in the XDP TX process
 *   to stash virtual and DMA address so that they can be recycled when the TX
 *   operation is completed.
 */
#define NFDK_TX_BUF_PTR(val) ((val) & ~(sizeof(void *) - 1))
#define NFDK_TX_BUF_INFO(val) ((val) & (sizeof(void *) - 1))
#define NFDK_TX_BUF_INFO_SOP BIT(0)

struct nfp_nfdk_tx_buf {
	union {
		/* First slot */
		union {
			struct sk_buff *skb;
			void *frag;
			unsigned long val;
		};

		/* 1 + nr_frags next slots */
		dma_addr_t dma_addr;

		/* TSO (optional) */
		struct {
			u32 pkt_cnt;
			u32 real_len;
		};

		u64 raw;
	};
};

static inline int nfp_nfdk_headlen_to_segs(unsigned int headlen)
{
	/* First descriptor fits less data, so adjust for that */
	return DIV_ROUND_UP(headlen +
			    NFDK_TX_MAX_DATA_PER_DESC -
			    NFDK_TX_MAX_DATA_PER_HEAD,
			    NFDK_TX_MAX_DATA_PER_DESC);
}

int nfp_nfdk_poll(struct napi_struct *napi, int budget);
netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev);
bool
nfp_nfdk_ctrl_tx_one(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
		     struct sk_buff *skb, bool old);
void nfp_nfdk_ctrl_poll(struct tasklet_struct *t);
void nfp_nfdk_rx_ring_fill_freelist(struct nfp_net_dp *dp,
				    struct nfp_net_rx_ring *rx_ring);
#ifndef CONFIG_NFP_NET_IPSEC
static inline u64 nfp_nfdk_ipsec_tx(u64 flags, struct sk_buff *skb)
{
	return flags;
}
#else
u64 nfp_nfdk_ipsec_tx(u64 flags, struct sk_buff *skb);
#endif
#endif