AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/10/08 19:43 flow patch-triage
1m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "KMSANReasoning": "",
  "NeedsKMSAN": false,
  "Reasoning": "The patch adds support for the Qualcomm IPQ5424 SoC to the Qualcomm Packet Process Engine (PPE) network driver and updates DeviceTree bindings and documentation. This is a platform driver for dedicated SoC hardware (ARCH_QCOM) requiring specific physical ASIC peripherals (clocks, interconnects, reset controllers) that are not emulated in standard virtualized environments (QEMU/GCE on amd64). Because the driver cannot probe or execute on amd64, the changes are structurally unreachable and not worth fuzzing.",
  "WorthFuzzing": false
}

1/1 2026/10/08 19:43 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 9b2e3adc9112df7aec393b3ca1a337f95566811a\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Thu Oct 8 19:43:58 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml b/Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml\nindex 6d0b21a10732a..e5d218fc5d825 100644\n--- a/Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml\n+++ b/Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml\n@@ -74,9 +74,14 @@ description: |\n     +-------\u003e|             QCA8075 PHY             | | PHY4  | | PHY5  |\n      (clock) +-------------------------------------+ +-------+ +-------+\n \n+  The IPQ5424 PPE reuses the same switch core, but wires up only 3\n+  front panel ports (GMAC0-2) and the single EDMA FIFO interface; it\n+  has no EIP FIFO and no ports 4-6.\n+\n properties:\n   compatible:\n     enum:\n+      - qcom,ipq5424-ppe\n       - qcom,ipq9574-ppe\n \n   reg:\n@@ -105,24 +110,16 @@ properties:\n     description: PPE switch miscellaneous interrupt\n \n   interconnects:\n-    items:\n-      - description: Bus interconnect path leading to PPE switch core function\n-      - description: Bus interconnect path leading to PPE register access\n-      - description: Bus interconnect path leading to QoS generation\n-      - description: Bus interconnect path leading to timeout reference\n-      - description: Bus interconnect path leading to NSS NOC from memory NOC\n-      - description: Bus interconnect path leading to memory NOC from NSS NOC\n-      - description: Bus interconnect path leading to enhanced memory NOC from NSS NOC\n+    minItems: 5\n+    maxItems: 7\n+    description:\n+      The number of interconnect paths depends on compatible, 5 paths for\n+      qcom,ipq5424-ppe and 7 paths for qcom,ipq9574-ppe, enumerated in the\n+      allOf conditionals below.\n \n   interconnect-names:\n-    items:\n-      - const: ppe\n-      - const: ppe_cfg\n-      - const: qos_gen\n-      - const: timeout_ref\n-      - const: nssnoc_memnoc\n-      - const: memnoc_nssnoc\n-      - const: memnoc_nssnoc_1\n+    minItems: 5\n+    maxItems: 7\n \n   ethernet-dma:\n     type: object\n@@ -144,8 +141,14 @@ properties:\n           - const: apb\n \n       resets:\n-        maxItems: 1\n-        description: EDMA reset\n+        items:\n+          - description: EDMA system reset\n+          - description: EDMA APB reset\n+\n+      reset-names:\n+        items:\n+          - const: sys\n+          - const: apb\n \n       interrupts:\n         minItems: 65\n@@ -170,12 +173,13 @@ properties:\n       - clocks\n       - clock-names\n       - resets\n+      - reset-names\n       - interrupts\n       - interrupt-names\n \n   ethernet-ports:\n     patternProperties:\n-      \"^ethernet-port@[1-6]+$\":\n+      \"^ethernet-port@[1-6]$\":\n         type: object\n         unevaluatedProperties: false\n         $ref: ethernet-switch-port.yaml#\n@@ -229,6 +233,62 @@ required:\n \n allOf:\n   - $ref: ethernet-switch.yaml\n+  - if:\n+      properties:\n+        compatible:\n+          contains:\n+            const: qcom,ipq9574-ppe\n+    then:\n+      properties:\n+        interconnects:\n+          items:\n+            - description: Bus interconnect path leading to PPE switch core function\n+            - description: Bus interconnect path leading to PPE register access\n+            - description: Bus interconnect path leading to QoS generation\n+            - description: Bus interconnect path leading to timeout reference\n+            - description: Bus interconnect path leading to NSS NOC from memory NOC\n+            - description: Bus interconnect path leading to memory NOC from NSS NOC\n+            - description: Bus interconnect path leading to enhanced memory NOC from NSS NOC\n+\n+        interconnect-names:\n+          items:\n+            - const: ppe\n+            - const: ppe_cfg\n+            - const: qos_gen\n+            - const: timeout_ref\n+            - const: nssnoc_memnoc\n+            - const: memnoc_nssnoc\n+            - const: memnoc_nssnoc_1\n+  - if:\n+      properties:\n+        compatible:\n+          contains:\n+            const: qcom,ipq5424-ppe\n+    then:\n+      properties:\n+        interconnects:\n+          items:\n+            - description: Bus interconnect path leading to PPE switch core function\n+            - description: Bus interconnect path leading to PPE register access\n+            - description: Bus interconnect path leading to CE AXI\n+            - description: Bus interconnect path leading to CE APB\n+            - description: Bus interconnect path leading to NSS CSR access\n+\n+        interconnect-names:\n+          items:\n+            - const: ppe\n+            - const: ppe_cfg\n+            - const: nssnoc_ce_axi\n+            - const: nssnoc_ce_apb\n+            - const: nssnoc_nss_csr\n+\n+        ethernet-ports:\n+          patternProperties:\n+            \"^ethernet-port@[1-3]$\":\n+              properties:\n+                reg:\n+                  maximum: 3\n+            \"^ethernet-port@[4-6]$\": false\n \n unevaluatedProperties: false\n \n@@ -273,7 +333,10 @@ examples:\n                      \u003c\u0026nsscc NSS_CC_PPE_EDMA_CFG_CLK\u003e;\n             clock-names = \"sys\",\n                           \"apb\";\n-            resets = \u003c\u0026nsscc EDMA_HW_RESET\u003e;\n+            resets = \u003c\u0026nsscc PPE_EDMA_ARES\u003e,\n+                     \u003c\u0026nsscc PPE_EDMA_CFG_ARES\u003e;\n+            reset-names = \"sys\",\n+                          \"apb\";\n             interrupts = \u003cGIC_SPI 363 IRQ_TYPE_LEVEL_HIGH\u003e,\n                          \u003cGIC_SPI 364 IRQ_TYPE_LEVEL_HIGH\u003e,\n                          \u003cGIC_SPI 365 IRQ_TYPE_LEVEL_HIGH\u003e,\ndiff --git a/Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst b/Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst\nindex 4ab299a28969a..04c48cec66d53 100644\n--- a/Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst\n+++ b/Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst\n@@ -167,6 +167,14 @@ PPE Driver Supported SoCs\n The PPE driver supports the following IPQ SoC:\n \n - IPQ9574\n+    The PPE runs at a clock rate of 353 MHz. The switch core has 6 front panel\n+    ports (port1 to port6) and two FIFO interfaces: the EDMA FIFO (port0) for\n+    the host CPU communication and the EIP FIFO (port7) for the EIP engine.\n+- IPQ5424\n+    The PPE reuses the same switch core as IPQ9574 and runs at a clock rate of\n+    375 MHz. It supports 3 front panel ports (port1 to port3) with MAC0 to MAC2,\n+    and only the EDMA FIFO interface (port0) for the host CPU communication. The\n+    EIP FIFO and port4 to port6 are not available.\n \n \n Enabling the Driver\ndiff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.c b/drivers/net/ethernet/qualcomm/ppe/ppe.c\nindex 3c301e609d3e3..b144fd8189983 100644\n--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c\n+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c\n@@ -18,13 +18,36 @@\n #include \"ppe_config.h\"\n #include \"ppe_debugfs.h\"\n \n-#define PPE_PORT_MAX\t\t8\n-#define PPE_CLK_RATE\t\t353000000\n+#define IPQ9574_PPE_CLK_RATE\t353000000\n+#define IPQ5424_PPE_CLK_RATE\t375000000\n+\n+/* 6 physical ports, 1 EDMA FIFO and 1 EIP FIFO. */\n+#define IPQ9574_PPE_PORT_MAX\t\t8\n+/* 3 physical ports and 1 EDMA FIFO. */\n+#define IPQ5424_PPE_PORT_MAX\t\t4\n+\n+/**\n+ * struct ppe_of_data - PPE private data of IPQ SoC\n+ * @type: PPE type value\n+ * @ppe_rate: PPE clock rate\n+ * @num_ports: Number of PPE ports\n+ * @regmap_config: Regmap configuration\n+ * @icc_paths: Interconnect paths per PPE type\n+ * @num_icc_paths: Number of ICC paths\n+ */\n+struct ppe_of_data {\n+\tenum ppe_type type;\n+\tunsigned long ppe_rate;\n+\tint num_ports;\n+\tconst struct regmap_config *regmap_config;\n+\tconst struct icc_bulk_data *icc_paths;\n+\tint num_icc_paths;\n+};\n \n /* ICC clocks for enabling PPE device. The avg_bw and peak_bw with value 0\n  * will be updated by the clock rate of PPE.\n  */\n-static const struct icc_bulk_data ppe_icc_data[] = {\n+static const struct icc_bulk_data ipq9574_ppe_icc_data[] = {\n \t{\n \t\t.name = \"ppe\",\n \t\t.avg_bw = 0,\n@@ -62,6 +85,34 @@ static const struct icc_bulk_data ppe_icc_data[] = {\n \t},\n };\n \n+static const struct icc_bulk_data ipq5424_ppe_icc_data[] = {\n+\t{\n+\t\t.name = \"ppe\",\n+\t\t.avg_bw = 0,\n+\t\t.peak_bw = 0,\n+\t},\n+\t{\n+\t\t.name = \"ppe_cfg\",\n+\t\t.avg_bw = 0,\n+\t\t.peak_bw = 0,\n+\t},\n+\t{\n+\t\t.name = \"nssnoc_ce_axi\",\n+\t\t.avg_bw = 0,\n+\t\t.peak_bw = 0,\n+\t},\n+\t{\n+\t\t.name = \"nssnoc_ce_apb\",\n+\t\t.avg_bw = 0,\n+\t\t.peak_bw = 0,\n+\t},\n+\t{\n+\t\t.name = \"nssnoc_nss_csr\",\n+\t\t.avg_bw = 100000,\n+\t\t.peak_bw = 100000,\n+\t},\n+};\n+\n static const struct regmap_range ppe_readable_ranges[] = {\n \tregmap_reg_range(0x0, 0x1ff),\t\t/* Global */\n \tregmap_reg_range(0x400, 0x5ff),\t\t/* LPI CSR */\n@@ -108,7 +159,36 @@ static const struct regmap_config regmap_config_ipq9574 = {\n \t.max_register = 0xbef800,\n };\n \n-static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)\n+/* For IPQ5424, there are only three Ethernet ports, the register space of\n+ * GMAC/XGMAC 3-5 is unavailable.\n+ */\n+static const struct regmap_range ppe_reserved_ranges_ipq5424[] = {\n+\tregmap_reg_range(0x1600, 0x17ff),\t/* GMAC3 */\n+\tregmap_reg_range(0x1800, 0x19ff),\t/* GMAC4 */\n+\tregmap_reg_range(0x1a00, 0x1bff),\t/* GMAC5 */\n+\tregmap_reg_range(0x50c000, 0x50ffff),\t/* XGMAC3 */\n+\tregmap_reg_range(0x510000, 0x513fff),\t/* XGMAC4 */\n+\tregmap_reg_range(0x514000, 0x517fff),\t/* XGMAC5 */\n+};\n+\n+static const struct regmap_access_table ppe_reg_table_ipq5424 = {\n+\t.yes_ranges = ppe_readable_ranges,\n+\t.n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges),\n+\t.no_ranges = ppe_reserved_ranges_ipq5424,\n+\t.n_no_ranges = ARRAY_SIZE(ppe_reserved_ranges_ipq5424),\n+};\n+\n+static const struct regmap_config regmap_config_ipq5424 = {\n+\t.reg_bits = 32,\n+\t.reg_stride = 4,\n+\t.val_bits = 32,\n+\t.rd_table = \u0026ppe_reg_table_ipq5424,\n+\t.wr_table = \u0026ppe_reg_table_ipq5424,\n+\t.max_register = 0xbef800,\n+};\n+\n+static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev,\n+\t\t\t\t    const struct ppe_of_data *data)\n {\n \tunsigned long ppe_rate = ppe_dev-\u003eclk_rate;\n \tstruct device *dev = ppe_dev-\u003edev;\n@@ -118,15 +198,15 @@ static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)\n \tint ret, i;\n \n \tfor (i = 0; i \u003c ppe_dev-\u003enum_icc_paths; i++) {\n-\t\tppe_dev-\u003eicc_paths[i].name = ppe_icc_data[i].name;\n-\t\tppe_dev-\u003eicc_paths[i].avg_bw = ppe_icc_data[i].avg_bw ? :\n+\t\tppe_dev-\u003eicc_paths[i].name = data-\u003eicc_paths[i].name;\n+\t\tppe_dev-\u003eicc_paths[i].avg_bw = data-\u003eicc_paths[i].avg_bw ? :\n \t\t\t\t\t       Bps_to_icc(ppe_rate);\n \n \t\t/* PPE does not have an explicit peak bandwidth requirement,\n \t\t * so set the peak bandwidth to be equal to the average\n \t\t * bandwidth.\n \t\t */\n-\t\tppe_dev-\u003eicc_paths[i].peak_bw = ppe_icc_data[i].peak_bw ? :\n+\t\tppe_dev-\u003eicc_paths[i].peak_bw = data-\u003eicc_paths[i].peak_bw ? :\n \t\t\t\t\t\tBps_to_icc(ppe_rate);\n \t}\n \n@@ -173,12 +253,17 @@ static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)\n static int qcom_ppe_probe(struct platform_device *pdev)\n {\n \tstruct device *dev = \u0026pdev-\u003edev;\n+\tconst struct ppe_of_data *data;\n \tstruct ppe_device *ppe_dev;\n \tvoid __iomem *base;\n-\tint ret, num_icc;\n+\tint ret;\n+\n+\tdata = of_device_get_match_data(dev);\n+\tif (!data)\n+\t\treturn dev_err_probe(dev, -EINVAL, \"PPE no match data provided\\n\");\n \n-\tnum_icc = ARRAY_SIZE(ppe_icc_data);\n-\tppe_dev = devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc),\n+\tppe_dev = devm_kzalloc(dev,\n+\t\t\t       struct_size(ppe_dev, icc_paths, data-\u003enum_icc_paths),\n \t\t\t       GFP_KERNEL);\n \tif (!ppe_dev)\n \t\treturn -ENOMEM;\n@@ -187,16 +272,17 @@ static int qcom_ppe_probe(struct platform_device *pdev)\n \tif (IS_ERR(base))\n \t\treturn dev_err_probe(dev, PTR_ERR(base), \"PPE ioremap failed\\n\");\n \n-\tppe_dev-\u003eregmap = devm_regmap_init_mmio(dev, base, \u0026regmap_config_ipq9574);\n+\tppe_dev-\u003eregmap = devm_regmap_init_mmio(dev, base, data-\u003eregmap_config);\n \tif (IS_ERR(ppe_dev-\u003eregmap))\n \t\treturn dev_err_probe(dev, PTR_ERR(ppe_dev-\u003eregmap),\n \t\t\t\t     \"PPE initialize regmap failed\\n\");\n \tppe_dev-\u003edev = dev;\n-\tppe_dev-\u003eclk_rate = PPE_CLK_RATE;\n-\tppe_dev-\u003enum_ports = PPE_PORT_MAX;\n-\tppe_dev-\u003enum_icc_paths = num_icc;\n+\tppe_dev-\u003etype = data-\u003etype;\n+\tppe_dev-\u003eclk_rate = data-\u003eppe_rate;\n+\tppe_dev-\u003enum_ports = data-\u003enum_ports;\n+\tppe_dev-\u003enum_icc_paths = data-\u003enum_icc_paths;\n \n-\tret = ppe_clock_init_and_reset(ppe_dev);\n+\tret = ppe_clock_init_and_reset(ppe_dev, data);\n \tif (ret)\n \t\treturn dev_err_probe(dev, ret, \"PPE clock config failed\\n\");\n \n@@ -218,8 +304,27 @@ static void qcom_ppe_remove(struct platform_device *pdev)\n \tppe_debugfs_teardown(ppe_dev);\n }\n \n+static const struct ppe_of_data ipq9574_data = {\n+\t.type = IPQ9574_PPE,\n+\t.ppe_rate = IPQ9574_PPE_CLK_RATE,\n+\t.num_ports = IPQ9574_PPE_PORT_MAX,\n+\t.regmap_config = \u0026regmap_config_ipq9574,\n+\t.icc_paths = ipq9574_ppe_icc_data,\n+\t.num_icc_paths = ARRAY_SIZE(ipq9574_ppe_icc_data),\n+};\n+\n+static const struct ppe_of_data ipq5424_data = {\n+\t.type = IPQ5424_PPE,\n+\t.ppe_rate = IPQ5424_PPE_CLK_RATE,\n+\t.num_ports = IPQ5424_PPE_PORT_MAX,\n+\t.regmap_config = \u0026regmap_config_ipq5424,\n+\t.icc_paths = ipq5424_ppe_icc_data,\n+\t.num_icc_paths = ARRAY_SIZE(ipq5424_ppe_icc_data),\n+};\n+\n static const struct of_device_id qcom_ppe_of_match[] = {\n-\t{ .compatible = \"qcom,ipq9574-ppe\" },\n+\t{ .compatible = \"qcom,ipq9574-ppe\", .data = \u0026ipq9574_data },\n+\t{ .compatible = \"qcom,ipq5424-ppe\", .data = \u0026ipq5424_data },\n \t{}\n };\n MODULE_DEVICE_TABLE(of, qcom_ppe_of_match);\ndiff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.h b/drivers/net/ethernet/qualcomm/ppe/ppe.h\nindex 27458f0bc2064..33b876d2e0794 100644\n--- a/drivers/net/ethernet/qualcomm/ppe/ppe.h\n+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h\n@@ -13,10 +13,24 @@ struct device;\n struct regmap;\n struct dentry;\n \n+/**\n+ * enum ppe_type - PPE device type.\n+ * @IPQ9574_PPE: PPE device of IPQ9574.\n+ * @IPQ5424_PPE: PPE device of IPQ5424.\n+ *\n+ * PPE type is used to identify the PPE device of the different\n+ * IPQ platform.\n+ */\n+enum ppe_type {\n+\tIPQ9574_PPE,\n+\tIPQ5424_PPE,\n+};\n+\n /**\n  * struct ppe_device - PPE device private data.\n  * @dev: PPE device structure.\n  * @regmap: PPE register map.\n+ * @type: Different PPE type on various IPQ SoC.\n  * @clk_rate: PPE clock rate.\n  * @num_ports: Number of PPE ports.\n  * @debugfs_root: Debugfs root entry.\n@@ -30,6 +44,7 @@ struct dentry;\n struct ppe_device {\n \tstruct device *dev;\n \tstruct regmap *regmap;\n+\tenum ppe_type type;\n \tunsigned long clk_rate;\n \tunsigned int num_ports;\n \tstruct dentry *debugfs_root;\ndiff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c\nindex 125b73be92b13..94885240166b8 100644\n--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c\n+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c\n@@ -230,6 +230,56 @@ static const struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = {\n \t},\n };\n \n+/* IPQ5424 has fewer PPE physical ports (3) than IPQ9574 (6), so fewer\n+ * buffers need to be reserved for per-port purposes. Out of the same\n+ * 2048 total, the rest assigned to the general 'group0' pool is\n+ * correspondingly larger here, 1650 versus IPQ9574's 1550.\n+ */\n+static const int ipq5424_ppe_bm_group_config = 1650;\n+\n+/* The buffer configurations per PPE port on IPQ5424. There are 19 BM\n+ * ports supported by PPE. BM port (0-15) is for EDMA port 0, and BM\n+ * port (16-18) is for the 3 PPE physical ports.\n+ */\n+static const struct ppe_bm_port_config ipq5424_ppe_bm_port_config[] = {\n+\t{\n+\t\t/* Buffer configuration for the BM port ID 0 of EDMA. */\n+\t\t.port_id_start\t= 0,\n+\t\t.port_id_end\t= 0,\n+\t\t.pre_alloc\t= 0,\n+\t\t.in_fly_buf\t= 100,\n+\t\t.ceil\t\t= 1146,\n+\t\t.weight\t\t= 7,\n+\t\t.resume_offset\t= 8,\n+\t\t.resume_ceil\t= 0,\n+\t\t.dynamic\t= true,\n+\t},\n+\t{\n+\t\t/* Buffer configuration for the BM port ID 1-15 of EDMA. */\n+\t\t.port_id_start\t= 1,\n+\t\t.port_id_end\t= 15,\n+\t\t.pre_alloc\t= 0,\n+\t\t.in_fly_buf\t= 100,\n+\t\t.ceil\t\t= 250,\n+\t\t.weight\t\t= 4,\n+\t\t.resume_offset\t= 36,\n+\t\t.resume_ceil\t= 0,\n+\t\t.dynamic\t= true,\n+\t},\n+\t{\n+\t\t/* Buffer configuration for the BM port ID 16-18 of PPE ports. */\n+\t\t.port_id_start\t= 16,\n+\t\t.port_id_end\t= 18,\n+\t\t.pre_alloc\t= 0,\n+\t\t.in_fly_buf\t= 128,\n+\t\t.ceil\t\t= 250,\n+\t\t.weight\t\t= 4,\n+\t\t.resume_offset\t= 36,\n+\t\t.resume_ceil\t= 0,\n+\t\t.dynamic\t= true,\n+\t},\n+};\n+\n /* QM fetches the packet from PPE buffer management for transmitting the\n  * packet out. The QM group configuration limits the total number of buffers\n  * enqueued by all PPE hardware queues.\n@@ -264,6 +314,37 @@ static const struct ppe_qm_queue_config ipq9574_ppe_qm_queue_config[] = {\n \t},\n };\n \n+/* Multicast queues are dedicated per PPE port. IPQ5424 has only 3 physical\n+ * PPE ports, versus IPQ9574's 6 PPE ports, so multicast queues 284 to 299\n+ * are not available on IPQ5424, and the buffer pool assigned to the general\n+ * 'group0' is larger here, 2010 versus IPQ9574's 2000.\n+ */\n+static const int ipq5424_ppe_qm_group_config = 2010;\n+\n+/* Default QM settings for unicast and multicast queues for IPQ5424. */\n+static const struct ppe_qm_queue_config ipq5424_ppe_qm_queue_config[] = {\n+\t{\n+\t\t/* QM settings for unicast queues 0 to 255. */\n+\t\t.queue_start\t= 0,\n+\t\t.queue_end\t= 255,\n+\t\t.prealloc_buf\t= 0,\n+\t\t.ceil\t\t= 1200,\n+\t\t.weight\t\t= 7,\n+\t\t.resume_offset\t= 36,\n+\t\t.dynamic\t= true,\n+\t},\n+\t{\n+\t\t/* QM settings for multicast queues 256 to 283. */\n+\t\t.queue_start\t= 256,\n+\t\t.queue_end\t= 283,\n+\t\t.prealloc_buf\t= 0,\n+\t\t.ceil\t\t= 250,\n+\t\t.weight\t\t= 0,\n+\t\t.resume_offset\t= 36,\n+\t\t.dynamic\t= false,\n+\t},\n+};\n+\n /* PPE scheduler configuration for BM includes multiple entries. Each entry\n  * indicates the primary port to be assigned the buffers for the ingress or\n  * to release the buffers for the egress. Backup port ID will be used when\n@@ -439,6 +520,205 @@ static const struct ppe_scheduler_qm_config ipq9574_ppe_sch_qm_config[] = {\n \t{0x98, 6, 5, true, 2},\n };\n \n+static const struct ppe_scheduler_bm_config ipq5424_ppe_sch_bm_config[] = {\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, true, 1},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, false, 0},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, true, 2},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, false, 0},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, true, 1},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, false, 0},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, false, 0},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, true, 1},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, true, 2},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, false, 0},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, true, 3},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, true, 2},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, false, 0},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, true, 3},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, true, 1},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, false, 0},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, true, 2},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, false, 0},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, true, 1},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, true, 2},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, false, 0},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, true, 1},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, true, 3},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, false, 0},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, true, 1},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, true, 2},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, false, 0},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, true, 3},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, true, 1},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, false, 0},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, true, 3},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, false, 0},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, true, 1},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, true, 2},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, false, 0},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, true, 1},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, true, 2},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, false, 0},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, true, 3},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 3, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, true, 2},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  3, false, 0},\n+\t{true, PPE_SCH_INGRESS, 2, false, 0},\n+\t{true, PPE_SCH_EGRESS,  0, false, 0},\n+\t{true, PPE_SCH_INGRESS, 1, false, 0},\n+\t{true, PPE_SCH_EGRESS,  2, true, 3},\n+\t{true, PPE_SCH_INGRESS, 0, false, 0},\n+\t{true, PPE_SCH_EGRESS,  1, false, 0},\n+};\n+\n+/* ensch_port_bmp is left as 0 for every entry here, unlike\n+ * ipq9574_ppe_sch_qm_config[] above. This is expected for IPQ5424,\n+ * not an omission.\n+ */\n+static const struct ppe_scheduler_qm_config ipq5424_ppe_sch_qm_config[] = {\n+\t{0x0, 3, 2, false, 0},\n+\t{0x0, 1, 3, false, 0},\n+\t{0x0, 0, 1, false, 0},\n+\t{0x0, 2, 0, false, 0},\n+\t{0x0, 1, 2, false, 0},\n+\t{0x0, 3, 1, true, 0},\n+\t{0x0, 3, 2, false, 0},\n+\t{0x0, 1, 0, false, 0},\n+\t{0x0, 2, 1, false, 0},\n+\t{0x0, 2, 0, false, 0},\n+\t{0x0, 1, 2, false, 0},\n+\t{0x0, 3, 1, true, 0},\n+\t{0x0, 3, 2, false, 0},\n+\t{0x0, 1, 3, false, 0},\n+\t{0x0, 0, 1, false, 0},\n+\t{0x0, 2, 0, false, 0},\n+\t{0x0, 1, 2, false, 0},\n+\t{0x0, 3, 1, true, 0},\n+\t{0x0, 3, 2, false, 0},\n+\t{0x0, 1, 0, false, 0},\n+\t{0x0, 2, 1, false, 0},\n+\t{0x0, 2, 0, false, 0},\n+\t{0x0, 1, 2, false, 0},\n+\t{0x0, 0, 1, false, 0},\n+\t{0x0, 2, 0, false, 0},\n+\t{0x0, 3, 1, false, 0},\n+\t{0x0, 2, 0, false, 0},\n+\t{0x0, 1, 2, false, 0},\n+\t{0x0, 1, 0, false, 0},\n+\t{0x0, 2, 1, false, 0},\n+\t{0x0, 3, 2, true, 0},\n+\t{0x0, 3, 1, false, 0},\n+\t{0x0, 2, 0, false, 0},\n+\t{0x0, 1, 2, false, 0},\n+\t{0x0, 1, 3, false, 0},\n+\t{0x0, 0, 1, false, 0},\n+\t{0x0, 3, 2, true, 0},\n+\t{0x0, 3, 1, false, 0},\n+\t{0x0, 2, 0, false, 0},\n+\t{0x0, 1, 2, false, 0},\n+\t{0x0, 1, 0, false, 0},\n+\t{0x0, 2, 1, false, 0},\n+\t{0x0, 0, 2, false, 0},\n+\t{0x0, 3, 1, false, 0},\n+\t{0x0, 2, 0, false, 0},\n+\t{0x0, 1, 2, false, 0},\n+\t{0x0, 1, 0, false, 0},\n+\t{0x0, 2, 1, false, 0},\n+\t{0x0, 0, 2, false, 0},\n+\t{0x0, 3, 0, false, 0},\n+\t{0x0, 3, 1, false, 0},\n+\t{0x0, 2, 3, false, 0},\n+\t{0x0, 0, 2, false, 0},\n+\t{0x0, 1, 0, false, 0},\n+\t{0x0, 2, 1, false, 0},\n+\t{0x0, 3, 2, true, 0},\n+\t{0x0, 3, 1, false, 0},\n+\t{0x0, 2, 3, false, 0},\n+\t{0x0, 0, 2, false, 0},\n+\t{0x0, 1, 0, false, 0},\n+\t{0x0, 2, 1, false, 0},\n+\t{0x0, 0, 2, false, 0},\n+\t{0x0, 3, 0, false, 0},\n+};\n+\n static const struct ppe_scheduler_port_config ppe_port_sch_config[] = {\n \t{\n \t\t.port\t\t= 0,\n@@ -733,7 +1013,7 @@ static const struct ppe_scheduler_port_config ppe_port_sch_config[] = {\n /* The scheduler resource is applied to each PPE port, The resource\n  * includes the unicast \u0026 multicast queues, flow nodes and DRR nodes.\n  */\n-static const struct ppe_port_schedule_resource ppe_scheduler_res[] = {\n+static const struct ppe_port_schedule_resource ipq9574_ppe_scheduler_res[] = {\n \t{\t.ucastq_start\t= 0,\n \t\t.ucastq_end\t= 63,\n \t\t.mcastq_start\t= 256,\n@@ -835,6 +1115,64 @@ static const struct ppe_port_schedule_resource ppe_scheduler_res[] = {\n \t},\n };\n \n+static const struct ppe_port_schedule_resource ipq5424_ppe_scheduler_res[] = {\n+\t{\t.ucastq_start\t= 0,\n+\t\t.ucastq_end\t= 63,\n+\t\t.mcastq_start\t= 256,\n+\t\t.mcastq_end\t= 271,\n+\t\t.flow_id_start\t= 0,\n+\t\t.flow_id_end\t= 0,\n+\t\t.l0node_start\t= 0,\n+\t\t.l0node_end\t= 7,\n+\t\t.l1node_start\t= 0,\n+\t\t.l1node_end\t= 0,\n+\t},\n+\t{\t.ucastq_start\t= 144,\n+\t\t.ucastq_end\t= 159,\n+\t\t.mcastq_start\t= 272,\n+\t\t.mcastq_end\t= 275,\n+\t\t.flow_id_start\t= 36,\n+\t\t.flow_id_end\t= 39,\n+\t\t.l0node_start\t= 48,\n+\t\t.l0node_end\t= 63,\n+\t\t.l1node_start\t= 8,\n+\t\t.l1node_end\t= 11,\n+\t},\n+\t{\t.ucastq_start\t= 160,\n+\t\t.ucastq_end\t= 175,\n+\t\t.mcastq_start\t= 276,\n+\t\t.mcastq_end\t= 279,\n+\t\t.flow_id_start\t= 40,\n+\t\t.flow_id_end\t= 43,\n+\t\t.l0node_start\t= 64,\n+\t\t.l0node_end\t= 79,\n+\t\t.l1node_start\t= 12,\n+\t\t.l1node_end\t= 15,\n+\t},\n+\t{\t.ucastq_start\t= 176,\n+\t\t.ucastq_end\t= 191,\n+\t\t.mcastq_start\t= 280,\n+\t\t.mcastq_end\t= 283,\n+\t\t.flow_id_start\t= 44,\n+\t\t.flow_id_end\t= 47,\n+\t\t.l0node_start\t= 80,\n+\t\t.l0node_end\t= 95,\n+\t\t.l1node_start\t= 16,\n+\t\t.l1node_end\t= 19,\n+\t},\n+\t{\t.ucastq_start\t= 64,\n+\t\t.ucastq_end\t= 143,\n+\t\t.mcastq_start\t= 0,\n+\t\t.mcastq_end\t= 0,\n+\t\t.flow_id_start\t= 1,\n+\t\t.flow_id_end\t= 35,\n+\t\t.l0node_start\t= 8,\n+\t\t.l0node_end\t= 47,\n+\t\t.l1node_start\t= 1,\n+\t\t.l1node_end\t= 7,\n+\t},\n+};\n+\n /* Set the PPE queue level scheduler configuration. */\n static int ppe_scheduler_l0_queue_map_set(struct ppe_device *ppe_dev,\n \t\t\t\t\t  int node_id, int port,\n@@ -1072,15 +1410,31 @@ int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,\n \t\t\t  enum ppe_resource_type type,\n \t\t\t  int *res_start, int *res_end)\n {\n+\tconst struct ppe_port_schedule_resource *scheduler_res;\n \tstruct ppe_port_schedule_resource res;\n+\tunsigned int scheduler_res_len;\n \n-\t/* The reserved resource with the maximum port ID of PPE is\n-\t * also allowed to be acquired.\n+\tswitch (ppe_dev-\u003etype) {\n+\tcase IPQ9574_PPE:\n+\t\tscheduler_res = ipq9574_ppe_scheduler_res;\n+\t\tscheduler_res_len = ARRAY_SIZE(ipq9574_ppe_scheduler_res);\n+\t\tbreak;\n+\tcase IPQ5424_PPE:\n+\t\tscheduler_res = ipq5424_ppe_scheduler_res;\n+\t\tscheduler_res_len = ARRAY_SIZE(ipq5424_ppe_scheduler_res);\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_err(ppe_dev-\u003edev, \"Invalid PPE type %d\\n\", ppe_dev-\u003etype);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* The reserved resource, stored at the last entry of the\n+\t * scheduler resource table, is also allowed to be acquired.\n \t */\n-\tif (port \u003e ppe_dev-\u003enum_ports)\n+\tif (port \u003e= scheduler_res_len)\n \t\treturn -EINVAL;\n \n-\tres = ppe_scheduler_res[port];\n+\tres = scheduler_res[port];\n \tswitch (type) {\n \tcase PPE_RES_UCAST:\n \t\t*res_start = res.ucastq_start;\n@@ -1122,7 +1476,7 @@ int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,\n  */\n int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, struct ppe_sc_cfg cfg)\n {\n-\tu32 val, reg, servcode_val[2] = {};\n+\tu32 val, reg, servcode_val[2] = {}, in_l2_val[2] = {};\n \tunsigned long bitmap_value;\n \tint ret;\n \n@@ -1136,9 +1490,16 @@ int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, struct ppe_sc_cfg cfg)\n \t\t\t  test_bit(PPE_SC_BYPASS_COUNTER_RX, cfg.bitmaps.counter));\n \tval |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_TX_CNT_EN,\n \t\t\t  test_bit(PPE_SC_BYPASS_COUNTER_TX, cfg.bitmaps.counter));\n-\treg = PPE_IN_L2_SERVICE_TBL_ADDR + PPE_IN_L2_SERVICE_TBL_INC * sc;\n+\treg = PPE_IN_L2_SERVICE_TBL_ADDR + PPE_IN_L2_SERVICE_TBL_INC(ppe_dev) * sc;\n \n-\tret = regmap_write(ppe_dev-\u003eregmap, reg, val);\n+\tin_l2_val[0] = val;\n+\n+\tbitmap_value = bitmap_read(cfg.bitmaps.egress, PPE_SC_BYPASS_EGRESS_SMAC_MC_DROP,\n+\t\t\t\t   PPE_SC_BYPASS_EGRESS_SIZE - PPE_SC_BYPASS_EGRESS_SMAC_MC_DROP);\n+\tin_l2_val[1] = FIELD_PREP(PPE_IN_L2_SERVICE_TBL_W1_BYPASS_BITMAP_EXT, bitmap_value);\n+\n+\tret = regmap_bulk_write(ppe_dev-\u003eregmap, reg, in_l2_val,\n+\t\t\t\tPPE_IN_L2_SERVICE_TBL_WORDS(ppe_dev));\n \tif (ret)\n \t\treturn ret;\n \n@@ -1413,7 +1774,7 @@ static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,\n \n \t/* Assign the default group ID 0 to the BM port. */\n \tval = FIELD_PREP(PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, 0);\n-\treg = PPE_BM_PORT_GROUP_ID_ADDR + PPE_BM_PORT_GROUP_ID_INC * bm_port_id;\n+\treg = PPE_BM_PORT_GROUP_ID_ADDR(ppe_dev) + PPE_BM_PORT_GROUP_ID_INC * bm_port_id;\n \tret = regmap_update_bits(ppe_dev-\u003eregmap, reg,\n \t\t\t\t PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID,\n \t\t\t\t val);\n@@ -1431,25 +1792,38 @@ static int ppe_config_bm(struct ppe_device *ppe_dev)\n {\n \tconst struct ppe_bm_port_config *port_cfg;\n \tunsigned int i, bm_port_id, port_cfg_cnt;\n-\tu32 reg, val;\n+\tu32 reg, val, group_cfg;\n \tint ret;\n \n+\tswitch (ppe_dev-\u003etype) {\n+\tcase IPQ9574_PPE:\n+\t\tport_cfg = ipq9574_ppe_bm_port_config;\n+\t\tport_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config);\n+\t\tgroup_cfg = ipq9574_ppe_bm_group_config;\n+\t\tbreak;\n+\tcase IPQ5424_PPE:\n+\t\tport_cfg = ipq5424_ppe_bm_port_config;\n+\t\tport_cfg_cnt = ARRAY_SIZE(ipq5424_ppe_bm_port_config);\n+\t\tgroup_cfg = ipq5424_ppe_bm_group_config;\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_err(ppe_dev-\u003edev, \"Invalid PPE type %d\\n\", ppe_dev-\u003etype);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treg = PPE_BM_SHARED_GROUP_CFG_ADDR(ppe_dev);\n+\n \t/* Configure the allocated buffer number only for group 0.\n \t * The buffer number of group 1-3 is already cleared to 0\n \t * after PPE reset during the probe of PPE driver.\n \t */\n-\treg = PPE_BM_SHARED_GROUP_CFG_ADDR;\n-\tval = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,\n-\t\t\t ipq9574_ppe_bm_group_config);\n+\tval = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT, group_cfg);\n \tret = regmap_update_bits(ppe_dev-\u003eregmap, reg,\n \t\t\t\t PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,\n \t\t\t\t val);\n \tif (ret)\n \t\tgoto bm_config_fail;\n \n-\t/* Configure buffer thresholds for the BM ports. */\n-\tport_cfg = ipq9574_ppe_bm_port_config;\n-\tport_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config);\n \tfor (i = 0; i \u003c port_cfg_cnt; i++) {\n \t\tfor (bm_port_id = port_cfg[i].port_id_start;\n \t\t     bm_port_id \u003c= port_cfg[i].port_id_end; bm_port_id++) {\n@@ -1472,12 +1846,28 @@ static int ppe_config_bm(struct ppe_device *ppe_dev)\n  */\n static int ppe_config_qm(struct ppe_device *ppe_dev)\n {\n+\tint ret, i, group_buffer_cfg, queue_id, queue_cfg_count;\n \tconst struct ppe_qm_queue_config *queue_cfg;\n-\tint ret, i, queue_id, queue_cfg_count;\n \tu32 reg, multicast_queue_cfg[5];\n \tu32 unicast_queue_cfg[4];\n \tu32 group_cfg[3];\n \n+\tswitch (ppe_dev-\u003etype) {\n+\tcase IPQ9574_PPE:\n+\t\tgroup_buffer_cfg = ipq9574_ppe_qm_group_config;\n+\t\tqueue_cfg = ipq9574_ppe_qm_queue_config;\n+\t\tqueue_cfg_count = ARRAY_SIZE(ipq9574_ppe_qm_queue_config);\n+\t\tbreak;\n+\tcase IPQ5424_PPE:\n+\t\tgroup_buffer_cfg = ipq5424_ppe_qm_group_config;\n+\t\tqueue_cfg = ipq5424_ppe_qm_queue_config;\n+\t\tqueue_cfg_count = ARRAY_SIZE(ipq5424_ppe_qm_queue_config);\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_err(ppe_dev-\u003edev, \"Invalid PPE type %d\\n\", ppe_dev-\u003etype);\n+\t\treturn -EINVAL;\n+\t}\n+\n \t/* Assign the buffer number to the group 0 by default. */\n \treg = PPE_AC_GRP_CFG_TBL_ADDR;\n \tret = regmap_bulk_read(ppe_dev-\u003eregmap, reg,\n@@ -1485,15 +1875,13 @@ static int ppe_config_qm(struct ppe_device *ppe_dev)\n \tif (ret)\n \t\tgoto qm_config_fail;\n \n-\tPPE_AC_GRP_SET_BUF_LIMIT(group_cfg, ipq9574_ppe_qm_group_config);\n+\tPPE_AC_GRP_SET_BUF_LIMIT(group_cfg, group_buffer_cfg);\n \n \tret = regmap_bulk_write(ppe_dev-\u003eregmap, reg,\n \t\t\t\tgroup_cfg, ARRAY_SIZE(group_cfg));\n \tif (ret)\n \t\tgoto qm_config_fail;\n \n-\tqueue_cfg = ipq9574_ppe_qm_queue_config;\n-\tqueue_cfg_count = ARRAY_SIZE(ipq9574_ppe_qm_queue_config);\n \tfor (i = 0; i \u003c queue_cfg_count; i++) {\n \t\tqueue_id = queue_cfg[i].queue_start;\n \n@@ -1530,8 +1918,13 @@ static int ppe_config_qm(struct ppe_device *ppe_dev)\n \t\t\t\tif (ret)\n \t\t\t\t\tgoto qm_config_fail;\n \t\t\t} else {\n+\t\t\t\t/* The multicast queue table is indexed from 0 for\n+\t\t\t\t * the first multicast queue, which follows the\n+\t\t\t\t * unicast queues.\n+\t\t\t\t */\n \t\t\t\treg = PPE_AC_MULTICAST_QUEUE_CFG_TBL_ADDR +\n-\t\t\t\t      PPE_AC_MULTICAST_QUEUE_CFG_TBL_INC * queue_id;\n+\t\t\t\t      PPE_AC_MULTICAST_QUEUE_CFG_TBL_INC *\n+\t\t\t\t      (queue_id - PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES);\n \n \t\t\t\tret = regmap_bulk_read(ppe_dev-\u003eregmap, reg,\n \t\t\t\t\t\t       multicast_queue_cfg,\n@@ -1630,14 +2023,29 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev)\n \tconst struct ppe_scheduler_port_config *port_cfg;\n \tconst struct ppe_scheduler_qm_config *qm_cfg;\n \tconst struct ppe_scheduler_bm_config *bm_cfg;\n-\tint ret, i, count;\n+\tint ret, i, bm_count, qm_count, count;\n \tu32 val, reg;\n \n-\tcount = ARRAY_SIZE(ipq9574_ppe_sch_bm_config);\n-\tbm_cfg = ipq9574_ppe_sch_bm_config;\n+\tswitch (ppe_dev-\u003etype) {\n+\tcase IPQ9574_PPE:\n+\t\tbm_cfg = ipq9574_ppe_sch_bm_config;\n+\t\tbm_count = ARRAY_SIZE(ipq9574_ppe_sch_bm_config);\n+\t\tqm_cfg = ipq9574_ppe_sch_qm_config;\n+\t\tqm_count = ARRAY_SIZE(ipq9574_ppe_sch_qm_config);\n+\t\tbreak;\n+\tcase IPQ5424_PPE:\n+\t\tbm_cfg = ipq5424_ppe_sch_bm_config;\n+\t\tbm_count = ARRAY_SIZE(ipq5424_ppe_sch_bm_config);\n+\t\tqm_cfg = ipq5424_ppe_sch_qm_config;\n+\t\tqm_count = ARRAY_SIZE(ipq5424_ppe_sch_qm_config);\n+\t\tbreak;\n+\tdefault:\n+\t\tdev_err(ppe_dev-\u003edev, \"Invalid PPE type %d\\n\", ppe_dev-\u003etype);\n+\t\treturn -EINVAL;\n+\t}\n \n \t/* Configure the depth of BM scheduler entries. */\n-\tval = FIELD_PREP(PPE_BM_SCH_CTRL_SCH_DEPTH, count);\n+\tval = FIELD_PREP(PPE_BM_SCH_CTRL_SCH_DEPTH, bm_count);\n \tval |= FIELD_PREP(PPE_BM_SCH_CTRL_SCH_OFFSET, 0);\n \tval |= FIELD_PREP(PPE_BM_SCH_CTRL_SCH_EN, 1);\n \n@@ -1649,7 +2057,7 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev)\n \t * egress port, the second port takes effect when the specified port\n \t * is in the inactive state.\n \t */\n-\tfor (i = 0; i \u003c count; i++) {\n+\tfor (i = 0; i \u003c bm_count; i++) {\n \t\tval = FIELD_PREP(PPE_BM_SCH_CFG_TBL_VALID, bm_cfg[i].valid);\n \t\tval |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_DIR, bm_cfg[i].dir);\n \t\tval |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_PORT_NUM, bm_cfg[i].port);\n@@ -1664,11 +2072,8 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev)\n \t\t\tgoto sch_config_fail;\n \t}\n \n-\tcount = ARRAY_SIZE(ipq9574_ppe_sch_qm_config);\n-\tqm_cfg = ipq9574_ppe_sch_qm_config;\n-\n \t/* Configure the depth of QM scheduler entries. */\n-\tval = FIELD_PREP(PPE_PSCH_SCH_DEPTH_CFG_SCH_DEPTH, count);\n+\tval = FIELD_PREP(PPE_PSCH_SCH_DEPTH_CFG_SCH_DEPTH, qm_count);\n \tret = regmap_write(ppe_dev-\u003eregmap, PPE_PSCH_SCH_DEPTH_CFG_ADDR, val);\n \tif (ret)\n \t\tgoto sch_config_fail;\n@@ -1677,7 +2082,7 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev)\n \t * port, the second port takes effect when the specified dequeue\n \t * port is in the inactive port.\n \t */\n-\tfor (i = 0; i \u003c count; i++) {\n+\tfor (i = 0; i \u003c qm_count; i++) {\n \t\tval = FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_ENS_PORT_BITMAP,\n \t\t\t\t qm_cfg[i].ensch_port_bmp);\n \t\tval |= FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_ENS_PORT,\ndiff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h\nindex 60493e51e0a43..e7cdab9d963ac 100644\n--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h\n+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h\n@@ -163,6 +163,10 @@ enum ppe_sc_egress_type {\n \tPPE_SC_BYPASS_EGRESS_FAKE_MAC_DROP = 21,\n \tPPE_SC_BYPASS_EGRESS_TUNL_CONTEXT = 22,\n \tPPE_SC_BYPASS_EGRESS_FLOW_POLICER = 23,\n+\t/* Values 24-26 are only supported by IPQ5424. */\n+\tPPE_SC_BYPASS_EGRESS_SMAC_MC_DROP = 24,\n+\tPPE_SC_BYPASS_EGRESS_L2_FLOODING = 25,\n+\tPPE_SC_BYPASS_EGRESS_TUNNEL_EXP_CNT_CTRL = 26,\n \t/* This must be last as it determines the size of the BITMAP. */\n \tPPE_SC_BYPASS_EGRESS_SIZE,\n };\ndiff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c\nindex fd959a76ff433..8d5a6fad83379 100644\n--- a/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c\n+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c\n@@ -201,7 +201,7 @@ static int ppe_bm_counter_get(struct ppe_device *ppe_dev, struct seq_file *seq)\n \n \tseq_printf(seq, \"%-24s\", \"BM SILENT_DROP:\");\n \ttag = 0;\n-\tfor (i = 0; i \u003c PPE_DROP_CNT_TBL_ENTRIES; i++) {\n+\tfor (i = 0; i \u003c PPE_DROP_CNT_TBL_ENTRIES(ppe_dev); i++) {\n \t\treg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC;\n \t\tret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD,\n \t\t\t\t      \u0026pkt_cnt, NULL);\n@@ -225,7 +225,7 @@ static int ppe_bm_counter_get(struct ppe_device *ppe_dev, struct seq_file *seq)\n \t */\n \tseq_printf(seq, \"%-24s\", \"BM OVERFLOW_DROP:\");\n \ttag = 0;\n-\tfor (i = 0; i \u003c PPE_DROP_STAT_TBL_ENTRIES; i++) {\n+\tfor (i = 0; i \u003c PPE_DROP_STAT_TBL_ENTRIES(ppe_dev); i++) {\n \t\treg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i;\n \n \t\tret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,\n@@ -248,8 +248,8 @@ static int ppe_bm_counter_get(struct ppe_device *ppe_dev, struct seq_file *seq)\n \t/* The number of currently occupied buffers, that can't be flushed. */\n \tseq_printf(seq, \"%-24s\", \"BM USED/REACT:\");\n \ttag = 0;\n-\tfor (i = 0; i \u003c PPE_BM_USED_CNT_TBL_ENTRIES; i++) {\n-\t\treg = PPE_BM_USED_CNT_TBL_ADDR + i * PPE_BM_USED_CNT_TBL_INC;\n+\tfor (i = 0; i \u003c PPE_BM_USED_CNT_TBL_ENTRIES(ppe_dev); i++) {\n+\t\treg = PPE_BM_USED_CNT_TBL_ADDR(ppe_dev) + i * PPE_BM_USED_CNT_TBL_INC;\n \t\tret = regmap_read(ppe_dev-\u003eregmap, reg, \u0026val);\n \t\tif (ret) {\n \t\t\tdev_err(ppe_dev-\u003edev, \"CNT ERROR %d\\n\", ret);\n@@ -261,7 +261,7 @@ static int ppe_bm_counter_get(struct ppe_device *ppe_dev, struct seq_file *seq)\n \t\t */\n \t\tpkt_cnt = FIELD_GET(PPE_BM_USED_CNT_VAL, val);\n \n-\t\treg = PPE_BM_REACT_CNT_TBL_ADDR + i * PPE_BM_REACT_CNT_TBL_INC;\n+\t\treg = PPE_BM_REACT_CNT_TBL_ADDR(ppe_dev) + i * PPE_BM_REACT_CNT_TBL_INC;\n \t\tret = regmap_read(ppe_dev-\u003eregmap, reg, \u0026val);\n \t\tif (ret) {\n \t\t\tdev_err(ppe_dev-\u003edev, \"CNT ERROR %d\\n\", ret);\n@@ -723,12 +723,12 @@ static ssize_t ppe_packet_counter_write(struct file *file,\n \n \tswitch (entry-\u003ecounter_type) {\n \tcase PPE_CNT_BM:\n-\t\tfor (i = 0; i \u003c PPE_DROP_CNT_TBL_ENTRIES; i++) {\n+\t\tfor (i = 0; i \u003c PPE_DROP_CNT_TBL_ENTRIES(ppe_dev); i++) {\n \t\t\treg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC;\n \t\t\tppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD);\n \t\t}\n \n-\t\tfor (i = 0; i \u003c PPE_DROP_STAT_TBL_ENTRIES; i++) {\n+\t\tfor (i = 0; i \u003c PPE_DROP_STAT_TBL_ENTRIES(ppe_dev); i++) {\n \t\t\treg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i;\n \t\t\tppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);\n \t\t}\ndiff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h\nindex 746dfbb5a6821..d08ab02bdf79e 100644\n--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h\n+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h\n@@ -18,12 +18,20 @@\n \n /* PPE drop counters. */\n #define PPE_DROP_CNT_TBL_ADDR\t\t\t0xb024\n-#define PPE_DROP_CNT_TBL_ENTRIES\t\t8\n+#define PPE_DROP_CNT_TBL_IPQ9574_ENTRIES\t8\n+#define PPE_DROP_CNT_TBL_IPQ5424_ENTRIES\t4\n+#define PPE_DROP_CNT_TBL_ENTRIES(ppe_dev)\t\t\t\t\t\\\n+\t((ppe_dev)-\u003etype == IPQ5424_PPE ? PPE_DROP_CNT_TBL_IPQ5424_ENTRIES :\t\\\n+\t\t\t\t\t  PPE_DROP_CNT_TBL_IPQ9574_ENTRIES)\n #define PPE_DROP_CNT_TBL_INC\t\t\t4\n \n /* BM port drop counters. */\n #define PPE_DROP_STAT_TBL_ADDR\t\t\t0xe000\n-#define PPE_DROP_STAT_TBL_ENTRIES\t\t30\n+#define PPE_DROP_STAT_TBL_IPQ9574_ENTRIES\t30\n+#define PPE_DROP_STAT_TBL_IPQ5424_ENTRIES\t38\n+#define PPE_DROP_STAT_TBL_ENTRIES(ppe_dev)\t\t\t\t\t\\\n+\t((ppe_dev)-\u003etype == IPQ5424_PPE ? PPE_DROP_STAT_TBL_IPQ5424_ENTRIES :\t\\\n+\t\t\t\t\t  PPE_DROP_STAT_TBL_IPQ9574_ENTRIES)\n #define PPE_DROP_STAT_TBL_INC\t\t\t0x10\n \n /* Egress VLAN counters. */\n@@ -223,13 +231,23 @@\n /* PPE service code configuration for destination port and counter. */\n #define PPE_IN_L2_SERVICE_TBL_ADDR\t\t0x66000\n #define PPE_IN_L2_SERVICE_TBL_ENTRIES\t\t256\n-#define PPE_IN_L2_SERVICE_TBL_INC\t\t0x10\n+#define PPE_IN_L2_SERVICE_TBL_IPQ9574_INC\t0x10\n+#define PPE_IN_L2_SERVICE_TBL_IPQ5424_INC\t0x20\n+#define PPE_IN_L2_SERVICE_TBL_INC(ppe_dev)\t\t\t\t\t\\\n+\t((ppe_dev)-\u003etype == IPQ5424_PPE ? PPE_IN_L2_SERVICE_TBL_IPQ5424_INC :\t\\\n+\t\t\t\t\t  PPE_IN_L2_SERVICE_TBL_IPQ9574_INC)\n+#define PPE_IN_L2_SERVICE_TBL_IPQ9574_WORDS\t1\n+#define PPE_IN_L2_SERVICE_TBL_IPQ5424_WORDS\t2\n+#define PPE_IN_L2_SERVICE_TBL_WORDS(ppe_dev)\t\t\t\t\t\\\n+\t((ppe_dev)-\u003etype == IPQ5424_PPE ? PPE_IN_L2_SERVICE_TBL_IPQ5424_WORDS :\t\\\n+\t\t\t\t\t  PPE_IN_L2_SERVICE_TBL_IPQ9574_WORDS)\n #define PPE_IN_L2_SERVICE_TBL_DST_PORT_ID_VALID\tBIT(0)\n #define PPE_IN_L2_SERVICE_TBL_DST_PORT_ID\tGENMASK(4, 1)\n #define PPE_IN_L2_SERVICE_TBL_DST_DIRECTION\tBIT(5)\n #define PPE_IN_L2_SERVICE_TBL_DST_BYPASS_BITMAP\tGENMASK(29, 6)\n #define PPE_IN_L2_SERVICE_TBL_RX_CNT_EN\t\tBIT(30)\n #define PPE_IN_L2_SERVICE_TBL_TX_CNT_EN\t\tBIT(31)\n+#define PPE_IN_L2_SERVICE_TBL_W1_BYPASS_BITMAP_EXT\tGENMASK(7, 0)\n \n /* L2 Port configurations */\n #define PPE_L2_VP_PORT_TBL_ADDR\t\t\t0x98000\n@@ -386,39 +404,74 @@\n #define PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT_EN\tBIT(16)\n #define PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT\tGENMASK(20, 17)\n \n-/* There are 15 BM ports and 4 BM groups supported by PPE.\n- * BM port (0-7) is for EDMA port 0, BM port (8-13) is for\n- * PPE physical port 1-6 and BM port 14 is for EIP port.\n+/* There are 15 BM ports on IPQ9574 and 19 BM ports on IPQ5424, and\n+ * 4 BM groups supported by PPE. On IPQ9574, BM port (0-7) is for EDMA\n+ * port 0, BM port (8-13) is for PPE physical port 1-6 and BM port 14\n+ * is for EIP port. On IPQ5424, BM port (0-15) is for EDMA port 0 and\n+ * BM port (16-18) is for PPE physical port 1-3.\n+ *\n+ * The per-BM-port tables PPE_BM_PORT_FC_MODE and PPE_BM_PORT_FC_CFG_TBL\n+ * are at the same address on both SoCs, IPQ5424 only has more entries.\n  */\n+#define PPE_BM_PORT_IPQ9574_ENTRIES\t\t15\n+#define PPE_BM_PORT_IPQ5424_ENTRIES\t\t19\n+#define PPE_BM_PORT_ENTRIES(ppe_dev)\t\t\t\t\t\t\\\n+\t((ppe_dev)-\u003etype == IPQ5424_PPE ? PPE_BM_PORT_IPQ5424_ENTRIES :\t\\\n+\t\t\t\t\t  PPE_BM_PORT_IPQ9574_ENTRIES)\n+\n #define PPE_BM_PORT_FC_MODE_ADDR\t\t0x600100\n-#define PPE_BM_PORT_FC_MODE_ENTRIES\t\t15\n+#define PPE_BM_PORT_FC_MODE_ENTRIES(ppe_dev)\tPPE_BM_PORT_ENTRIES(ppe_dev)\n #define PPE_BM_PORT_FC_MODE_INC\t\t\t0x4\n #define PPE_BM_PORT_FC_MODE_EN\t\t\tBIT(0)\n \n-#define PPE_BM_PORT_GROUP_ID_ADDR\t\t0x600180\n-#define PPE_BM_PORT_GROUP_ID_ENTRIES\t\t15\n+#define PPE_BM_PORT_GROUP_ID_IPQ9574_ADDR\t0x600180\n+#define PPE_BM_PORT_GROUP_ID_IPQ5424_ADDR\t0x6001c0\n+#define PPE_BM_PORT_GROUP_ID_ADDR(ppe_dev)\t\t\t\t\t\\\n+\t((ppe_dev)-\u003etype == IPQ5424_PPE ? PPE_BM_PORT_GROUP_ID_IPQ5424_ADDR :\t\\\n+\t\t\t\t\t  PPE_BM_PORT_GROUP_ID_IPQ9574_ADDR)\n+#define PPE_BM_PORT_GROUP_ID_ENTRIES(ppe_dev)\tPPE_BM_PORT_ENTRIES(ppe_dev)\n #define PPE_BM_PORT_GROUP_ID_INC\t\t0x4\n #define PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID\tGENMASK(1, 0)\n \n /* Counters for PPE buffers used for packets cached. */\n-#define PPE_BM_USED_CNT_TBL_ADDR\t\t0x6001c0\n-#define PPE_BM_USED_CNT_TBL_ENTRIES\t\t15\n+#define PPE_BM_USED_CNT_TBL_IPQ9574_ADDR\t0x6001c0\n+#define PPE_BM_USED_CNT_TBL_IPQ5424_ADDR\t0x600220\n+#define PPE_BM_USED_CNT_TBL_ADDR(ppe_dev)\t\t\t\t\t\\\n+\t((ppe_dev)-\u003etype == IPQ5424_PPE ? PPE_BM_USED_CNT_TBL_IPQ5424_ADDR :\t\\\n+\t\t\t\t\t  PPE_BM_USED_CNT_TBL_IPQ9574_ADDR)\n+#define PPE_BM_USED_CNT_TBL_IPQ9574_ENTRIES\t15\n+#define PPE_BM_USED_CNT_TBL_IPQ5424_ENTRIES\t19\n+#define PPE_BM_USED_CNT_TBL_ENTRIES(ppe_dev)\t\t\t\t\t\\\n+\t((ppe_dev)-\u003etype == IPQ5424_PPE ? PPE_BM_USED_CNT_TBL_IPQ5424_ENTRIES : \\\n+\t\t\t\t\t  PPE_BM_USED_CNT_TBL_IPQ9574_ENTRIES)\n #define PPE_BM_USED_CNT_TBL_INC\t\t\t0x4\n #define PPE_BM_USED_CNT_VAL\t\t\tGENMASK(10, 0)\n \n /* Counters for PPE buffers used for packets received after pause frame sent. */\n-#define PPE_BM_REACT_CNT_TBL_ADDR\t\t0x600240\n-#define PPE_BM_REACT_CNT_TBL_ENTRIES\t\t15\n+#define PPE_BM_REACT_CNT_TBL_IPQ9574_ADDR\t0x600240\n+#define PPE_BM_REACT_CNT_TBL_IPQ5424_ADDR\t0x600280\n+#define PPE_BM_REACT_CNT_TBL_ADDR(ppe_dev)\t\t\t\t\t\\\n+\t((ppe_dev)-\u003etype == IPQ5424_PPE ? PPE_BM_REACT_CNT_TBL_IPQ5424_ADDR :\t\\\n+\t\t\t\t\t  PPE_BM_REACT_CNT_TBL_IPQ9574_ADDR)\n+#define PPE_BM_REACT_CNT_TBL_IPQ9574_ENTRIES\t15\n+#define PPE_BM_REACT_CNT_TBL_IPQ5424_ENTRIES\t19\n+#define PPE_BM_REACT_CNT_TBL_ENTRIES(ppe_dev)\t\t\t\t\t\\\n+\t((ppe_dev)-\u003etype == IPQ5424_PPE ? PPE_BM_REACT_CNT_TBL_IPQ5424_ENTRIES :\t\\\n+\t\t\t\t\t  PPE_BM_REACT_CNT_TBL_IPQ9574_ENTRIES)\n #define PPE_BM_REACT_CNT_TBL_INC\t\t0x4\n #define PPE_BM_REACT_CNT_VAL\t\t\tGENMASK(8, 0)\n \n-#define PPE_BM_SHARED_GROUP_CFG_ADDR\t\t0x600290\n+#define PPE_BM_SHARED_GROUP_CFG_IPQ9574_ADDR\t0x600290\n+#define PPE_BM_SHARED_GROUP_CFG_IPQ5424_ADDR\t0x6002f0\n+#define PPE_BM_SHARED_GROUP_CFG_ADDR(ppe_dev)\t\t\t\t\t\t\\\n+\t((ppe_dev)-\u003etype == IPQ5424_PPE ? PPE_BM_SHARED_GROUP_CFG_IPQ5424_ADDR :\t\\\n+\t\t\t\t\t  PPE_BM_SHARED_GROUP_CFG_IPQ9574_ADDR)\n #define PPE_BM_SHARED_GROUP_CFG_ENTRIES\t\t4\n #define PPE_BM_SHARED_GROUP_CFG_INC\t\t0x4\n #define PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT\tGENMASK(10, 0)\n \n #define PPE_BM_PORT_FC_CFG_TBL_ADDR\t\t0x601000\n-#define PPE_BM_PORT_FC_CFG_TBL_ENTRIES\t\t15\n+#define PPE_BM_PORT_FC_CFG_TBL_ENTRIES(ppe_dev)\tPPE_BM_PORT_ENTRIES(ppe_dev)\n #define PPE_BM_PORT_FC_CFG_TBL_INC\t\t0x10\n #define PPE_BM_PORT_FC_W0_REACT_LIMIT\t\tGENMASK(8, 0)\n #define PPE_BM_PORT_FC_W0_RESUME_THRESHOLD\tGENMASK(17, 9)\n"
}

2/1 2026/10/08 19:43 agent patch-evaluator
1m Model:
core

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch adds support for the Qualcomm IPQ5424 SoC to the Qualcomm Packet Process Engine (PPE) network driver and updates DeviceTree bindings and documentation. This is a platform driver for dedicated SoC hardware (ARCH_QCOM) requiring specific physical ASIC peripherals (clocks, interconnects, reset controllers) that are not emulated in standard virtualized environments (QEMU/GCE on amd64). Because the driver cannot probe or execute on amd64, the changes are structurally unreachable and not worth fuzzing.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.

================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.

- REACHABILITY IS THE PRIMARY GATE:
  Fuzzing can only discover bugs in code that can actually execute in standard virtualized
  environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
  If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
  regardless of whether it adds assertions or complex logic.

- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
  Patch authors routinely label changes as "cleanups", "refactorings", or state
  "No functional change intended". Do NOT take these claims at face value.
  Code refactorings that rearrange logic, introduce helper functions, or alter state management
  in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
  If reachable executable code is modified or refactored, it MUST be fuzzed.

- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
  When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
  BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
  Even if the author believes the invariant always holds, fuzzing is essential to verify whether
  an unusual sequence of operations can violate it.

================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:

- Non-kernel and non-executable changes:
  * Modifications to Documentation/, comments, or spelling fixes.
  * User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
    that do not affect the compiled kernel image (vmlinux) or kernel modules.
  * Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
    that do not alter control flow or data structures.
  * Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
  * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
    ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
  * Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
    physical PCI hot-unplug or manual sysfs driver unbinding.
  * Code paths exclusive to architectures other than the target architecture.

================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
  * Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
    BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
  * Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
  * Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
  * Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).

================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:

- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
  Do NOT list generic, ubiquitous functions called by almost every program in the corpus
  (including, but not limited to: general memory allocators and deallocators, page fault
  and trap handlers, or core synchronization primitives; this is not an exhaustive list).
  Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
  which severely dilutes fuzzing effort away from the actual changes.

- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
  List functions that specifically implement the logic being added or altered, or direct API entrypoints
  for the subsystem feature under review.

- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
  Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
  distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
  If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
  functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).

================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit 9b2e3adc9112df7aec393b3ca1a337f95566811a
Author: syz-cluster <triage@syzkaller.com>
Date:   Thu Oct 8 19:43:58 2026 +0000

    syz-cluster: applied patch under review

diff --git a/Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml b/Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml
index 6d0b21a10732a..e5d218fc5d825 100644
--- a/Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml
+++ b/Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml
@@ -74,9 +74,14 @@ description: |
     +------->|             QCA8075 PHY             | | PHY4  | | PHY5  |
      (clock) +-------------------------------------+ +-------+ +-------+
 
+  The IPQ5424 PPE reuses the same switch core, but wires up only 3
+  front panel ports (GMAC0-2) and the single EDMA FIFO interface; it
+  has no EIP FIFO and no ports 4-6.
+
 properties:
   compatible:
     enum:
+      - qcom,ipq5424-ppe
       - qcom,ipq9574-ppe
 
   reg:
@@ -105,24 +110,16 @@ properties:
     description: PPE switch miscellaneous interrupt
 
   interconnects:
-    items:
-      - description: Bus interconnect path leading to PPE switch core function
-      - description: Bus interconnect path leading to PPE register access
-      - description: Bus interconnect path leading to QoS generation
-      - description: Bus interconnect path leading to timeout reference
-      - description: Bus interconnect path leading to NSS NOC from memory NOC
-      - description: Bus interconnect path leading to memory NOC from NSS NOC
-      - description: Bus interconnect path leading to enhanced memory NOC from NSS NOC
+    minItems: 5
+    maxItems: 7
+    description:
+      The number of interconnect paths depends on compatible, 5 paths for
+      qcom,ipq5424-ppe and 7 paths for qcom,ipq9574-ppe, enumerated in the
+      allOf conditionals below.
 
   interconnect-names:
-    items:
-      - const: ppe
-      - const: ppe_cfg
-      - const: qos_gen
-      - const: timeout_ref
-      - const: nssnoc_memnoc
-      - const: memnoc_nssnoc
-      - const: memnoc_nssnoc_1
+    minItems: 5
+    maxItems: 7
 
   ethernet-dma:
     type: object
@@ -144,8 +141,14 @@ properties:
           - const: apb
 
       resets:
-        maxItems: 1
-        description: EDMA reset
+        items:
+          - description: EDMA system reset
+          - description: EDMA APB reset
+
+      reset-names:
+        items:
+          - const: sys
+          - const: apb
 
       interrupts:
         minItems: 65
@@ -170,12 +173,13 @@ properties:
       - clocks
       - clock-names
       - resets
+      - reset-names
       - interrupts
       - interrupt-names
 
   ethernet-ports:
     patternProperties:
-      "^ethernet-port@[1-6]+$":
+      "^ethernet-port@[1-6]$":
         type: object
         unevaluatedProperties: false
         $ref: ethernet-switch-port.yaml#
@@ -229,6 +233,62 @@ required:
 
 allOf:
   - $ref: ethernet-switch.yaml
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: qcom,ipq9574-ppe
+    then:
+      properties:
+        interconnects:
+          items:
+            - description: Bus interconnect path leading to PPE switch core function
+            - description: Bus interconnect path leading to PPE register access
+            - description: Bus interconnect path leading to QoS generation
+            - description: Bus interconnect path leading to timeout reference
+            - description: Bus interconnect path leading to NSS NOC from memory NOC
+            - description: Bus interconnect path leading to memory NOC from NSS NOC
+            - description: Bus interconnect path leading to enhanced memory NOC from NSS NOC
+
+        interconnect-names:
+          items:
+            - const: ppe
+            - const: ppe_cfg
+            - const: qos_gen
+            - const: timeout_ref
+            - const: nssnoc_memnoc
+            - const: memnoc_nssnoc
+            - const: memnoc_nssnoc_1
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: qcom,ipq5424-ppe
+    then:
+      properties:
+        interconnects:
+          items:
+            - description: Bus interconnect path leading to PPE switch core function
+            - description: Bus interconnect path leading to PPE register access
+            - description: Bus interconnect path leading to CE AXI
+            - description: Bus interconnect path leading to CE APB
+            - description: Bus interconnect path leading to NSS CSR access
+
+        interconnect-names:
+          items:
+            - const: ppe
+            - const: ppe_cfg
+            - const: nssnoc_ce_axi
+            - const: nssnoc_ce_apb
+            - const: nssnoc_nss_csr
+
+        ethernet-ports:
+          patternProperties:
+            "^ethernet-port@[1-3]$":
+              properties:
+                reg:
+                  maximum: 3
+            "^ethernet-port@[4-6]$": false
 
 unevaluatedProperties: false
 
@@ -273,7 +333,10 @@ examples:
                      <&nsscc NSS_CC_PPE_EDMA_CFG_CLK>;
             clock-names = "sys",
                           "apb";
-            resets = <&nsscc EDMA_HW_RESET>;
+            resets = <&nsscc PPE_EDMA_ARES>,
+                     <&nsscc PPE_EDMA_CFG_ARES>;
+            reset-names = "sys",
+                          "apb";
             interrupts = <GIC_SPI 363 IRQ_TYPE_LEVEL_HIGH>,
                          <GIC_SPI 364 IRQ_TYPE_LEVEL_HIGH>,
                          <GIC_SPI 365 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst b/Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst
index 4ab299a28969a..04c48cec66d53 100644
--- a/Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst
+++ b/Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst
@@ -167,6 +167,14 @@ PPE Driver Supported SoCs
 The PPE driver supports the following IPQ SoC:
 
 - IPQ9574
+    The PPE runs at a clock rate of 353 MHz. The switch core has 6 front panel
+    ports (port1 to port6) and two FIFO interfaces: the EDMA FIFO (port0) for
+    the host CPU communication and the EIP FIFO (port7) for the EIP engine.
+- IPQ5424
+    The PPE reuses the same switch core as IPQ9574 and runs at a clock rate of
+    375 MHz. It supports 3 front panel ports (port1 to port3) with MAC0 to MAC2,
+    and only the EDMA FIFO interface (port0) for the host CPU communication. The
+    EIP FIFO and port4 to port6 are not available.
 
 
 Enabling the Driver
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.c b/drivers/net/ethernet/qualcomm/ppe/ppe.c
index 3c301e609d3e3..b144fd8189983 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
@@ -18,13 +18,36 @@
 #include "ppe_config.h"
 #include "ppe_debugfs.h"
 
-#define PPE_PORT_MAX		8
-#define PPE_CLK_RATE		353000000
+#define IPQ9574_PPE_CLK_RATE	353000000
+#define IPQ5424_PPE_CLK_RATE	375000000
+
+/* 6 physical ports, 1 EDMA FIFO and 1 EIP FIFO. */
+#define IPQ9574_PPE_PORT_MAX		8
+/* 3 physical ports and 1 EDMA FIFO. */
+#define IPQ5424_PPE_PORT_MAX		4
+
+/**
+ * struct ppe_of_data - PPE private data of IPQ SoC
+ * @type: PPE type value
+ * @ppe_rate: PPE clock rate
+ * @num_ports: Number of PPE ports
+ * @regmap_config: Regmap configuration
+ * @icc_paths: Interconnect paths per PPE type
+ * @num_icc_paths: Number of ICC paths
+ */
+struct ppe_of_data {
+	enum ppe_type type;
+	unsigned long ppe_rate;
+	int num_ports;
+	const struct regmap_config *regmap_config;
+	const struct icc_bulk_data *icc_paths;
+	int num_icc_paths;
+};
 
 /* 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[] = {
+static const struct icc_bulk_data ipq9574_ppe_icc_data[] = {
 	{
 		.name = "ppe",
 		.avg_bw = 0,
@@ -62,6 +85,34 @@ static const struct icc_bulk_data ppe_icc_data[] = {
 	},
 };
 
+static const struct icc_bulk_data ipq5424_ppe_icc_data[] = {
+	{
+		.name = "ppe",
+		.avg_bw = 0,
+		.peak_bw = 0,
+	},
+	{
+		.name = "ppe_cfg",
+		.avg_bw = 0,
+		.peak_bw = 0,
+	},
+	{
+		.name = "nssnoc_ce_axi",
+		.avg_bw = 0,
+		.peak_bw = 0,
+	},
+	{
+		.name = "nssnoc_ce_apb",
+		.avg_bw = 0,
+		.peak_bw = 0,
+	},
+	{
+		.name = "nssnoc_nss_csr",
+		.avg_bw = 100000,
+		.peak_bw = 100000,
+	},
+};
+
 static const struct regmap_range ppe_readable_ranges[] = {
 	regmap_reg_range(0x0, 0x1ff),		/* Global */
 	regmap_reg_range(0x400, 0x5ff),		/* LPI CSR */
@@ -108,7 +159,36 @@ static const struct regmap_config regmap_config_ipq9574 = {
 	.max_register = 0xbef800,
 };
 
-static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
+/* For IPQ5424, there are only three Ethernet ports, the register space of
+ * GMAC/XGMAC 3-5 is unavailable.
+ */
+static const struct regmap_range ppe_reserved_ranges_ipq5424[] = {
+	regmap_reg_range(0x1600, 0x17ff),	/* GMAC3 */
+	regmap_reg_range(0x1800, 0x19ff),	/* GMAC4 */
+	regmap_reg_range(0x1a00, 0x1bff),	/* GMAC5 */
+	regmap_reg_range(0x50c000, 0x50ffff),	/* XGMAC3 */
+	regmap_reg_range(0x510000, 0x513fff),	/* XGMAC4 */
+	regmap_reg_range(0x514000, 0x517fff),	/* XGMAC5 */
+};
+
+static const struct regmap_access_table ppe_reg_table_ipq5424 = {
+	.yes_ranges = ppe_readable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges),
+	.no_ranges = ppe_reserved_ranges_ipq5424,
+	.n_no_ranges = ARRAY_SIZE(ppe_reserved_ranges_ipq5424),
+};
+
+static const struct regmap_config regmap_config_ipq5424 = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.rd_table = &ppe_reg_table_ipq5424,
+	.wr_table = &ppe_reg_table_ipq5424,
+	.max_register = 0xbef800,
+};
+
+static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev,
+				    const struct ppe_of_data *data)
 {
 	unsigned long ppe_rate = ppe_dev->clk_rate;
 	struct device *dev = ppe_dev->dev;
@@ -118,15 +198,15 @@ static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
 	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 ? :
+		ppe_dev->icc_paths[i].name = data->icc_paths[i].name;
+		ppe_dev->icc_paths[i].avg_bw = data->icc_paths[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 ? :
+		ppe_dev->icc_paths[i].peak_bw = data->icc_paths[i].peak_bw ? :
 						Bps_to_icc(ppe_rate);
 	}
 
@@ -173,12 +253,17 @@ static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
 static int qcom_ppe_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	const struct ppe_of_data *data;
 	struct ppe_device *ppe_dev;
 	void __iomem *base;
-	int ret, num_icc;
+	int ret;
+
+	data = of_device_get_match_data(dev);
+	if (!data)
+		return dev_err_probe(dev, -EINVAL, "PPE no match data provided\n");
 
-	num_icc = ARRAY_SIZE(ppe_icc_data);
-	ppe_dev = devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc),
+	ppe_dev = devm_kzalloc(dev,
+			       struct_size(ppe_dev, icc_paths, data->num_icc_paths),
 			       GFP_KERNEL);
 	if (!ppe_dev)
 		return -ENOMEM;
@@ -187,16 +272,17 @@ static int qcom_ppe_probe(struct platform_device *pdev)
 	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);
+	ppe_dev->regmap = devm_regmap_init_mmio(dev, base, data->regmap_config);
 	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;
+	ppe_dev->type = data->type;
+	ppe_dev->clk_rate = data->ppe_rate;
+	ppe_dev->num_ports = data->num_ports;
+	ppe_dev->num_icc_paths = data->num_icc_paths;
 
-	ret = ppe_clock_init_and_reset(ppe_dev);
+	ret = ppe_clock_init_and_reset(ppe_dev, data);
 	if (ret)
 		return dev_err_probe(dev, ret, "PPE clock config failed\n");
 
@@ -218,8 +304,27 @@ static void qcom_ppe_remove(struct platform_device *pdev)
 	ppe_debugfs_teardown(ppe_dev);
 }
 
+static const struct ppe_of_data ipq9574_data = {
+	.type = IPQ9574_PPE,
+	.ppe_rate = IPQ9574_PPE_CLK_RATE,
+	.num_ports = IPQ9574_PPE_PORT_MAX,
+	.regmap_config = &regmap_config_ipq9574,
+	.icc_paths = ipq9574_ppe_icc_data,
+	.num_icc_paths = ARRAY_SIZE(ipq9574_ppe_icc_data),
+};
+
+static const struct ppe_of_data ipq5424_data = {
+	.type = IPQ5424_PPE,
+	.ppe_rate = IPQ5424_PPE_CLK_RATE,
+	.num_ports = IPQ5424_PPE_PORT_MAX,
+	.regmap_config = &regmap_config_ipq5424,
+	.icc_paths = ipq5424_ppe_icc_data,
+	.num_icc_paths = ARRAY_SIZE(ipq5424_ppe_icc_data),
+};
+
 static const struct of_device_id qcom_ppe_of_match[] = {
-	{ .compatible = "qcom,ipq9574-ppe" },
+	{ .compatible = "qcom,ipq9574-ppe", .data = &ipq9574_data },
+	{ .compatible = "qcom,ipq5424-ppe", .data = &ipq5424_data },
 	{}
 };
 MODULE_DEVICE_TABLE(of, qcom_ppe_of_match);
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.h b/drivers/net/ethernet/qualcomm/ppe/ppe.h
index 27458f0bc2064..33b876d2e0794 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h
@@ -13,10 +13,24 @@ struct device;
 struct regmap;
 struct dentry;
 
+/**
+ * enum ppe_type - PPE device type.
+ * @IPQ9574_PPE: PPE device of IPQ9574.
+ * @IPQ5424_PPE: PPE device of IPQ5424.
+ *
+ * PPE type is used to identify the PPE device of the different
+ * IPQ platform.
+ */
+enum ppe_type {
+	IPQ9574_PPE,
+	IPQ5424_PPE,
+};
+
 /**
  * struct ppe_device - PPE device private data.
  * @dev: PPE device structure.
  * @regmap: PPE register map.
+ * @type: Different PPE type on various IPQ SoC.
  * @clk_rate: PPE clock rate.
  * @num_ports: Number of PPE ports.
  * @debugfs_root: Debugfs root entry.
@@ -30,6 +44,7 @@ struct dentry;
 struct ppe_device {
 	struct device *dev;
 	struct regmap *regmap;
+	enum ppe_type type;
 	unsigned long clk_rate;
 	unsigned int num_ports;
 	struct dentry *debugfs_root;
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
index 125b73be92b13..94885240166b8 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
@@ -230,6 +230,56 @@ static const struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = {
 	},
 };
 
+/* IPQ5424 has fewer PPE physical ports (3) than IPQ9574 (6), so fewer
+ * buffers need to be reserved for per-port purposes. Out of the same
+ * 2048 total, the rest assigned to the general 'group0' pool is
+ * correspondingly larger here, 1650 versus IPQ9574's 1550.
+ */
+static const int ipq5424_ppe_bm_group_config = 1650;
+
+/* The buffer configurations per PPE port on IPQ5424. There are 19 BM
+ * ports supported by PPE. BM port (0-15) is for EDMA port 0, and BM
+ * port (16-18) is for the 3 PPE physical ports.
+ */
+static const struct ppe_bm_port_config ipq5424_ppe_bm_port_config[] = {
+	{
+		/* Buffer configuration for the BM port ID 0 of EDMA. */
+		.port_id_start	= 0,
+		.port_id_end	= 0,
+		.pre_alloc	= 0,
+		.in_fly_buf	= 100,
+		.ceil		= 1146,
+		.weight		= 7,
+		.resume_offset	= 8,
+		.resume_ceil	= 0,
+		.dynamic	= true,
+	},
+	{
+		/* Buffer configuration for the BM port ID 1-15 of EDMA. */
+		.port_id_start	= 1,
+		.port_id_end	= 15,
+		.pre_alloc	= 0,
+		.in_fly_buf	= 100,
+		.ceil		= 250,
+		.weight		= 4,
+		.resume_offset	= 36,
+		.resume_ceil	= 0,
+		.dynamic	= true,
+	},
+	{
+		/* Buffer configuration for the BM port ID 16-18 of PPE ports. */
+		.port_id_start	= 16,
+		.port_id_end	= 18,
+		.pre_alloc	= 0,
+		.in_fly_buf	= 128,
+		.ceil		= 250,
+		.weight		= 4,
+		.resume_offset	= 36,
+		.resume_ceil	= 0,
+		.dynamic	= true,
+	},
+};
+
 /* QM fetches the packet from PPE buffer management for transmitting the
  * packet out. The QM group configuration limits the total number of buffers
  * enqueued by all PPE hardware queues.
@@ -264,6 +314,37 @@ static const struct ppe_qm_queue_config ipq9574_ppe_qm_queue_config[] = {
 	},
 };
 
+/* Multicast queues are dedicated per PPE port. IPQ5424 has only 3 physical
+ * PPE ports, versus IPQ9574's 6 PPE ports, so multicast queues 284 to 299
+ * are not available on IPQ5424, and the buffer pool assigned to the general
+ * 'group0' is larger here, 2010 versus IPQ9574's 2000.
+ */
+static const int ipq5424_ppe_qm_group_config = 2010;
+
+/* Default QM settings for unicast and multicast queues for IPQ5424. */
+static const struct ppe_qm_queue_config ipq5424_ppe_qm_queue_config[] = {
+	{
+		/* QM settings for unicast queues 0 to 255. */
+		.queue_start	= 0,
+		.queue_end	= 255,
+		.prealloc_buf	= 0,
+		.ceil		= 1200,
+		.weight		= 7,
+		.resume_offset	= 36,
+		.dynamic	= true,
+	},
+	{
+		/* QM settings for multicast queues 256 to 283. */
+		.queue_start	= 256,
+		.queue_end	= 283,
+		.prealloc_buf	= 0,
+		.ceil		= 250,
+		.weight		= 0,
+		.resume_offset	= 36,
+		.dynamic	= false,
+	},
+};
+
 /* PPE scheduler configuration for BM includes multiple entries. Each entry
  * indicates the primary port to be assigned the buffers for the ingress or
  * to release the buffers for the egress. Backup port ID will be used when
@@ -439,6 +520,205 @@ static const struct ppe_scheduler_qm_config ipq9574_ppe_sch_qm_config[] = {
 	{0x98, 6, 5, true, 2},
 };
 
+static const struct ppe_scheduler_bm_config ipq5424_ppe_sch_bm_config[] = {
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  3, true, 1},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  2, false, 0},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  1, true, 2},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  3, false, 0},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  2, true, 1},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  1, false, 0},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  3, false, 0},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  2, true, 1},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  3, true, 2},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  1, false, 0},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  2, true, 3},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  1, true, 2},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  3, false, 0},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  2, true, 3},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  1, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  3, true, 1},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  2, false, 0},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  1, true, 2},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  3, false, 0},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  2, true, 1},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  1, true, 2},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  3, false, 0},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  2, true, 1},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  1, true, 3},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  2, false, 0},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  3, true, 1},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  1, true, 2},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  3, false, 0},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  2, true, 3},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  1, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  3, true, 1},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  2, false, 0},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  1, true, 3},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  2, false, 0},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  3, true, 1},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  1, true, 2},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  3, false, 0},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  2, true, 1},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  3, true, 2},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  1, false, 0},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  2, true, 3},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 3, false, 0},
+	{true, PPE_SCH_EGRESS,  1, true, 2},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  3, false, 0},
+	{true, PPE_SCH_INGRESS, 2, false, 0},
+	{true, PPE_SCH_EGRESS,  0, false, 0},
+	{true, PPE_SCH_INGRESS, 1, false, 0},
+	{true, PPE_SCH_EGRESS,  2, true, 3},
+	{true, PPE_SCH_INGRESS, 0, false, 0},
+	{true, PPE_SCH_EGRESS,  1, false, 0},
+};
+
+/* ensch_port_bmp is left as 0 for every entry here, unlike
+ * ipq9574_ppe_sch_qm_config[] above. This is expected for IPQ5424,
+ * not an omission.
+ */
+static const struct ppe_scheduler_qm_config ipq5424_ppe_sch_qm_config[] = {
+	{0x0, 3, 2, false, 0},
+	{0x0, 1, 3, false, 0},
+	{0x0, 0, 1, false, 0},
+	{0x0, 2, 0, false, 0},
+	{0x0, 1, 2, false, 0},
+	{0x0, 3, 1, true, 0},
+	{0x0, 3, 2, false, 0},
+	{0x0, 1, 0, false, 0},
+	{0x0, 2, 1, false, 0},
+	{0x0, 2, 0, false, 0},
+	{0x0, 1, 2, false, 0},
+	{0x0, 3, 1, true, 0},
+	{0x0, 3, 2, false, 0},
+	{0x0, 1, 3, false, 0},
+	{0x0, 0, 1, false, 0},
+	{0x0, 2, 0, false, 0},
+	{0x0, 1, 2, false, 0},
+	{0x0, 3, 1, true, 0},
+	{0x0, 3, 2, false, 0},
+	{0x0, 1, 0, false, 0},
+	{0x0, 2, 1, false, 0},
+	{0x0, 2, 0, false, 0},
+	{0x0, 1, 2, false, 0},
+	{0x0, 0, 1, false, 0},
+	{0x0, 2, 0, false, 0},
+	{0x0, 3, 1, false, 0},
+	{0x0, 2, 0, false, 0},
+	{0x0, 1, 2, false, 0},
+	{0x0, 1, 0, false, 0},
+	{0x0, 2, 1, false, 0},
+	{0x0, 3, 2, true, 0},
+	{0x0, 3, 1, false, 0},
+	{0x0, 2, 0, false, 0},
+	{0x0, 1, 2, false, 0},
+	{0x0, 1, 3, false, 0},
+	{0x0, 0, 1, false, 0},
+	{0x0, 3, 2, true, 0},
+	{0x0, 3, 1, false, 0},
+	{0x0, 2, 0, false, 0},
+	{0x0, 1, 2, false, 0},
+	{0x0, 1, 0, false, 0},
+	{0x0, 2, 1, false, 0},
+	{0x0, 0, 2, false, 0},
+	{0x0, 3, 1, false, 0},
+	{0x0, 2, 0, false, 0},
+	{0x0, 1, 2, false, 0},
+	{0x0, 1, 0, false, 0},
+	{0x0, 2, 1, false, 0},
+	{0x0, 0, 2, false, 0},
+	{0x0, 3, 0, false, 0},
+	{0x0, 3, 1, false, 0},
+	{0x0, 2, 3, false, 0},
+	{0x0, 0, 2, false, 0},
+	{0x0, 1, 0, false, 0},
+	{0x0, 2, 1, false, 0},
+	{0x0, 3, 2, true, 0},
+	{0x0, 3, 1, false, 0},
+	{0x0, 2, 3, false, 0},
+	{0x0, 0, 2, false, 0},
+	{0x0, 1, 0, false, 0},
+	{0x0, 2, 1, false, 0},
+	{0x0, 0, 2, false, 0},
+	{0x0, 3, 0, false, 0},
+};
+
 static const struct ppe_scheduler_port_config ppe_port_sch_config[] = {
 	{
 		.port		= 0,
@@ -733,7 +1013,7 @@ static const struct ppe_scheduler_port_config ppe_port_sch_config[] = {
 /* The scheduler resource is applied to each PPE port, The resource
  * includes the unicast & multicast queues, flow nodes and DRR nodes.
  */
-static const struct ppe_port_schedule_resource ppe_scheduler_res[] = {
+static const struct ppe_port_schedule_resource ipq9574_ppe_scheduler_res[] = {
 	{	.ucastq_start	= 0,
 		.ucastq_end	= 63,
 		.mcastq_start	= 256,
@@ -835,6 +1115,64 @@ static const struct ppe_port_schedule_resource ppe_scheduler_res[] = {
 	},
 };
 
+static const struct ppe_port_schedule_resource ipq5424_ppe_scheduler_res[] = {
+	{	.ucastq_start	= 0,
+		.ucastq_end	= 63,
+		.mcastq_start	= 256,
+		.mcastq_end	= 271,
+		.flow_id_start	= 0,
+		.flow_id_end	= 0,
+		.l0node_start	= 0,
+		.l0node_end	= 7,
+		.l1node_start	= 0,
+		.l1node_end	= 0,
+	},
+	{	.ucastq_start	= 144,
+		.ucastq_end	= 159,
+		.mcastq_start	= 272,
+		.mcastq_end	= 275,
+		.flow_id_start	= 36,
+		.flow_id_end	= 39,
+		.l0node_start	= 48,
+		.l0node_end	= 63,
+		.l1node_start	= 8,
+		.l1node_end	= 11,
+	},
+	{	.ucastq_start	= 160,
+		.ucastq_end	= 175,
+		.mcastq_start	= 276,
+		.mcastq_end	= 279,
+		.flow_id_start	= 40,
+		.flow_id_end	= 43,
+		.l0node_start	= 64,
+		.l0node_end	= 79,
+		.l1node_start	= 12,
+		.l1node_end	= 15,
+	},
+	{	.ucastq_start	= 176,
+		.ucastq_end	= 191,
+		.mcastq_start	= 280,
+		.mcastq_end	= 283,
+		.flow_id_start	= 44,
+		.flow_id_end	= 47,
+		.l0node_start	= 80,
+		.l0node_end	= 95,
+		.l1node_start	= 16,
+		.l1node_end	= 19,
+	},
+	{	.ucastq_start	= 64,
+		.ucastq_end	= 143,
+		.mcastq_start	= 0,
+		.mcastq_end	= 0,
+		.flow_id_start	= 1,
+		.flow_id_end	= 35,
+		.l0node_start	= 8,
+		.l0node_end	= 47,
+		.l1node_start	= 1,
+		.l1node_end	= 7,
+	},
+};
+
 /* Set the PPE queue level scheduler configuration. */
 static int ppe_scheduler_l0_queue_map_set(struct ppe_device *ppe_dev,
 					  int node_id, int port,
@@ -1072,15 +1410,31 @@ int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,
 			  enum ppe_resource_type type,
 			  int *res_start, int *res_end)
 {
+	const struct ppe_port_schedule_resource *scheduler_res;
 	struct ppe_port_schedule_resource res;
+	unsigned int scheduler_res_len;
 
-	/* The reserved resource with the maximum port ID of PPE is
-	 * also allowed to be acquired.
+	switch (ppe_dev->type) {
+	case IPQ9574_PPE:
+		scheduler_res = ipq9574_ppe_scheduler_res;
+		scheduler_res_len = ARRAY_SIZE(ipq9574_ppe_scheduler_res);
+		break;
+	case IPQ5424_PPE:
+		scheduler_res = ipq5424_ppe_scheduler_res;
+		scheduler_res_len = ARRAY_SIZE(ipq5424_ppe_scheduler_res);
+		break;
+	default:
+		dev_err(ppe_dev->dev, "Invalid PPE type %d\n", ppe_dev->type);
+		return -EINVAL;
+	}
+
+	/* The reserved resource, stored at the last entry of the
+	 * scheduler resource table, is also allowed to be acquired.
 	 */
-	if (port > ppe_dev->num_ports)
+	if (port >= scheduler_res_len)
 		return -EINVAL;
 
-	res = ppe_scheduler_res[port];
+	res = scheduler_res[port];
 	switch (type) {
 	case PPE_RES_UCAST:
 		*res_start = res.ucastq_start;
@@ -1122,7 +1476,7 @@ int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,
  */
 int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, struct ppe_sc_cfg cfg)
 {
-	u32 val, reg, servcode_val[2] = {};
+	u32 val, reg, servcode_val[2] = {}, in_l2_val[2] = {};
 	unsigned long bitmap_value;
 	int ret;
 
@@ -1136,9 +1490,16 @@ int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, struct ppe_sc_cfg cfg)
 			  test_bit(PPE_SC_BYPASS_COUNTER_RX, cfg.bitmaps.counter));
 	val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_TX_CNT_EN,
 			  test_bit(PPE_SC_BYPASS_COUNTER_TX, cfg.bitmaps.counter));
-	reg = PPE_IN_L2_SERVICE_TBL_ADDR + PPE_IN_L2_SERVICE_TBL_INC * sc;
+	reg = PPE_IN_L2_SERVICE_TBL_ADDR + PPE_IN_L2_SERVICE_TBL_INC(ppe_dev) * sc;
 
-	ret = regmap_write(ppe_dev->regmap, reg, val);
+	in_l2_val[0] = val;
+
+	bitmap_value = bitmap_read(cfg.bitmaps.egress, PPE_SC_BYPASS_EGRESS_SMAC_MC_DROP,
+				   PPE_SC_BYPASS_EGRESS_SIZE - PPE_SC_BYPASS_EGRESS_SMAC_MC_DROP);
+	in_l2_val[1] = FIELD_PREP(PPE_IN_L2_SERVICE_TBL_W1_BYPASS_BITMAP_EXT, bitmap_value);
+
+	ret = regmap_bulk_write(ppe_dev->regmap, reg, in_l2_val,
+				PPE_IN_L2_SERVICE_TBL_WORDS(ppe_dev));
 	if (ret)
 		return ret;
 
@@ -1413,7 +1774,7 @@ static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
 
 	/* Assign the default group ID 0 to the BM port. */
 	val = FIELD_PREP(PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, 0);
-	reg = PPE_BM_PORT_GROUP_ID_ADDR + PPE_BM_PORT_GROUP_ID_INC * bm_port_id;
+	reg = PPE_BM_PORT_GROUP_ID_ADDR(ppe_dev) + PPE_BM_PORT_GROUP_ID_INC * bm_port_id;
 	ret = regmap_update_bits(ppe_dev->regmap, reg,
 				 PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID,
 				 val);
@@ -1431,25 +1792,38 @@ static int ppe_config_bm(struct ppe_device *ppe_dev)
 {
 	const struct ppe_bm_port_config *port_cfg;
 	unsigned int i, bm_port_id, port_cfg_cnt;
-	u32 reg, val;
+	u32 reg, val, group_cfg;
 	int ret;
 
+	switch (ppe_dev->type) {
+	case IPQ9574_PPE:
+		port_cfg = ipq9574_ppe_bm_port_config;
+		port_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config);
+		group_cfg = ipq9574_ppe_bm_group_config;
+		break;
+	case IPQ5424_PPE:
+		port_cfg = ipq5424_ppe_bm_port_config;
+		port_cfg_cnt = ARRAY_SIZE(ipq5424_ppe_bm_port_config);
+		group_cfg = ipq5424_ppe_bm_group_config;
+		break;
+	default:
+		dev_err(ppe_dev->dev, "Invalid PPE type %d\n", ppe_dev->type);
+		return -EINVAL;
+	}
+
+	reg = PPE_BM_SHARED_GROUP_CFG_ADDR(ppe_dev);
+
 	/* Configure the allocated buffer number only for group 0.
 	 * The buffer number of group 1-3 is already cleared to 0
 	 * after PPE reset during the probe of PPE driver.
 	 */
-	reg = PPE_BM_SHARED_GROUP_CFG_ADDR;
-	val = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,
-			 ipq9574_ppe_bm_group_config);
+	val = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT, group_cfg);
 	ret = regmap_update_bits(ppe_dev->regmap, reg,
 				 PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,
 				 val);
 	if (ret)
 		goto bm_config_fail;
 
-	/* Configure buffer thresholds for the BM ports. */
-	port_cfg = ipq9574_ppe_bm_port_config;
-	port_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config);
 	for (i = 0; i < port_cfg_cnt; i++) {
 		for (bm_port_id = port_cfg[i].port_id_start;
 		     bm_port_id <= port_cfg[i].port_id_end; bm_port_id++) {
@@ -1472,12 +1846,28 @@ static int ppe_config_bm(struct ppe_device *ppe_dev)
  */
 static int ppe_config_qm(struct ppe_device *ppe_dev)
 {
+	int ret, i, group_buffer_cfg, queue_id, queue_cfg_count;
 	const struct ppe_qm_queue_config *queue_cfg;
-	int ret, i, queue_id, queue_cfg_count;
 	u32 reg, multicast_queue_cfg[5];
 	u32 unicast_queue_cfg[4];
 	u32 group_cfg[3];
 
+	switch (ppe_dev->type) {
+	case IPQ9574_PPE:
+		group_buffer_cfg = ipq9574_ppe_qm_group_config;
+		queue_cfg = ipq9574_ppe_qm_queue_config;
+		queue_cfg_count = ARRAY_SIZE(ipq9574_ppe_qm_queue_config);
+		break;
+	case IPQ5424_PPE:
+		group_buffer_cfg = ipq5424_ppe_qm_group_config;
+		queue_cfg = ipq5424_ppe_qm_queue_config;
+		queue_cfg_count = ARRAY_SIZE(ipq5424_ppe_qm_queue_config);
+		break;
+	default:
+		dev_err(ppe_dev->dev, "Invalid PPE type %d\n", ppe_dev->type);
+		return -EINVAL;
+	}
+
 	/* Assign the buffer number to the group 0 by default. */
 	reg = PPE_AC_GRP_CFG_TBL_ADDR;
 	ret = regmap_bulk_read(ppe_dev->regmap, reg,
@@ -1485,15 +1875,13 @@ static int ppe_config_qm(struct ppe_device *ppe_dev)
 	if (ret)
 		goto qm_config_fail;
 
-	PPE_AC_GRP_SET_BUF_LIMIT(group_cfg, ipq9574_ppe_qm_group_config);
+	PPE_AC_GRP_SET_BUF_LIMIT(group_cfg, group_buffer_cfg);
 
 	ret = regmap_bulk_write(ppe_dev->regmap, reg,
 				group_cfg, ARRAY_SIZE(group_cfg));
 	if (ret)
 		goto qm_config_fail;
 
-	queue_cfg = ipq9574_ppe_qm_queue_config;
-	queue_cfg_count = ARRAY_SIZE(ipq9574_ppe_qm_queue_config);
 	for (i = 0; i < queue_cfg_count; i++) {
 		queue_id = queue_cfg[i].queue_start;
 
@@ -1530,8 +1918,13 @@ static int ppe_config_qm(struct ppe_device *ppe_dev)
 				if (ret)
 					goto qm_config_fail;
 			} else {
+				/* The multicast queue table is indexed from 0 for
+				 * the first multicast queue, which follows the
+				 * unicast queues.
+				 */
 				reg = PPE_AC_MULTICAST_QUEUE_CFG_TBL_ADDR +
-				      PPE_AC_MULTICAST_QUEUE_CFG_TBL_INC * queue_id;
+				      PPE_AC_MULTICAST_QUEUE_CFG_TBL_INC *
+				      (queue_id - PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES);
 
 				ret = regmap_bulk_read(ppe_dev->regmap, reg,
 						       multicast_queue_cfg,
@@ -1630,14 +2023,29 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev)
 	const struct ppe_scheduler_port_config *port_cfg;
 	const struct ppe_scheduler_qm_config *qm_cfg;
 	const struct ppe_scheduler_bm_config *bm_cfg;
-	int ret, i, count;
+	int ret, i, bm_count, qm_count, count;
 	u32 val, reg;
 
-	count = ARRAY_SIZE(ipq9574_ppe_sch_bm_config);
-	bm_cfg = ipq9574_ppe_sch_bm_config;
+	switch (ppe_dev->type) {
+	case IPQ9574_PPE:
+		bm_cfg = ipq9574_ppe_sch_bm_config;
+		bm_count = ARRAY_SIZE(ipq9574_ppe_sch_bm_config);
+		qm_cfg = ipq9574_ppe_sch_qm_config;
+		qm_count = ARRAY_SIZE(ipq9574_ppe_sch_qm_config);
+		break;
+	case IPQ5424_PPE:
+		bm_cfg = ipq5424_ppe_sch_bm_config;
+		bm_count = ARRAY_SIZE(ipq5424_ppe_sch_bm_config);
+		qm_cfg = ipq5424_ppe_sch_qm_config;
+		qm_count = ARRAY_SIZE(ipq5424_ppe_sch_qm_config);
+		break;
+	default:
+		dev_err(ppe_dev->dev, "Invalid PPE type %d\n", ppe_dev->type);
+		return -EINVAL;
+	}
 
 	/* Configure the depth of BM scheduler entries. */
-	val = FIELD_PREP(PPE_BM_SCH_CTRL_SCH_DEPTH, count);
+	val = FIELD_PREP(PPE_BM_SCH_CTRL_SCH_DEPTH, bm_count);
 	val |= FIELD_PREP(PPE_BM_SCH_CTRL_SCH_OFFSET, 0);
 	val |= FIELD_PREP(PPE_BM_SCH_CTRL_SCH_EN, 1);
 
@@ -1649,7 +2057,7 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev)
 	 * egress port, the second port takes effect when the specified port
 	 * is in the inactive state.
 	 */
-	for (i = 0; i < count; i++) {
+	for (i = 0; i < bm_count; i++) {
 		val = FIELD_PREP(PPE_BM_SCH_CFG_TBL_VALID, bm_cfg[i].valid);
 		val |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_DIR, bm_cfg[i].dir);
 		val |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_PORT_NUM, bm_cfg[i].port);
@@ -1664,11 +2072,8 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev)
 			goto sch_config_fail;
 	}
 
-	count = ARRAY_SIZE(ipq9574_ppe_sch_qm_config);
-	qm_cfg = ipq9574_ppe_sch_qm_config;
-
 	/* Configure the depth of QM scheduler entries. */
-	val = FIELD_PREP(PPE_PSCH_SCH_DEPTH_CFG_SCH_DEPTH, count);
+	val = FIELD_PREP(PPE_PSCH_SCH_DEPTH_CFG_SCH_DEPTH, qm_count);
 	ret = regmap_write(ppe_dev->regmap, PPE_PSCH_SCH_DEPTH_CFG_ADDR, val);
 	if (ret)
 		goto sch_config_fail;
@@ -1677,7 +2082,7 @@ static int ppe_config_scheduler(struct ppe_device *ppe_dev)
 	 * port, the second port takes effect when the specified dequeue
 	 * port is in the inactive port.
 	 */
-	for (i = 0; i < count; i++) {
+	for (i = 0; i < qm_count; i++) {
 		val = FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_ENS_PORT_BITMAP,
 				 qm_cfg[i].ensch_port_bmp);
 		val |= FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_ENS_PORT,
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
index 60493e51e0a43..e7cdab9d963ac 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
@@ -163,6 +163,10 @@ enum ppe_sc_egress_type {
 	PPE_SC_BYPASS_EGRESS_FAKE_MAC_DROP = 21,
 	PPE_SC_BYPASS_EGRESS_TUNL_CONTEXT = 22,
 	PPE_SC_BYPASS_EGRESS_FLOW_POLICER = 23,
+	/* Values 24-26 are only supported by IPQ5424. */
+	PPE_SC_BYPASS_EGRESS_SMAC_MC_DROP = 24,
+	PPE_SC_BYPASS_EGRESS_L2_FLOODING = 25,
+	PPE_SC_BYPASS_EGRESS_TUNNEL_EXP_CNT_CTRL = 26,
 	/* This must be last as it determines the size of the BITMAP. */
 	PPE_SC_BYPASS_EGRESS_SIZE,
 };
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c
index fd959a76ff433..8d5a6fad83379 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c
@@ -201,7 +201,7 @@ static int ppe_bm_counter_get(struct ppe_device *ppe_dev, struct seq_file *seq)
 
 	seq_printf(seq, "%-24s", "BM SILENT_DROP:");
 	tag = 0;
-	for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) {
+	for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES(ppe_dev); 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);
@@ -225,7 +225,7 @@ static int ppe_bm_counter_get(struct ppe_device *ppe_dev, struct seq_file *seq)
 	 */
 	seq_printf(seq, "%-24s", "BM OVERFLOW_DROP:");
 	tag = 0;
-	for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES; i++) {
+	for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES(ppe_dev); 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,
@@ -248,8 +248,8 @@ static int ppe_bm_counter_get(struct ppe_device *ppe_dev, struct seq_file *seq)
 	/* 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;
+	for (i = 0; i < PPE_BM_USED_CNT_TBL_ENTRIES(ppe_dev); i++) {
+		reg = PPE_BM_USED_CNT_TBL_ADDR(ppe_dev) + 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);
@@ -261,7 +261,7 @@ static int ppe_bm_counter_get(struct ppe_device *ppe_dev, struct seq_file *seq)
 		 */
 		pkt_cnt = FIELD_GET(PPE_BM_USED_CNT_VAL, val);
 
-		reg = PPE_BM_REACT_CNT_TBL_ADDR + i * PPE_BM_REACT_CNT_TBL_INC;
+		reg = PPE_BM_REACT_CNT_TBL_ADDR(ppe_dev) + 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);
@@ -723,12 +723,12 @@ static ssize_t ppe_packet_counter_write(struct file *file,
 
 	switch (entry->counter_type) {
 	case PPE_CNT_BM:
-		for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) {
+		for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES(ppe_dev); 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++) {
+		for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES(ppe_dev); 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);
 		}
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
index 746dfbb5a6821..d08ab02bdf79e 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
@@ -18,12 +18,20 @@
 
 /* PPE drop counters. */
 #define PPE_DROP_CNT_TBL_ADDR			0xb024
-#define PPE_DROP_CNT_TBL_ENTRIES		8
+#define PPE_DROP_CNT_TBL_IPQ9574_ENTRIES	8
+#define PPE_DROP_CNT_TBL_IPQ5424_ENTRIES	4
+#define PPE_DROP_CNT_TBL_ENTRIES(ppe_dev)					\
+	((ppe_dev)->type == IPQ5424_PPE ? PPE_DROP_CNT_TBL_IPQ5424_ENTRIES :	\
+					  PPE_DROP_CNT_TBL_IPQ9574_ENTRIES)
 #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_IPQ9574_ENTRIES	30
+#define PPE_DROP_STAT_TBL_IPQ5424_ENTRIES	38
+#define PPE_DROP_STAT_TBL_ENTRIES(ppe_dev)					\
+	((ppe_dev)->type == IPQ5424_PPE ? PPE_DROP_STAT_TBL_IPQ5424_ENTRIES :	\
+					  PPE_DROP_STAT_TBL_IPQ9574_ENTRIES)
 #define PPE_DROP_STAT_TBL_INC			0x10
 
 /* Egress VLAN counters. */
@@ -223,13 +231,23 @@
 /* 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_IPQ9574_INC	0x10
+#define PPE_IN_L2_SERVICE_TBL_IPQ5424_INC	0x20
+#define PPE_IN_L2_SERVICE_TBL_INC(ppe_dev)					\
+	((ppe_dev)->type == IPQ5424_PPE ? PPE_IN_L2_SERVICE_TBL_IPQ5424_INC :	\
+					  PPE_IN_L2_SERVICE_TBL_IPQ9574_INC)
+#define PPE_IN_L2_SERVICE_TBL_IPQ9574_WORDS	1
+#define PPE_IN_L2_SERVICE_TBL_IPQ5424_WORDS	2
+#define PPE_IN_L2_SERVICE_TBL_WORDS(ppe_dev)					\
+	((ppe_dev)->type == IPQ5424_PPE ? PPE_IN_L2_SERVICE_TBL_IPQ5424_WORDS :	\
+					  PPE_IN_L2_SERVICE_TBL_IPQ9574_WORDS)
 #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)
+#define PPE_IN_L2_SERVICE_TBL_W1_BYPASS_BITMAP_EXT	GENMASK(7, 0)
 
 /* L2 Port configurations */
 #define PPE_L2_VP_PORT_TBL_ADDR			0x98000
@@ -386,39 +404,74 @@
 #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.
+/* There are 15 BM ports on IPQ9574 and 19 BM ports on IPQ5424, and
+ * 4 BM groups supported by PPE. On IPQ9574, 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. On IPQ5424, BM port (0-15) is for EDMA port 0 and
+ * BM port (16-18) is for PPE physical port 1-3.
+ *
+ * The per-BM-port tables PPE_BM_PORT_FC_MODE and PPE_BM_PORT_FC_CFG_TBL
+ * are at the same address on both SoCs, IPQ5424 only has more entries.
  */
+#define PPE_BM_PORT_IPQ9574_ENTRIES		15
+#define PPE_BM_PORT_IPQ5424_ENTRIES		19
+#define PPE_BM_PORT_ENTRIES(ppe_dev)						\
+	((ppe_dev)->type == IPQ5424_PPE ? PPE_BM_PORT_IPQ5424_ENTRIES :	\
+					  PPE_BM_PORT_IPQ9574_ENTRIES)
+
 #define PPE_BM_PORT_FC_MODE_ADDR		0x600100
-#define PPE_BM_PORT_FC_MODE_ENTRIES		15
+#define PPE_BM_PORT_FC_MODE_ENTRIES(ppe_dev)	PPE_BM_PORT_ENTRIES(ppe_dev)
 #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_IPQ9574_ADDR	0x600180
+#define PPE_BM_PORT_GROUP_ID_IPQ5424_ADDR	0x6001c0
+#define PPE_BM_PORT_GROUP_ID_ADDR(ppe_dev)					\
+	((ppe_dev)->type == IPQ5424_PPE ? PPE_BM_PORT_GROUP_ID_IPQ5424_ADDR :	\
+					  PPE_BM_PORT_GROUP_ID_IPQ9574_ADDR)
+#define PPE_BM_PORT_GROUP_ID_ENTRIES(ppe_dev)	PPE_BM_PORT_ENTRIES(ppe_dev)
 #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_IPQ9574_ADDR	0x6001c0
+#define PPE_BM_USED_CNT_TBL_IPQ5424_ADDR	0x600220
+#define PPE_BM_USED_CNT_TBL_ADDR(ppe_dev)					\
+	((ppe_dev)->type == IPQ5424_PPE ? PPE_BM_USED_CNT_TBL_IPQ5424_ADDR :	\
+					  PPE_BM_USED_CNT_TBL_IPQ9574_ADDR)
+#define PPE_BM_USED_CNT_TBL_IPQ9574_ENTRIES	15
+#define PPE_BM_USED_CNT_TBL_IPQ5424_ENTRIES	19
+#define PPE_BM_USED_CNT_TBL_ENTRIES(ppe_dev)					\
+	((ppe_dev)->type == IPQ5424_PPE ? PPE_BM_USED_CNT_TBL_IPQ5424_ENTRIES : \
+					  PPE_BM_USED_CNT_TBL_IPQ9574_ENTRIES)
 #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_IPQ9574_ADDR	0x600240
+#define PPE_BM_REACT_CNT_TBL_IPQ5424_ADDR	0x600280
+#define PPE_BM_REACT_CNT_TBL_ADDR(ppe_dev)					\
+	((ppe_dev)->type == IPQ5424_PPE ? PPE_BM_REACT_CNT_TBL_IPQ5424_ADDR :	\
+					  PPE_BM_REACT_CNT_TBL_IPQ9574_ADDR)
+#define PPE_BM_REACT_CNT_TBL_IPQ9574_ENTRIES	15
+#define PPE_BM_REACT_CNT_TBL_IPQ5424_ENTRIES	19
+#define PPE_BM_REACT_CNT_TBL_ENTRIES(ppe_dev)					\
+	((ppe_dev)->type == IPQ5424_PPE ? PPE_BM_REACT_CNT_TBL_IPQ5424_ENTRIES :	\
+					  PPE_BM_REACT_CNT_TBL_IPQ9574_ENTRIES)
 #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_IPQ9574_ADDR	0x600290
+#define PPE_BM_SHARED_GROUP_CFG_IPQ5424_ADDR	0x6002f0
+#define PPE_BM_SHARED_GROUP_CFG_ADDR(ppe_dev)						\
+	((ppe_dev)->type == IPQ5424_PPE ? PPE_BM_SHARED_GROUP_CFG_IPQ5424_ADDR :	\
+					  PPE_BM_SHARED_GROUP_CFG_IPQ9574_ADDR)
 #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_ENTRIES(ppe_dev)	PPE_BM_PORT_ENTRIES(ppe_dev)
 #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)

3/2 2026/10/08 19:43 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 23717
							output: 32
							thoughts: 342
						

Thoughts:
**Analyzing This Patch: Qualcomm PPE Driver Updates**

Okay, let's dive into this. The first thing I'm doing is breaking down the specifics of this patch. My initial scan tells me this is aimed at the amd64 architecture, which I'm taking as a good sign for general compatibility, even if the primary target is the Qualcomm IPQ SoCs.

Now, let's get into the files modified. I'm seeing changes to the documentation and the driver source code itself. Specific modifications are targeting the device tree bindings and associated documentation, which makes me think this is likely a feature or hardware enablement change. I'm also seeing core driver files being touched, including the core `.c` and `.h` files, configuration and debug files.

The directory structure immediately screams "Qualcomm PPE driver" to me: `drivers/net/ethernet/qualcomm/ppe/`. It's pretty straightforward, indicating this driver is associated with Qualcomm's IPQ SoCs, specifically mentioning the IPQ9574 and IPQ5424. The IPQ9574/IPQ5424 SoCs are members of Qualcomm's Networking Pro series, which means these are ARM64 SoCs, likely based on Cortex-A73 cores, the usual suspect. Now, since I'm already in this directory, I'm going to quickly check the associated `Kconfig` for this specific driver. That'll give me context on its build status and any relevant dependencies.



4/2 2026/10/08 19:44 tool grepper
0m Args:
{
  "Expression": "PPE",
  "PathPrefixes": [
    "drivers/net/ethernet/qualcomm/"
  ]
}

Results:
{
  "Output": "\nFull output is too long, showing 200 out of 2623 lines.\nUse more precise expression or PathPrefixes if possible.\n\nNumber of matching lines per file (14 files in total):\ndrivers/net/ethernet/qualcomm/Kconfig:3\ndrivers/net/ethernet/qualcomm/Makefile:1\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c:5\ndrivers/net/ethernet/qualcomm/emac/emac-mac.h:5\ndrivers/net/ethernet/qualcomm/emac/emac-sgmii.c:4\ndrivers/net/ethernet/qualcomm/emac/emac.h:2\ndrivers/net/ethernet/qualcomm/ppe/Makefile:2\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:29\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:16\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:561\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.h:141\ndrivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c:204\ndrivers/net/ethernet/qualcomm/ppe/ppe_debugfs.h:3\ndrivers/net/ethernet/qualcomm/ppe/ppe_regs.h:513\n\ndrivers/net/ethernet/qualcomm/Kconfig=50=config QCOM_EMAC\n--\ndrivers/net/ethernet/qualcomm/Kconfig-62-\ndrivers/net/ethernet/qualcomm/Kconfig:63:config QCOM_PPE\ndrivers/net/ethernet/qualcomm/Kconfig:64:\ttristate \"Qualcomm PPE Ethernet support\"\ndrivers/net/ethernet/qualcomm/Kconfig-65-\tdepends on COMMON_CLK \u0026\u0026 HAS_IOMEM \u0026\u0026 OF\n--\ndrivers/net/ethernet/qualcomm/Kconfig-69-\t  This driver supports the Qualcomm Technologies, Inc. packet\ndrivers/net/ethernet/qualcomm/Kconfig:70:\t  process engine (PPE) available with IPQ SoC. The PPE includes\ndrivers/net/ethernet/qualcomm/Kconfig-71-\t  the Ethernet MACs, Ethernet DMA (EDMA) and switch core that\n--\ndrivers/net/ethernet/qualcomm/Makefile=12=obj-y += emac/\ndrivers/net/ethernet/qualcomm/Makefile-13-\ndrivers/net/ethernet/qualcomm/Makefile:14:obj-$(CONFIG_QCOM_PPE) += ppe/\ndrivers/net/ethernet/qualcomm/Makefile-15-obj-$(CONFIG_RMNET) += rmnet/\n--\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c-200-\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c:201:/* EMAC_EMAC_WRAPPER_TX_TS_INX */\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c:202:#define EMAC_WRAPPER_TX_TS_EMPTY                               BIT(31)\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c:203:#define EMAC_WRAPPER_TX_TS_INX_BMSK                             0xffff\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c-204-\n--\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c=481=static void emac_mac_start(struct emac_adapter *adpt)\n--\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c-493-\tmac = readl(adpt-\u003ebase + EMAC_MAC_CTRL);\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c:494:\tcsr1 = readl(adpt-\u003ecsr + EMAC_EMAC_WRAPPER_CSR1);\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c-495-\n--\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c-557-\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c:558:\twritel_relaxed(csr1, adpt-\u003ecsr + EMAC_EMAC_WRAPPER_CSR1);\ndrivers/net/ethernet/qualcomm/emac/emac-mac.c-559-\n--\ndrivers/net/ethernet/qualcomm/emac/emac-mac.h-18-/* EMAC_CSR register offsets */\ndrivers/net/ethernet/qualcomm/emac/emac-mac.h:19:#define EMAC_EMAC_WRAPPER_CSR1                                0x000000\ndrivers/net/ethernet/qualcomm/emac/emac-mac.h:20:#define EMAC_EMAC_WRAPPER_CSR2                                0x000004\ndrivers/net/ethernet/qualcomm/emac/emac-mac.h:21:#define EMAC_EMAC_WRAPPER_TX_TS_LO                            0x000104\ndrivers/net/ethernet/qualcomm/emac/emac-mac.h:22:#define EMAC_EMAC_WRAPPER_TX_TS_HI                            0x000108\ndrivers/net/ethernet/qualcomm/emac/emac-mac.h:23:#define EMAC_EMAC_WRAPPER_TX_TS_INX                           0x00010c\ndrivers/net/ethernet/qualcomm/emac/emac-mac.h-24-\n--\ndrivers/net/ethernet/qualcomm/emac/emac-sgmii.c=181=static void emac_sgmii_reset_prepare(struct emac_adapter *adpt)\n--\ndrivers/net/ethernet/qualcomm/emac/emac-sgmii.c-186-\t/* Reset PHY */\ndrivers/net/ethernet/qualcomm/emac/emac-sgmii.c:187:\tval = readl(phy-\u003ebase + EMAC_EMAC_WRAPPER_CSR2);\ndrivers/net/ethernet/qualcomm/emac/emac-sgmii.c-188-\twritel(((val \u0026 ~PHY_RESET) | PHY_RESET), phy-\u003ebase +\ndrivers/net/ethernet/qualcomm/emac/emac-sgmii.c:189:\t       EMAC_EMAC_WRAPPER_CSR2);\ndrivers/net/ethernet/qualcomm/emac/emac-sgmii.c-190-\t/* Ensure phy-reset command is written to HW before the release cmd */\ndrivers/net/ethernet/qualcomm/emac/emac-sgmii.c-191-\tmsleep(50);\ndrivers/net/ethernet/qualcomm/emac/emac-sgmii.c:192:\tval = readl(phy-\u003ebase + EMAC_EMAC_WRAPPER_CSR2);\ndrivers/net/ethernet/qualcomm/emac/emac-sgmii.c:193:\twritel((val \u0026 ~PHY_RESET), phy-\u003ebase + EMAC_EMAC_WRAPPER_CSR2);\ndrivers/net/ethernet/qualcomm/emac/emac-sgmii.c-194-\t/* Ensure phy-reset release command is written to HW before initializing\n--\ndrivers/net/ethernet/qualcomm/emac/emac.h-155-\ndrivers/net/ethernet/qualcomm/emac/emac.h:156:/* EMAC_EMAC_WRAPPER_CSR1 */\ndrivers/net/ethernet/qualcomm/emac/emac.h-157-#define TX_INDX_FIFO_SYNC_RST                                  BIT(23)\n--\ndrivers/net/ethernet/qualcomm/emac/emac.h-165-\ndrivers/net/ethernet/qualcomm/emac/emac.h:166:/* EMAC_EMAC_WRAPPER_CSR2 */\ndrivers/net/ethernet/qualcomm/emac/emac.h-167-#define HDRIVE_BMSK                                             0x3000\n--\ndrivers/net/ethernet/qualcomm/ppe/Makefile-2-#\ndrivers/net/ethernet/qualcomm/ppe/Makefile:3:# Makefile for the device driver of PPE (Packet Process Engine) in IPQ SoC\ndrivers/net/ethernet/qualcomm/ppe/Makefile-4-#\ndrivers/net/ethernet/qualcomm/ppe/Makefile-5-\ndrivers/net/ethernet/qualcomm/ppe/Makefile:6:obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o\ndrivers/net/ethernet/qualcomm/ppe/Makefile-7-qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-5-\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:6:/* PPE platform device probe, DTSI parser and PPE clock initializations. */\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-7-\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-20-\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:21:#define IPQ9574_PPE_CLK_RATE\t353000000\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:22:#define IPQ5424_PPE_CLK_RATE\t375000000\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-23-\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-24-/* 6 physical ports, 1 EDMA FIFO and 1 EIP FIFO. */\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:25:#define IPQ9574_PPE_PORT_MAX\t\t8\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-26-/* 3 physical ports and 1 EDMA FIFO. */\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:27:#define IPQ5424_PPE_PORT_MAX\t\t4\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-28-\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-29-/**\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:30: * struct ppe_of_data - PPE private data of IPQ SoC\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:31: * @type: PPE type value\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:32: * @ppe_rate: PPE clock rate\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:33: * @num_ports: Number of PPE ports\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-34- * @regmap_config: Regmap configuration\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:35: * @icc_paths: Interconnect paths per PPE type\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-36- * @num_icc_paths: Number of ICC paths\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c=38=struct ppe_of_data {\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-46-\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:47:/* ICC clocks for enabling PPE device. The avg_bw and peak_bw with value 0\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:48: * will be updated by the clock rate of PPE.\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-49- */\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c=190=static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev,\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-204-\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:205:\t\t/* PPE does not have an explicit peak bandwidth requirement,\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-206-\t\t * so set the peak bandwidth to be equal to the average\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-221-\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:222:\t/* The PPE clocks have a common parent clock. Setting the clock\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:223:\t * rate of \"ppe\" ensures the clock rate of all PPE clocks is\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-224-\t * configured to the same rate.\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-237-\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:238:\t/* Reset the PPE. */\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-239-\trstc = devm_reset_control_get_exclusive(dev, NULL);\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-246-\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:247:\t/* The delay 10 ms of assert is necessary for resetting PPE. */\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-248-\tusleep_range(10000, 11000);\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c=253=static int qcom_ppe_probe(struct platform_device *pdev)\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-262-\tif (!data)\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:263:\t\treturn dev_err_probe(dev, -EINVAL, \"PPE no match data provided\\n\");\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-264-\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-272-\tif (IS_ERR(base))\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:273:\t\treturn dev_err_probe(dev, PTR_ERR(base), \"PPE ioremap failed\\n\");\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-274-\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-277-\t\treturn dev_err_probe(dev, PTR_ERR(ppe_dev-\u003eregmap),\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:278:\t\t\t\t     \"PPE initialize regmap failed\\n\");\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-279-\tppe_dev-\u003edev = dev;\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-286-\tif (ret)\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:287:\t\treturn dev_err_probe(dev, ret, \"PPE clock config failed\\n\");\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-288-\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-290-\tif (ret)\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:291:\t\treturn dev_err_probe(dev, ret, \"PPE HW config failed\\n\");\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-292-\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c=307=static const struct ppe_of_data ipq9574_data = {\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:308:\t.type = IPQ9574_PPE,\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:309:\t.ppe_rate = IPQ9574_PPE_CLK_RATE,\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:310:\t.num_ports = IPQ9574_PPE_PORT_MAX,\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-311-\t.regmap_config = \u0026regmap_config_ipq9574,\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c=316=static const struct ppe_of_data ipq5424_data = {\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:317:\t.type = IPQ5424_PPE,\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:318:\t.ppe_rate = IPQ5424_PPE_CLK_RATE,\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:319:\t.num_ports = IPQ5424_PPE_PORT_MAX,\ndrivers/net/ethernet/qualcomm/ppe/ppe.c-320-\t.regmap_config = \u0026regmap_config_ipq5424,\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.c=342=MODULE_LICENSE(\"GPL\");\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:343:MODULE_DESCRIPTION(\"Qualcomm Technologies, Inc. IPQ PPE driver\");\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.h-5-\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:6:#ifndef __PPE_H__\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:7:#define __PPE_H__\ndrivers/net/ethernet/qualcomm/ppe/ppe.h-8-\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.h=14=struct dentry;\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.h-16-/**\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:17: * enum ppe_type - PPE device type.\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:18: * @IPQ9574_PPE: PPE device of IPQ9574.\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:19: * @IPQ5424_PPE: PPE device of IPQ5424.\ndrivers/net/ethernet/qualcomm/ppe/ppe.h-20- *\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:21: * PPE type is used to identify the PPE device of the different\ndrivers/net/ethernet/qualcomm/ppe/ppe.h-22- * IPQ platform.\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.h=24=enum ppe_type {\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:25:\tIPQ9574_PPE,\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:26:\tIPQ5424_PPE,\ndrivers/net/ethernet/qualcomm/ppe/ppe.h-27-};\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.h-29-/**\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:30: * struct ppe_device - PPE device private data.\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:31: * @dev: PPE device structure.\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:32: * @regmap: PPE register map.\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:33: * @type: Different PPE type on various IPQ SoC.\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:34: * @clk_rate: PPE clock rate.\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:35: * @num_ports: Number of PPE ports.\ndrivers/net/ethernet/qualcomm/ppe/ppe.h-36- * @debugfs_root: Debugfs root entry.\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe.h-39- *\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:40: * PPE device is the instance of PPE hardware, which is used to\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:41: * configure PPE packet process modules such as BM (buffer management),\ndrivers/net/ethernet/qualcomm/ppe/ppe.h-42- * QM (queue management), and scheduler.\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-5-\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:6:/* PPE HW initialization configs such as BM(buffer management),\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-7- * QM(queue management) and scheduler configs.\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-19-\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:20:#define PPE_QUEUE_SCH_PRI_NUM\t\t8\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-21-\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-22-/**\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:23: * struct ppe_bm_port_config - PPE BM port configuration.\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-24- * @port_id_start: The fist BM port ID to configure.\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c=37=struct ppe_bm_port_config {\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-49-/**\n\n"
}

5/2 2026/10/08 19:44 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 29907
							output: 39
							thoughts: 24
						

Thoughts:
Here's a summary of my thought process, tailored for an expert like you:

**Diving into the Qualcomm Ethernet Configuration**

Okay, so I need to zero in on the Qualcomm Ethernet configuration. Specifically, I should start by looking at `drivers/net/ethernet/qualcomm/Kconfig`. That's the logical place to start for any kernel configuration settings related to Qualcomm Ethernet drivers. I'm going to jump to line 63 or thereabouts. Chances are, this line or the lines surrounding it will define some key options or dependencies. I'm expecting to find conditional compilation options, maybe some hardware feature enablement flags, or perhaps dependencies on other Qualcomm-specific components. That section is usually a good starting point to understand which features are enabled, disabled, and how they relate to the overall Ethernet driver configuration within the Qualcomm platform. I'm hoping it's well-commented, as that will speed things up significantly. Let's see what we find!



6/2 2026/10/08 19:44 tool read-file
0m Args:
{
  "File": "drivers/net/ethernet/qualcomm/Kconfig",
  "FirstLine": 60,
  "LineCount": 25
}

Results:
{
  "Contents": "  60:\t\t  low power, Receive-Side Scaling (RSS), and IEEE 1588-2008\n  61:\t\t  Precision Clock Synchronization Protocol.\n  62:\t\n  63:\tconfig QCOM_PPE\n  64:\t\ttristate \"Qualcomm PPE Ethernet support\"\n  65:\t\tdepends on COMMON_CLK \u0026\u0026 HAS_IOMEM \u0026\u0026 OF\n  66:\t\tdepends on ARCH_QCOM || COMPILE_TEST\n  67:\t\tselect REGMAP_MMIO\n  68:\t\thelp\n  69:\t\t  This driver supports the Qualcomm Technologies, Inc. packet\n  70:\t\t  process engine (PPE) available with IPQ SoC. The PPE includes\n  71:\t\t  the Ethernet MACs, Ethernet DMA (EDMA) and switch core that\n  72:\t\t  supports L3 flow offload, L2 switch function, RSS and tunnel\n  73:\t\t  offload.\n  74:\t\n  75:\t\t  To compile this driver as a module, choose M here. The module\n  76:\t\t  will be called qcom-ppe.\n  77:\t\n  78:\tsource \"drivers/net/ethernet/qualcomm/rmnet/Kconfig\"\n  79:\t\n  80:\tendif # NET_VENDOR_QUALCOMM\n"
}

7/2 2026/10/08 19:44 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 30501
							output: 43
							thoughts: 177
						

Thoughts:
**Analyzing the `qcom_ppe` Device**

Okay, so I'm looking at this `qcom_ppe` device and I need to quickly determine its nature. The first thing I'll do is confirm that it's a platform device, most likely discovered through the Device Tree. I see the `qcom_ppe_of_match[]` table which looks like a classic Device Tree match table. The presence of `compatible` strings like "qcom,ipq9574-ppe" and "qcom,ipq5424-ppe" strongly suggests Device Tree probing. These compatible strings likely point to specific SoCs or board revisions. The `.data` field associated with each compatible string is a pointer to device-specific data structs like `ipq9574_data` and `ipq5424_data`. So far, so good, a standard Device Tree platform device setup.

Next, I'll need to dive into `ppe.c` and take a look at the `qcom_ppe_driver` structure. This will provide the details of the driver itself: its probe and remove functions, supported device IDs, and so on. Understanding the driver structure is crucial to understand the device interaction.



8/2 2026/10/08 19:44 tool read-file
0m Args:
{
  "File": "drivers/net/ethernet/qualcomm/ppe/ppe.c",
  "FirstLine": 320,
  "LineCount": 40
}

Results:
{
  "Contents": " 320:\t\t.regmap_config = \u0026regmap_config_ipq5424,\n 321:\t\t.icc_paths = ipq5424_ppe_icc_data,\n 322:\t\t.num_icc_paths = ARRAY_SIZE(ipq5424_ppe_icc_data),\n 323:\t};\n 324:\t\n 325:\tstatic const struct of_device_id qcom_ppe_of_match[] = {\n 326:\t\t{ .compatible = \"qcom,ipq9574-ppe\", .data = \u0026ipq9574_data },\n 327:\t\t{ .compatible = \"qcom,ipq5424-ppe\", .data = \u0026ipq5424_data },\n 328:\t\t{}\n 329:\t};\n 330:\tMODULE_DEVICE_TABLE(of, qcom_ppe_of_match);\n 331:\t\n 332:\tstatic struct platform_driver qcom_ppe_driver = {\n 333:\t\t.driver = {\n 334:\t\t\t.name = \"qcom_ppe\",\n 335:\t\t\t.of_match_table = qcom_ppe_of_match,\n 336:\t\t},\n 337:\t\t.probe\t= qcom_ppe_probe,\n 338:\t\t.remove = qcom_ppe_remove,\n 339:\t};\n 340:\tmodule_platform_driver(qcom_ppe_driver);\n 341:\t\n 342:\tMODULE_LICENSE(\"GPL\");\n 343:\tMODULE_DESCRIPTION(\"Qualcomm Technologies, Inc. IPQ PPE driver\");\n"
}

9/2 2026/10/08 19:44 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 31426
							output: 27
							thoughts: 71
						

Thoughts:
Here's my take on those thoughts:

**Investigating the qcom_ppe_driver**

Okay, so `qcom_ppe_driver` is definitely interesting. It's a platform driver that's getting matched up through Device Tree, specifically using the "qcom,ipq9574-ppe" and "qcom,ipq5424-ppe" compatible strings. That gives me a good starting point, but I need to understand the wider scope of this. I'm thinking, are there any *other* places in the kernel using functions that start with `ppe_*`? That prefix is a pretty good indicator of its function space. Time to do a quick sweep of the code base. I need to get a handle on the entire landscape of `ppe_*` interactions before I dive deeper into this specific driver. Knowledge is power.



10/2 2026/10/08 19:44 tool grepper
0m Args:
{
  "Expression": "ppe_",
  "PathPrefixes": [
    "drivers/net/"
  ]
}

Results:
{
  "Output": "\nFull output is too long, showing 200 out of 4836 lines.\nUse more precise expression or PathPrefixes if possible.\n\nNumber of matching lines per file (66 files in total):\ndrivers/net/ethernet/airoha/Makefile:1\ndrivers/net/ethernet/airoha/airoha_eth.c:17\ndrivers/net/ethernet/airoha/airoha_eth.h:14\ndrivers/net/ethernet/airoha/airoha_npu.c:66\ndrivers/net/ethernet/airoha/airoha_ppe.c:193\ndrivers/net/ethernet/airoha/airoha_ppe_debugfs.c:22\ndrivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c:38\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c:1\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c:14\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h:22\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c:7\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c:214\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h:26\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c:16\ndrivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h:4\ndrivers/net/ethernet/mediatek/Makefile:1\ndrivers/net/ethernet/mediatek/mtk_eth_soc.c:32\ndrivers/net/ethernet/mediatek/mtk_eth_soc.h:4\ndrivers/net/ethernet/mediatek/mtk_ppe.c:78\ndrivers/net/ethernet/mediatek/mtk_ppe.h:11\ndrivers/net/ethernet/mediatek/mtk_ppe_debugfs.c:10\ndrivers/net/ethernet/mediatek/mtk_ppe_offload.c:11\ndrivers/net/ethernet/mediatek/mtk_wed.c:3\ndrivers/net/ethernet/qualcomm/ppe/Makefile:1\ndrivers/net/ethernet/qualcomm/ppe/ppe.c:76\ndrivers/net/ethernet/qualcomm/ppe/ppe.h:5\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:228\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.h:37\ndrivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c:122\ndrivers/net/ethernet/qualcomm/ppe/ppe_debugfs.h:2\ndrivers/net/ethernet/qualcomm/ppe/ppe_regs.h:25\ndrivers/net/ppp/ppp_mppe.c:64\ndrivers/net/wireless/ath/ath11k/core.h:3\ndrivers/net/wireless/ath/ath11k/mac.c:7\ndrivers/net/wireless/ath/ath11k/wmi.c:3\ndrivers/net/wireless/ath/ath11k/wmi.h:8\ndrivers/net/wireless/ath/ath12k/core.h:4\ndrivers/net/wireless/ath/ath12k/hal.h:1\ndrivers/net/wireless/ath/ath12k/mac.c:18\ndrivers/net/wireless/ath/ath12k/wifi7/hal.h:1\ndrivers/net/wireless/ath/ath12k/wifi7/hal_desc.h:3\ndrivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c:1\ndrivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c:5\ndrivers/net/wireless/ath/ath12k/wifi7/hal_rx_desc.h:1\ndrivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c:1\ndrivers/net/wireless/ath/ath12k/wmi.c:2\ndrivers/net/wireless/ath/ath12k/wmi.h:11\ndrivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c:4\ndrivers/net/wireless/intel/iwlwifi/mld/sta.c:18\ndrivers/net/wireless/intel/iwlwifi/mvm/mac80211.c:18\n... and 16 more files\n\ndrivers/net/ethernet/airoha/Makefile=7=airoha-eth-y := airoha_eth.o airoha_ppe.o\ndrivers/net/ethernet/airoha/Makefile:8:airoha-eth-$(CONFIG_DEBUG_FS) += airoha_ppe_debugfs.o\ndrivers/net/ethernet/airoha/Makefile-9-obj-$(CONFIG_NET_AIROHA_NPU) += airoha_npu.o\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=76=static int airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-142-\ndrivers/net/ethernet/airoha/airoha_eth.c:143:\tairoha_ppe_init_upd_mem(dev, addr);\ndrivers/net/ethernet/airoha/airoha_eth.c-144-\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=326=static void airoha_fe_pse_ports_init(struct airoha_eth *eth)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-342-\ndrivers/net/ethernet/airoha/airoha_eth.c:343:\tif (airoha_ppe_is_enabled(eth, 1)) {\ndrivers/net/ethernet/airoha/airoha_eth.c-344-\t\tu32 all_rsv;\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-387-\t\t\t\t\t PSE_QUEUE_RSV_PAGES);\ndrivers/net/ethernet/airoha/airoha_eth.c:388:\tif (airoha_ppe_is_enabled(eth, 1)) {\ndrivers/net/ethernet/airoha/airoha_eth.c-389-\t\t/* PPE2 */\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=880=static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-979-\t\tif (reason == PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)\ndrivers/net/ethernet/airoha/airoha_eth.c:980:\t\t\tairoha_ppe_check_skb(\u0026eth-\u003eppe-\u003edev, q-\u003eskb, hash,\ndrivers/net/ethernet/airoha/airoha_eth.c-981-\t\t\t\t\t     false);\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=1848=static int airoha_hw_init(struct platform_device *pdev,\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-1877-\ndrivers/net/ethernet/airoha/airoha_eth.c:1878:\terr = airoha_ppe_init(eth);\ndrivers/net/ethernet/airoha/airoha_eth.c-1879-\tif (err)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=1892=static void airoha_hw_cleanup(struct airoha_eth *eth)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-1897-\t\tairoha_qdma_cleanup(eth, \u0026eth-\u003eqdma[i]);\ndrivers/net/ethernet/airoha/airoha_eth.c:1898:\tairoha_ppe_deinit(eth);\ndrivers/net/ethernet/airoha/airoha_eth.c-1899-}\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=2163=static void airoha_dev_set_xmit_frame_size(struct net_device *netdev)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-2166-\ndrivers/net/ethernet/airoha/airoha_eth.c:2167:\tairoha_ppe_set_xmit_frame_size(dev);\ndrivers/net/ethernet/airoha/airoha_eth.c-2168-\tif (!airoha_is_lan_gdm_dev(dev))\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=2174=static int airoha_dev_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-2212-\tif (!airoha_is_lan_gdm_dev(dev) \u0026\u0026\ndrivers/net/ethernet/airoha/airoha_eth.c:2213:\t    airoha_ppe_is_enabled(qdma-\u003eeth, 1))\ndrivers/net/ethernet/airoha/airoha_eth.c-2214-\t\tpse_port = FE_PSE_PORT_PPE2;\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=2224=static int airoha_dev_stop(struct net_device *netdev)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-2232-\tif (--port-\u003eusers)\ndrivers/net/ethernet/airoha/airoha_eth.c:2233:\t\tairoha_ppe_set_xmit_frame_size(dev);\ndrivers/net/ethernet/airoha/airoha_eth.c-2234-\telse\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=2264=static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-2309-\tfor (i = 0; i \u003c eth-\u003esoc-\u003enum_ppe; i++)\ndrivers/net/ethernet/airoha/airoha_eth.c:2310:\t\tairoha_ppe_set_cpu_port(dev, i, AIROHA_GDM2_IDX);\ndrivers/net/ethernet/airoha/airoha_eth.c-2311-\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=2322=static int airoha_disable_gdm2_loopback(struct airoha_gdm_dev *dev)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-2342-\t\t\tLPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK);\ndrivers/net/ethernet/airoha/airoha_eth.c:2343:\tpse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2\ndrivers/net/ethernet/airoha/airoha_eth.c-2344-\t\t\t\t\t\t : FE_PSE_PORT_PPE1;\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=2392=static void airoha_dev_set_qdma(struct airoha_gdm_dev *dev)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-2396-\tstruct airoha_eth *eth = dev-\u003eeth;\ndrivers/net/ethernet/airoha/airoha_eth.c:2397:\tint i, ppe_id;\ndrivers/net/ethernet/airoha/airoha_eth.c-2398-\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-2412-\ndrivers/net/ethernet/airoha/airoha_eth.c:2413:\tppe_id = !airoha_is_lan_gdm_dev(dev) \u0026\u0026 airoha_ppe_is_enabled(eth, 1);\ndrivers/net/ethernet/airoha/airoha_eth.c:2414:\tairoha_ppe_set_cpu_port(dev, ppe_id, airoha_get_fe_port(dev));\ndrivers/net/ethernet/airoha/airoha_eth.c-2415-\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=3394=static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type,\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-3405-\tcase TC_SETUP_CLSFLOWER:\ndrivers/net/ethernet/airoha/airoha_eth.c:3406:\t\treturn airoha_ppe_setup_tc_block_cb(\u0026eth-\u003eppe-\u003edev, type_data);\ndrivers/net/ethernet/airoha/airoha_eth.c-3407-\tcase TC_SETUP_CLSMATCHALL:\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=3489=static void airoha_disable_qos_for_gdm34(struct net_device *netdev)\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-3507-\tairoha_set_macaddr(dev, netdev-\u003edev_addr);\ndrivers/net/ethernet/airoha/airoha_eth.c:3508:\tairoha_ppe_set_xmit_frame_size(dev);\ndrivers/net/ethernet/airoha/airoha_eth.c-3509-\n--\ndrivers/net/ethernet/airoha/airoha_eth.c=3516=static int airoha_enable_qos_for_gdm34(struct net_device *netdev,\n--\ndrivers/net/ethernet/airoha/airoha_eth.c-3560-\ndrivers/net/ethernet/airoha/airoha_eth.c:3561:\t\tpse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2\ndrivers/net/ethernet/airoha/airoha_eth.c-3562-\t\t\t\t\t\t\t : FE_PSE_PORT_PPE1;\n--\ndrivers/net/ethernet/airoha/airoha_eth.h=629=struct airoha_ppe {\ndrivers/net/ethernet/airoha/airoha_eth.h:630:\tstruct airoha_ppe_dev dev;\ndrivers/net/ethernet/airoha/airoha_eth.h-631-\tstruct airoha_eth *eth;\n--\ndrivers/net/ethernet/airoha/airoha_eth.h=751=airoha_qdma_deref(struct airoha_gdm_dev *dev)\n--\ndrivers/net/ethernet/airoha/airoha_eth.h-757-\ndrivers/net/ethernet/airoha/airoha_eth.h:758:void airoha_ppe_set_xmit_frame_size(struct airoha_gdm_dev *dev);\ndrivers/net/ethernet/airoha/airoha_eth.h:759:void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport);\ndrivers/net/ethernet/airoha/airoha_eth.h:760:bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index);\ndrivers/net/ethernet/airoha/airoha_eth.h:761:void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,\ndrivers/net/ethernet/airoha/airoha_eth.h-762-\t\t\t  u16 hash, bool rx_wlan);\ndrivers/net/ethernet/airoha/airoha_eth.h:763:int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data);\ndrivers/net/ethernet/airoha/airoha_eth.h:764:int airoha_ppe_init(struct airoha_eth *eth);\ndrivers/net/ethernet/airoha/airoha_eth.h:765:void airoha_ppe_deinit(struct airoha_eth *eth);\ndrivers/net/ethernet/airoha/airoha_eth.h:766:void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev, const u8 *addr);\ndrivers/net/ethernet/airoha/airoha_eth.h:767:u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe);\ndrivers/net/ethernet/airoha/airoha_eth.h:768:struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,\ndrivers/net/ethernet/airoha/airoha_eth.h-769-\t\t\t\t\t\t  u32 hash);\ndrivers/net/ethernet/airoha/airoha_eth.h:770:void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash,\ndrivers/net/ethernet/airoha/airoha_eth.h-771-\t\t\t\t    struct airoha_foe_stats64 *stats);\n--\ndrivers/net/ethernet/airoha/airoha_eth.h-773-#ifdef CONFIG_DEBUG_FS\ndrivers/net/ethernet/airoha/airoha_eth.h:774:int airoha_ppe_debugfs_init(struct airoha_ppe *ppe);\ndrivers/net/ethernet/airoha/airoha_eth.h-775-#else\ndrivers/net/ethernet/airoha/airoha_eth.h:776:static inline int airoha_ppe_debugfs_init(struct airoha_ppe *ppe)\ndrivers/net/ethernet/airoha/airoha_eth.h-777-{\n--\ndrivers/net/ethernet/airoha/airoha_npu.c=116=struct airoha_npu_soc_data {\n--\ndrivers/net/ethernet/airoha/airoha_npu.c-129-\ndrivers/net/ethernet/airoha/airoha_npu.c:130:struct ppe_mbox_data {\ndrivers/net/ethernet/airoha/airoha_npu.c-131-\tu32 func_type;\n--\ndrivers/net/ethernet/airoha/airoha_npu.c-140-\t\t\tu8 rsv[3];\ndrivers/net/ethernet/airoha/airoha_npu.c:141:\t\t\tu32 ppe_type;\ndrivers/net/ethernet/airoha/airoha_npu.c-142-\t\t\tu32 wan_mode;\n--\ndrivers/net/ethernet/airoha/airoha_npu.c=319=static irqreturn_t airoha_npu_wdt_handler(int irq, void *core_instance)\n--\ndrivers/net/ethernet/airoha/airoha_npu.c-333-\ndrivers/net/ethernet/airoha/airoha_npu.c:334:static int airoha_npu_ppe_init(struct airoha_npu *npu)\ndrivers/net/ethernet/airoha/airoha_npu.c-335-{\ndrivers/net/ethernet/airoha/airoha_npu.c:336:\tstruct ppe_mbox_data *ppe_data;\ndrivers/net/ethernet/airoha/airoha_npu.c-337-\tint err;\ndrivers/net/ethernet/airoha/airoha_npu.c-338-\ndrivers/net/ethernet/airoha/airoha_npu.c:339:\tppe_data = kzalloc_obj(*ppe_data);\ndrivers/net/ethernet/airoha/airoha_npu.c:340:\tif (!ppe_data)\ndrivers/net/ethernet/airoha/airoha_npu.c-341-\t\treturn -ENOMEM;\ndrivers/net/ethernet/airoha/airoha_npu.c-342-\ndrivers/net/ethernet/airoha/airoha_npu.c:343:\tppe_data-\u003efunc_type = NPU_OP_SET;\ndrivers/net/ethernet/airoha/airoha_npu.c:344:\tppe_data-\u003efunc_id = PPE_FUNC_SET_WAIT_HWNAT_INIT;\ndrivers/net/ethernet/airoha/airoha_npu.c:345:\tppe_data-\u003einit_info.ppe_type = PPE_TYPE_L2B_IPV4_IPV6;\ndrivers/net/ethernet/airoha/airoha_npu.c:346:\tppe_data-\u003einit_info.wan_mode = QDMA_WAN_ETHER;\ndrivers/net/ethernet/airoha/airoha_npu.c-347-\ndrivers/net/ethernet/airoha/airoha_npu.c:348:\terr = airoha_npu_send_msg(npu, NPU_FUNC_PPE, ppe_data,\ndrivers/net/ethernet/airoha/airoha_npu.c:349:\t\t\t\t  sizeof(*ppe_data));\ndrivers/net/ethernet/airoha/airoha_npu.c:350:\tkfree(ppe_data);\ndrivers/net/ethernet/airoha/airoha_npu.c-351-\n--\ndrivers/net/ethernet/airoha/airoha_npu.c-354-\ndrivers/net/ethernet/airoha/airoha_npu.c:355:static int airoha_npu_ppe_deinit(struct airoha_npu *npu)\ndrivers/net/ethernet/airoha/airoha_npu.c-356-{\ndrivers/net/ethernet/airoha/airoha_npu.c:357:\tstruct ppe_mbox_data *ppe_data;\ndrivers/net/ethernet/airoha/airoha_npu.c-358-\tint err;\ndrivers/net/ethernet/airoha/airoha_npu.c-359-\ndrivers/net/ethernet/airoha/airoha_npu.c:360:\tppe_data = kzalloc_obj(*ppe_data);\ndrivers/net/ethernet/airoha/airoha_npu.c:361:\tif (!ppe_data)\ndrivers/net/ethernet/airoha/airoha_npu.c-362-\t\treturn -ENOMEM;\ndrivers/net/ethernet/airoha/airoha_npu.c-363-\ndrivers/net/ethernet/airoha/airoha_npu.c:364:\tppe_data-\u003efunc_type = NPU_OP_SET;\ndrivers/net/ethernet/airoha/airoha_npu.c:365:\tppe_data-\u003efunc_id = PPE_FUNC_SET_WAIT_HWNAT_DEINIT;\ndrivers/net/ethernet/airoha/airoha_npu.c-366-\ndrivers/net/ethernet/airoha/airoha_npu.c:367:\terr = airoha_npu_send_msg(npu, NPU_FUNC_PPE, ppe_data,\ndrivers/net/ethernet/airoha/airoha_npu.c:368:\t\t\t\t  sizeof(*ppe_data));\ndrivers/net/ethernet/airoha/airoha_npu.c:369:\tkfree(ppe_data);\ndrivers/net/ethernet/airoha/airoha_npu.c-370-\n--\ndrivers/net/ethernet/airoha/airoha_npu.c-373-\ndrivers/net/ethernet/airoha/airoha_npu.c:374:static int airoha_npu_ppe_flush_sram_entries(struct airoha_npu *npu,\ndrivers/net/ethernet/airoha/airoha_npu.c-375-\t\t\t\t\t     dma_addr_t foe_addr,\n--\ndrivers/net/ethernet/airoha/airoha_npu.c-377-{\ndrivers/net/ethernet/airoha/airoha_npu.c:378:\tstruct ppe_mbox_data *ppe_data;\ndrivers/net/ethernet/airoha/airoha_npu.c-379-\tint err;\ndrivers/net/ethernet/airoha/airoha_npu.c-380-\ndrivers/net/ethernet/airoha/airoha_npu.c:381:\tppe_data = kzalloc_obj(*ppe_data);\ndrivers/net/ethernet/airoha/airoha_npu.c:382:\tif (!ppe_data)\ndrivers/net/ethernet/airoha/airoha_npu.c-383-\t\treturn -ENOMEM;\ndrivers/net/ethernet/airoha/airoha_npu.c-384-\ndrivers/net/ethernet/airoha/airoha_npu.c:385:\tppe_data-\u003efunc_type = NPU_OP_SET;\ndrivers/net/ethernet/airoha/airoha_npu.c:386:\tppe_data-\u003efunc_id = PPE_FUNC_SET_WAIT_API;\ndrivers/net/ethernet/airoha/airoha_npu.c:387:\tppe_data-\u003eset_info.func_id = PPE_SRAM_RESET_VAL;\ndrivers/net/ethernet/airoha/airoha_npu.c:388:\tppe_data-\u003eset_info.data = foe_addr;\ndrivers/net/ethernet/airoha/airoha_npu.c:389:\tppe_data-\u003eset_info.size = sram_num_entries;\ndrivers/net/ethernet/airoha/airoha_npu.c-390-\ndrivers/net/ethernet/airoha/airoha_npu.c:391:\terr = airoha_npu_send_msg(npu, NPU_FUNC_PPE, ppe_data,\ndrivers/net/ethernet/airoha/airoha_npu.c:392:\t\t\t\t  sizeof(*ppe_data));\ndrivers/net/ethernet/airoha/airoha_npu.c:393:\tkfree(ppe_data);\ndrivers/net/ethernet/airoha/airoha_npu.c-394-\n--\ndrivers/net/ethernet/airoha/airoha_npu.c=398=static int airoha_npu_foe_commit_entry(struct airoha_npu *npu,\n--\n\n"
}

11/2 2026/10/08 19:44 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 38619
							output: 21
							thoughts: 65
						

Thoughts:
Here's my thinking process:

**Diving into the PPE Implementation**

Alright, so I need to understand how this PPE (Packet Processing Engine, I assume) is being used. Let's start with the header files. `ppe.h` – that's the core. I remember seeing `struct ppe_device` defined there, and functions like `ppe_port_resource_get`. It's a pretty standard approach, defining the structures and interfaces in the header.

My next move is obvious: I need to trace the usage of those functions and the structures. Where are these `ppe_port_resource_get` calls happening? Where is `struct ppe_device` being instantiated and used? I’m going to search the codebase for calls to the functions declared in `ppe.h` and also `ppe_config.h`, if applicable. That will give me the crucial context I need to figure out the data flow and overall architecture related to the PPE. I’m thinking this will unveil the relationships between the different PPE components. I'll probably also look for where the struct is allocated, and freed.



12/2 2026/10/08 19:44 tool grepper
0m Args:
{
  "Expression": "ppe_port_resource_get"
}

Results:
{
  "Output": "drivers/net/ethernet/qualcomm/ppe/ppe_config.c=1382=int ppe_queue_ucast_offset_hash_set(struct ppe_device *ppe_dev,\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-1397-/**\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:1398: * ppe_port_resource_get - Get PPE resource per port\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-1399- * @ppe_dev: PPE device\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-1408- */\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:1409:int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-1410-\t\t\t  enum ppe_resource_type type,\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c=2124=static int ppe_queue_dest_init(struct ppe_device *ppe_dev)\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-2131-\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:2132:\t\tret = ppe_port_resource_get(ppe_dev, port_id, PPE_RES_UCAST,\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-2133-\t\t\t\t\t    \u0026res_start, \u0026res_end);\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-2148-\t\t/* Queue priority range supported by each PPE port */\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:2149:\t\tret = ppe_port_resource_get(ppe_dev, port_id, PPE_RES_L0_NODE,\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-2150-\t\t\t\t\t    \u0026res_start, \u0026res_end);\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c=2313=static int ppe_queues_to_ring_init(struct ppe_device *ppe_dev)\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-2317-\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:2318:\tret = ppe_port_resource_get(ppe_dev, 0, PPE_RES_UCAST,\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-2319-\t\t\t\t    \u0026queue_id, \u0026queue_max);\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.h=306=int ppe_queue_ucast_offset_hash_set(struct ppe_device *ppe_dev,\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.h-309-\t\t\t\t    int queue_offset);\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.h:310:int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.h-311-\t\t\t  enum ppe_resource_type type,\n"
}

13/2 2026/10/08 19:44 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 39821
							output: 21
							thoughts: 15
						

Thoughts:
Here's a summary of my thought process:

**Investigating `ppe_sc_config_set` Usage**

Okay, so I've encountered `ppe_sc_config_set`... My immediate impulse is to understand its scope. Let's not just assume its significance; let's see where this function is actually being *used*. A quick cross-reference check is absolutely necessary. It's the most efficient way to understand its dependencies and overall role within the system. We need to identify the call sites.



14/2 2026/10/08 19:44 tool grepper
0m Args:
{
  "Expression": "ppe_sc_config_set"
}

Results:
{
  "Output": "drivers/net/ethernet/qualcomm/ppe/ppe_config.c=1409=int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-1466-/**\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:1467: * ppe_sc_config_set - Set PPE service code configuration\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-1468- * @ppe_dev: PPE device\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-1476- */\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:1477:int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, struct ppe_sc_cfg cfg)\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-1478-{\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c=2198=static int ppe_servcode_init(struct ppe_device *ppe_dev)\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-2212-\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c:2213:\treturn ppe_sc_config_set(ppe_dev, PPE_EDMA_SC_BYPASS_ID, sc_cfg);\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.c-2214-}\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.h=310=int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,\n--\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.h-312-\t\t\t  int *res_start, int *res_end);\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.h:313:int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc,\ndrivers/net/ethernet/qualcomm/ppe/ppe_config.h-314-\t\t      struct ppe_sc_cfg cfg);\n"
}

15/2 2026/10/08 19:44 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 40550
							output: 36
							thoughts: 1052
						

Thoughts:
**Reaching the Qualcomm PPE: A Dead End for Fuzzing**

Okay, let's break this down. My primary concern is whether this `qcom_ppe_probe` function, and by extension the `qcom_ppe` driver, is reachable and therefore worth fuzzing, based on the requirements. I'm seeing it's a probe function for a platform driver, specifically for Qualcomm's packet process engine (PPE). This PPE is tied to IPQ SoCs – networking-focused chips like the IPQ9574 and IPQ5424. The driver's description nails it; this is about offloading functions like L3 flows, L2 switching, RSS, and tunnel offload using the hardware.

My first thought is, is this hardware even present or emulated in the virtual environments we're working with, specifically GCE or QEMU? And that's where the instructions become critical. Section 1 explicitly states that we can only focus on code that *can* execute in these standard virtualized environments. Section 2 gives clear "negative criteria" - cases where we must return `WorthFuzzing=false`. And here's where it clicks.

The target architecture is amd64, and the driver depends on `ARCH_QCOM` (ARM/Qualcomm) and OF (Device Tree) for matching. I know Qualcomm SoCs rely heavily on Device Tree for configuration, so this is critical. I'm thinking, can this platform driver *ever* probe or execute on `amd64` in GCE or QEMU? Absolutely not. On amd64, `ARCH_QCOM` is not defined, so OF matching for Qualcomm devices won't happen. Even if we could get it to *build* with `COMPILE_TEST`, it's useless because GCE and QEMU on amd64 don't, by default, have the Qualcomm IPQ9574 or IPQ5424 device tree node or hardware present!

Furthermore, a closer look at `ppe.c` confirms this. We're talking about direct hardware access - `ioremap`, clock controls (`devm_clk_get`), interconnects, and reset controls – all hallmarks of a dedicated on-chip hardware peripheral, a *SoC peripheral*, on these Qualcomm chips. This is not something that can be emulated or instantiated on a standard x86_64 or amd64 virtual machine! QEMU on amd64 does not simulate this.

Given all of this, I need to ensure there are no other entry points to this code, but I highly doubt there are. This is a dead end. Therefore, I need to return `WorthFuzzing=false`.



16/2 2026/10/08 19:44 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "EXPORT_SYMBOL",
  "PathPrefixes": [
    "drivers/net/ethernet/qualcomm/ppe/"
  ]
}

Results:
{
  "error": "no matches"
}

17/2 2026/10/08 19:44 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 42230
							output: 139
							thoughts: 976
						

Thoughts:
**Analysis of PPE Driver Reachability for Fuzzing**

Okay, here's the breakdown. I've examined the `drivers/net/ethernet/qualcomm/ppe/` directory and it's immediately clear: *zero* exported symbols. This whole driver, `qcom-ppe.ko`, is internal. The only entry point is `qcom_ppe_driver`, registered as a `module_platform_driver`. That's the first red flag.

Diving deeper, this driver specifically targets `"qcom,ipq9574-ppe"` and `"qcom,ipq5424-ppe"` compatible devices. *That* means it *must* have a device tree node instantiation to work, which is IPQ9574/IPQ5424 SoCs - hardware or good emulation. Since `qcom_ppe_probe` *never* gets to run without that hardware, nothing else in that driver – `ppe_config_*`, `ppe_debugfs_*`, nothing – will ever be touched.

Then I checked the architecture, this is built for `ARCH_QCOM`, which is ARM. This is running on `amd64`. Even on ARM, the standard virtualization setups (GCE, QEMU's virt machine) *do not* emulate the Qualcomm IPQ9574/5424 PPE hardware, with the necessary interconnects, reset controllers, clocks, etc. So even if I *could* get the driver built and loaded on ARM in a virtual environment, it still couldn't *work*. And on `amd64`, it's just completely unreachable.

I went back and re-read the guidelines. Section 1 says that reachability is *the* primary gate. We can only fuzz code that *can* execute in a standard virtual environment with software-emulated devices. Section 2 confirms: if code is structurally unreachable, it is *not* fuzzed.

Here's what I've got: I'm adding support for Qualcomm IPQ5424 SoC, updating devicetree bindings, and documentation changes. The core code changes are within `drivers/net/ethernet/qualcomm/ppe/*`. This is the Qualcomm Packet Process Engine (PPE) driver, designed for those specific IPQ SoCs (`ARCH_QCOM`). This hardware is embedded, SoC-specific hardware and not emulated in the standard virtual environments (QEMU, GCE) in this system. That means it’s structurally unreachable on `amd64`. It's only reachable in an environment with the needed hardware, which isn't present.

So, the conclusion is clear. `WorthFuzzing` must be false. The `FocusSymbols` are empty, `EnableConfigs` are empty and I have a clear explanation, which covers how the hardware is specific to Qualcomm IPQ SoCs, the driver is platform, and the hardware is not emulated in standard environments. This hardware is not reachable. Now it's time to invoke `set-results`.



18/2 2026/10/08 19:45 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch adds support for the Qualcomm IPQ5424 SoC to the Qualcomm Packet Process Engine (PPE) network driver and updates DeviceTree bindings and documentation. This is a platform driver for dedicated SoC hardware (ARCH_QCOM) requiring specific physical ASIC peripherals (clocks, interconnects, reset controllers) that are not emulated in standard virtualized environments (QEMU/GCE on amd64). Because the driver cannot probe or execute on amd64, the changes are structurally unreachable and not worth fuzzing.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch adds support for the Qualcomm IPQ5424 SoC to the Qualcomm Packet Process Engine (PPE) network driver and updates DeviceTree bindings and documentation. This is a platform driver for dedicated SoC hardware (ARCH_QCOM) requiring specific physical ASIC peripherals (clocks, interconnects, reset controllers) that are not emulated in standard virtualized environments (QEMU/GCE on amd64). Because the driver cannot probe or execute on amd64, the changes are structurally unreachable and not worth fuzzing.",
  "WorthFuzzing": false
}

19/1 2026/10/08 19:45 action If
0m Args:
{
  "WorthFuzzing": false
}

Results:
null

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)