new_ctrl = nn->dp.ctrl;
 
-       if (nn->dp.ctrl & NFP_NET_CFG_CTRL_RSS) {
+       if (nn->dp.ctrl & NFP_NET_CFG_CTRL_RSS_ANY) {
                nfp_net_rss_write_key(nn);
                nfp_net_rss_write_itbl(nn);
                nn_writel(nn, NFP_NET_CFG_RSS_CTRL, nn->rss_cfg);
                nn->fw_ver.resv, nn->fw_ver.class,
                nn->fw_ver.major, nn->fw_ver.minor,
                nn->max_mtu);
-       nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+       nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
                nn->cap,
                nn->cap & NFP_NET_CFG_CTRL_PROMISC  ? "PROMISC "  : "",
                nn->cap & NFP_NET_CFG_CTRL_L2BC     ? "L2BCFILT " : "",
                nn->cap & NFP_NET_CFG_CTRL_GATHER   ? "GATHER "   : "",
                nn->cap & NFP_NET_CFG_CTRL_LSO      ? "TSO1 "     : "",
                nn->cap & NFP_NET_CFG_CTRL_LSO2     ? "TSO2 "     : "",
-               nn->cap & NFP_NET_CFG_CTRL_RSS      ? "RSS "      : "",
+               nn->cap & NFP_NET_CFG_CTRL_RSS      ? "RSS1 "     : "",
+               nn->cap & NFP_NET_CFG_CTRL_RSS2     ? "RSS2 "     : "",
                nn->cap & NFP_NET_CFG_CTRL_L2SWITCH ? "L2SWITCH " : "",
                nn->cap & NFP_NET_CFG_CTRL_MSIXAUTO ? "AUTOMASK " : "",
                nn->cap & NFP_NET_CFG_CTRL_IRQMOD   ? "IRQMOD "   : "",
        struct nfp_net *nn = netdev_priv(netdev);
        int err;
 
-       nn->dp.chained_metadata_format = nn->fw_ver.major > 3;
-
        nn->dp.rx_dma_dir = DMA_FROM_DEVICE;
 
        /* Get some of the read-only fields from the BAR */
        nn->cap = nn_readl(nn, NFP_NET_CFG_CAP);
        nn->max_mtu = nn_readl(nn, NFP_NET_CFG_MAX_MTU);
 
+       /* Chained metadata is signalled by capabilities except in version 4 */
+       nn->dp.chained_metadata_format = nn->fw_ver.major == 4 ||
+                                        nn->cap & NFP_NET_CFG_CTRL_CHAIN_META;
+       if (nn->dp.chained_metadata_format && nn->fw_ver.major != 4)
+               nn->cap &= ~NFP_NET_CFG_CTRL_RSS;
+
        nfp_net_write_mac_addr(nn);
 
        /* Determine RX packet/metadata boundary offset */
                nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_LSO2 ?:
                                         NFP_NET_CFG_CTRL_LSO;
        }
-       if (nn->cap & NFP_NET_CFG_CTRL_RSS) {
+       if (nn->cap & NFP_NET_CFG_CTRL_RSS_ANY) {
                netdev->hw_features |= NETIF_F_RXHASH;
                nfp_net_rss_init(nn);
-               nn->dp.ctrl |= NFP_NET_CFG_CTRL_RSS;
+               nn->dp.ctrl |= nn->cap & NFP_NET_CFG_CTRL_RSS2 ?:
+                                        NFP_NET_CFG_CTRL_RSS;
        }
        if (nn->cap & NFP_NET_CFG_CTRL_VXLAN &&
            nn->cap & NFP_NET_CFG_CTRL_NVGRE) {
 
 #define   NFP_NET_CFG_CTRL_GATHER         (0x1 <<  9) /* Gather DMA */
 #define   NFP_NET_CFG_CTRL_LSO            (0x1 << 10) /* LSO/TSO (version 1) */
 #define   NFP_NET_CFG_CTRL_RINGCFG        (0x1 << 16) /* Ring runtime changes */
-#define   NFP_NET_CFG_CTRL_RSS            (0x1 << 17) /* RSS */
+#define   NFP_NET_CFG_CTRL_RSS           (0x1 << 17) /* RSS (version 1) */
 #define   NFP_NET_CFG_CTRL_IRQMOD         (0x1 << 18) /* Interrupt moderation */
 #define   NFP_NET_CFG_CTRL_RINGPRIO       (0x1 << 19) /* Ring priorities */
 #define   NFP_NET_CFG_CTRL_MSIXAUTO       (0x1 << 20) /* MSI-X auto-masking */
 #define   NFP_NET_CFG_CTRL_NVGRE         (0x1 << 25) /* NVGRE tunnel support */
 #define   NFP_NET_CFG_CTRL_BPF           (0x1 << 27) /* BPF offload capable */
 #define   NFP_NET_CFG_CTRL_LSO2                  (0x1 << 28) /* LSO/TSO (version 2) */
+#define   NFP_NET_CFG_CTRL_RSS2                  (0x1 << 29) /* RSS (version 2) */
 
 #define NFP_NET_CFG_CTRL_LSO_ANY       (NFP_NET_CFG_CTRL_LSO | \
                                         NFP_NET_CFG_CTRL_LSO2)
+#define NFP_NET_CFG_CTRL_RSS_ANY       (NFP_NET_CFG_CTRL_RSS | \
+                                        NFP_NET_CFG_CTRL_RSS2)
+#define NFP_NET_CFG_CTRL_CHAIN_META    NFP_NET_CFG_CTRL_RSS2
 
 #define NFP_NET_CFG_UPDATE              0x0004
 #define   NFP_NET_CFG_UPDATE_GEN          (0x1 <<  0) /* General update */
 
 
        cmd->data = 0;
 
-       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS))
+       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY))
                return -EOPNOTSUPP;
 
        nfp_rss_flag = ethtool_flow_to_nfp_flag(cmd->flow_type);
        u32 nfp_rss_flag;
        int err;
 
-       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS))
+       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY))
                return -EOPNOTSUPP;
 
        /* RSS only supports IP SA/DA and L4 src/dst ports  */
 {
        struct nfp_net *nn = netdev_priv(netdev);
 
-       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS))
+       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY))
                return 0;
 
        return ARRAY_SIZE(nn->rss_itbl);
 {
        struct nfp_net *nn = netdev_priv(netdev);
 
-       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS))
+       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY))
                return -EOPNOTSUPP;
 
        return nfp_net_rss_key_sz(nn);
        struct nfp_net *nn = netdev_priv(netdev);
        int i;
 
-       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS))
+       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY))
                return -EOPNOTSUPP;
 
        if (indir)
        struct nfp_net *nn = netdev_priv(netdev);
        int i;
 
-       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS) ||
+       if (!(nn->cap & NFP_NET_CFG_CTRL_RSS_ANY) ||
            !(hfunc == ETH_RSS_HASH_NO_CHANGE || hfunc == nn->rss_hfunc))
                return -EOPNOTSUPP;