Implement write handlers for TLDQSEL and TRLRC registers to allow the guest to configure Transmit Rate Limiting. Translate the register Rate Factor into a physical target rate (bytes/sec) per queue. Disable TRL and clear timers when the link status changes or when TRL is disabled by the guest.
Signed-off-by: Josh Hilke <[email protected]> --- hw/net/igb_core.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c index c94e8d3..dea8136 100644 --- a/hw/net/igb_core.c +++ b/hw/net/igb_core.c @@ -2137,11 +2137,27 @@ igb_set_phy_ctrl(IGBCore *core, uint16_t val) } } +static void igb_trl_disable_queue(IGBCore *core, int qidx) +{ + core->trl[qidx].trlrc = 0; + + timer_del(core->trl[qidx].timer); +} + +static void igb_trl_disable(IGBCore *core) +{ + for (int i = 0; i < IGB_NUM_QUEUES; i++) { + igb_trl_disable_queue(core, i); + } +} + void igb_core_set_link_status(IGBCore *core) { NetClientState *nc = qemu_get_queue(core->owner_nic); uint32_t old_status = core->mac[STATUS]; + igb_trl_disable(core); + trace_e1000e_link_status_changed(nc->link_down ? false : true); if (nc->link_down) { @@ -2624,6 +2640,42 @@ static void igb_set_vtivar(IGBCore *core, int index, uint32_t val) */ } +static uint32_t igb_get_trlrc(IGBCore *core, int index) +{ + int qidx = core->mac[TRLDQSEL]; + + return core->trl[qidx].trlrc; +} + +static void igb_set_trldqsel(IGBCore *core, int index, uint32_t val) +{ + core->mac[index] = val & 0xF; +} + +static void igb_set_trlrc(IGBCore *core, int index, uint32_t val) +{ + uint64_t rf_scaled; + int qidx; + + qidx = core->mac[TRLDQSEL]; + core->trl[qidx].trlrc = val; + + if (!igb_trl_enabled(val)) { + goto disable; + } + + rf_scaled = igb_trl_get_scaled_rate_factor(val); + + /* Zero is not a valid rate factor, treat as disabled */ + if (rf_scaled == 0) { + goto disable; + } + return; + +disable: + igb_trl_disable_queue(core, qidx); +} + static inline void igb_autoneg_timer(void *opaque) { @@ -3679,6 +3731,7 @@ static const readops igb_macreg_readops[] = { [RQDPC15] = igb_mac_read_clr4, [VTIVAR ... VTIVAR + 7] = igb_mac_readreg, [VTIVAR_MISC ... VTIVAR_MISC + 7] = igb_mac_readreg, + [TRLRC] = igb_get_trlrc, }; enum { IGB_NREADOPS = ARRAY_SIZE(igb_macreg_readops) }; @@ -4127,7 +4180,9 @@ static const writeops igb_macreg_writeops[] = { [PVTEICR6] = igb_set_vteicr, [PVTEICR7] = igb_set_vteicr, [VTIVAR ... VTIVAR + 7] = igb_set_vtivar, - [VTIVAR_MISC ... VTIVAR_MISC + 7] = igb_mac_writereg + [VTIVAR_MISC ... VTIVAR_MISC + 7] = igb_mac_writereg, + [TRLDQSEL] = igb_set_trldqsel, + [TRLRC] = igb_set_trlrc }; enum { IGB_NWRITEOPS = ARRAY_SIZE(igb_macreg_writeops) }; -- 2.54.0.1136.gdb2ca164c4-goog
