Introduce register offsets and bitmask constants for the Transmit Rate Limiter (TRL). Add the IGBTrlTimer structure and corresponding fields to IGBCore to track TRL state (timers, throttling status, and target rates) per queue. Initialize and free these timers during the device realize/uninit lifecycle, and reset them on device reset.
Signed-off-by: Josh Hilke <[email protected]> --- hw/net/igb_common.h | 1 + hw/net/igb_core.c | 17 +++++++++++++++++ hw/net/igb_core.h | 11 +++++++++++ hw/net/igb_regs.h | 11 +++++++++++ 4 files changed, 40 insertions(+) diff --git a/hw/net/igb_common.h b/hw/net/igb_common.h index b316a5b..8c0a0cf 100644 --- a/hw/net/igb_common.h +++ b/hw/net/igb_common.h @@ -148,6 +148,7 @@ enum { defreg(MTA_A), defreg(VTIVAR), defreg(VTIVAR_MISC), + defreg(TRLDQSEL), defreg(TRLRC), }; uint64_t igb_mmio_read(void *opaque, hwaddr addr, unsigned size); diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c index 45d8fd7..64f21c1 100644 --- a/hw/net/igb_core.c +++ b/hw/net/igb_core.c @@ -4282,6 +4282,11 @@ igb_autoneg_resume(IGBCore *core) } } +static void igb_trl_timer_cb(void *opaque) +{ + /* Stub */ +} + void igb_core_pci_realize(IGBCore *core, const uint16_t *eeprom_templ, @@ -4296,6 +4301,11 @@ igb_core_pci_realize(IGBCore *core, for (i = 0; i < IGB_NUM_QUEUES; i++) { net_tx_pkt_init(&core->tx[i].tx_pkt, E1000E_MAX_TX_FRAGS); + core->trl_timer[i].timer = + timer_new_ns(QEMU_CLOCK_VIRTUAL, igb_trl_timer_cb, + &core->trl_timer[i]); + core->trl_timer[i].core = core; + core->trl_timer[i].queue_idx = i; } net_rx_pkt_init(&core->rx_pkt); @@ -4319,6 +4329,7 @@ igb_core_pci_uninit(IGBCore *core) for (i = 0; i < IGB_NUM_QUEUES; i++) { net_tx_pkt_uninit(core->tx[i].tx_pkt); + timer_free(core->trl_timer[i].timer); } net_rx_pkt_uninit(core->rx_pkt); @@ -4469,6 +4480,12 @@ static void igb_reset(IGBCore *core, bool sw) igb_intrmgr_reset(core); + for (i = 0; i < IGB_NUM_QUEUES; i++) { + timer_del(core->trl_timer[i].timer); + core->trl_throttled[i] = false; + core->trl_target_rate[i] = 0; + } + memset(core->phy, 0, sizeof core->phy); memcpy(core->phy, igb_phy_reg_init, sizeof igb_phy_reg_init); diff --git a/hw/net/igb_core.h b/hw/net/igb_core.h index d70b54e..ffd45ed 100644 --- a/hw/net/igb_core.h +++ b/hw/net/igb_core.h @@ -63,6 +63,12 @@ typedef struct IGBIntrDelayTimer_st { IGBCore *core; } IGBIntrDelayTimer; +typedef struct IGBTrlTimer_st { + QEMUTimer *timer; + IGBCore *core; + int queue_idx; +} IGBTrlTimer; + struct IGBCore { uint32_t mac[E1000E_MAC_SIZE]; uint16_t phy[MAX_PHY_REG_ADDRESS + 1]; @@ -99,6 +105,11 @@ struct IGBCore { void (*owner_start_recv)(PCIDevice *d); int64_t timadj; + + /* Transmit Rate Limiting */ + IGBTrlTimer trl_timer[IGB_NUM_QUEUES]; + bool trl_throttled[IGB_NUM_QUEUES]; + uint64_t trl_target_rate[IGB_NUM_QUEUES]; /* in bytes per second */ }; void diff --git a/hw/net/igb_regs.h b/hw/net/igb_regs.h index 4dc4c31..f7895ef 100644 --- a/hw/net/igb_regs.h +++ b/hw/net/igb_regs.h @@ -718,4 +718,15 @@ static inline uint8_t igb_ivar_entry_tx(uint8_t i) return i < 8 ? i * 4 + 1 : (i - 8) * 4 + 3; } +/* Transmit Rate Limiting */ +#define E1000_TRLDQSEL 0x03604 +#define E1000_TRLRC 0x036B0 + +#define E1000_TRLRC_RS_ENA BIT(31) +#define E1000_TRLRC_RF_DEC_MASK 0x3FFF +#define E1000_TRLRC_RF_INT_MASK 0x3FF + +/* 1 Gbps link rate in bytes per second (1,000,000,000 bits/s / 8) */ +#define E1000_LINK_RATE_1GBPS 125000000ULL + #endif -- 2.54.0.1136.gdb2ca164c4-goog
