Add a unit test to verify register writes/reads to the rate limit register (TRLC) return the correct value based on which queue is currently selected in the queue selection register (TRLDQSEL).
Signed-off-by: Josh Hilke <[email protected]> --- tests/qtest/igb-test.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/qtest/igb-test.c b/tests/qtest/igb-test.c index 3d397ea..119be6a 100644 --- a/tests/qtest/igb-test.c +++ b/tests/qtest/igb-test.c @@ -45,6 +45,20 @@ static const struct eth_header packet = { .h_source = E1000E_ADDRESS, }; +/* + * Calculate TRL rate factor for a given target rate. + * + * Rate Factor = 1 Gbps / Target Rate. + * + * The hardware TRLRC register stores the rate factor as a fixed-point number + * with 14 fractional bits. Scale 1Gbps by 2^14 before dividing to preserve + * precision in integer arithmetic. + */ +static uint32_t igb_trl_get_rate_factor(uint64_t rate_bytes_s) +{ + return (E1000_LINK_RATE_1GBPS << 14) / rate_bytes_s; +} + static void igb_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc) { union e1000_adv_tx_desc descr; @@ -191,6 +205,41 @@ static void test_igb_multiple_transfers(void *obj, void *data, } +/* + * Verify the rate limit value register (TRLC) returns the correct value based + * on which queue is selected (TRLDQSEL). + */ +static void test_igb_transmit_rate_limiter_regs(void *obj, void *data, + QGuestAllocator *alloc) +{ + QOSGraphObject *e_object = obj; + QE1000E_PCI *e1000e = obj; + QPCIDevice *dev = e_object->get_driver(e_object, "pci-device"); + QE1000E *d = &e1000e->e1000e; + const int qidx0 = 0, qidx1 = 1; + uint32_t val0, val1; + + if (qpci_check_buggy_msi(dev)) { + return; + } + + e1000e_macreg_write(d, E1000_TRLDQSEL, qidx0); + val0 = E1000_TRLRC_RS_ENA | + igb_trl_get_rate_factor(E1000_LINK_RATE_1GBPS / 1000); + e1000e_macreg_write(d, E1000_TRLRC, val0); + + e1000e_macreg_write(d, E1000_TRLDQSEL, qidx1); + val1 = E1000_TRLRC_RS_ENA | + igb_trl_get_rate_factor(E1000_LINK_RATE_1GBPS / 500); + e1000e_macreg_write(d, E1000_TRLRC, val1); + + e1000e_macreg_write(d, E1000_TRLDQSEL, qidx0); + g_assert_cmphex(e1000e_macreg_read(d, E1000_TRLRC), ==, val0); + + e1000e_macreg_write(d, E1000_TRLDQSEL, qidx1); + g_assert_cmphex(e1000e_macreg_read(d, E1000_TRLRC), ==, val1); +} + static void data_test_clear(void *sockets) { int *test_sockets = sockets; @@ -247,6 +296,8 @@ static void register_igb_test(void) qos_add_test("rx", "igb", test_igb_rx, &opts); qos_add_test("multiple_transfers", "igb", test_igb_multiple_transfers, &opts); + qos_add_test("transmit_rate_limiter_regs", "igb", + test_igb_transmit_rate_limiter_regs, &opts); #endif opts.before = data_test_init_no_socket; -- 2.54.0.1136.gdb2ca164c4-goog
