return rc;
 }
 
+static int efx_ef10_rx_pull_rss_config(struct efx_nic *efx)
+{
+       struct efx_ef10_nic_data *nic_data = efx->nic_data;
+       MCDI_DECLARE_BUF(inbuf, MC_CMD_RSS_CONTEXT_GET_TABLE_IN_LEN);
+       MCDI_DECLARE_BUF(tablebuf, MC_CMD_RSS_CONTEXT_GET_TABLE_OUT_LEN);
+       MCDI_DECLARE_BUF(keybuf, MC_CMD_RSS_CONTEXT_GET_KEY_OUT_LEN);
+       size_t outlen;
+       int rc, i;
+
+       BUILD_BUG_ON(MC_CMD_RSS_CONTEXT_GET_TABLE_IN_LEN !=
+                    MC_CMD_RSS_CONTEXT_GET_KEY_IN_LEN);
+
+       if (nic_data->rx_rss_context == EFX_EF10_RSS_CONTEXT_INVALID)
+               return -ENOENT;
+
+       MCDI_SET_DWORD(inbuf, RSS_CONTEXT_GET_TABLE_IN_RSS_CONTEXT_ID,
+                      nic_data->rx_rss_context);
+       BUILD_BUG_ON(ARRAY_SIZE(efx->rx_indir_table) !=
+                    MC_CMD_RSS_CONTEXT_GET_TABLE_OUT_INDIRECTION_TABLE_LEN);
+       rc = efx_mcdi_rpc(efx, MC_CMD_RSS_CONTEXT_GET_TABLE, inbuf, sizeof(inbuf),
+                         tablebuf, sizeof(tablebuf), &outlen);
+       if (rc != 0)
+               return rc;
+
+       if (WARN_ON(outlen != MC_CMD_RSS_CONTEXT_GET_TABLE_OUT_LEN))
+               return -EIO;
+
+       for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
+               efx->rx_indir_table[i] = MCDI_PTR(tablebuf,
+                               RSS_CONTEXT_GET_TABLE_OUT_INDIRECTION_TABLE)[i];
+
+       MCDI_SET_DWORD(inbuf, RSS_CONTEXT_GET_KEY_IN_RSS_CONTEXT_ID,
+                      nic_data->rx_rss_context);
+       BUILD_BUG_ON(ARRAY_SIZE(efx->rx_hash_key) !=
+                    MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
+       rc = efx_mcdi_rpc(efx, MC_CMD_RSS_CONTEXT_GET_KEY, inbuf, sizeof(inbuf),
+                         keybuf, sizeof(keybuf), &outlen);
+       if (rc != 0)
+               return rc;
+
+       if (WARN_ON(outlen != MC_CMD_RSS_CONTEXT_GET_KEY_OUT_LEN))
+               return -EIO;
+
+       for (i = 0; i < ARRAY_SIZE(efx->rx_hash_key); ++i)
+               efx->rx_hash_key[i] = MCDI_PTR(
+                               keybuf, RSS_CONTEXT_GET_KEY_OUT_TOEPLITZ_KEY)[i];
+
+       return 0;
+}
+
 static int efx_ef10_pf_rx_push_rss_config(struct efx_nic *efx, bool user,
                                          const u32 *rx_indir_table,
                                          const u8 *key)
        .tx_write = efx_ef10_tx_write,
        .tx_limit_len = efx_ef10_tx_limit_len,
        .rx_push_rss_config = efx_ef10_vf_rx_push_rss_config,
+       .rx_pull_rss_config = efx_ef10_rx_pull_rss_config,
        .rx_probe = efx_ef10_rx_probe,
        .rx_init = efx_ef10_rx_init,
        .rx_remove = efx_ef10_rx_remove,
        .tx_write = efx_ef10_tx_write,
        .tx_limit_len = efx_ef10_tx_limit_len,
        .rx_push_rss_config = efx_ef10_pf_rx_push_rss_config,
+       .rx_pull_rss_config = efx_ef10_rx_pull_rss_config,
        .rx_probe = efx_ef10_rx_probe,
        .rx_init = efx_ef10_rx_init,
        .rx_remove = efx_ef10_rx_remove,
 
                                u8 *hfunc)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
+       int rc;
+
+       rc = efx->type->rx_pull_rss_config(efx);
+       if (rc)
+               return rc;
 
        if (hfunc)
                *hfunc = ETH_RSS_HASH_TOP;
 
        }
 }
 
+void efx_farch_rx_pull_indir_table(struct efx_nic *efx)
+{
+       size_t i = 0;
+       efx_dword_t dword;
+
+       BUILD_BUG_ON(ARRAY_SIZE(efx->rx_indir_table) !=
+                    FR_BZ_RX_INDIRECTION_TBL_ROWS);
+
+       for (i = 0; i < FR_BZ_RX_INDIRECTION_TBL_ROWS; i++) {
+               efx_readd(efx, &dword,
+                          FR_BZ_RX_INDIRECTION_TBL +
+                          FR_BZ_RX_INDIRECTION_TBL_STEP * i);
+               efx->rx_indir_table[i] = EFX_DWORD_FIELD(dword, FRF_BZ_IT_QUEUE);
+       }
+}
+
 /* Looks at available SRAM resources and works out how many queues we
  * can support, and where things like descriptor caches should live.
  *
 
  * @tx_remove: Free resources for TX queue
  * @tx_write: Write TX descriptors and doorbell
  * @rx_push_rss_config: Write RSS hash key and indirection table to the NIC
+ * @rx_pull_rss_config: Read RSS hash key and indirection table back from the NIC
  * @rx_probe: Allocate resources for RX queue
  * @rx_init: Initialise RX queue on the NIC
  * @rx_remove: Free resources for RX queue
                                     dma_addr_t dma_addr, unsigned int len);
        int (*rx_push_rss_config)(struct efx_nic *efx, bool user,
                                  const u32 *rx_indir_table, const u8 *key);
+       int (*rx_pull_rss_config)(struct efx_nic *efx);
        int (*rx_probe)(struct efx_rx_queue *rx_queue);
        void (*rx_init)(struct efx_rx_queue *rx_queue);
        void (*rx_remove)(struct efx_rx_queue *rx_queue);
 
 void efx_farch_init_common(struct efx_nic *efx);
 void efx_ef10_handle_drain_event(struct efx_nic *efx);
 void efx_farch_rx_push_indir_table(struct efx_nic *efx);
+void efx_farch_rx_pull_indir_table(struct efx_nic *efx);
 
 int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
                         unsigned int len, gfp_t gfp_flags);
 
        return rc;
 }
 
+static int siena_rx_pull_rss_config(struct efx_nic *efx)
+{
+       efx_oword_t temp;
+
+       /* Read from IPv6 RSS key as that's longer (the IPv4 key is just the
+        * first 128 bits of the same key, assuming it's been set by
+        * siena_rx_push_rss_config, below)
+        */
+       efx_reado(efx, &temp, FR_CZ_RX_RSS_IPV6_REG1);
+       memcpy(efx->rx_hash_key, &temp, sizeof(temp));
+       efx_reado(efx, &temp, FR_CZ_RX_RSS_IPV6_REG2);
+       memcpy(efx->rx_hash_key + sizeof(temp), &temp, sizeof(temp));
+       efx_reado(efx, &temp, FR_CZ_RX_RSS_IPV6_REG3);
+       memcpy(efx->rx_hash_key + 2 * sizeof(temp), &temp,
+              FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8);
+       efx_farch_rx_pull_indir_table(efx);
+       return 0;
+}
+
 static int siena_rx_push_rss_config(struct efx_nic *efx, bool user,
                                    const u32 *rx_indir_table, const u8 *key)
 {
        .tx_write = efx_farch_tx_write,
        .tx_limit_len = efx_farch_tx_limit_len,
        .rx_push_rss_config = siena_rx_push_rss_config,
+       .rx_pull_rss_config = siena_rx_pull_rss_config,
        .rx_probe = efx_farch_rx_probe,
        .rx_init = efx_farch_rx_init,
        .rx_remove = efx_farch_rx_remove,