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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
|
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (c) Tehuti Networks Ltd. */
#ifndef _TN40_H_
#define _TN40_H_
#include "tn40_regs.h"
#define TN40_DRV_NAME "tn40xx"
#define TN40_MDIO_SPEED_1MHZ (1)
#define TN40_MDIO_SPEED_6MHZ (6)
/* netdev tx queue len for Luxor. The default value is 1000.
* ifconfig eth1 txqueuelen 3000 - to change it at runtime.
*/
#define TN40_NDEV_TXQ_LEN 1000
#define TN40_FIFO_SIZE 4096
#define TN40_FIFO_EXTRA_SPACE 1024
#define TN40_TXF_DESC_SZ 16
#define TN40_MAX_TX_LEVEL (priv->txd_fifo0.m.memsz - 16)
#define TN40_MIN_TX_LEVEL 256
#define TN40_NO_UPD_PACKETS 40
#define TN40_MAX_MTU BIT(14)
#define TN40_PCK_TH_MULT 128
#define TN40_INT_COAL_MULT 2
#define TN40_INT_REG_VAL(coal, coal_rc, rxf_th, pck_th) ( \
FIELD_PREP(GENMASK(14, 0), (coal)) | \
FIELD_PREP(BIT(15), (coal_rc)) | \
FIELD_PREP(GENMASK(19, 16), (rxf_th)) | \
FIELD_PREP(GENMASK(31, 20), (pck_th)) \
)
struct tn40_fifo {
dma_addr_t da; /* Physical address of fifo (used by HW) */
char *va; /* Virtual address of fifo (used by SW) */
u32 rptr, wptr;
/* Cached values of RPTR and WPTR registers,
* they're 32 bits on both 32 and 64 archs.
*/
u16 reg_cfg0;
u16 reg_cfg1;
u16 reg_rptr;
u16 reg_wptr;
u16 memsz; /* Memory size allocated for fifo */
u16 size_mask;
u16 pktsz; /* Skb packet size to allocate */
u16 rcvno; /* Number of buffers that come from this RXF */
};
struct tn40_txf_fifo {
struct tn40_fifo m; /* The minimal set of variables used by all fifos */
};
struct tn40_txd_fifo {
struct tn40_fifo m; /* The minimal set of variables used by all fifos */
};
struct tn40_rxf_fifo {
struct tn40_fifo m; /* The minimal set of variables used by all fifos */
};
struct tn40_rxd_fifo {
struct tn40_fifo m; /* The minimal set of variables used by all fifos */
};
struct tn40_rx_map {
struct page *page;
};
struct tn40_rxdb {
unsigned int *stack;
struct tn40_rx_map *elems;
unsigned int nelem;
unsigned int top;
};
union tn40_tx_dma_addr {
dma_addr_t dma;
struct sk_buff *skb;
};
/* Entry in the db.
* if len == 0 addr is dma
* if len != 0 addr is skb
*/
struct tn40_tx_map {
union tn40_tx_dma_addr addr;
int len;
};
/* tx database - implemented as circular fifo buffer */
struct tn40_txdb {
struct tn40_tx_map *start; /* Points to the first element */
struct tn40_tx_map *end; /* Points just AFTER the last element */
struct tn40_tx_map *rptr; /* Points to the next element to read */
struct tn40_tx_map *wptr; /* Points to the next element to write */
int size; /* Number of elements in the db */
};
struct tn40_priv {
struct net_device *ndev;
struct pci_dev *pdev;
struct napi_struct napi;
/* RX FIFOs: 1 for data (full) descs, and 2 for free descs */
struct tn40_rxd_fifo rxd_fifo0;
struct tn40_rxf_fifo rxf_fifo0;
struct tn40_rxdb *rxdb0; /* Rx dbs to store skb pointers */
struct page_pool *page_pool;
/* Tx FIFOs: 1 for data desc, 1 for empty (acks) desc */
struct tn40_txd_fifo txd_fifo0;
struct tn40_txf_fifo txf_fifo0;
struct tn40_txdb txdb;
int tx_level;
int tx_update_mark;
int tx_noupd;
int stats_flag;
struct rtnl_link_stats64 stats;
u64 alloc_fail;
struct u64_stats_sync syncp;
u8 txd_size;
u8 txf_size;
u8 rxd_size;
u8 rxf_size;
u32 rdintcm;
u32 tdintcm;
u32 isr_mask;
void __iomem *regs;
/* SHORT_PKT_FIX */
u32 b0_len;
dma_addr_t b0_dma; /* Physical address of buffer */
char *b0_va; /* Virtual address of buffer */
struct mii_bus *mdio;
struct phy_device *phydev;
struct phylink *phylink;
struct phylink_config phylink_config;
};
/* RX FREE descriptor - 64bit */
struct tn40_rxf_desc {
__le32 info; /* Buffer Count + Info - described below */
__le32 va_lo; /* VAdr[31:0] */
__le32 va_hi; /* VAdr[63:32] */
__le32 pa_lo; /* PAdr[31:0] */
__le32 pa_hi; /* PAdr[63:32] */
__le32 len; /* Buffer Length */
};
#define TN40_GET_RXD_BC(x) FIELD_GET(GENMASK(4, 0), (x))
#define TN40_GET_RXD_ERR(x) FIELD_GET(GENMASK(26, 21), (x))
#define TN40_GET_RXD_PKT_ID(x) FIELD_GET(GENMASK(30, 28), (x))
#define TN40_GET_RXD_VTAG(x) FIELD_GET(BIT(31), (x))
#define TN40_GET_RXD_VLAN_TCI(x) FIELD_GET(GENMASK(15, 0), (x))
struct tn40_rxd_desc {
__le32 rxd_val1;
__le16 len;
__le16 rxd_vlan;
__le32 va_lo;
__le32 va_hi;
__le32 rss_lo;
__le32 rss_hash;
};
#define TN40_MAX_PBL (19)
/* PBL describes each virtual buffer to be transmitted from the host. */
struct tn40_pbl {
__le32 pa_lo;
__le32 pa_hi;
__le32 len;
};
/* First word for TXD descriptor. It means: type = 3 for regular Tx packet,
* hw_csum = 7 for IP+UDP+TCP HW checksums.
*/
#define TN40_TXD_W1_VAL(bc, checksum, vtag, lgsnd, vlan_id) ( \
GENMASK(17, 16) | \
FIELD_PREP(GENMASK(4, 0), (bc)) | \
FIELD_PREP(GENMASK(7, 5), (checksum)) | \
FIELD_PREP(BIT(8), (vtag)) | \
FIELD_PREP(GENMASK(12, 9), (lgsnd)) | \
FIELD_PREP(GENMASK(15, 13), \
FIELD_GET(GENMASK(15, 13), (vlan_id))) | \
FIELD_PREP(GENMASK(31, 20), \
FIELD_GET(GENMASK(11, 0), (vlan_id))) \
)
struct tn40_txd_desc {
__le32 txd_val1;
__le16 mss;
__le16 length;
__le32 va_lo;
__le32 va_hi;
struct tn40_pbl pbl[]; /* Fragments */
};
struct tn40_txf_desc {
u32 status;
u32 va_lo; /* VAdr[31:0] */
u32 va_hi; /* VAdr[63:32] */
u32 pad;
};
static inline u32 tn40_read_reg(struct tn40_priv *priv, u32 reg)
{
return readl(priv->regs + reg);
}
static inline void tn40_write_reg(struct tn40_priv *priv, u32 reg, u32 val)
{
writel(val, priv->regs + reg);
}
int tn40_set_link_speed(struct tn40_priv *priv, u32 speed);
int tn40_mdiobus_init(struct tn40_priv *priv);
int tn40_phy_register(struct tn40_priv *priv);
void tn40_phy_unregister(struct tn40_priv *priv);
#endif /* _TN40XX_H */
|