Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for the device driver of PPE (Packet Process Engine) in IPQ SoC
#
obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o
qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o
@@ -0,0 +1,239 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
/* PPE platform device probe, DTSI parser and PPE clock initializations. */
#include <linux/clk.h>
#include <linux/interconnect.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include "ppe.h"
#include "ppe_config.h"
#include "ppe_debugfs.h"
#define PPE_PORT_MAX 8
#define PPE_CLK_RATE 353000000
/* ICC clocks for enabling PPE device. The avg_bw and peak_bw with value 0
* will be updated by the clock rate of PPE.
*/
static const struct icc_bulk_data ppe_icc_data[] = {
{
.name = "ppe",
.avg_bw = 0,
.peak_bw = 0,
},
{
.name = "ppe_cfg",
.avg_bw = 0,
.peak_bw = 0,
},
{
.name = "qos_gen",
.avg_bw = 6000,
.peak_bw = 6000,
},
{
.name = "timeout_ref",
.avg_bw = 6000,
.peak_bw = 6000,
},
{
.name = "nssnoc_memnoc",
.avg_bw = 533333,
.peak_bw = 533333,
},
{
.name = "memnoc_nssnoc",
.avg_bw = 533333,
.peak_bw = 533333,
},
{
.name = "memnoc_nssnoc_1",
.avg_bw = 533333,
.peak_bw = 533333,
},
};
static const struct regmap_range ppe_readable_ranges[] = {
regmap_reg_range(0x0, 0x1ff), /* Global */
regmap_reg_range(0x400, 0x5ff), /* LPI CSR */
regmap_reg_range(0x1000, 0x11ff), /* GMAC0 */
regmap_reg_range(0x1200, 0x13ff), /* GMAC1 */
regmap_reg_range(0x1400, 0x15ff), /* GMAC2 */
regmap_reg_range(0x1600, 0x17ff), /* GMAC3 */
regmap_reg_range(0x1800, 0x19ff), /* GMAC4 */
regmap_reg_range(0x1a00, 0x1bff), /* GMAC5 */
regmap_reg_range(0xb000, 0xefff), /* PRX CSR */
regmap_reg_range(0xf000, 0x1efff), /* IPE */
regmap_reg_range(0x20000, 0x5ffff), /* PTX CSR */
regmap_reg_range(0x60000, 0x9ffff), /* IPE L2 CSR */
regmap_reg_range(0xb0000, 0xeffff), /* IPO CSR */
regmap_reg_range(0x100000, 0x17ffff), /* IPE PC */
regmap_reg_range(0x180000, 0x1bffff), /* PRE IPO CSR */
regmap_reg_range(0x1d0000, 0x1dffff), /* Tunnel parser */
regmap_reg_range(0x1e0000, 0x1effff), /* Ingress parse */
regmap_reg_range(0x200000, 0x2fffff), /* IPE L3 */
regmap_reg_range(0x300000, 0x3fffff), /* IPE tunnel */
regmap_reg_range(0x400000, 0x4fffff), /* Scheduler */
regmap_reg_range(0x500000, 0x503fff), /* XGMAC0 */
regmap_reg_range(0x504000, 0x507fff), /* XGMAC1 */
regmap_reg_range(0x508000, 0x50bfff), /* XGMAC2 */
regmap_reg_range(0x50c000, 0x50ffff), /* XGMAC3 */
regmap_reg_range(0x510000, 0x513fff), /* XGMAC4 */
regmap_reg_range(0x514000, 0x517fff), /* XGMAC5 */
regmap_reg_range(0x600000, 0x6fffff), /* BM */
regmap_reg_range(0x800000, 0x9fffff), /* QM */
regmap_reg_range(0xb00000, 0xbef800), /* EDMA */
};
static const struct regmap_access_table ppe_reg_table = {
.yes_ranges = ppe_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges),
};
static const struct regmap_config regmap_config_ipq9574 = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.rd_table = &ppe_reg_table,
.wr_table = &ppe_reg_table,
.max_register = 0xbef800,
.fast_io = true,
};
static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
{
unsigned long ppe_rate = ppe_dev->clk_rate;
struct device *dev = ppe_dev->dev;
struct reset_control *rstc;
struct clk_bulk_data *clks;
struct clk *clk;
int ret, i;
for (i = 0; i < ppe_dev->num_icc_paths; i++) {
ppe_dev->icc_paths[i].name = ppe_icc_data[i].name;
ppe_dev->icc_paths[i].avg_bw = ppe_icc_data[i].avg_bw ? :
Bps_to_icc(ppe_rate);
/* PPE does not have an explicit peak bandwidth requirement,
* so set the peak bandwidth to be equal to the average
* bandwidth.
*/
ppe_dev->icc_paths[i].peak_bw = ppe_icc_data[i].peak_bw ? :
Bps_to_icc(ppe_rate);
}
ret = devm_of_icc_bulk_get(dev, ppe_dev->num_icc_paths,
ppe_dev->icc_paths);
if (ret)
return ret;
ret = icc_bulk_set_bw(ppe_dev->num_icc_paths, ppe_dev->icc_paths);
if (ret)
return ret;
/* The PPE clocks have a common parent clock. Setting the clock
* rate of "ppe" ensures the clock rate of all PPE clocks is
* configured to the same rate.
*/
clk = devm_clk_get(dev, "ppe");
if (IS_ERR(clk))
return PTR_ERR(clk);
ret = clk_set_rate(clk, ppe_rate);
if (ret)
return ret;
ret = devm_clk_bulk_get_all_enabled(dev, &clks);
if (ret < 0)
return ret;
/* Reset the PPE. */
rstc = devm_reset_control_get_exclusive(dev, NULL);
if (IS_ERR(rstc))
return PTR_ERR(rstc);
ret = reset_control_assert(rstc);
if (ret)
return ret;
/* The delay 10 ms of assert is necessary for resetting PPE. */
usleep_range(10000, 11000);
return reset_control_deassert(rstc);
}
static int qcom_ppe_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ppe_device *ppe_dev;
void __iomem *base;
int ret, num_icc;
num_icc = ARRAY_SIZE(ppe_icc_data);
ppe_dev = devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc),
GFP_KERNEL);
if (!ppe_dev)
return -ENOMEM;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return dev_err_probe(dev, PTR_ERR(base), "PPE ioremap failed\n");
ppe_dev->regmap = devm_regmap_init_mmio(dev, base, &regmap_config_ipq9574);
if (IS_ERR(ppe_dev->regmap))
return dev_err_probe(dev, PTR_ERR(ppe_dev->regmap),
"PPE initialize regmap failed\n");
ppe_dev->dev = dev;
ppe_dev->clk_rate = PPE_CLK_RATE;
ppe_dev->num_ports = PPE_PORT_MAX;
ppe_dev->num_icc_paths = num_icc;
ret = ppe_clock_init_and_reset(ppe_dev);
if (ret)
return dev_err_probe(dev, ret, "PPE clock config failed\n");
ret = ppe_hw_config(ppe_dev);
if (ret)
return dev_err_probe(dev, ret, "PPE HW config failed\n");
ppe_debugfs_setup(ppe_dev);
platform_set_drvdata(pdev, ppe_dev);
return 0;
}
static void qcom_ppe_remove(struct platform_device *pdev)
{
struct ppe_device *ppe_dev;
ppe_dev = platform_get_drvdata(pdev);
ppe_debugfs_teardown(ppe_dev);
}
static const struct of_device_id qcom_ppe_of_match[] = {
{ .compatible = "qcom,ipq9574-ppe" },
{}
};
MODULE_DEVICE_TABLE(of, qcom_ppe_of_match);
static struct platform_driver qcom_ppe_driver = {
.driver = {
.name = "qcom_ppe",
.of_match_table = qcom_ppe_of_match,
},
.probe = qcom_ppe_probe,
.remove = qcom_ppe_remove,
};
module_platform_driver(qcom_ppe_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ PPE driver");
@@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0-only
*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef __PPE_H__
#define __PPE_H__
#include <linux/compiler.h>
#include <linux/interconnect.h>
struct device;
struct regmap;
struct dentry;
/**
* struct ppe_device - PPE device private data.
* @dev: PPE device structure.
* @regmap: PPE register map.
* @clk_rate: PPE clock rate.
* @num_ports: Number of PPE ports.
* @debugfs_root: Debugfs root entry.
* @num_icc_paths: Number of interconnect paths.
* @icc_paths: Interconnect path array.
*
* PPE device is the instance of PPE hardware, which is used to
* configure PPE packet process modules such as BM (buffer management),
* QM (queue management), and scheduler.
*/
struct ppe_device {
struct device *dev;
struct regmap *regmap;
unsigned long clk_rate;
unsigned int num_ports;
struct dentry *debugfs_root;
unsigned int num_icc_paths;
struct icc_bulk_data icc_paths[] __counted_by(num_icc_paths);
};
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,317 @@
/* SPDX-License-Identifier: GPL-2.0-only
*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef __PPE_CONFIG_H__
#define __PPE_CONFIG_H__
#include <linux/types.h>
#include "ppe.h"
/* There are different table index ranges for configuring queue base ID of
* the destination port, CPU code and service code.
*/
#define PPE_QUEUE_BASE_DEST_PORT 0
#define PPE_QUEUE_BASE_CPU_CODE 1024
#define PPE_QUEUE_BASE_SERVICE_CODE 2048
#define PPE_QUEUE_INTER_PRI_NUM 16
#define PPE_QUEUE_HASH_NUM 256
/* The service code is used by EDMA port to transmit packet to PPE. */
#define PPE_EDMA_SC_BYPASS_ID 1
/* The PPE RSS hash configured for IPv4 and IPv6 packet separately. */
#define PPE_RSS_HASH_MODE_IPV4 BIT(0)
#define PPE_RSS_HASH_MODE_IPV6 BIT(1)
#define PPE_RSS_HASH_IP_LENGTH 4
#define PPE_RSS_HASH_TUPLES 5
/* PPE supports 300 queues, each bit presents as one queue. */
#define PPE_RING_TO_QUEUE_BITMAP_WORD_CNT 10
/**
* enum ppe_scheduler_frame_mode - PPE scheduler frame mode.
* @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG,
* preamble, Ethernet packet and CRC.
* @PPE_SCH_WITH_FRAME_CRC: The scheduled frame includes Ethernet frame and CRC
* excluding IPG and preamble.
* @PPE_SCH_WITH_L3_PAYLOAD: The scheduled frame includes layer 3 packet data.
*/
enum ppe_scheduler_frame_mode {
PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC = 0,
PPE_SCH_WITH_FRAME_CRC = 1,
PPE_SCH_WITH_L3_PAYLOAD = 2,
};
/**
* struct ppe_scheduler_cfg - PPE scheduler configuration.
* @flow_id: PPE flow ID.
* @pri: Scheduler priority.
* @drr_node_id: Node ID for scheduled traffic.
* @drr_node_wt: Weight for scheduled traffic.
* @unit_is_packet: Packet based or byte based unit for scheduled traffic.
* @frame_mode: Packet mode to be scheduled.
*
* PPE scheduler supports commit rate and exceed rate configurations.
*/
struct ppe_scheduler_cfg {
int flow_id;
int pri;
int drr_node_id;
int drr_node_wt;
bool unit_is_packet;
enum ppe_scheduler_frame_mode frame_mode;
};
/**
* enum ppe_resource_type - PPE resource type.
* @PPE_RES_UCAST: Unicast queue resource.
* @PPE_RES_MCAST: Multicast queue resource.
* @PPE_RES_L0_NODE: Level 0 for queue based node resource.
* @PPE_RES_L1_NODE: Level 1 for flow based node resource.
* @PPE_RES_FLOW_ID: Flow based node resource.
*/
enum ppe_resource_type {
PPE_RES_UCAST,
PPE_RES_MCAST,
PPE_RES_L0_NODE,
PPE_RES_L1_NODE,
PPE_RES_FLOW_ID,
};
/**
* struct ppe_queue_ucast_dest - PPE unicast queue destination.
* @src_profile: Source profile.
* @service_code_en: Enable service code to map the queue base ID.
* @service_code: Service code.
* @cpu_code_en: Enable CPU code to map the queue base ID.
* @cpu_code: CPU code.
* @dest_port: destination port.
*
* PPE egress queue ID is decided by the service code if enabled, otherwise
* by the CPU code if enabled, or by destination port if both service code
* and CPU code are disabled.
*/
struct ppe_queue_ucast_dest {
int src_profile;
bool service_code_en;
int service_code;
bool cpu_code_en;
int cpu_code;
int dest_port;
};
/* Hardware bitmaps for bypassing features of the ingress packet. */
enum ppe_sc_ingress_type {
PPE_SC_BYPASS_INGRESS_VLAN_TAG_FMT_CHECK = 0,
PPE_SC_BYPASS_INGRESS_VLAN_MEMBER_CHECK = 1,
PPE_SC_BYPASS_INGRESS_VLAN_TRANSLATE = 2,
PPE_SC_BYPASS_INGRESS_MY_MAC_CHECK = 3,
PPE_SC_BYPASS_INGRESS_DIP_LOOKUP = 4,
PPE_SC_BYPASS_INGRESS_FLOW_LOOKUP = 5,
PPE_SC_BYPASS_INGRESS_FLOW_ACTION = 6,
PPE_SC_BYPASS_INGRESS_ACL = 7,
PPE_SC_BYPASS_INGRESS_FAKE_MAC_HEADER = 8,
PPE_SC_BYPASS_INGRESS_SERVICE_CODE = 9,
PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L2 = 10,
PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L3_IPV4 = 11,
PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L3_IPV6 = 12,
PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L4 = 13,
PPE_SC_BYPASS_INGRESS_FLOW_SERVICE_CODE = 14,
PPE_SC_BYPASS_INGRESS_ACL_SERVICE_CODE = 15,
PPE_SC_BYPASS_INGRESS_FAKE_L2_PROTO = 16,
PPE_SC_BYPASS_INGRESS_PPPOE_TERMINATION = 17,
PPE_SC_BYPASS_INGRESS_DEFAULT_VLAN = 18,
PPE_SC_BYPASS_INGRESS_DEFAULT_PCP = 19,
PPE_SC_BYPASS_INGRESS_VSI_ASSIGN = 20,
/* Values 21-23 are not specified by hardware. */
PPE_SC_BYPASS_INGRESS_VLAN_ASSIGN_FAIL = 24,
PPE_SC_BYPASS_INGRESS_SOURCE_GUARD = 25,
PPE_SC_BYPASS_INGRESS_MRU_MTU_CHECK = 26,
PPE_SC_BYPASS_INGRESS_FLOW_SRC_CHECK = 27,
PPE_SC_BYPASS_INGRESS_FLOW_QOS = 28,
/* This must be last as it determines the size of the BITMAP. */
PPE_SC_BYPASS_INGRESS_SIZE,
};
/* Hardware bitmaps for bypassing features of the egress packet. */
enum ppe_sc_egress_type {
PPE_SC_BYPASS_EGRESS_VLAN_MEMBER_CHECK = 0,
PPE_SC_BYPASS_EGRESS_VLAN_TRANSLATE = 1,
PPE_SC_BYPASS_EGRESS_VLAN_TAG_FMT_CTRL = 2,
PPE_SC_BYPASS_EGRESS_FDB_LEARN = 3,
PPE_SC_BYPASS_EGRESS_FDB_REFRESH = 4,
PPE_SC_BYPASS_EGRESS_L2_SOURCE_SECURITY = 5,
PPE_SC_BYPASS_EGRESS_MANAGEMENT_FWD = 6,
PPE_SC_BYPASS_EGRESS_BRIDGING_FWD = 7,
PPE_SC_BYPASS_EGRESS_IN_STP_FLTR = 8,
PPE_SC_BYPASS_EGRESS_EG_STP_FLTR = 9,
PPE_SC_BYPASS_EGRESS_SOURCE_FLTR = 10,
PPE_SC_BYPASS_EGRESS_POLICER = 11,
PPE_SC_BYPASS_EGRESS_L2_PKT_EDIT = 12,
PPE_SC_BYPASS_EGRESS_L3_PKT_EDIT = 13,
PPE_SC_BYPASS_EGRESS_ACL_POST_ROUTING_CHECK = 14,
PPE_SC_BYPASS_EGRESS_PORT_ISOLATION = 15,
PPE_SC_BYPASS_EGRESS_PRE_ACL_QOS = 16,
PPE_SC_BYPASS_EGRESS_POST_ACL_QOS = 17,
PPE_SC_BYPASS_EGRESS_DSCP_QOS = 18,
PPE_SC_BYPASS_EGRESS_PCP_QOS = 19,
PPE_SC_BYPASS_EGRESS_PREHEADER_QOS = 20,
PPE_SC_BYPASS_EGRESS_FAKE_MAC_DROP = 21,
PPE_SC_BYPASS_EGRESS_TUNL_CONTEXT = 22,
PPE_SC_BYPASS_EGRESS_FLOW_POLICER = 23,
/* This must be last as it determines the size of the BITMAP. */
PPE_SC_BYPASS_EGRESS_SIZE,
};
/* Hardware bitmaps for bypassing counter of packet. */
enum ppe_sc_counter_type {
PPE_SC_BYPASS_COUNTER_RX_VLAN = 0,
PPE_SC_BYPASS_COUNTER_RX = 1,
PPE_SC_BYPASS_COUNTER_TX_VLAN = 2,
PPE_SC_BYPASS_COUNTER_TX = 3,
/* This must be last as it determines the size of the BITMAP. */
PPE_SC_BYPASS_COUNTER_SIZE,
};
/* Hardware bitmaps for bypassing features of tunnel packet. */
enum ppe_sc_tunnel_type {
PPE_SC_BYPASS_TUNNEL_SERVICE_CODE = 0,
PPE_SC_BYPASS_TUNNEL_TUNNEL_HANDLE = 1,
PPE_SC_BYPASS_TUNNEL_L3_IF_CHECK = 2,
PPE_SC_BYPASS_TUNNEL_VLAN_CHECK = 3,
PPE_SC_BYPASS_TUNNEL_DMAC_CHECK = 4,
PPE_SC_BYPASS_TUNNEL_UDP_CSUM_0_CHECK = 5,
PPE_SC_BYPASS_TUNNEL_TBL_DE_ACCE_CHECK = 6,
PPE_SC_BYPASS_TUNNEL_PPPOE_MC_TERM_CHECK = 7,
PPE_SC_BYPASS_TUNNEL_TTL_EXCEED_CHECK = 8,
PPE_SC_BYPASS_TUNNEL_MAP_SRC_CHECK = 9,
PPE_SC_BYPASS_TUNNEL_MAP_DST_CHECK = 10,
PPE_SC_BYPASS_TUNNEL_LPM_DST_LOOKUP = 11,
PPE_SC_BYPASS_TUNNEL_LPM_LOOKUP = 12,
PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L2 = 13,
PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L3_IPV4 = 14,
PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L3_IPV6 = 15,
PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L4 = 16,
PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_TUNNEL = 17,
/* Values 18-19 are not specified by hardware. */
PPE_SC_BYPASS_TUNNEL_PRE_IPO = 20,
/* This must be last as it determines the size of the BITMAP. */
PPE_SC_BYPASS_TUNNEL_SIZE,
};
/**
* struct ppe_sc_bypass - PPE service bypass bitmaps
* @ingress: Bitmap of features that can be bypassed on the ingress packet.
* @egress: Bitmap of features that can be bypassed on the egress packet.
* @counter: Bitmap of features that can be bypassed on the counter type.
* @tunnel: Bitmap of features that can be bypassed on the tunnel packet.
*/
struct ppe_sc_bypass {
DECLARE_BITMAP(ingress, PPE_SC_BYPASS_INGRESS_SIZE);
DECLARE_BITMAP(egress, PPE_SC_BYPASS_EGRESS_SIZE);
DECLARE_BITMAP(counter, PPE_SC_BYPASS_COUNTER_SIZE);
DECLARE_BITMAP(tunnel, PPE_SC_BYPASS_TUNNEL_SIZE);
};
/**
* struct ppe_sc_cfg - PPE service code configuration.
* @dest_port_valid: Generate destination port or not.
* @dest_port: Destination port ID.
* @bitmaps: Bitmap of bypass features.
* @is_src: Destination port acts as source port, packet sent to CPU.
* @next_service_code: New service code generated.
* @eip_field_update_bitmap: Fields updated as actions taken for EIP.
* @eip_hw_service: Selected hardware functions for EIP.
* @eip_offset_sel: Packet offset selection, using packet's layer 4 offset
* or using packet's layer 3 offset for EIP.
*
* Service code is generated during the packet passing through PPE.
*/
struct ppe_sc_cfg {
bool dest_port_valid;
int dest_port;
struct ppe_sc_bypass bitmaps;
bool is_src;
int next_service_code;
int eip_field_update_bitmap;
int eip_hw_service;
int eip_offset_sel;
};
/**
* enum ppe_action_type - PPE action of the received packet.
* @PPE_ACTION_FORWARD: Packet forwarded per L2/L3 process.
* @PPE_ACTION_DROP: Packet dropped by PPE.
* @PPE_ACTION_COPY_TO_CPU: Packet copied to CPU port per multicast queue.
* @PPE_ACTION_REDIRECT_TO_CPU: Packet redirected to CPU port per unicast queue.
*/
enum ppe_action_type {
PPE_ACTION_FORWARD = 0,
PPE_ACTION_DROP = 1,
PPE_ACTION_COPY_TO_CPU = 2,
PPE_ACTION_REDIRECT_TO_CPU = 3,
};
/**
* struct ppe_rss_hash_cfg - PPE RSS hash configuration.
* @hash_mask: Mask of the generated hash value.
* @hash_fragment_mode: Hash generation mode for the first fragment of TCP,
* UDP and UDP-Lite packets, to use either 3 tuple or 5 tuple for RSS hash
* key computation.
* @hash_seed: Seed to generate RSS hash.
* @hash_sip_mix: Source IP selection.
* @hash_dip_mix: Destination IP selection.
* @hash_protocol_mix: Protocol selection.
* @hash_sport_mix: Source L4 port selection.
* @hash_dport_mix: Destination L4 port selection.
* @hash_fin_inner: RSS hash value first selection.
* @hash_fin_outer: RSS hash value second selection.
*
* PPE RSS hash value is generated for the packet based on the RSS hash
* configured.
*/
struct ppe_rss_hash_cfg {
u32 hash_mask;
bool hash_fragment_mode;
u32 hash_seed;
u8 hash_sip_mix[PPE_RSS_HASH_IP_LENGTH];
u8 hash_dip_mix[PPE_RSS_HASH_IP_LENGTH];
u8 hash_protocol_mix;
u8 hash_sport_mix;
u8 hash_dport_mix;
u8 hash_fin_inner[PPE_RSS_HASH_TUPLES];
u8 hash_fin_outer[PPE_RSS_HASH_TUPLES];
};
int ppe_hw_config(struct ppe_device *ppe_dev);
int ppe_queue_scheduler_set(struct ppe_device *ppe_dev,
int node_id, bool flow_level, int port,
struct ppe_scheduler_cfg scheduler_cfg);
int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev,
struct ppe_queue_ucast_dest queue_dst,
int queue_base,
int profile_id);
int ppe_queue_ucast_offset_pri_set(struct ppe_device *ppe_dev,
int profile_id,
int priority,
int queue_offset);
int ppe_queue_ucast_offset_hash_set(struct ppe_device *ppe_dev,
int profile_id,
int rss_hash,
int queue_offset);
int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,
enum ppe_resource_type type,
int *res_start, int *res_end);
int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc,
struct ppe_sc_cfg cfg);
int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port);
int ppe_rss_hash_config_set(struct ppe_device *ppe_dev, int mode,
struct ppe_rss_hash_cfg hash_cfg);
int ppe_ring_queue_map_set(struct ppe_device *ppe_dev,
int ring_id,
u32 *queue_map);
#endif
@@ -0,0 +1,847 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
/* PPE debugfs routines for display of PPE counters useful for debug. */
#include <linux/bitfield.h>
#include <linux/debugfs.h>
#include <linux/dev_printk.h>
#include <linux/device.h>
#include <linux/regmap.h>
#include <linux/seq_file.h>
#include "ppe.h"
#include "ppe_config.h"
#include "ppe_debugfs.h"
#include "ppe_regs.h"
#define PPE_PKT_CNT_TBL_SIZE 3
#define PPE_DROP_PKT_CNT_TBL_SIZE 5
#define PPE_W0_PKT_CNT GENMASK(31, 0)
#define PPE_W2_DROP_PKT_CNT_LOW GENMASK(31, 8)
#define PPE_W3_DROP_PKT_CNT_HIGH GENMASK(7, 0)
#define PPE_GET_PKT_CNT(tbl_cnt) \
FIELD_GET(PPE_W0_PKT_CNT, *(tbl_cnt))
#define PPE_GET_DROP_PKT_CNT_LOW(tbl_cnt) \
FIELD_GET(PPE_W2_DROP_PKT_CNT_LOW, *((tbl_cnt) + 0x2))
#define PPE_GET_DROP_PKT_CNT_HIGH(tbl_cnt) \
FIELD_GET(PPE_W3_DROP_PKT_CNT_HIGH, *((tbl_cnt) + 0x3))
/**
* enum ppe_cnt_size_type - PPE counter size type
* @PPE_PKT_CNT_SIZE_1WORD: Counter size with single register
* @PPE_PKT_CNT_SIZE_3WORD: Counter size with table of 3 words
* @PPE_PKT_CNT_SIZE_5WORD: Counter size with table of 5 words
*
* PPE takes the different register size to record the packet counters.
* It uses single register, or register table with 3 words or 5 words.
* The counter with table size 5 words also records the drop counter.
* There are also some other counter types occupying sizes less than 32
* bits, which is not covered by this enumeration type.
*/
enum ppe_cnt_size_type {
PPE_PKT_CNT_SIZE_1WORD,
PPE_PKT_CNT_SIZE_3WORD,
PPE_PKT_CNT_SIZE_5WORD,
};
/**
* enum ppe_cnt_type - PPE counter type.
* @PPE_CNT_BM: Packet counter processed by BM.
* @PPE_CNT_PARSE: Packet counter parsed on ingress.
* @PPE_CNT_PORT_RX: Packet counter on the ingress port.
* @PPE_CNT_VLAN_RX: VLAN packet counter received.
* @PPE_CNT_L2_FWD: Packet counter processed by L2 forwarding.
* @PPE_CNT_CPU_CODE: Packet counter marked with various CPU codes.
* @PPE_CNT_VLAN_TX: VLAN packet counter transmitted.
* @PPE_CNT_PORT_TX: Packet counter on the egress port.
* @PPE_CNT_QM: Packet counter processed by QM.
*/
enum ppe_cnt_type {
PPE_CNT_BM,
PPE_CNT_PARSE,
PPE_CNT_PORT_RX,
PPE_CNT_VLAN_RX,
PPE_CNT_L2_FWD,
PPE_CNT_CPU_CODE,
PPE_CNT_VLAN_TX,
PPE_CNT_PORT_TX,
PPE_CNT_QM,
};
/**
* struct ppe_debugfs_entry - PPE debugfs entry.
* @name: Debugfs file name.
* @counter_type: PPE packet counter type.
* @ppe: PPE device.
*
* The PPE debugfs entry is used to create the debugfs file and passed
* to debugfs_create_file() as private data.
*/
struct ppe_debugfs_entry {
const char *name;
enum ppe_cnt_type counter_type;
struct ppe_device *ppe;
};
static const struct ppe_debugfs_entry debugfs_files[] = {
{
.name = "bm",
.counter_type = PPE_CNT_BM,
},
{
.name = "parse",
.counter_type = PPE_CNT_PARSE,
},
{
.name = "port_rx",
.counter_type = PPE_CNT_PORT_RX,
},
{
.name = "vlan_rx",
.counter_type = PPE_CNT_VLAN_RX,
},
{
.name = "l2_forward",
.counter_type = PPE_CNT_L2_FWD,
},
{
.name = "cpu_code",
.counter_type = PPE_CNT_CPU_CODE,
},
{
.name = "vlan_tx",
.counter_type = PPE_CNT_VLAN_TX,
},
{
.name = "port_tx",
.counter_type = PPE_CNT_PORT_TX,
},
{
.name = "qm",
.counter_type = PPE_CNT_QM,
},
};
static int ppe_pkt_cnt_get(struct ppe_device *ppe_dev, u32 reg,
enum ppe_cnt_size_type cnt_type,
u32 *cnt, u32 *drop_cnt)
{
u32 drop_pkt_cnt[PPE_DROP_PKT_CNT_TBL_SIZE];
u32 pkt_cnt[PPE_PKT_CNT_TBL_SIZE];
u32 value;
int ret;
switch (cnt_type) {
case PPE_PKT_CNT_SIZE_1WORD:
ret = regmap_read(ppe_dev->regmap, reg, &value);
if (ret)
return ret;
*cnt = value;
break;
case PPE_PKT_CNT_SIZE_3WORD:
ret = regmap_bulk_read(ppe_dev->regmap, reg,
pkt_cnt, ARRAY_SIZE(pkt_cnt));
if (ret)
return ret;
*cnt = PPE_GET_PKT_CNT(pkt_cnt);
break;
case PPE_PKT_CNT_SIZE_5WORD:
ret = regmap_bulk_read(ppe_dev->regmap, reg,
drop_pkt_cnt, ARRAY_SIZE(drop_pkt_cnt));
if (ret)
return ret;
*cnt = PPE_GET_PKT_CNT(drop_pkt_cnt);
/* Drop counter with low 24 bits. */
value = PPE_GET_DROP_PKT_CNT_LOW(drop_pkt_cnt);
*drop_cnt = FIELD_PREP(GENMASK(23, 0), value);
/* Drop counter with high 8 bits. */
value = PPE_GET_DROP_PKT_CNT_HIGH(drop_pkt_cnt);
*drop_cnt |= FIELD_PREP(GENMASK(31, 24), value);
break;
}
return 0;
}
static void ppe_tbl_pkt_cnt_clear(struct ppe_device *ppe_dev, u32 reg,
enum ppe_cnt_size_type cnt_type)
{
u32 drop_pkt_cnt[PPE_DROP_PKT_CNT_TBL_SIZE] = {};
u32 pkt_cnt[PPE_PKT_CNT_TBL_SIZE] = {};
switch (cnt_type) {
case PPE_PKT_CNT_SIZE_1WORD:
regmap_write(ppe_dev->regmap, reg, 0);
break;
case PPE_PKT_CNT_SIZE_3WORD:
regmap_bulk_write(ppe_dev->regmap, reg,
pkt_cnt, ARRAY_SIZE(pkt_cnt));
break;
case PPE_PKT_CNT_SIZE_5WORD:
regmap_bulk_write(ppe_dev->regmap, reg,
drop_pkt_cnt, ARRAY_SIZE(drop_pkt_cnt));
break;
}
}
static int ppe_bm_counter_get(struct ppe_device *ppe_dev, struct seq_file *seq)
{
u32 reg, val, pkt_cnt, pkt_cnt1;
int ret, i, tag;
seq_printf(seq, "%-24s", "BM SILENT_DROP:");
tag = 0;
for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) {
reg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD,
&pkt_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (pkt_cnt > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u(%s=%04d)", pkt_cnt, "port", i);
}
}
seq_putc(seq, '\n');
/* The number of packets dropped because hardware buffers were
* available only partially for the packet.
*/
seq_printf(seq, "%-24s", "BM OVERFLOW_DROP:");
tag = 0;
for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES; i++) {
reg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
&pkt_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (pkt_cnt > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u(%s=%04d)", pkt_cnt, "port", i);
}
}
seq_putc(seq, '\n');
/* The number of currently occupied buffers, that can't be flushed. */
seq_printf(seq, "%-24s", "BM USED/REACT:");
tag = 0;
for (i = 0; i < PPE_BM_USED_CNT_TBL_ENTRIES; i++) {
reg = PPE_BM_USED_CNT_TBL_ADDR + i * PPE_BM_USED_CNT_TBL_INC;
ret = regmap_read(ppe_dev->regmap, reg, &val);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
/* The number of PPE buffers used for caching the received
* packets before the pause frame sent.
*/
pkt_cnt = FIELD_GET(PPE_BM_USED_CNT_VAL, val);
reg = PPE_BM_REACT_CNT_TBL_ADDR + i * PPE_BM_REACT_CNT_TBL_INC;
ret = regmap_read(ppe_dev->regmap, reg, &val);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
/* The number of PPE buffers used for caching the received
* packets after pause frame sent out.
*/
pkt_cnt1 = FIELD_GET(PPE_BM_REACT_CNT_VAL, val);
if (pkt_cnt > 0 || pkt_cnt1 > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, pkt_cnt1,
"port", i);
}
}
seq_putc(seq, '\n');
return 0;
}
/* The number of packets processed by the ingress parser module of PPE. */
static int ppe_parse_pkt_counter_get(struct ppe_device *ppe_dev,
struct seq_file *seq)
{
u32 reg, cnt = 0, tunnel_cnt = 0;
int i, ret, tag = 0;
seq_printf(seq, "%-24s", "PARSE TPRX/IPRX:");
for (i = 0; i < PPE_IPR_PKT_CNT_TBL_ENTRIES; i++) {
reg = PPE_TPR_PKT_CNT_TBL_ADDR + i * PPE_TPR_PKT_CNT_TBL_INC;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD,
&tunnel_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
reg = PPE_IPR_PKT_CNT_TBL_ADDR + i * PPE_IPR_PKT_CNT_TBL_INC;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD,
&cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (tunnel_cnt > 0 || cnt > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u/%u(%s=%04d)", tunnel_cnt, cnt,
"port", i);
}
}
seq_putc(seq, '\n');
return 0;
}
/* The number of packets received or dropped on the ingress port. */
static int ppe_port_rx_counter_get(struct ppe_device *ppe_dev,
struct seq_file *seq)
{
u32 reg, pkt_cnt = 0, drop_cnt = 0;
int ret, i, tag;
seq_printf(seq, "%-24s", "PORT RX/RX_DROP:");
tag = 0;
for (i = 0; i < PPE_PHY_PORT_RX_CNT_TBL_ENTRIES; i++) {
reg = PPE_PHY_PORT_RX_CNT_TBL_ADDR + PPE_PHY_PORT_RX_CNT_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD,
&pkt_cnt, &drop_cnt);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (pkt_cnt > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, drop_cnt,
"port", i);
}
}
seq_putc(seq, '\n');
seq_printf(seq, "%-24s", "VPORT RX/RX_DROP:");
tag = 0;
for (i = 0; i < PPE_PORT_RX_CNT_TBL_ENTRIES; i++) {
reg = PPE_PORT_RX_CNT_TBL_ADDR + PPE_PORT_RX_CNT_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD,
&pkt_cnt, &drop_cnt);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (pkt_cnt > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, drop_cnt,
"port", i);
}
}
seq_putc(seq, '\n');
return 0;
}
/* The number of packets received or dropped by layer 2 processing. */
static int ppe_l2_counter_get(struct ppe_device *ppe_dev,
struct seq_file *seq)
{
u32 reg, pkt_cnt = 0, drop_cnt = 0;
int ret, i, tag = 0;
seq_printf(seq, "%-24s", "L2 RX/RX_DROP:");
for (i = 0; i < PPE_PRE_L2_CNT_TBL_ENTRIES; i++) {
reg = PPE_PRE_L2_CNT_TBL_ADDR + PPE_PRE_L2_CNT_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD,
&pkt_cnt, &drop_cnt);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (pkt_cnt > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, drop_cnt,
"vsi", i);
}
}
seq_putc(seq, '\n');
return 0;
}
/* The number of VLAN packets received by PPE. */
static int ppe_vlan_rx_counter_get(struct ppe_device *ppe_dev,
struct seq_file *seq)
{
u32 reg, pkt_cnt = 0;
int ret, i, tag = 0;
seq_printf(seq, "%-24s", "VLAN RX:");
for (i = 0; i < PPE_VLAN_CNT_TBL_ENTRIES; i++) {
reg = PPE_VLAN_CNT_TBL_ADDR + PPE_VLAN_CNT_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
&pkt_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (pkt_cnt > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u(%s=%04d)", pkt_cnt, "vsi", i);
}
}
seq_putc(seq, '\n');
return 0;
}
/* The number of packets handed to CPU by PPE. */
static int ppe_cpu_code_counter_get(struct ppe_device *ppe_dev,
struct seq_file *seq)
{
u32 reg, pkt_cnt = 0;
int ret, i;
seq_printf(seq, "%-24s", "CPU CODE:");
for (i = 0; i < PPE_DROP_CPU_CNT_TBL_ENTRIES; i++) {
reg = PPE_DROP_CPU_CNT_TBL_ADDR + PPE_DROP_CPU_CNT_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
&pkt_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (!pkt_cnt)
continue;
/* There are 256 CPU codes saved in the first 256 entries
* of register table, and 128 drop codes for each PPE port
* (0-7), the total entries is 256 + 8 * 128.
*/
if (i < 256)
seq_printf(seq, "%10u(cpucode:%d)", pkt_cnt, i);
else
seq_printf(seq, "%10u(port=%04d),dropcode:%d", pkt_cnt,
(i - 256) % 8, (i - 256) / 8);
seq_putc(seq, '\n');
seq_printf(seq, "%-24s", "");
}
seq_putc(seq, '\n');
return 0;
}
/* The number of packets forwarded by VLAN on the egress direction. */
static int ppe_vlan_tx_counter_get(struct ppe_device *ppe_dev,
struct seq_file *seq)
{
u32 reg, pkt_cnt = 0;
int ret, i, tag = 0;
seq_printf(seq, "%-24s", "VLAN TX:");
for (i = 0; i < PPE_EG_VSI_COUNTER_TBL_ENTRIES; i++) {
reg = PPE_EG_VSI_COUNTER_TBL_ADDR + PPE_EG_VSI_COUNTER_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
&pkt_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (pkt_cnt > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u(%s=%04d)", pkt_cnt, "vsi", i);
}
}
seq_putc(seq, '\n');
return 0;
}
/* The number of packets transmitted or dropped on the egress port. */
static int ppe_port_tx_counter_get(struct ppe_device *ppe_dev,
struct seq_file *seq)
{
u32 reg, pkt_cnt = 0, drop_cnt = 0;
int ret, i, tag;
seq_printf(seq, "%-24s", "VPORT TX/TX_DROP:");
tag = 0;
for (i = 0; i < PPE_VPORT_TX_COUNTER_TBL_ENTRIES; i++) {
reg = PPE_VPORT_TX_COUNTER_TBL_ADDR + PPE_VPORT_TX_COUNTER_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
&pkt_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
reg = PPE_VPORT_TX_DROP_CNT_TBL_ADDR + PPE_VPORT_TX_DROP_CNT_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
&drop_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (pkt_cnt > 0 || drop_cnt > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, drop_cnt,
"port", i);
}
}
seq_putc(seq, '\n');
seq_printf(seq, "%-24s", "PORT TX/TX_DROP:");
tag = 0;
for (i = 0; i < PPE_PORT_TX_COUNTER_TBL_ENTRIES; i++) {
reg = PPE_PORT_TX_COUNTER_TBL_ADDR + PPE_PORT_TX_COUNTER_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
&pkt_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
reg = PPE_PORT_TX_DROP_CNT_TBL_ADDR + PPE_PORT_TX_DROP_CNT_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
&drop_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (pkt_cnt > 0 || drop_cnt > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u/%u(%s=%04d)", pkt_cnt, drop_cnt,
"port", i);
}
}
seq_putc(seq, '\n');
return 0;
}
/* The number of packets transmitted or pending by the PPE queue. */
static int ppe_queue_counter_get(struct ppe_device *ppe_dev,
struct seq_file *seq)
{
u32 reg, val, pkt_cnt = 0, pend_cnt = 0, drop_cnt = 0;
int ret, i, tag = 0;
seq_printf(seq, "%-24s", "QUEUE TX/PEND/DROP:");
for (i = 0; i < PPE_QUEUE_TX_COUNTER_TBL_ENTRIES; i++) {
reg = PPE_QUEUE_TX_COUNTER_TBL_ADDR + PPE_QUEUE_TX_COUNTER_TBL_INC * i;
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
&pkt_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
if (i < PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES) {
reg = PPE_AC_UNICAST_QUEUE_CNT_TBL_ADDR +
PPE_AC_UNICAST_QUEUE_CNT_TBL_INC * i;
ret = regmap_read(ppe_dev->regmap, reg, &val);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
pend_cnt = FIELD_GET(PPE_AC_UNICAST_QUEUE_CNT_TBL_PEND_CNT, val);
reg = PPE_UNICAST_DROP_CNT_TBL_ADDR +
PPE_AC_UNICAST_QUEUE_CNT_TBL_INC *
(i * PPE_UNICAST_DROP_TYPES + PPE_UNICAST_DROP_FORCE_OFFSET);
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
&drop_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
} else {
int mq_offset = i - PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES;
reg = PPE_AC_MULTICAST_QUEUE_CNT_TBL_ADDR +
PPE_AC_MULTICAST_QUEUE_CNT_TBL_INC * mq_offset;
ret = regmap_read(ppe_dev->regmap, reg, &val);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
pend_cnt = FIELD_GET(PPE_AC_MULTICAST_QUEUE_CNT_TBL_PEND_CNT, val);
if (mq_offset < PPE_P0_MULTICAST_QUEUE_NUM) {
reg = PPE_CPU_PORT_MULTICAST_FORCE_DROP_CNT_TBL_ADDR(mq_offset);
} else {
mq_offset -= PPE_P0_MULTICAST_QUEUE_NUM;
reg = PPE_P1_MULTICAST_DROP_CNT_TBL_ADDR;
reg += (mq_offset / PPE_MULTICAST_QUEUE_NUM) *
PPE_MULTICAST_QUEUE_PORT_ADDR_INC;
reg += (mq_offset % PPE_MULTICAST_QUEUE_NUM) *
PPE_MULTICAST_DROP_CNT_TBL_INC *
PPE_MULTICAST_DROP_TYPES;
}
ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
&drop_cnt, NULL);
if (ret) {
dev_err(ppe_dev->dev, "CNT ERROR %d\n", ret);
return ret;
}
}
if (pkt_cnt > 0 || pend_cnt > 0 || drop_cnt > 0) {
if (!((++tag) % 4))
seq_printf(seq, "\n%-24s", "");
seq_printf(seq, "%10u/%u/%u(%s=%04d)",
pkt_cnt, pend_cnt, drop_cnt, "queue", i);
}
}
seq_putc(seq, '\n');
return 0;
}
/* Display the various packet counters of PPE. */
static int ppe_packet_counter_show(struct seq_file *seq, void *v)
{
struct ppe_debugfs_entry *entry = seq->private;
struct ppe_device *ppe_dev = entry->ppe;
int ret;
switch (entry->counter_type) {
case PPE_CNT_BM:
ret = ppe_bm_counter_get(ppe_dev, seq);
break;
case PPE_CNT_PARSE:
ret = ppe_parse_pkt_counter_get(ppe_dev, seq);
break;
case PPE_CNT_PORT_RX:
ret = ppe_port_rx_counter_get(ppe_dev, seq);
break;
case PPE_CNT_VLAN_RX:
ret = ppe_vlan_rx_counter_get(ppe_dev, seq);
break;
case PPE_CNT_L2_FWD:
ret = ppe_l2_counter_get(ppe_dev, seq);
break;
case PPE_CNT_CPU_CODE:
ret = ppe_cpu_code_counter_get(ppe_dev, seq);
break;
case PPE_CNT_VLAN_TX:
ret = ppe_vlan_tx_counter_get(ppe_dev, seq);
break;
case PPE_CNT_PORT_TX:
ret = ppe_port_tx_counter_get(ppe_dev, seq);
break;
case PPE_CNT_QM:
ret = ppe_queue_counter_get(ppe_dev, seq);
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
/* Flush the various packet counters of PPE. */
static ssize_t ppe_packet_counter_write(struct file *file,
const char __user *buf,
size_t count, loff_t *pos)
{
struct ppe_debugfs_entry *entry = file_inode(file)->i_private;
struct ppe_device *ppe_dev = entry->ppe;
u32 reg;
int i;
switch (entry->counter_type) {
case PPE_CNT_BM:
for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) {
reg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD);
}
for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES; i++) {
reg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
}
break;
case PPE_CNT_PARSE:
for (i = 0; i < PPE_IPR_PKT_CNT_TBL_ENTRIES; i++) {
reg = PPE_IPR_PKT_CNT_TBL_ADDR + i * PPE_IPR_PKT_CNT_TBL_INC;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD);
reg = PPE_TPR_PKT_CNT_TBL_ADDR + i * PPE_TPR_PKT_CNT_TBL_INC;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD);
}
break;
case PPE_CNT_PORT_RX:
for (i = 0; i < PPE_PORT_RX_CNT_TBL_ENTRIES; i++) {
reg = PPE_PORT_RX_CNT_TBL_ADDR + PPE_PORT_RX_CNT_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD);
}
for (i = 0; i < PPE_PHY_PORT_RX_CNT_TBL_ENTRIES; i++) {
reg = PPE_PHY_PORT_RX_CNT_TBL_ADDR + PPE_PHY_PORT_RX_CNT_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD);
}
break;
case PPE_CNT_VLAN_RX:
for (i = 0; i < PPE_VLAN_CNT_TBL_ENTRIES; i++) {
reg = PPE_VLAN_CNT_TBL_ADDR + PPE_VLAN_CNT_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
}
break;
case PPE_CNT_L2_FWD:
for (i = 0; i < PPE_PRE_L2_CNT_TBL_ENTRIES; i++) {
reg = PPE_PRE_L2_CNT_TBL_ADDR + PPE_PRE_L2_CNT_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD);
}
break;
case PPE_CNT_CPU_CODE:
for (i = 0; i < PPE_DROP_CPU_CNT_TBL_ENTRIES; i++) {
reg = PPE_DROP_CPU_CNT_TBL_ADDR + PPE_DROP_CPU_CNT_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
}
break;
case PPE_CNT_VLAN_TX:
for (i = 0; i < PPE_EG_VSI_COUNTER_TBL_ENTRIES; i++) {
reg = PPE_EG_VSI_COUNTER_TBL_ADDR + PPE_EG_VSI_COUNTER_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
}
break;
case PPE_CNT_PORT_TX:
for (i = 0; i < PPE_PORT_TX_COUNTER_TBL_ENTRIES; i++) {
reg = PPE_PORT_TX_DROP_CNT_TBL_ADDR + PPE_PORT_TX_DROP_CNT_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
reg = PPE_PORT_TX_COUNTER_TBL_ADDR + PPE_PORT_TX_COUNTER_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
}
for (i = 0; i < PPE_VPORT_TX_COUNTER_TBL_ENTRIES; i++) {
reg = PPE_VPORT_TX_COUNTER_TBL_ADDR + PPE_VPORT_TX_COUNTER_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
reg = PPE_VPORT_TX_DROP_CNT_TBL_ADDR + PPE_VPORT_TX_DROP_CNT_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
}
break;
case PPE_CNT_QM:
for (i = 0; i < PPE_QUEUE_TX_COUNTER_TBL_ENTRIES; i++) {
reg = PPE_QUEUE_TX_COUNTER_TBL_ADDR + PPE_QUEUE_TX_COUNTER_TBL_INC * i;
ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
}
break;
default:
break;
}
return count;
}
DEFINE_SHOW_STORE_ATTRIBUTE(ppe_packet_counter);
void ppe_debugfs_setup(struct ppe_device *ppe_dev)
{
struct ppe_debugfs_entry *entry;
int i;
ppe_dev->debugfs_root = debugfs_create_dir("ppe", NULL);
if (IS_ERR(ppe_dev->debugfs_root))
return;
for (i = 0; i < ARRAY_SIZE(debugfs_files); i++) {
entry = devm_kzalloc(ppe_dev->dev, sizeof(*entry), GFP_KERNEL);
if (!entry)
return;
entry->ppe = ppe_dev;
entry->counter_type = debugfs_files[i].counter_type;
debugfs_create_file(debugfs_files[i].name, 0444,
ppe_dev->debugfs_root, entry,
&ppe_packet_counter_fops);
}
}
void ppe_debugfs_teardown(struct ppe_device *ppe_dev)
{
debugfs_remove_recursive(ppe_dev->debugfs_root);
ppe_dev->debugfs_root = NULL;
}
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-only
*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
/* PPE debugfs counters setup. */
#ifndef __PPE_DEBUGFS_H__
#define __PPE_DEBUGFS_H__
#include "ppe.h"
void ppe_debugfs_setup(struct ppe_device *ppe_dev);
void ppe_debugfs_teardown(struct ppe_device *ppe_dev);
#endif
@@ -0,0 +1,591 @@
/* SPDX-License-Identifier: GPL-2.0-only
*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
/* PPE hardware register and table declarations. */
#ifndef __PPE_REGS_H__
#define __PPE_REGS_H__
#include <linux/bitfield.h>
/* PPE scheduler configurations for buffer manager block. */
#define PPE_BM_SCH_CTRL_ADDR 0xb000
#define PPE_BM_SCH_CTRL_INC 4
#define PPE_BM_SCH_CTRL_SCH_DEPTH GENMASK(7, 0)
#define PPE_BM_SCH_CTRL_SCH_OFFSET GENMASK(14, 8)
#define PPE_BM_SCH_CTRL_SCH_EN BIT(31)
/* PPE drop counters. */
#define PPE_DROP_CNT_TBL_ADDR 0xb024
#define PPE_DROP_CNT_TBL_ENTRIES 8
#define PPE_DROP_CNT_TBL_INC 4
/* BM port drop counters. */
#define PPE_DROP_STAT_TBL_ADDR 0xe000
#define PPE_DROP_STAT_TBL_ENTRIES 30
#define PPE_DROP_STAT_TBL_INC 0x10
/* Egress VLAN counters. */
#define PPE_EG_VSI_COUNTER_TBL_ADDR 0x41000
#define PPE_EG_VSI_COUNTER_TBL_ENTRIES 64
#define PPE_EG_VSI_COUNTER_TBL_INC 0x10
/* Port TX counters. */
#define PPE_PORT_TX_COUNTER_TBL_ADDR 0x45000
#define PPE_PORT_TX_COUNTER_TBL_ENTRIES 8
#define PPE_PORT_TX_COUNTER_TBL_INC 0x10
/* Virtual port TX counters. */
#define PPE_VPORT_TX_COUNTER_TBL_ADDR 0x47000
#define PPE_VPORT_TX_COUNTER_TBL_ENTRIES 256
#define PPE_VPORT_TX_COUNTER_TBL_INC 0x10
/* Queue counters. */
#define PPE_QUEUE_TX_COUNTER_TBL_ADDR 0x4a000
#define PPE_QUEUE_TX_COUNTER_TBL_ENTRIES 300
#define PPE_QUEUE_TX_COUNTER_TBL_INC 0x10
/* RSS settings are to calculate the random RSS hash value generated during
* packet receive to ARM cores. This hash is then used to generate the queue
* offset used to determine the queue used to transmit the packet to ARM cores.
*/
#define PPE_RSS_HASH_MASK_ADDR 0xb4318
#define PPE_RSS_HASH_MASK_HASH_MASK GENMASK(20, 0)
#define PPE_RSS_HASH_MASK_FRAGMENT BIT(28)
#define PPE_RSS_HASH_SEED_ADDR 0xb431c
#define PPE_RSS_HASH_SEED_VAL GENMASK(31, 0)
#define PPE_RSS_HASH_MIX_ADDR 0xb4320
#define PPE_RSS_HASH_MIX_ENTRIES 11
#define PPE_RSS_HASH_MIX_INC 4
#define PPE_RSS_HASH_MIX_VAL GENMASK(4, 0)
#define PPE_RSS_HASH_FIN_ADDR 0xb4350
#define PPE_RSS_HASH_FIN_ENTRIES 5
#define PPE_RSS_HASH_FIN_INC 4
#define PPE_RSS_HASH_FIN_INNER GENMASK(4, 0)
#define PPE_RSS_HASH_FIN_OUTER GENMASK(9, 5)
#define PPE_RSS_HASH_MASK_IPV4_ADDR 0xb4380
#define PPE_RSS_HASH_MASK_IPV4_HASH_MASK GENMASK(20, 0)
#define PPE_RSS_HASH_MASK_IPV4_FRAGMENT BIT(28)
#define PPE_RSS_HASH_SEED_IPV4_ADDR 0xb4384
#define PPE_RSS_HASH_SEED_IPV4_VAL GENMASK(31, 0)
#define PPE_RSS_HASH_MIX_IPV4_ADDR 0xb4390
#define PPE_RSS_HASH_MIX_IPV4_ENTRIES 5
#define PPE_RSS_HASH_MIX_IPV4_INC 4
#define PPE_RSS_HASH_MIX_IPV4_VAL GENMASK(4, 0)
#define PPE_RSS_HASH_FIN_IPV4_ADDR 0xb43b0
#define PPE_RSS_HASH_FIN_IPV4_ENTRIES 5
#define PPE_RSS_HASH_FIN_IPV4_INC 4
#define PPE_RSS_HASH_FIN_IPV4_INNER GENMASK(4, 0)
#define PPE_RSS_HASH_FIN_IPV4_OUTER GENMASK(9, 5)
#define PPE_BM_SCH_CFG_TBL_ADDR 0xc000
#define PPE_BM_SCH_CFG_TBL_ENTRIES 128
#define PPE_BM_SCH_CFG_TBL_INC 0x10
#define PPE_BM_SCH_CFG_TBL_PORT_NUM GENMASK(3, 0)
#define PPE_BM_SCH_CFG_TBL_DIR BIT(4)
#define PPE_BM_SCH_CFG_TBL_VALID BIT(5)
#define PPE_BM_SCH_CFG_TBL_SECOND_PORT_VALID BIT(6)
#define PPE_BM_SCH_CFG_TBL_SECOND_PORT GENMASK(11, 8)
/* PPE service code configuration for the ingress direction functions,
* including bypass configuration for relevant PPE switch core functions
* such as flow entry lookup bypass.
*/
#define PPE_SERVICE_TBL_ADDR 0x15000
#define PPE_SERVICE_TBL_ENTRIES 256
#define PPE_SERVICE_TBL_INC 0x10
#define PPE_SERVICE_W0_BYPASS_BITMAP GENMASK(31, 0)
#define PPE_SERVICE_W1_RX_CNT_EN BIT(0)
#define PPE_SERVICE_SET_BYPASS_BITMAP(tbl_cfg, value) \
FIELD_MODIFY(PPE_SERVICE_W0_BYPASS_BITMAP, tbl_cfg, value)
#define PPE_SERVICE_SET_RX_CNT_EN(tbl_cfg, value) \
FIELD_MODIFY(PPE_SERVICE_W1_RX_CNT_EN, (tbl_cfg) + 0x1, value)
/* PPE port egress VLAN configurations. */
#define PPE_PORT_EG_VLAN_TBL_ADDR 0x20020
#define PPE_PORT_EG_VLAN_TBL_ENTRIES 8
#define PPE_PORT_EG_VLAN_TBL_INC 4
#define PPE_PORT_EG_VLAN_TBL_VLAN_TYPE BIT(0)
#define PPE_PORT_EG_VLAN_TBL_CTAG_MODE GENMASK(2, 1)
#define PPE_PORT_EG_VLAN_TBL_STAG_MODE GENMASK(4, 3)
#define PPE_PORT_EG_VLAN_TBL_VSI_TAG_MODE_EN BIT(5)
#define PPE_PORT_EG_VLAN_TBL_PCP_PROP_CMD BIT(6)
#define PPE_PORT_EG_VLAN_TBL_DEI_PROP_CMD BIT(7)
#define PPE_PORT_EG_VLAN_TBL_TX_COUNTING_EN BIT(8)
/* PPE queue counters enable/disable control. */
#define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044
#define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2)
/* PPE service code configuration on the egress direction. */
#define PPE_EG_SERVICE_TBL_ADDR 0x43000
#define PPE_EG_SERVICE_TBL_ENTRIES 256
#define PPE_EG_SERVICE_TBL_INC 0x10
#define PPE_EG_SERVICE_W0_UPDATE_ACTION GENMASK(31, 0)
#define PPE_EG_SERVICE_W1_NEXT_SERVCODE GENMASK(7, 0)
#define PPE_EG_SERVICE_W1_HW_SERVICE GENMASK(13, 8)
#define PPE_EG_SERVICE_W1_OFFSET_SEL BIT(14)
#define PPE_EG_SERVICE_W1_TX_CNT_EN BIT(15)
#define PPE_EG_SERVICE_SET_UPDATE_ACTION(tbl_cfg, value) \
FIELD_MODIFY(PPE_EG_SERVICE_W0_UPDATE_ACTION, tbl_cfg, value)
#define PPE_EG_SERVICE_SET_NEXT_SERVCODE(tbl_cfg, value) \
FIELD_MODIFY(PPE_EG_SERVICE_W1_NEXT_SERVCODE, (tbl_cfg) + 0x1, value)
#define PPE_EG_SERVICE_SET_HW_SERVICE(tbl_cfg, value) \
FIELD_MODIFY(PPE_EG_SERVICE_W1_HW_SERVICE, (tbl_cfg) + 0x1, value)
#define PPE_EG_SERVICE_SET_OFFSET_SEL(tbl_cfg, value) \
FIELD_MODIFY(PPE_EG_SERVICE_W1_OFFSET_SEL, (tbl_cfg) + 0x1, value)
#define PPE_EG_SERVICE_SET_TX_CNT_EN(tbl_cfg, value) \
FIELD_MODIFY(PPE_EG_SERVICE_W1_TX_CNT_EN, (tbl_cfg) + 0x1, value)
/* PPE port bridge configuration */
#define PPE_PORT_BRIDGE_CTRL_ADDR 0x60300
#define PPE_PORT_BRIDGE_CTRL_ENTRIES 8
#define PPE_PORT_BRIDGE_CTRL_INC 4
#define PPE_PORT_BRIDGE_NEW_LRN_EN BIT(0)
#define PPE_PORT_BRIDGE_STA_MOVE_LRN_EN BIT(3)
#define PPE_PORT_BRIDGE_TXMAC_EN BIT(16)
/* PPE port control configurations for the traffic to the multicast queues. */
#define PPE_MC_MTU_CTRL_TBL_ADDR 0x60a00
#define PPE_MC_MTU_CTRL_TBL_ENTRIES 8
#define PPE_MC_MTU_CTRL_TBL_INC 4
#define PPE_MC_MTU_CTRL_TBL_MTU GENMASK(13, 0)
#define PPE_MC_MTU_CTRL_TBL_MTU_CMD GENMASK(15, 14)
#define PPE_MC_MTU_CTRL_TBL_TX_CNT_EN BIT(16)
/* PPE VSI configurations */
#define PPE_VSI_TBL_ADDR 0x63800
#define PPE_VSI_TBL_ENTRIES 64
#define PPE_VSI_TBL_INC 0x10
#define PPE_VSI_W0_MEMBER_PORT_BITMAP GENMASK(7, 0)
#define PPE_VSI_W0_UUC_BITMAP GENMASK(15, 8)
#define PPE_VSI_W0_UMC_BITMAP GENMASK(23, 16)
#define PPE_VSI_W0_BC_BITMAP GENMASK(31, 24)
#define PPE_VSI_W1_NEW_ADDR_LRN_EN BIT(0)
#define PPE_VSI_W1_NEW_ADDR_FWD_CMD GENMASK(2, 1)
#define PPE_VSI_W1_STATION_MOVE_LRN_EN BIT(3)
#define PPE_VSI_W1_STATION_MOVE_FWD_CMD GENMASK(5, 4)
#define PPE_VSI_SET_MEMBER_PORT_BITMAP(tbl_cfg, value) \
FIELD_MODIFY(PPE_VSI_W0_MEMBER_PORT_BITMAP, tbl_cfg, value)
#define PPE_VSI_SET_UUC_BITMAP(tbl_cfg, value) \
FIELD_MODIFY(PPE_VSI_W0_UUC_BITMAP, tbl_cfg, value)
#define PPE_VSI_SET_UMC_BITMAP(tbl_cfg, value) \
FIELD_MODIFY(PPE_VSI_W0_UMC_BITMAP, tbl_cfg, value)
#define PPE_VSI_SET_BC_BITMAP(tbl_cfg, value) \
FIELD_MODIFY(PPE_VSI_W0_BC_BITMAP, tbl_cfg, value)
#define PPE_VSI_SET_NEW_ADDR_LRN_EN(tbl_cfg, value) \
FIELD_MODIFY(PPE_VSI_W1_NEW_ADDR_LRN_EN, (tbl_cfg) + 0x1, value)
#define PPE_VSI_SET_NEW_ADDR_FWD_CMD(tbl_cfg, value) \
FIELD_MODIFY(PPE_VSI_W1_NEW_ADDR_FWD_CMD, (tbl_cfg) + 0x1, value)
#define PPE_VSI_SET_STATION_MOVE_LRN_EN(tbl_cfg, value) \
FIELD_MODIFY(PPE_VSI_W1_STATION_MOVE_LRN_EN, (tbl_cfg) + 0x1, value)
#define PPE_VSI_SET_STATION_MOVE_FWD_CMD(tbl_cfg, value) \
FIELD_MODIFY(PPE_VSI_W1_STATION_MOVE_FWD_CMD, (tbl_cfg) + 0x1, value)
/* PPE port control configurations for the traffic to the unicast queues. */
#define PPE_MRU_MTU_CTRL_TBL_ADDR 0x65000
#define PPE_MRU_MTU_CTRL_TBL_ENTRIES 256
#define PPE_MRU_MTU_CTRL_TBL_INC 0x10
#define PPE_MRU_MTU_CTRL_W0_MRU GENMASK(13, 0)
#define PPE_MRU_MTU_CTRL_W0_MRU_CMD GENMASK(15, 14)
#define PPE_MRU_MTU_CTRL_W0_MTU GENMASK(29, 16)
#define PPE_MRU_MTU_CTRL_W0_MTU_CMD GENMASK(31, 30)
#define PPE_MRU_MTU_CTRL_W1_RX_CNT_EN BIT(0)
#define PPE_MRU_MTU_CTRL_W1_TX_CNT_EN BIT(1)
#define PPE_MRU_MTU_CTRL_W1_SRC_PROFILE GENMASK(3, 2)
#define PPE_MRU_MTU_CTRL_W1_INNER_PREC_LOW BIT(31)
#define PPE_MRU_MTU_CTRL_W2_INNER_PREC_HIGH GENMASK(1, 0)
#define PPE_MRU_MTU_CTRL_SET_MRU(tbl_cfg, value) \
FIELD_MODIFY(PPE_MRU_MTU_CTRL_W0_MRU, tbl_cfg, value)
#define PPE_MRU_MTU_CTRL_SET_MRU_CMD(tbl_cfg, value) \
FIELD_MODIFY(PPE_MRU_MTU_CTRL_W0_MRU_CMD, tbl_cfg, value)
#define PPE_MRU_MTU_CTRL_SET_MTU(tbl_cfg, value) \
FIELD_MODIFY(PPE_MRU_MTU_CTRL_W0_MTU, tbl_cfg, value)
#define PPE_MRU_MTU_CTRL_SET_MTU_CMD(tbl_cfg, value) \
FIELD_MODIFY(PPE_MRU_MTU_CTRL_W0_MTU_CMD, tbl_cfg, value)
#define PPE_MRU_MTU_CTRL_SET_RX_CNT_EN(tbl_cfg, value) \
FIELD_MODIFY(PPE_MRU_MTU_CTRL_W1_RX_CNT_EN, (tbl_cfg) + 0x1, value)
#define PPE_MRU_MTU_CTRL_SET_TX_CNT_EN(tbl_cfg, value) \
FIELD_MODIFY(PPE_MRU_MTU_CTRL_W1_TX_CNT_EN, (tbl_cfg) + 0x1, value)
/* PPE service code configuration for destination port and counter. */
#define PPE_IN_L2_SERVICE_TBL_ADDR 0x66000
#define PPE_IN_L2_SERVICE_TBL_ENTRIES 256
#define PPE_IN_L2_SERVICE_TBL_INC 0x10
#define PPE_IN_L2_SERVICE_TBL_DST_PORT_ID_VALID BIT(0)
#define PPE_IN_L2_SERVICE_TBL_DST_PORT_ID GENMASK(4, 1)
#define PPE_IN_L2_SERVICE_TBL_DST_DIRECTION BIT(5)
#define PPE_IN_L2_SERVICE_TBL_DST_BYPASS_BITMAP GENMASK(29, 6)
#define PPE_IN_L2_SERVICE_TBL_RX_CNT_EN BIT(30)
#define PPE_IN_L2_SERVICE_TBL_TX_CNT_EN BIT(31)
/* L2 Port configurations */
#define PPE_L2_VP_PORT_TBL_ADDR 0x98000
#define PPE_L2_VP_PORT_TBL_ENTRIES 256
#define PPE_L2_VP_PORT_TBL_INC 0x10
#define PPE_L2_VP_PORT_W0_INVALID_VSI_FWD_EN BIT(0)
#define PPE_L2_VP_PORT_W0_DST_INFO GENMASK(9, 2)
#define PPE_L2_PORT_SET_INVALID_VSI_FWD_EN(tbl_cfg, value) \
FIELD_MODIFY(PPE_L2_VP_PORT_W0_INVALID_VSI_FWD_EN, tbl_cfg, value)
#define PPE_L2_PORT_SET_DST_INFO(tbl_cfg, value) \
FIELD_MODIFY(PPE_L2_VP_PORT_W0_DST_INFO, tbl_cfg, value)
/* Port RX and RX drop counters. */
#define PPE_PORT_RX_CNT_TBL_ADDR 0x150000
#define PPE_PORT_RX_CNT_TBL_ENTRIES 256
#define PPE_PORT_RX_CNT_TBL_INC 0x20
/* Physical port RX and RX drop counters. */
#define PPE_PHY_PORT_RX_CNT_TBL_ADDR 0x156000
#define PPE_PHY_PORT_RX_CNT_TBL_ENTRIES 8
#define PPE_PHY_PORT_RX_CNT_TBL_INC 0x20
/* Counters for the packet to CPU port. */
#define PPE_DROP_CPU_CNT_TBL_ADDR 0x160000
#define PPE_DROP_CPU_CNT_TBL_ENTRIES 1280
#define PPE_DROP_CPU_CNT_TBL_INC 0x10
/* VLAN counters. */
#define PPE_VLAN_CNT_TBL_ADDR 0x178000
#define PPE_VLAN_CNT_TBL_ENTRIES 64
#define PPE_VLAN_CNT_TBL_INC 0x10
/* PPE L2 counters. */
#define PPE_PRE_L2_CNT_TBL_ADDR 0x17c000
#define PPE_PRE_L2_CNT_TBL_ENTRIES 64
#define PPE_PRE_L2_CNT_TBL_INC 0x20
/* Port TX drop counters. */
#define PPE_PORT_TX_DROP_CNT_TBL_ADDR 0x17d000
#define PPE_PORT_TX_DROP_CNT_TBL_ENTRIES 8
#define PPE_PORT_TX_DROP_CNT_TBL_INC 0x10
/* Virtual port TX counters. */
#define PPE_VPORT_TX_DROP_CNT_TBL_ADDR 0x17e000
#define PPE_VPORT_TX_DROP_CNT_TBL_ENTRIES 256
#define PPE_VPORT_TX_DROP_CNT_TBL_INC 0x10
/* Counters for the tunnel packet. */
#define PPE_TPR_PKT_CNT_TBL_ADDR 0x1d0080
#define PPE_TPR_PKT_CNT_TBL_ENTRIES 8
#define PPE_TPR_PKT_CNT_TBL_INC 4
/* Counters for the all packet received. */
#define PPE_IPR_PKT_CNT_TBL_ADDR 0x1e0080
#define PPE_IPR_PKT_CNT_TBL_ENTRIES 8
#define PPE_IPR_PKT_CNT_TBL_INC 4
/* PPE service code configuration for the tunnel packet. */
#define PPE_TL_SERVICE_TBL_ADDR 0x306000
#define PPE_TL_SERVICE_TBL_ENTRIES 256
#define PPE_TL_SERVICE_TBL_INC 4
#define PPE_TL_SERVICE_TBL_BYPASS_BITMAP GENMASK(31, 0)
/* Port scheduler global config. */
#define PPE_PSCH_SCH_DEPTH_CFG_ADDR 0x400000
#define PPE_PSCH_SCH_DEPTH_CFG_INC 4
#define PPE_PSCH_SCH_DEPTH_CFG_SCH_DEPTH GENMASK(7, 0)
/* PPE queue level scheduler configurations. */
#define PPE_L0_FLOW_MAP_TBL_ADDR 0x402000
#define PPE_L0_FLOW_MAP_TBL_ENTRIES 300
#define PPE_L0_FLOW_MAP_TBL_INC 0x10
#define PPE_L0_FLOW_MAP_TBL_FLOW_ID GENMASK(5, 0)
#define PPE_L0_FLOW_MAP_TBL_C_PRI GENMASK(8, 6)
#define PPE_L0_FLOW_MAP_TBL_E_PRI GENMASK(11, 9)
#define PPE_L0_FLOW_MAP_TBL_C_NODE_WT GENMASK(21, 12)
#define PPE_L0_FLOW_MAP_TBL_E_NODE_WT GENMASK(31, 22)
#define PPE_L0_C_FLOW_CFG_TBL_ADDR 0x404000
#define PPE_L0_C_FLOW_CFG_TBL_ENTRIES 512
#define PPE_L0_C_FLOW_CFG_TBL_INC 0x10
#define PPE_L0_C_FLOW_CFG_TBL_NODE_ID GENMASK(7, 0)
#define PPE_L0_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(8)
#define PPE_L0_E_FLOW_CFG_TBL_ADDR 0x406000
#define PPE_L0_E_FLOW_CFG_TBL_ENTRIES 512
#define PPE_L0_E_FLOW_CFG_TBL_INC 0x10
#define PPE_L0_E_FLOW_CFG_TBL_NODE_ID GENMASK(7, 0)
#define PPE_L0_E_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(8)
#define PPE_L0_FLOW_PORT_MAP_TBL_ADDR 0x408000
#define PPE_L0_FLOW_PORT_MAP_TBL_ENTRIES 300
#define PPE_L0_FLOW_PORT_MAP_TBL_INC 0x10
#define PPE_L0_FLOW_PORT_MAP_TBL_PORT_NUM GENMASK(3, 0)
#define PPE_L0_COMP_CFG_TBL_ADDR 0x428000
#define PPE_L0_COMP_CFG_TBL_ENTRIES 300
#define PPE_L0_COMP_CFG_TBL_INC 0x10
#define PPE_L0_COMP_CFG_TBL_SHAPER_METER_LEN GENMASK(1, 0)
#define PPE_L0_COMP_CFG_TBL_NODE_METER_LEN GENMASK(3, 2)
/* PPE queue to Ethernet DMA ring mapping table. */
#define PPE_RING_Q_MAP_TBL_ADDR 0x42a000
#define PPE_RING_Q_MAP_TBL_ENTRIES 24
#define PPE_RING_Q_MAP_TBL_INC 0x40
/* Table addresses for per-queue dequeue setting. */
#define PPE_DEQ_OPR_TBL_ADDR 0x430000
#define PPE_DEQ_OPR_TBL_ENTRIES 300
#define PPE_DEQ_OPR_TBL_INC 0x10
#define PPE_DEQ_OPR_TBL_DEQ_DISABLE BIT(0)
/* PPE flow level scheduler configurations. */
#define PPE_L1_FLOW_MAP_TBL_ADDR 0x440000
#define PPE_L1_FLOW_MAP_TBL_ENTRIES 64
#define PPE_L1_FLOW_MAP_TBL_INC 0x10
#define PPE_L1_FLOW_MAP_TBL_FLOW_ID GENMASK(3, 0)
#define PPE_L1_FLOW_MAP_TBL_C_PRI GENMASK(6, 4)
#define PPE_L1_FLOW_MAP_TBL_E_PRI GENMASK(9, 7)
#define PPE_L1_FLOW_MAP_TBL_C_NODE_WT GENMASK(19, 10)
#define PPE_L1_FLOW_MAP_TBL_E_NODE_WT GENMASK(29, 20)
#define PPE_L1_C_FLOW_CFG_TBL_ADDR 0x442000
#define PPE_L1_C_FLOW_CFG_TBL_ENTRIES 64
#define PPE_L1_C_FLOW_CFG_TBL_INC 0x10
#define PPE_L1_C_FLOW_CFG_TBL_NODE_ID GENMASK(5, 0)
#define PPE_L1_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(6)
#define PPE_L1_E_FLOW_CFG_TBL_ADDR 0x444000
#define PPE_L1_E_FLOW_CFG_TBL_ENTRIES 64
#define PPE_L1_E_FLOW_CFG_TBL_INC 0x10
#define PPE_L1_E_FLOW_CFG_TBL_NODE_ID GENMASK(5, 0)
#define PPE_L1_E_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(6)
#define PPE_L1_FLOW_PORT_MAP_TBL_ADDR 0x446000
#define PPE_L1_FLOW_PORT_MAP_TBL_ENTRIES 64
#define PPE_L1_FLOW_PORT_MAP_TBL_INC 0x10
#define PPE_L1_FLOW_PORT_MAP_TBL_PORT_NUM GENMASK(3, 0)
#define PPE_L1_COMP_CFG_TBL_ADDR 0x46a000
#define PPE_L1_COMP_CFG_TBL_ENTRIES 64
#define PPE_L1_COMP_CFG_TBL_INC 0x10
#define PPE_L1_COMP_CFG_TBL_SHAPER_METER_LEN GENMASK(1, 0)
#define PPE_L1_COMP_CFG_TBL_NODE_METER_LEN GENMASK(3, 2)
/* PPE port scheduler configurations for egress. */
#define PPE_PSCH_SCH_CFG_TBL_ADDR 0x47a000
#define PPE_PSCH_SCH_CFG_TBL_ENTRIES 128
#define PPE_PSCH_SCH_CFG_TBL_INC 0x10
#define PPE_PSCH_SCH_CFG_TBL_DES_PORT GENMASK(3, 0)
#define PPE_PSCH_SCH_CFG_TBL_ENS_PORT GENMASK(7, 4)
#define PPE_PSCH_SCH_CFG_TBL_ENS_PORT_BITMAP GENMASK(15, 8)
#define PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT_EN BIT(16)
#define PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT GENMASK(20, 17)
/* There are 15 BM ports and 4 BM groups supported by PPE.
* BM port (0-7) is for EDMA port 0, BM port (8-13) is for
* PPE physical port 1-6 and BM port 14 is for EIP port.
*/
#define PPE_BM_PORT_FC_MODE_ADDR 0x600100
#define PPE_BM_PORT_FC_MODE_ENTRIES 15
#define PPE_BM_PORT_FC_MODE_INC 0x4
#define PPE_BM_PORT_FC_MODE_EN BIT(0)
#define PPE_BM_PORT_GROUP_ID_ADDR 0x600180
#define PPE_BM_PORT_GROUP_ID_ENTRIES 15
#define PPE_BM_PORT_GROUP_ID_INC 0x4
#define PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID GENMASK(1, 0)
/* Counters for PPE buffers used for packets cached. */
#define PPE_BM_USED_CNT_TBL_ADDR 0x6001c0
#define PPE_BM_USED_CNT_TBL_ENTRIES 15
#define PPE_BM_USED_CNT_TBL_INC 0x4
#define PPE_BM_USED_CNT_VAL GENMASK(10, 0)
/* Counters for PPE buffers used for packets received after pause frame sent. */
#define PPE_BM_REACT_CNT_TBL_ADDR 0x600240
#define PPE_BM_REACT_CNT_TBL_ENTRIES 15
#define PPE_BM_REACT_CNT_TBL_INC 0x4
#define PPE_BM_REACT_CNT_VAL GENMASK(8, 0)
#define PPE_BM_SHARED_GROUP_CFG_ADDR 0x600290
#define PPE_BM_SHARED_GROUP_CFG_ENTRIES 4
#define PPE_BM_SHARED_GROUP_CFG_INC 0x4
#define PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT GENMASK(10, 0)
#define PPE_BM_PORT_FC_CFG_TBL_ADDR 0x601000
#define PPE_BM_PORT_FC_CFG_TBL_ENTRIES 15
#define PPE_BM_PORT_FC_CFG_TBL_INC 0x10
#define PPE_BM_PORT_FC_W0_REACT_LIMIT GENMASK(8, 0)
#define PPE_BM_PORT_FC_W0_RESUME_THRESHOLD GENMASK(17, 9)
#define PPE_BM_PORT_FC_W0_RESUME_OFFSET GENMASK(28, 18)
#define PPE_BM_PORT_FC_W0_CEILING_LOW GENMASK(31, 29)
#define PPE_BM_PORT_FC_W1_CEILING_HIGH GENMASK(7, 0)
#define PPE_BM_PORT_FC_W1_WEIGHT GENMASK(10, 8)
#define PPE_BM_PORT_FC_W1_DYNAMIC BIT(11)
#define PPE_BM_PORT_FC_W1_PRE_ALLOC GENMASK(22, 12)
#define PPE_BM_PORT_FC_SET_REACT_LIMIT(tbl_cfg, value) \
FIELD_MODIFY(PPE_BM_PORT_FC_W0_REACT_LIMIT, tbl_cfg, value)
#define PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(tbl_cfg, value) \
FIELD_MODIFY(PPE_BM_PORT_FC_W0_RESUME_THRESHOLD, tbl_cfg, value)
#define PPE_BM_PORT_FC_SET_RESUME_OFFSET(tbl_cfg, value) \
FIELD_MODIFY(PPE_BM_PORT_FC_W0_RESUME_OFFSET, tbl_cfg, value)
#define PPE_BM_PORT_FC_SET_CEILING_LOW(tbl_cfg, value) \
FIELD_MODIFY(PPE_BM_PORT_FC_W0_CEILING_LOW, tbl_cfg, value)
#define PPE_BM_PORT_FC_SET_CEILING_HIGH(tbl_cfg, value) \
FIELD_MODIFY(PPE_BM_PORT_FC_W1_CEILING_HIGH, (tbl_cfg) + 0x1, value)
#define PPE_BM_PORT_FC_SET_WEIGHT(tbl_cfg, value) \
FIELD_MODIFY(PPE_BM_PORT_FC_W1_WEIGHT, (tbl_cfg) + 0x1, value)
#define PPE_BM_PORT_FC_SET_DYNAMIC(tbl_cfg, value) \
FIELD_MODIFY(PPE_BM_PORT_FC_W1_DYNAMIC, (tbl_cfg) + 0x1, value)
#define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \
FIELD_MODIFY(PPE_BM_PORT_FC_W1_PRE_ALLOC, (tbl_cfg) + 0x1, value)
/* The queue base configurations based on destination port,
* service code or CPU code.
*/
#define PPE_UCAST_QUEUE_MAP_TBL_ADDR 0x810000
#define PPE_UCAST_QUEUE_MAP_TBL_ENTRIES 3072
#define PPE_UCAST_QUEUE_MAP_TBL_INC 0x10
#define PPE_UCAST_QUEUE_MAP_TBL_PROFILE_ID GENMASK(3, 0)
#define PPE_UCAST_QUEUE_MAP_TBL_QUEUE_ID GENMASK(11, 4)
/* The queue offset configurations based on RSS hash value. */
#define PPE_UCAST_HASH_MAP_TBL_ADDR 0x830000
#define PPE_UCAST_HASH_MAP_TBL_ENTRIES 4096
#define PPE_UCAST_HASH_MAP_TBL_INC 0x10
#define PPE_UCAST_HASH_MAP_TBL_HASH GENMASK(7, 0)
/* The queue offset configurations based on PPE internal priority. */
#define PPE_UCAST_PRIORITY_MAP_TBL_ADDR 0x842000
#define PPE_UCAST_PRIORITY_MAP_TBL_ENTRIES 256
#define PPE_UCAST_PRIORITY_MAP_TBL_INC 0x10
#define PPE_UCAST_PRIORITY_MAP_TBL_CLASS GENMASK(3, 0)
/* PPE unicast queue (0-255) configurations. */
#define PPE_AC_UNICAST_QUEUE_CFG_TBL_ADDR 0x848000
#define PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES 256
#define PPE_AC_UNICAST_QUEUE_CFG_TBL_INC 0x10
#define PPE_AC_UNICAST_QUEUE_CFG_W0_EN BIT(0)
#define PPE_AC_UNICAST_QUEUE_CFG_W0_WRED_EN BIT(1)
#define PPE_AC_UNICAST_QUEUE_CFG_W0_FC_EN BIT(2)
#define PPE_AC_UNICAST_QUEUE_CFG_W0_CLR_AWARE BIT(3)
#define PPE_AC_UNICAST_QUEUE_CFG_W0_GRP_ID GENMASK(5, 4)
#define PPE_AC_UNICAST_QUEUE_CFG_W0_PRE_LIMIT GENMASK(16, 6)
#define PPE_AC_UNICAST_QUEUE_CFG_W0_DYNAMIC BIT(17)
#define PPE_AC_UNICAST_QUEUE_CFG_W0_WEIGHT GENMASK(20, 18)
#define PPE_AC_UNICAST_QUEUE_CFG_W0_THRESHOLD GENMASK(31, 21)
#define PPE_AC_UNICAST_QUEUE_CFG_W3_GRN_RESUME GENMASK(23, 13)
#define PPE_AC_UNICAST_QUEUE_SET_EN(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_UNICAST_QUEUE_CFG_W0_EN, tbl_cfg, value)
#define PPE_AC_UNICAST_QUEUE_SET_GRP_ID(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_UNICAST_QUEUE_CFG_W0_GRP_ID, tbl_cfg, value)
#define PPE_AC_UNICAST_QUEUE_SET_PRE_LIMIT(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_UNICAST_QUEUE_CFG_W0_PRE_LIMIT, tbl_cfg, value)
#define PPE_AC_UNICAST_QUEUE_SET_DYNAMIC(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_UNICAST_QUEUE_CFG_W0_DYNAMIC, tbl_cfg, value)
#define PPE_AC_UNICAST_QUEUE_SET_WEIGHT(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_UNICAST_QUEUE_CFG_W0_WEIGHT, tbl_cfg, value)
#define PPE_AC_UNICAST_QUEUE_SET_THRESHOLD(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_UNICAST_QUEUE_CFG_W0_THRESHOLD, tbl_cfg, value)
#define PPE_AC_UNICAST_QUEUE_SET_GRN_RESUME(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_UNICAST_QUEUE_CFG_W3_GRN_RESUME, (tbl_cfg) + 0x3, value)
/* PPE multicast queue (256-299) configurations. */
#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_ADDR 0x84a000
#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_ENTRIES 44
#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_INC 0x10
#define PPE_AC_MULTICAST_QUEUE_CFG_W0_EN BIT(0)
#define PPE_AC_MULTICAST_QUEUE_CFG_W0_FC_EN BIT(1)
#define PPE_AC_MULTICAST_QUEUE_CFG_W0_CLR_AWARE BIT(2)
#define PPE_AC_MULTICAST_QUEUE_CFG_W0_GRP_ID GENMASK(4, 3)
#define PPE_AC_MULTICAST_QUEUE_CFG_W0_PRE_LIMIT GENMASK(15, 5)
#define PPE_AC_MULTICAST_QUEUE_CFG_W0_THRESHOLD GENMASK(26, 16)
#define PPE_AC_MULTICAST_QUEUE_CFG_W2_RESUME GENMASK(17, 7)
#define PPE_AC_MULTICAST_QUEUE_SET_EN(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_MULTICAST_QUEUE_CFG_W0_EN, tbl_cfg, value)
#define PPE_AC_MULTICAST_QUEUE_SET_GRN_GRP_ID(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_MULTICAST_QUEUE_CFG_W0_GRP_ID, tbl_cfg, value)
#define PPE_AC_MULTICAST_QUEUE_SET_GRN_PRE_LIMIT(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_MULTICAST_QUEUE_CFG_W0_PRE_LIMIT, tbl_cfg, value)
#define PPE_AC_MULTICAST_QUEUE_SET_GRN_THRESHOLD(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_MULTICAST_QUEUE_CFG_W0_THRESHOLD, tbl_cfg, value)
#define PPE_AC_MULTICAST_QUEUE_SET_GRN_RESUME(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_MULTICAST_QUEUE_CFG_W2_RESUME, (tbl_cfg) + 0x2, value)
/* PPE admission control group (0-3) configurations */
#define PPE_AC_GRP_CFG_TBL_ADDR 0x84c000
#define PPE_AC_GRP_CFG_TBL_ENTRIES 0x4
#define PPE_AC_GRP_CFG_TBL_INC 0x10
#define PPE_AC_GRP_W0_AC_EN BIT(0)
#define PPE_AC_GRP_W0_AC_FC_EN BIT(1)
#define PPE_AC_GRP_W0_CLR_AWARE BIT(2)
#define PPE_AC_GRP_W0_THRESHOLD_LOW GENMASK(31, 25)
#define PPE_AC_GRP_W1_THRESHOLD_HIGH GENMASK(3, 0)
#define PPE_AC_GRP_W1_BUF_LIMIT GENMASK(14, 4)
#define PPE_AC_GRP_W2_RESUME_GRN GENMASK(15, 5)
#define PPE_AC_GRP_W2_PRE_ALLOC GENMASK(26, 16)
#define PPE_AC_GRP_SET_BUF_LIMIT(tbl_cfg, value) \
FIELD_MODIFY(PPE_AC_GRP_W1_BUF_LIMIT, (tbl_cfg) + 0x1, value)
/* Counters for packets handled by unicast queues (0-255). */
#define PPE_AC_UNICAST_QUEUE_CNT_TBL_ADDR 0x84e000
#define PPE_AC_UNICAST_QUEUE_CNT_TBL_ENTRIES 256
#define PPE_AC_UNICAST_QUEUE_CNT_TBL_INC 0x10
#define PPE_AC_UNICAST_QUEUE_CNT_TBL_PEND_CNT GENMASK(12, 0)
/* Counters for packets handled by multicast queues (256-299). */
#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_ADDR 0x852000
#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_ENTRIES 44
#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_INC 0x10
#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_PEND_CNT GENMASK(12, 0)
/* Table addresses for per-queue enqueue setting. */
#define PPE_ENQ_OPR_TBL_ADDR 0x85c000
#define PPE_ENQ_OPR_TBL_ENTRIES 300
#define PPE_ENQ_OPR_TBL_INC 0x10
#define PPE_ENQ_OPR_TBL_ENQ_DISABLE BIT(0)
/* Unicast drop count includes the possible drops with WRED for the green,
* yellow and red categories.
*/
#define PPE_UNICAST_DROP_CNT_TBL_ADDR 0x9e0000
#define PPE_UNICAST_DROP_CNT_TBL_ENTRIES 1536
#define PPE_UNICAST_DROP_CNT_TBL_INC 0x10
#define PPE_UNICAST_DROP_TYPES 6
#define PPE_UNICAST_DROP_FORCE_OFFSET 3
/* There are 16 multicast queues dedicated to CPU port 0. Multicast drop
* count includes the force drop for green, yellow and red category packets.
*/
#define PPE_P0_MULTICAST_DROP_CNT_TBL_ADDR 0x9f0000
#define PPE_P0_MULTICAST_DROP_CNT_TBL_ENTRIES 48
#define PPE_P0_MULTICAST_DROP_CNT_TBL_INC 0x10
#define PPE_P0_MULTICAST_QUEUE_NUM 16
/* Each PPE physical port has four dedicated multicast queues, providing
* a total of 12 entries per port. The multicast drop count includes forced
* drops for green, yellow, and red category packets.
*/
#define PPE_MULTICAST_QUEUE_PORT_ADDR_INC 0x1000
#define PPE_MULTICAST_DROP_CNT_TBL_INC 0x10
#define PPE_MULTICAST_DROP_TYPES 3
#define PPE_MULTICAST_QUEUE_NUM 4
#define PPE_MULTICAST_DROP_CNT_TBL_ENTRIES 12
#define PPE_CPU_PORT_MULTICAST_FORCE_DROP_CNT_TBL_ADDR(mq_offset) \
(PPE_P0_MULTICAST_DROP_CNT_TBL_ADDR + \
(mq_offset) * PPE_P0_MULTICAST_DROP_CNT_TBL_INC * \
PPE_MULTICAST_DROP_TYPES)
#define PPE_P1_MULTICAST_DROP_CNT_TBL_ADDR \
(PPE_P0_MULTICAST_DROP_CNT_TBL_ADDR + PPE_MULTICAST_QUEUE_PORT_ADDR_INC)
#endif