From 3a7921560d2fd38433fdb2e9b8728ab832880680 Mon Sep 17 00:00:00 2001 From: Steen Hegelund Date: Thu, 17 Nov 2022 22:31:11 +0100 Subject: [PATCH] net: microchip: sparx5: Add VCAP rule debugFS support for the VCAP API This add support to show all rules in a VCAP instance. The information shown is: - rule id - address range - size - chain id - keyset name, subword size, register span - actionset name, subword size, register span - counter value - sticky bit (one bit width counter) Signed-off-by: Steen Hegelund Signed-off-by: David S. Miller --- .../net/ethernet/microchip/vcap/vcap_api.c | 15 ++- .../microchip/vcap/vcap_api_debugfs.c | 116 ++++++++++++++++++ .../microchip/vcap/vcap_api_private.h | 14 +++ 3 files changed, 141 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c index 153e28e124bc..3da714e9639c 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api.c +++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c @@ -502,7 +502,7 @@ int vcap_api_check(struct vcap_control *ctrl) return 0; } -static void vcap_erase_cache(struct vcap_rule_internal *ri) +void vcap_erase_cache(struct vcap_rule_internal *ri) { ri->vctrl->ops->cache_erase(ri->admin); } @@ -578,7 +578,7 @@ int vcap_lookup_rule_by_cookie(struct vcap_control *vctrl, u64 cookie) EXPORT_SYMBOL_GPL(vcap_lookup_rule_by_cookie); /* Make a shallow copy of the rule without the fields */ -static struct vcap_rule_internal *vcap_dup_rule(struct vcap_rule_internal *ri) +struct vcap_rule_internal *vcap_dup_rule(struct vcap_rule_internal *ri) { struct vcap_rule_internal *duprule; @@ -782,9 +782,16 @@ const char *vcap_keyfield_name(struct vcap_control *vctrl, } EXPORT_SYMBOL_GPL(vcap_keyfield_name); +/* map actionset id to a string with the actionset name */ +const char *vcap_actionset_name(struct vcap_control *vctrl, + enum vcap_actionfield_set actionset) +{ + return vctrl->stats->actionfield_set_names[actionset]; +} + /* map action field id to a string with the action name */ -static const char *vcap_actionfield_name(struct vcap_control *vctrl, - enum vcap_action_field action) +const char *vcap_actionfield_name(struct vcap_control *vctrl, + enum vcap_action_field action) { return vctrl->stats->actionfield_names[action]; } diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c index 4a1ca26be901..b4bc32a08f2c 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c +++ b/drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c @@ -234,6 +234,106 @@ static int vcap_addr_keyset(struct vcap_control *vctrl, admin->cache.maskstream, false, 0); } +static int vcap_read_rule(struct vcap_rule_internal *ri) +{ + struct vcap_admin *admin = ri->admin; + int sw_idx, ent_idx = 0, act_idx = 0; + u32 addr = ri->addr; + + if (!ri->size || !ri->keyset_sw_regs || !ri->actionset_sw_regs) { + pr_err("%s:%d: rule is empty\n", __func__, __LINE__); + return -EINVAL; + } + vcap_erase_cache(ri); + /* Use the values in the streams to read the VCAP cache */ + for (sw_idx = 0; sw_idx < ri->size; sw_idx++, addr++) { + ri->vctrl->ops->update(ri->ndev, admin, VCAP_CMD_READ, + VCAP_SEL_ALL, addr); + ri->vctrl->ops->cache_read(ri->ndev, admin, + VCAP_SEL_ENTRY, ent_idx, + ri->keyset_sw_regs); + ri->vctrl->ops->cache_read(ri->ndev, admin, + VCAP_SEL_ACTION, act_idx, + ri->actionset_sw_regs); + if (sw_idx == 0) + ri->vctrl->ops->cache_read(ri->ndev, admin, + VCAP_SEL_COUNTER, + ri->counter_id, 0); + ent_idx += ri->keyset_sw_regs; + act_idx += ri->actionset_sw_regs; + } + return 0; +} + +static void vcap_show_admin_rule(struct vcap_control *vctrl, + struct vcap_admin *admin, + struct vcap_output_print *out, + struct vcap_rule_internal *ri) +{ + ri->counter.value = admin->cache.counter; + ri->counter.sticky = admin->cache.sticky; + out->prf(out->dst, + "rule: %u, addr: [%d,%d], X%d, ctr[%d]: %d, hit: %d\n", + ri->data.id, ri->addr, ri->addr + ri->size - 1, ri->size, + ri->counter_id, ri->counter.value, ri->counter.sticky); + out->prf(out->dst, " chain_id: %d\n", ri->data.vcap_chain_id); + out->prf(out->dst, " user: %d\n", ri->data.user); + out->prf(out->dst, " priority: %d\n", ri->data.priority); + out->prf(out->dst, " keyset: %s\n", + vcap_keyset_name(vctrl, ri->data.keyset)); + out->prf(out->dst, " actionset: %s\n", + vcap_actionset_name(vctrl, ri->data.actionset)); +} + +static void vcap_show_admin_info(struct vcap_control *vctrl, + struct vcap_admin *admin, + struct vcap_output_print *out) +{ + const struct vcap_info *vcap = &vctrl->vcaps[admin->vtype]; + + out->prf(out->dst, "name: %s\n", vcap->name); + out->prf(out->dst, "rows: %d\n", vcap->rows); + out->prf(out->dst, "sw_count: %d\n", vcap->sw_count); + out->prf(out->dst, "sw_width: %d\n", vcap->sw_width); + out->prf(out->dst, "sticky_width: %d\n", vcap->sticky_width); + out->prf(out->dst, "act_width: %d\n", vcap->act_width); + out->prf(out->dst, "default_cnt: %d\n", vcap->default_cnt); + out->prf(out->dst, "require_cnt_dis: %d\n", vcap->require_cnt_dis); + out->prf(out->dst, "version: %d\n", vcap->version); + out->prf(out->dst, "vtype: %d\n", admin->vtype); + out->prf(out->dst, "vinst: %d\n", admin->vinst); + out->prf(out->dst, "first_cid: %d\n", admin->first_cid); + out->prf(out->dst, "last_cid: %d\n", admin->last_cid); + out->prf(out->dst, "lookups: %d\n", admin->lookups); + out->prf(out->dst, "first_valid_addr: %d\n", admin->first_valid_addr); + out->prf(out->dst, "last_valid_addr: %d\n", admin->last_valid_addr); + out->prf(out->dst, "last_used_addr: %d\n", admin->last_used_addr); +} + +static int vcap_show_admin(struct vcap_control *vctrl, + struct vcap_admin *admin, + struct vcap_output_print *out) +{ + struct vcap_rule_internal *elem, *ri; + int ret = 0; + + vcap_show_admin_info(vctrl, admin, out); + list_for_each_entry(elem, &admin->rules, list) { + ri = vcap_dup_rule(elem); + if (IS_ERR(ri)) + goto free_rule; + /* Read data from VCAP */ + ret = vcap_read_rule(ri); + if (ret) + goto free_rule; + out->prf(out->dst, "\n"); + vcap_show_admin_rule(vctrl, admin, out, ri); +free_rule: + vcap_free_rule((struct vcap_rule *)ri); + } + return ret; +} + static int vcap_show_admin_raw(struct vcap_control *vctrl, struct vcap_admin *admin, struct vcap_output_print *out) @@ -313,6 +413,19 @@ void vcap_port_debugfs(struct device *dev, struct dentry *parent, } EXPORT_SYMBOL_GPL(vcap_port_debugfs); +/* Show the full VCAP instance data (rules with all fields) */ +static int vcap_debugfs_show(struct seq_file *m, void *unused) +{ + struct vcap_admin_debugfs_info *info = m->private; + struct vcap_output_print out = { + .prf = (void *)seq_printf, + .dst = m, + }; + + return vcap_show_admin(info->vctrl, info->admin, &out); +} +DEFINE_SHOW_ATTRIBUTE(vcap_debugfs); + /* Show the raw VCAP instance data (rules with address info) */ static int vcap_raw_debugfs_show(struct seq_file *m, void *unused) { @@ -347,6 +460,9 @@ struct dentry *vcap_debugfs(struct device *dev, struct dentry *parent, info->admin = admin; debugfs_create_file(name, 0444, dir, info, &vcap_raw_debugfs_fops); + sprintf(name, "%s_%d", vctrl->vcaps[admin->vtype].name, + admin->vinst); + debugfs_create_file(name, 0444, dir, info, &vcap_debugfs_fops); } return dir; } diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_private.h b/drivers/net/ethernet/microchip/vcap/vcap_api_private.h index 1ea25c5d0ca7..57309de463d7 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api_private.h +++ b/drivers/net/ethernet/microchip/vcap/vcap_api_private.h @@ -43,6 +43,10 @@ struct vcap_stream_iter { /* Check that the control has a valid set of callbacks */ int vcap_api_check(struct vcap_control *ctrl); +/* Make a shallow copy of the rule without the fields */ +struct vcap_rule_internal *vcap_dup_rule(struct vcap_rule_internal *ri); +/* Erase the VCAP cache area used or encoding and decoding */ +void vcap_erase_cache(struct vcap_rule_internal *ri); /* Iterator functionality */ @@ -70,4 +74,14 @@ vcap_keyfield_typegroup(struct vcap_control *vctrl, const struct vcap_field *vcap_keyfields(struct vcap_control *vctrl, enum vcap_type vt, enum vcap_keyfield_set keyset); + +/* Actionset and actionfield functionality */ + +/* Map actionset id to a string with the actionset name */ +const char *vcap_actionset_name(struct vcap_control *vctrl, + enum vcap_actionfield_set actionset); +/* Map key field id to a string with the key name */ +const char *vcap_actionfield_name(struct vcap_control *vctrl, + enum vcap_action_field action); + #endif /* __VCAP_API_PRIVATE__ */