Browse Source

[Hermon] Add driver for Mellanox Hermon (ConnectX) cards.

tags/v0.9.4
Michael Brown 16 years ago
parent
commit
396dc6e797

+ 3313
- 0
src/drivers/infiniband/MT25408_PRM.h
File diff suppressed because it is too large
View File


+ 2168
- 0
src/drivers/infiniband/hermon.c
File diff suppressed because it is too large
View File


+ 459
- 0
src/drivers/infiniband/hermon.h View File

@@ -0,0 +1,459 @@
1
+#ifndef _HERMON_H
2
+#define _HERMON_H
3
+
4
+/** @file
5
+ *
6
+ * Mellanox Hermon Infiniband HCA driver
7
+ *
8
+ */
9
+
10
+#include <stdint.h>
11
+#include <gpxe/uaccess.h>
12
+#include "mlx_bitops.h"
13
+#include "MT25408_PRM.h"
14
+
15
+/*
16
+ * Hardware constants
17
+ *
18
+ */
19
+
20
+/* PCI BARs */
21
+#define HERMON_PCI_CONFIG_BAR		PCI_BASE_ADDRESS_0
22
+#define HERMON_PCI_CONFIG_BAR_SIZE	0x100000
23
+#define HERMON_PCI_UAR_BAR		PCI_BASE_ADDRESS_2
24
+
25
+/* Work queue entry and completion queue entry opcodes */
26
+#define HERMON_OPCODE_SEND		0x0a
27
+#define HERMON_OPCODE_RECV_ERROR	0xfe
28
+#define HERMON_OPCODE_SEND_ERROR	0xff
29
+
30
+/* HCA command register opcodes */
31
+#define HERMON_HCR_QUERY_DEV_CAP	0x0003
32
+#define HERMON_HCR_QUERY_FW		0x0004
33
+#define HERMON_HCR_INIT_HCA		0x0007
34
+#define HERMON_HCR_CLOSE_HCA		0x0008
35
+#define HERMON_HCR_INIT_PORT		0x0009
36
+#define HERMON_HCR_CLOSE_PORT		0x000a
37
+#define HERMON_HCR_SW2HW_MPT		0x000d
38
+#define HERMON_HCR_WRITE_MTT		0x0011
39
+#define HERMON_HCR_MAP_EQ		0x0012
40
+#define HERMON_HCR_SW2HW_EQ		0x0013
41
+#define HERMON_HCR_HW2SW_EQ		0x0014
42
+#define HERMON_HCR_SW2HW_CQ		0x0016
43
+#define HERMON_HCR_HW2SW_CQ		0x0017
44
+#define HERMON_HCR_RST2INIT_QP		0x0019
45
+#define HERMON_HCR_INIT2RTR_QP		0x001a
46
+#define HERMON_HCR_RTR2RTS_QP		0x001b
47
+#define HERMON_HCR_2RST_QP		0x0021
48
+#define HERMON_HCR_MAD_IFC		0x0024
49
+#define HERMON_HCR_READ_MCG		0x0025
50
+#define HERMON_HCR_WRITE_MCG		0x0026
51
+#define HERMON_HCR_MGID_HASH		0x0027
52
+#define HERMON_HCR_RUN_FW		0x0ff6
53
+#define HERMON_HCR_DISABLE_LAM		0x0ff7
54
+#define HERMON_HCR_ENABLE_LAM		0x0ff8
55
+#define HERMON_HCR_UNMAP_ICM		0x0ff9
56
+#define HERMON_HCR_MAP_ICM		0x0ffa
57
+#define HERMON_HCR_UNMAP_ICM_AUX	0x0ffb
58
+#define HERMON_HCR_MAP_ICM_AUX		0x0ffc
59
+#define HERMON_HCR_SET_ICM_SIZE		0x0ffd
60
+#define HERMON_HCR_UNMAP_FA		0x0ffe
61
+#define HERMON_HCR_MAP_FA		0x0fff
62
+
63
+/* Service types */
64
+#define HERMON_ST_UD			0x03
65
+
66
+/* MTUs */
67
+#define HERMON_MTU_2048			0x04
68
+
69
+#define HERMON_INVALID_LKEY		0x00000100UL
70
+
71
+#define HERMON_PAGE_SIZE		4096
72
+
73
+#define HERMON_DB_POST_SND_OFFSET	0x14
74
+
75
+/*
76
+ * Datatypes that seem to be missing from the autogenerated documentation
77
+ *
78
+ */
79
+struct hermonprm_mgm_hash_st {
80
+	pseudo_bit_t reserved0[0x00020];
81
+/* -------------- */
82
+	pseudo_bit_t hash[0x00010];
83
+	pseudo_bit_t reserved1[0x00010];
84
+} __attribute__ (( packed ));
85
+
86
+struct hermonprm_mcg_entry_st {
87
+	struct hermonprm_mcg_hdr_st hdr;
88
+	struct hermonprm_mcg_qp_dw_st qp[8];
89
+} __attribute__ (( packed ));
90
+
91
+struct hermonprm_cq_db_record_st {
92
+	pseudo_bit_t update_ci[0x00018];
93
+	pseudo_bit_t reserved0[0x00008];
94
+/* -------------- */
95
+	pseudo_bit_t arm_ci[0x00018];
96
+	pseudo_bit_t cmd[0x00003];
97
+	pseudo_bit_t reserved1[0x00001];
98
+	pseudo_bit_t cmd_sn[0x00002];
99
+	pseudo_bit_t reserved2[0x00002];
100
+} __attribute__ (( packed ));
101
+
102
+struct hermonprm_send_db_register_st {
103
+	pseudo_bit_t reserved[0x00008];
104
+	pseudo_bit_t qn[0x00018];
105
+} __attribute__ (( packed ));
106
+
107
+struct hermonprm_scalar_parameter_st {
108
+	pseudo_bit_t value_hi[0x00020];
109
+/* -------------- */
110
+	pseudo_bit_t value[0x00020];
111
+} __attribute__ (( packed ));
112
+
113
+/*
114
+ * Wrapper structures for hardware datatypes
115
+ *
116
+ */
117
+
118
+struct MLX_DECLARE_STRUCT ( hermonprm_completion_queue_context );
119
+struct MLX_DECLARE_STRUCT ( hermonprm_completion_queue_entry );
120
+struct MLX_DECLARE_STRUCT ( hermonprm_completion_with_error );
121
+struct MLX_DECLARE_STRUCT ( hermonprm_cq_db_record );
122
+struct MLX_DECLARE_STRUCT ( hermonprm_eqc );
123
+struct MLX_DECLARE_STRUCT ( hermonprm_hca_command_register );
124
+struct MLX_DECLARE_STRUCT ( hermonprm_init_hca );
125
+struct MLX_DECLARE_STRUCT ( hermonprm_init_port );
126
+struct MLX_DECLARE_STRUCT ( hermonprm_mad_ifc );
127
+struct MLX_DECLARE_STRUCT ( hermonprm_mcg_entry );
128
+struct MLX_DECLARE_STRUCT ( hermonprm_mgm_hash );
129
+struct MLX_DECLARE_STRUCT ( hermonprm_mpt );
130
+struct MLX_DECLARE_STRUCT ( hermonprm_mtt );
131
+struct MLX_DECLARE_STRUCT ( hermonprm_qp_db_record );
132
+struct MLX_DECLARE_STRUCT ( hermonprm_qp_ee_state_transitions );
133
+struct MLX_DECLARE_STRUCT ( hermonprm_query_dev_cap );
134
+struct MLX_DECLARE_STRUCT ( hermonprm_query_fw );
135
+struct MLX_DECLARE_STRUCT ( hermonprm_queue_pair_ee_context_entry );
136
+struct MLX_DECLARE_STRUCT ( hermonprm_scalar_parameter );
137
+struct MLX_DECLARE_STRUCT ( hermonprm_send_db_register );
138
+struct MLX_DECLARE_STRUCT ( hermonprm_ud_address_vector );
139
+struct MLX_DECLARE_STRUCT ( hermonprm_virtual_physical_mapping );
140
+struct MLX_DECLARE_STRUCT ( hermonprm_wqe_segment_ctrl_send );
141
+struct MLX_DECLARE_STRUCT ( hermonprm_wqe_segment_data_ptr );
142
+struct MLX_DECLARE_STRUCT ( hermonprm_wqe_segment_ud );
143
+
144
+/*
145
+ * Composite hardware datatypes
146
+ *
147
+ */
148
+
149
+struct hermonprm_write_mtt {
150
+	struct hermonprm_scalar_parameter mtt_base_addr;
151
+	struct hermonprm_scalar_parameter reserved;
152
+	struct hermonprm_mtt mtt;
153
+} __attribute__ (( packed ));
154
+
155
+#define HERMON_MAX_GATHER 1
156
+
157
+struct hermonprm_ud_send_wqe {
158
+	struct hermonprm_wqe_segment_ctrl_send ctrl;
159
+	struct hermonprm_wqe_segment_ud ud;
160
+	struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_GATHER];
161
+} __attribute__ (( packed ));
162
+
163
+#define HERMON_MAX_SCATTER 1
164
+
165
+struct hermonprm_recv_wqe {
166
+	struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_SCATTER];
167
+} __attribute__ (( packed ));
168
+
169
+union hermonprm_completion_entry {
170
+	struct hermonprm_completion_queue_entry normal;
171
+	struct hermonprm_completion_with_error error;
172
+} __attribute__ (( packed ));
173
+
174
+union hermonprm_doorbell_register {
175
+	struct hermonprm_send_db_register send;
176
+	uint32_t dword[1];
177
+} __attribute__ (( packed ));
178
+
179
+union hermonprm_mad {
180
+	struct hermonprm_mad_ifc ifc;
181
+	union ib_mad mad;
182
+} __attribute__ (( packed ));
183
+
184
+/*
185
+ * gPXE-specific definitions
186
+ *
187
+ */
188
+
189
+/** Hermon device capabilitiess */
190
+struct hermon_dev_cap {
191
+	/** CMPT entry size */
192
+	size_t cmpt_entry_size;
193
+	/** Number of reserved QPs */
194
+	unsigned int reserved_qps;
195
+	/** QP context entry size */
196
+	size_t qpc_entry_size;
197
+	/** Alternate path context entry size */
198
+	size_t altc_entry_size;
199
+	/** Auxiliary context entry size */
200
+	size_t auxc_entry_size;
201
+	/** Number of reserved SRQs */
202
+	unsigned int reserved_srqs;
203
+	/** SRQ context entry size */
204
+	size_t srqc_entry_size;
205
+	/** Number of reserved CQs */
206
+	unsigned int reserved_cqs;
207
+	/** CQ context entry size */
208
+	size_t cqc_entry_size;
209
+	/** Number of reserved EQs */
210
+	unsigned int reserved_eqs;
211
+	/** EQ context entry size */
212
+	size_t eqc_entry_size;
213
+	/** Number of reserved MTTs */
214
+	unsigned int reserved_mtts;
215
+	/** MTT entry size */
216
+	size_t mtt_entry_size;
217
+	/** Number of reserved MRWs */
218
+	unsigned int reserved_mrws;
219
+	/** DMPT entry size */
220
+	size_t dmpt_entry_size;
221
+	/** Number of reserved UARs */
222
+	unsigned int reserved_uars;
223
+};
224
+
225
+/** Number of cMPT entries of each type */
226
+#define HERMON_CMPT_MAX_ENTRIES ( 1 << 24 )
227
+
228
+/** Hermon ICM memory map entry */
229
+struct hermon_icm_map {
230
+	/** Offset (virtual address within ICM) */
231
+	uint64_t offset;
232
+	/** Length */
233
+	size_t len;
234
+};
235
+
236
+/** Discontiguous regions within Hermon ICM */
237
+enum hermon_icm_map_regions {
238
+	HERMON_ICM_QP_CMPT = 0,
239
+	HERMON_ICM_SRQ_CMPT,
240
+	HERMON_ICM_CQ_CMPT,
241
+	HERMON_ICM_EQ_CMPT,
242
+	HERMON_ICM_OTHER,
243
+	HERMON_ICM_NUM_REGIONS
244
+};
245
+
246
+/** UAR page for doorbell accesses
247
+ *
248
+ * Pages 0-127 are reserved for event queue doorbells only, so we use
249
+ * page 128.
250
+ */
251
+#define HERMON_UAR_PAGE		128
252
+
253
+/** Maximum number of allocatable MTT entries
254
+ *
255
+ * This is a policy decision, not a device limit.
256
+ */
257
+#define HERMON_MAX_MTTS		64
258
+
259
+/** A Hermon MTT descriptor */
260
+struct hermon_mtt {
261
+	/** MTT offset */
262
+	unsigned int mtt_offset;
263
+	/** Number of pages */
264
+	unsigned int num_pages;
265
+	/** MTT base address */
266
+	unsigned int mtt_base_addr;
267
+	/** Offset within page */
268
+	unsigned int page_offset;
269
+};
270
+
271
+/** Alignment of Hermon send work queue entries */
272
+#define HERMON_SEND_WQE_ALIGN 128
273
+
274
+/** A Hermon send work queue entry */
275
+union hermon_send_wqe {
276
+	struct hermonprm_ud_send_wqe ud;
277
+	uint8_t force_align[HERMON_SEND_WQE_ALIGN];
278
+} __attribute__ (( packed ));
279
+
280
+/** A Hermon send work queue */
281
+struct hermon_send_work_queue {
282
+	/** Number of work queue entries, including headroom
283
+	 *
284
+	 * Hermon requires us to leave unused space within the send
285
+	 * WQ, so we create a send WQ with more entries than are
286
+	 * requested in the create_qp() call.
287
+	 */
288
+	unsigned int num_wqes;
289
+	/** Work queue entries */
290
+	union hermon_send_wqe *wqe;
291
+	/** Size of work queue */
292
+	size_t wqe_size;
293
+};
294
+
295
+/** Alignment of Hermon receive work queue entries */
296
+#define HERMON_RECV_WQE_ALIGN 16
297
+
298
+/** A Hermon receive work queue entry */
299
+union hermon_recv_wqe {
300
+	struct hermonprm_recv_wqe recv;
301
+	uint8_t force_align[HERMON_RECV_WQE_ALIGN];
302
+} __attribute__ (( packed ));
303
+
304
+/** A Hermon receive work queue */
305
+struct hermon_recv_work_queue {
306
+	/** Work queue entries */
307
+	union hermon_recv_wqe *wqe;
308
+	/** Size of work queue */
309
+	size_t wqe_size;
310
+	/** Doorbell */
311
+	struct hermonprm_qp_db_record doorbell __attribute__ (( aligned (4) ));
312
+};
313
+
314
+/** Maximum number of allocatable queue pairs
315
+ *
316
+ * This is a policy decision, not a device limit.
317
+ */
318
+#define HERMON_MAX_QPS		8
319
+
320
+/** Base queue pair number */
321
+#define HERMON_QPN_BASE 0x550000
322
+
323
+/** A Hermon queue pair */
324
+struct hermon_queue_pair {
325
+	/** Work queue buffer */
326
+	void *wqe;
327
+	/** Size of work queue buffer */
328
+	size_t wqe_size;
329
+	/** MTT descriptor */
330
+	struct hermon_mtt mtt;
331
+	/** Send work queue */
332
+	struct hermon_send_work_queue send;
333
+	/** Receive work queue */
334
+	struct hermon_recv_work_queue recv;
335
+};
336
+
337
+/** Maximum number of allocatable completion queues
338
+ *
339
+ * This is a policy decision, not a device limit.
340
+ */
341
+#define HERMON_MAX_CQS		8
342
+
343
+/** A Hermon completion queue */
344
+struct hermon_completion_queue {
345
+	/** Completion queue entries */
346
+	union hermonprm_completion_entry *cqe;
347
+	/** Size of completion queue */
348
+	size_t cqe_size;
349
+	/** MTT descriptor */
350
+	struct hermon_mtt mtt;
351
+	/** Doorbell */
352
+	struct hermonprm_cq_db_record doorbell __attribute__ (( aligned (8) ));
353
+};
354
+
355
+/** Maximum number of allocatable event queues
356
+ *
357
+ * This is a policy decision, not a device limit.
358
+ */
359
+#define HERMON_MAX_EQS		4
360
+
361
+/** A Hermon resource bitmask */
362
+typedef uint32_t hermon_bitmask_t;
363
+
364
+/** Size of a hermon resource bitmask */
365
+#define HERMON_BITMASK_SIZE(max_entries)				     \
366
+	( ( (max_entries) + ( 8 * sizeof ( hermon_bitmask_t ) ) - 1 ) /	     \
367
+	  ( 8 * sizeof ( hermon_bitmask_t ) ) )
368
+
369
+/** A Hermon device */
370
+struct hermon {
371
+	/** PCI configuration registers */
372
+	void *config;
373
+	/** PCI user Access Region */
374
+	void *uar;
375
+
376
+	/** Command toggle */
377
+	unsigned int toggle;
378
+	/** Command input mailbox */
379
+	void *mailbox_in;
380
+	/** Command output mailbox */
381
+	void *mailbox_out;
382
+
383
+	/** Firmware area in external memory */
384
+	userptr_t firmware_area;
385
+	/** ICM map */
386
+	struct hermon_icm_map icm_map[HERMON_ICM_NUM_REGIONS];
387
+	/** ICM area */
388
+	userptr_t icm;
389
+
390
+	/** Reserved LKey
391
+	 *
392
+	 * Used to get unrestricted memory access.
393
+	 */
394
+	unsigned long reserved_lkey;
395
+
396
+	/** Completion queue in-use bitmask */
397
+	hermon_bitmask_t cq_inuse[ HERMON_BITMASK_SIZE ( HERMON_MAX_CQS ) ];
398
+	/** Queue pair in-use bitmask */
399
+	hermon_bitmask_t qp_inuse[ HERMON_BITMASK_SIZE ( HERMON_MAX_QPS ) ];
400
+	/** MTT entry in-use bitmask */
401
+	hermon_bitmask_t mtt_inuse[ HERMON_BITMASK_SIZE ( HERMON_MAX_MTTS ) ];
402
+
403
+	/** Device capabilities */
404
+	struct hermon_dev_cap cap;
405
+};
406
+
407
+/** Global protection domain */
408
+#define HERMON_GLOBAL_PD		0x123456
409
+
410
+/** Memory key prefix */
411
+#define HERMON_MKEY_PREFIX		0x77000000UL
412
+
413
+/*
414
+ * HCA commands
415
+ *
416
+ */
417
+
418
+#define HERMON_HCR_BASE			0x80680
419
+#define HERMON_HCR_REG(x)		( HERMON_HCR_BASE + 4 * (x) )
420
+#define HERMON_HCR_MAX_WAIT_MS		2000
421
+#define HERMON_MBOX_ALIGN		4096
422
+#define HERMON_MBOX_SIZE		512
423
+
424
+/* HCA command is split into
425
+ *
426
+ * bits  11:0	Opcode
427
+ * bit     12	Input uses mailbox
428
+ * bit     13	Output uses mailbox
429
+ * bits 22:14	Input parameter length (in dwords)
430
+ * bits 31:23	Output parameter length (in dwords)
431
+ *
432
+ * Encoding the information in this way allows us to cut out several
433
+ * parameters to the hermon_command() call.
434
+ */
435
+#define HERMON_HCR_IN_MBOX		0x00001000UL
436
+#define HERMON_HCR_OUT_MBOX		0x00002000UL
437
+#define HERMON_HCR_OPCODE( _command )	( (_command) & 0xfff )
438
+#define HERMON_HCR_IN_LEN( _command )	( ( (_command) >> 12 ) & 0x7fc )
439
+#define HERMON_HCR_OUT_LEN( _command )	( ( (_command) >> 21 ) & 0x7fc )
440
+
441
+/** Build HCR command from component parts */
442
+#define HERMON_HCR_INOUT_CMD( _opcode, _in_mbox, _in_len,		     \
443
+			     _out_mbox, _out_len )			     \
444
+	( (_opcode) |							     \
445
+	  ( (_in_mbox) ? HERMON_HCR_IN_MBOX : 0 ) |			     \
446
+	  ( ( (_in_len) / 4 ) << 14 ) |					     \
447
+	  ( (_out_mbox) ? HERMON_HCR_OUT_MBOX : 0 ) |			     \
448
+	  ( ( (_out_len) / 4 ) << 23 ) )
449
+
450
+#define HERMON_HCR_IN_CMD( _opcode, _in_mbox, _in_len )			     \
451
+	HERMON_HCR_INOUT_CMD ( _opcode, _in_mbox, _in_len, 0, 0 )
452
+
453
+#define HERMON_HCR_OUT_CMD( _opcode, _out_mbox, _out_len )		     \
454
+	HERMON_HCR_INOUT_CMD ( _opcode, 0, 0, _out_mbox, _out_len )
455
+
456
+#define HERMON_HCR_VOID_CMD( _opcode )					     \
457
+	HERMON_HCR_INOUT_CMD ( _opcode, 0, 0, 0, 0 )
458
+
459
+#endif /* _HERMON_H */

+ 1
- 0
src/include/gpxe/errfile.h View File

@@ -107,6 +107,7 @@
107 107
 
108 108
 #define ERRFILE_scsi		     ( ERRFILE_DRIVER | 0x00700000 )
109 109
 #define ERRFILE_arbel		     ( ERRFILE_DRIVER | 0x00710000 )
110
+#define ERRFILE_hermon		     ( ERRFILE_DRIVER | 0x00720000 )
110 111
 
111 112
 #define ERRFILE_aoe			( ERRFILE_NET | 0x00000000 )
112 113
 #define ERRFILE_arp			( ERRFILE_NET | 0x00010000 )

Loading…
Cancel
Save