Browse Source

[ena] Add driver for Amazon ENA virtual function NIC

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 6 years ago
parent
commit
2fb70e8b32
3 changed files with 1628 additions and 0 deletions
  1. 1039
    0
      src/drivers/net/ena.c
  2. 588
    0
      src/drivers/net/ena.h
  3. 1
    0
      src/include/ipxe/errfile.h

+ 1039
- 0
src/drivers/net/ena.c
File diff suppressed because it is too large
View File


+ 588
- 0
src/drivers/net/ena.h View File

@@ -0,0 +1,588 @@
1
+#ifndef _ENA_H
2
+#define _ENA_H
3
+
4
+/** @file
5
+ *
6
+ * Amazon ENA network driver
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
+
12
+#include <stdint.h>
13
+#include <ipxe/if_ether.h>
14
+
15
+/** BAR size */
16
+#define ENA_BAR_SIZE 16384
17
+
18
+/** Queue alignment */
19
+#define ENA_ALIGN 4096
20
+
21
+/** Number of admin queue entries */
22
+#define ENA_AQ_COUNT 2
23
+
24
+/** Number of admin completion queue entries */
25
+#define ENA_ACQ_COUNT 2
26
+
27
+/** Number of transmit queue entries */
28
+#define ENA_TX_COUNT 16
29
+
30
+/** Number of receive queue entries */
31
+#define ENA_RX_COUNT 16
32
+
33
+/** Base address low register offset */
34
+#define ENA_BASE_LO 0x0
35
+
36
+/** Base address high register offset */
37
+#define ENA_BASE_HI 0x4
38
+
39
+/** Capability register value */
40
+#define ENA_CAPS( count, size ) ( ( (size) << 16 ) | ( (count) << 0 ) )
41
+
42
+/** Admin queue base address register */
43
+#define ENA_AQ_BASE 0x10
44
+
45
+/** Admin queue capabilities register */
46
+#define ENA_AQ_CAPS 0x18
47
+
48
+/** Admin completion queue base address register */
49
+#define ENA_ACQ_BASE 0x20
50
+
51
+/** Admin completion queue capabilities register */
52
+#define ENA_ACQ_CAPS 0x28
53
+
54
+/** Admin queue doorbell register */
55
+#define ENA_AQ_DB 0x2c
56
+
57
+/** Maximum time to wait for admin requests */
58
+#define ENA_ADMIN_MAX_WAIT_MS 5000
59
+
60
+/** Device control register */
61
+#define ENA_CTRL 0x54
62
+#define ENA_CTRL_RESET 0x00000001UL	/**< Reset */
63
+
64
+/** Maximum time to wait for reset */
65
+#define ENA_RESET_MAX_WAIT_MS 1000
66
+
67
+/** Device status register */
68
+#define ENA_STAT 0x58
69
+#define ENA_STAT_READY 0x00000001UL	/**< Ready */
70
+
71
+/** Admin queue entry header */
72
+struct ena_aq_header {
73
+	/** Request identifier */
74
+	uint8_t id;
75
+	/** Reserved */
76
+	uint8_t reserved;
77
+	/** Opcode */
78
+	uint8_t opcode;
79
+	/** Flags */
80
+	uint8_t flags;
81
+} __attribute__ (( packed ));
82
+
83
+/** Admin queue ownership phase flag */
84
+#define ENA_AQ_PHASE 0x01
85
+
86
+/** Admin completion queue entry header */
87
+struct ena_acq_header {
88
+	/** Request identifier */
89
+	uint8_t id;
90
+	/** Reserved */
91
+	uint8_t reserved;
92
+	/** Status */
93
+	uint8_t status;
94
+	/** Flags */
95
+	uint8_t flags;
96
+	/** Extended status */
97
+	uint16_t ext;
98
+	/** Consumer index */
99
+	uint16_t cons;
100
+} __attribute__ (( packed ));
101
+
102
+/** Admin completion queue ownership phase flag */
103
+#define ENA_ACQ_PHASE 0x01
104
+
105
+/** Device attributes */
106
+#define ENA_DEVICE_ATTRIBUTES 1
107
+
108
+/** Device attributes */
109
+struct ena_device_attributes {
110
+	/** Implementation */
111
+	uint32_t implementation;
112
+	/** Device version */
113
+	uint32_t version;
114
+	/** Supported features */
115
+	uint32_t features;
116
+	/** Reserved */
117
+	uint8_t reserved_a[4];
118
+	/** Physical address width */
119
+	uint32_t physical;
120
+	/** Virtual address width */
121
+	uint32_t virtual;
122
+	/** MAC address */
123
+	uint8_t mac[ETH_ALEN];
124
+	/** Reserved */
125
+	uint8_t reserved_b[2];
126
+	/** Maximum MTU */
127
+	uint32_t mtu;
128
+} __attribute__ (( packed ));
129
+
130
+/** Feature */
131
+union ena_feature {
132
+	/** Device attributes */
133
+	struct ena_device_attributes device;
134
+};
135
+
136
+/** Submission queue direction */
137
+enum ena_sq_direction {
138
+	/** Transmit */
139
+	ENA_SQ_TX = 0x20,
140
+	/** Receive */
141
+	ENA_SQ_RX = 0x40,
142
+};
143
+
144
+/** Create submission queue */
145
+#define ENA_CREATE_SQ 1
146
+
147
+/** Create submission queue request */
148
+struct ena_create_sq_req {
149
+	/** Header */
150
+	struct ena_aq_header header;
151
+	/** Direction */
152
+	uint8_t direction;
153
+	/** Reserved */
154
+	uint8_t reserved_a;
155
+	/** Policy */
156
+	uint16_t policy;
157
+	/** Completion queue identifier */
158
+	uint16_t cq_id;
159
+	/** Number of entries */
160
+	uint16_t count;
161
+	/** Base address */
162
+	uint64_t address;
163
+	/** Writeback address */
164
+	uint64_t writeback;
165
+	/** Reserved */
166
+	uint8_t reserved_b[8];
167
+} __attribute__ (( packed ));
168
+
169
+/** Submission queue policy */
170
+enum ena_sq_policy {
171
+	/** Use host memory */
172
+	ENA_SQ_HOST_MEMORY = 0x0001,
173
+	/** Memory is contiguous */
174
+	ENA_SQ_CONTIGUOUS = 0x0100,
175
+};
176
+
177
+/** Create submission queue response */
178
+struct ena_create_sq_rsp {
179
+	/** Header */
180
+	struct ena_acq_header header;
181
+	/** Submission queue identifier */
182
+	uint16_t id;
183
+	/** Reserved */
184
+	uint8_t reserved[2];
185
+	/** Doorbell register offset */
186
+	uint32_t doorbell;
187
+	/** LLQ descriptor ring offset */
188
+	uint32_t llq_desc;
189
+	/** LLQ header offset */
190
+	uint32_t llq_data;
191
+} __attribute__ (( packed ));
192
+
193
+/** Destroy submission queue */
194
+#define ENA_DESTROY_SQ 2
195
+
196
+/** Destroy submission queue request */
197
+struct ena_destroy_sq_req {
198
+	/** Header */
199
+	struct ena_aq_header header;
200
+	/** Submission queue identifier */
201
+	uint16_t id;
202
+	/** Direction */
203
+	uint8_t direction;
204
+	/** Reserved */
205
+	uint8_t reserved;
206
+} __attribute__ (( packed ));
207
+
208
+/** Destroy submission queue response */
209
+struct ena_destroy_sq_rsp {
210
+	/** Header */
211
+	struct ena_acq_header header;
212
+} __attribute__ (( packed ));
213
+
214
+/** Create completion queue */
215
+#define ENA_CREATE_CQ 3
216
+
217
+/** Create completion queue request */
218
+struct ena_create_cq_req {
219
+	/** Header */
220
+	struct ena_aq_header header;
221
+	/** Interrupts enabled */
222
+	uint8_t intr;
223
+	/** Entry size (in 32-bit words) */
224
+	uint8_t size;
225
+	/** Number of entries */
226
+	uint16_t count;
227
+	/** MSI-X vector */
228
+	uint32_t vector;
229
+	/** Base address */
230
+	uint64_t address;
231
+} __attribute__ (( packed ));
232
+
233
+/** Create completion queue response */
234
+struct ena_create_cq_rsp {
235
+	/** Header */
236
+	struct ena_acq_header header;
237
+	/** Completion queue identifier */
238
+	uint16_t id;
239
+	/** Actual number of entries */
240
+	uint16_t count;
241
+	/** NUMA node register offset */
242
+	uint32_t node;
243
+	/** Doorbell register offset */
244
+	uint32_t doorbell;
245
+	/** Interrupt unmask register offset */
246
+	uint32_t intr;
247
+} __attribute__ (( packed ));
248
+
249
+/** Destroy completion queue */
250
+#define ENA_DESTROY_CQ 4
251
+
252
+/** Destroy completion queue request */
253
+struct ena_destroy_cq_req {
254
+	/** Header */
255
+	struct ena_aq_header header;
256
+	/** Completion queue identifier */
257
+	uint16_t id;
258
+	/** Reserved */
259
+	uint8_t reserved[2];
260
+} __attribute__ (( packed ));
261
+
262
+/** Destroy completion queue response */
263
+struct ena_destroy_cq_rsp {
264
+	/** Header */
265
+	struct ena_acq_header header;
266
+} __attribute__ (( packed ));
267
+
268
+/** Get feature */
269
+#define ENA_GET_FEATURE 8
270
+
271
+/** Get feature request */
272
+struct ena_get_feature_req {
273
+	/** Header */
274
+	struct ena_aq_header header;
275
+	/** Length */
276
+	uint32_t len;
277
+	/** Address */
278
+	uint64_t address;
279
+	/** Flags */
280
+	uint8_t flags;
281
+	/** Feature identifier */
282
+	uint8_t id;
283
+	/** Reserved */
284
+	uint8_t reserved[2];
285
+} __attribute__ (( packed ));
286
+
287
+/** Get feature response */
288
+struct ena_get_feature_rsp {
289
+	/** Header */
290
+	struct ena_acq_header header;
291
+	/** Feature */
292
+	union ena_feature feature;
293
+} __attribute__ (( packed ));
294
+
295
+/** Get statistics */
296
+#define ENA_GET_STATS 11
297
+
298
+/** Get statistics request */
299
+struct ena_get_stats_req {
300
+	/** Header */
301
+	struct ena_aq_header header;
302
+	/** Reserved */
303
+	uint8_t reserved_a[12];
304
+	/** Type */
305
+	uint8_t type;
306
+	/** Scope */
307
+	uint8_t scope;
308
+	/** Reserved */
309
+	uint8_t reserved_b[2];
310
+	/** Queue ID */
311
+	uint16_t queue;
312
+	/** Device ID */
313
+	uint16_t device;
314
+} __attribute__ (( packed ));
315
+
316
+/** Basic statistics */
317
+#define ENA_STATS_TYPE_BASIC 0
318
+
319
+/** Ethernet statistics */
320
+#define ENA_STATS_SCOPE_ETH 1
321
+
322
+/** My device */
323
+#define ENA_DEVICE_MINE 0xffff
324
+
325
+/** Get statistics response */
326
+struct ena_get_stats_rsp {
327
+	/** Header */
328
+	struct ena_acq_header header;
329
+	/** Transmit byte count */
330
+	uint64_t tx_bytes;
331
+	/** Transmit packet count */
332
+	uint64_t tx_packets;
333
+	/** Receive byte count */
334
+	uint64_t rx_bytes;
335
+	/** Receive packet count */
336
+	uint64_t rx_packets;
337
+	/** Receive drop count */
338
+	uint64_t rx_drops;
339
+} __attribute__ (( packed ));
340
+
341
+/** Admin queue request */
342
+union ena_aq_req {
343
+	/** Header */
344
+	struct ena_aq_header header;
345
+	/** Create submission queue */
346
+	struct ena_create_sq_req create_sq;
347
+	/** Destroy submission queue */
348
+	struct ena_destroy_sq_req destroy_sq;
349
+	/** Create completion queue */
350
+	struct ena_create_cq_req create_cq;
351
+	/** Destroy completion queue */
352
+	struct ena_destroy_cq_req destroy_cq;
353
+	/** Get feature */
354
+	struct ena_get_feature_req get_feature;
355
+	/** Get statistics */
356
+	struct ena_get_stats_req get_stats;
357
+	/** Padding */
358
+	uint8_t pad[64];
359
+};
360
+
361
+/** Admin completion queue response */
362
+union ena_acq_rsp {
363
+	/** Header */
364
+	struct ena_acq_header header;
365
+	/** Create submission queue */
366
+	struct ena_create_sq_rsp create_sq;
367
+	/** Destroy submission queue */
368
+	struct ena_destroy_sq_rsp destroy_sq;
369
+	/** Create completion queue */
370
+	struct ena_create_cq_rsp create_cq;
371
+	/** Destroy completion queue */
372
+	struct ena_destroy_cq_rsp destroy_cq;
373
+	/** Get feature */
374
+	struct ena_get_feature_rsp get_feature;
375
+	/** Get statistics */
376
+	struct ena_get_stats_rsp get_stats;
377
+	/** Padding */
378
+	uint8_t pad[64];
379
+};
380
+
381
+/** Admin queue */
382
+struct ena_aq {
383
+	/** Requests */
384
+	union ena_aq_req *req;
385
+	/** Producer counter */
386
+	unsigned int prod;
387
+};
388
+
389
+/** Admin completion queue */
390
+struct ena_acq {
391
+	/** Responses */
392
+	union ena_acq_rsp *rsp;
393
+	/** Consumer counter */
394
+	unsigned int cons;
395
+	/** Phase */
396
+	unsigned int phase;
397
+};
398
+
399
+/** Transmit submission queue entry */
400
+struct ena_tx_sqe {
401
+	/** Length */
402
+	uint16_t len;
403
+	/** Reserved */
404
+	uint8_t reserved_a;
405
+	/** Flags */
406
+	uint8_t flags;
407
+	/** Reserved */
408
+	uint8_t reserved_b[3];
409
+	/** Request identifier */
410
+	uint8_t id;
411
+	/** Address */
412
+	uint64_t address;
413
+} __attribute__ (( packed ));
414
+
415
+/** Receive submission queue entry */
416
+struct ena_rx_sqe {
417
+	/** Length */
418
+	uint16_t len;
419
+	/** Reserved */
420
+	uint8_t reserved_a;
421
+	/** Flags */
422
+	uint8_t flags;
423
+	/** Request identifier */
424
+	uint16_t id;
425
+	/** Reserved */
426
+	uint8_t reserved_b[2];
427
+	/** Address */
428
+	uint64_t address;
429
+} __attribute__ (( packed ));
430
+
431
+/** Submission queue ownership phase flag */
432
+#define ENA_SQE_PHASE 0x01
433
+
434
+/** This is the first descriptor */
435
+#define ENA_SQE_FIRST 0x04
436
+
437
+/** This is the last descriptor */
438
+#define ENA_SQE_LAST 0x08
439
+
440
+/** Request completion */
441
+#define ENA_SQE_CPL 0x10
442
+
443
+/** Transmit completion queue entry */
444
+struct ena_tx_cqe {
445
+	/** Request identifier */
446
+	uint16_t id;
447
+	/** Status */
448
+	uint8_t status;
449
+	/** Flags */
450
+	uint8_t flags;
451
+	/** Reserved */
452
+	uint8_t reserved[2];
453
+	/** Consumer index */
454
+	uint16_t cons;
455
+} __attribute__ (( packed ));
456
+
457
+/** Receive completion queue entry */
458
+struct ena_rx_cqe {
459
+	/** Reserved */
460
+	uint8_t reserved_a[3];
461
+	/** Flags */
462
+	uint8_t flags;
463
+	/** Length */
464
+	uint16_t len;
465
+	/** Request identifier */
466
+	uint16_t id;
467
+	/** Reserved */
468
+	uint8_t reserved_b[8];
469
+} __attribute__ (( packed ));
470
+
471
+/** Completion queue ownership phase flag */
472
+#define ENA_CQE_PHASE 0x01
473
+
474
+/** Submission queue */
475
+struct ena_sq {
476
+	/** Entries */
477
+	union {
478
+		/** Transmit submission queue entries */
479
+		struct ena_tx_sqe *tx;
480
+		/** Receive submission queue entries */
481
+		struct ena_rx_sqe *rx;
482
+		/** Raw data */
483
+		void *raw;
484
+	} sqe;
485
+	/** Doorbell register offset */
486
+	unsigned int doorbell;
487
+	/** Total length of entries */
488
+	size_t len;
489
+	/** Producer counter */
490
+	unsigned int prod;
491
+	/** Phase */
492
+	unsigned int phase;
493
+	/** Submission queue identifier */
494
+	uint16_t id;
495
+	/** Direction */
496
+	uint8_t direction;
497
+	/** Number of entries */
498
+	uint8_t count;
499
+};
500
+
501
+/**
502
+ * Initialise submission queue
503
+ *
504
+ * @v sq		Submission queue
505
+ * @v direction		Direction
506
+ * @v count		Number of entries
507
+ * @v size		Size of each entry
508
+ */
509
+static inline __attribute__ (( always_inline )) void
510
+ena_sq_init ( struct ena_sq *sq, unsigned int direction, unsigned int count,
511
+	      size_t size ) {
512
+
513
+	sq->len = ( count * size );
514
+	sq->direction = direction;
515
+	sq->count = count;
516
+}
517
+
518
+/** Completion queue */
519
+struct ena_cq {
520
+	/** Entries */
521
+	union {
522
+		/** Transmit completion queue entries */
523
+		struct ena_tx_cqe *tx;
524
+		/** Receive completion queue entries */
525
+		struct ena_rx_cqe *rx;
526
+		/** Raw data */
527
+		void *raw;
528
+	} cqe;
529
+	/** Doorbell register offset */
530
+	unsigned int doorbell;
531
+	/** Total length of entries */
532
+	size_t len;
533
+	/** Consumer counter */
534
+	unsigned int cons;
535
+	/** Phase */
536
+	unsigned int phase;
537
+	/** Completion queue identifier */
538
+	uint16_t id;
539
+	/** Entry size (in 32-bit words) */
540
+	uint8_t size;
541
+	/** Requested number of entries */
542
+	uint8_t requested;
543
+	/** Actual number of entries */
544
+	uint8_t actual;
545
+	/** Actual number of entries minus one */
546
+	uint8_t mask;
547
+};
548
+
549
+/**
550
+ * Initialise completion queue
551
+ *
552
+ * @v cq		Completion queue
553
+ * @v count		Number of entries
554
+ * @v size		Size of each entry
555
+ */
556
+static inline __attribute__ (( always_inline )) void
557
+ena_cq_init ( struct ena_cq *cq, unsigned int count, size_t size ) {
558
+
559
+	cq->len = ( count * size );
560
+	cq->size = ( size / sizeof ( uint32_t ) );
561
+	cq->requested = count;
562
+}
563
+
564
+/** Queue pair */
565
+struct ena_qp {
566
+	/** Submission queue */
567
+	struct ena_sq sq;
568
+	/** Completion queue */
569
+	struct ena_cq cq;
570
+};
571
+
572
+/** An ENA network card */
573
+struct ena_nic {
574
+	/** Registers */
575
+	void *regs;
576
+	/** Admin queue */
577
+	struct ena_aq aq;
578
+	/** Admin completion queue */
579
+	struct ena_acq acq;
580
+	/** Transmit queue */
581
+	struct ena_qp tx;
582
+	/** Receive queue */
583
+	struct ena_qp rx;
584
+	/** Receive I/O buffers */
585
+	struct io_buffer *rx_iobuf[ENA_RX_COUNT];
586
+};
587
+
588
+#endif /* _ENA_H */

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

@@ -202,6 +202,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
202 202
 #define ERRFILE_exanic		     ( ERRFILE_DRIVER | 0x00c60000 )
203 203
 #define ERRFILE_smscusb		     ( ERRFILE_DRIVER | 0x00c70000 )
204 204
 #define ERRFILE_lan78xx		     ( ERRFILE_DRIVER | 0x00c80000 )
205
+#define ERRFILE_ena		     ( ERRFILE_DRIVER | 0x00c90000 )
205 206
 
206 207
 #define ERRFILE_aoe			( ERRFILE_NET | 0x00000000 )
207 208
 #define ERRFILE_arp			( ERRFILE_NET | 0x00010000 )

Loading…
Cancel
Save