Commit 2da48943 authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller
Browse files

octeontx2-pf: devlink params support to set mcam entry count



Added support for setting or modifying MCAM entry count at
runtime via devlink params.

commands:
  devlink dev param show
pci/0002:02:00.0:
  name mcam_count type driver-specific
    values:
      cmode runtime value 16

  devlink dev param set pci/0002:02:00.0 name mcam_count
				value 64 cmode runtime

Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarSubbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2e2a8126
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -7,7 +7,8 @@ obj-$(CONFIG_OCTEONTX2_PF) += rvu_nicpf.o
obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o

rvu_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o \
               otx2_ptp.o otx2_flows.o otx2_tc.o cn10k.o otx2_dmac_flt.o
rvu_nicvf-y := otx2_vf.o
               otx2_ptp.o otx2_flows.o otx2_tc.o cn10k.o otx2_dmac_flt.o \
               otx2_devlink.o
rvu_nicvf-y := otx2_vf.o otx2_devlink.o

ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af
+7 −1
Original line number Diff line number Diff line
@@ -19,11 +19,13 @@
#include <linux/timecounter.h>
#include <linux/soc/marvell/octeontx2/asm.h>
#include <net/pkt_cls.h>
#include <net/devlink.h>

#include <mbox.h>
#include <npc.h>
#include "otx2_reg.h"
#include "otx2_txrx.h"
#include "otx2_devlink.h"
#include <rvu_trace.h>

/* PCI device IDs */
@@ -376,6 +378,9 @@ struct otx2_nic {
	struct hwtstamp_config	tstamp;

	unsigned long		rq_bmap;

	/* Devlink */
	struct otx2_devlink	*dl;
};

static inline bool is_otx2_lbkvf(struct pci_dev *pdev)
@@ -818,7 +823,7 @@ int otx2_set_real_num_queues(struct net_device *netdev,
/* MCAM filter related APIs */
int otx2_mcam_flow_init(struct otx2_nic *pf);
int otx2vf_mcam_flow_init(struct otx2_nic *pfvf);
int otx2_alloc_mcam_entries(struct otx2_nic *pfvf);
int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count);
void otx2_mcam_flow_del(struct otx2_nic *pf);
int otx2_destroy_ntuple_flows(struct otx2_nic *pf);
int otx2_destroy_mcam_flows(struct otx2_nic *pfvf);
@@ -843,6 +848,7 @@ int otx2_init_tc(struct otx2_nic *nic);
void otx2_shutdown_tc(struct otx2_nic *nic);
int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type,
		  void *type_data);
int otx2_tc_alloc_ent_bitmap(struct otx2_nic *nic);
/* CGX/RPM DMAC filters support */
int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf);
int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u8 bit_pos);
+156 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Marvell RVU PF/VF Netdev Devlink
 *
 * Copyright (C) 2021 Marvell.
 */

#include "otx2_common.h"

/* Devlink Params APIs */
static int otx2_dl_mcam_count_validate(struct devlink *devlink, u32 id,
				       union devlink_param_value val,
				       struct netlink_ext_ack *extack)
{
	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
	struct otx2_nic *pfvf = otx2_dl->pfvf;
	struct otx2_flow_config *flow_cfg;

	if (!pfvf->flow_cfg) {
		NL_SET_ERR_MSG_MOD(extack,
				   "pfvf->flow_cfg not initialized");
		return -EINVAL;
	}

	flow_cfg = pfvf->flow_cfg;
	if (flow_cfg && flow_cfg->nr_flows) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Cannot modify count when there are active rules");
		return -EINVAL;
	}

	return 0;
}

static int otx2_dl_mcam_count_set(struct devlink *devlink, u32 id,
				  struct devlink_param_gset_ctx *ctx)
{
	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
	struct otx2_nic *pfvf = otx2_dl->pfvf;

	if (!pfvf->flow_cfg)
		return 0;

	otx2_alloc_mcam_entries(pfvf, ctx->val.vu16);
	otx2_tc_alloc_ent_bitmap(pfvf);

	return 0;
}

static int otx2_dl_mcam_count_get(struct devlink *devlink, u32 id,
				  struct devlink_param_gset_ctx *ctx)
{
	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
	struct otx2_nic *pfvf = otx2_dl->pfvf;
	struct otx2_flow_config *flow_cfg;

	if (!pfvf->flow_cfg) {
		ctx->val.vu16 = 0;
		return 0;
	}

	flow_cfg = pfvf->flow_cfg;
	ctx->val.vu16 = flow_cfg->max_flows;

	return 0;
}

enum otx2_dl_param_id {
	OTX2_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
	OTX2_DEVLINK_PARAM_ID_MCAM_COUNT,
};

static const struct devlink_param otx2_dl_params[] = {
	DEVLINK_PARAM_DRIVER(OTX2_DEVLINK_PARAM_ID_MCAM_COUNT,
			     "mcam_count", DEVLINK_PARAM_TYPE_U16,
			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
			     otx2_dl_mcam_count_get, otx2_dl_mcam_count_set,
			     otx2_dl_mcam_count_validate),
};

/* Devlink OPs */
static int otx2_devlink_info_get(struct devlink *devlink,
				 struct devlink_info_req *req,
				 struct netlink_ext_ack *extack)
{
	struct otx2_devlink *otx2_dl = devlink_priv(devlink);
	struct otx2_nic *pfvf = otx2_dl->pfvf;

	if (is_otx2_vf(pfvf->pcifunc))
		return devlink_info_driver_name_put(req, "rvu_nicvf");

	return devlink_info_driver_name_put(req, "rvu_nicpf");
}

static const struct devlink_ops otx2_devlink_ops = {
	.info_get = otx2_devlink_info_get,
};

int otx2_register_dl(struct otx2_nic *pfvf)
{
	struct otx2_devlink *otx2_dl;
	struct devlink *dl;
	int err;

	dl = devlink_alloc(&otx2_devlink_ops,
			   sizeof(struct otx2_devlink), pfvf->dev);
	if (!dl) {
		dev_warn(pfvf->dev, "devlink_alloc failed\n");
		return -ENOMEM;
	}

	err = devlink_register(dl);
	if (err) {
		dev_err(pfvf->dev, "devlink register failed with error %d\n", err);
		devlink_free(dl);
		return err;
	}

	otx2_dl = devlink_priv(dl);
	otx2_dl->dl = dl;
	otx2_dl->pfvf = pfvf;
	pfvf->dl = otx2_dl;

	err = devlink_params_register(dl, otx2_dl_params,
				      ARRAY_SIZE(otx2_dl_params));
	if (err) {
		dev_err(pfvf->dev,
			"devlink params register failed with error %d", err);
		goto err_dl;
	}

	devlink_params_publish(dl);

	return 0;

err_dl:
	devlink_unregister(dl);
	devlink_free(dl);
	return err;
}

void otx2_unregister_dl(struct otx2_nic *pfvf)
{
	struct otx2_devlink *otx2_dl = pfvf->dl;
	struct devlink *dl;

	if (!otx2_dl || !otx2_dl->dl)
		return;

	dl = otx2_dl->dl;

	devlink_params_unregister(dl, otx2_dl_params,
				  ARRAY_SIZE(otx2_dl_params));

	devlink_unregister(dl);
	devlink_free(dl);
}
+20 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell RVU PF/VF Netdev Devlink
 *
 * Copyright (C) 2021 Marvell.
 *
 */

#ifndef	OTX2_DEVLINK_H
#define	OTX2_DEVLINK_H

struct otx2_devlink {
	struct devlink *dl;
	struct otx2_nic *pfvf;
};

/* Devlink APIs */
int otx2_register_dl(struct otx2_nic *pfvf);
void otx2_unregister_dl(struct otx2_nic *pfvf);

#endif /* RVU_DEVLINK_H */
+19 −12
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@

#define OTX2_DEFAULT_ACTION	0x1

static int otx2_mcam_entry_init(struct otx2_nic *pfvf);

struct otx2_flow {
	struct ethtool_rx_flow_spec flow_spec;
	struct list_head list;
@@ -66,7 +68,7 @@ static int mcam_entry_cmp(const void *a, const void *b)
	return *(u16 *)a - *(u16 *)b;
}

static int otx2_alloc_ntuple_mcam_entries(struct otx2_nic *pfvf, u16 count)
int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)
{
	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
	struct npc_mcam_alloc_entry_req *req;
@@ -81,8 +83,12 @@ static int otx2_alloc_ntuple_mcam_entries(struct otx2_nic *pfvf, u16 count)

	flow_cfg->flow_ent = devm_kmalloc_array(pfvf->dev, count,
						sizeof(u16), GFP_KERNEL);
	if (!flow_cfg->flow_ent)
	if (!flow_cfg->flow_ent) {
		netdev_err(pfvf->netdev,
			   "%s: Unable to allocate memory for flow entries\n",
			    __func__);
		return -ENOMEM;
	}

	mutex_lock(&pfvf->mbox.lock);

@@ -139,8 +145,10 @@ static int otx2_alloc_ntuple_mcam_entries(struct otx2_nic *pfvf, u16 count)

	flow_cfg->max_flows = allocated;

	if (allocated) {
		pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC;
		pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
	}

	if (allocated != count)
		netdev_info(pfvf->netdev,
@@ -148,8 +156,9 @@ static int otx2_alloc_ntuple_mcam_entries(struct otx2_nic *pfvf, u16 count)
			    count, allocated);
	return allocated;
}
EXPORT_SYMBOL(otx2_alloc_mcam_entries);

int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
static int otx2_mcam_entry_init(struct otx2_nic *pfvf)
{
	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
	struct npc_mcam_alloc_entry_req *req;
@@ -209,7 +218,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
	mutex_unlock(&pfvf->mbox.lock);

	/* Allocate entries for Ntuple filters */
	count = otx2_alloc_ntuple_mcam_entries(pfvf, OTX2_DEFAULT_FLOWCOUNT);
	count = otx2_alloc_mcam_entries(pfvf, OTX2_DEFAULT_FLOWCOUNT);
	if (count <= 0) {
		otx2_clear_ntuple_flow_info(pfvf, flow_cfg);
		return 0;
@@ -223,7 +232,6 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
int otx2vf_mcam_flow_init(struct otx2_nic *pfvf)
{
	struct otx2_flow_config *flow_cfg;
	int count;

	pfvf->flow_cfg = devm_kzalloc(pfvf->dev,
				      sizeof(struct otx2_flow_config),
@@ -235,10 +243,6 @@ int otx2vf_mcam_flow_init(struct otx2_nic *pfvf)
	INIT_LIST_HEAD(&flow_cfg->flow_list);
	flow_cfg->max_flows = 0;

	count = otx2_alloc_ntuple_mcam_entries(pfvf, OTX2_DEFAULT_FLOWCOUNT);
	if (count <= 0)
		return -ENOMEM;

	return 0;
}
EXPORT_SYMBOL(otx2vf_mcam_flow_init);
@@ -254,7 +258,10 @@ int otx2_mcam_flow_init(struct otx2_nic *pf)

	INIT_LIST_HEAD(&pf->flow_cfg->flow_list);

	err = otx2_alloc_mcam_entries(pf);
	/* Allocate bare minimum number of MCAM entries needed for
	 * unicast and ntuple filters.
	 */
	err = otx2_mcam_entry_init(pf);
	if (err)
		return err;

Loading