Generate new patches for 6.18 from my ipq95xx development branch. Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com> Link: https://github.com/openwrt/openwrt/pull/21506 Signed-off-by: Robert Marko <robimarko@gmail.com>
3180 lines
104 KiB
Diff
3180 lines
104 KiB
Diff
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)
|
|
|