net: microchip: sparx5: Add VCAP debugFS support

Add a debugFS root folder for Sparx5 and add a vcap folder underneath with
the VCAP instances and the ports

Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Steen Hegelund 2022-11-17 22:31:09 +01:00 committed by David S. Miller
parent 277e9179ef
commit e0305cc1d1
12 changed files with 266 additions and 64 deletions

View File

@ -12,6 +12,7 @@ sparx5-switch-y := sparx5_main.o sparx5_packet.o \
sparx5_vcap_impl.o sparx5_vcap_ag_api.o sparx5_tc_flower.o sparx5_tc_matchall.o
sparx5-switch-$(CONFIG_SPARX5_DCB) += sparx5_dcb.o
sparx5-switch-$(CONFIG_DEBUG_FS) += sparx5_vcap_debugfs.o
# Provide include files
ccflags-y += -I$(srctree)/drivers/net/ethernet/microchip/vcap

View File

@ -763,6 +763,8 @@ static int mchp_sparx5_probe(struct platform_device *pdev)
/* Default values, some from DT */
sparx5->coreclock = SPX5_CORE_CLOCK_DEFAULT;
sparx5->debugfs_root = debugfs_create_dir("sparx5", NULL);
ports = of_get_child_by_name(np, "ethernet-ports");
if (!ports) {
dev_err(sparx5->dev, "no ethernet-ports child node found\n");
@ -906,6 +908,7 @@ static int mchp_sparx5_remove(struct platform_device *pdev)
{
struct sparx5 *sparx5 = platform_get_drvdata(pdev);
debugfs_remove_recursive(sparx5->debugfs_root);
if (sparx5->xtr_irq) {
disable_irq(sparx5->xtr_irq);
sparx5->xtr_irq = -ENXIO;

View File

@ -17,6 +17,7 @@
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/hrtimer.h>
#include <linux/debugfs.h>
#include "sparx5_main_regs.h"
@ -292,6 +293,8 @@ struct sparx5 {
struct vcap_control *vcap_ctrl;
/* PGID allocation map */
u8 pgid_map[PGID_TABLE_SIZE];
/* Common root for debugfs */
struct dentry *debugfs_root;
};
/* sparx5_switchdev.c */

View File

@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-2.0+
/* Microchip Sparx5 Switch driver VCAP debugFS implementation
*
* Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
*/
#include <linux/types.h>
#include <linux/list.h>
#include "sparx5_vcap_debugfs.h"
#include "sparx5_main_regs.h"
#include "sparx5_main.h"
#include "sparx5_vcap_impl.h"
#include "sparx5_vcap_ag_api.h"
/* Provide port information via a callback interface */
int sparx5_port_info(struct net_device *ndev,
struct vcap_admin *admin,
struct vcap_output_print *out)
{
/* this will be added later */
return 0;
}

View File

@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/* Microchip Sparx5 Switch driver VCAP implementation
*
* Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
*/
#ifndef __SPARX5_VCAP_DEBUGFS_H__
#define __SPARX5_VCAP_DEBUGFS_H__
#include <linux/netdevice.h>
#include <vcap_api.h>
#include <vcap_api_client.h>
#if defined(CONFIG_DEBUG_FS)
/* Provide port information via a callback interface */
int sparx5_port_info(struct net_device *ndev,
struct vcap_admin *admin,
struct vcap_output_print *out);
#else
static inline int sparx5_port_info(struct net_device *ndev,
struct vcap_admin *admin,
struct vcap_output_print *out)
{
return 0;
}
#endif
#endif /* __SPARX5_VCAP_DEBUGFS_H__ */

View File

@ -12,10 +12,12 @@
#include "vcap_api.h"
#include "vcap_api_client.h"
#include "vcap_api_debugfs.h"
#include "sparx5_main_regs.h"
#include "sparx5_main.h"
#include "sparx5_vcap_impl.h"
#include "sparx5_vcap_ag_api.h"
#include "sparx5_vcap_debugfs.h"
#define SUPER_VCAP_BLK_SIZE 3072 /* addresses per Super VCAP block */
#define STREAMSIZE (64 * 4) /* bytes in the VCAP cache area */
@ -30,54 +32,6 @@
ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_SET(_v6_uc) | \
ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_SET(_arp))
/* IS2 port keyset selection control */
/* IS2 non-ethernet traffic type keyset generation */
enum vcap_is2_port_sel_noneth {
VCAP_IS2_PS_NONETH_MAC_ETYPE,
VCAP_IS2_PS_NONETH_CUSTOM_1,
VCAP_IS2_PS_NONETH_CUSTOM_2,
VCAP_IS2_PS_NONETH_NO_LOOKUP
};
/* IS2 IPv4 unicast traffic type keyset generation */
enum vcap_is2_port_sel_ipv4_uc {
VCAP_IS2_PS_IPV4_UC_MAC_ETYPE,
VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER,
VCAP_IS2_PS_IPV4_UC_IP_7TUPLE,
};
/* IS2 IPv4 multicast traffic type keyset generation */
enum vcap_is2_port_sel_ipv4_mc {
VCAP_IS2_PS_IPV4_MC_MAC_ETYPE,
VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER,
VCAP_IS2_PS_IPV4_MC_IP_7TUPLE,
VCAP_IS2_PS_IPV4_MC_IP4_VID,
};
/* IS2 IPv6 unicast traffic type keyset generation */
enum vcap_is2_port_sel_ipv6_uc {
VCAP_IS2_PS_IPV6_UC_MAC_ETYPE,
VCAP_IS2_PS_IPV6_UC_IP_7TUPLE,
VCAP_IS2_PS_IPV6_UC_IP6_STD,
VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER,
};
/* IS2 IPv6 multicast traffic type keyset generation */
enum vcap_is2_port_sel_ipv6_mc {
VCAP_IS2_PS_IPV6_MC_MAC_ETYPE,
VCAP_IS2_PS_IPV6_MC_IP_7TUPLE,
VCAP_IS2_PS_IPV6_MC_IP6_VID,
VCAP_IS2_PS_IPV6_MC_IP6_STD,
VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER,
};
/* IS2 ARP traffic type keyset generation */
enum vcap_is2_port_sel_arp {
VCAP_IS2_PS_ARP_MAC_ETYPE,
VCAP_IS2_PS_ARP_ARP,
};
static struct sparx5_vcap_inst {
enum vcap_type vtype; /* type of vcap */
int vinst; /* instance number within the same type */
@ -548,15 +502,6 @@ static void sparx5_vcap_move(struct net_device *ndev, struct vcap_admin *admin,
sparx5_vcap_wait_super_update(sparx5);
}
/* Provide port information via a callback interface */
static int sparx5_port_info(struct net_device *ndev, enum vcap_type vtype,
int (*pf)(void *out, int arg, const char *fmt, ...),
void *out, int arg)
{
/* this will be added later */
return 0;
}
/* Enable all lookups in the VCAP instance */
static int sparx5_vcap_enable(struct net_device *ndev,
struct vcap_admin *admin,
@ -702,6 +647,7 @@ int sparx5_vcap_init(struct sparx5 *sparx5)
const struct sparx5_vcap_inst *cfg;
struct vcap_control *ctrl;
struct vcap_admin *admin;
struct dentry *dir;
int err = 0, idx;
/* Create a VCAP control instance that owns the platform specific VCAP
@ -740,6 +686,11 @@ int sparx5_vcap_init(struct sparx5 *sparx5)
sparx5_vcap_port_key_selection(sparx5, admin);
list_add_tail(&admin->list, &ctrl->list);
}
dir = vcap_debugfs(sparx5->dev, sparx5->debugfs_root, ctrl);
for (idx = 0; idx < SPX5_PORTS; ++idx)
if (sparx5->ports[idx])
vcap_port_debugfs(sparx5->dev, dir, ctrl,
sparx5->ports[idx]->ndev);
return err;
}

View File

@ -17,4 +17,52 @@
#define SPARX5_VCAP_CID_IS2_MAX \
(VCAP_CID_INGRESS_STAGE2_L3 + VCAP_CID_LOOKUP_SIZE - 1) /* IS2 Max */
/* IS2 port keyset selection control */
/* IS2 non-ethernet traffic type keyset generation */
enum vcap_is2_port_sel_noneth {
VCAP_IS2_PS_NONETH_MAC_ETYPE,
VCAP_IS2_PS_NONETH_CUSTOM_1,
VCAP_IS2_PS_NONETH_CUSTOM_2,
VCAP_IS2_PS_NONETH_NO_LOOKUP
};
/* IS2 IPv4 unicast traffic type keyset generation */
enum vcap_is2_port_sel_ipv4_uc {
VCAP_IS2_PS_IPV4_UC_MAC_ETYPE,
VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER,
VCAP_IS2_PS_IPV4_UC_IP_7TUPLE,
};
/* IS2 IPv4 multicast traffic type keyset generation */
enum vcap_is2_port_sel_ipv4_mc {
VCAP_IS2_PS_IPV4_MC_MAC_ETYPE,
VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER,
VCAP_IS2_PS_IPV4_MC_IP_7TUPLE,
VCAP_IS2_PS_IPV4_MC_IP4_VID,
};
/* IS2 IPv6 unicast traffic type keyset generation */
enum vcap_is2_port_sel_ipv6_uc {
VCAP_IS2_PS_IPV6_UC_MAC_ETYPE,
VCAP_IS2_PS_IPV6_UC_IP_7TUPLE,
VCAP_IS2_PS_IPV6_UC_IP6_STD,
VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER,
};
/* IS2 IPv6 multicast traffic type keyset generation */
enum vcap_is2_port_sel_ipv6_mc {
VCAP_IS2_PS_IPV6_MC_MAC_ETYPE,
VCAP_IS2_PS_IPV6_MC_IP_7TUPLE,
VCAP_IS2_PS_IPV6_MC_IP6_VID,
VCAP_IS2_PS_IPV6_MC_IP6_STD,
VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER,
};
/* IS2 ARP traffic type keyset generation */
enum vcap_is2_port_sel_arp {
VCAP_IS2_PS_ARP_MAC_ETYPE,
VCAP_IS2_PS_ARP_ARP,
};
#endif /* __SPARX5_VCAP_IMPL_H__ */

View File

@ -5,5 +5,6 @@
obj-$(CONFIG_VCAP) += vcap.o
obj-$(CONFIG_VCAP_KUNIT_TEST) += vcap_model_kunit.o
vcap-$(CONFIG_DEBUG_FS) += vcap_api_debugfs.o
vcap-y += vcap_api.o

View File

@ -203,6 +203,13 @@ struct vcap_keyset_list {
enum vcap_keyfield_set *keysets; /* the list of keysets */
};
/* Client output printf-like function with destination */
struct vcap_output_print {
__printf(2, 3)
void (*prf)(void *out, const char *fmt, ...);
void *dst;
};
/* Client supplied VCAP callback operations */
struct vcap_operations {
/* validate port keyset operation */
@ -252,10 +259,8 @@ struct vcap_operations {
/* informational */
int (*port_info)
(struct net_device *ndev,
enum vcap_type vtype,
int (*pf)(void *out, int arg, const char *fmt, ...),
void *out,
int arg);
struct vcap_admin *admin,
struct vcap_output_print *out);
/* enable/disable the lookups in a vcap instance */
int (*enable)
(struct net_device *ndev,

View File

@ -0,0 +1,93 @@
// SPDX-License-Identifier: GPL-2.0+
/* Microchip VCAP API debug file system support
*
* Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
*
*/
#include <linux/types.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/netdevice.h>
#include "vcap_api_debugfs.h"
struct vcap_admin_debugfs_info {
struct vcap_control *vctrl;
struct vcap_admin *admin;
};
struct vcap_port_debugfs_info {
struct vcap_control *vctrl;
struct net_device *ndev;
};
/* Show the port configuration and status */
static int vcap_port_debugfs_show(struct seq_file *m, void *unused)
{
struct vcap_port_debugfs_info *info = m->private;
struct vcap_admin *admin;
struct vcap_output_print out = {
.prf = (void *)seq_printf,
.dst = m,
};
list_for_each_entry(admin, &info->vctrl->list, list) {
if (admin->vinst)
continue;
info->vctrl->ops->port_info(info->ndev, admin, &out);
}
return 0;
}
DEFINE_SHOW_ATTRIBUTE(vcap_port_debugfs);
void vcap_port_debugfs(struct device *dev, struct dentry *parent,
struct vcap_control *vctrl,
struct net_device *ndev)
{
struct vcap_port_debugfs_info *info;
info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
if (!info)
return;
info->vctrl = vctrl;
info->ndev = ndev;
debugfs_create_file(netdev_name(ndev), 0444, parent, info,
&vcap_port_debugfs_fops);
}
EXPORT_SYMBOL_GPL(vcap_port_debugfs);
/* Show the raw VCAP instance data (rules with address info) */
static int vcap_raw_debugfs_show(struct seq_file *m, void *unused)
{
/* The output will be added later */
return 0;
}
DEFINE_SHOW_ATTRIBUTE(vcap_raw_debugfs);
struct dentry *vcap_debugfs(struct device *dev, struct dentry *parent,
struct vcap_control *vctrl)
{
struct vcap_admin_debugfs_info *info;
struct vcap_admin *admin;
struct dentry *dir;
char name[50];
dir = debugfs_create_dir("vcaps", parent);
if (PTR_ERR_OR_ZERO(dir))
return NULL;
list_for_each_entry(admin, &vctrl->list, list) {
sprintf(name, "raw_%s_%d", vctrl->vcaps[admin->vtype].name,
admin->vinst);
info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
if (!info)
return NULL;
info->vctrl = vctrl;
info->admin = admin;
debugfs_create_file(name, 0444, dir, info,
&vcap_raw_debugfs_fops);
}
return dir;
}
EXPORT_SYMBOL_GPL(vcap_debugfs);

View File

@ -0,0 +1,41 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries.
* Microchip VCAP API
*/
#ifndef __VCAP_API_DEBUGFS__
#define __VCAP_API_DEBUGFS__
#include <linux/types.h>
#include <linux/debugfs.h>
#include <linux/netdevice.h>
#include "vcap_api.h"
#if defined(CONFIG_DEBUG_FS)
void vcap_port_debugfs(struct device *dev, struct dentry *parent,
struct vcap_control *vctrl,
struct net_device *ndev);
/* Create a debugFS entry for a vcap instance */
struct dentry *vcap_debugfs(struct device *dev, struct dentry *parent,
struct vcap_control *vctrl);
#else
static inline void vcap_port_debugfs(struct device *dev, struct dentry *parent,
struct vcap_control *vctrl,
struct net_device *ndev)
{
}
static inline struct dentry *vcap_debugfs(struct device *dev,
struct dentry *parent,
struct vcap_control *vctrl)
{
return NULL;
}
#endif
#endif /* __VCAP_API_DEBUGFS__ */

View File

@ -204,9 +204,9 @@ static void test_cache_move(struct net_device *ndev, struct vcap_admin *admin,
}
/* Provide port information via a callback interface */
static int vcap_test_port_info(struct net_device *ndev, enum vcap_type vtype,
int (*pf)(void *out, int arg, const char *fmt, ...),
void *out, int arg)
static int vcap_test_port_info(struct net_device *ndev,
struct vcap_admin *admin,
struct vcap_output_print *out)
{
return 0;
}