--- /dev/null
+From a355002e08a1db55eec93f469d28cfaab7b60f4b Mon Sep 17 00:00:00 2001
+From: Luo Jie <quic_luoj@quicinc.com>
+Date: Thu, 22 May 2025 11:16:12 +0800
+Subject: [PATCH] net: qualcomm: Update IPQ9574 PPE driver
+
+Update PPE driver to keep aligned with the upstream patches. The
+updated PPE driver also fix some known issues such as GRO/GSO/TSO
+issue for the performance improvement.
+
+Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
+Alex G: print error code when failing to connect phylink
+Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
+---
+ drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +-
+ drivers/net/ethernet/qualcomm/ppe/edma.c | 158 +---
+ drivers/net/ethernet/qualcomm/ppe/edma.h | 27 +-
+ .../net/ethernet/qualcomm/ppe/edma_cfg_rx.c | 138 ++--
+ .../net/ethernet/qualcomm/ppe/edma_cfg_rx.h | 5 +-
+ .../net/ethernet/qualcomm/ppe/edma_cfg_tx.c | 22 +-
+ .../net/ethernet/qualcomm/ppe/edma_cfg_tx.h | 2 +-
+ .../net/ethernet/qualcomm/ppe/edma_debugfs.c | 2 +-
+ .../net/ethernet/qualcomm/ppe/edma_ethtool.c | 31 +-
+ drivers/net/ethernet/qualcomm/ppe/edma_port.c | 20 +-
+ drivers/net/ethernet/qualcomm/ppe/edma_port.h | 4 +-
+ drivers/net/ethernet/qualcomm/ppe/edma_rx.c | 65 +-
+ drivers/net/ethernet/qualcomm/ppe/edma_rx.h | 2 +-
+ drivers/net/ethernet/qualcomm/ppe/edma_tx.c | 98 ++-
+ drivers/net/ethernet/qualcomm/ppe/edma_tx.h | 16 +-
+ drivers/net/ethernet/qualcomm/ppe/ppe.c | 4 +-
+ drivers/net/ethernet/qualcomm/ppe/ppe.h | 2 +
+ drivers/net/ethernet/qualcomm/ppe/ppe_api.c | 113 +++
+ drivers/net/ethernet/qualcomm/ppe/ppe_api.h | 43 ++
+ .../net/ethernet/qualcomm/ppe/ppe_config.c | 81 +-
+ .../net/ethernet/qualcomm/ppe/ppe_config.h | 2 -
+ drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 707 ++++++++++--------
+ drivers/net/ethernet/qualcomm/ppe/ppe_port.h | 24 +-
+ drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 78 +-
+ 24 files changed, 889 insertions(+), 757 deletions(-)
+ create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_api.c
+ create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_api.h
+
+--- a/drivers/net/ethernet/qualcomm/ppe/Makefile
++++ b/drivers/net/ethernet/qualcomm/ppe/Makefile
+@@ -4,7 +4,7 @@
+ #
+
+ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o
+-qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o
++qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o ppe_api.o
+
+ #EDMA
+ qcom-ppe-objs += edma.o edma_cfg_rx.o edma_cfg_tx.o edma_debugfs.o edma_port.o edma_rx.o edma_tx.o edma_ethtool.o
+--- a/drivers/net/ethernet/qualcomm/ppe/edma.c
++++ b/drivers/net/ethernet/qualcomm/ppe/edma.c
+@@ -1,5 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+- /* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ /* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ /* Qualcomm Ethernet DMA driver setup, HW configuration, clocks and
+@@ -121,7 +121,7 @@ static struct edma_hw_info ipq9574_hw_in
+ .tx = &ipq9574_tx_ring_info,
+ .txcmpl = &ipq9574_txcmpl_ring_info,
+ .max_ports = 6,
+- .napi_budget_rx = 128,
++ .napi_budget_rx = 32,
+ .napi_budget_tx = 512,
+ };
+
+@@ -156,13 +156,12 @@ static int edma_clock_set_and_enable(str
+ }
+
+ of_node_put(edma_np);
+-
+ dev_dbg(dev, "set %lu rate for %s\n", rate, id);
+
+ return 0;
+ }
+
+-static int edma_clock_init(void)
++static int edma_clock_configure(void)
+ {
+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev;
+ struct device *dev = ppe_dev->dev;
+@@ -181,6 +180,8 @@ static int edma_clock_init(void)
+ if (ret)
+ return ret;
+
++ dev_dbg(dev, "EDMA clocks are configured\n");
++
+ return 0;
+ }
+
+@@ -245,7 +246,7 @@ static int edma_configure_ucast_prio_map
+ }
+
+ ret = ppe_edma_queue_offset_config(edma_ctx->ppe_dev,
+- PPE_QUEUE_CLASS_PRIORITY, int_pri, pri_class);
++ PPE_QUEUE_OFFSET_BY_PRIORITY, int_pri, pri_class);
+
+ if (ret) {
+ pr_err("Failed with error: %d to set queue priority class for int_pri: %d for profile_id: %d\n",
+@@ -480,7 +481,7 @@ txcmpl_ring_irq_name_alloc_fail:
+ return ret;
+ }
+
+-static int edma_irq_init(void)
++static int edma_irq_configure(void)
+ {
+ struct edma_hw_info *hw_info = edma_ctx->hw_info;
+ struct edma_ring_info *txcmpl = hw_info->txcmpl;
+@@ -588,44 +589,23 @@ static int edma_hw_reset(void)
+ struct device *dev = ppe_dev->dev;
+ struct reset_control *edma_hw_rst;
+ struct device_node *edma_np;
+- const char *reset_string;
+- u32 count, i;
+- int ret;
+
+- /* Count and parse reset names from DTSI. */
+ edma_np = of_get_child_by_name(dev->of_node, EDMA_NODE_NAME);
+- count = of_property_count_strings(edma_np, "reset-names");
+- if (count < 0) {
+- dev_err(dev, "EDMA reset entry not found\n");
++ edma_hw_rst = of_reset_control_get_exclusive(edma_np, NULL);
++ if (IS_ERR(edma_hw_rst)) {
+ of_node_put(edma_np);
+- return -EINVAL;
++ return PTR_ERR(edma_hw_rst);
+ }
+
+- for (i = 0; i < count; i++) {
+- ret = of_property_read_string_index(edma_np, "reset-names",
+- i, &reset_string);
+- if (ret) {
+- dev_err(dev, "Error reading reset-names");
+- of_node_put(edma_np);
+- return -EINVAL;
+- }
+-
+- edma_hw_rst = of_reset_control_get_exclusive(edma_np, reset_string);
+- if (IS_ERR(edma_hw_rst)) {
+- of_node_put(edma_np);
+- return PTR_ERR(edma_hw_rst);
+- }
+-
+- /* 100ms delay is required by hardware to reset EDMA. */
+- reset_control_assert(edma_hw_rst);
+- fsleep(100);
++ /* 100ms delay is required by hardware to reset EDMA. */
++ reset_control_assert(edma_hw_rst);
++ fsleep(100);
+
+- reset_control_deassert(edma_hw_rst);
+- fsleep(100);
++ reset_control_deassert(edma_hw_rst);
++ fsleep(100);
+
+- reset_control_put(edma_hw_rst);
+- dev_dbg(dev, "EDMA HW reset, i:%d reset_string:%s\n", i, reset_string);
+- }
++ reset_control_put(edma_hw_rst);
++ dev_dbg(dev, "EDMA HW reset\n");
+
+ of_node_put(edma_np);
+
+@@ -647,14 +627,12 @@ static int edma_hw_configure(void)
+
+ pr_debug("EDMA ver %d hw init\n", data);
+
+- /* Setup private data structure. */
+ edma_ctx->intr_info.intr_mask_rx = EDMA_RXDESC_INT_MASK_PKT_INT;
+ edma_ctx->intr_info.intr_mask_txcmpl = EDMA_TX_INT_MASK_PKT_INT;
+
+- /* Reset EDMA. */
+ ret = edma_hw_reset();
+ if (ret) {
+- pr_err("Error in resetting the hardware. ret: %d\n", ret);
++ pr_err("Error in resetting the hardware, ret: %d\n", ret);
+ return ret;
+ }
+
+@@ -668,7 +646,7 @@ static int edma_hw_configure(void)
+ edma_ctx->dummy_dev = alloc_netdev_dummy(0);
+ if (!edma_ctx->dummy_dev) {
+ ret = -ENOMEM;
+- pr_err("Failed to allocate dummy device. ret: %d\n", ret);
++ pr_err("Failed to allocate dummy device, ret: %d\n", ret);
+ goto dummy_dev_alloc_failed;
+ }
+
+@@ -682,7 +660,7 @@ static int edma_hw_configure(void)
+
+ ret = edma_alloc_rings();
+ if (ret) {
+- pr_err("Error in initializaing the rings. ret: %d\n", ret);
++ pr_err("Error in initializing the rings, ret: %d\n", ret);
+ goto edma_alloc_rings_failed;
+ }
+
+@@ -702,7 +680,7 @@ static int edma_hw_configure(void)
+
+ ret = edma_cfg_rx_rings();
+ if (ret) {
+- pr_err("Error in configuring Rx rings. ret: %d\n", ret);
++ pr_err("Error in configuring Rx rings, ret: %d\n", ret);
+ goto edma_cfg_rx_rings_failed;
+ }
+
+@@ -720,15 +698,13 @@ static int edma_hw_configure(void)
+ if (ret)
+ return ret;
+
+- /* Configure Tx Timeout Threshold. */
+ data = EDMA_TX_TIMEOUT_THRESH_VAL;
+-
+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_TIMEOUT_THRESH_ADDR;
+ ret = regmap_write(regmap, reg, data);
+ if (ret)
+ return ret;
+
+- /* Set Miscellaneous error mask. */
++ /* Set Miscellaneous error interrupt mask. */
+ data = EDMA_MISC_AXI_RD_ERR_MASK |
+ EDMA_MISC_AXI_WR_ERR_MASK |
+ EDMA_MISC_RX_DESC_FIFO_FULL_MASK |
+@@ -743,15 +719,15 @@ static int edma_hw_configure(void)
+ edma_cfg_rx_napi_add();
+ edma_cfg_rx_napi_enable();
+
+- /* Global EDMA enable and padding enable. */
++ /* Enable whole edma to work and padding if packet length less than 60
++ * byte in EDMA port interface control register.
++ */
+ data = EDMA_PORT_PAD_EN | EDMA_PORT_EDMA_EN;
+-
+ reg = EDMA_BASE_OFFSET + EDMA_REG_PORT_CTRL_ADDR;
+ ret = regmap_write(regmap, reg, data);
+ if (ret)
+ return ret;
+
+- /* Initialize unicast priority map table. */
+ ret = (int)edma_configure_ucast_prio_map_tbl();
+ if (ret) {
+ pr_err("Failed to initialize unicast priority map table: %d\n",
+@@ -759,7 +735,6 @@ static int edma_hw_configure(void)
+ goto configure_ucast_prio_map_tbl_failed;
+ }
+
+- /* Initialize RPS hash map table. */
+ ret = edma_cfg_rx_rps_hash_map();
+ if (ret) {
+ pr_err("Failed to configure rps hash table: %d\n",
+@@ -767,6 +742,8 @@ static int edma_hw_configure(void)
+ goto edma_cfg_rx_rps_hash_map_failed;
+ }
+
++ pr_info("EDMA Hardware Configured\n");
++
+ return 0;
+
+ edma_cfg_rx_rps_hash_map_failed:
+@@ -803,14 +780,13 @@ void edma_destroy(struct ppe_device *ppe
+ edma_ctx->rx_rps_ctl_table_hdr = NULL;
+ }
+
+- /* Disable interrupts. */
+ for (i = 1; i <= hw_info->max_ports; i++)
+ edma_cfg_tx_disable_interrupts(i);
+
+ edma_cfg_rx_disable_interrupts();
+ edma_disable_misc_interrupt();
+
+- /* Free IRQ for TXCMPL rings. */
++ /* Free IRQ for Tx cmpl rings. */
+ for (i = 0; i < txcmpl->num_rings; i++) {
+ synchronize_irq(edma_ctx->intr_info.intr_txcmpl[i]);
+
+@@ -820,7 +796,7 @@ void edma_destroy(struct ppe_device *ppe
+ }
+ kfree(edma_txcmpl_irq_name);
+
+- /* Free IRQ for RXDESC rings */
++ /* Free IRQ for Rx DESC rings */
+ for (i = 0; i < rx->num_rings; i++) {
+ synchronize_irq(edma_ctx->intr_info.intr_rx[i]);
+ free_irq(edma_ctx->intr_info.intr_rx[i],
+@@ -861,7 +837,7 @@ static struct ctl_table edma_rx_rps_core
+ * edma_setup - EDMA Setup.
+ * @ppe_dev: PPE device
+ *
+- * Configure Ethernet global ctx, clocks, hardware and interrupts.
++ * Configure EDMA global context, clocks, hardware and interrupts.
+ *
+ * Return 0 on success, negative error code on failure.
+ */
+@@ -889,22 +865,19 @@ int edma_setup(struct ppe_device *ppe_de
+ return -EINVAL;
+ }
+
+- /* Configure the EDMA common clocks. */
+- ret = edma_clock_init();
++ ret = edma_clock_configure();
+ if (ret) {
+ dev_err(dev, "Error in configuring the EDMA clocks\n");
+ return ret;
+ }
+
+- dev_dbg(dev, "QCOM EDMA common clocks are configured\n");
+-
+ ret = edma_hw_configure();
+ if (ret) {
+ dev_err(dev, "Error in edma configuration\n");
+ return ret;
+ }
+
+- ret = edma_irq_init();
++ ret = edma_irq_configure();
+ if (ret) {
+ dev_err(dev, "Error in irq initialization\n");
+ return ret;
+@@ -925,70 +898,3 @@ int edma_setup(struct ppe_device *ppe_de
+
+ return 0;
+ }
+-
+-/**
+- * ppe_edma_queue_offset_config - Configure queue offset for EDMA interface
+- * @ppe_dev: PPE device
+- * @class: The class to configure queue offset
+- * @index: Class index, internal priority or hash value
+- * @queue_offset: Queue offset value
+- *
+- * PPE EDMA queue offset is configured based on the PPE internal priority or
+- * RSS hash value, the profile ID is fixed to 0 for EDMA interface.
+- *
+- * Return 0 on success, negative error code on failure.
+- */
+-int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev,
+- enum ppe_queue_class_type class,
+- int index, int queue_offset)
+-{
+- if (class == PPE_QUEUE_CLASS_PRIORITY)
+- return ppe_queue_ucast_offset_pri_set(ppe_dev, 0,
+- index, queue_offset);
+-
+- return ppe_queue_ucast_offset_hash_set(ppe_dev, 0,
+- index, queue_offset);
+-}
+-
+-/**
+- * ppe_edma_queue_resource_get - Get EDMA queue resource
+- * @ppe_dev: PPE device
+- * @type: Resource type
+- * @res_start: Resource start ID returned
+- * @res_end: Resource end ID returned
+- *
+- * PPE EDMA queue resource includes unicast queue and multicast queue.
+- *
+- * Return 0 on success, negative error code on failure.
+- */
+-int ppe_edma_queue_resource_get(struct ppe_device *ppe_dev, int type,
+- int *res_start, int *res_end)
+-{
+- if (type != PPE_RES_UCAST && type != PPE_RES_MCAST)
+- return -EINVAL;
+-
+- return ppe_port_resource_get(ppe_dev, 0, type, res_start, res_end);
+-};
+-
+-/**
+- * ppe_edma_ring_to_queues_config - Map EDMA ring to PPE queues
+- * @ppe_dev: PPE device
+- * @ring_id: EDMA ring ID
+- * @num: Number of queues mapped to EDMA ring
+- * @queues: PPE queue IDs
+- *
+- * PPE queues are configured to map with the special EDMA ring ID.
+- *
+- * Return 0 on success, negative error code on failure.
+- */
+-int ppe_edma_ring_to_queues_config(struct ppe_device *ppe_dev, int ring_id,
+- int num, int queues[] __counted_by(num))
+-{
+- u32 queue_bmap[PPE_RING_TO_QUEUE_BITMAP_WORD_CNT] = {};
+- int index;
+-
+- for (index = 0; index < num; index++)
+- queue_bmap[queues[index] / 32] |= BIT_MASK(queues[index] % 32);
+-
+- return ppe_ring_queue_map_set(ppe_dev, ring_id, queue_bmap);
+-}
+--- a/drivers/net/ethernet/qualcomm/ppe/edma.h
++++ b/drivers/net/ethernet/qualcomm/ppe/edma.h
+@@ -1,13 +1,13 @@
+ /* SPDX-License-Identifier: GPL-2.0-only
+- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #ifndef __EDMA_MAIN__
+ #define __EDMA_MAIN__
+
+-#include "ppe_config.h"
+ #include "edma_rx.h"
+ #include "edma_tx.h"
++#include "ppe_api.h"
+
+ /* One clock cycle = 1/(EDMA clock frequency in Mhz) micro seconds.
+ *
+@@ -37,16 +37,6 @@
+ (max)) & ((max) - 1)); })
+
+ /**
+- * enum ppe_queue_class_type - PPE queue class type
+- * @PPE_QUEUE_CLASS_PRIORITY: Queue offset configured from internal priority
+- * @PPE_QUEUE_CLASS_HASH: Queue offset configured from RSS hash.
+- */
+-enum ppe_queue_class_type {
+- PPE_QUEUE_CLASS_PRIORITY,
+- PPE_QUEUE_CLASS_HASH,
+-};
+-
+-/**
+ * struct edma_err_stats - EDMA error stats
+ * @edma_axi_read_err: AXI read error
+ * @edma_axi_write_err: AXI write error
+@@ -123,7 +113,7 @@ struct edma_intr_info {
+ /**
+ * struct edma_context - EDMA context.
+ * @netdev_arr: Net device for each EDMA port
+- * @dummy_dev: Dummy netdevice for RX DMA
++ * @dummy_dev: Dummy netdevice for Rx DMA
+ * @ppe_dev: PPE device
+ * @hw_info: EDMA Hardware info
+ * @intr_info: EDMA Interrupt info
+@@ -154,7 +144,7 @@ struct edma_context {
+ bool tx_requeue_stop;
+ };
+
+-/* Global EDMA context */
++/* Global EDMA context. */
+ extern struct edma_context *edma_ctx;
+
+ int edma_err_stats_alloc(void);
+@@ -164,13 +154,4 @@ int edma_setup(struct ppe_device *ppe_de
+ void edma_debugfs_teardown(void);
+ int edma_debugfs_setup(struct ppe_device *ppe_dev);
+ void edma_set_ethtool_ops(struct net_device *netdev);
+-int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev,
+- enum ppe_queue_class_type class,
+- int index, int queue_offset);
+-int ppe_edma_queue_resource_get(struct ppe_device *ppe_dev, int type,
+- int *res_start, int *res_end);
+-int ppe_edma_ring_to_queues_config(struct ppe_device *ppe_dev, int ring_id,
+- int num, int queues[] __counted_by(num));
+-
+-
+ #endif
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c
+@@ -1,5 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+-/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++/* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ /* Configure rings, Buffers and NAPI for receive path along with
+@@ -19,9 +19,6 @@
+ #include "ppe.h"
+ #include "ppe_regs.h"
+
+-/* EDMA Queue ID to Ring ID Table. */
+-#define EDMA_QID2RID_TABLE_MEM(q) (0xb9000 + (0x4 * (q)))
+-
+ /* Rx ring queue offset. */
+ #define EDMA_QUEUE_OFFSET(q_id) ((q_id) / EDMA_MAX_PRI_PER_CORE)
+
+@@ -32,6 +29,9 @@
+ /* EDMA Queue ID to Ring ID configuration. */
+ #define EDMA_QID2RID_NUM_PER_REG 4
+
++/* EDMA Queue ID to Ring ID Table. */
++#define EDMA_QID2RID_TABLE_MEM(q) (0xb9000 + (0x4 * (q)))
++
+ int rx_queues[] = {0, 8, 16, 24};
+
+ static u32 edma_rx_ring_queue_map[][EDMA_MAX_CORE] = {{ 0, 8, 16, 24 },
+@@ -75,7 +75,7 @@ static int edma_cfg_rx_desc_ring_reset_q
+ for (i = 0; i < EDMA_MAX_PRI_PER_CORE; i++) {
+ queue_id = edma_rx_ring_queue_map[i][rxdesc_ring_idx];
+
+- ret = ppe_queue_priority_set(edma_ctx->ppe_dev, queue_id, i);
++ ret = ppe_queue_node_priority_set(edma_ctx->ppe_dev, queue_id, i);
+ if (ret) {
+ pr_err("Error in resetting %u queue's priority\n",
+ queue_id);
+@@ -138,7 +138,7 @@ static int edma_cfg_rx_desc_ring_to_queu
+ pr_err("Error in configuring Rx ring to PPE queue mapping, ret: %d, id: %d\n",
+ ret, rxdesc_ring->ring_id);
+ if (!edma_cfg_rx_desc_rings_reset_queue_mapping())
+- pr_err("Error in resetting Rx desc ringbackpressure configurations\n");
++ pr_err("Error in resetting Rx desc ring configurations\n");
+
+ return ret;
+ }
+@@ -219,7 +219,9 @@ static void edma_cfg_rx_qid_to_rx_desc_r
+
+ desc_index = (rx->ring_start & EDMA_RX_RING_ID_MASK);
+
+- /* Here map all the queues to ring. */
++ /* There are 4 Rx desc rings, one for each core.
++ * Map the unicast queues to Rx desc rings.
++ */
+ for (q_id = EDMA_RX_QUEUE_START;
+ q_id <= EDMA_CPU_PORT_QUEUE_MAX(EDMA_RX_QUEUE_START);
+ q_id += EDMA_QID2RID_NUM_PER_REG) {
+@@ -271,6 +273,11 @@ static void edma_cfg_rx_rings_to_rx_fill
+ struct edma_ring_info *rx = hw_info->rx;
+ u32 i, data, reg;
+
++ /* Set RXDESC2FILL_MAP_xx reg.
++ * 3 registers hold the Rxfill mapping for all Rx desc rings.
++ * 3 bits holds the Rx fill ring mapping for each of the
++ * Rx descriptor ring.
++ */
+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_0_ADDR, 0);
+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_1_ADDR, 0);
+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_2_ADDR, 0);
+@@ -326,7 +333,6 @@ void edma_cfg_rx_rings_enable(void)
+ struct edma_ring_info *rx = hw_info->rx;
+ u32 i, reg;
+
+- /* Enable Rx rings */
+ for (i = rx->ring_start; i < rx->ring_start + rx->num_rings; i++) {
+ u32 data;
+
+@@ -445,7 +451,6 @@ static int edma_cfg_rx_fill_ring_dma_all
+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev;
+ struct device *dev = ppe_dev->dev;
+
+- /* Allocate RxFill ring descriptors */
+ rxfill_ring->desc = dma_alloc_coherent(dev, (sizeof(struct edma_rxfill_desc)
+ * rxfill_ring->count),
+ &rxfill_ring->dma,
+@@ -633,6 +638,62 @@ rxdesc_mem_alloc_fail:
+ return -ENOMEM;
+ }
+
++static void edma_cfg_rx_fill_ring_configure(struct edma_rxfill_ring *rxfill_ring)
++{
++ struct ppe_device *ppe_dev = edma_ctx->ppe_dev;
++ struct regmap *regmap = ppe_dev->regmap;
++ u32 ring_sz, reg;
++
++ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_BA(rxfill_ring->ring_id);
++ regmap_write(regmap, reg, (u32)(rxfill_ring->dma & EDMA_RING_DMA_MASK));
++
++ ring_sz = rxfill_ring->count & EDMA_RXFILL_RING_SIZE_MASK;
++ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_RING_SIZE(rxfill_ring->ring_id);
++ regmap_write(regmap, reg, ring_sz);
++
++ edma_rx_alloc_buffer(rxfill_ring, rxfill_ring->count - 1);
++}
++
++static void edma_cfg_rx_desc_ring_flow_control(u32 threshold_xoff, u32 threshold_xon)
++{
++ struct edma_hw_info *hw_info = edma_ctx->hw_info;
++ struct ppe_device *ppe_dev = edma_ctx->ppe_dev;
++ struct regmap *regmap = ppe_dev->regmap;
++ struct edma_ring_info *rx = hw_info->rx;
++ u32 data, i, reg;
++
++ data = (threshold_xoff & EDMA_RXDESC_FC_XOFF_THRE_MASK) << EDMA_RXDESC_FC_XOFF_THRE_SHIFT;
++ data |= ((threshold_xon & EDMA_RXDESC_FC_XON_THRE_MASK) << EDMA_RXDESC_FC_XON_THRE_SHIFT);
++
++ for (i = 0; i < rx->num_rings; i++) {
++ struct edma_rxdesc_ring *rxdesc_ring;
++
++ rxdesc_ring = &edma_ctx->rx_rings[i];
++ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_FC_THRE(rxdesc_ring->ring_id);
++ regmap_write(regmap, reg, data);
++ }
++}
++
++static void edma_cfg_rx_fill_ring_flow_control(int threshold_xoff, int threshold_xon)
++{
++ struct edma_hw_info *hw_info = edma_ctx->hw_info;
++ struct edma_ring_info *rxfill = hw_info->rxfill;
++ struct ppe_device *ppe_dev = edma_ctx->ppe_dev;
++ struct regmap *regmap = ppe_dev->regmap;
++ u32 data, i, reg;
++
++ data = (threshold_xoff & EDMA_RXFILL_FC_XOFF_THRE_MASK) << EDMA_RXFILL_FC_XOFF_THRE_SHIFT;
++ data |= ((threshold_xon & EDMA_RXFILL_FC_XON_THRE_MASK) << EDMA_RXFILL_FC_XON_THRE_SHIFT);
++
++ for (i = 0; i < rxfill->num_rings; i++) {
++ struct edma_rxfill_ring *rxfill_ring;
++
++ rxfill_ring = &edma_ctx->rxfill_rings[i];
++ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_FC_THRE(rxfill_ring->ring_id);
++ regmap_write(regmap, reg, data);
++ }
++}
++
+ /**
+ * edma_cfg_rx_buff_size_setup - Configure EDMA Rx jumbo buffer
+ *
+@@ -729,62 +790,6 @@ void edma_cfg_rx_rings_cleanup(void)
+ edma_ctx->rx_rings = NULL;
+ }
+
+-static void edma_cfg_rx_fill_ring_configure(struct edma_rxfill_ring *rxfill_ring)
+-{
+- struct ppe_device *ppe_dev = edma_ctx->ppe_dev;
+- struct regmap *regmap = ppe_dev->regmap;
+- u32 ring_sz, reg;
+-
+- reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_BA(rxfill_ring->ring_id);
+- regmap_write(regmap, reg, (u32)(rxfill_ring->dma & EDMA_RING_DMA_MASK));
+-
+- ring_sz = rxfill_ring->count & EDMA_RXFILL_RING_SIZE_MASK;
+- reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_RING_SIZE(rxfill_ring->ring_id);
+- regmap_write(regmap, reg, ring_sz);
+-
+- edma_rx_alloc_buffer(rxfill_ring, rxfill_ring->count - 1);
+-}
+-
+-static void edma_cfg_rx_desc_ring_flow_control(u32 threshold_xoff, u32 threshold_xon)
+-{
+- struct edma_hw_info *hw_info = edma_ctx->hw_info;
+- struct ppe_device *ppe_dev = edma_ctx->ppe_dev;
+- struct regmap *regmap = ppe_dev->regmap;
+- struct edma_ring_info *rx = hw_info->rx;
+- u32 data, i, reg;
+-
+- data = (threshold_xoff & EDMA_RXDESC_FC_XOFF_THRE_MASK) << EDMA_RXDESC_FC_XOFF_THRE_SHIFT;
+- data |= ((threshold_xon & EDMA_RXDESC_FC_XON_THRE_MASK) << EDMA_RXDESC_FC_XON_THRE_SHIFT);
+-
+- for (i = 0; i < rx->num_rings; i++) {
+- struct edma_rxdesc_ring *rxdesc_ring;
+-
+- rxdesc_ring = &edma_ctx->rx_rings[i];
+- reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_FC_THRE(rxdesc_ring->ring_id);
+- regmap_write(regmap, reg, data);
+- }
+-}
+-
+-static void edma_cfg_rx_fill_ring_flow_control(int threshold_xoff, int threshold_xon)
+-{
+- struct edma_hw_info *hw_info = edma_ctx->hw_info;
+- struct edma_ring_info *rxfill = hw_info->rxfill;
+- struct ppe_device *ppe_dev = edma_ctx->ppe_dev;
+- struct regmap *regmap = ppe_dev->regmap;
+- u32 data, i, reg;
+-
+- data = (threshold_xoff & EDMA_RXFILL_FC_XOFF_THRE_MASK) << EDMA_RXFILL_FC_XOFF_THRE_SHIFT;
+- data |= ((threshold_xon & EDMA_RXFILL_FC_XON_THRE_MASK) << EDMA_RXFILL_FC_XON_THRE_SHIFT);
+-
+- for (i = 0; i < rxfill->num_rings; i++) {
+- struct edma_rxfill_ring *rxfill_ring;
+-
+- rxfill_ring = &edma_ctx->rxfill_rings[i];
+- reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_FC_THRE(rxfill_ring->ring_id);
+- regmap_write(regmap, reg, data);
+- }
+-}
+-
+ /**
+ * edma_cfg_rx_rings - Configure EDMA Rx rings.
+ *
+@@ -917,6 +922,7 @@ void edma_cfg_rx_napi_delete(void)
+ if (!rxdesc_ring->napi_added)
+ continue;
+
++ napi_disable(&rxdesc_ring->napi);
+ netif_napi_del(&rxdesc_ring->napi);
+ rxdesc_ring->napi_added = false;
+ }
+@@ -978,7 +984,7 @@ int edma_cfg_rx_rps_hash_map(void)
+
+ for (hash = 0; hash < PPE_QUEUE_HASH_NUM; hash++) {
+ ret = ppe_edma_queue_offset_config(edma_ctx->ppe_dev,
+- PPE_QUEUE_CLASS_HASH, hash, q_map[idx]);
++ PPE_QUEUE_OFFSET_BY_HASH, hash, q_map[idx]);
+ if (ret)
+ return ret;
+
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h
+@@ -1,5 +1,5 @@
+ /* SPDX-License-Identifier: GPL-2.0-only
+- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #ifndef __EDMA_CFG_RX__
+@@ -28,6 +28,7 @@
+
+ /* Rx AC flow control default threshold */
+ #define EDMA_RX_AC_FC_THRES_DEF 0x104
++
+ /* Rx mitigation timer's default value in microseconds */
+ #define EDMA_RX_MITIGATION_TIMER_DEF 25
+
+@@ -66,7 +67,7 @@ void edma_cfg_rx_rings_enable(void);
+ void edma_cfg_rx_rings_disable(void);
+ void edma_cfg_rx_buff_size_setup(void);
+ int edma_cfg_rx_rps_hash_map(void);
+-int edma_cfg_rx_rps(const struct ctl_table *table, int write,
++int edma_cfg_rx_rps(struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos);
+ int edma_cfg_rx_rps_bitmap(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos);
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.c
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.c
+@@ -1,5 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+-/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++/* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ /* Configure rings, Buffers and NAPI for transmit path along with
+@@ -27,7 +27,7 @@ static void edma_cfg_txcmpl_ring_cleanup
+ /* Free any buffers assigned to any descriptors. */
+ edma_tx_complete(EDMA_TX_RING_SIZE - 1, txcmpl_ring);
+
+- /* Free TxCmpl ring descriptors. */
++ /* Free Tx cmpl ring descriptors. */
+ dma_free_coherent(dev, sizeof(struct edma_txcmpl_desc)
+ * txcmpl_ring->count, txcmpl_ring->desc,
+ txcmpl_ring->dma);
+@@ -101,7 +101,6 @@ static int edma_cfg_tx_desc_ring_setup(s
+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev;
+ struct device *dev = ppe_dev->dev;
+
+- /* Allocate RxFill ring descriptors. */
+ txdesc_ring->pdesc = dma_alloc_coherent(dev, sizeof(struct edma_txdesc_pri)
+ * txdesc_ring->count,
+ &txdesc_ring->pdma,
+@@ -159,14 +158,14 @@ static void edma_cfg_txcmpl_ring_configu
+ struct regmap *regmap = ppe_dev->regmap;
+ u32 data, reg;
+
+- /* Configure TxCmpl ring base address. */
++ /* Configure Tx cmpl ring base address. */
+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_BA(txcmpl_ring->id);
+ regmap_write(regmap, reg, (u32)(txcmpl_ring->dma & EDMA_RING_DMA_MASK));
+
+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_RING_SIZE(txcmpl_ring->id);
+ regmap_write(regmap, reg, (u32)(txcmpl_ring->count & EDMA_TXDESC_RING_SIZE_MASK));
+
+- /* Set TxCmpl ret mode to opaque. */
++ /* Set Tx cmpl ret mode to opaque. */
+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_CTRL(txcmpl_ring->id);
+ regmap_write(regmap, reg, EDMA_TXCMPL_RETMODE_OPAQUE);
+
+@@ -327,10 +326,10 @@ void edma_cfg_tx_ring_mappings(void)
+ else
+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_5_ADDR;
+
+- pr_debug("Configure Tx desc:%u to use TxCmpl:%u\n", i, desc_index);
++ pr_debug("Configure Tx desc:%u to use Tx cmpl:%u\n", i, desc_index);
+
+ /* Set the Tx complete descriptor ring number in the mapping register.
+- * E.g. If (txcmpl ring)desc_index = 31, (txdesc ring)i = 28.
++ * E.g. If (Tx cmpl ring)desc_index = 31, (txdesc ring)i = 28.
+ * reg = EDMA_REG_TXDESC2CMPL_MAP_4_ADDR
+ * data |= (desc_index & 0x1F) << ((i % 6) * 5);
+ * data |= (0x1F << 20); -
+@@ -408,7 +407,7 @@ static int edma_cfg_tx_rings_setup(void)
+ }
+ }
+
+- /* Allocate TxCmpl ring descriptors. */
++ /* Allocate Tx cmpl ring descriptors. */
+ for (i = 0; i < txcmpl->num_rings; i++) {
+ struct edma_txcmpl_ring *txcmpl_ring = NULL;
+ int ret;
+@@ -419,7 +418,7 @@ static int edma_cfg_tx_rings_setup(void)
+
+ ret = edma_cfg_txcmpl_ring_setup(txcmpl_ring);
+ if (ret != 0) {
+- pr_err("Error in setting up %d TxCmpl ring. ret: %d",
++ pr_err("Error in setting up %d Tx cmpl ring. ret: %d",
+ txcmpl_ring->id, ret);
+ while (i-- >= 0)
+ edma_cfg_txcmpl_ring_cleanup(&edma_ctx->txcmpl_rings[i]);
+@@ -527,7 +526,7 @@ void edma_cfg_tx_rings(void)
+ for (i = 0; i < tx->num_rings; i++)
+ edma_cfg_tx_desc_ring_configure(&edma_ctx->tx_rings[i]);
+
+- /* Configure TxCmpl ring. */
++ /* Configure Tx cmpl ring. */
+ for (i = 0; i < txcmpl->num_rings; i++)
+ edma_cfg_txcmpl_ring_configure(&edma_ctx->txcmpl_rings[i]);
+ }
+@@ -634,6 +633,7 @@ void edma_cfg_tx_napi_delete(u32 port_id
+ if (!txcmpl_ring->napi_added)
+ continue;
+
++ napi_disable(&txcmpl_ring->napi);
+ netif_napi_del(&txcmpl_ring->napi);
+ txcmpl_ring->napi_added = false;
+ }
+@@ -666,7 +666,7 @@ void edma_cfg_tx_napi_add(struct net_dev
+ netif_napi_add_weight(netdev, &txcmpl_ring->napi,
+ edma_tx_napi_poll, hw_info->napi_budget_tx);
+ txcmpl_ring->napi_added = true;
+- netdev_dbg(netdev, "Napi added for txcmpl ring: %u\n", txcmpl_ring->id);
++ netdev_dbg(netdev, "Napi added for Tx cmpl ring: %u\n", txcmpl_ring->id);
+ }
+
+ netdev_dbg(netdev, "Tx NAPI budget: %d\n", edma_tx_napi_budget);
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.h
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.h
+@@ -1,5 +1,5 @@
+ /* SPDX-License-Identifier: GPL-2.0-only
+- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #ifndef __EDMA_CFG_TX__
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_debugfs.c
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_debugfs.c
+@@ -1,5 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+-/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++/* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ /* EDMA debugfs routines for display of Tx/Rx counters. */
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_ethtool.c
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_ethtool.c
+@@ -1,5 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+-/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++/* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ /* ethtool support for EDMA */
+@@ -242,33 +242,6 @@ static int edma_set_pauseparam(struct ne
+ return phylink_ethtool_set_pauseparam(port->phylink, pause);
+ }
+
+-static int edma_get_eee(struct net_device *netdev, struct ethtool_keee *eee)
+-{
+- struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
+- struct ppe_port *port = port_priv->ppe_port;
+-
+- if (!port_priv)
+- return -EINVAL;
+-
+- return phylink_ethtool_get_eee(port->phylink, eee);
+-}
+-
+-static int edma_set_eee(struct net_device *netdev, struct ethtool_keee *eee)
+-{
+- struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
+- struct ppe_port *port = port_priv->ppe_port;
+- int ret;
+-
+- if (!port_priv)
+- return -EINVAL;
+-
+- ret = ppe_port_set_mac_eee(port_priv->ppe_port, eee);
+- if (ret)
+- return ret;
+-
+- return phylink_ethtool_set_eee(port->phylink, eee);
+-}
+-
+ static const struct ethtool_ops edma_ethtool_ops = {
+ .get_strings = &edma_get_strings,
+ .get_sset_count = &edma_get_strset_count,
+@@ -278,8 +251,6 @@ static const struct ethtool_ops edma_eth
+ .set_link_ksettings = edma_set_link_ksettings,
+ .get_pauseparam = &edma_get_pauseparam,
+ .set_pauseparam = &edma_set_pauseparam,
+- .get_eee = &edma_get_eee,
+- .set_eee = &edma_set_eee,
+ };
+
+ /**
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_port.c
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c
+@@ -1,5 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+- /* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ /* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ /* EDMA port initialization, configuration and netdevice ops handling */
+@@ -59,9 +59,12 @@ static void edma_port_stats_free(struct
+ static void edma_port_configure(struct net_device *netdev)
+ {
+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
+- struct ppe_port *port = port_priv->ppe_port;
++ struct ppe_port *port = port_priv->ppe_port;
+ int port_id = port->port_id;
+
++ netdev_dbg(netdev, "Configuring the port %s(qcom-id:%d)\n",
++ netdev->name, port_id);
++
+ edma_cfg_tx_fill_per_port_tx_map(netdev, port_id);
+ edma_cfg_tx_rings_enable(port_id);
+ edma_cfg_tx_napi_add(netdev, port_id);
+@@ -70,7 +73,7 @@ static void edma_port_configure(struct n
+ static void edma_port_deconfigure(struct net_device *netdev)
+ {
+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev);
+- struct ppe_port *port = port_priv->ppe_port;
++ struct ppe_port *port = port_priv->ppe_port;
+ int port_id = port->port_id;
+
+ edma_cfg_tx_napi_delete(port_id);
+@@ -140,7 +143,6 @@ static int edma_port_close(struct net_de
+ edma_cfg_tx_disable_interrupts(port_id);
+ edma_cfg_tx_napi_disable(port_id);
+
+- /* Phylink close. */
+ if (ppe_port->phylink)
+ phylink_stop(ppe_port->phylink);
+
+@@ -219,7 +221,7 @@ static netdev_tx_t edma_port_xmit(struct
+ if (unlikely(ret == EDMA_TX_FAIL_NO_DESC)) {
+ if (likely(!edma_ctx->tx_requeue_stop)) {
+ cpu_id = smp_processor_id();
+- netdev_dbg(dev, "Stopping tx queue due to lack oftx descriptors\n");
++ netdev_dbg(dev, "Stopping tx queue due to lack of tx descriptors\n");
+ u64_stats_update_begin(&stats->syncp);
+ ++stats->tx_queue_stopped[cpu_id];
+ u64_stats_update_end(&stats->syncp);
+@@ -406,16 +408,12 @@ int edma_port_setup(struct ppe_port *por
+ port_id, netdev->dev_addr);
+ }
+
+- /* Allocate memory for EDMA port statistics. */
+ ret = edma_port_stats_alloc(netdev);
+ if (ret) {
+ netdev_dbg(netdev, "EDMA port stats alloc failed\n");
+ goto stats_alloc_fail;
+ }
+
+- netdev_dbg(netdev, "Configuring the port %s(qcom-id:%d)\n",
+- netdev->name, port_id);
+-
+ /* We expect 'port_id' to correspond to ports numbers on SoC.
+ * These begin from '1' and hence we subtract
+ * one when using it as an array index.
+@@ -424,7 +422,6 @@ int edma_port_setup(struct ppe_port *por
+
+ edma_port_configure(netdev);
+
+- /* Setup phylink. */
+ ret = ppe_port_phylink_setup(port, netdev);
+ if (ret) {
+ netdev_dbg(netdev, "EDMA port phylink setup for netdevice %s\n",
+@@ -432,7 +429,6 @@ int edma_port_setup(struct ppe_port *por
+ goto port_phylink_setup_fail;
+ }
+
+- /* Register the network interface. */
+ ret = register_netdev(netdev);
+ if (ret) {
+ netdev_dbg(netdev, "Error registering netdevice %s\n",
+@@ -440,7 +436,7 @@ int edma_port_setup(struct ppe_port *por
+ goto register_netdev_fail;
+ }
+
+- netdev_dbg(netdev, "Setup EDMA port GMAC%d done\n", port_id);
++ netdev_dbg(netdev, "Setup EDMA port%d done\n", port_id);
+ return ret;
+
+ register_netdev_fail:
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_port.h
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.h
+@@ -1,5 +1,5 @@
+ /* SPDX-License-Identifier: GPL-2.0-only
+- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #ifndef __EDMA_PORTS__
+@@ -17,7 +17,7 @@
+ | NETIF_F_TSO6)
+
+ /**
+- * struct edma_port_rx_stats - EDMA RX per CPU stats for the port.
++ * struct edma_port_rx_stats - EDMA Rx per CPU stats for the port.
+ * @rx_pkts: Number of Rx packets
+ * @rx_bytes: Number of Rx bytes
+ * @rx_drops: Number of Rx drops
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_rx.c
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_rx.c
+@@ -1,5 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+-/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++/* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ /* Provides APIs to alloc Rx Buffers, reap the buffers, receive and
+@@ -33,10 +33,12 @@ static int edma_rx_alloc_buffer_list(str
+ struct device *dev = ppe_dev->dev;
+ u16 prod_idx, start_idx;
+ u16 num_alloc = 0;
++ u32 dma_map_size;
+ u32 reg;
+
+ prod_idx = rxfill_ring->prod_idx;
+ start_idx = prod_idx;
++ dma_map_size = rx_alloc_size - EDMA_RX_SKB_HEADROOM - NET_IP_ALIGN;
+
+ while (likely(alloc_count--)) {
+ dma_addr_t buff_addr;
+@@ -56,9 +58,9 @@ static int edma_rx_alloc_buffer_list(str
+ skb_reserve(skb, EDMA_RX_SKB_HEADROOM + NET_IP_ALIGN);
+
+ if (likely(!page_mode)) {
+- buff_addr = dma_map_single(dev, skb->data, rx_alloc_size, DMA_FROM_DEVICE);
++ buff_addr = dma_map_single(dev, skb->data, dma_map_size, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, buff_addr)) {
+- dev_dbg(dev, "edma_context:%p Unable to dma for non page mode",
++ dev_dbg(dev, "edma_context:%pK Unable to dma for non page mode",
+ edma_ctx);
+ dev_kfree_skb_any(skb);
+ break;
+@@ -70,14 +72,14 @@ static int edma_rx_alloc_buffer_list(str
+ ++rxfill_stats->page_alloc_failed;
+ u64_stats_update_end(&rxfill_stats->syncp);
+ dev_kfree_skb_any(skb);
+- dev_dbg(dev, "edma_context:%p Unable to allocate page",
++ dev_dbg(dev, "edma_context:%pK Unable to allocate page",
+ edma_ctx);
+ break;
+ }
+
+- buff_addr = dma_map_page(dev, pg, 0, PAGE_SIZE, DMA_FROM_DEVICE);
++ buff_addr = dma_map_page(dev, pg, 0, PAGE_SIZE, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, buff_addr)) {
+- dev_dbg(dev, "edma_context:%p Mapping error for page mode",
++ dev_dbg(dev, "edma_context:%pK Mapping error for page mode",
+ edma_ctx);
+ __free_page(pg);
+ dev_kfree_skb_any(skb);
+@@ -97,9 +99,12 @@ static int edma_rx_alloc_buffer_list(str
+ (u32)(buf_len) & EDMA_RXFILL_BUF_SIZE_MASK);
+ prod_idx = (prod_idx + 1) & EDMA_RX_RING_SIZE_MASK;
+ num_alloc++;
++
++ EDMA_RXFILL_ENDIAN_SET(rxfill_desc);
+ }
+
+ if (likely(num_alloc)) {
++ dsb(st);
+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_PROD_IDX(rxfill_ring->ring_id);
+ regmap_write(regmap, reg, prod_idx);
+ rxfill_ring->prod_idx = prod_idx;
+@@ -122,24 +127,26 @@ int edma_rx_alloc_buffer(struct edma_rxf
+ return edma_rx_alloc_buffer_list(rxfill_ring, alloc_count);
+ }
+
+-/* Mark ip_summed appropriately in the skb as per the L3/L4 checksum
+- * status in descriptor.
+- */
+-static void edma_rx_checksum_verify(struct edma_rxdesc_pri *rxdesc_pri,
++static inline uint8_t edma_rx_checksum_verify(struct edma_rxdesc_pri *rxdesc_pri,
+ struct sk_buff *skb)
+ {
+ u8 pid = EDMA_RXDESC_PID_GET(rxdesc_pri);
+
+ skb_checksum_none_assert(skb);
+
++ /* Mark ip_summed appropriately in the skb as per the L3/L4 checksum
++ * status in descriptor.
++ */
+ if (likely(EDMA_RX_PID_IS_IPV4(pid))) {
+ if (likely(EDMA_RXDESC_L3CSUM_STATUS_GET(rxdesc_pri)) &&
+ likely(EDMA_RXDESC_L4CSUM_STATUS_GET(rxdesc_pri)))
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
++ return CHECKSUM_UNNECESSARY;
+ } else if (likely(EDMA_RX_PID_IS_IPV6(pid))) {
+ if (likely(EDMA_RXDESC_L4CSUM_STATUS_GET(rxdesc_pri)))
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
++ return CHECKSUM_UNNECESSARY;
+ }
++
++ return skb->ip_summed;
+ }
+
+ static void edma_rx_process_last_segment(struct edma_rxdesc_ring *rxdesc_ring,
+@@ -154,7 +161,6 @@ static void edma_rx_process_last_segment
+ struct net_device *dev;
+ u32 pkt_length;
+
+- /* Get packet length. */
+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri);
+
+ skb_head = rxdesc_ring->head;
+@@ -162,7 +168,7 @@ static void edma_rx_process_last_segment
+
+ /* Check Rx checksum offload status. */
+ if (likely(dev->features & NETIF_F_RXCSUM))
+- edma_rx_checksum_verify(rxdesc_pri, skb_head);
++ skb->ip_summed = edma_rx_checksum_verify(rxdesc_pri, skb_head);
+
+ /* Get stats for the netdevice. */
+ port_dev = netdev_priv(dev);
+@@ -207,7 +213,7 @@ static void edma_rx_process_last_segment
+ rx_stats->rx_fraglist_pkts += (u64)(!page_mode);
+ u64_stats_update_end(&rx_stats->syncp);
+
+- pr_debug("edma_context:%p skb:%p Jumbo pkt_length:%u\n",
++ pr_debug("edma_context:%pK skb:%pK Jumbo pkt_length:%u\n",
+ edma_ctx, skb_head, skb_head->len);
+
+ skb_head->protocol = eth_type_trans(skb_head, dev);
+@@ -229,9 +235,8 @@ static void edma_rx_handle_frag_list(str
+ {
+ u32 pkt_length;
+
+- /* Get packet length. */
+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri);
+- pr_debug("edma_context:%p skb:%p fragment pkt_length:%u\n",
++ pr_debug("edma_context:%pK skb:%pK fragment pkt_length:%u\n",
+ edma_ctx, skb, pkt_length);
+
+ if (!(rxdesc_ring->head)) {
+@@ -275,9 +280,8 @@ static void edma_rx_handle_nr_frags(stru
+ skb_frag_t *frag = NULL;
+ u32 pkt_length;
+
+- /* Get packet length. */
+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri);
+- pr_debug("edma_context:%p skb:%p fragment pkt_length:%u\n",
++ pr_debug("edma_context:%pK skb:%pK fragment pkt_length:%u\n",
+ edma_ctx, skb, pkt_length);
+
+ if (!(rxdesc_ring->head)) {
+@@ -327,7 +331,6 @@ static bool edma_rx_handle_linear_packet
+ pcpu_stats = &port_dev->pcpu_stats;
+ rx_stats = this_cpu_ptr(pcpu_stats->rx_stats);
+
+- /* Get packet length. */
+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri);
+
+ if (likely(!page_mode)) {
+@@ -355,7 +358,7 @@ send_to_stack:
+
+ /* Check Rx checksum offload status. */
+ if (likely(skb->dev->features & NETIF_F_RXCSUM))
+- edma_rx_checksum_verify(rxdesc_pri, skb);
++ skb->ip_summed = edma_rx_checksum_verify(rxdesc_pri, skb);
+
+ u64_stats_update_begin(&rx_stats->syncp);
+ rx_stats->rx_pkts++;
+@@ -363,15 +366,15 @@ send_to_stack:
+ rx_stats->rx_nr_frag_pkts += (u64)page_mode;
+ u64_stats_update_end(&rx_stats->syncp);
+
++ netdev_dbg(skb->dev, "edma_context:%pK, skb:%pK pkt_length:%u\n",
++ edma_ctx, skb, skb->len);
++
+ skb->protocol = eth_type_trans(skb, skb->dev);
+ if (skb->dev->features & NETIF_F_GRO)
+ napi_gro_receive(&rxdesc_ring->napi, skb);
+ else
+ netif_receive_skb(skb);
+
+- netdev_dbg(skb->dev, "edma_context:%p, skb:%p pkt_length:%u\n",
+- edma_ctx, skb, skb->len);
+-
+ return true;
+ }
+
+@@ -390,7 +393,7 @@ static struct net_device *edma_rx_get_sr
+ src_port_num = src_info & EDMA_RXDESC_PORTNUM_BITS;
+ } else {
+ if (net_ratelimit()) {
+- pr_warn("Invalid src info_type:0x%x. Drop skb:%p\n",
++ pr_warn("Invalid src info_type:0x%x. Drop skb:%pK\n",
+ (src_info & EDMA_RXDESC_SRCINFO_TYPE_MASK), skb);
+ }
+
+@@ -401,11 +404,10 @@ static struct net_device *edma_rx_get_sr
+ return NULL;
+ }
+
+- /* Packet with PP source. */
+ if (likely(src_port_num <= hw_info->max_ports)) {
+ if (unlikely(src_port_num < EDMA_START_IFNUM)) {
+ if (net_ratelimit())
+- pr_warn("Port number error :%d. Drop skb:%p\n",
++ pr_warn("Port number error :%d. Drop skb:%pK\n",
+ src_port_num, skb);
+
+ u64_stats_update_begin(&rxdesc_stats->syncp);
+@@ -427,7 +429,7 @@ static struct net_device *edma_rx_get_sr
+ return ndev;
+
+ if (net_ratelimit())
+- pr_warn("Netdev Null src_info_type:0x%x src port num:%d Drop skb:%p\n",
++ pr_warn("Netdev Null src_info_type:0x%x src port num:%d Drop skb:%pK\n",
+ (src_info & EDMA_RXDESC_SRCINFO_TYPE_MASK),
+ src_port_num, skb);
+
+@@ -482,16 +484,17 @@ static int edma_rx_reap(struct edma_rxde
+ struct net_device *ndev;
+ struct sk_buff *skb;
+ dma_addr_t dma_addr;
++ u32 dma_map_size;
+
+ skb = next_skb;
+ rxdesc_pri = next_rxdesc_pri;
+ dma_addr = EDMA_RXDESC_BUFFER_ADDR_GET(rxdesc_pri);
++ dma_map_size = alloc_size - EDMA_RX_SKB_HEADROOM - NET_IP_ALIGN;
+
+ if (!page_mode)
+- dma_unmap_single(dev, dma_addr, alloc_size,
+- DMA_TO_DEVICE);
++ dma_unmap_single(dev, dma_addr, dma_map_size, DMA_FROM_DEVICE);
+ else
+- dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_TO_DEVICE);
++ dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
+
+ /* Update consumer index. */
+ cons_idx = (cons_idx + 1) & EDMA_RX_RING_SIZE_MASK;
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_rx.h
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_rx.h
+@@ -1,5 +1,5 @@
+ /* SPDX-License-Identifier: GPL-2.0-only
+- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #ifndef __EDMA_RX__
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_tx.c
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_tx.c
+@@ -1,5 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+-/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++/* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ /* Provide APIs to alloc Tx Buffers, fill the Tx descriptors and transmit
+@@ -68,14 +68,9 @@ enum edma_tx_gso_status edma_tx_gso_segm
+ if (likely(!skb_is_nonlinear(skb)))
+ return EDMA_TX_GSO_NOT_NEEDED;
+
+- /* Check if TSO is enabled. If so, return as skb doesn't
+- * need to be segmented by linux.
+- */
+- if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) {
+- num_tx_desc_needed = edma_tx_num_descs_for_sg(skb);
+- if (likely(num_tx_desc_needed <= EDMA_TX_TSO_SEG_MAX))
+- return EDMA_TX_GSO_NOT_NEEDED;
+- }
++ num_tx_desc_needed = edma_tx_num_descs_for_sg(skb);
++ if (likely(num_tx_desc_needed <= EDMA_TX_TSO_SEG_MAX))
++ return EDMA_TX_GSO_NOT_NEEDED;
+
+ /* GSO segmentation of the skb into multiple segments. */
+ *segs = skb_gso_segment(skb, netdev->features
+@@ -119,7 +114,7 @@ u32 edma_tx_complete(u32 work_to_do, str
+ if (likely(txcmpl_ring->avail_pkt >= work_to_do)) {
+ avail = work_to_do;
+ } else {
+- /* Get TXCMPL ring producer index. */
++ /* Get Tx cmpl ring producer index. */
+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_PROD_IDX(txcmpl_ring->id);
+ regmap_read(regmap, reg, &data);
+ prod_idx = data & EDMA_TXCMPL_PROD_IDX_MASK;
+@@ -128,7 +123,7 @@ u32 edma_tx_complete(u32 work_to_do, str
+ txcmpl_ring->avail_pkt = avail;
+
+ if (unlikely(!avail)) {
+- dev_dbg(dev, "No available descriptors are pending for %d txcmpl ring\n",
++ dev_dbg(dev, "No available descriptors are pending for %d Tx cmpl ring\n",
+ txcmpl_ring->id);
+ u64_stats_update_begin(&txcmpl_stats->syncp);
+ ++txcmpl_stats->no_pending_desc;
+@@ -144,9 +139,6 @@ u32 edma_tx_complete(u32 work_to_do, str
+ end_idx = (cons_idx + avail) & EDMA_TX_RING_SIZE_MASK;
+ txcmpl = EDMA_TXCMPL_DESC(txcmpl_ring, cons_idx);
+
+- /* Instead of freeing the skb, it might be better to save and use
+- * for Rxfill.
+- */
+ while (likely(avail--)) {
+ /* The last descriptor holds the SKB pointer for scattered frames.
+ * So skip the descriptors with more bit set.
+@@ -172,27 +164,13 @@ u32 edma_tx_complete(u32 work_to_do, str
+ ++txcmpl_stats->invalid_buffer;
+ u64_stats_update_end(&txcmpl_stats->syncp);
+ } else {
+- dev_dbg(dev, "TXCMPL: skb:%p, skb->len %d, skb->data_len %d, cons_idx:%d prod_idx:%d word2:0x%x word3:0x%x\n",
+- skb, skb->len, skb->data_len, cons_idx, prod_idx,
+- txcmpl->word2, txcmpl->word3);
+-
+- txcmpl_errors = EDMA_TXCOMP_RING_ERROR_GET(txcmpl->word3);
+- if (unlikely(txcmpl_errors)) {
+- if (net_ratelimit())
+- dev_err(dev, "Error 0x%0x observed in tx complete %d ring\n",
+- txcmpl_errors, txcmpl_ring->id);
+-
+- u64_stats_update_begin(&txcmpl_stats->syncp);
+- ++txcmpl_stats->errors;
+- u64_stats_update_end(&txcmpl_stats->syncp);
+- }
+
+ /* Retrieve pool id for unmapping.
+ * 0 for linear skb and (pool id - 1) represents nr_frag index.
+ */
+ if (!EDMA_TXCOMP_POOL_ID_GET(txcmpl)) {
+ dma_unmap_single(dev, virt_to_phys(skb->data),
+- skb->len, DMA_TO_DEVICE);
++ skb_headlen(skb), DMA_TO_DEVICE);
+ } else {
+ u8 frag_index = (EDMA_TXCOMP_POOL_ID_GET(txcmpl) - 1);
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[frag_index];
+@@ -201,6 +179,21 @@ u32 edma_tx_complete(u32 work_to_do, str
+ PAGE_SIZE, DMA_TO_DEVICE);
+ }
+
++ dev_dbg(dev, "TXCMPL: skb:%pK, skb->len %d, skb->data_len %d, cons_idx:%d prod_idx:%d word2:0x%x word3:0x%x\n",
++ skb, skb->len, skb->data_len, cons_idx, prod_idx,
++ txcmpl->word2, txcmpl->word3);
++
++ txcmpl_errors = EDMA_TXCOMP_RING_ERROR_GET(txcmpl->word3);
++ if (unlikely(txcmpl_errors)) {
++ if (net_ratelimit())
++ dev_err(dev, "Error 0x%0x observed in tx complete %d ring\n",
++ txcmpl_errors, txcmpl_ring->id);
++
++ u64_stats_update_begin(&txcmpl_stats->syncp);
++ ++txcmpl_stats->errors;
++ u64_stats_update_end(&txcmpl_stats->syncp);
++ }
++
+ dev_kfree_skb(skb);
+ }
+
+@@ -211,7 +204,7 @@ u32 edma_tx_complete(u32 work_to_do, str
+ txcmpl_ring->cons_idx = cons_idx;
+ txcmpl_ring->avail_pkt -= count;
+
+- dev_dbg(dev, "TXCMPL:%u count:%u prod_idx:%u cons_idx:%u\n",
++ dev_dbg(dev, "Tx cmpl:%u count:%u prod_idx:%u cons_idx:%u\n",
+ txcmpl_ring->id, count, prod_idx, cons_idx);
+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_CONS_IDX(txcmpl_ring->id);
+ regmap_write(regmap, reg, cons_idx);
+@@ -265,7 +258,7 @@ int edma_tx_napi_poll(struct napi_struct
+ /* No more packets to process. Finish NAPI processing. */
+ napi_complete(napi);
+
+- /* Set TXCMPL ring interrupt mask. */
++ /* Set Tx cmpl ring interrupt mask. */
+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_MASK(txcmpl_ring->id);
+ regmap_write(regmap, reg, edma_ctx->intr_info.intr_mask_txcmpl);
+
+@@ -392,7 +385,7 @@ static u32 edma_tx_skb_nr_frags(struct e
+ return num_descs;
+ }
+
+-static void edma_tx_fill_pp_desc(struct edma_port_priv *port_priv,
++static void edma_tx_fill_desc(struct edma_port_priv *port_priv,
+ struct edma_txdesc_pri *txd, struct sk_buff *skb,
+ struct edma_port_tx_stats *stats)
+ {
+@@ -463,7 +456,7 @@ static struct edma_txdesc_pri *edma_tx_s
+
+ EDMA_TXDESC_BUFFER_ADDR_SET(txd, buff_addr);
+ EDMA_TXDESC_POOL_ID_SET(txd, 0);
+- edma_tx_fill_pp_desc(port_priv, txd, skb, stats);
++ edma_tx_fill_desc(port_priv, txd, skb, stats);
+
+ /* Set packet length in the descriptor. */
+ EDMA_TXDESC_DATA_LEN_SET(txd, buf_len);
+@@ -528,6 +521,23 @@ static u32 edma_tx_skb_sg_fill_desc(stru
+ /* Head skb processed already. */
+ num_descs++;
+
++ /* Process skb with nr_frags. */
++ if (unlikely(skb_shinfo(skb)->nr_frags)) {
++ num_descs += edma_tx_skb_nr_frags(txdesc_ring, &txd, skb,
++ hw_next_to_use, &invalid_frag);
++ if (unlikely(!num_descs)) {
++ dev_dbg(dev, "No descriptor available for ring %d\n", txdesc_ring->id);
++ edma_tx_dma_unmap_frags(skb, invalid_frag);
++ *txdesc = NULL;
++ return num_descs;
++ }
++
++ u64_stats_update_begin(&stats->syncp);
++ stats->tx_nr_frag_pkts++;
++ u64_stats_update_end(&stats->syncp);
++ }
++
++ /* Process skb if it has frag_list */
+ if (unlikely(skb_has_frag_list(skb))) {
+ struct edma_txdesc_pri *start_desc = NULL;
+ u32 start_idx = 0, end_idx = 0;
+@@ -608,23 +618,9 @@ skip_primary:
+ u64_stats_update_begin(&stats->syncp);
+ stats->tx_fraglist_pkts++;
+ u64_stats_update_end(&stats->syncp);
+- } else {
+- /* Process skb with nr_frags. */
+- num_descs += edma_tx_skb_nr_frags(txdesc_ring, &txd, skb,
+- hw_next_to_use, &invalid_frag);
+- if (unlikely(!num_descs)) {
+- dev_dbg(dev, "No descriptor available for ring %d\n", txdesc_ring->id);
+- edma_tx_dma_unmap_frags(skb, invalid_frag);
+- *txdesc = NULL;
+- return num_descs;
+- }
+-
+- u64_stats_update_begin(&stats->syncp);
+- stats->tx_nr_frag_pkts++;
+- u64_stats_update_end(&stats->syncp);
+ }
+
+- dev_dbg(dev, "skb:%p num_descs_filled: %u, nr_frags %u, frag_list fragments %u\n",
++ dev_dbg(dev, "skb:%pK num_descs_filled: %u, nr_frags %u, frag_list fragments %u\n",
+ skb, num_descs, skb_shinfo(skb)->nr_frags, num_sg_frag_list);
+
+ *txdesc = txd;
+@@ -775,7 +771,7 @@ enum edma_tx_status edma_tx_ring_xmit(st
+ netdev_dbg(netdev, "No descriptor available for ring %d\n",
+ txdesc_ring->id);
+ dma_unmap_single(dev, virt_to_phys(skb->data),
+- skb->len, DMA_TO_DEVICE);
++ skb_headlen(skb), DMA_TO_DEVICE);
+ u64_stats_update_begin(&txdesc_stats->syncp);
+ ++txdesc_stats->no_desc_avail;
+ u64_stats_update_end(&txdesc_stats->syncp);
+@@ -792,10 +788,12 @@ enum edma_tx_status edma_tx_ring_xmit(st
+ txdesc_ring->prod_idx = hw_next_to_use & EDMA_TXDESC_PROD_IDX_MASK;
+ txdesc_ring->avail_desc -= num_desc_filled;
+
+- netdev_dbg(netdev, "%s: skb:%p tx_ring:%u proto:0x%x skb->len:%d\n port:%u prod_idx:%u ip_summed:0x%x\n",
++ netdev_dbg(netdev, "%s: skb:%pK tx_ring:%u proto:0x%x skb->len:%d\n port:%u prod_idx:%u ip_summed:0x%x\n",
+ netdev->name, skb, txdesc_ring->id, ntohs(skb->protocol),
+ skb->len, port_id, hw_next_to_use, skb->ip_summed);
+
++ dsb(st);
++
+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_PROD_IDX(txdesc_ring->id);
+ regmap_write(regmap, reg, txdesc_ring->prod_idx);
+
+--- a/drivers/net/ethernet/qualcomm/ppe/edma_tx.h
++++ b/drivers/net/ethernet/qualcomm/ppe/edma_tx.h
+@@ -1,5 +1,5 @@
+ /* SPDX-License-Identifier: GPL-2.0-only
+- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #ifndef __EDMA_TX__
+@@ -66,7 +66,7 @@
+ #define EDMA_TXDESC_L4_CSUM_SET(desc) ((desc)->word5 |= \
+ (FIELD_PREP(EDMA_TXDESC_L4_CSUM_SET_MASK, 1)))
+
+-#define EDMA_TXDESC_POOL_ID_SET_MASK GENMASK(24, 18)
++#define EDMA_TXDESC_POOL_ID_SET_MASK GENMASK(23, 18)
+ #define EDMA_TXDESC_POOL_ID_SET(desc, x) ((desc)->word5 |= \
+ (FIELD_PREP(EDMA_TXDESC_POOL_ID_SET_MASK, x)))
+
+@@ -153,7 +153,7 @@ enum edma_tx_gso_status {
+ };
+
+ /**
+- * struct edma_txcmpl_stats - EDMA TX complete ring statistics.
++ * struct edma_txcmpl_stats - EDMA Tx complete ring statistics.
+ * @invalid_buffer: Invalid buffer address received.
+ * @errors: Other Tx complete descriptor errors indicated by the hardware.
+ * @desc_with_more_bit: Packet's segment transmit count.
+@@ -181,7 +181,7 @@ struct edma_txdesc_stats {
+ };
+
+ /**
+- * struct edma_txdesc_pri - EDMA primary TX descriptor.
++ * struct edma_txdesc_pri - EDMA primary Tx descriptor.
+ * @word0: Low 32-bit of buffer address.
+ * @word1: Buffer recycling, PTP tag flag, PRI valid flag.
+ * @word2: Low 32-bit of opaque value.
+@@ -203,7 +203,7 @@ struct edma_txdesc_pri {
+ };
+
+ /**
+- * struct edma_txdesc_sec - EDMA secondary TX descriptor.
++ * struct edma_txdesc_sec - EDMA secondary Tx descriptor.
+ * @word0: Reserved.
+ * @word1: Custom csum offset, payload offset, TTL/NAT action.
+ * @word2: NAPT translated port, DSCP value, TTL value.
+@@ -225,7 +225,7 @@ struct edma_txdesc_sec {
+ };
+
+ /**
+- * struct edma_txcmpl_desc - EDMA TX complete descriptor.
++ * struct edma_txcmpl_desc - EDMA Tx complete descriptor.
+ * @word0: Low 32-bit opaque value.
+ * @word1: High 32-bit opaque value.
+ * @word2: More fragment, transmit ring id, pool id.
+@@ -239,7 +239,7 @@ struct edma_txcmpl_desc {
+ };
+
+ /**
+- * struct edma_txdesc_ring - EDMA TX descriptor ring
++ * struct edma_txdesc_ring - EDMA Tx descriptor ring
+ * @prod_idx: Producer index
+ * @id: Tx ring number
+ * @avail_desc: Number of available descriptor to process
+@@ -265,7 +265,7 @@ struct edma_txdesc_ring {
+ };
+
+ /**
+- * struct edma_txcmpl_ring - EDMA TX complete ring
++ * struct edma_txcmpl_ring - EDMA Tx complete ring
+ * @napi: NAPI
+ * @cons_idx: Consumer index
+ * @avail_pkt: Number of available packets to process
+--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
++++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
+@@ -229,11 +229,9 @@ static void qcom_ppe_remove(struct platf
+ struct ppe_device *ppe_dev;
+
+ ppe_dev = platform_get_drvdata(pdev);
+- ppe_debugfs_teardown(ppe_dev);
+ ppe_port_mac_deinit(ppe_dev);
++ ppe_debugfs_teardown(ppe_dev);
+ edma_destroy(ppe_dev);
+-
+- platform_set_drvdata(pdev, NULL);
+ }
+
+ static const struct of_device_id qcom_ppe_of_match[] = {
+--- a/drivers/net/ethernet/qualcomm/ppe/ppe.h
++++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h
+@@ -13,6 +13,8 @@ struct device;
+ struct regmap;
+ struct dentry;
+
++struct ppe_ports;
++
+ /**
+ * struct ppe_device - PPE device private data.
+ * @dev: PPE device structure.
+--- /dev/null
++++ b/drivers/net/ethernet/qualcomm/ppe/ppe_api.c
+@@ -0,0 +1,113 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
++ */
++
++#include "ppe.h"
++#include "ppe_api.h"
++#include "ppe_config.h"
++
++/**
++ * ppe_queue_node_priority_set - set scheduler priority of PPE queue or flow
++ * @ppe_dev: PPE device
++ * @node_id: PPE hardware node ID, which can be queue ID or flow ID.
++ * @priority: PPE discipline scheduler priority
++ *
++ * Configure scheduler priority for a given PPE node. Node may be of type
++ * PPE queue or flow. The packet is dispatched first by queue scheduler
++ * (level 0), then dispatched by flow scheduler (level 1).
++ *
++ * Return 0 on success, negative error code on failure.
++ */
++int ppe_queue_node_priority_set(struct ppe_device *ppe_dev,
++ int node_id, int priority)
++{
++ struct ppe_scheduler_cfg sch_cfg;
++ int ret, port, level = 0;
++
++ if (node_id >= PPE_QUEUE_ID_MAX + PPE_FLOW_ID_MAX)
++ return -EINVAL;
++
++ if (node_id >= PPE_QUEUE_ID_MAX) {
++ level = 1;
++ node_id -= PPE_QUEUE_ID_MAX;
++ }
++
++ ret = ppe_queue_scheduler_get(ppe_dev, node_id, level, &port, &sch_cfg);
++ if (ret)
++ return ret;
++
++ sch_cfg.pri = priority;
++
++ return ppe_queue_scheduler_set(ppe_dev, node_id, level, port, sch_cfg);
++}
++
++/**
++ * ppe_edma_queue_offset_config - Configure queue offset for EDMA interface
++ * @ppe_dev: PPE device
++ * @type: The type can be internal priority or PPE hash
++ * @index: Class index, which can be internal priority or hash value
++ * @queue_offset: Queue offset value which is added by the queue base to get
++ * the egress queue ID.
++ *
++ * PPE EDMA queue offset is configured based on the PPE internal priority or
++ * RSS hash value, the profile ID is fixed to 0 for the EDMA interface.
++ *
++ * Return 0 on success, negative error code on failure.
++ */
++int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev,
++ enum ppe_queue_offset_type type,
++ int index, int queue_offset)
++{
++ if (type == PPE_QUEUE_OFFSET_BY_PRIORITY)
++ return ppe_queue_ucast_offset_pri_set(ppe_dev, 0,
++ index, queue_offset);
++
++ return ppe_queue_ucast_offset_hash_set(ppe_dev, 0,
++ index, queue_offset);
++}
++
++/**
++ * ppe_edma_queue_resource_get - Get EDMA queue resource
++ * @ppe_dev: PPE device
++ * @type: Resource type
++ * @res_start: Resource start ID returned
++ * @res_end: Resource end ID returned
++ *
++ * PPE EDMA queue resource includes unicast queue and multicast queue.
++ *
++ * Return 0 on success, negative error code on failure.
++ */
++int ppe_edma_queue_resource_get(struct ppe_device *ppe_dev,
++ enum ppe_resource_type type,
++ int *res_start, int *res_end)
++{
++ if (type != PPE_RES_UCAST && type != PPE_RES_MCAST)
++ return -EINVAL;
++
++ return ppe_port_resource_get(ppe_dev, 0, type, res_start, res_end);
++};
++
++/**
++ * ppe_edma_ring_to_queues_config - Configure EDMA ring to queue mapping in PPE
++ * @ppe_dev: PPE device
++ * @ring_id: EDMA ring ID
++ * @num: Number of queues mapped to EDMA ring
++ * @queues: PPE queue IDs
++ *
++ * Enable EDMA ring to PPE queue mapping configuration for packet
++ * receive to an EDMA ring.
++ *
++ * Return 0 on success, negative error code on failure.
++ */
++int ppe_edma_ring_to_queues_config(struct ppe_device *ppe_dev, int ring_id,
++ int num, int queues[])
++{
++ u32 queue_bmap[PPE_RING_TO_QUEUE_BITMAP_WORD_CNT] = {};
++ int index;
++
++ for (index = 0; index < num; index++)
++ queue_bmap[queues[index] / 32] |= BIT_MASK(queues[index] % 32);
++
++ return ppe_ring_queue_map_set(ppe_dev, ring_id, queue_bmap);
++}
+--- /dev/null
++++ b/drivers/net/ethernet/qualcomm/ppe/ppe_api.h
+@@ -0,0 +1,43 @@
++/* SPDX-License-Identifier: GPL-2.0-only
++ *
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
++ */
++
++/* Functions for low level PPE configurations which are needed during ethernet
++ * driver initialization.
++ */
++
++#ifndef __PPE_API_H__
++#define __PPE_API_H__
++
++#include "ppe.h"
++#include "ppe_config.h"
++
++#define PPE_QUEUE_ID_MAX 300
++#define PPE_FLOW_ID_MAX 64
++#define PPE_QUEUE_INTERNAL_PRI_NUM 16
++#define PPE_QUEUE_HASH_NUM 256
++
++/**
++ * enum ppe_queue_offset_type - PPE queue offset type
++ * @PPE_QUEUE_CLASS_PRIORITY: Queue offset decided by PPE internal priority
++ * @PPE_QUEUE_CLASS_HASH: Queue offset decided by PPE RSS hash value.
++ */
++enum ppe_queue_offset_type {
++ PPE_QUEUE_OFFSET_BY_PRIORITY,
++ PPE_QUEUE_OFFSET_BY_HASH,
++};
++
++int ppe_queue_node_priority_set(struct ppe_device *ppe_dev,
++ int node_id, int priority);
++
++int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev,
++ enum ppe_queue_offset_type type,
++ int index, int queue_offset);
++
++int ppe_edma_queue_resource_get(struct ppe_device *ppe_dev,
++ enum ppe_resource_type type,
++ int *res_start, int *res_end);
++int ppe_edma_ring_to_queues_config(struct ppe_device *ppe_dev, int ring_id,
++ int num, int queues[]);
++#endif
+--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
++++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
+@@ -889,7 +889,7 @@ static int ppe_scheduler_l0_queue_map_se
+ val);
+ }
+
+-/* Get the first level scheduler configuration. */
++/* Get the PPE queue level scheduler configuration. */
+ static int ppe_scheduler_l0_queue_map_get(struct ppe_device *ppe_dev,
+ int node_id, int *port,
+ struct ppe_scheduler_cfg *scheduler_cfg)
+@@ -986,7 +986,7 @@ static int ppe_scheduler_l1_queue_map_se
+ return regmap_update_bits(ppe_dev->regmap, reg, PPE_L1_COMP_CFG_TBL_NODE_METER_LEN, val);
+ }
+
+-/* Get the second level scheduler configuration. */
++/* Get the PPE flow level scheduler configuration. */
+ static int ppe_scheduler_l1_queue_map_get(struct ppe_device *ppe_dev,
+ int node_id, int *port,
+ struct ppe_scheduler_cfg *scheduler_cfg)
+@@ -1056,58 +1056,6 @@ int ppe_queue_scheduler_set(struct ppe_d
+ }
+
+ /**
+- * ppe_queue_scheduler_get - get QoS scheduler of PPE hardware queue
+- * @ppe_dev: PPE device
+- * @node_id: PPE node ID
+- * @flow_level: Flow level scheduler or queue level scheduler
+- * @port: PPE port ID to get scheduler config
+- * @scheduler_cfg: QoS scheduler configuration
+- *
+- * The hardware QoS function is supported by PPE, the current scheduler
+- * configuration can be acquired based on the queue ID of PPE port.
+- *
+- * Return 0 on success, negative error code on failure.
+- */
+-int ppe_queue_scheduler_get(struct ppe_device *ppe_dev,
+- int node_id, bool flow_level, int *port,
+- struct ppe_scheduler_cfg *scheduler_cfg)
+-{
+- if (flow_level)
+- return ppe_scheduler_l1_queue_map_get(ppe_dev, node_id,
+- port, scheduler_cfg);
+-
+- return ppe_scheduler_l0_queue_map_get(ppe_dev, node_id,
+- port, scheduler_cfg);
+-}
+-
+-
+-/**
+- * ppe_queue_priority_set - set scheduler priority of PPE hardware queue
+- * @ppe_dev: PPE device
+- * @node_id: PPE hardware node ID, which is either queue ID or flow ID
+- * @priority: Qos scheduler priority
+- *
+- * Configure scheduler priority of PPE hardware queque, the maximum node
+- * ID supported is PPE_QUEUE_ID_NUM added by PPE_FLOW_ID_NUM, queue ID
+- * belongs to level 0, flow ID belongs to level 1 in the packet pipeline.
+- *
+- * Return 0 on success, negative error code on failure.
+- */
+-int ppe_queue_priority_set(struct ppe_device *ppe_dev,
+- int node_id, int priority)
+-{
+- struct ppe_scheduler_cfg sch_cfg;
+- int ret, port, level = 0;
+-
+- ret = ppe_queue_scheduler_get(ppe_dev, node_id, level, &port, &sch_cfg);
+- if (ret)
+- return ret;
+-
+- sch_cfg.pri = priority;
+- return ppe_queue_scheduler_set(ppe_dev, node_id, level, port, sch_cfg);
+-}
+-
+-/**
+ * ppe_queue_ucast_base_set - Set PPE unicast queue base ID and profile ID
+ * @ppe_dev: PPE device
+ * @queue_dst: PPE queue destination configuration
+@@ -1520,6 +1468,31 @@ int ppe_ring_queue_map_set(struct ppe_de
+ ARRAY_SIZE(queue_bitmap_val));
+ }
+
++/**
++ * ppe_queue_scheduler_get - get scheduler of PPE hardware queue
++ * @ppe_dev: PPE device
++ * @node_id: PPE queue ID or flow ID
++ * @flow_level: Flow level scheduler or queue level scheduler
++ * @port: PPE port ID to get scheduler config
++ * @scheduler_cfg: PPE scheduler configuration
++ *
++ * The current scheduler configuration can be acquired based on the
++ * queue ID of PPE port.
++ *
++ * Return 0 on success, negative error code on failure.
++ */
++int ppe_queue_scheduler_get(struct ppe_device *ppe_dev,
++ int node_id, bool flow_level, int *port,
++ struct ppe_scheduler_cfg *scheduler_cfg)
++{
++ if (flow_level)
++ return ppe_scheduler_l1_queue_map_get(ppe_dev, node_id,
++ port, scheduler_cfg);
++
++ return ppe_scheduler_l0_queue_map_get(ppe_dev, node_id,
++ port, scheduler_cfg);
++}
++
+ static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
+ const struct ppe_bm_port_config port_cfg)
+ {
+--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
++++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
+@@ -294,8 +294,6 @@ int ppe_queue_scheduler_set(struct ppe_d
+ int ppe_queue_scheduler_get(struct ppe_device *ppe_dev,
+ int node_id, bool flow_level, int *port,
+ struct ppe_scheduler_cfg *scheduler_cfg);
+-int ppe_queue_priority_set(struct ppe_device *ppe_dev,
+- int queue_id, int priority);
+ int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev,
+ struct ppe_queue_ucast_dest queue_dst,
+ int queue_base,
+--- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c
++++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c
+@@ -1,16 +1,17 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ /* PPE Port MAC initialization and PPE port MAC functions. */
+
+ #include <linux/clk.h>
++#include <linux/of.h>
+ #include <linux/of_net.h>
+ #include <linux/pcs/pcs-qcom-ipq9574.h>
+ #include <linux/phylink.h>
+-#include <linux/reset.h>
+ #include <linux/regmap.h>
++#include <linux/reset.h>
+ #include <linux/rtnetlink.h>
+
+ #include "edma_port.h"
+@@ -117,7 +118,7 @@ enum ppe_xgmib_stats_type {
+ xgmib_rx_broadcast_g,
+ xgmib_rx_multicast_g,
+ xgmib_rx_crc_err,
+- xgmib_rx_runt_err,
++ xgmib_rx_frag_err,
+ xgmib_rx_jabber_err,
+ xgmib_rx_undersize_g,
+ xgmib_rx_oversize_g,
+@@ -219,7 +220,7 @@ static const struct ppe_mac_mib_info xgm
+ PPE_MAC_MIB_DESC(8, XGMAC_RXBROAD_G_ADDR, "rx_broadcast_g"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXMULTI_G_ADDR, "rx_multicast_g"),
+ PPE_MAC_MIB_DESC(8, XGMAC_RXCRC_ERR_ADDR, "rx_crc_err"),
+- PPE_MAC_MIB_DESC(4, XGMAC_RXRUNT_ERR_ADDR, "rx_runt_err"),
++ PPE_MAC_MIB_DESC(4, XGMAC_RXFRAG_ERR_ADDR, "rx_frag_err"),
+ PPE_MAC_MIB_DESC(4, XGMAC_RXJABBER_ERR_ADDR, "rx_jabber_err"),
+ PPE_MAC_MIB_DESC(4, XGMAC_RXUNDERSIZE_G_ADDR, "rx_undersize_g"),
+ PPE_MAC_MIB_DESC(4, XGMAC_RXOVERSIZE_G_ADDR, "rx_oversize_g"),
+@@ -257,7 +258,8 @@ static void ppe_port_gmib_update(struct
+
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret) {
+- dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret);
++ dev_warn(ppe_dev->dev, "PPE port GMIB read fail %d\n",
++ ret);
+ continue;
+ }
+
+@@ -265,8 +267,8 @@ static void ppe_port_gmib_update(struct
+ if (mib->size == 8) {
+ ret = regmap_read(ppe_dev->regmap, reg + 4, &val);
+ if (ret) {
+- dev_warn(ppe_dev->dev, "%s: %d\n",
+- __func__, ret);
++ dev_warn(ppe_dev->dev,
++ "PPE port GMIB read fail %d\n", ret);
+ continue;
+ }
+
+@@ -288,6 +290,43 @@ static void ppe_port_gmib_stats_poll(str
+ msecs_to_jiffies(PPE_GMIB_POLL_INTERVAL_MS));
+ }
+
++/* Start PPE port GMAC MIB statistics polling work */
++static int ppe_port_gmib_work_start(struct ppe_port *ppe_port)
++{
++ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
++
++ if (!ppe_port->gmib_stats) {
++ u64 *gstats;
++ /* Allocate array memory to store GMIB statistics */
++ gstats = devm_kzalloc(ppe_dev->dev,
++ sizeof(*gstats) * ARRAY_SIZE(gmib_info),
++ GFP_KERNEL);
++ if (!gstats)
++ return -ENOMEM;
++
++ ppe_port->gmib_stats = gstats;
++
++ /* Init GMIB statistics polling work */
++ spin_lock_init(&ppe_port->gmib_stats_lock);
++ INIT_DELAYED_WORK(&ppe_port->gmib_read,
++ ppe_port_gmib_stats_poll);
++ }
++
++ /* Start GMIB statistics polling work */
++ schedule_delayed_work(&ppe_port->gmib_read, 0);
++
++ return 0;
++}
++
++/* Stop PPE port GMAC MIB statistics polling work */
++static void ppe_port_gmib_work_stop(struct ppe_port *ppe_port)
++{
++ if (ppe_port->gmib_stats) {
++ /* Stop GMIB statistics polling work */
++ cancel_delayed_work_sync(&ppe_port->gmib_read);
++ }
++}
++
+ /* Get the XGMAC MIB counter based on the specific MIB stats type */
+ static u64 ppe_port_xgmib_get(struct ppe_port *ppe_port,
+ enum ppe_xgmib_stats_type xgmib_type)
+@@ -304,7 +343,7 @@ static u64 ppe_port_xgmib_get(struct ppe
+
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret) {
+- dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret);
++ dev_warn(ppe_dev->dev, "PPE port XGMIB read fail %d\n", ret);
+ goto data_return;
+ }
+
+@@ -312,7 +351,8 @@ static u64 ppe_port_xgmib_get(struct ppe
+ if (mib->size == 8) {
+ ret = regmap_read(ppe_dev->regmap, reg + 4, &val);
+ if (ret) {
+- dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret);
++ dev_warn(ppe_dev->dev, "PPE port XGMIB read fail %d\n",
++ ret);
+ goto data_return;
+ }
+
+@@ -338,10 +378,12 @@ int ppe_port_get_sset_count(struct ppe_p
+ if (sset != ETH_SS_STATS)
+ return 0;
+
+- if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC)
+- return ARRAY_SIZE(gmib_info);
+- else
+- return ARRAY_SIZE(xgmib_info);
++ /* The MAC type is invisible to the upper interface. The interface
++ * can switch between GMAC and XGMAC in different interface modes.
++ * Therefore, the unified XGMIB statistics format is used, and GMIB
++ * statistics will be merged into the XGMIB statistics.
++ */
++ return ARRAY_SIZE(xgmib_info);
+ }
+
+ /**
+@@ -361,15 +403,9 @@ void ppe_port_get_strings(struct ppe_por
+ if (stringset != ETH_SS_STATS)
+ return;
+
+- if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) {
+- for (i = 0; i < ARRAY_SIZE(gmib_info); i++)
+- strscpy(data + i * ETH_GSTRING_LEN, gmib_info[i].name,
+- ETH_GSTRING_LEN);
+- } else {
+- for (i = 0; i < ARRAY_SIZE(xgmib_info); i++)
+- strscpy(data + i * ETH_GSTRING_LEN, xgmib_info[i].name,
+- ETH_GSTRING_LEN);
+- }
++ for (i = 0; i < ARRAY_SIZE(xgmib_info); i++)
++ strscpy(data + i * ETH_GSTRING_LEN, xgmib_info[i].name,
++ ETH_GSTRING_LEN);
+ }
+
+ /**
+@@ -385,17 +421,64 @@ void ppe_port_get_ethtool_stats(struct p
+ {
+ int i;
+
+- if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) {
++ for (i = 0; i < ARRAY_SIZE(xgmib_info); i++)
++ data[i] = ppe_port_xgmib_get(ppe_port, i);
++
++ /* Merge the GMIB statistics into the XGMIB statistics to show
++ * the total counters for this interface.
++ */
++ if (ppe_port->gmib_stats) {
++ u64 *gsrc = ppe_port->gmib_stats;
++
+ spin_lock(&ppe_port->gmib_stats_lock);
+
+ ppe_port_gmib_update(ppe_port);
+- for (i = 0; i < ARRAY_SIZE(gmib_info); i++)
+- data[i] = ppe_port->gmib_stats[i];
++
++ data[xgmib_tx_bytes] += gsrc[gmib_tx_bytes];
++ data[xgmib_tx_frames] += gsrc[gmib_tx_broadcast];
++ data[xgmib_tx_frames] += gsrc[gmib_tx_multicast];
++ data[xgmib_tx_frames] += gsrc[gmib_tx_unicast];
++ data[xgmib_tx_broadcast_g] += gsrc[gmib_tx_broadcast];
++ data[xgmib_tx_multicast_g] += gsrc[gmib_tx_multicast];
++ data[xgmib_tx_pkt64] += gsrc[gmib_tx_pkt64];
++ data[xgmib_tx_pkt65to127] += gsrc[gmib_tx_pkt65to127];
++ data[xgmib_tx_pkt128to255] += gsrc[gmib_tx_pkt128to255];
++ data[xgmib_tx_pkt256to511] += gsrc[gmib_tx_pkt256to511];
++ data[xgmib_tx_pkt512to1023] += gsrc[gmib_tx_pkt512to1023];
++ data[xgmib_tx_pkt1024tomax] += gsrc[gmib_tx_pkt1024to1518];
++ data[xgmib_tx_pkt1024tomax] += gsrc[gmib_tx_pkt1519tomax];
++ data[xgmib_tx_unicast] += gsrc[gmib_tx_unicast];
++ data[xgmib_tx_multicast] += gsrc[gmib_tx_multicast];
++ data[xgmib_tx_broadcast] += gsrc[gmib_tx_broadcast];
++ data[xgmib_tx_underflow_err] += gsrc[gmib_tx_underrun];
++ data[xgmib_tx_bytes_g] += gsrc[gmib_tx_bytes];
++ data[xgmib_tx_frames_g] += gsrc[gmib_tx_broadcast];
++ data[xgmib_tx_frames_g] += gsrc[gmib_tx_multicast];
++ data[xgmib_tx_frames_g] += gsrc[gmib_tx_unicast];
++ data[xgmib_tx_pause] += gsrc[gmib_tx_pause];
++
++ data[xgmib_rx_frames] += gsrc[gmib_rx_broadcast];
++ data[xgmib_rx_frames] += gsrc[gmib_rx_multicast];
++ data[xgmib_rx_frames] += gsrc[gmib_rx_unicast];
++ data[xgmib_rx_bytes] += gsrc[gmib_rx_bytes_g];
++ data[xgmib_rx_bytes] += gsrc[gmib_rx_bytes_b];
++ data[xgmib_rx_bytes_g] += gsrc[gmib_rx_bytes_g];
++ data[xgmib_rx_broadcast_g] += gsrc[gmib_rx_broadcast];
++ data[xgmib_rx_multicast_g] += gsrc[gmib_rx_multicast];
++ data[xgmib_rx_crc_err] += gsrc[gmib_rx_fcserr];
++ data[xgmib_rx_crc_err] += gsrc[gmib_rx_frag];
++ data[xgmib_rx_frag_err] += gsrc[gmib_rx_frag];
++ data[xgmib_rx_pkt64] += gsrc[gmib_rx_pkt64];
++ data[xgmib_rx_pkt65to127] += gsrc[gmib_rx_pkt65to127];
++ data[xgmib_rx_pkt128to255] += gsrc[gmib_rx_pkt128to255];
++ data[xgmib_rx_pkt256to511] += gsrc[gmib_rx_pkt256to511];
++ data[xgmib_rx_pkt512to1023] += gsrc[gmib_rx_pkt512to1023];
++ data[xgmib_rx_pkt1024tomax] += gsrc[gmib_rx_pkt1024to1518];
++ data[xgmib_rx_pkt1024tomax] += gsrc[gmib_rx_pkt1519tomax];
++ data[xgmib_rx_unicast_g] += gsrc[gmib_rx_unicast];
++ data[xgmib_rx_pause] += gsrc[gmib_rx_pause];
+
+ spin_unlock(&ppe_port->gmib_stats_lock);
+- } else {
+- for (i = 0; i < ARRAY_SIZE(xgmib_info); i++)
+- data[i] = ppe_port_xgmib_get(ppe_port, i);
+ }
+ }
+
+@@ -410,56 +493,57 @@ void ppe_port_get_ethtool_stats(struct p
+ void ppe_port_get_stats64(struct ppe_port *ppe_port,
+ struct rtnl_link_stats64 *s)
+ {
+- if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) {
+- u64 *src = ppe_port->gmib_stats;
++ s->multicast = ppe_port_xgmib_get(ppe_port, xgmib_rx_multicast_g);
++
++ s->rx_packets = s->multicast;
++ s->rx_packets += ppe_port_xgmib_get(ppe_port, xgmib_rx_unicast_g);
++ s->rx_packets += ppe_port_xgmib_get(ppe_port, xgmib_rx_broadcast_g);
++
++ s->tx_packets = ppe_port_xgmib_get(ppe_port, xgmib_tx_frames);
++ s->rx_bytes = ppe_port_xgmib_get(ppe_port, xgmib_rx_bytes);
++ s->tx_bytes = ppe_port_xgmib_get(ppe_port, xgmib_tx_bytes);
++
++ s->rx_crc_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_crc_err);
++ s->rx_fifo_errors = ppe_port_xgmib_get(ppe_port,
++ xgmib_rx_fifo_overflow);
++
++ s->rx_length_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_len_err);
++ s->rx_errors = s->rx_crc_errors +
++ s->rx_fifo_errors + s->rx_length_errors;
++ s->rx_dropped = s->rx_errors;
++
++ s->tx_fifo_errors = ppe_port_xgmib_get(ppe_port,
++ xgmib_tx_underflow_err);
++ s->tx_errors = s->tx_packets -
++ ppe_port_xgmib_get(ppe_port, xgmib_tx_frames_g);
++
++ if (ppe_port->gmib_stats) {
++ u64 *gsrc = ppe_port->gmib_stats;
++ u64 temp;
+
+ spin_lock(&ppe_port->gmib_stats_lock);
+
+ ppe_port_gmib_update(ppe_port);
+
+- s->rx_packets = src[gmib_rx_unicast] +
+- src[gmib_rx_broadcast] + src[gmib_rx_multicast];
+-
+- s->tx_packets = src[gmib_tx_unicast] +
+- src[gmib_tx_broadcast] + src[gmib_tx_multicast];
+-
+- s->rx_bytes = src[gmib_rx_bytes_g];
+- s->tx_bytes = src[gmib_tx_bytes];
+- s->multicast = src[gmib_rx_multicast];
+-
+- s->rx_crc_errors = src[gmib_rx_fcserr] + src[gmib_rx_frag];
+- s->rx_frame_errors = src[gmib_rx_alignerr];
+- s->rx_errors = s->rx_crc_errors + s->rx_frame_errors;
+- s->rx_dropped = src[gmib_rx_toolong] + s->rx_errors;
+-
+- s->tx_fifo_errors = src[gmib_tx_underrun];
+- s->tx_aborted_errors = src[gmib_tx_abortcol];
+- s->tx_errors = s->tx_fifo_errors + s->tx_aborted_errors;
+- s->collisions = src[gmib_tx_collisions];
++ s->multicast += gsrc[gmib_rx_multicast];
++ s->rx_packets += gsrc[gmib_rx_unicast];
++ s->rx_packets += gsrc[gmib_rx_broadcast];
++ s->rx_packets += gsrc[gmib_rx_multicast];
++ s->tx_packets += gsrc[gmib_tx_unicast];
++ s->tx_packets += gsrc[gmib_tx_broadcast];
++ s->tx_packets += gsrc[gmib_tx_multicast];
++ s->rx_bytes += gsrc[gmib_rx_bytes_g];
++ s->tx_bytes += gsrc[gmib_tx_bytes];
++ temp = gsrc[gmib_rx_fcserr] + gsrc[gmib_rx_frag];
++ s->rx_crc_errors += temp;
++ temp += gsrc[gmib_rx_alignerr];
++ s->rx_errors += temp;
++ s->rx_dropped += temp;
++ s->tx_fifo_errors += gsrc[gmib_tx_underrun];
++ s->tx_errors += gsrc[gmib_tx_underrun];
++ s->tx_errors += gsrc[gmib_tx_abortcol];
+
+ spin_unlock(&ppe_port->gmib_stats_lock);
+- } else {
+- s->multicast = ppe_port_xgmib_get(ppe_port, xgmib_rx_multicast_g);
+-
+- s->rx_packets = s->multicast;
+- s->rx_packets += ppe_port_xgmib_get(ppe_port, xgmib_rx_unicast_g);
+- s->rx_packets += ppe_port_xgmib_get(ppe_port, xgmib_rx_broadcast_g);
+-
+- s->tx_packets = ppe_port_xgmib_get(ppe_port, xgmib_tx_frames);
+- s->rx_bytes = ppe_port_xgmib_get(ppe_port, xgmib_rx_bytes);
+- s->tx_bytes = ppe_port_xgmib_get(ppe_port, xgmib_tx_bytes);
+-
+- s->rx_crc_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_crc_err);
+- s->rx_fifo_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_fifo_overflow);
+-
+- s->rx_length_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_len_err);
+- s->rx_errors = s->rx_crc_errors +
+- s->rx_fifo_errors + s->rx_length_errors;
+- s->rx_dropped = s->rx_errors;
+-
+- s->tx_fifo_errors = ppe_port_xgmib_get(ppe_port, xgmib_tx_underflow_err);
+- s->tx_errors = s->tx_packets -
+- ppe_port_xgmib_get(ppe_port, xgmib_tx_frames_g);
+ }
+ }
+
+@@ -479,73 +563,37 @@ int ppe_port_set_mac_address(struct ppe_
+ u32 reg, val;
+ int ret;
+
+- if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) {
+- reg = PPE_PORT_GMAC_ADDR(port);
+- val = (addr[5] << 8) | addr[4];
+- ret = regmap_write(ppe_dev->regmap, reg + GMAC_GOL_ADDR0_ADDR, val);
+- if (ret)
+- return ret;
+-
+- val = (addr[0] << 24) | (addr[1] << 16) |
+- (addr[2] << 8) | addr[3];
+- ret = regmap_write(ppe_dev->regmap, reg + GMAC_GOL_ADDR1_ADDR, val);
+- if (ret)
+- return ret;
+- } else {
+- reg = PPE_PORT_XGMAC_ADDR(port);
+- val = (addr[5] << 8) | addr[4] | XGMAC_ADDR_EN;
+- ret = regmap_write(ppe_dev->regmap, reg + XGMAC_ADDR0_H_ADDR, val);
+- if (ret)
+- return ret;
+-
+- val = (addr[3] << 24) | (addr[2] << 16) |
+- (addr[1] << 8) | addr[0];
+- ret = regmap_write(ppe_dev->regmap, reg + XGMAC_ADDR0_L_ADDR, val);
+- if (ret)
+- return ret;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * ppe_port_set_mac_eee() - Set EEE configuration for PPE port MAC
+- * @ppe_port: PPE port
+- * @eee: EEE settings
+- *
+- * Description: Set port MAC EEE settings for the given PPE port.
+- *
+- * Return: 0 upon success or a negative error upon failure.
+- */
+-int ppe_port_set_mac_eee(struct ppe_port *ppe_port, struct ethtool_keee *eee)
+-{
+- struct ppe_device *ppe_dev = ppe_port->ppe_dev;
+- int port = ppe_port->port_id;
+- u32 val;
+- int ret;
+-
+- ret = regmap_read(ppe_dev->regmap, PPE_LPI_EN_ADDR, &val);
++ /* Set address to GMAC */
++ reg = PPE_PORT_GMAC_ADDR(port);
++ val = (addr[5] << 8) | addr[4];
++ ret = regmap_write(ppe_dev->regmap, reg + GMAC_GOL_ADDR0_ADDR, val);
+ if (ret)
+ return ret;
+
+- if (eee->tx_lpi_enabled)
+- val |= PPE_LPI_PORT_EN(port);
+- else
+- val &= ~PPE_LPI_PORT_EN(port);
++ val = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
++ ret = regmap_write(ppe_dev->regmap, reg + GMAC_GOL_ADDR1_ADDR, val);
++ if (ret)
++ return ret;
+
+- ret = regmap_write(ppe_dev->regmap, PPE_LPI_EN_ADDR, val);
++ /* Set address to XGMAC */
++ reg = PPE_PORT_XGMAC_ADDR(port);
++ val = (addr[5] << 8) | addr[4] | XGMAC_ADDR_EN;
++ ret = regmap_write(ppe_dev->regmap, reg + XGMAC_ADDR0_H_ADDR, val);
++ if (ret)
++ return ret;
+
+- return ret;
++ val = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
++ return regmap_write(ppe_dev->regmap, reg + XGMAC_ADDR0_L_ADDR, val);
+ }
+
+ /**
+- * ppe_port_set_maxframe() - Set port maximum frame size
++ * ppe_port_set_maxframe() - Set maximum frame size including MTU and MRU of port
+ * @ppe_port: PPE port structure
+- * @maxframe_size: Maximum frame size supported by PPE port
++ * @maxframe_size: Maximum frame size configured to the PPE port
+ *
+- * Description: Set MTU of network interface specified by @ppe_port.
++ * Set maximum frame size of network interface specified by @ppe_port.
+ *
+- * Return: 0 upon success or a negative error upon failure.
++ * Return: 0 on success, negative error code on failure.
+ */
+ int ppe_port_set_maxframe(struct ppe_port *ppe_port, int maxframe_size)
+ {
+@@ -585,42 +633,23 @@ int ppe_port_set_maxframe(struct ppe_por
+ /* PPE port and MAC reset */
+ static int ppe_port_mac_reset(struct ppe_port *ppe_port)
+ {
+- struct ppe_device *ppe_dev = ppe_port->ppe_dev;
+- int ret;
++ int ret, i;
+
+- ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]);
+- if (ret)
+- goto error;
+-
+- ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_RX]);
+- if (ret)
+- goto error;
+-
+- ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_TX]);
+- if (ret)
+- goto error;
+-
+- /* 150ms delay is required by hardware to reset PPE port and MAC */
+- msleep(150);
+-
+- ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]);
+- if (ret)
+- goto error;
+-
+- ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_RX]);
+- if (ret)
+- goto error;
++ for (i = PPE_PORT_CLK_RST_MAC; i < PPE_PORT_CLK_RST_MAX; i++) {
++ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]);
++ if (ret)
++ return ret;
++ }
+
+- ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_TX]);
+- if (ret)
+- goto error;
++ fsleep(10000);
+
+- return ret;
++ for (i = PPE_PORT_CLK_RST_MAC; i < PPE_PORT_CLK_RST_MAX; i++) {
++ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]);
++ if (ret)
++ return ret;
++ }
+
+-error:
+- dev_err(ppe_dev->dev, "%s: port %d reset fail %d\n",
+- __func__, ppe_port->port_id, ret);
+- return ret;
++ return 0;
+ }
+
+ /* PPE port MAC configuration for phylink */
+@@ -643,31 +672,28 @@ static void ppe_port_mac_config(struct p
+ case PHY_INTERFACE_MODE_10G_QXGMII:
+ mac_type = PPE_MAC_TYPE_XGMAC;
+ break;
++ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_QSGMII:
+ case PHY_INTERFACE_MODE_PSGMII:
+- case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ mac_type = PPE_MAC_TYPE_GMAC;
+ break;
+ default:
+- dev_err(ppe_dev->dev, "%s: Unsupport interface %s\n",
+- __func__, phy_modes(state->interface));
++ dev_err(ppe_dev->dev, "Unsupported interface %s\n",
++ phy_modes(state->interface));
+ return;
+ }
+
+- /* Reset Port MAC for GMAC */
+- if (mac_type == PPE_MAC_TYPE_GMAC) {
+- ret = ppe_port_mac_reset(ppe_port);
+- if (ret)
+- goto err_mac_config;
+- }
++ /* Reset Port MAC */
++ ret = ppe_port_mac_reset(ppe_port);
++ if (ret)
++ goto err_mac_config;
+
+ /* Port mux to select GMAC or XGMAC */
+ mask = PPE_PORT_SEL_XGMAC(port);
+ val = mac_type == PPE_MAC_TYPE_GMAC ? 0 : mask;
+ ret = regmap_update_bits(ppe_dev->regmap,
+- PPE_PORT_MUX_CTRL_ADDR,
+- mask, val);
++ PPE_PORT_MUX_CTRL_ADDR, mask, val);
+ if (ret)
+ goto err_mac_config;
+
+@@ -676,8 +702,111 @@ static void ppe_port_mac_config(struct p
+ return;
+
+ err_mac_config:
+- dev_err(ppe_dev->dev, "%s: port %d MAC config fail %d\n",
+- __func__, port, ret);
++ dev_err(ppe_dev->dev, "PPE port %d MAC config fail %d\n", port, ret);
++}
++
++/* Get port MAC speed clock rate for GMII/GMII+ interface */
++static unsigned long ppe_port_mac_clock_rate_get_gmii(int speed)
++{
++ unsigned long rate = 0;
++
++ switch (speed) {
++ case SPEED_2500:
++ rate = 312500000;
++ break;
++ case SPEED_1000:
++ rate = 125000000;
++ break;
++ case SPEED_100:
++ rate = 25000000;
++ break;
++ case SPEED_10:
++ rate = 2500000;
++ break;
++ default:
++ break;
++ }
++
++ return rate;
++}
++
++/* Get port MAC speed clock rate for XGMII interface */
++static unsigned long ppe_port_mac_clock_rate_get_xgmii(int speed)
++{
++ unsigned long rate = 0;
++
++ switch (speed) {
++ case SPEED_10000:
++ rate = 312500000;
++ break;
++ case SPEED_5000:
++ rate = 156250000;
++ break;
++ case SPEED_2500:
++ rate = 78125000;
++ break;
++ case SPEED_1000:
++ rate = 125000000;
++ break;
++ case SPEED_100:
++ rate = 12500000;
++ break;
++ case SPEED_10:
++ rate = 1250000;
++ break;
++ default:
++ break;
++ }
++
++ return rate;
++}
++
++/* Set PPE port MAC speed clock to appropriate rate */
++static int ppe_port_mac_speed_clock_rate_set(struct ppe_port *ppe_port,
++ phy_interface_t interface,
++ int speed)
++{
++ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
++ struct device *device = ppe_dev->dev;
++ unsigned long rate;
++ int ret;
++
++ switch (interface) {
++ case PHY_INTERFACE_MODE_SGMII:
++ case PHY_INTERFACE_MODE_QSGMII:
++ case PHY_INTERFACE_MODE_PSGMII:
++ case PHY_INTERFACE_MODE_2500BASEX:
++ rate = ppe_port_mac_clock_rate_get_gmii(speed);
++ break;
++ case PHY_INTERFACE_MODE_USXGMII:
++ case PHY_INTERFACE_MODE_10GBASER:
++ case PHY_INTERFACE_MODE_10G_QXGMII:
++ rate = ppe_port_mac_clock_rate_get_xgmii(speed);
++ break;
++ default:
++ dev_err(device,
++ "Unsupported interface %s\n", phy_modes(interface));
++ return -EOPNOTSUPP;
++ }
++
++ if (rate == 0) {
++ dev_err(device, "Invalid port speed clock rate\n");
++ return -EINVAL;
++ }
++
++ ret = clk_set_rate(ppe_port->clks[PPE_PORT_CLK_RST_RX], rate);
++ if (ret) {
++ dev_err(device, "Failed to set PPE port RX clock rate\n");
++ return ret;
++ }
++
++ ret = clk_set_rate(ppe_port->clks[PPE_PORT_CLK_RST_TX], rate);
++ if (ret) {
++ dev_err(device, "Failed to set PPE port TX clock rate\n");
++ return ret;
++ }
++
++ return 0;
+ }
+
+ /* PPE port GMAC link up configuration */
+@@ -688,6 +817,11 @@ static int ppe_port_gmac_link_up(struct
+ int ret, port = ppe_port->port_id;
+ u32 reg, val;
+
++ /* Start GMAC MIB statistics polling work task */
++ ret = ppe_port_gmib_work_start(ppe_port);
++ if (ret)
++ return ret;
++
+ /* Set GMAC speed */
+ switch (speed) {
+ case SPEED_1000:
+@@ -700,8 +834,8 @@ static int ppe_port_gmac_link_up(struct
+ val = GMAC_SPEED_10;
+ break;
+ default:
+- dev_err(ppe_dev->dev, "%s: Invalid GMAC speed %s\n",
+- __func__, phy_speed_to_str(speed));
++ dev_err(ppe_dev->dev, "Invalid GMAC speed %s\n",
++ phy_speed_to_str(speed));
+ return -EINVAL;
+ }
+
+@@ -720,10 +854,8 @@ static int ppe_port_gmac_link_up(struct
+ if (rx_pause)
+ val |= GMAC_RXFCEN;
+
+- ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_ENABLE_ADDR,
+- GMAC_ENABLE_ALL, val);
+-
+- return ret;
++ return regmap_update_bits(ppe_dev->regmap, reg + GMAC_ENABLE_ADDR,
++ GMAC_ENABLE_ALL, val);
+ }
+
+ /* PPE port XGMAC link up configuration */
+@@ -764,8 +896,8 @@ static int ppe_port_xgmac_link_up(struct
+ val = XGMAC_SPEED_10;
+ break;
+ default:
+- dev_err(ppe_dev->dev, "%s: Invalid XGMAC speed %s\n",
+- __func__, phy_speed_to_str(speed));
++ dev_err(ppe_dev->dev, "Invalid XGMAC speed %s\n",
++ phy_speed_to_str(speed));
+ return -EINVAL;
+ }
+
+@@ -792,10 +924,8 @@ static int ppe_port_xgmac_link_up(struct
+ return ret;
+
+ /* Enable XGMAC RX*/
+- ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_RX_CONFIG_ADDR,
+- XGMAC_RXEN, XGMAC_RXEN);
+-
+- return ret;
++ return regmap_set_bits(ppe_dev->regmap, reg + XGMAC_RX_CONFIG_ADDR,
++ XGMAC_RXEN);
+ }
+
+ /* PPE port MAC link up configuration for phylink */
+@@ -813,9 +943,12 @@ static void ppe_port_mac_link_up(struct
+ int ret, port = ppe_port->port_id;
+ u32 reg, val;
+
+- /* Start GMIB statistics polling */
+- schedule_delayed_work(&ppe_port->gmib_read, 0);
++ /* Set PPE port MAC speed clock */
++ ret = ppe_port_mac_speed_clock_rate_set(ppe_port, interface, speed);
++ if (ret)
++ goto err_port_mac_link_up;
+
++ /* Configure PPE MAC according current speed */
+ if (mac_type == PPE_MAC_TYPE_GMAC)
+ ret = ppe_port_gmac_link_up(ppe_port,
+ speed, duplex, tx_pause, rx_pause);
+@@ -836,17 +969,47 @@ static void ppe_port_mac_link_up(struct
+
+ /* Enable PPE port TX */
+ reg = PPE_PORT_BRIDGE_CTRL_ADDR + PPE_PORT_BRIDGE_CTRL_INC * port;
+- ret = regmap_update_bits(ppe_dev->regmap, reg,
+- PPE_PORT_BRIDGE_TXMAC_EN,
+- PPE_PORT_BRIDGE_TXMAC_EN);
++ ret = regmap_set_bits(ppe_dev->regmap, reg, PPE_PORT_BRIDGE_TXMAC_EN);
+ if (ret)
+ goto err_port_mac_link_up;
+
+ return;
+
+ err_port_mac_link_up:
+- dev_err(ppe_dev->dev, "%s: port %d link up fail %d\n",
+- __func__, port, ret);
++ dev_err(ppe_dev->dev, "PPE port %d link up fail %d\n", port, ret);
++}
++
++/* PPE port GMAC link down configuration */
++static int ppe_port_gmac_link_down(struct ppe_port *ppe_port)
++{
++ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
++ int port = ppe_port->port_id;
++ u32 reg;
++
++ /* Stop GMAC MIB statistics polling work task */
++ ppe_port_gmib_work_stop(ppe_port);
++
++ /* Disable GMAC RX and TX */
++ reg = PPE_PORT_GMAC_ADDR(port) + GMAC_ENABLE_ADDR;
++ return regmap_clear_bits(ppe_dev->regmap, reg, GMAC_TRXEN);
++}
++
++/* PPE port XGMAC link down configuration */
++static int ppe_port_xgmac_link_down(struct ppe_port *ppe_port)
++{
++ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
++ int ret, port = ppe_port->port_id;
++ u32 reg;
++
++ /* Disable XGMAC RX and TX */
++ reg = PPE_PORT_XGMAC_ADDR(port);
++ ret = regmap_clear_bits(ppe_dev->regmap,
++ reg + XGMAC_RX_CONFIG_ADDR, XGMAC_RXEN);
++ if (ret)
++ return ret;
++
++ return regmap_clear_bits(ppe_dev->regmap,
++ reg + XGMAC_TX_CONFIG_ADDR, XGMAC_TXEN);
+ }
+
+ /* PPE port MAC link down configuration for phylink */
+@@ -861,48 +1024,28 @@ static void ppe_port_mac_link_down(struc
+ int ret, port = ppe_port->port_id;
+ u32 reg;
+
+- /* Stop GMIB statistics polling */
+- cancel_delayed_work_sync(&ppe_port->gmib_read);
+-
+ /* Disable PPE port TX */
+ reg = PPE_PORT_BRIDGE_CTRL_ADDR + PPE_PORT_BRIDGE_CTRL_INC * port;
+- ret = regmap_update_bits(ppe_dev->regmap, reg,
+- PPE_PORT_BRIDGE_TXMAC_EN, 0);
++ ret = regmap_clear_bits(ppe_dev->regmap, reg, PPE_PORT_BRIDGE_TXMAC_EN);
+ if (ret)
+ goto err_port_mac_link_down;
+
+- /* Disable PPE MAC */
+- if (mac_type == PPE_MAC_TYPE_GMAC) {
+- reg = PPE_PORT_GMAC_ADDR(port) + GMAC_ENABLE_ADDR;
+- ret = regmap_update_bits(ppe_dev->regmap, reg, GMAC_TRXEN, 0);
+- if (ret)
+- goto err_port_mac_link_down;
+- } else {
+- reg = PPE_PORT_XGMAC_ADDR(port);
+- ret = regmap_update_bits(ppe_dev->regmap,
+- reg + XGMAC_RX_CONFIG_ADDR,
+- XGMAC_RXEN, 0);
+- if (ret)
+- goto err_port_mac_link_down;
+-
+- ret = regmap_update_bits(ppe_dev->regmap,
+- reg + XGMAC_TX_CONFIG_ADDR,
+- XGMAC_TXEN, 0);
+- if (ret)
+- goto err_port_mac_link_down;
+- }
++ if (mac_type == PPE_MAC_TYPE_GMAC)
++ ret = ppe_port_gmac_link_down(ppe_port);
++ else
++ ret = ppe_port_xgmac_link_down(ppe_port);
++ if (ret)
++ goto err_port_mac_link_down;
+
+ return;
+
+ err_port_mac_link_down:
+- dev_err(ppe_dev->dev, "%s: port %d link down fail %d\n",
+- __func__, port, ret);
++ dev_err(ppe_dev->dev, "PPE port %d link down fail %d\n", port, ret);
+ }
+
+ /* PPE port MAC PCS selection for phylink */
+-static
+-struct phylink_pcs *ppe_port_mac_select_pcs(struct phylink_config *config,
+- phy_interface_t interface)
++static struct phylink_pcs *ppe_port_mac_select_pcs(struct phylink_config *config,
++ phy_interface_t interface)
+ {
+ struct ppe_port *ppe_port = container_of(config, struct ppe_port,
+ phylink_config);
+@@ -920,8 +1063,8 @@ struct phylink_pcs *ppe_port_mac_select_
+ PPE_PORT_MUX_CTRL_ADDR,
+ PPE_PORT5_SEL_PCS1, val);
+ if (ret) {
+- dev_err(ppe_dev->dev, "%s: port5 select PCS fail %d\n",
+- __func__, ret);
++ dev_err(ppe_dev->dev, "PPE port5 select PCS fail %d\n",
++ ret);
+ return NULL;
+ }
+ }
+@@ -936,6 +1079,17 @@ static const struct phylink_mac_ops ppe_
+ .mac_select_pcs = ppe_port_mac_select_pcs,
+ };
+
++static const phy_interface_t mac_interfaces[] = {
++ PHY_INTERFACE_MODE_SGMII,
++ PHY_INTERFACE_MODE_QSGMII,
++ PHY_INTERFACE_MODE_PSGMII,
++ PHY_INTERFACE_MODE_1000BASEX,
++ PHY_INTERFACE_MODE_2500BASEX,
++ PHY_INTERFACE_MODE_USXGMII,
++ PHY_INTERFACE_MODE_10GBASER,
++ PHY_INTERFACE_MODE_10G_QXGMII,
++};
++
+ /**
+ * ppe_port_phylink_setup() - Set phylink instance for the given PPE port
+ * @ppe_port: PPE port
+@@ -950,9 +1104,9 @@ int ppe_port_phylink_setup(struct ppe_po
+ {
+ struct ppe_device *ppe_dev = ppe_port->ppe_dev;
+ struct device_node *pcs_node;
+- int ret;
++ int i, ret;
+
+- /* Create PCS */
++ /* Get PCS instance */
+ pcs_node = of_parse_phandle(ppe_port->np, "pcs-handle", 0);
+ if (!pcs_node)
+ return -ENODEV;
+@@ -960,8 +1114,8 @@ int ppe_port_phylink_setup(struct ppe_po
+ ppe_port->pcs = ipq_pcs_get(pcs_node);
+ of_node_put(pcs_node);
+ if (IS_ERR(ppe_port->pcs)) {
+- dev_err(ppe_dev->dev, "%s: port %d failed to create PCS\n",
+- __func__, ppe_port->port_id);
++ dev_err(ppe_dev->dev, "PPE port %d failed to create PCS\n",
++ ppe_port->port_id);
+ return PTR_ERR(ppe_port->pcs);
+ }
+
+@@ -971,22 +1125,10 @@ int ppe_port_phylink_setup(struct ppe_po
+ ppe_port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE |
+ MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000 |
+ MAC_2500FD | MAC_5000FD | MAC_10000FD;
+- __set_bit(PHY_INTERFACE_MODE_QSGMII,
+- ppe_port->phylink_config.supported_interfaces);
+- __set_bit(PHY_INTERFACE_MODE_PSGMII,
+- ppe_port->phylink_config.supported_interfaces);
+- __set_bit(PHY_INTERFACE_MODE_SGMII,
+- ppe_port->phylink_config.supported_interfaces);
+- __set_bit(PHY_INTERFACE_MODE_1000BASEX,
+- ppe_port->phylink_config.supported_interfaces);
+- __set_bit(PHY_INTERFACE_MODE_2500BASEX,
+- ppe_port->phylink_config.supported_interfaces);
+- __set_bit(PHY_INTERFACE_MODE_USXGMII,
+- ppe_port->phylink_config.supported_interfaces);
+- __set_bit(PHY_INTERFACE_MODE_10GBASER,
+- ppe_port->phylink_config.supported_interfaces);
+- __set_bit(PHY_INTERFACE_MODE_10G_QXGMII,
+- ppe_port->phylink_config.supported_interfaces);
++
++ for (i = 0; i < ARRAY_SIZE(mac_interfaces); i++)
++ __set_bit(mac_interfaces[i],
++ ppe_port->phylink_config.supported_interfaces);
+
+ /* Create phylink */
+ ppe_port->phylink = phylink_create(&ppe_port->phylink_config,
+@@ -994,8 +1136,8 @@ int ppe_port_phylink_setup(struct ppe_po
+ ppe_port->interface,
+ &ppe_phylink_ops);
+ if (IS_ERR(ppe_port->phylink)) {
+- dev_err(ppe_dev->dev, "%s: port %d failed to create phylink\n",
+- __func__, ppe_port->port_id);
++ dev_err(ppe_dev->dev, "PPE port %d failed to create phylink\n",
++ ppe_port->port_id);
+ ret = PTR_ERR(ppe_port->phylink);
+ goto err_free_pcs;
+ }
+@@ -1003,8 +1145,8 @@ int ppe_port_phylink_setup(struct ppe_po
+ /* Connect phylink */
+ ret = phylink_of_phy_connect(ppe_port->phylink, ppe_port->np, 0);
+ if (ret) {
+- dev_err(ppe_dev->dev, "%s: port %d failed to connect phylink\n",
+- __func__, ppe_port->port_id);
++ dev_err(ppe_dev->dev, "PPE port %d failed to connect phylink: %pe\n",
++ ppe_port->port_id, ERR_PTR(ret));
+ goto err_free_phylink;
+ }
+
+@@ -1037,7 +1179,7 @@ void ppe_port_phylink_destroy(struct ppe
+ ppe_port->phylink = NULL;
+ }
+
+- /* Destroy PCS */
++ /* Release PCS instance */
+ if (ppe_port->pcs) {
+ ipq_pcs_put(ppe_port->pcs);
+ ppe_port->pcs = NULL;
+@@ -1050,7 +1192,7 @@ static int ppe_port_clock_init(struct pp
+ struct device_node *port_node = ppe_port->np;
+ struct reset_control *rstc;
+ struct clk *clk;
+- int i, j, ret;
++ int i, ret;
+
+ for (i = 0; i < PPE_PORT_CLK_RST_MAX; i++) {
+ /* Get PPE port resets which will be used to reset PPE
+@@ -1084,10 +1226,11 @@ err_clk_en:
+ err_clk_get:
+ reset_control_put(rstc);
+ err_rst:
+- for (j = 0; j < i; j++) {
+- clk_disable_unprepare(ppe_port->clks[j]);
+- clk_put(ppe_port->clks[j]);
+- reset_control_put(ppe_port->rstcs[j]);
++ while (i) {
++ i--;
++ clk_disable_unprepare(ppe_port->clks[i]);
++ clk_put(ppe_port->clks[i]);
++ reset_control_put(ppe_port->rstcs[i]);
+ }
+
+ return ret;
+@@ -1114,12 +1257,12 @@ static int ppe_port_mac_hw_init(struct p
+
+ /* GMAC RX and TX are initialized as disabled */
+ reg = PPE_PORT_GMAC_ADDR(port);
+- ret = regmap_update_bits(ppe_dev->regmap,
+- reg + GMAC_ENABLE_ADDR, GMAC_TRXEN, 0);
++ ret = regmap_clear_bits(ppe_dev->regmap,
++ reg + GMAC_ENABLE_ADDR, GMAC_TRXEN);
+ if (ret)
+ return ret;
+
+- /* GMAC max frame size configuration */
++ /* GMAC jumbo frame size and max frame size configuration */
+ val = FIELD_PREP(GMAC_JUMBO_SIZE_M, PPE_PORT_MAC_MAX_FRAME_SIZE);
+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_JUMBO_SIZE_ADDR,
+ GMAC_JUMBO_SIZE_M, val);
+@@ -1128,13 +1271,13 @@ static int ppe_port_mac_hw_init(struct p
+
+ val = FIELD_PREP(GMAC_MAXFRAME_SIZE_M, PPE_PORT_MAC_MAX_FRAME_SIZE);
+ val |= FIELD_PREP(GMAC_TX_THD_M, 0x1);
+- ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_CTRL_ADDR,
++ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_CTRL0_ADDR,
+ GMAC_CTRL_MASK, val);
+ if (ret)
+ return ret;
+
+ val = FIELD_PREP(GMAC_HIGH_IPG_M, 0xc);
+- ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_DBG_CTRL_ADDR,
++ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_CTRL1_ADDR,
+ GMAC_HIGH_IPG_M, val);
+ if (ret)
+ return ret;
+@@ -1142,13 +1285,13 @@ static int ppe_port_mac_hw_init(struct p
+ /* Enable and reset GMAC MIB counters and set as read clear
+ * mode, the GMAC MIB counters will be cleared after reading.
+ */
+- ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_MIB_CTRL_ADDR,
+- GMAC_MIB_CTRL_MASK, GMAC_MIB_CTRL_MASK);
++ ret = regmap_set_bits(ppe_dev->regmap, reg + GMAC_MIB_CTRL_ADDR,
++ GMAC_MIB_CTRL_MASK);
+ if (ret)
+ return ret;
+
+- ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_MIB_CTRL_ADDR,
+- GMAC_MIB_RST, 0);
++ ret = regmap_clear_bits(ppe_dev->regmap, reg + GMAC_MIB_CTRL_ADDR,
++ GMAC_MIB_RST);
+ if (ret)
+ return ret;
+
+@@ -1179,31 +1322,8 @@ static int ppe_port_mac_hw_init(struct p
+ return ret;
+
+ /* Enable and reset XGMAC MIB counters */
+- ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_MMC_CTRL_ADDR,
+- XGMAC_MCF | XGMAC_CNTRST, XGMAC_CNTRST);
+-
+- return ret;
+-}
+-
+-/* PPE port MAC MIB work task initialization */
+-static int ppe_port_mac_mib_work_init(struct ppe_port *ppe_port)
+-{
+- struct ppe_device *ppe_dev = ppe_port->ppe_dev;
+- u64 *gstats;
+-
+- gstats = devm_kzalloc(ppe_dev->dev,
+- sizeof(*gstats) * ARRAY_SIZE(gmib_info),
+- GFP_KERNEL);
+- if (!gstats)
+- return -ENOMEM;
+-
+- ppe_port->gmib_stats = gstats;
+-
+- spin_lock_init(&ppe_port->gmib_stats_lock);
+- INIT_DELAYED_WORK(&ppe_port->gmib_read,
+- ppe_port_gmib_stats_poll);
+-
+- return 0;
++ return regmap_update_bits(ppe_dev->regmap, reg + XGMAC_MMC_CTRL_ADDR,
++ XGMAC_MCF | XGMAC_CNTRST, XGMAC_CNTRST);
+ }
+
+ /**
+@@ -1218,8 +1338,8 @@ static int ppe_port_mac_mib_work_init(st
+ int ppe_port_mac_init(struct ppe_device *ppe_dev)
+ {
+ struct device_node *ports_node, *port_node;
+- int port, num, ret, j, i = 0;
+ struct ppe_ports *ppe_ports;
++ int port, num, ret, i = 0;
+ phy_interface_t phy_mode;
+
+ ports_node = of_get_child_by_name(ppe_dev->dev->of_node,
+@@ -1259,6 +1379,7 @@ int ppe_port_mac_init(struct ppe_device
+ ppe_ports->port[i].port_id = port;
+ ppe_ports->port[i].np = port_node;
+ ppe_ports->port[i].interface = phy_mode;
++ ppe_ports->port[i].mac_type = PPE_MAC_TYPE_GMAC;
+
+ ret = ppe_port_clock_init(&ppe_ports->port[i]);
+ if (ret) {
+@@ -1272,12 +1393,6 @@ int ppe_port_mac_init(struct ppe_device
+ goto err_port_node;
+ }
+
+- ret = ppe_port_mac_mib_work_init(&ppe_ports->port[i]);
+- if (ret) {
+- dev_err(ppe_dev->dev, "Failed to initialize MAC MIB work\n");
+- goto err_port_node;
+- }
+-
+ ret = edma_port_setup(&ppe_ports->port[i]);
+ if (ret) {
+ dev_err(ppe_dev->dev, "QCOM EDMA port setup failed\n");
+@@ -1299,8 +1414,11 @@ err_port_setup:
+ }
+
+ err_port_clk:
+- for (j = 0; j < i; j++)
+- ppe_port_clock_deinit(&ppe_ports->port[j]);
++ while (i) {
++ i--;
++ ppe_port_clock_deinit(&ppe_ports->port[i]);
++ }
++
+ err_port_node:
+ of_node_put(port_node);
+ err_ports_node:
+@@ -1322,10 +1440,7 @@ void ppe_port_mac_deinit(struct ppe_devi
+
+ for (i = 0; i < ppe_dev->ports->num; i++) {
+ ppe_port = &ppe_dev->ports->port[i];
+-
+- /* Destroy all phylinks and edma ports */
+ edma_port_destroy(ppe_port);
+-
+ ppe_port_clock_deinit(ppe_port);
+ }
+ }
+--- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.h
++++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h
+@@ -1,16 +1,23 @@
+ /* SPDX-License-Identifier: GPL-2.0-only
+ *
+- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+ #ifndef __PPE_PORT_H__
+ #define __PPE_PORT_H__
+
++#include <linux/compiler.h>
++#include <linux/phy.h>
+ #include <linux/phylink.h>
+
+-struct ethtool_keee;
++struct clk;
++struct device_node;
++struct net_device;
++struct reset_control;
+ struct rtnl_link_stats64;
+
++struct ppe_device;
++
+ /**
+ * enum ppe_port_clk_rst_type - PPE port clock and reset ID type
+ * @PPE_PORT_CLK_RST_MAC: The clock and reset ID for port MAC
+@@ -37,14 +44,14 @@ enum ppe_mac_type {
+
+ /**
+ * struct ppe_port - Private data for each PPE port
+- * @phylink: Linux phylink instance
+- * @phylink_config: Linux phylink configurations
+- * @pcs: Linux phylink PCS instance
+ * @np: Port device tree node
+ * @ppe_dev: Back pointer to PPE device private data
+ * @interface: Port interface mode
+ * @mac_type: Port MAC type, GMAC or XGMAC
+ * @port_id: Port ID
++ * @phylink: Linux phylink instance
++ * @phylink_config: Linux phylink configurations
++ * @pcs: Linux phylink PCS instance
+ * @clks: Port clocks
+ * @rstcs: Port resets
+ * @gmib_read: Delay work task for GMAC MIB statistics polling function
+@@ -52,14 +59,14 @@ enum ppe_mac_type {
+ * @gmib_stats_lock: Lock to protect GMAC MIB statistics
+ */
+ struct ppe_port {
+- struct phylink *phylink;
+- struct phylink_config phylink_config;
+- struct phylink_pcs *pcs;
+ struct device_node *np;
+ struct ppe_device *ppe_dev;
+ phy_interface_t interface;
+ enum ppe_mac_type mac_type;
+ int port_id;
++ struct phylink *phylink;
++ struct phylink_config phylink_config;
++ struct phylink_pcs *pcs;
+ struct clk *clks[PPE_PORT_CLK_RST_MAX];
+ struct reset_control *rstcs[PPE_PORT_CLK_RST_MAX];
+ struct delayed_work gmib_read;
+@@ -88,6 +95,5 @@ void ppe_port_get_ethtool_stats(struct p
+ void ppe_port_get_stats64(struct ppe_port *ppe_port,
+ struct rtnl_link_stats64 *s);
+ int ppe_port_set_mac_address(struct ppe_port *ppe_port, const u8 *addr);
+-int ppe_port_set_mac_eee(struct ppe_port *ppe_port, struct ethtool_keee *eee);
+ int ppe_port_set_maxframe(struct ppe_port *ppe_port, int maxframe_size);
+ #endif
+--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
++++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
+@@ -20,16 +20,6 @@
+ #define PPE_PORT5_SEL_PCS1 BIT(4)
+ #define PPE_PORT_SEL_XGMAC(x) (BIT(8) << ((x) - 1))
+
+-/* PPE port LPI enable register */
+-#define PPE_LPI_EN_ADDR 0x400
+-#define PPE_LPI_PORT1_EN BIT(0)
+-#define PPE_LPI_PORT2_EN BIT(1)
+-#define PPE_LPI_PORT3_EN BIT(2)
+-#define PPE_LPI_PORT4_EN BIT(3)
+-#define PPE_LPI_PORT5_EN BIT(4)
+-#define PPE_LPI_PORT6_EN BIT(5)
+-#define PPE_LPI_PORT_EN(x) (BIT(0) << ((x) - 1))
+-
+ /* PPE scheduler configurations for buffer manager block. */
+ #define PPE_BM_SCH_CTRL_ADDR 0xb000
+ #define PPE_BM_SCH_CTRL_INC 4
+@@ -47,9 +37,6 @@
+ #define PPE_DROP_STAT_TBL_ENTRIES 30
+ #define PPE_DROP_STAT_TBL_INC 0x10
+
+-#define PPE_EPE_DBG_IN_CNT_ADDR 0x26054
+-#define PPE_EPE_DBG_OUT_CNT_ADDR 0x26070
+-
+ /* Egress VLAN counters. */
+ #define PPE_EG_VSI_COUNTER_TBL_ADDR 0x41000
+ #define PPE_EG_VSI_COUNTER_TBL_ENTRIES 64
+@@ -578,6 +565,41 @@
+ #define PPE_ENQ_OPR_TBL_INC 0x10
+ #define PPE_ENQ_OPR_TBL_ENQ_DISABLE BIT(0)
+
++/* Unicast drop count includes the possible drops with WRED for the green,
++ * yellow and red categories.
++ */
++#define PPE_UNICAST_DROP_CNT_TBL_ADDR 0x9e0000
++#define PPE_UNICAST_DROP_CNT_TBL_ENTRIES 1536
++#define PPE_UNICAST_DROP_CNT_TBL_INC 0x10
++#define PPE_UNICAST_DROP_TYPES 6
++#define PPE_UNICAST_DROP_FORCE_OFFSET 3
++
++/* There are 16 multicast queues dedicated to CPU port 0. Multicast drop
++ * count includes the force drop for green, yellow and red category packets.
++ */
++#define PPE_P0_MULTICAST_DROP_CNT_TBL_ADDR 0x9f0000
++#define PPE_P0_MULTICAST_DROP_CNT_TBL_ENTRIES 48
++#define PPE_P0_MULTICAST_DROP_CNT_TBL_INC 0x10
++#define PPE_P0_MULTICAST_QUEUE_NUM 16
++
++/* Each PPE physical port has four dedicated multicast queues, providing
++ * a total of 12 entries per port. The multicast drop count includes forced
++ * drops for green, yellow, and red category packets.
++ */
++#define PPE_MULTICAST_QUEUE_PORT_ADDR_INC 0x1000
++#define PPE_MULTICAST_DROP_CNT_TBL_INC 0x10
++#define PPE_MULTICAST_DROP_TYPES 3
++#define PPE_MULTICAST_QUEUE_NUM 4
++#define PPE_MULTICAST_DROP_CNT_TBL_ENTRIES 12
++
++#define PPE_CPU_PORT_MULTICAST_FORCE_DROP_CNT_TBL_ADDR(mq_offset) \
++ (PPE_P0_MULTICAST_DROP_CNT_TBL_ADDR + \
++ (mq_offset) * PPE_P0_MULTICAST_DROP_CNT_TBL_INC * \
++ PPE_MULTICAST_DROP_TYPES)
++
++#define PPE_P1_MULTICAST_DROP_CNT_TBL_ADDR \
++ (PPE_P0_MULTICAST_DROP_CNT_TBL_ADDR + PPE_MULTICAST_QUEUE_PORT_ADDR_INC)
++
+ /* PPE GMAC and XGMAC register base address */
+ #define PPE_PORT_GMAC_ADDR(x) (0x001000 + ((x) - 1) * 0x200)
+ #define PPE_PORT_XGMAC_ADDR(x) (0x500000 + ((x) - 1) * 0x4000)
+@@ -614,7 +636,7 @@
+ #define GMAC_ADDR_BYTE3 GENMASK(7, 0)
+
+ /* GMAC control register */
+-#define GMAC_CTRL_ADDR 0x18
++#define GMAC_CTRL0_ADDR 0x18
+ #define GMAC_TX_THD_M GENMASK(27, 24)
+ #define GMAC_MAXFRAME_SIZE_M GENMASK(21, 8)
+ #define GMAC_CRS_SEL BIT(6)
+@@ -623,7 +645,7 @@
+ (GMAC_TX_THD_M | GMAC_MAXFRAME_SIZE_M | GMAC_CRS_SEL)
+
+ /* GMAC debug control register */
+-#define GMAC_DBG_CTRL_ADDR 0x1c
++#define GMAC_CTRL1_ADDR 0x1c
+ #define GMAC_HIGH_IPG_M GENMASK(15, 8)
+
+ /* GMAC jumbo size register */
+@@ -778,7 +800,7 @@
+ #define XGMAC_RXBROAD_G_ADDR 0x918
+ #define XGMAC_RXMULTI_G_ADDR 0x920
+ #define XGMAC_RXCRC_ERR_ADDR 0x928
+-#define XGMAC_RXRUNT_ERR_ADDR 0x930
++#define XGMAC_RXFRAG_ERR_ADDR 0x930
+ #define XGMAC_RXJABBER_ERR_ADDR 0x934
+ #define XGMAC_RXUNDERSIZE_G_ADDR 0x938
+ #define XGMAC_RXOVERSIZE_G_ADDR 0x93C
+@@ -892,7 +914,7 @@
+ #define EDMA_REG_TX_MOD_TIMER(n) (0x99008 + (0x1000 * (n)))
+ #define EDMA_REG_TX_INT_CTRL(n) (0x9900c + (0x1000 * (n)))
+
+-/* EDMA_QID2RID_TABLE_MEM register field masks */
++/* EDMA_QID2RID_TABLE_MEM register (Rx queue to ring ID mapping) field masks */
+ #define EDMA_RX_RING_ID_QUEUE0_MASK GENMASK(7, 0)
+ #define EDMA_RX_RING_ID_QUEUE1_MASK GENMASK(15, 8)
+ #define EDMA_RX_RING_ID_QUEUE2_MASK GENMASK(23, 16)
+@@ -920,7 +942,7 @@
+ /* Rx Descriptor ring pre-header base address mask */
+ #define EDMA_RXDESC_PREHEADER_BA_MASK 0xffffffff
+
+-/* Tx descriptor prod ring index mask */
++/* Tx descriptor producer ring index mask */
+ #define EDMA_TXDESC_PROD_IDX_MASK 0xffff
+
+ /* Tx descriptor consumer ring index mask */
+@@ -935,7 +957,7 @@
+ #define EDMA_TXDESC_CTRL_TXEN_MASK BIT(0)
+ #define EDMA_TXDESC_CTRL_FC_GRP_ID_MASK GENMASK(3, 1)
+
+-/* Tx completion ring prod index mask */
++/* Tx completion ring producer index mask */
+ #define EDMA_TXCMPL_PROD_IDX_MASK 0xffff
+
+ /* Tx completion ring urgent threshold mask */
+@@ -946,7 +968,7 @@
+ #define EDMA_TX_MOD_TIMER_INIT_MASK 0xffff
+ #define EDMA_TX_MOD_TIMER_INIT_SHIFT 0
+
+-/* Rx fill ring prod index mask */
++/* Rx fill ring producer index mask */
+ #define EDMA_RXFILL_PROD_IDX_MASK 0xffff
+
+ /* Rx fill ring consumer index mask */
+@@ -964,10 +986,10 @@
+ /* Rx fill ring enable bit */
+ #define EDMA_RXFILL_RING_EN 0x1
+
+-/* Rx desc ring prod index mask */
++/* Rx desc ring producer index mask */
+ #define EDMA_RXDESC_PROD_IDX_MASK 0xffff
+
+-/* Rx descriptor ring cons index mask */
++/* Rx descriptor ring consumer index mask */
+ #define EDMA_RXDESC_CONS_IDX_MASK 0xffff
+
+ /* Rx descriptor ring size masks */
+@@ -1005,23 +1027,23 @@
+ /* EDMA Ring mask */
+ #define EDMA_RING_DMA_MASK 0xffffffff
+
+-/* RXDESC threshold interrupt. */
++/* Rx desc threshold interrupt. */
+ #define EDMA_RXDESC_UGT_INT_STAT 0x2
+
+-/* RXDESC timer interrupt */
++/* Rx desc timer interrupt */
+ #define EDMA_RXDESC_PKT_INT_STAT 0x1
+
+-/* RXDESC Interrupt status mask */
++/* Rx desc interrupt status mask */
+ #define EDMA_RXDESC_RING_INT_STATUS_MASK \
+ (EDMA_RXDESC_UGT_INT_STAT | EDMA_RXDESC_PKT_INT_STAT)
+
+-/* TXCMPL threshold interrupt. */
++/* Tx cmpl threshold interrupt. */
+ #define EDMA_TXCMPL_UGT_INT_STAT 0x2
+
+-/* TXCMPL timer interrupt */
++/* Tx cmpl timer interrupt */
+ #define EDMA_TXCMPL_PKT_INT_STAT 0x1
+
+-/* TXCMPL Interrupt status mask */
++/* Tx cmpl interrupt status mask */
+ #define EDMA_TXCMPL_RING_INT_STATUS_MASK \
+ (EDMA_TXCMPL_UGT_INT_STAT | EDMA_TXCMPL_PKT_INT_STAT)
+