summaryrefslogtreecommitdiffstats
path: root/src/drivers/infiniband/golan.h
blob: 2fd06ecf0cb7dfa143dd1c1c53b07c0e8a6791c8 (plain) (blame)
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
#ifndef _GOLAN_H_
#define _GOLAN_H_

/*
 * Copyright (C) 2013-2015 Mellanox Technologies Ltd.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

FILE_LICENCE ( GPL2_OR_LATER );

#include <ipxe/pci.h>
#include <ipxe/pcibackup.h>
#include <byteswap.h>
#include <errno.h>
#include <ipxe/io.h>
#include <stdio.h>
#include <unistd.h>
#include "CIB_PRM.h"
#include "mlx_utils/include/public/mlx_utils.h"

#define GOLAN_PCI_CONFIG_BAR_SIZE	0x100000//HERMON_PCI_CONFIG_BAR_SIZE //TODO: What is the BAR size?

#define GOLAN_PAS_SIZE	sizeof(uint64_t)

#define GOLAN_INVALID_LKEY 0x00000100UL

#define GOLAN_MAX_PORTS	2
#define GOLAN_PORT_BASE 1

#define MELLANOX_VID	0x15b3
#define GOLAN_HCA_BAR	PCI_BASE_ADDRESS_0	//BAR 0

#define GOLAN_HCR_MAX_WAIT_MS	10000

#define min(a,b) ((a)<(b)?(a):(b))

#define GOLAN_PAGE_SHIFT	12
#define	GOLAN_PAGE_SIZE		(1 << GOLAN_PAGE_SHIFT)
#define GOLAN_PAGE_MASK		(GOLAN_PAGE_SIZE - 1)

#define MAX_MBOX	( GOLAN_PAGE_SIZE / MAILBOX_STRIDE )
#define DEF_CMD_IDX	1
#define MEM_CMD_IDX	0
#define NO_MBOX		0xffff
#define MEM_MBOX	MEM_CMD_IDX
#define GEN_MBOX	DEF_CMD_IDX

#define CMD_IF_REV	4

#define MAX_PASE_MBOX	((GOLAN_CMD_PAS_CNT) - 2)

#define CMD_STATUS( golan , idx )		((struct golan_outbox_hdr *)(get_cmd( (golan) , (idx) )->out))->status
#define CMD_SYND( golan , idx )		((struct golan_outbox_hdr *)(get_cmd( (golan) , (idx) )->out))->syndrome
#define QRY_PAGES_OUT( golan, idx )		((struct golan_query_pages_outbox *)(get_cmd( (golan) , (idx) )->out))

#define VIRT_2_BE64_BUS( addr )		cpu_to_be64(((unsigned long long )virt_to_bus(addr)))
#define BE64_BUS_2_VIRT( addr )		bus_to_virt(be64_to_cpu(addr))
#define USR_2_BE64_BUS( addr )		cpu_to_be64(((unsigned long long )user_to_phys(addr, 0)))
#define BE64_BUS_2_USR( addr )		be64_to_cpu(phys_to_user(addr))

#define GET_INBOX(golan, idx)		(&(((struct mbox *)(golan->mboxes.inbox))[idx]))
#define GET_OUTBOX(golan, idx)		(&(((struct mbox *)(golan->mboxes.outbox))[idx]))

#define GOLAN_MBOX_IN( cmd_ptr, in_ptr ) ( {				  \
	union {								  \
		__be32 raw[4];						  \
		typeof ( *(in_ptr) ) cooked;				  \
	} *u = container_of ( &(cmd_ptr)->in[0], typeof ( *u ), raw[0] ); \
	&u->cooked; } )

#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))

/* Fw status fields */
typedef enum {
	NO_ERRORS          = 0x0,
	SIGNATURE_ERROR    = 0x1,
	TOKEN_ERROR        = 0x2,
	BAD_BLOCK_NUMBER   = 0x3,
	BAD_OUTPUT_POINTER = 0x4,   // pointer not align to mailbox size
	BAD_INPUT_POINTER  = 0x5,   // pointer not align to mailbox size
	INTERNAL_ERROR     = 0x6,
	INPUT_LEN_ERROR    = 0x7,   // input  length less than 0x8.
	OUTPUT_LEN_ERROR   = 0x8,   // output length less than 0x8.
	RESERVE_NOT_ZERO   = 0x9,
	BAD_CMD_TYPE       = 0x10,
} return_hdr_t;

struct golan_cmdq_md {
	void	*addr;
	u16	log_stride;
	u16	size;
};

struct golan_uar {
    uint32_t    	index;
    void        	*virt;
    unsigned long	phys;
};


struct golan_firmware_area {
	/* length of area in pages */
	uint32_t npages;
	/** Firmware area in external memory
	 *
	 * This is allocated when first needed, and freed only on
	 * final teardown, in order to avoid memory map changes at
	 * runtime.
	 */
	userptr_t area;
};
/* Queue Pair */
#define GOLAN_SEND_WQE_BB_SIZE			64
#define GOLAN_SEND_UD_WQE_SIZE			sizeof(struct golan_send_wqe_ud)
#define GOLAN_RECV_WQE_SIZE				sizeof(struct golan_recv_wqe_ud)
#define GOLAN_WQEBBS_PER_SEND_UD_WQE	DIV_ROUND_UP(GOLAN_SEND_UD_WQE_SIZE, GOLAN_SEND_WQE_BB_SIZE)
#define GOLAN_SEND_OPCODE			0x0a
#define GOLAN_WQE_CTRL_WQE_IDX_BIT	8

enum golan_ib_qp_state {
	GOLAN_IB_QPS_RESET,
	GOLAN_IB_QPS_INIT,
	GOLAN_IB_QPS_RTR,
	GOLAN_IB_QPS_RTS,
	GOLAN_IB_QPS_SQD,
	GOLAN_IB_QPS_SQE,
	GOLAN_IB_QPS_ERR
};

struct golan_send_wqe_ud {
	struct golan_wqe_ctrl_seg ctrl;
	struct golan_av datagram;
	struct golan_wqe_data_seg data;
};

union golan_send_wqe {
	struct golan_send_wqe_ud ud;
	uint8_t pad[GOLAN_WQEBBS_PER_SEND_UD_WQE * GOLAN_SEND_WQE_BB_SIZE];
};

struct golan_recv_wqe_ud {
	struct golan_wqe_data_seg data[2];
};

struct golan_recv_wq {
	struct golan_recv_wqe_ud *wqes;
	/* WQ size in bytes */
	int	size;
	/* In SQ, it will be increased in wqe_size (number of WQEBBs per WQE) */
	u16 next_idx;
	/** GRH buffers (if applicable) */
	struct ib_global_route_header *grh;
	/** Size of GRH buffers */
	size_t grh_size;
};

struct golan_send_wq {
	union golan_send_wqe *wqes;
	/* WQ size in bytes */
	int size;
	/* In SQ, it will be increased in wqe_size (number of WQEBBs per WQE) */
	u16 next_idx;
};

struct golan_queue_pair {
	void *wqes;
	int size;
	struct golan_recv_wq rq;
	struct golan_send_wq sq;
	struct golan_qp_db *doorbell_record;
	u32 doorbell_qpn;
	enum golan_ib_qp_state state;
};

/* Completion Queue */
#define GOLAN_CQE_OPCODE_NOT_VALID	0x0f
#define GOLAN_CQE_OPCODE_BIT		4
#define GOLAN_CQ_DB_RECORD_SIZE		sizeof(uint64_t)
#define GOLAN_CQE_OWNER_MASK		1

#define MANAGE_PAGES_PSA_OFFSET		0
#define PXE_CMDIF_REF			5

enum {
	GOLAN_CQE_SW_OWNERSHIP = 0x0,
	GOLAN_CQE_HW_OWNERSHIP = 0x1
};

enum {
	GOLAN_CQE_SIZE_64	= 0,
	GOLAN_CQE_SIZE_128	= 1
};

struct golan_completion_queue {
	struct golan_cqe64	*cqes;
	int					size;
	__be64		*doorbell_record;
};


/* Event Queue */
#define GOLAN_EQE_SIZE				sizeof(struct golan_eqe)
#define GOLAN_NUM_EQES 				8
#define GOLAN_EQ_DOORBELL_OFFSET		0x40
#define DB_BUFFER0_EVEN_OFFSET	0x800
#define DB_BUFFER0_ODD_OFFSET	0x900

#define GOLAN_EQ_MAP_ALL_EVENTS					\
	((1 << GOLAN_EVENT_TYPE_PATH_MIG         	)|	\
	(1 << GOLAN_EVENT_TYPE_COMM_EST          	)|	\
	(1 << GOLAN_EVENT_TYPE_SQ_DRAINED        	)|	\
	(1 << GOLAN_EVENT_TYPE_SRQ_LAST_WQE		)|	\
	(1 << GOLAN_EVENT_TYPE_SRQ_RQ_LIMIT      	)|	\
	(1 << GOLAN_EVENT_TYPE_CQ_ERROR          	)|	\
	(1 << GOLAN_EVENT_TYPE_WQ_CATAS_ERROR    	)|	\
	(1 << GOLAN_EVENT_TYPE_PATH_MIG_FAILED   	)|	\
	(1 << GOLAN_EVENT_TYPE_WQ_INVAL_REQ_ERROR	)|	\
	(1 << GOLAN_EVENT_TYPE_WQ_ACCESS_ERROR	 	)|	\
	(1 << GOLAN_EVENT_TYPE_SRQ_CATAS_ERROR   	)|	\
	(1 << GOLAN_EVENT_TYPE_INTERNAL_ERROR  	 	)|	\
	(1 << GOLAN_EVENT_TYPE_PORT_CHANGE   	  	)|	\
	(1 << GOLAN_EVENT_TYPE_GPIO_EVENT         	)|	\
	(1 << GOLAN_EVENT_TYPE_CLIENT_RE_REGISTER 	)|	\
	(1 << GOLAN_EVENT_TYPE_REMOTE_CONFIG     	)|	\
	(1 << GOLAN_EVENT_TYPE_DB_BF_CONGESTION   	)|	\
	(1 << GOLAN_EVENT_TYPE_STALL_EVENT        	)|	\
	(1 << GOLAN_EVENT_TYPE_PACKET_DROPPED     	)|	\
	(1 << GOLAN_EVENT_TYPE_CMD             	  	)|	\
	(1 << GOLAN_EVENT_TYPE_PAGE_REQUEST       	))

enum golan_event {
	GOLAN_EVENT_TYPE_COMP			= 0x0,

	GOLAN_EVENT_TYPE_PATH_MIG		= 0x01,
	GOLAN_EVENT_TYPE_COMM_EST		= 0x02,
	GOLAN_EVENT_TYPE_SQ_DRAINED		= 0x03,
	GOLAN_EVENT_TYPE_SRQ_LAST_WQE		= 0x13,
	GOLAN_EVENT_TYPE_SRQ_RQ_LIMIT		= 0x14,

	GOLAN_EVENT_TYPE_CQ_ERROR		= 0x04,
	GOLAN_EVENT_TYPE_WQ_CATAS_ERROR		= 0x05,
	GOLAN_EVENT_TYPE_PATH_MIG_FAILED	= 0x07,
	GOLAN_EVENT_TYPE_WQ_INVAL_REQ_ERROR	= 0x10,
	GOLAN_EVENT_TYPE_WQ_ACCESS_ERROR	= 0x11,
	GOLAN_EVENT_TYPE_SRQ_CATAS_ERROR	= 0x12,

	GOLAN_EVENT_TYPE_INTERNAL_ERROR		= 0x08,
	GOLAN_EVENT_TYPE_PORT_CHANGE		= 0x09,
	GOLAN_EVENT_TYPE_GPIO_EVENT		= 0x15,
//	GOLAN_EVENT_TYPE_CLIENT_RE_REGISTER	= 0x16,
	GOLAN_EVENT_TYPE_REMOTE_CONFIG		= 0x19,

	GOLAN_EVENT_TYPE_DB_BF_CONGESTION	= 0x1a,
	GOLAN_EVENT_TYPE_STALL_EVENT		= 0x1b,

	GOLAN_EVENT_TYPE_PACKET_DROPPED		= 0x1f,

	GOLAN_EVENT_TYPE_CMD			= 0x0a,
	GOLAN_EVENT_TYPE_PAGE_REQUEST		= 0x0b,
	GOLAN_EVENT_TYPE_PAGE_FAULT		= 0x0C,
};

enum golan_port_sub_event {
    GOLAN_PORT_CHANGE_SUBTYPE_DOWN		= 1,
    GOLAN_PORT_CHANGE_SUBTYPE_ACTIVE		= 4,
    GOLAN_PORT_CHANGE_SUBTYPE_INITIALIZED	= 5,
    GOLAN_PORT_CHANGE_SUBTYPE_LID		= 6,
    GOLAN_PORT_CHANGE_SUBTYPE_PKEY		= 7,
    GOLAN_PORT_CHANGE_SUBTYPE_GUID		= 8,
    GOLAN_PORT_CHANGE_SUBTYPE_CLIENT_REREG	= 9
};


enum {
	GOLAN_EQE_SW_OWNERSHIP = 0x0,
	GOLAN_EQE_HW_OWNERSHIP = 0x1
};

enum {
	GOLAN_EQ_UNARMED	= 0,
	GOLAN_EQ_ARMED		= 1,
};

struct golan_event_queue {
	uint8_t			eqn;
	uint64_t		mask;
	struct golan_eqe	*eqes;
	int			size;
	__be32			*doorbell;
	uint32_t		cons_index;
};

struct golan_port {
	/** Infiniband device */
	struct ib_device	*ibdev;
	/** Network device */
	struct net_device	*netdev;
	/** VEP number */
	u8 vep_number;
};

struct golan_mboxes {
	void 	*inbox;
	void	*outbox;
};

#define GOLAN_OPEN	0x1

struct golan {
	struct pci_device		*pci;
	struct golan_hca_init_seg	*iseg;
	struct golan_cmdq_md		cmd;
	struct golan_hca_cap		caps; /* stored as big indian*/
	struct golan_mboxes		mboxes;
	struct list_head		pages;
	uint32_t			cmd_bm;
	uint32_t			total_dma_pages;
	struct golan_uar		uar;
	struct golan_event_queue 	eq;
	uint32_t			pdn;
	u32				mkey;
	u32				flags;
	mlx_utils		*utils;

	struct golan_port		ports[GOLAN_MAX_PORTS];
#define GOLAN_FW_AREAS_NUM 2
	struct golan_firmware_area fw_areas[GOLAN_FW_AREAS_NUM];
};

#endif /* _GOLAN_H_*/