| #ifndef _GVE_H | |
| #define _GVE_H | |
| /** @file | |
| * | |
| * Google Virtual Ethernet network driver | |
| * | |
| * The Google Virtual Ethernet NIC (GVE or gVNIC) is found only in | |
| * Google Cloud instances. There is essentially zero documentation | |
| * available beyond the mostly uncommented source code in the Linux | |
| * kernel. | |
| */ | |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | |
| #include <stdint.h> | |
| #include <ipxe/dma.h> | |
| #include <ipxe/pci.h> | |
| #include <ipxe/pcimsix.h> | |
| #include <ipxe/in.h> | |
| #include <ipxe/process.h> | |
| #include <ipxe/retry.h> | |
| struct gve_nic; | |
| /** | |
| * A Google Cloud MAC address | |
| * | |
| * Google Cloud locally assigned MAC addresses encode the local IPv4 | |
| * address in the trailing 32 bits, presumably as a performance | |
| * optimisation to allow ARP resolution to be skipped by a suitably | |
| * aware network stack. | |
| */ | |
| struct google_mac { | |
| /** Reserved */ | |
| uint8_t reserved[2]; | |
| /** Local IPv4 address */ | |
| struct in_addr in; | |
| } __attribute__ (( packed )); | |
| /** Page size */ | |
| #define GVE_PAGE_SIZE 0x1000 | |
| /** | |
| * Address alignment | |
| * | |
| * All DMA data structure base addresses seem to need to be aligned to | |
| * a page boundary. (This is not documented anywhere, but is inferred | |
| * from existing source code and experimentation.) | |
| */ | |
| #define GVE_ALIGN GVE_PAGE_SIZE | |
| /** Configuration BAR */ | |
| #define GVE_CFG_BAR PCI_BASE_ADDRESS_0 | |
| /** | |
| * Configuration BAR size | |
| * | |
| * All registers within the configuration BAR are big-endian. | |
| */ | |
| #define GVE_CFG_SIZE 0x1000 | |
| /** Device status */ | |
| #define GVE_CFG_DEVSTAT 0x0000 | |
| #define GVE_CFG_DEVSTAT_RESET 0x00000010UL /**< Device is reset */ | |
| /** Driver status */ | |
| #define GVE_CFG_DRVSTAT 0x0004 | |
| #define GVE_CFG_DRVSTAT_RUN 0x00000001UL /**< Run admin queue */ | |
| /** Maximum time to wait for reset */ | |
| #define GVE_RESET_MAX_WAIT_MS 500 | |
| /** Admin queue page frame number (for older devices) */ | |
| #define GVE_CFG_ADMIN_PFN 0x0010 | |
| /** Admin queue doorbell */ | |
| #define GVE_CFG_ADMIN_DB 0x0014 | |
| /** Admin queue event counter */ | |
| #define GVE_CFG_ADMIN_EVT 0x0018 | |
| /** Driver version (8-bit register) */ | |
| #define GVE_CFG_VERSION 0x001f | |
| /** Admin queue base address high 32 bits */ | |
| #define GVE_CFG_ADMIN_BASE_HI 0x0020 | |
| /** Admin queue base address low 32 bits */ | |
| #define GVE_CFG_ADMIN_BASE_LO 0x0024 | |
| /** Admin queue base address length (16-bit register) */ | |
| #define GVE_CFG_ADMIN_LEN 0x0028 | |
| /** Doorbell BAR */ | |
| #define GVE_DB_BAR PCI_BASE_ADDRESS_2 | |
| /** | |
| * Admin queue entry header | |
| * | |
| * All values within admin queue entries are big-endian. | |
| */ | |
| struct gve_admin_header { | |
| /** Reserved */ | |
| uint8_t reserved[3]; | |
| /** Operation code */ | |
| uint8_t opcode; | |
| /** Status */ | |
| uint32_t status; | |
| } __attribute__ (( packed )); | |
| /** Command succeeded */ | |
| #define GVE_ADMIN_STATUS_OK 0x00000001 | |
| /** Simple admin command */ | |
| struct gve_admin_simple { | |
| /** Header */ | |
| struct gve_admin_header hdr; | |
| /** ID */ | |
| uint32_t id; | |
| } __attribute__ (( packed )); | |
| /** Describe device command */ | |
| #define GVE_ADMIN_DESCRIBE 0x0001 | |
| /** Describe device command */ | |
| struct gve_admin_describe { | |
| /** Header */ | |
| struct gve_admin_header hdr; | |
| /** Descriptor buffer address */ | |
| uint64_t addr; | |
| /** Descriptor version */ | |
| uint32_t ver; | |
| /** Descriptor maximum length */ | |
| uint32_t len; | |
| } __attribute__ (( packed )); | |
| /** Device descriptor version */ | |
| #define GVE_ADMIN_DESCRIBE_VER 1 | |
| /** Device descriptor */ | |
| struct gve_device_descriptor { | |
| /** Reserved */ | |
| uint8_t reserved_a[10]; | |
| /** Number of transmit queue entries */ | |
| uint16_t tx_count; | |
| /** Number of receive queue entries */ | |
| uint16_t rx_count; | |
| /** Reserved */ | |
| uint8_t reserved_b[2]; | |
| /** Maximum transmit unit */ | |
| uint16_t mtu; | |
| /** Number of event counters */ | |
| uint16_t counters; | |
| /** Reserved */ | |
| uint8_t reserved_c[4]; | |
| /** MAC address */ | |
| struct google_mac mac; | |
| /** Number of device options */ | |
| uint16_t opt_count; | |
| /** Total length (including this header) */ | |
| uint16_t len; | |
| /** Reserved */ | |
| uint8_t reserved_d[6]; | |
| /** Space for options | |
| * | |
| * There is no specified upper limit, and no negotiation | |
| * mechanism for the amount of space required. We allow space | |
| * for seems like a reasonable number of options. | |
| */ | |
| uint8_t opts[216]; | |
| } __attribute__ (( packed )); | |
| /** Device option header */ | |
| struct gve_option { | |
| /** Option ID */ | |
| uint16_t id; | |
| /** Length (excluding this header) */ | |
| uint16_t len; | |
| /** Required feature mask | |
| * | |
| * The purpose of this field is remarkably unclear. The Linux | |
| * kernel driver does define enum gve_dev_opt_req_feat_mask, | |
| * but every member of this enum has a zero value. | |
| */ | |
| uint32_t required; | |
| } __attribute__ (( packed )); | |
| /** In-order descriptor queues with raw DMA addressing */ | |
| #define GVE_OPT_GQI_RDA 0x02 | |
| /** In-order descriptor queues with queue page list addressing */ | |
| #define GVE_OPT_GQI_QPL 0x03 | |
| /** Out-of-order descriptor queues with raw DMA addressing */ | |
| #define GVE_OPT_DQO_RDA 0x04 | |
| /** Out-of-order descriptor queues with queue page list addressing */ | |
| #define GVE_OPT_DQO_QPL 0x07 | |
| /** Configure device resources command */ | |
| #define GVE_ADMIN_CONFIGURE 0x0002 | |
| /** Configure device resources command */ | |
| struct gve_admin_configure { | |
| /** Header */ | |
| struct gve_admin_header hdr; | |
| /** Event counter array */ | |
| uint64_t events; | |
| /** IRQ doorbell address */ | |
| uint64_t irqs; | |
| /** Number of event counters */ | |
| uint32_t num_events; | |
| /** Number of IRQ doorbells */ | |
| uint32_t num_irqs; | |
| /** IRQ doorbell stride */ | |
| uint32_t irq_stride; | |
| /** MSI-X base index */ | |
| uint32_t msix_base; | |
| /** Descriptor queue format */ | |
| uint8_t format; | |
| /** Reserved */ | |
| uint8_t reserved[7]; | |
| } __attribute__ (( packed )); | |
| /** Descriptor queue format */ | |
| #define GVE_FORMAT( mode ) ( (mode) + 1 ) | |
| /** Register page list command */ | |
| #define GVE_ADMIN_REGISTER 0x0003 | |
| /** Register page list command */ | |
| struct gve_admin_register { | |
| /** Header */ | |
| struct gve_admin_header hdr; | |
| /** Page list ID */ | |
| uint32_t id; | |
| /** Number of pages */ | |
| uint32_t count; | |
| /** Address list address */ | |
| uint64_t addr; | |
| /** Page size */ | |
| uint64_t size; | |
| } __attribute__ (( packed )); | |
| /** | |
| * Maximum number of pages per queue | |
| * | |
| * This is a policy decision. Must be sufficient to allow for both | |
| * the transmit and receive queue fill levels. | |
| */ | |
| #define GVE_QPL_MAX 32 | |
| /** Page list */ | |
| struct gve_pages { | |
| /** Page address */ | |
| uint64_t addr[GVE_QPL_MAX]; | |
| } __attribute__ (( packed )); | |
| /** Unregister page list command */ | |
| #define GVE_ADMIN_UNREGISTER 0x0004 | |
| /** Create transmit queue command */ | |
| #define GVE_ADMIN_CREATE_TX 0x0005 | |
| /** Create transmit queue command */ | |
| struct gve_admin_create_tx { | |
| /** Header */ | |
| struct gve_admin_header hdr; | |
| /** Queue ID */ | |
| uint32_t id; | |
| /** Reserved */ | |
| uint8_t reserved_a[4]; | |
| /** Queue resources address */ | |
| uint64_t res; | |
| /** Descriptor ring address */ | |
| uint64_t desc; | |
| /** Queue page list ID */ | |
| uint32_t qpl_id; | |
| /** Notification channel ID */ | |
| uint32_t notify_id; | |
| /** Completion ring address */ | |
| uint64_t cmplt; | |
| /** Number of descriptor ring entries */ | |
| uint16_t desc_count; | |
| /** Number of completion ring entries */ | |
| uint16_t cmplt_count; | |
| /** Reserved */ | |
| uint8_t reserved_b[4]; | |
| } __attribute__ (( packed )); | |
| /** Create receive queue command */ | |
| #define GVE_ADMIN_CREATE_RX 0x0006 | |
| /** Create receive queue command */ | |
| struct gve_admin_create_rx { | |
| /** Header */ | |
| struct gve_admin_header hdr; | |
| /** Queue ID */ | |
| uint32_t id; | |
| /** Index */ | |
| uint32_t index; | |
| /** Reserved */ | |
| uint8_t reserved_a[4]; | |
| /** Notification channel ID */ | |
| uint32_t notify_id; | |
| /** Queue resources address */ | |
| uint64_t res; | |
| /** Completion ring address */ | |
| uint64_t cmplt; | |
| /** Descriptor ring address */ | |
| uint64_t desc; | |
| /** Queue page list ID */ | |
| uint32_t qpl_id; | |
| /** Number of descriptor ring entries */ | |
| uint16_t desc_count; | |
| /** Packet buffer size */ | |
| uint16_t bufsz; | |
| /** Number of completion ring entries */ | |
| uint16_t cmplt_count; | |
| /** Reserved */ | |
| uint8_t reserved[6]; | |
| } __attribute__ (( packed )); | |
| /** Destroy transmit queue command */ | |
| #define GVE_ADMIN_DESTROY_TX 0x0007 | |
| /** Destroy receive queue command */ | |
| #define GVE_ADMIN_DESTROY_RX 0x0008 | |
| /** Deconfigure device resources command */ | |
| #define GVE_ADMIN_DECONFIGURE 0x0009 | |
| /** An admin queue command */ | |
| union gve_admin_command { | |
| /** Header */ | |
| struct gve_admin_header hdr; | |
| /** Simple command */ | |
| struct gve_admin_simple simple; | |
| /** Describe device */ | |
| struct gve_admin_describe desc; | |
| /** Configure device resources */ | |
| struct gve_admin_configure conf; | |
| /** Register page list */ | |
| struct gve_admin_register reg; | |
| /** Create transmit queue */ | |
| struct gve_admin_create_tx create_tx; | |
| /** Create receive queue */ | |
| struct gve_admin_create_rx create_rx; | |
| /** Padding */ | |
| uint8_t pad[64]; | |
| }; | |
| /** | |
| * Number of admin queue commands | |
| * | |
| * This is theoretically a policy decision. However, older revisions | |
| * of the hardware seem to have only the "admin queue page frame | |
| * number" register and no "admin queue length" register, with the | |
| * implication that the admin queue must be exactly one page in | |
| * length. | |
| * | |
| * Choose to use a one page (4kB) admin queue for both older and newer | |
| * versions of the hardware, to minimise variability. | |
| */ | |
| #define GVE_ADMIN_COUNT ( GVE_PAGE_SIZE / sizeof ( union gve_admin_command ) ) | |
| /** Admin queue */ | |
| struct gve_admin { | |
| /** Commands */ | |
| union gve_admin_command *cmd; | |
| /** Producer counter */ | |
| uint32_t prod; | |
| /** DMA mapping */ | |
| struct dma_mapping map; | |
| }; | |
| /** Scratch buffer for admin queue commands */ | |
| struct gve_scratch { | |
| /** Buffer contents */ | |
| union { | |
| /** Device descriptor */ | |
| struct gve_device_descriptor desc; | |
| /** Page address list */ | |
| struct gve_pages pages; | |
| } *buf; | |
| /** DMA mapping */ | |
| struct dma_mapping map; | |
| }; | |
| /** | |
| * An event counter | |
| * | |
| * Written by the device to indicate completions. The device chooses | |
| * which counter to use for each transmit queue, and stores the index | |
| * of the chosen counter in the queue resources. | |
| */ | |
| struct gve_event { | |
| /** Number of events that have occurred */ | |
| volatile uint32_t count; | |
| } __attribute__ (( packed )); | |
| /** Event counter array */ | |
| struct gve_events { | |
| /** Event counters */ | |
| struct gve_event *event; | |
| /** DMA mapping */ | |
| struct dma_mapping map; | |
| /** Actual number of event counters */ | |
| unsigned int count; | |
| }; | |
| /** An interrupt channel */ | |
| struct gve_irq { | |
| /** Interrupt doorbell index (within doorbell BAR) */ | |
| uint32_t db_idx; | |
| /** Reserved */ | |
| uint8_t reserved[60]; | |
| } __attribute__ (( packed )); | |
| /** | |
| * Number of interrupt channels | |
| * | |
| * We tell the device how many interrupt channels we have provided via | |
| * the "configure device resources" admin queue command. The device | |
| * will accept being given zero interrupt channels, but will | |
| * subsequently fail to create more than a single queue (either | |
| * transmit or receive). | |
| * | |
| * There is, of course, no documentation indicating how may interrupt | |
| * channels actually need to be provided. In the absence of evidence | |
| * to the contrary, assume that two channels (one for transmit, one | |
| * for receive) will be sufficient. | |
| */ | |
| #define GVE_IRQ_COUNT 2 | |
| /** Interrupt channel array */ | |
| struct gve_irqs { | |
| /** Interrupt channels */ | |
| struct gve_irq *irq; | |
| /** DMA mapping */ | |
| struct dma_mapping map; | |
| /** Interrupt doorbells */ | |
| volatile uint32_t *db[GVE_IRQ_COUNT]; | |
| }; | |
| /** Disable in-order queue interrupt */ | |
| #define GVE_GQI_IRQ_DISABLE 0x40000000UL | |
| /** Rearm out-of-order queue interrupt */ | |
| #define GVE_DQO_IRQ_REARM 0x00000019UL | |
| /** | |
| * Queue resources | |
| * | |
| * Written by the device to indicate the indices of the chosen event | |
| * counter and descriptor doorbell register. | |
| * | |
| * This appears to be a largely pointless data structure: the relevant | |
| * information is static for the lifetime of the queue and could | |
| * trivially have been returned in the response for the "create | |
| * transmit/receive queue" command, instead of requiring yet another | |
| * page-aligned coherent DMA buffer allocation. | |
| */ | |
| struct gve_resources { | |
| /** Descriptor doorbell index (within doorbell BAR) */ | |
| uint32_t db_idx; | |
| /** Event counter index (within event counter array) */ | |
| uint32_t evt_idx; | |
| /** Reserved */ | |
| uint8_t reserved[56]; | |
| } __attribute__ (( packed )); | |
| /** | |
| * Queue data buffer size | |
| * | |
| * In theory, we may specify the size of receive buffers. However, | |
| * the original version of the device seems not to have a parameter | |
| * for this, and assumes the use of half-page (2kB) buffers. Choose | |
| * to use this as the buffer size, on the assumption that older | |
| * devices will not support any other buffer size. | |
| */ | |
| #define GVE_BUF_SIZE ( GVE_PAGE_SIZE / 2 ) | |
| /** Number of data buffers per page */ | |
| #define GVE_BUF_PER_PAGE ( GVE_PAGE_SIZE / GVE_BUF_SIZE ) | |
| /** | |
| * Queue page list | |
| * | |
| * The device uses preregistered pages for fast-path DMA operations | |
| * (i.e. transmit and receive buffers). A list of device addresses | |
| * for each page must be registered before the transmit or receive | |
| * queue is created, and cannot subsequently be modified. | |
| * | |
| * The Linux driver allocates pages as DMA_TO_DEVICE or | |
| * DMA_FROM_DEVICE as appropriate, and uses dma_sync_single_for_cpu() | |
| * etc to ensure that data is copied to/from bounce buffers as needed. | |
| * | |
| * Unfortunately there is no such sync operation available within our | |
| * DMA API, since we are constrained by the limitations imposed by | |
| * EFI_PCI_IO_PROTOCOL. There is no way to synchronise a buffer | |
| * without also [un]mapping it, and no way to force the reuse of the | |
| * same device address for a subsequent remapping. We are therefore | |
| * constrained to use only DMA-coherent buffers, since this is the | |
| * only way we can repeatedly reuse the same device address. | |
| * | |
| * Newer versions of the gVNIC device support "raw DMA addressing | |
| * (RDA)", which is essentially a prebuilt queue page list covering | |
| * the whole of the guest address space. Unfortunately we cannot rely | |
| * on this, since older versions will not support it. | |
| * | |
| * Experimentation suggests that the device will accept a request to | |
| * create a queue page list covering the whole of the guest address | |
| * space via two giant "pages" of 2^63 bytes each. However, | |
| * experimentation also suggests that the device will accept any old | |
| * garbage value as the "page size". In the total absence of any | |
| * documentation, it is probably unsafe to conclude that the device is | |
| * bothering to look at or respect the "page size" parameter: it is | |
| * most likely just presuming the use of 4kB pages. | |
| */ | |
| struct gve_qpl { | |
| /** Page addresses */ | |
| void *data; | |
| /** Page mapping */ | |
| struct dma_mapping map; | |
| /** Number of pages */ | |
| unsigned int count; | |
| /** Queue page list ID */ | |
| unsigned int id; | |
| /** Queue page list base device address | |
| * | |
| * This will be zero in the GQI-QPL operating mode, or the DMA | |
| * address of the first page in any other operating mode. | |
| * (Despite its name, DQO-QPL still requires the use of raw | |
| * DMA addresses in transmit and receive descriptors.) | |
| */ | |
| physaddr_t base; | |
| }; | |
| /** Raw DMA addressing queue page list ID */ | |
| #define GVE_RAW_QPL 0xffffffff | |
| /** | |
| * Maximum number of transmit buffers | |
| * | |
| * This is a policy decision. | |
| */ | |
| #define GVE_TX_FILL 8 | |
| /** Transmit queue page list ID */ | |
| #define GVE_TX_QPL 0x18ae5458 | |
| /** Tranmsit queue interrupt channel */ | |
| #define GVE_TX_IRQ 0 | |
| /** A transmit or receive buffer descriptor */ | |
| struct gve_buffer { | |
| /** Address (within queue page list address space) */ | |
| uint64_t addr; | |
| } __attribute__ (( packed )); | |
| /** An in-order transmit descriptor */ | |
| struct gve_gqi_tx_descriptor { | |
| /** Type */ | |
| uint8_t type; | |
| /** Reserved */ | |
| uint8_t reserved_a[2]; | |
| /** Number of descriptors in this packet */ | |
| uint8_t count; | |
| /** Total length of this packet */ | |
| uint16_t total; | |
| /** Length of this descriptor */ | |
| uint16_t len; | |
| /** Buffer descriptor */ | |
| struct gve_buffer buf; | |
| } __attribute__ (( packed )); | |
| /** Start of packet transmit descriptor type */ | |
| #define GVE_GQI_TX_TYPE_START 0x00 | |
| /** Continuation of packet transmit descriptor type */ | |
| #define GVE_GQI_TX_TYPE_CONT 0x20 | |
| /** An out-of-order transmit tag | |
| * | |
| * From the hardware perspective, this is an opaque 15-bit (sic) value | |
| * that is simply copied from the descriptor to the corresponding | |
| * completion. | |
| */ | |
| struct gve_dqo_tx_tag { | |
| /** Buffer index within queue page list */ | |
| uint8_t id; | |
| /** Number of descriptors covered by this completion | |
| * | |
| * Note that this is a 7-bit quantity: the high bit may be | |
| * (ab)used by the hardware to indicate that a completion is a | |
| * terminologically undefined "miss" completion. | |
| */ | |
| int8_t count; | |
| } __attribute__ (( packed )); | |
| /** An out-of-order transmit descriptor */ | |
| struct gve_dqo_tx_descriptor { | |
| /** Buffer descriptor */ | |
| struct gve_buffer buf; | |
| /** Descriptor type and flags */ | |
| uint8_t type; | |
| /** Reserved */ | |
| uint8_t reserved_a[3]; | |
| /** Tag */ | |
| struct gve_dqo_tx_tag tag; | |
| /** Length of this descriptor */ | |
| uint16_t len; | |
| } __attribute__ (( packed )); | |
| /** Normal packet transmit descriptor type */ | |
| #define GVE_DQO_TX_TYPE_PACKET 0x0c | |
| /** Last transmit descriptor in a packet */ | |
| #define GVE_DQO_TX_TYPE_LAST 0x20 | |
| /** An out-of-order transmit completion */ | |
| struct gve_dqo_tx_completion { | |
| /** Reserved */ | |
| uint8_t reserved_a[1]; | |
| /** Completion flags */ | |
| uint8_t flags; | |
| /** Tag */ | |
| struct gve_dqo_tx_tag tag; | |
| /** Reserved */ | |
| uint8_t reserved_b[4]; | |
| } __attribute__ (( packed )); | |
| /** Transmit completion packet flag */ | |
| #define GVE_DQO_TXF_PKT 0x10 | |
| /** Transmit completion generation flag */ | |
| #define GVE_DQO_TXF_GEN 0x80 | |
| /** | |
| * Maximum number of receive buffers | |
| * | |
| * This is a policy decision. Experiments suggest that using fewer | |
| * than 64 receive buffers leads to excessive packet drop rates on | |
| * some instance types. | |
| */ | |
| #define GVE_RX_FILL 64 | |
| /** Receive queue page list ID */ | |
| #define GVE_RX_QPL 0x18ae5258 | |
| /** Receive queue interrupt channel */ | |
| #define GVE_RX_IRQ 1 | |
| /** An in-order receive descriptor */ | |
| struct gve_gqi_rx_descriptor { | |
| /** Buffer descriptor */ | |
| struct gve_buffer buf; | |
| } __attribute__ (( packed )); | |
| /** Receive error */ | |
| #define GVE_GQI_RXF_ERROR 0x08 | |
| /** Receive packet continues into next descriptor */ | |
| #define GVE_GQI_RXF_MORE 0x20 | |
| /** Receive sequence number mask */ | |
| #define GVE_GQI_RX_SEQ_MASK 0x07 | |
| /** An in-order receive completion descriptor */ | |
| struct gve_gqi_rx_completion { | |
| /** Reserved */ | |
| uint8_t reserved[60]; | |
| /** Length */ | |
| uint16_t len; | |
| /** Flags */ | |
| uint8_t flags; | |
| /** Sequence number */ | |
| uint8_t seq; | |
| } __attribute__ (( packed )); | |
| /** Padding at the start of all received packets */ | |
| #define GVE_GQI_RX_PAD 2 | |
| /** An out-of-order receive descriptor */ | |
| struct gve_dqo_rx_descriptor { | |
| /** Tag */ | |
| uint8_t tag; | |
| /** Reserved */ | |
| uint8_t reserved_a[7]; | |
| /** Buffer descriptor */ | |
| struct gve_buffer buf; | |
| /** Reserved */ | |
| uint8_t reserved_b[16]; | |
| } __attribute__ (( packed )); | |
| /** An out-of-order receive completion */ | |
| struct gve_dqo_rx_completion { | |
| /** Reserved */ | |
| uint8_t reserved_a[1]; | |
| /** Status */ | |
| uint8_t status; | |
| /** Reserved */ | |
| uint8_t reserved_b[2]; | |
| /** Length and generation bit */ | |
| uint16_t len; | |
| /** Reserved */ | |
| uint8_t reserved_c[2]; | |
| /** Flags */ | |
| uint8_t flags; | |
| /** Reserved */ | |
| uint8_t reserved_d[3]; | |
| /** Tag */ | |
| uint8_t tag; | |
| /** Reserved */ | |
| uint8_t reserved_e[19]; | |
| } __attribute__ (( packed )); | |
| /** Receive error */ | |
| #define GVE_DQO_RXS_ERROR 0x04 | |
| /** Receive completion generation flag */ | |
| #define GVE_DQO_RXL_GEN 0x4000 | |
| /** Last receive descriptor in a packet */ | |
| #define GVE_DQO_RXF_LAST 0x02 | |
| /** Queue strides */ | |
| struct gve_queue_stride { | |
| /** Descriptor ring stride */ | |
| uint8_t desc; | |
| /** Completion ring stride */ | |
| uint8_t cmplt; | |
| }; | |
| /** A descriptor queue */ | |
| struct gve_queue { | |
| /** Descriptor ring */ | |
| union { | |
| /** Transmit descriptors */ | |
| union { | |
| /** In-order transmit descriptors */ | |
| struct gve_gqi_tx_descriptor *gqi; | |
| /** Out-of-order transmit descriptors */ | |
| struct gve_dqo_tx_descriptor *dqo; | |
| } tx; | |
| /** Receive descriptors */ | |
| union { | |
| /** In-order receive descriptors */ | |
| struct gve_gqi_rx_descriptor *gqi; | |
| /** Out-of-order receive descriptors */ | |
| struct gve_dqo_rx_descriptor *dqo; | |
| } rx; | |
| /** Raw data */ | |
| void *raw; | |
| } desc; | |
| /** Completion ring */ | |
| union { | |
| /** Transmit completions */ | |
| union { | |
| /** Out-of-order transmit completions */ | |
| struct gve_dqo_tx_completion *dqo; | |
| } tx; | |
| /** Receive completions */ | |
| union { | |
| /** In-order receive completions */ | |
| struct gve_gqi_rx_completion *gqi; | |
| /** Out-of-order receive completions */ | |
| struct gve_dqo_rx_completion *dqo; | |
| } rx; | |
| /** Raw data */ | |
| void *raw; | |
| } cmplt; | |
| /** Queue resources */ | |
| struct gve_resources *res; | |
| /** Queue type */ | |
| const struct gve_queue_type *type; | |
| /** Queue strides */ | |
| struct gve_queue_stride stride; | |
| /** Number of descriptors (must be a power of two) */ | |
| unsigned int count; | |
| /** Maximum fill level (must be a power of two) */ | |
| unsigned int fill; | |
| /** Descriptor mapping */ | |
| struct dma_mapping desc_map; | |
| /** Completion mapping */ | |
| struct dma_mapping cmplt_map; | |
| /** Queue resources mapping */ | |
| struct dma_mapping res_map; | |
| /** Doorbell register */ | |
| volatile uint32_t *db; | |
| /** Event counter */ | |
| struct gve_event *event; | |
| /** Producer counter */ | |
| uint32_t prod; | |
| /** Consumer counter */ | |
| uint32_t cons; | |
| /** Completion counter */ | |
| uint32_t done; | |
| /** Tag ring */ | |
| uint8_t *tag; | |
| /** Queue page list */ | |
| struct gve_qpl qpl; | |
| }; | |
| /** A descriptor queue type */ | |
| struct gve_queue_type { | |
| /** Name */ | |
| const char *name; | |
| /** | |
| * Populate command parameters to create queue | |
| * | |
| * @v queue Descriptor queue | |
| * @v qpl Queue page list ID | |
| * @v cmd Admin queue command | |
| */ | |
| void ( * param ) ( struct gve_queue *queue, uint32_t qpl, | |
| union gve_admin_command *cmd ); | |
| /** Queue page list ID */ | |
| uint32_t qpl; | |
| /** Interrupt channel */ | |
| uint8_t irq; | |
| /** Maximum fill level */ | |
| uint8_t fill; | |
| /** Queue strides */ | |
| struct { | |
| /** In-order queue strides */ | |
| struct gve_queue_stride gqi; | |
| /** Out-of-order queue strides */ | |
| struct gve_queue_stride dqo; | |
| } stride; | |
| /** Command to create queue */ | |
| uint8_t create; | |
| /** Command to destroy queue */ | |
| uint8_t destroy; | |
| }; | |
| /** A Google Virtual Ethernet NIC */ | |
| struct gve_nic { | |
| /** Configuration registers */ | |
| void *cfg; | |
| /** Doorbell registers */ | |
| void *db; | |
| /** PCI revision */ | |
| uint8_t revision; | |
| /** Network device */ | |
| struct net_device *netdev; | |
| /** DMA device */ | |
| struct dma_device *dma; | |
| /** Dummy MSI-X interrupt */ | |
| struct pci_msix msix; | |
| /** Admin queue */ | |
| struct gve_admin admin; | |
| /** Interrupt channels */ | |
| struct gve_irqs irqs; | |
| /** Event counters */ | |
| struct gve_events events; | |
| /** Scratch buffer */ | |
| struct gve_scratch scratch; | |
| /** Supported options */ | |
| uint32_t options; | |
| /** Operating mode */ | |
| unsigned int mode; | |
| /** Transmit queue */ | |
| struct gve_queue tx; | |
| /** Receive queue */ | |
| struct gve_queue rx; | |
| /** Transmit I/O buffers (indexed by tag) */ | |
| struct io_buffer *tx_iobuf[GVE_TX_FILL]; | |
| /** Transmit tag chain */ | |
| uint8_t tx_chain[GVE_TX_FILL]; | |
| /** Transmit tag ring */ | |
| uint8_t tx_tag[GVE_TX_FILL]; | |
| /** Receive tag ring */ | |
| uint8_t rx_tag[GVE_RX_FILL]; | |
| /** Receive sequence number */ | |
| unsigned int seq; | |
| /** Startup process */ | |
| struct process startup; | |
| /** Startup process retry counter */ | |
| unsigned int retries; | |
| /** Reset recovery watchdog timer */ | |
| struct retry_timer watchdog; | |
| /** Reset recovery recorded activity counter */ | |
| uint32_t activity; | |
| }; | |
| /** Operating mode | |
| * | |
| * These values are chosen to allow for easy transformation to a queue | |
| * format identifier as used for the "Configure device resources" | |
| * command. | |
| */ | |
| #define GVE_MODE_QPL 0x01 /**< Use registered queue pages */ | |
| #define GVE_MODE_DQO 0x02 /**< Use out-of-order queues */ | |
| /** Maximum time to wait for admin queue commands */ | |
| #define GVE_ADMIN_MAX_WAIT_MS 500 | |
| /** Maximum number of times to reattempt device reset */ | |
| #define GVE_RESET_MAX_RETRY 5 | |
| /** Time between reset recovery checks */ | |
| #define GVE_WATCHDOG_TIMEOUT ( 1 * TICKS_PER_SEC ) | |
| #endif /* _GVE_H */ |