The IGC RETA register stores four 8-bit queue indexes.
igc_rss_configure() and igc_add_rss_filter() used a fresh
uninitialized union for each table entry and wrote the register only
every fourth entry. As a result, three bytes of each RETA register
came from stack garbage.

Build the register a word at a time and initialize all four queue
indexes before writing it.

Fixes: a5aeb2b9e225 ("net/igc: support Rx and Tx")
Fixes: 746664d546fb ("net/igc: support flow API")
Cc: [email protected]
Signed-off-by: Shuzo Ichiyoshi <[email protected]>
---
 drivers/net/intel/e1000/igc_txrx.c | 49 ++++++++++++++++--------------
 1 file changed, 26 insertions(+), 23 deletions(-)

diff --git a/drivers/net/intel/e1000/igc_txrx.c 
b/drivers/net/intel/e1000/igc_txrx.c
index c13460f381..1ab8f2079d 100644
--- a/drivers/net/intel/e1000/igc_txrx.c
+++ b/drivers/net/intel/e1000/igc_txrx.c
@@ -828,17 +828,20 @@ igc_rss_configure(struct rte_eth_dev *dev)
        uint16_t i;
 
        /* Fill in redirection table. */
-       for (i = 0; i < IGC_RSS_RDT_SIZD; i++) {
-               union igc_rss_reta_reg reta;
-               uint16_t q_idx, reta_idx;
-
-               q_idx = (uint8_t)((dev->data->nb_rx_queues > 1) ?
-                                  i % dev->data->nb_rx_queues : 0);
-               reta_idx = i % sizeof(reta);
-               reta.bytes[reta_idx] = q_idx;
-               if (reta_idx == sizeof(reta) - 1)
-                       E1000_WRITE_REG_LE_VALUE(hw,
-                               E1000_RETA(i / sizeof(reta)), reta.dword);
+       for (i = 0; i < IGC_RSS_RDT_SIZD; i += IGC_RSS_RDT_REG_SIZE) {
+               union igc_rss_reta_reg reta = { .dword = 0 };
+               uint16_t reta_idx;
+
+               RTE_BUILD_BUG_ON(sizeof(reta.bytes) != IGC_RSS_RDT_REG_SIZE);
+               for (reta_idx = 0; reta_idx < IGC_RSS_RDT_REG_SIZE; reta_idx++) 
{
+                       uint16_t q_idx;
+
+                       q_idx = (uint8_t)((dev->data->nb_rx_queues > 1) ?
+                               (i + reta_idx) % dev->data->nb_rx_queues : 0);
+                       reta.bytes[reta_idx] = q_idx;
+               }
+               E1000_WRITE_REG_LE_VALUE(hw,
+                       E1000_RETA(i / IGC_RSS_RDT_REG_SIZE), reta.dword);
        }
 
        /*
@@ -944,18 +947,18 @@ igc_add_rss_filter(struct rte_eth_dev *dev, struct 
igc_rss_filter *rss)
        igc_rss_conf_set(rss_filter, &rss->conf);
 
        /* Fill in redirection table. */
-       for (i = 0, j = 0; i < IGC_RSS_RDT_SIZD; i++, j++) {
-               union igc_rss_reta_reg reta;
-               uint16_t q_idx, reta_idx;
-
-               if (j == rss->conf.queue_num)
-                       j = 0;
-               q_idx = rss->conf.queue[j];
-               reta_idx = i % sizeof(reta);
-               reta.bytes[reta_idx] = q_idx;
-               if (reta_idx == sizeof(reta) - 1)
-                       E1000_WRITE_REG_LE_VALUE(hw,
-                               E1000_RETA(i / sizeof(reta)), reta.dword);
+       for (i = 0, j = 0; i < IGC_RSS_RDT_SIZD; i += IGC_RSS_RDT_REG_SIZE) {
+               union igc_rss_reta_reg reta = { .dword = 0 };
+               uint16_t reta_idx;
+
+               RTE_BUILD_BUG_ON(sizeof(reta.bytes) != IGC_RSS_RDT_REG_SIZE);
+               for (reta_idx = 0; reta_idx < IGC_RSS_RDT_REG_SIZE; reta_idx++, 
j++) {
+                       if (j == rss->conf.queue_num)
+                               j = 0;
+                       reta.bytes[reta_idx] = rss->conf.queue[j];
+               }
+               E1000_WRITE_REG_LE_VALUE(hw,
+                       E1000_RETA(i / IGC_RSS_RDT_REG_SIZE), reta.dword);
        }
 
        if (rss_conf.rss_key == NULL)
-- 
2.43.0

Reply via email to