iPXE
ena.h
Go to the documentation of this file.
00001 #ifndef _ENA_H
00002 #define _ENA_H
00003 
00004 /** @file
00005  *
00006  * Amazon ENA network driver
00007  *
00008  */
00009 
00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00011 
00012 #include <stdint.h>
00013 #include <ipxe/if_ether.h>
00014 
00015 /** BAR size */
00016 #define ENA_BAR_SIZE 16384
00017 
00018 /** Queue alignment */
00019 #define ENA_ALIGN 4096
00020 
00021 /** Number of admin queue entries */
00022 #define ENA_AQ_COUNT 2
00023 
00024 /** Number of admin completion queue entries */
00025 #define ENA_ACQ_COUNT 2
00026 
00027 /** Number of transmit queue entries */
00028 #define ENA_TX_COUNT 16
00029 
00030 /** Number of receive queue entries */
00031 #define ENA_RX_COUNT 16
00032 
00033 /** Base address low register offset */
00034 #define ENA_BASE_LO 0x0
00035 
00036 /** Base address high register offset */
00037 #define ENA_BASE_HI 0x4
00038 
00039 /** Capability register value */
00040 #define ENA_CAPS( count, size ) ( ( (size) << 16 ) | ( (count) << 0 ) )
00041 
00042 /** Admin queue base address register */
00043 #define ENA_AQ_BASE 0x10
00044 
00045 /** Admin queue capabilities register */
00046 #define ENA_AQ_CAPS 0x18
00047 
00048 /** Admin completion queue base address register */
00049 #define ENA_ACQ_BASE 0x20
00050 
00051 /** Admin completion queue capabilities register */
00052 #define ENA_ACQ_CAPS 0x28
00053 
00054 /** Admin queue doorbell register */
00055 #define ENA_AQ_DB 0x2c
00056 
00057 /** Maximum time to wait for admin requests */
00058 #define ENA_ADMIN_MAX_WAIT_MS 5000
00059 
00060 /** Device control register */
00061 #define ENA_CTRL 0x54
00062 #define ENA_CTRL_RESET 0x00000001UL     /**< Reset */
00063 
00064 /** Maximum time to wait for reset */
00065 #define ENA_RESET_MAX_WAIT_MS 1000
00066 
00067 /** Device status register */
00068 #define ENA_STAT 0x58
00069 #define ENA_STAT_READY 0x00000001UL     /**< Ready */
00070 
00071 /** Admin queue entry header */
00072 struct ena_aq_header {
00073         /** Request identifier */
00074         uint8_t id;
00075         /** Reserved */
00076         uint8_t reserved;
00077         /** Opcode */
00078         uint8_t opcode;
00079         /** Flags */
00080         uint8_t flags;
00081 } __attribute__ (( packed ));
00082 
00083 /** Admin queue ownership phase flag */
00084 #define ENA_AQ_PHASE 0x01
00085 
00086 /** Admin completion queue entry header */
00087 struct ena_acq_header {
00088         /** Request identifier */
00089         uint8_t id;
00090         /** Reserved */
00091         uint8_t reserved;
00092         /** Status */
00093         uint8_t status;
00094         /** Flags */
00095         uint8_t flags;
00096         /** Extended status */
00097         uint16_t ext;
00098         /** Consumer index */
00099         uint16_t cons;
00100 } __attribute__ (( packed ));
00101 
00102 /** Admin completion queue ownership phase flag */
00103 #define ENA_ACQ_PHASE 0x01
00104 
00105 /** Device attributes */
00106 #define ENA_DEVICE_ATTRIBUTES 1
00107 
00108 /** Device attributes */
00109 struct ena_device_attributes {
00110         /** Implementation */
00111         uint32_t implementation;
00112         /** Device version */
00113         uint32_t version;
00114         /** Supported features */
00115         uint32_t features;
00116         /** Reserved */
00117         uint8_t reserved_a[4];
00118         /** Physical address width */
00119         uint32_t physical;
00120         /** Virtual address width */
00121         uint32_t virtual;
00122         /** MAC address */
00123         uint8_t mac[ETH_ALEN];
00124         /** Reserved */
00125         uint8_t reserved_b[2];
00126         /** Maximum MTU */
00127         uint32_t mtu;
00128 } __attribute__ (( packed ));
00129 
00130 /** Feature */
00131 union ena_feature {
00132         /** Device attributes */
00133         struct ena_device_attributes device;
00134 };
00135 
00136 /** Submission queue direction */
00137 enum ena_sq_direction {
00138         /** Transmit */
00139         ENA_SQ_TX = 0x20,
00140         /** Receive */
00141         ENA_SQ_RX = 0x40,
00142 };
00143 
00144 /** Create submission queue */
00145 #define ENA_CREATE_SQ 1
00146 
00147 /** Create submission queue request */
00148 struct ena_create_sq_req {
00149         /** Header */
00150         struct ena_aq_header header;
00151         /** Direction */
00152         uint8_t direction;
00153         /** Reserved */
00154         uint8_t reserved_a;
00155         /** Policy */
00156         uint16_t policy;
00157         /** Completion queue identifier */
00158         uint16_t cq_id;
00159         /** Number of entries */
00160         uint16_t count;
00161         /** Base address */
00162         uint64_t address;
00163         /** Writeback address */
00164         uint64_t writeback;
00165         /** Reserved */
00166         uint8_t reserved_b[8];
00167 } __attribute__ (( packed ));
00168 
00169 /** Submission queue policy */
00170 enum ena_sq_policy {
00171         /** Use host memory */
00172         ENA_SQ_HOST_MEMORY = 0x0001,
00173         /** Memory is contiguous */
00174         ENA_SQ_CONTIGUOUS = 0x0100,
00175 };
00176 
00177 /** Create submission queue response */
00178 struct ena_create_sq_rsp {
00179         /** Header */
00180         struct ena_acq_header header;
00181         /** Submission queue identifier */
00182         uint16_t id;
00183         /** Reserved */
00184         uint8_t reserved[2];
00185         /** Doorbell register offset */
00186         uint32_t doorbell;
00187         /** LLQ descriptor ring offset */
00188         uint32_t llq_desc;
00189         /** LLQ header offset */
00190         uint32_t llq_data;
00191 } __attribute__ (( packed ));
00192 
00193 /** Destroy submission queue */
00194 #define ENA_DESTROY_SQ 2
00195 
00196 /** Destroy submission queue request */
00197 struct ena_destroy_sq_req {
00198         /** Header */
00199         struct ena_aq_header header;
00200         /** Submission queue identifier */
00201         uint16_t id;
00202         /** Direction */
00203         uint8_t direction;
00204         /** Reserved */
00205         uint8_t reserved;
00206 } __attribute__ (( packed ));
00207 
00208 /** Destroy submission queue response */
00209 struct ena_destroy_sq_rsp {
00210         /** Header */
00211         struct ena_acq_header header;
00212 } __attribute__ (( packed ));
00213 
00214 /** Create completion queue */
00215 #define ENA_CREATE_CQ 3
00216 
00217 /** Create completion queue request */
00218 struct ena_create_cq_req {
00219         /** Header */
00220         struct ena_aq_header header;
00221         /** Interrupts enabled */
00222         uint8_t intr;
00223         /** Entry size (in 32-bit words) */
00224         uint8_t size;
00225         /** Number of entries */
00226         uint16_t count;
00227         /** MSI-X vector */
00228         uint32_t vector;
00229         /** Base address */
00230         uint64_t address;
00231 } __attribute__ (( packed ));
00232 
00233 /** Create completion queue response */
00234 struct ena_create_cq_rsp {
00235         /** Header */
00236         struct ena_acq_header header;
00237         /** Completion queue identifier */
00238         uint16_t id;
00239         /** Actual number of entries */
00240         uint16_t count;
00241         /** NUMA node register offset */
00242         uint32_t node;
00243         /** Doorbell register offset */
00244         uint32_t doorbell;
00245         /** Interrupt unmask register offset */
00246         uint32_t intr;
00247 } __attribute__ (( packed ));
00248 
00249 /** Destroy completion queue */
00250 #define ENA_DESTROY_CQ 4
00251 
00252 /** Destroy completion queue request */
00253 struct ena_destroy_cq_req {
00254         /** Header */
00255         struct ena_aq_header header;
00256         /** Completion queue identifier */
00257         uint16_t id;
00258         /** Reserved */
00259         uint8_t reserved[2];
00260 } __attribute__ (( packed ));
00261 
00262 /** Destroy completion queue response */
00263 struct ena_destroy_cq_rsp {
00264         /** Header */
00265         struct ena_acq_header header;
00266 } __attribute__ (( packed ));
00267 
00268 /** Get feature */
00269 #define ENA_GET_FEATURE 8
00270 
00271 /** Get feature request */
00272 struct ena_get_feature_req {
00273         /** Header */
00274         struct ena_aq_header header;
00275         /** Length */
00276         uint32_t len;
00277         /** Address */
00278         uint64_t address;
00279         /** Flags */
00280         uint8_t flags;
00281         /** Feature identifier */
00282         uint8_t id;
00283         /** Reserved */
00284         uint8_t reserved[2];
00285 } __attribute__ (( packed ));
00286 
00287 /** Get feature response */
00288 struct ena_get_feature_rsp {
00289         /** Header */
00290         struct ena_acq_header header;
00291         /** Feature */
00292         union ena_feature feature;
00293 } __attribute__ (( packed ));
00294 
00295 /** Get statistics */
00296 #define ENA_GET_STATS 11
00297 
00298 /** Get statistics request */
00299 struct ena_get_stats_req {
00300         /** Header */
00301         struct ena_aq_header header;
00302         /** Reserved */
00303         uint8_t reserved_a[12];
00304         /** Type */
00305         uint8_t type;
00306         /** Scope */
00307         uint8_t scope;
00308         /** Reserved */
00309         uint8_t reserved_b[2];
00310         /** Queue ID */
00311         uint16_t queue;
00312         /** Device ID */
00313         uint16_t device;
00314 } __attribute__ (( packed ));
00315 
00316 /** Basic statistics */
00317 #define ENA_STATS_TYPE_BASIC 0
00318 
00319 /** Ethernet statistics */
00320 #define ENA_STATS_SCOPE_ETH 1
00321 
00322 /** My device */
00323 #define ENA_DEVICE_MINE 0xffff
00324 
00325 /** Get statistics response */
00326 struct ena_get_stats_rsp {
00327         /** Header */
00328         struct ena_acq_header header;
00329         /** Transmit byte count */
00330         uint64_t tx_bytes;
00331         /** Transmit packet count */
00332         uint64_t tx_packets;
00333         /** Receive byte count */
00334         uint64_t rx_bytes;
00335         /** Receive packet count */
00336         uint64_t rx_packets;
00337         /** Receive drop count */
00338         uint64_t rx_drops;
00339 } __attribute__ (( packed ));
00340 
00341 /** Admin queue request */
00342 union ena_aq_req {
00343         /** Header */
00344         struct ena_aq_header header;
00345         /** Create submission queue */
00346         struct ena_create_sq_req create_sq;
00347         /** Destroy submission queue */
00348         struct ena_destroy_sq_req destroy_sq;
00349         /** Create completion queue */
00350         struct ena_create_cq_req create_cq;
00351         /** Destroy completion queue */
00352         struct ena_destroy_cq_req destroy_cq;
00353         /** Get feature */
00354         struct ena_get_feature_req get_feature;
00355         /** Get statistics */
00356         struct ena_get_stats_req get_stats;
00357         /** Padding */
00358         uint8_t pad[64];
00359 };
00360 
00361 /** Admin completion queue response */
00362 union ena_acq_rsp {
00363         /** Header */
00364         struct ena_acq_header header;
00365         /** Create submission queue */
00366         struct ena_create_sq_rsp create_sq;
00367         /** Destroy submission queue */
00368         struct ena_destroy_sq_rsp destroy_sq;
00369         /** Create completion queue */
00370         struct ena_create_cq_rsp create_cq;
00371         /** Destroy completion queue */
00372         struct ena_destroy_cq_rsp destroy_cq;
00373         /** Get feature */
00374         struct ena_get_feature_rsp get_feature;
00375         /** Get statistics */
00376         struct ena_get_stats_rsp get_stats;
00377         /** Padding */
00378         uint8_t pad[64];
00379 };
00380 
00381 /** Admin queue */
00382 struct ena_aq {
00383         /** Requests */
00384         union ena_aq_req *req;
00385         /** Producer counter */
00386         unsigned int prod;
00387 };
00388 
00389 /** Admin completion queue */
00390 struct ena_acq {
00391         /** Responses */
00392         union ena_acq_rsp *rsp;
00393         /** Consumer counter */
00394         unsigned int cons;
00395         /** Phase */
00396         unsigned int phase;
00397 };
00398 
00399 /** Transmit submission queue entry */
00400 struct ena_tx_sqe {
00401         /** Length */
00402         uint16_t len;
00403         /** Reserved */
00404         uint8_t reserved_a;
00405         /** Flags */
00406         uint8_t flags;
00407         /** Reserved */
00408         uint8_t reserved_b[3];
00409         /** Request identifier */
00410         uint8_t id;
00411         /** Address */
00412         uint64_t address;
00413 } __attribute__ (( packed ));
00414 
00415 /** Receive submission queue entry */
00416 struct ena_rx_sqe {
00417         /** Length */
00418         uint16_t len;
00419         /** Reserved */
00420         uint8_t reserved_a;
00421         /** Flags */
00422         uint8_t flags;
00423         /** Request identifier */
00424         uint16_t id;
00425         /** Reserved */
00426         uint8_t reserved_b[2];
00427         /** Address */
00428         uint64_t address;
00429 } __attribute__ (( packed ));
00430 
00431 /** Submission queue ownership phase flag */
00432 #define ENA_SQE_PHASE 0x01
00433 
00434 /** This is the first descriptor */
00435 #define ENA_SQE_FIRST 0x04
00436 
00437 /** This is the last descriptor */
00438 #define ENA_SQE_LAST 0x08
00439 
00440 /** Request completion */
00441 #define ENA_SQE_CPL 0x10
00442 
00443 /** Transmit completion queue entry */
00444 struct ena_tx_cqe {
00445         /** Request identifier */
00446         uint16_t id;
00447         /** Status */
00448         uint8_t status;
00449         /** Flags */
00450         uint8_t flags;
00451         /** Reserved */
00452         uint8_t reserved[2];
00453         /** Consumer index */
00454         uint16_t cons;
00455 } __attribute__ (( packed ));
00456 
00457 /** Receive completion queue entry */
00458 struct ena_rx_cqe {
00459         /** Reserved */
00460         uint8_t reserved_a[3];
00461         /** Flags */
00462         uint8_t flags;
00463         /** Length */
00464         uint16_t len;
00465         /** Request identifier */
00466         uint16_t id;
00467         /** Reserved */
00468         uint8_t reserved_b[8];
00469 } __attribute__ (( packed ));
00470 
00471 /** Completion queue ownership phase flag */
00472 #define ENA_CQE_PHASE 0x01
00473 
00474 /** Submission queue */
00475 struct ena_sq {
00476         /** Entries */
00477         union {
00478                 /** Transmit submission queue entries */
00479                 struct ena_tx_sqe *tx;
00480                 /** Receive submission queue entries */
00481                 struct ena_rx_sqe *rx;
00482                 /** Raw data */
00483                 void *raw;
00484         } sqe;
00485         /** Doorbell register offset */
00486         unsigned int doorbell;
00487         /** Total length of entries */
00488         size_t len;
00489         /** Producer counter */
00490         unsigned int prod;
00491         /** Phase */
00492         unsigned int phase;
00493         /** Submission queue identifier */
00494         uint16_t id;
00495         /** Direction */
00496         uint8_t direction;
00497         /** Number of entries */
00498         uint8_t count;
00499 };
00500 
00501 /**
00502  * Initialise submission queue
00503  *
00504  * @v sq                Submission queue
00505  * @v direction         Direction
00506  * @v count             Number of entries
00507  * @v size              Size of each entry
00508  */
00509 static inline __attribute__ (( always_inline )) void
00510 ena_sq_init ( struct ena_sq *sq, unsigned int direction, unsigned int count,
00511               size_t size ) {
00512 
00513         sq->len = ( count * size );
00514         sq->direction = direction;
00515         sq->count = count;
00516 }
00517 
00518 /** Completion queue */
00519 struct ena_cq {
00520         /** Entries */
00521         union {
00522                 /** Transmit completion queue entries */
00523                 struct ena_tx_cqe *tx;
00524                 /** Receive completion queue entries */
00525                 struct ena_rx_cqe *rx;
00526                 /** Raw data */
00527                 void *raw;
00528         } cqe;
00529         /** Doorbell register offset */
00530         unsigned int doorbell;
00531         /** Total length of entries */
00532         size_t len;
00533         /** Consumer counter */
00534         unsigned int cons;
00535         /** Phase */
00536         unsigned int phase;
00537         /** Completion queue identifier */
00538         uint16_t id;
00539         /** Entry size (in 32-bit words) */
00540         uint8_t size;
00541         /** Requested number of entries */
00542         uint8_t requested;
00543         /** Actual number of entries */
00544         uint8_t actual;
00545         /** Actual number of entries minus one */
00546         uint8_t mask;
00547 };
00548 
00549 /**
00550  * Initialise completion queue
00551  *
00552  * @v cq                Completion queue
00553  * @v count             Number of entries
00554  * @v size              Size of each entry
00555  */
00556 static inline __attribute__ (( always_inline )) void
00557 ena_cq_init ( struct ena_cq *cq, unsigned int count, size_t size ) {
00558 
00559         cq->len = ( count * size );
00560         cq->size = ( size / sizeof ( uint32_t ) );
00561         cq->requested = count;
00562 }
00563 
00564 /** Queue pair */
00565 struct ena_qp {
00566         /** Submission queue */
00567         struct ena_sq sq;
00568         /** Completion queue */
00569         struct ena_cq cq;
00570 };
00571 
00572 /** An ENA network card */
00573 struct ena_nic {
00574         /** Registers */
00575         void *regs;
00576         /** Admin queue */
00577         struct ena_aq aq;
00578         /** Admin completion queue */
00579         struct ena_acq acq;
00580         /** Transmit queue */
00581         struct ena_qp tx;
00582         /** Receive queue */
00583         struct ena_qp rx;
00584         /** Receive I/O buffers */
00585         struct io_buffer *rx_iobuf[ENA_RX_COUNT];
00586 };
00587 
00588 #endif /* _ENA_H */