--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#include "roc_api.h"
+#include "roc_priv.h"
+
+void
+roc_nix_rss_key_default_fill(struct roc_nix *roc_nix,
+ uint8_t key[ROC_NIX_RSS_KEY_LEN])
+{
+ PLT_SET_USED(roc_nix);
+ const uint8_t default_key[ROC_NIX_RSS_KEY_LEN] = {
+ 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED,
+ 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD,
+ 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED,
+ 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD,
+ 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD};
+
+ memcpy(key, default_key, ROC_NIX_RSS_KEY_LEN);
+}
+
+void
+roc_nix_rss_key_set(struct roc_nix *roc_nix,
+ const uint8_t key[ROC_NIX_RSS_KEY_LEN])
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ const uint64_t *keyptr;
+ uint64_t val;
+ uint32_t idx;
+
+ keyptr = (const uint64_t *)key;
+ for (idx = 0; idx < (ROC_NIX_RSS_KEY_LEN >> 3); idx++) {
+ val = plt_cpu_to_be_64(keyptr[idx]);
+ plt_write64(val, nix->base + NIX_LF_RX_SECRETX(idx));
+ }
+}
+
+void
+roc_nix_rss_key_get(struct roc_nix *roc_nix, uint8_t key[ROC_NIX_RSS_KEY_LEN])
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ uint64_t *keyptr = (uint64_t *)key;
+ uint64_t val;
+ uint32_t idx;
+
+ for (idx = 0; idx < (ROC_NIX_RSS_KEY_LEN >> 3); idx++) {
+ val = plt_read64(nix->base + NIX_LF_RX_SECRETX(idx));
+ keyptr[idx] = plt_be_to_cpu_64(val);
+ }
+}
+
+static int
+nix_cn9k_rss_reta_set(struct nix *nix, uint8_t group,
+ uint16_t reta[ROC_NIX_RSS_RETA_MAX])
+{
+ struct mbox *mbox = (&nix->dev)->mbox;
+ struct nix_aq_enq_req *req;
+ uint16_t idx;
+ int rc;
+
+ for (idx = 0; idx < nix->reta_sz; idx++) {
+ req = mbox_alloc_msg_nix_aq_enq(mbox);
+ if (!req) {
+ /* The shared memory buffer can be full.
+ * Flush it and retry
+ */
+ rc = mbox_process(mbox);
+ if (rc < 0)
+ return rc;
+ req = mbox_alloc_msg_nix_aq_enq(mbox);
+ if (!req)
+ return NIX_ERR_NO_MEM;
+ }
+ req->rss.rq = reta[idx];
+ /* Fill AQ info */
+ req->qidx = (group * nix->reta_sz) + idx;
+ req->ctype = NIX_AQ_CTYPE_RSS;
+ req->op = NIX_AQ_INSTOP_INIT;
+ }
+
+ rc = mbox_process(mbox);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static int
+nix_rss_reta_set(struct nix *nix, uint8_t group,
+ uint16_t reta[ROC_NIX_RSS_RETA_MAX])
+{
+ struct mbox *mbox = (&nix->dev)->mbox;
+ struct nix_cn10k_aq_enq_req *req;
+ uint16_t idx;
+ int rc;
+
+ for (idx = 0; idx < nix->reta_sz; idx++) {
+ req = mbox_alloc_msg_nix_cn10k_aq_enq(mbox);
+ if (!req) {
+ /* The shared memory buffer can be full.
+ * Flush it and retry
+ */
+ rc = mbox_process(mbox);
+ if (rc < 0)
+ return rc;
+ req = mbox_alloc_msg_nix_cn10k_aq_enq(mbox);
+ if (!req)
+ return NIX_ERR_NO_MEM;
+ }
+ req->rss.rq = reta[idx];
+ /* Fill AQ info */
+ req->qidx = (group * nix->reta_sz) + idx;
+ req->ctype = NIX_AQ_CTYPE_RSS;
+ req->op = NIX_AQ_INSTOP_INIT;
+ }
+
+ rc = mbox_process(mbox);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+int
+roc_nix_rss_reta_set(struct roc_nix *roc_nix, uint8_t group,
+ uint16_t reta[ROC_NIX_RSS_RETA_MAX])
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ int rc;
+
+ if (group >= ROC_NIX_RSS_GRPS)
+ return NIX_ERR_PARAM;
+
+ if (roc_model_is_cn9k())
+ rc = nix_cn9k_rss_reta_set(nix, group, reta);
+ else
+ rc = nix_rss_reta_set(nix, group, reta);
+ if (rc)
+ return rc;
+
+ memcpy(&nix->reta[group], reta, ROC_NIX_RSS_RETA_MAX);
+ return 0;
+}
+
+int
+roc_nix_rss_reta_get(struct roc_nix *roc_nix, uint8_t group,
+ uint16_t reta[ROC_NIX_RSS_RETA_MAX])
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+ if (group >= ROC_NIX_RSS_GRPS)
+ return NIX_ERR_PARAM;
+
+ memcpy(reta, &nix->reta[group], ROC_NIX_RSS_RETA_MAX);
+ return 0;
+}
+
+int
+roc_nix_rss_flowkey_set(struct roc_nix *roc_nix, uint8_t *alg_idx,
+ uint32_t flowkey, uint8_t group, int mcam_index)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct nix_rss_flowkey_cfg_rsp *rss_rsp;
+ struct mbox *mbox = (&nix->dev)->mbox;
+ struct nix_rss_flowkey_cfg *cfg;
+ int rc = -ENOSPC;
+
+ if (group >= ROC_NIX_RSS_GRPS)
+ return NIX_ERR_PARAM;
+
+ cfg = mbox_alloc_msg_nix_rss_flowkey_cfg(mbox);
+ if (cfg == NULL)
+ return rc;
+ cfg->flowkey_cfg = flowkey;
+ cfg->mcam_index = mcam_index; /* -1 indicates default group */
+ cfg->group = group; /* 0 is default group */
+ rc = mbox_process_msg(mbox, (void *)&rss_rsp);
+ if (rc)
+ return rc;
+ if (alg_idx)
+ *alg_idx = rss_rsp->alg_idx;
+
+ return rc;
+}
+
+int
+roc_nix_rss_default_setup(struct roc_nix *roc_nix, uint32_t flowkey)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ uint16_t idx, qcnt = nix->nb_rx_queues;
+ uint16_t reta[ROC_NIX_RSS_RETA_MAX];
+ uint8_t key[ROC_NIX_RSS_KEY_LEN];
+ uint8_t alg_idx;
+ int rc;
+
+ roc_nix_rss_key_default_fill(roc_nix, key);
+ roc_nix_rss_key_set(roc_nix, key);
+
+ /* Update default RSS RETA */
+ for (idx = 0; idx < nix->reta_sz; idx++)
+ reta[idx] = idx % qcnt;
+ rc = roc_nix_rss_reta_set(roc_nix, 0, reta);
+ if (rc) {
+ plt_err("Failed to set RSS reta table rc=%d", rc);
+ goto fail;
+ }
+
+ /* Update the default flowkey */
+ rc = roc_nix_rss_flowkey_set(roc_nix, &alg_idx, flowkey,
+ ROC_NIX_RSS_GROUP_DEFAULT, -1);
+ if (rc) {
+ plt_err("Failed to set RSS flowkey rc=%d", rc);
+ goto fail;
+ }
+
+ nix->rss_alg_idx = alg_idx;
+fail:
+ return rc;
+}