return 0;
 }
 
+static void set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
+{
+       struct nix_rx_flowkey_alg *field = NULL;
+       int idx, key_type;
+
+       if (!alg)
+               return;
+
+       /* FIELD0: IPv4
+        * FIELD1: IPv6
+        * FIELD2: TCP/UDP/SCTP/ALL
+        * FIELD3: Unused
+        * FIELD4: Unused
+        *
+        * Each of the 32 possible flow key algorithm definitions should
+        * fall into above incremental config (except ALG0). Otherwise a
+        * single NPC MCAM entry is not sufficient for supporting RSS.
+        *
+        * If a different definition or combination needed then NPC MCAM
+        * has to be programmed to filter such pkts and it's action should
+        * point to this definition to calculate flowtag or hash.
+        */
+       for (idx = 0; idx < 32; idx++) {
+               key_type = flow_cfg & BIT_ULL(idx);
+               if (!key_type)
+                       continue;
+               switch (key_type) {
+               case FLOW_KEY_TYPE_PORT:
+                       field = &alg[0];
+                       field->sel_chan = true;
+                       /* This should be set to 1, when SEL_CHAN is set */
+                       field->bytesm1 = 1;
+                       break;
+               case FLOW_KEY_TYPE_IPV4:
+                       field = &alg[0];
+                       field->lid = NPC_LID_LC;
+                       field->ltype_match = NPC_LT_LC_IP;
+                       field->hdr_offset = 12; /* SIP offset */
+                       field->bytesm1 = 7; /* SIP + DIP, 8 bytes */
+                       field->ltype_mask = 0xF; /* Match only IPv4 */
+                       break;
+               case FLOW_KEY_TYPE_IPV6:
+                       field = &alg[1];
+                       field->lid = NPC_LID_LC;
+                       field->ltype_match = NPC_LT_LC_IP6;
+                       field->hdr_offset = 8; /* SIP offset */
+                       field->bytesm1 = 31; /* SIP + DIP, 32 bytes */
+                       field->ltype_mask = 0xF; /* Match only IPv6 */
+                       break;
+               case FLOW_KEY_TYPE_TCP:
+               case FLOW_KEY_TYPE_UDP:
+               case FLOW_KEY_TYPE_SCTP:
+                       field = &alg[2];
+                       field->lid = NPC_LID_LD;
+                       field->bytesm1 = 3; /* Sport + Dport, 4 bytes */
+                       if (key_type == FLOW_KEY_TYPE_TCP)
+                               field->ltype_match |= NPC_LT_LD_TCP;
+                       else if (key_type == FLOW_KEY_TYPE_UDP)
+                               field->ltype_match |= NPC_LT_LD_UDP;
+                       else if (key_type == FLOW_KEY_TYPE_SCTP)
+                               field->ltype_match |= NPC_LT_LD_SCTP;
+                       field->key_offset = 32; /* After IPv4/v6 SIP, DIP */
+                       field->ltype_mask = ~field->ltype_match;
+                       break;
+               }
+               if (field)
+                       field->ena = 1;
+               field = NULL;
+       }
+}
+
+static void nix_rx_flowkey_alg_cfg(struct rvu *rvu, int blkaddr)
+{
+#define FIELDS_PER_ALG 5
+       u64 field[FLOW_KEY_ALG_MAX][FIELDS_PER_ALG];
+       u32 flowkey_cfg, minkey_cfg;
+       int alg, fid;
+
+       memset(&field, 0, sizeof(u64) * FLOW_KEY_ALG_MAX * FIELDS_PER_ALG);
+
+       /* Only incoming channel number */
+       flowkey_cfg = FLOW_KEY_TYPE_PORT;
+       set_flowkey_fields((void *)&field[FLOW_KEY_ALG_PORT], flowkey_cfg);
+
+       /* For a incoming pkt if none of the fields match then flowkey
+        * will be zero, hence tag generated will also be zero.
+        * RSS entry at rsse_index = NIX_AF_LF()_RSS_GRP()[OFFSET] will
+        * be used to queue the packet.
+        */
+
+       /* IPv4/IPv6 SIP/DIPs */
+       flowkey_cfg = FLOW_KEY_TYPE_IPV4 | FLOW_KEY_TYPE_IPV6;
+       set_flowkey_fields((void *)&field[FLOW_KEY_ALG_IP], flowkey_cfg);
+
+       /* TCPv4/v6 4-tuple, SIP, DIP, Sport, Dport */
+       minkey_cfg = flowkey_cfg;
+       flowkey_cfg = minkey_cfg | FLOW_KEY_TYPE_TCP;
+       set_flowkey_fields((void *)&field[FLOW_KEY_ALG_TCP], flowkey_cfg);
+
+       /* UDPv4/v6 4-tuple, SIP, DIP, Sport, Dport */
+       flowkey_cfg = minkey_cfg | FLOW_KEY_TYPE_UDP;
+       set_flowkey_fields((void *)&field[FLOW_KEY_ALG_UDP], flowkey_cfg);
+
+       /* SCTPv4/v6 4-tuple, SIP, DIP, Sport, Dport */
+       flowkey_cfg = minkey_cfg | FLOW_KEY_TYPE_SCTP;
+       set_flowkey_fields((void *)&field[FLOW_KEY_ALG_SCTP], flowkey_cfg);
+
+       /* TCP/UDP v4/v6 4-tuple, rest IP pkts 2-tuple */
+       flowkey_cfg = minkey_cfg | FLOW_KEY_TYPE_TCP | FLOW_KEY_TYPE_UDP;
+       set_flowkey_fields((void *)&field[FLOW_KEY_ALG_TCP_UDP], flowkey_cfg);
+
+       /* TCP/SCTP v4/v6 4-tuple, rest IP pkts 2-tuple */
+       flowkey_cfg = minkey_cfg | FLOW_KEY_TYPE_TCP | FLOW_KEY_TYPE_SCTP;
+       set_flowkey_fields((void *)&field[FLOW_KEY_ALG_TCP_SCTP], flowkey_cfg);
+
+       /* UDP/SCTP v4/v6 4-tuple, rest IP pkts 2-tuple */
+       flowkey_cfg = minkey_cfg | FLOW_KEY_TYPE_UDP | FLOW_KEY_TYPE_SCTP;
+       set_flowkey_fields((void *)&field[FLOW_KEY_ALG_UDP_SCTP], flowkey_cfg);
+
+       /* TCP/UDP/SCTP v4/v6 4-tuple, rest IP pkts 2-tuple */
+       flowkey_cfg = minkey_cfg | FLOW_KEY_TYPE_TCP |
+                     FLOW_KEY_TYPE_UDP | FLOW_KEY_TYPE_SCTP;
+       set_flowkey_fields((void *)&field[FLOW_KEY_ALG_TCP_UDP_SCTP],
+                          flowkey_cfg);
+
+       for (alg = 0; alg < FLOW_KEY_ALG_MAX; alg++) {
+               for (fid = 0; fid < FIELDS_PER_ALG; fid++)
+                       rvu_write64(rvu, blkaddr,
+                                   NIX_AF_RX_FLOW_KEY_ALGX_FIELDX(alg, fid),
+                                   field[alg][fid]);
+       }
+}
+
 static int nix_calibrate_x2p(struct rvu *rvu, int blkaddr)
 {
        int idx, err;
                            (NPC_LID_LD << 8) | (NPC_LT_LD_TCP << 4) | 0x0F);
                rvu_write64(rvu, blkaddr, NIX_AF_RX_DEF_OIP4,
                            (NPC_LID_LC << 8) | (NPC_LT_LC_IP << 4) | 0x0F);
+
+               nix_rx_flowkey_alg_cfg(rvu, blkaddr);
        }
        return 0;
 }