Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/gve/gve_utils.c
| /*- | /*- | ||||
| * SPDX-License-Identifier: BSD-3-Clause | * SPDX-License-Identifier: BSD-3-Clause | ||||
| * | * | ||||
| * Copyright (c) 2023 Google LLC | * Copyright (c) 2023-2024 Google LLC | ||||
| * | * | ||||
| * Redistribution and use in source and binary forms, with or without modification, | * Redistribution and use in source and binary forms, with or without modification, | ||||
| * are permitted provided that the following conditions are met: | * are permitted provided that the following conditions are met: | ||||
| * | * | ||||
| * 1. Redistributions of source code must retain the above copyright notice, this | * 1. Redistributions of source code must retain the above copyright notice, this | ||||
| * list of conditions and the following disclaimer. | * list of conditions and the following disclaimer. | ||||
| * | * | ||||
| * 2. Redistributions in binary form must reproduce the above copyright notice, | * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||
| Show All 11 Lines | |||||
| * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||||
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | */ | ||||
| #include "gve.h" | #include "gve.h" | ||||
| #include "gve_dqo.h" | |||||
| uint32_t | uint32_t | ||||
| gve_reg_bar_read_4(struct gve_priv *priv, bus_size_t offset) | gve_reg_bar_read_4(struct gve_priv *priv, bus_size_t offset) | ||||
| { | { | ||||
| return (be32toh(bus_read_4(priv->reg_bar, offset))); | return (be32toh(bus_read_4(priv->reg_bar, offset))); | ||||
| } | } | ||||
| void | void | ||||
| gve_reg_bar_write_4(struct gve_priv *priv, bus_size_t offset, uint32_t val) | gve_reg_bar_write_4(struct gve_priv *priv, bus_size_t offset, uint32_t val) | ||||
| { | { | ||||
| bus_write_4(priv->reg_bar, offset, htobe32(val)); | bus_write_4(priv->reg_bar, offset, htobe32(val)); | ||||
| } | } | ||||
| void | void | ||||
| gve_db_bar_write_4(struct gve_priv *priv, bus_size_t offset, uint32_t val) | gve_db_bar_write_4(struct gve_priv *priv, bus_size_t offset, uint32_t val) | ||||
| { | { | ||||
| bus_write_4(priv->db_bar, offset, htobe32(val)); | bus_write_4(priv->db_bar, offset, htobe32(val)); | ||||
| } | } | ||||
| void | void | ||||
| gve_db_bar_dqo_write_4(struct gve_priv *priv, bus_size_t offset, uint32_t val) | |||||
| { | |||||
| bus_write_4(priv->db_bar, offset, val); | |||||
| } | |||||
| void | |||||
| gve_alloc_counters(counter_u64_t *stat, int num_stats) | gve_alloc_counters(counter_u64_t *stat, int num_stats) | ||||
| { | { | ||||
| int i; | int i; | ||||
| for (i = 0; i < num_stats; i++) | for (i = 0; i < num_stats; i++) | ||||
| stat[i] = counter_u64_alloc(M_WAITOK); | stat[i] = counter_u64_alloc(M_WAITOK); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 242 Lines • ▼ Show 20 Lines | for (i = 0; i < num_tx; i++) { | ||||
| if (irq->res == NULL) { | if (irq->res == NULL) { | ||||
| device_printf(priv->dev, "Failed to alloc irq %d for Tx queue %d\n", | device_printf(priv->dev, "Failed to alloc irq %d for Tx queue %d\n", | ||||
| rid, i); | rid, i); | ||||
| err = ENOMEM; | err = ENOMEM; | ||||
| goto abort; | goto abort; | ||||
| } | } | ||||
| err = bus_setup_intr(priv->dev, irq->res, INTR_TYPE_NET | INTR_MPSAFE, | err = bus_setup_intr(priv->dev, irq->res, INTR_TYPE_NET | INTR_MPSAFE, | ||||
| gve_tx_intr, NULL, &priv->tx[i], &irq->cookie); | gve_is_gqi(priv) ? gve_tx_intr : gve_tx_intr_dqo, NULL, | ||||
| &priv->tx[i], &irq->cookie); | |||||
| if (err != 0) { | if (err != 0) { | ||||
| device_printf(priv->dev, "Failed to setup irq %d for Tx queue %d, " | device_printf(priv->dev, "Failed to setup irq %d for Tx queue %d, " | ||||
| "err: %d\n", rid, i, err); | "err: %d\n", rid, i, err); | ||||
| goto abort; | goto abort; | ||||
| } | } | ||||
| bus_describe_intr(priv->dev, irq->res, irq->cookie, "tx%d", i); | bus_describe_intr(priv->dev, irq->res, irq->cookie, "tx%d", i); | ||||
| com->ntfy_id = i; | com->ntfy_id = i; | ||||
| Show All 10 Lines | for (j = 0; j < num_rx; j++) { | ||||
| if (irq->res == NULL) { | if (irq->res == NULL) { | ||||
| device_printf(priv->dev, | device_printf(priv->dev, | ||||
| "Failed to alloc irq %d for Rx queue %d", rid, j); | "Failed to alloc irq %d for Rx queue %d", rid, j); | ||||
| err = ENOMEM; | err = ENOMEM; | ||||
| goto abort; | goto abort; | ||||
| } | } | ||||
| err = bus_setup_intr(priv->dev, irq->res, INTR_TYPE_NET | INTR_MPSAFE, | err = bus_setup_intr(priv->dev, irq->res, INTR_TYPE_NET | INTR_MPSAFE, | ||||
| gve_rx_intr, NULL, &priv->rx[j], &irq->cookie); | gve_is_gqi(priv) ? gve_rx_intr : gve_rx_intr_dqo, NULL, | ||||
| &priv->rx[j], &irq->cookie); | |||||
| if (err != 0) { | if (err != 0) { | ||||
| device_printf(priv->dev, "Failed to setup irq %d for Rx queue %d, " | device_printf(priv->dev, "Failed to setup irq %d for Rx queue %d, " | ||||
| "err: %d\n", rid, j, err); | "err: %d\n", rid, j, err); | ||||
| goto abort; | goto abort; | ||||
| } | } | ||||
| bus_describe_intr(priv->dev, irq->res, irq->cookie, "rx%d", j); | bus_describe_intr(priv->dev, irq->res, irq->cookie, "rx%d", j); | ||||
| com->ntfy_id = i + j; | com->ntfy_id = i + j; | ||||
| Show All 23 Lines | gve_alloc_irqs(struct gve_priv *priv) | ||||
| return (0); | return (0); | ||||
| abort: | abort: | ||||
| gve_free_irqs(priv); | gve_free_irqs(priv); | ||||
| return (err); | return (err); | ||||
| } | } | ||||
| /* | |||||
| * Builds register value to write to DQO IRQ doorbell to enable with specified | |||||
| * ITR interval. | |||||
| */ | |||||
| static uint32_t | |||||
| gve_setup_itr_interval_dqo(uint32_t interval_us) | |||||
| { | |||||
| uint32_t result = GVE_ITR_ENABLE_BIT_DQO; | |||||
| /* Interval has 2us granularity. */ | |||||
| interval_us >>= 1; | |||||
| interval_us &= GVE_ITR_INTERVAL_DQO_MASK; | |||||
| result |= (interval_us << GVE_ITR_INTERVAL_DQO_SHIFT); | |||||
| return (result); | |||||
| } | |||||
| void | void | ||||
| gve_unmask_all_queue_irqs(struct gve_priv *priv) | gve_unmask_all_queue_irqs(struct gve_priv *priv) | ||||
| { | { | ||||
| struct gve_tx_ring *tx; | struct gve_tx_ring *tx; | ||||
| struct gve_rx_ring *rx; | struct gve_rx_ring *rx; | ||||
| int idx; | int idx; | ||||
| for (idx = 0; idx < priv->tx_cfg.num_queues; idx++) { | for (idx = 0; idx < priv->tx_cfg.num_queues; idx++) { | ||||
| tx = &priv->tx[idx]; | tx = &priv->tx[idx]; | ||||
| if (gve_is_gqi(priv)) | |||||
| gve_db_bar_write_4(priv, tx->com.irq_db_offset, 0); | gve_db_bar_write_4(priv, tx->com.irq_db_offset, 0); | ||||
| else | |||||
| gve_db_bar_dqo_write_4(priv, tx->com.irq_db_offset, | |||||
| gve_setup_itr_interval_dqo(GVE_TX_IRQ_RATELIMIT_US_DQO)); | |||||
| } | } | ||||
| for (idx = 0; idx < priv->rx_cfg.num_queues; idx++) { | for (idx = 0; idx < priv->rx_cfg.num_queues; idx++) { | ||||
| rx = &priv->rx[idx]; | rx = &priv->rx[idx]; | ||||
| if (gve_is_gqi(priv)) | |||||
| gve_db_bar_write_4(priv, rx->com.irq_db_offset, 0); | gve_db_bar_write_4(priv, rx->com.irq_db_offset, 0); | ||||
| else | |||||
| gve_db_bar_dqo_write_4(priv, rx->com.irq_db_offset, | |||||
| gve_setup_itr_interval_dqo(GVE_RX_IRQ_RATELIMIT_US_DQO)); | |||||
| } | } | ||||
| } | } | ||||
| void | void | ||||
| gve_mask_all_queue_irqs(struct gve_priv *priv) | gve_mask_all_queue_irqs(struct gve_priv *priv) | ||||
| { | { | ||||
| for (int idx = 0; idx < priv->tx_cfg.num_queues; idx++) { | for (int idx = 0; idx < priv->tx_cfg.num_queues; idx++) { | ||||
| struct gve_tx_ring *tx = &priv->tx[idx]; | struct gve_tx_ring *tx = &priv->tx[idx]; | ||||
| gve_db_bar_write_4(priv, tx->com.irq_db_offset, GVE_IRQ_MASK); | gve_db_bar_write_4(priv, tx->com.irq_db_offset, GVE_IRQ_MASK); | ||||
| } | } | ||||
| for (int idx = 0; idx < priv->rx_cfg.num_queues; idx++) { | for (int idx = 0; idx < priv->rx_cfg.num_queues; idx++) { | ||||
| struct gve_rx_ring *rx = &priv->rx[idx]; | struct gve_rx_ring *rx = &priv->rx[idx]; | ||||
| gve_db_bar_write_4(priv, rx->com.irq_db_offset, GVE_IRQ_MASK); | gve_db_bar_write_4(priv, rx->com.irq_db_offset, GVE_IRQ_MASK); | ||||
| } | } | ||||
| } | } | ||||