154dfc97bSShailend Chand /*- 254dfc97bSShailend Chand * SPDX-License-Identifier: BSD-3-Clause 354dfc97bSShailend Chand * 4*d438b4efSShailend Chand * Copyright (c) 2023-2024 Google LLC 554dfc97bSShailend Chand * 654dfc97bSShailend Chand * Redistribution and use in source and binary forms, with or without modification, 754dfc97bSShailend Chand * are permitted provided that the following conditions are met: 854dfc97bSShailend Chand * 954dfc97bSShailend Chand * 1. Redistributions of source code must retain the above copyright notice, this 1054dfc97bSShailend Chand * list of conditions and the following disclaimer. 1154dfc97bSShailend Chand * 1254dfc97bSShailend Chand * 2. Redistributions in binary form must reproduce the above copyright notice, 1354dfc97bSShailend Chand * this list of conditions and the following disclaimer in the documentation 1454dfc97bSShailend Chand * and/or other materials provided with the distribution. 1554dfc97bSShailend Chand * 1654dfc97bSShailend Chand * 3. Neither the name of the copyright holder nor the names of its contributors 1754dfc97bSShailend Chand * may be used to endorse or promote products derived from this software without 1854dfc97bSShailend Chand * specific prior written permission. 1954dfc97bSShailend Chand * 2054dfc97bSShailend Chand * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 2154dfc97bSShailend Chand * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2254dfc97bSShailend Chand * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2354dfc97bSShailend Chand * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 2454dfc97bSShailend Chand * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2554dfc97bSShailend Chand * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2654dfc97bSShailend Chand * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 2754dfc97bSShailend Chand * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2854dfc97bSShailend Chand * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 2954dfc97bSShailend Chand * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3054dfc97bSShailend Chand */ 3154dfc97bSShailend Chand #include "gve.h" 32*d438b4efSShailend Chand #include "gve_dqo.h" 3354dfc97bSShailend Chand 3454dfc97bSShailend Chand uint32_t 3554dfc97bSShailend Chand gve_reg_bar_read_4(struct gve_priv *priv, bus_size_t offset) 3654dfc97bSShailend Chand { 3754dfc97bSShailend Chand return (be32toh(bus_read_4(priv->reg_bar, offset))); 3854dfc97bSShailend Chand } 3954dfc97bSShailend Chand 4054dfc97bSShailend Chand void 4154dfc97bSShailend Chand gve_reg_bar_write_4(struct gve_priv *priv, bus_size_t offset, uint32_t val) 4254dfc97bSShailend Chand { 4354dfc97bSShailend Chand bus_write_4(priv->reg_bar, offset, htobe32(val)); 4454dfc97bSShailend Chand } 4554dfc97bSShailend Chand 4654dfc97bSShailend Chand void 4754dfc97bSShailend Chand gve_db_bar_write_4(struct gve_priv *priv, bus_size_t offset, uint32_t val) 4854dfc97bSShailend Chand { 4954dfc97bSShailend Chand bus_write_4(priv->db_bar, offset, htobe32(val)); 5054dfc97bSShailend Chand } 5154dfc97bSShailend Chand 5254dfc97bSShailend Chand void 53*d438b4efSShailend Chand gve_db_bar_dqo_write_4(struct gve_priv *priv, bus_size_t offset, uint32_t val) 54*d438b4efSShailend Chand { 55*d438b4efSShailend Chand bus_write_4(priv->db_bar, offset, val); 56*d438b4efSShailend Chand } 57*d438b4efSShailend Chand 58*d438b4efSShailend Chand void 5954dfc97bSShailend Chand gve_alloc_counters(counter_u64_t *stat, int num_stats) 6054dfc97bSShailend Chand { 6154dfc97bSShailend Chand int i; 6254dfc97bSShailend Chand 6354dfc97bSShailend Chand for (i = 0; i < num_stats; i++) 6454dfc97bSShailend Chand stat[i] = counter_u64_alloc(M_WAITOK); 6554dfc97bSShailend Chand } 6654dfc97bSShailend Chand 6754dfc97bSShailend Chand void 6854dfc97bSShailend Chand gve_free_counters(counter_u64_t *stat, int num_stats) 6954dfc97bSShailend Chand { 7054dfc97bSShailend Chand int i; 7154dfc97bSShailend Chand 7254dfc97bSShailend Chand for (i = 0; i < num_stats; i++) 7354dfc97bSShailend Chand counter_u64_free(stat[i]); 7454dfc97bSShailend Chand } 7554dfc97bSShailend Chand 7654dfc97bSShailend Chand /* Currently assumes a single segment. */ 7754dfc97bSShailend Chand static void 7854dfc97bSShailend Chand gve_dmamap_load_callback(void *arg, bus_dma_segment_t *segs, int nseg, 7954dfc97bSShailend Chand int error) 8054dfc97bSShailend Chand { 8154dfc97bSShailend Chand if (error == 0) 8254dfc97bSShailend Chand *(bus_addr_t *) arg = segs[0].ds_addr; 8354dfc97bSShailend Chand } 8454dfc97bSShailend Chand 8554dfc97bSShailend Chand int 8654dfc97bSShailend Chand gve_dma_alloc_coherent(struct gve_priv *priv, int size, int align, 8754dfc97bSShailend Chand struct gve_dma_handle *dma) 8854dfc97bSShailend Chand { 8954dfc97bSShailend Chand int err; 9054dfc97bSShailend Chand device_t dev = priv->dev; 9154dfc97bSShailend Chand 9254dfc97bSShailend Chand err = bus_dma_tag_create( 9354dfc97bSShailend Chand bus_get_dma_tag(dev), /* parent */ 9454dfc97bSShailend Chand align, 0, /* alignment, bounds */ 9554dfc97bSShailend Chand BUS_SPACE_MAXADDR, /* lowaddr */ 9654dfc97bSShailend Chand BUS_SPACE_MAXADDR, /* highaddr */ 9754dfc97bSShailend Chand NULL, NULL, /* filter, filterarg */ 9854dfc97bSShailend Chand size, /* maxsize */ 9954dfc97bSShailend Chand 1, /* nsegments */ 10054dfc97bSShailend Chand size, /* maxsegsize */ 10154dfc97bSShailend Chand BUS_DMA_ALLOCNOW, /* flags */ 10254dfc97bSShailend Chand NULL, /* lockfunc */ 10354dfc97bSShailend Chand NULL, /* lockarg */ 10454dfc97bSShailend Chand &dma->tag); 10554dfc97bSShailend Chand if (err != 0) { 10654dfc97bSShailend Chand device_printf(dev, "%s: bus_dma_tag_create failed: %d\n", 10754dfc97bSShailend Chand __func__, err); 10854dfc97bSShailend Chand goto clear_tag; 10954dfc97bSShailend Chand } 11054dfc97bSShailend Chand 11154dfc97bSShailend Chand err = bus_dmamem_alloc(dma->tag, (void **) &dma->cpu_addr, 11254dfc97bSShailend Chand BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 11354dfc97bSShailend Chand &dma->map); 11454dfc97bSShailend Chand if (err != 0) { 11554dfc97bSShailend Chand device_printf(dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n", 11654dfc97bSShailend Chand __func__, (uintmax_t)size, err); 11754dfc97bSShailend Chand goto destroy_tag; 11854dfc97bSShailend Chand } 11954dfc97bSShailend Chand 12054dfc97bSShailend Chand /* An address set by the callback will never be -1 */ 12154dfc97bSShailend Chand dma->bus_addr = (bus_addr_t)-1; 12254dfc97bSShailend Chand err = bus_dmamap_load(dma->tag, dma->map, dma->cpu_addr, size, 12354dfc97bSShailend Chand gve_dmamap_load_callback, &dma->bus_addr, BUS_DMA_NOWAIT); 12454dfc97bSShailend Chand if (err != 0 || dma->bus_addr == (bus_addr_t)-1) { 12554dfc97bSShailend Chand device_printf(dev, "%s: bus_dmamap_load failed: %d\n", __func__, err); 12654dfc97bSShailend Chand goto free_mem; 12754dfc97bSShailend Chand } 12854dfc97bSShailend Chand 12954dfc97bSShailend Chand return (0); 13054dfc97bSShailend Chand 13154dfc97bSShailend Chand free_mem: 13254dfc97bSShailend Chand bus_dmamem_free(dma->tag, dma->cpu_addr, dma->map); 13354dfc97bSShailend Chand destroy_tag: 13454dfc97bSShailend Chand bus_dma_tag_destroy(dma->tag); 13554dfc97bSShailend Chand clear_tag: 13654dfc97bSShailend Chand dma->tag = NULL; 13754dfc97bSShailend Chand 13854dfc97bSShailend Chand return (err); 13954dfc97bSShailend Chand } 14054dfc97bSShailend Chand 14154dfc97bSShailend Chand void 14254dfc97bSShailend Chand gve_dma_free_coherent(struct gve_dma_handle *dma) 14354dfc97bSShailend Chand { 14454dfc97bSShailend Chand bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 14554dfc97bSShailend Chand bus_dmamap_unload(dma->tag, dma->map); 14654dfc97bSShailend Chand bus_dmamem_free(dma->tag, dma->cpu_addr, dma->map); 14754dfc97bSShailend Chand bus_dma_tag_destroy(dma->tag); 14854dfc97bSShailend Chand } 14954dfc97bSShailend Chand 15054dfc97bSShailend Chand int 15154dfc97bSShailend Chand gve_dmamap_create(struct gve_priv *priv, int size, int align, 15254dfc97bSShailend Chand struct gve_dma_handle *dma) 15354dfc97bSShailend Chand { 15454dfc97bSShailend Chand int err; 15554dfc97bSShailend Chand device_t dev = priv->dev; 15654dfc97bSShailend Chand 15754dfc97bSShailend Chand err = bus_dma_tag_create( 15854dfc97bSShailend Chand bus_get_dma_tag(dev), /* parent */ 15954dfc97bSShailend Chand align, 0, /* alignment, bounds */ 16054dfc97bSShailend Chand BUS_SPACE_MAXADDR, /* lowaddr */ 16154dfc97bSShailend Chand BUS_SPACE_MAXADDR, /* highaddr */ 16254dfc97bSShailend Chand NULL, NULL, /* filter, filterarg */ 16354dfc97bSShailend Chand size, /* maxsize */ 16454dfc97bSShailend Chand 1, /* nsegments */ 16554dfc97bSShailend Chand size, /* maxsegsize */ 16654dfc97bSShailend Chand BUS_DMA_ALLOCNOW, /* flags */ 16754dfc97bSShailend Chand NULL, /* lockfunc */ 16854dfc97bSShailend Chand NULL, /* lockarg */ 16954dfc97bSShailend Chand &dma->tag); 17054dfc97bSShailend Chand if (err != 0) { 17154dfc97bSShailend Chand device_printf(dev, "%s: bus_dma_tag_create failed: %d\n", 17254dfc97bSShailend Chand __func__, err); 17354dfc97bSShailend Chand goto clear_tag; 17454dfc97bSShailend Chand } 17554dfc97bSShailend Chand 17654dfc97bSShailend Chand err = bus_dmamap_create(dma->tag, BUS_DMA_COHERENT, &dma->map); 17754dfc97bSShailend Chand if (err != 0) { 17854dfc97bSShailend Chand device_printf(dev, "%s: bus_dmamap_create failed: %d\n", 17954dfc97bSShailend Chand __func__, err); 18054dfc97bSShailend Chand goto destroy_tag; 18154dfc97bSShailend Chand } 18254dfc97bSShailend Chand 18354dfc97bSShailend Chand /* An address set by the callback will never be -1 */ 18454dfc97bSShailend Chand dma->bus_addr = (bus_addr_t)-1; 18554dfc97bSShailend Chand err = bus_dmamap_load(dma->tag, dma->map, dma->cpu_addr, size, 18654dfc97bSShailend Chand gve_dmamap_load_callback, &dma->bus_addr, BUS_DMA_WAITOK); 18754dfc97bSShailend Chand if (err != 0 || dma->bus_addr == (bus_addr_t)-1) { 18854dfc97bSShailend Chand device_printf(dev, "%s: bus_dmamap_load failed: %d\n", 18954dfc97bSShailend Chand __func__, err); 19054dfc97bSShailend Chand goto destroy_map; 19154dfc97bSShailend Chand } 19254dfc97bSShailend Chand 19354dfc97bSShailend Chand return (0); 19454dfc97bSShailend Chand 19554dfc97bSShailend Chand destroy_map: 19654dfc97bSShailend Chand bus_dmamap_destroy(dma->tag, dma->map); 19754dfc97bSShailend Chand destroy_tag: 19854dfc97bSShailend Chand bus_dma_tag_destroy(dma->tag); 19954dfc97bSShailend Chand clear_tag: 20054dfc97bSShailend Chand dma->tag = NULL; 20154dfc97bSShailend Chand 20254dfc97bSShailend Chand return (err); 20354dfc97bSShailend Chand } 20454dfc97bSShailend Chand 20554dfc97bSShailend Chand void 20654dfc97bSShailend Chand gve_dmamap_destroy(struct gve_dma_handle *dma) 20754dfc97bSShailend Chand { 20854dfc97bSShailend Chand bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 20954dfc97bSShailend Chand bus_dmamap_unload(dma->tag, dma->map); 21054dfc97bSShailend Chand bus_dmamap_destroy(dma->tag, dma->map); 21154dfc97bSShailend Chand bus_dma_tag_destroy(dma->tag); 21254dfc97bSShailend Chand } 21354dfc97bSShailend Chand 21454dfc97bSShailend Chand static int 21554dfc97bSShailend Chand gve_mgmnt_intr(void *arg) 21654dfc97bSShailend Chand { 21754dfc97bSShailend Chand struct gve_priv *priv = arg; 21854dfc97bSShailend Chand 21954dfc97bSShailend Chand taskqueue_enqueue(priv->service_tq, &priv->service_task); 22054dfc97bSShailend Chand return (FILTER_HANDLED); 22154dfc97bSShailend Chand } 22254dfc97bSShailend Chand 22354dfc97bSShailend Chand void 22454dfc97bSShailend Chand gve_free_irqs(struct gve_priv *priv) 22554dfc97bSShailend Chand { 22654dfc97bSShailend Chand struct gve_irq *irq; 22754dfc97bSShailend Chand int num_irqs; 22854dfc97bSShailend Chand int rid; 22954dfc97bSShailend Chand int rc; 23054dfc97bSShailend Chand int i; 23154dfc97bSShailend Chand 23254dfc97bSShailend Chand if (priv->irq_tbl == NULL) { 23354dfc97bSShailend Chand device_printf(priv->dev, "No irq table, nothing to free\n"); 23454dfc97bSShailend Chand return; 23554dfc97bSShailend Chand } 23654dfc97bSShailend Chand 23754dfc97bSShailend Chand num_irqs = priv->tx_cfg.num_queues + priv->rx_cfg.num_queues + 1; 23854dfc97bSShailend Chand 23954dfc97bSShailend Chand for (i = 0; i < num_irqs; i++) { 24054dfc97bSShailend Chand irq = &priv->irq_tbl[i]; 24154dfc97bSShailend Chand if (irq->res == NULL) 24254dfc97bSShailend Chand continue; 24354dfc97bSShailend Chand 24454dfc97bSShailend Chand rid = rman_get_rid(irq->res); 24554dfc97bSShailend Chand 24654dfc97bSShailend Chand rc = bus_teardown_intr(priv->dev, irq->res, irq->cookie); 24754dfc97bSShailend Chand if (rc != 0) 24854dfc97bSShailend Chand device_printf(priv->dev, "Failed to teardown irq num %d\n", 24954dfc97bSShailend Chand rid); 25054dfc97bSShailend Chand 25154dfc97bSShailend Chand rc = bus_release_resource(priv->dev, SYS_RES_IRQ, 25254dfc97bSShailend Chand rid, irq->res); 25354dfc97bSShailend Chand if (rc != 0) 25454dfc97bSShailend Chand device_printf(priv->dev, "Failed to release irq num %d\n", 25554dfc97bSShailend Chand rid); 25654dfc97bSShailend Chand 25754dfc97bSShailend Chand irq->res = NULL; 25854dfc97bSShailend Chand irq->cookie = NULL; 25954dfc97bSShailend Chand } 26054dfc97bSShailend Chand 26154dfc97bSShailend Chand free(priv->irq_tbl, M_GVE); 26254dfc97bSShailend Chand priv->irq_tbl = NULL; 26354dfc97bSShailend Chand 26454dfc97bSShailend Chand /* Safe to call even if msix was never alloced */ 26554dfc97bSShailend Chand pci_release_msi(priv->dev); 26654dfc97bSShailend Chand } 26754dfc97bSShailend Chand 26854dfc97bSShailend Chand int 26954dfc97bSShailend Chand gve_alloc_irqs(struct gve_priv *priv) 27054dfc97bSShailend Chand { 27154dfc97bSShailend Chand int num_tx = priv->tx_cfg.num_queues; 27254dfc97bSShailend Chand int num_rx = priv->rx_cfg.num_queues; 27354dfc97bSShailend Chand int req_nvecs = num_tx + num_rx + 1; 27454dfc97bSShailend Chand int got_nvecs = req_nvecs; 27554dfc97bSShailend Chand struct gve_irq *irq; 27654dfc97bSShailend Chand int i, j, m; 27754dfc97bSShailend Chand int rid; 27854dfc97bSShailend Chand int err; 27954dfc97bSShailend Chand 28054dfc97bSShailend Chand struct gve_ring_com *com; 28154dfc97bSShailend Chand struct gve_rx_ring *rx; 28254dfc97bSShailend Chand struct gve_tx_ring *tx; 28354dfc97bSShailend Chand 28454dfc97bSShailend Chand if (pci_alloc_msix(priv->dev, &got_nvecs) != 0) { 28554dfc97bSShailend Chand device_printf(priv->dev, "Failed to acquire any msix vectors\n"); 28654dfc97bSShailend Chand err = ENXIO; 28754dfc97bSShailend Chand goto abort; 28854dfc97bSShailend Chand } else if (got_nvecs != req_nvecs) { 28954dfc97bSShailend Chand device_printf(priv->dev, "Tried to acquire %d msix vectors, got only %d\n", 29054dfc97bSShailend Chand req_nvecs, got_nvecs); 29154dfc97bSShailend Chand err = ENOSPC; 29254dfc97bSShailend Chand goto abort; 29354dfc97bSShailend Chand } 29454dfc97bSShailend Chand 29554dfc97bSShailend Chand if (bootverbose) 29654dfc97bSShailend Chand device_printf(priv->dev, "Enabled MSIX with %d vectors\n", got_nvecs); 29754dfc97bSShailend Chand 29854dfc97bSShailend Chand priv->irq_tbl = malloc(sizeof(struct gve_irq) * req_nvecs, M_GVE, 29954dfc97bSShailend Chand M_WAITOK | M_ZERO); 30054dfc97bSShailend Chand 30154dfc97bSShailend Chand for (i = 0; i < num_tx; i++) { 30254dfc97bSShailend Chand irq = &priv->irq_tbl[i]; 30354dfc97bSShailend Chand tx = &priv->tx[i]; 30454dfc97bSShailend Chand com = &tx->com; 30554dfc97bSShailend Chand rid = i + 1; 30654dfc97bSShailend Chand 30754dfc97bSShailend Chand irq->res = bus_alloc_resource_any(priv->dev, SYS_RES_IRQ, 30854dfc97bSShailend Chand &rid, RF_ACTIVE); 30954dfc97bSShailend Chand if (irq->res == NULL) { 31054dfc97bSShailend Chand device_printf(priv->dev, "Failed to alloc irq %d for Tx queue %d\n", 31154dfc97bSShailend Chand rid, i); 31254dfc97bSShailend Chand err = ENOMEM; 31354dfc97bSShailend Chand goto abort; 31454dfc97bSShailend Chand } 31554dfc97bSShailend Chand 31654dfc97bSShailend Chand err = bus_setup_intr(priv->dev, irq->res, INTR_TYPE_NET | INTR_MPSAFE, 317*d438b4efSShailend Chand gve_is_gqi(priv) ? gve_tx_intr : gve_tx_intr_dqo, NULL, 318*d438b4efSShailend Chand &priv->tx[i], &irq->cookie); 31954dfc97bSShailend Chand if (err != 0) { 32054dfc97bSShailend Chand device_printf(priv->dev, "Failed to setup irq %d for Tx queue %d, " 32154dfc97bSShailend Chand "err: %d\n", rid, i, err); 32254dfc97bSShailend Chand goto abort; 32354dfc97bSShailend Chand } 32454dfc97bSShailend Chand 32554dfc97bSShailend Chand bus_describe_intr(priv->dev, irq->res, irq->cookie, "tx%d", i); 32654dfc97bSShailend Chand com->ntfy_id = i; 32754dfc97bSShailend Chand } 32854dfc97bSShailend Chand 32954dfc97bSShailend Chand for (j = 0; j < num_rx; j++) { 33054dfc97bSShailend Chand irq = &priv->irq_tbl[i + j]; 33154dfc97bSShailend Chand rx = &priv->rx[j]; 33254dfc97bSShailend Chand com = &rx->com; 33354dfc97bSShailend Chand rid = i + j + 1; 33454dfc97bSShailend Chand 33554dfc97bSShailend Chand irq->res = bus_alloc_resource_any(priv->dev, SYS_RES_IRQ, 33654dfc97bSShailend Chand &rid, RF_ACTIVE); 33754dfc97bSShailend Chand if (irq->res == NULL) { 33854dfc97bSShailend Chand device_printf(priv->dev, 33954dfc97bSShailend Chand "Failed to alloc irq %d for Rx queue %d", rid, j); 34054dfc97bSShailend Chand err = ENOMEM; 34154dfc97bSShailend Chand goto abort; 34254dfc97bSShailend Chand } 34354dfc97bSShailend Chand 34454dfc97bSShailend Chand err = bus_setup_intr(priv->dev, irq->res, INTR_TYPE_NET | INTR_MPSAFE, 345*d438b4efSShailend Chand gve_is_gqi(priv) ? gve_rx_intr : gve_rx_intr_dqo, NULL, 346*d438b4efSShailend Chand &priv->rx[j], &irq->cookie); 34754dfc97bSShailend Chand if (err != 0) { 34854dfc97bSShailend Chand device_printf(priv->dev, "Failed to setup irq %d for Rx queue %d, " 34954dfc97bSShailend Chand "err: %d\n", rid, j, err); 35054dfc97bSShailend Chand goto abort; 35154dfc97bSShailend Chand } 35254dfc97bSShailend Chand 35354dfc97bSShailend Chand bus_describe_intr(priv->dev, irq->res, irq->cookie, "rx%d", j); 35454dfc97bSShailend Chand com->ntfy_id = i + j; 35554dfc97bSShailend Chand } 35654dfc97bSShailend Chand 35754dfc97bSShailend Chand m = i + j; 35854dfc97bSShailend Chand rid = m + 1; 35954dfc97bSShailend Chand irq = &priv->irq_tbl[m]; 36054dfc97bSShailend Chand 36154dfc97bSShailend Chand irq->res = bus_alloc_resource_any(priv->dev, SYS_RES_IRQ, 36254dfc97bSShailend Chand &rid, RF_ACTIVE); 36354dfc97bSShailend Chand if (irq->res == NULL) { 36454dfc97bSShailend Chand device_printf(priv->dev, "Failed to allocate irq %d for mgmnt queue\n", rid); 36554dfc97bSShailend Chand err = ENOMEM; 36654dfc97bSShailend Chand goto abort; 36754dfc97bSShailend Chand } 36854dfc97bSShailend Chand 36954dfc97bSShailend Chand err = bus_setup_intr(priv->dev, irq->res, INTR_TYPE_NET | INTR_MPSAFE, 37054dfc97bSShailend Chand gve_mgmnt_intr, NULL, priv, &irq->cookie); 37154dfc97bSShailend Chand if (err != 0) { 37254dfc97bSShailend Chand device_printf(priv->dev, "Failed to setup irq %d for mgmnt queue, err: %d\n", 37354dfc97bSShailend Chand rid, err); 37454dfc97bSShailend Chand goto abort; 37554dfc97bSShailend Chand } 37654dfc97bSShailend Chand 37754dfc97bSShailend Chand bus_describe_intr(priv->dev, irq->res, irq->cookie, "mgmnt"); 37854dfc97bSShailend Chand 37954dfc97bSShailend Chand return (0); 38054dfc97bSShailend Chand 38154dfc97bSShailend Chand abort: 38254dfc97bSShailend Chand gve_free_irqs(priv); 38354dfc97bSShailend Chand return (err); 38454dfc97bSShailend Chand } 38554dfc97bSShailend Chand 386*d438b4efSShailend Chand /* 387*d438b4efSShailend Chand * Builds register value to write to DQO IRQ doorbell to enable with specified 388*d438b4efSShailend Chand * ITR interval. 389*d438b4efSShailend Chand */ 390*d438b4efSShailend Chand static uint32_t 391*d438b4efSShailend Chand gve_setup_itr_interval_dqo(uint32_t interval_us) 392*d438b4efSShailend Chand { 393*d438b4efSShailend Chand uint32_t result = GVE_ITR_ENABLE_BIT_DQO; 394*d438b4efSShailend Chand 395*d438b4efSShailend Chand /* Interval has 2us granularity. */ 396*d438b4efSShailend Chand interval_us >>= 1; 397*d438b4efSShailend Chand 398*d438b4efSShailend Chand interval_us &= GVE_ITR_INTERVAL_DQO_MASK; 399*d438b4efSShailend Chand result |= (interval_us << GVE_ITR_INTERVAL_DQO_SHIFT); 400*d438b4efSShailend Chand 401*d438b4efSShailend Chand return (result); 402*d438b4efSShailend Chand } 403*d438b4efSShailend Chand 40454dfc97bSShailend Chand void 40554dfc97bSShailend Chand gve_unmask_all_queue_irqs(struct gve_priv *priv) 40654dfc97bSShailend Chand { 40754dfc97bSShailend Chand struct gve_tx_ring *tx; 40854dfc97bSShailend Chand struct gve_rx_ring *rx; 40954dfc97bSShailend Chand int idx; 41054dfc97bSShailend Chand 41154dfc97bSShailend Chand for (idx = 0; idx < priv->tx_cfg.num_queues; idx++) { 41254dfc97bSShailend Chand tx = &priv->tx[idx]; 413*d438b4efSShailend Chand if (gve_is_gqi(priv)) 41454dfc97bSShailend Chand gve_db_bar_write_4(priv, tx->com.irq_db_offset, 0); 415*d438b4efSShailend Chand else 416*d438b4efSShailend Chand gve_db_bar_dqo_write_4(priv, tx->com.irq_db_offset, 417*d438b4efSShailend Chand gve_setup_itr_interval_dqo(GVE_TX_IRQ_RATELIMIT_US_DQO)); 41854dfc97bSShailend Chand } 419*d438b4efSShailend Chand 42054dfc97bSShailend Chand for (idx = 0; idx < priv->rx_cfg.num_queues; idx++) { 42154dfc97bSShailend Chand rx = &priv->rx[idx]; 422*d438b4efSShailend Chand if (gve_is_gqi(priv)) 42354dfc97bSShailend Chand gve_db_bar_write_4(priv, rx->com.irq_db_offset, 0); 424*d438b4efSShailend Chand else 425*d438b4efSShailend Chand gve_db_bar_dqo_write_4(priv, rx->com.irq_db_offset, 426*d438b4efSShailend Chand gve_setup_itr_interval_dqo(GVE_RX_IRQ_RATELIMIT_US_DQO)); 42754dfc97bSShailend Chand } 42854dfc97bSShailend Chand } 42954dfc97bSShailend Chand 43054dfc97bSShailend Chand void 43154dfc97bSShailend Chand gve_mask_all_queue_irqs(struct gve_priv *priv) 43254dfc97bSShailend Chand { 43354dfc97bSShailend Chand for (int idx = 0; idx < priv->tx_cfg.num_queues; idx++) { 43454dfc97bSShailend Chand struct gve_tx_ring *tx = &priv->tx[idx]; 43554dfc97bSShailend Chand gve_db_bar_write_4(priv, tx->com.irq_db_offset, GVE_IRQ_MASK); 43654dfc97bSShailend Chand } 43754dfc97bSShailend Chand for (int idx = 0; idx < priv->rx_cfg.num_queues; idx++) { 43854dfc97bSShailend Chand struct gve_rx_ring *rx = &priv->rx[idx]; 43954dfc97bSShailend Chand gve_db_bar_write_4(priv, rx->com.irq_db_offset, GVE_IRQ_MASK); 44054dfc97bSShailend Chand } 44154dfc97bSShailend Chand } 442