aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/fjes/fjes_hw.h
blob: b4608ea2a2d57c8cf4c2d08272f95d77033e2c21 (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
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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 *  FUJITSU Extended Socket Network Device driver
 *  Copyright (c) 2015 FUJITSU LIMITED
 */

#ifndef FJES_HW_H_
#define FJES_HW_H_

#include <linux/netdevice.h>
#include <linux/if_vlan.h>
#include <linux/vmalloc.h>

#include "fjes_regs.h"

struct fjes_hw;

#define EP_BUFFER_SUPPORT_VLAN_MAX 4
#define EP_BUFFER_INFO_SIZE 4096

#define FJES_DEBUG_PAGE_SIZE 4096
#define FJES_DEBUG_BUFFER_SIZE	(16 * FJES_DEBUG_PAGE_SIZE)

#define FJES_DEVICE_RESET_TIMEOUT  ((17 + 1) * 3 * 8) /* sec */
#define FJES_COMMAND_REQ_TIMEOUT  ((5 + 1) * 3 * 8) /* sec */
#define FJES_COMMAND_REQ_BUFF_TIMEOUT	(60 * 3) /* sec */
#define FJES_COMMAND_EPSTOP_WAIT_TIMEOUT	(1) /* sec */

#define FJES_CMD_REQ_ERR_INFO_PARAM  (0x0001)
#define FJES_CMD_REQ_ERR_INFO_STATUS (0x0002)

#define FJES_CMD_REQ_RES_CODE_NORMAL (0)
#define FJES_CMD_REQ_RES_CODE_BUSY   (1)

#define FJES_ZONING_STATUS_DISABLE	(0x00)
#define FJES_ZONING_STATUS_ENABLE	(0x01)
#define FJES_ZONING_STATUS_INVALID	(0xFF)

#define FJES_ZONING_ZONE_TYPE_NONE (0xFF)

#define FJES_TX_DELAY_SEND_NONE		(0)
#define FJES_TX_DELAY_SEND_PENDING	(1)

#define FJES_RX_STOP_REQ_NONE		(0x0)
#define FJES_RX_STOP_REQ_DONE		(0x1)
#define FJES_RX_STOP_REQ_REQUEST	(0x2)
#define FJES_RX_POLL_WORK		(0x4)
#define FJES_RX_MTU_CHANGING_DONE	(0x8)

#define EP_BUFFER_SIZE \
	(((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \
		/ EP_BUFFER_INFO_SIZE) * EP_BUFFER_INFO_SIZE)

#define EP_RING_NUM(buffer_size, frame_size) \
		(u32)((buffer_size) / (frame_size))
#define EP_RING_INDEX(_num, _max) (((_num) + (_max)) % (_max))
#define EP_RING_INDEX_INC(_num, _max) \
	((_num) = EP_RING_INDEX((_num) + 1, (_max)))
#define EP_RING_FULL(_head, _tail, _max)				\
	(0 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
#define EP_RING_EMPTY(_head, _tail, _max) \
	(1 == EP_RING_INDEX(((_tail) - (_head)), (_max)))

#define FJES_MTU_TO_BUFFER_SIZE(mtu) \
	(ETH_HLEN + VLAN_HLEN + (mtu) + ETH_FCS_LEN)
#define FJES_MTU_TO_FRAME_SIZE(mtu) \
	(sizeof(struct esmem_frame) + FJES_MTU_TO_BUFFER_SIZE(mtu))
#define FJES_MTU_DEFINE(size) \
	((size) - sizeof(struct esmem_frame) - \
	(ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN))

#define FJES_DEV_COMMAND_INFO_REQ_LEN	(4)
#define FJES_DEV_COMMAND_INFO_RES_LEN(epnum) (8 + 2 * (epnum))
#define FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(txb, rxb) \
	(24 + (8 * ((txb) / EP_BUFFER_INFO_SIZE + (rxb) / EP_BUFFER_INFO_SIZE)))
#define FJES_DEV_COMMAND_SHARE_BUFFER_RES_LEN	(8)
#define FJES_DEV_COMMAND_UNSHARE_BUFFER_REQ_LEN	(8)
#define FJES_DEV_COMMAND_UNSHARE_BUFFER_RES_LEN	(8)

#define FJES_DEV_REQ_BUF_SIZE(maxep) \
	FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(EP_BUFFER_SIZE, EP_BUFFER_SIZE)
#define FJES_DEV_RES_BUF_SIZE(maxep) \
	FJES_DEV_COMMAND_INFO_RES_LEN(maxep)

#define FJES_DEV_COMMAND_START_DBG_REQ_LEN(byte) \
	(16 + (8 * (byte) / FJES_DEBUG_PAGE_SIZE))
#define FJES_DEV_COMMAND_START_DBG_RES_LEN (8)
#define FJES_DEV_COMMAND_STOP_DBG_REQ_LEN (4)
#define FJES_DEV_COMMAND_STOP_DBG_RES_LEN (8)

/* Frame & MTU */
struct esmem_frame {
	__le32 frame_size;
	u8 frame_data[];
};

/* EP partner status */
enum ep_partner_status {
	EP_PARTNER_UNSHARE,
	EP_PARTNER_SHARED,
	EP_PARTNER_WAITING,
	EP_PARTNER_COMPLETE,
	EP_PARTNER_STATUS_MAX,
};

/* shared status region */
struct fjes_device_shared_info {
	int epnum;
	u8 ep_status[];
};

/* structures for command control request data*/
union fjes_device_command_req {
	struct {
		__le32 length;
	} info;
	struct {
		__le32 length;
		__le32 epid;
		__le64 buffer[];
	} share_buffer;
	struct {
		__le32 length;
		__le32 epid;
	} unshare_buffer;
	struct {
		__le32 length;
		__le32 mode;
		__le64 buffer_len;
		__le64 buffer[];
	} start_trace;
	struct {
		__le32 length;
	} stop_trace;
};

/* structures for command control response data */
union fjes_device_command_res {
	struct {
		__le32 length;
		__le32 code;
		struct {
			u8 es_status;
			u8 zone;
		} info[];
	} info;
	struct {
		__le32 length;
		__le32 code;
	} share_buffer;
	struct {
		__le32 length;
		__le32 code;
	} unshare_buffer;
	struct {
		__le32 length;
		__le32 code;
	} start_trace;
	struct {
		__le32 length;
		__le32 code;
	} stop_trace;
};

/* request command type */
enum fjes_dev_command_request_type {
	FJES_CMD_REQ_INFO		= 0x0001,
	FJES_CMD_REQ_SHARE_BUFFER	= 0x0002,
	FJES_CMD_REQ_UNSHARE_BUFFER	= 0x0004,
	FJES_CMD_REQ_START_DEBUG	= 0x0100,
	FJES_CMD_REQ_STOP_DEBUG		= 0x0200,
};

/* parameter for command control */
struct fjes_device_command_param {
	u32 req_len;
	phys_addr_t req_start;
	u32 res_len;
	phys_addr_t res_start;
	phys_addr_t share_start;
};

/* error code for command control */
enum fjes_dev_command_response_e {
	FJES_CMD_STATUS_UNKNOWN,
	FJES_CMD_STATUS_NORMAL,
	FJES_CMD_STATUS_TIMEOUT,
	FJES_CMD_STATUS_ERROR_PARAM,
	FJES_CMD_STATUS_ERROR_STATUS,
};

/* EP buffer information */
union ep_buffer_info {
	u8 raw[EP_BUFFER_INFO_SIZE];

	struct _ep_buffer_info_common_t {
		u32 version;
	} common;

	struct _ep_buffer_info_v1_t {
		u32 version;
		u32 info_size;

		u32 buffer_size;
		u16 count_max;

		u16 _rsv_1;

		u32 frame_max;
		u8 mac_addr[ETH_ALEN];

		u16 _rsv_2;
		u32 _rsv_3;

		u16 tx_status;
		u16 rx_status;

		u32 head;
		u32 tail;

		u16 vlan_id[EP_BUFFER_SUPPORT_VLAN_MAX];

	} v1i;

};

/* statistics of EP */
struct fjes_drv_ep_stats {
	u64 com_regist_buf_exec;
	u64 com_unregist_buf_exec;
	u64 send_intr_rx;
	u64 send_intr_unshare;
	u64 send_intr_zoneupdate;
	u64 recv_intr_rx;
	u64 recv_intr_unshare;
	u64 recv_intr_stop;
	u64 recv_intr_zoneupdate;
	u64 tx_buffer_full;
	u64 tx_dropped_not_shared;
	u64 tx_dropped_ver_mismatch;
	u64 tx_dropped_buf_size_mismatch;
	u64 tx_dropped_vlanid_mismatch;
};

/* buffer pair for Extended Partition */
struct ep_share_mem_info {
	struct epbuf_handler {
		void *buffer;
		size_t size;
		union ep_buffer_info *info;
		u8 *ring;
	} tx, rx;

	struct rtnl_link_stats64 net_stats;
	struct fjes_drv_ep_stats ep_stats;

	u16 tx_status_work;

	u8 es_status;
	u8 zone;
};

struct es_device_trace {
	u32 record_num;
	u32 current_record;
	u32 status_flag;
	u32 _rsv;

	struct {
			u16 epid;
			u16 dir_offset;
			u32 data;
			u64 tsc;
	} record[];
};

struct fjes_hw_info {
	struct fjes_device_shared_info *share;
	union fjes_device_command_req *req_buf;
	u64 req_buf_size;
	union fjes_device_command_res *res_buf;
	u64 res_buf_size;

	int *my_epid;
	int *max_epid;

	struct es_device_trace *trace;
	u64 trace_size;

	struct mutex lock; /* buffer lock*/

	unsigned long buffer_share_bit;
	unsigned long buffer_unshare_reserve_bit;
};

struct fjes_hw {
	void *back;

	unsigned long txrx_stop_req_bit;
	unsigned long epstop_req_bit;
	struct work_struct update_zone_task;
	struct work_struct epstop_task;

	int my_epid;
	int max_epid;

	struct ep_share_mem_info *ep_shm_info;

	struct fjes_hw_resource {
		u64 start;
		u64 size;
		int irq;
	} hw_res;

	u8 *base;

	struct fjes_hw_info hw_info;

	spinlock_t rx_status_lock; /* spinlock for rx_status */

	u32 debug_mode;
};

int fjes_hw_init(struct fjes_hw *);
void fjes_hw_exit(struct fjes_hw *);
int fjes_hw_reset(struct fjes_hw *);
int fjes_hw_request_info(struct fjes_hw *);
int fjes_hw_register_buff_addr(struct fjes_hw *, int,
			       struct ep_share_mem_info *);
int fjes_hw_unregister_buff_addr(struct fjes_hw *, int);
void fjes_hw_init_command_registers(struct fjes_hw *,
				    struct fjes_device_command_param *);
void fjes_hw_setup_epbuf(struct epbuf_handler *, u8 *, u32);
int fjes_hw_raise_interrupt(struct fjes_hw *, int, enum REG_ICTL_MASK);
void fjes_hw_set_irqmask(struct fjes_hw *, enum REG_ICTL_MASK, bool);
u32 fjes_hw_capture_interrupt_status(struct fjes_hw *);
void fjes_hw_raise_epstop(struct fjes_hw *);
int fjes_hw_wait_epstop(struct fjes_hw *);
enum ep_partner_status
	fjes_hw_get_partner_ep_status(struct fjes_hw *, int);

bool fjes_hw_epid_is_same_zone(struct fjes_hw *, int);
int fjes_hw_epid_is_shared(struct fjes_device_shared_info *, int);
bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32);
bool fjes_hw_check_mtu(struct epbuf_handler *, u32);
bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16);
bool fjes_hw_set_vlan_id(struct epbuf_handler *, u16);
void fjes_hw_del_vlan_id(struct epbuf_handler *, u16);
bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *);
void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *, size_t *);
void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *);
int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *, void *, size_t);

int fjes_hw_start_debug(struct fjes_hw *);
int fjes_hw_stop_debug(struct fjes_hw *);
#endif /* FJES_HW_H_ */