qualcommbe: remove upstreamed patches
Remove patches that are upstream in v6.18, but were not identified as upstreamed in the patch naming. 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>
This commit is contained in:
parent
0efbee297a
commit
b0534d0d41
@ -1,54 +0,0 @@
|
||||
From 52ebd52aa1906961142a2aba55d47a53b956847c Mon Sep 17 00:00:00 2001
|
||||
From: Devi Priya <quic_devipriy@quicinc.com>
|
||||
Date: Thu, 13 Mar 2025 16:33:58 +0530
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq9574: Add nsscc node
|
||||
|
||||
Add a node for the nss clock controller found on ipq9574 based devices.
|
||||
|
||||
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
|
||||
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
|
||||
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20250313110359.242491-6-quic_mmanikan@quicinc.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq9574.dtsi | 29 +++++++++++++++++++++++++++
|
||||
1 file changed, 29 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
|
||||
@@ -1195,6 +1195,35 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ nsscc: clock-controller@39b00000 {
|
||||
+ compatible = "qcom,ipq9574-nsscc";
|
||||
+ reg = <0x39b00000 0x80000>;
|
||||
+ clocks = <&xo_board_clk>,
|
||||
+ <&cmn_pll NSS_1200MHZ_CLK>,
|
||||
+ <&cmn_pll PPE_353MHZ_CLK>,
|
||||
+ <&gcc GPLL0_OUT_AUX>,
|
||||
+ <0>,
|
||||
+ <0>,
|
||||
+ <0>,
|
||||
+ <0>,
|
||||
+ <0>,
|
||||
+ <0>,
|
||||
+ <&gcc GCC_NSSCC_CLK>;
|
||||
+ clock-names = "xo",
|
||||
+ "nss_1200",
|
||||
+ "ppe_353",
|
||||
+ "gpll0_out",
|
||||
+ "uniphy0_rx",
|
||||
+ "uniphy0_tx",
|
||||
+ "uniphy1_rx",
|
||||
+ "uniphy1_tx",
|
||||
+ "uniphy2_rx",
|
||||
+ "uniphy2_tx",
|
||||
+ "bus";
|
||||
+ #clock-cells = <1>;
|
||||
+ #reset-cells = <1>;
|
||||
+ #interconnect-cells = <1>;
|
||||
+ };
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
@ -1,44 +0,0 @@
|
||||
From 2f2f5ae4d52ea882ba58f6b2fa6373a3d3db2bce Mon Sep 17 00:00:00 2001
|
||||
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
Date: Thu, 13 Mar 2025 12:44:22 +0530
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq9574: fix the msi interrupt numbers of
|
||||
pcie3
|
||||
|
||||
The MSI interrupt numbers of the PCIe3 controller are incorrect. Due
|
||||
to this, the functional bring up of the QDSP6 processor on the PCIe
|
||||
endpoint has failed. Correct the MSI interrupt numbers to properly
|
||||
bring up the QDSP6 processor on the PCIe endpoint.
|
||||
|
||||
Fixes: d80c7fbfa908 ("arm64: dts: qcom: ipq9574: Add PCIe PHYs and controller nodes")
|
||||
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20250313071422.510-1-quic_mmanikan@quicinc.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq9574.dtsi | 16 ++++++++--------
|
||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
|
||||
@@ -974,14 +974,14 @@
|
||||
ranges = <0x01000000 0x0 0x00000000 0x18200000 0x0 0x100000>,
|
||||
<0x02000000 0x0 0x18300000 0x18300000 0x0 0x7d00000>;
|
||||
|
||||
- interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
|
||||
- <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
|
||||
- <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
|
||||
- <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
|
||||
- <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
|
||||
- <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
|
||||
- <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
|
||||
- <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 415 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 494 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 495 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "msi0",
|
||||
"msi1",
|
||||
"msi2",
|
||||
@ -1,50 +0,0 @@
|
||||
From 583299efa34c4a484b211f84c63aee78b6c2b469 Mon Sep 17 00:00:00 2001
|
||||
From: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
Date: Thu, 6 Mar 2025 17:03:55 +0530
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq9574: Add SPI nand support
|
||||
|
||||
Add SPI NAND support for ipq9574 SoC.
|
||||
|
||||
Signed-off-by: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20250306113357.126602-2-quic_mdalam@quicinc.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq9574.dtsi | 27 +++++++++++++++++++++++++++
|
||||
1 file changed, 27 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
|
||||
@@ -675,6 +675,33 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ qpic_bam: dma-controller@7984000 {
|
||||
+ compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0";
|
||||
+ reg = <0x07984000 0x1c000>;
|
||||
+ interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clocks = <&gcc GCC_QPIC_AHB_CLK>;
|
||||
+ clock-names = "bam_clk";
|
||||
+ #dma-cells = <1>;
|
||||
+ qcom,ee = <0>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ qpic_nand: spi@79b0000 {
|
||||
+ compatible = "qcom,ipq9574-snand";
|
||||
+ reg = <0x079b0000 0x10000>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ clocks = <&gcc GCC_QPIC_CLK>,
|
||||
+ <&gcc GCC_QPIC_AHB_CLK>,
|
||||
+ <&gcc GCC_QPIC_IO_MACRO_CLK>;
|
||||
+ clock-names = "core", "aon", "iom";
|
||||
+ dmas = <&qpic_bam 0>,
|
||||
+ <&qpic_bam 1>,
|
||||
+ <&qpic_bam 2>;
|
||||
+ dma-names = "tx", "rx", "cmd";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
usb_0_qusbphy: phy@7b000 {
|
||||
compatible = "qcom,ipq9574-qusb2-phy";
|
||||
reg = <0x0007b000 0x180>;
|
||||
@ -1,68 +0,0 @@
|
||||
From a7c88bc81632974c0708308493aefb1f871b65fa Mon Sep 17 00:00:00 2001
|
||||
From: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
Date: Thu, 6 Mar 2025 17:03:56 +0530
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq9574: Enable SPI NAND for ipq9574
|
||||
|
||||
Enable SPI NAND support for ipq9574 SoC.
|
||||
|
||||
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
|
||||
Signed-off-by: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20250306113357.126602-3-quic_mdalam@quicinc.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
.../boot/dts/qcom/ipq9574-rdp-common.dtsi | 44 +++++++++++++++++++
|
||||
1 file changed, 44 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi
|
||||
@@ -146,6 +146,50 @@
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
+
|
||||
+ qpic_snand_default_state: qpic-snand-default-state {
|
||||
+ clock-pins {
|
||||
+ pins = "gpio5";
|
||||
+ function = "qspi_clk";
|
||||
+ drive-strength = <8>;
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+
|
||||
+ cs-pins {
|
||||
+ pins = "gpio4";
|
||||
+ function = "qspi_cs";
|
||||
+ drive-strength = <8>;
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+
|
||||
+ data-pins {
|
||||
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
|
||||
+ function = "qspi_data";
|
||||
+ drive-strength = <8>;
|
||||
+ bias-disable;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&qpic_bam {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&qpic_nand {
|
||||
+ pinctrl-0 = <&qpic_snand_default_state>;
|
||||
+ pinctrl-names = "default";
|
||||
+
|
||||
+ status = "okay";
|
||||
+
|
||||
+ flash@0 {
|
||||
+ compatible = "spi-nand";
|
||||
+ reg = <0>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+ nand-ecc-engine = <&qpic_nand>;
|
||||
+ nand-ecc-strength = <4>;
|
||||
+ nand-ecc-step-size = <512>;
|
||||
+ };
|
||||
};
|
||||
|
||||
&usb_0_dwc3 {
|
||||
@ -1,37 +0,0 @@
|
||||
From 0156e327aa854be5eb9cbec9d020be1026b5b446 Mon Sep 17 00:00:00 2001
|
||||
From: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
Date: Thu, 6 Mar 2025 17:03:57 +0530
|
||||
Subject: [PATCH] arm64: dts: qcom: ipq9574: Remove eMMC node
|
||||
|
||||
Remove eMMC node for rdp433, since rdp433
|
||||
default boot mode is norplusnand
|
||||
|
||||
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
|
||||
Signed-off-by: Md Sadre Alam <quic_mdalam@quicinc.com>
|
||||
Link: https://lore.kernel.org/r/20250306113357.126602-4-quic_mdalam@quicinc.com
|
||||
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
|
||||
---
|
||||
arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts | 12 ------------
|
||||
1 file changed, 12 deletions(-)
|
||||
|
||||
--- a/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts
|
||||
+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts
|
||||
@@ -55,18 +55,6 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
-&sdhc_1 {
|
||||
- pinctrl-0 = <&sdc_default_state>;
|
||||
- pinctrl-names = "default";
|
||||
- mmc-ddr-1_8v;
|
||||
- mmc-hs200-1_8v;
|
||||
- mmc-hs400-1_8v;
|
||||
- mmc-hs400-enhanced-strobe;
|
||||
- max-frequency = <384000000>;
|
||||
- bus-width = <8>;
|
||||
- status = "okay";
|
||||
-};
|
||||
-
|
||||
&tlmm {
|
||||
|
||||
pcie1_default: pcie1-default-state {
|
||||
@ -1,432 +0,0 @@
|
||||
From 48dc6d2fe28865a5c3d271aeb966b984a8085e7c Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:35 +0800
|
||||
Subject: [PATCH] dt-bindings: net: Add PPE for Qualcomm IPQ9574 SoC
|
||||
|
||||
The PPE (packet process engine) hardware block is available in Qualcomm
|
||||
IPQ chipsets that support PPE architecture, such as IPQ9574. The PPE in
|
||||
the IPQ9574 SoC includes six ethernet ports (6 GMAC and 6 XGMAC), which
|
||||
are used to connect with external PHY devices by PCS. It includes an L2
|
||||
switch function for bridging packets among the 6 ethernet ports and the
|
||||
CPU port. The CPU port enables packet transfer between the ethernet
|
||||
ports and the ARM cores in the SoC, using the ethernet DMA.
|
||||
|
||||
The PPE also includes packet processing offload capabilities for various
|
||||
networking functions such as route and bridge flows, VLANs, different
|
||||
tunnel protocols and VPN.
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
.../bindings/net/qcom,ipq9574-ppe.yaml | 406 ++++++++++++++++++
|
||||
1 file changed, 406 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml
|
||||
@@ -0,0 +1,406 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/net/qcom,ipq9574-ppe.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Qualcomm IPQ packet process engine (PPE)
|
||||
+
|
||||
+maintainers:
|
||||
+ - Luo Jie <quic_luoj@quicinc.com>
|
||||
+ - Lei Wei <quic_leiwei@quicinc.com>
|
||||
+ - Suruchi Agarwal <quic_suruchia@quicinc.com>
|
||||
+ - Pavithra R <quic_pavir@quicinc.com>>
|
||||
+
|
||||
+description:
|
||||
+ The Ethernet functionality in the PPE (Packet Process Engine) is comprised
|
||||
+ of three components, the switch core, port wrapper and Ethernet DMA.
|
||||
+
|
||||
+ The Switch core in the IPQ9574 PPE has maximum of 6 front panel ports and
|
||||
+ two FIFO interfaces. One of the two FIFO interfaces is used for Ethernet
|
||||
+ port to host CPU communication using Ethernet DMA. The other is used
|
||||
+ communicating to the EIP engine which is used for IPsec offload. On the
|
||||
+ IPQ9574, the PPE includes 6 GMAC/XGMACs that can be connected with external
|
||||
+ Ethernet PHY. Switch core also includes BM (Buffer Management), QM (Queue
|
||||
+ Management) and SCH (Scheduler) modules for supporting the packet processing.
|
||||
+
|
||||
+ The port wrapper provides connections from the 6 GMAC/XGMACS to UNIPHY (PCS)
|
||||
+ supporting various modes such as SGMII/QSGMII/PSGMII/USXGMII/10G-BASER. There
|
||||
+ are 3 UNIPHY (PCS) instances supported on the IPQ9574.
|
||||
+
|
||||
+ Ethernet DMA is used to transmit and receive packets between the six Ethernet
|
||||
+ ports and ARM host CPU.
|
||||
+
|
||||
+ The follow diagram shows the PPE hardware block along with its connectivity
|
||||
+ to the external hardware blocks such clock hardware blocks (CMNPLL, GCC,
|
||||
+ NSS clock controller) and ethernet PCS/PHY blocks. For depicting the PHY
|
||||
+ connectivity, one 4x1 Gbps PHY (QCA8075) and two 10 GBps PHYs are used as an
|
||||
+ example.
|
||||
+ - |
|
||||
+ +---------+
|
||||
+ | 48 MHZ |
|
||||
+ +----+----+
|
||||
+ |(clock)
|
||||
+ v
|
||||
+ +----+----+
|
||||
+ +------| CMN PLL |
|
||||
+ | +----+----+
|
||||
+ | |(clock)
|
||||
+ | v
|
||||
+ | +----+----+ +----+----+ (clock) +----+----+
|
||||
+ | +---| NSSCC | | GCC |--------->| MDIO |
|
||||
+ | | +----+----+ +----+----+ +----+----+
|
||||
+ | | |(clock & reset) |(clock)
|
||||
+ | | v v
|
||||
+ | | +-----------------------------+----------+----------+---------+
|
||||
+ | | | +-----+ |EDMA FIFO | | EIP FIFO|
|
||||
+ | | | | SCH | +----------+ +---------+
|
||||
+ | | | +-----+ | | |
|
||||
+ | | | +------+ +------+ +-------------------+ |
|
||||
+ | | | | BM | | QM | IPQ9574-PPE | L2/L3 Process | |
|
||||
+ | | | +------+ +------+ +-------------------+ |
|
||||
+ | | | | |
|
||||
+ | | | +-------+ +-------+ +-------+ +-------+ +-------+ +-------+ |
|
||||
+ | | | | MAC0 | | MAC1 | | MAC2 | | MAC3 | | XGMAC4| |XGMAC5 | |
|
||||
+ | | | +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ |
|
||||
+ | | | | | | | | | |
|
||||
+ | | +-----+---------+---------+---------+---------+---------+-----+
|
||||
+ | | | | | | | |
|
||||
+ | | +---+---------+---------+---------+---+ +---+---+ +---+---+
|
||||
+ +--+---->| PCS0 | | PCS1 | | PCS2 |
|
||||
+ |(clock) +---+---------+---------+---------+---+ +---+---+ +---+---+
|
||||
+ | | | | | | |
|
||||
+ | +---+---------+---------+---------+---+ +---+---+ +---+---+
|
||||
+ +------->| QCA8075 PHY | | PHY4 | | PHY5 |
|
||||
+ (clock) +-------------------------------------+ +-------+ +-------+
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ enum:
|
||||
+ - qcom,ipq9574-ppe
|
||||
+
|
||||
+ reg:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ clocks:
|
||||
+ items:
|
||||
+ - description: PPE core clock from NSS clock controller
|
||||
+ - description: PPE APB (Advanced Peripheral Bus) clock from NSS clock controller
|
||||
+ - description: PPE ingress process engine clock from NSS clock controller
|
||||
+ - description: PPE BM, QM and scheduler clock from NSS clock controller
|
||||
+
|
||||
+ clock-names:
|
||||
+ items:
|
||||
+ - const: ppe
|
||||
+ - const: apb
|
||||
+ - const: ipe
|
||||
+ - const: btq
|
||||
+
|
||||
+ resets:
|
||||
+ maxItems: 1
|
||||
+ description: PPE reset, which is necessary before configuring PPE hardware
|
||||
+
|
||||
+ interconnects:
|
||||
+ items:
|
||||
+ - description: Clock path leading to PPE switch core function
|
||||
+ - description: Clock path leading to PPE register access
|
||||
+ - description: Clock path leading to QoS generation
|
||||
+ - description: Clock path leading to timeout reference
|
||||
+ - description: Clock path leading to NSS NOC from memory NOC
|
||||
+ - description: Clock path leading to memory NOC from NSS NOC
|
||||
+ - description: Clock path leading to enhanced memory NOC from NSS NOC
|
||||
+
|
||||
+ interconnect-names:
|
||||
+ items:
|
||||
+ - const: ppe
|
||||
+ - const: ppe_cfg
|
||||
+ - const: qos_gen
|
||||
+ - const: timeout_ref
|
||||
+ - const: nssnoc_memnoc
|
||||
+ - const: memnoc_nssnoc
|
||||
+ - const: memnoc_nssnoc_1
|
||||
+
|
||||
+ ethernet-dma:
|
||||
+ type: object
|
||||
+ additionalProperties: false
|
||||
+ description:
|
||||
+ EDMA (Ethernet DMA) is used to transmit packets between PPE and ARM
|
||||
+ host CPU. There are 32 TX descriptor rings, 32 TX completion rings,
|
||||
+ 24 RX descriptor rings and 8 RX fill rings supported.
|
||||
+
|
||||
+ properties:
|
||||
+ clocks:
|
||||
+ items:
|
||||
+ - description: EDMA system clock from NSS Clock Controller
|
||||
+ - description: EDMA APB (Advanced Peripheral Bus) clock from
|
||||
+ NSS Clock Controller
|
||||
+
|
||||
+ clock-names:
|
||||
+ items:
|
||||
+ - const: sys
|
||||
+ - const: apb
|
||||
+
|
||||
+ resets:
|
||||
+ maxItems: 1
|
||||
+ description: EDMA reset from NSS clock controller
|
||||
+
|
||||
+ interrupts:
|
||||
+ minItems: 29
|
||||
+ maxItems: 57
|
||||
+
|
||||
+ interrupt-names:
|
||||
+ minItems: 29
|
||||
+ maxItems: 57
|
||||
+ items:
|
||||
+ pattern: '^(txcmpl_([0-9]|[1-2][0-9]|3[0-1])|rxdesc_([0-9]|1[0-9]|2[0-3])|misc)$'
|
||||
+ description:
|
||||
+ Interrupts "txcmpl_[0-31]" are the Ethernet DMA Tx completion ring interrupts.
|
||||
+ Interrupts "rxdesc_[0-23]" are the Ethernet DMA Rx Descriptor ring interrupts.
|
||||
+ Interrupt "misc" is the Ethernet DMA miscellaneous error interrupt.
|
||||
+
|
||||
+ required:
|
||||
+ - clocks
|
||||
+ - clock-names
|
||||
+ - resets
|
||||
+ - interrupts
|
||||
+ - interrupt-names
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - reg
|
||||
+ - clocks
|
||||
+ - clock-names
|
||||
+ - resets
|
||||
+ - interconnects
|
||||
+ - interconnect-names
|
||||
+ - ethernet-dma
|
||||
+
|
||||
+allOf:
|
||||
+ - $ref: ethernet-switch.yaml
|
||||
+
|
||||
+unevaluatedProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ #include <dt-bindings/clock/qcom,ipq9574-gcc.h>
|
||||
+ #include <dt-bindings/interconnect/qcom,ipq9574.h>
|
||||
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
+
|
||||
+ ethernet-switch@3a000000 {
|
||||
+ compatible = "qcom,ipq9574-ppe";
|
||||
+ reg = <0x3a000000 0xbef800>;
|
||||
+ clocks = <&nsscc 80>,
|
||||
+ <&nsscc 79>,
|
||||
+ <&nsscc 81>,
|
||||
+ <&nsscc 78>;
|
||||
+ clock-names = "ppe",
|
||||
+ "apb",
|
||||
+ "ipe",
|
||||
+ "btq";
|
||||
+ resets = <&nsscc 108>;
|
||||
+ interconnects = <&nsscc MASTER_NSSNOC_PPE &nsscc SLAVE_NSSNOC_PPE>,
|
||||
+ <&nsscc MASTER_NSSNOC_PPE_CFG &nsscc SLAVE_NSSNOC_PPE_CFG>,
|
||||
+ <&gcc MASTER_NSSNOC_QOSGEN_REF &gcc SLAVE_NSSNOC_QOSGEN_REF>,
|
||||
+ <&gcc MASTER_NSSNOC_TIMEOUT_REF &gcc SLAVE_NSSNOC_TIMEOUT_REF>,
|
||||
+ <&gcc MASTER_MEM_NOC_NSSNOC &gcc SLAVE_MEM_NOC_NSSNOC>,
|
||||
+ <&gcc MASTER_NSSNOC_MEMNOC &gcc SLAVE_NSSNOC_MEMNOC>,
|
||||
+ <&gcc MASTER_NSSNOC_MEM_NOC_1 &gcc SLAVE_NSSNOC_MEM_NOC_1>;
|
||||
+ interconnect-names = "ppe",
|
||||
+ "ppe_cfg",
|
||||
+ "qos_gen",
|
||||
+ "timeout_ref",
|
||||
+ "nssnoc_memnoc",
|
||||
+ "memnoc_nssnoc",
|
||||
+ "memnoc_nssnoc_1";
|
||||
+
|
||||
+ ethernet-dma {
|
||||
+ clocks = <&nsscc 77>,
|
||||
+ <&nsscc 76>;
|
||||
+ clock-names = "sys",
|
||||
+ "apb";
|
||||
+ resets = <&nsscc 0>;
|
||||
+ interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 380 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 509 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 508 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 507 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 506 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 505 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 504 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 503 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 502 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 501 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 500 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 499 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ interrupt-names = "txcmpl_8",
|
||||
+ "txcmpl_9",
|
||||
+ "txcmpl_10",
|
||||
+ "txcmpl_11",
|
||||
+ "txcmpl_12",
|
||||
+ "txcmpl_13",
|
||||
+ "txcmpl_14",
|
||||
+ "txcmpl_15",
|
||||
+ "txcmpl_16",
|
||||
+ "txcmpl_17",
|
||||
+ "txcmpl_18",
|
||||
+ "txcmpl_19",
|
||||
+ "txcmpl_20",
|
||||
+ "txcmpl_21",
|
||||
+ "txcmpl_22",
|
||||
+ "txcmpl_23",
|
||||
+ "txcmpl_24",
|
||||
+ "txcmpl_25",
|
||||
+ "txcmpl_26",
|
||||
+ "txcmpl_27",
|
||||
+ "txcmpl_28",
|
||||
+ "txcmpl_29",
|
||||
+ "txcmpl_30",
|
||||
+ "txcmpl_31",
|
||||
+ "rxdesc_20",
|
||||
+ "rxdesc_21",
|
||||
+ "rxdesc_22",
|
||||
+ "rxdesc_23",
|
||||
+ "misc";
|
||||
+ };
|
||||
+
|
||||
+ ethernet-ports {
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+
|
||||
+ port@1 {
|
||||
+ reg = <1>;
|
||||
+ phy-mode = "qsgmii";
|
||||
+ managed = "in-band-status";
|
||||
+ phy-handle = <&phy0>;
|
||||
+ pcs-handle = <&pcs0_mii0>;
|
||||
+ clocks = <&nsscc 33>,
|
||||
+ <&nsscc 34>,
|
||||
+ <&nsscc 37>;
|
||||
+ clock-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ resets = <&nsscc 29>,
|
||||
+ <&nsscc 96>,
|
||||
+ <&nsscc 97>;
|
||||
+ reset-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ };
|
||||
+
|
||||
+ port@2 {
|
||||
+ reg = <2>;
|
||||
+ phy-mode = "qsgmii";
|
||||
+ managed = "in-band-status";
|
||||
+ phy-handle = <&phy1>;
|
||||
+ pcs-handle = <&pcs0_mii1>;
|
||||
+ clocks = <&nsscc 40>,
|
||||
+ <&nsscc 41>,
|
||||
+ <&nsscc 44>;
|
||||
+ clock-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ resets = <&nsscc 30>,
|
||||
+ <&nsscc 98>,
|
||||
+ <&nsscc 99>;
|
||||
+ reset-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ };
|
||||
+
|
||||
+ port@3 {
|
||||
+ reg = <3>;
|
||||
+ phy-mode = "qsgmii";
|
||||
+ managed = "in-band-status";
|
||||
+ phy-handle = <&phy2>;
|
||||
+ pcs-handle = <&pcs0_mii2>;
|
||||
+ clocks = <&nsscc 47>,
|
||||
+ <&nsscc 48>,
|
||||
+ <&nsscc 51>;
|
||||
+ clock-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ resets = <&nsscc 31>,
|
||||
+ <&nsscc 100>,
|
||||
+ <&nsscc 101>;
|
||||
+ reset-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ };
|
||||
+
|
||||
+ port@4 {
|
||||
+ reg = <4>;
|
||||
+ phy-mode = "qsgmii";
|
||||
+ managed = "in-band-status";
|
||||
+ phy-handle = <&phy3>;
|
||||
+ pcs-handle = <&pcs0_mii3>;
|
||||
+ clocks = <&nsscc 54>,
|
||||
+ <&nsscc 55>,
|
||||
+ <&nsscc 58>;
|
||||
+ clock-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ resets = <&nsscc 32>,
|
||||
+ <&nsscc 102>,
|
||||
+ <&nsscc 103>;
|
||||
+ reset-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ };
|
||||
+
|
||||
+ port@5 {
|
||||
+ reg = <5>;
|
||||
+ phy-mode = "usxgmii";
|
||||
+ managed = "in-band-status";
|
||||
+ phy-handle = <&phy4>;
|
||||
+ pcs-handle = <&pcs1_mii0>;
|
||||
+ clocks = <&nsscc 61>,
|
||||
+ <&nsscc 62>,
|
||||
+ <&nsscc 65>;
|
||||
+ clock-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ resets = <&nsscc 33>,
|
||||
+ <&nsscc 104>,
|
||||
+ <&nsscc 105>;
|
||||
+ reset-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ };
|
||||
+
|
||||
+ port@6 {
|
||||
+ reg = <6>;
|
||||
+ phy-mode = "usxgmii";
|
||||
+ managed = "in-band-status";
|
||||
+ phy-handle = <&phy5>;
|
||||
+ pcs-handle = <&pcs2_mii0>;
|
||||
+ clocks = <&nsscc 68>,
|
||||
+ <&nsscc 69>,
|
||||
+ <&nsscc 72>;
|
||||
+ clock-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ resets = <&nsscc 34>,
|
||||
+ <&nsscc 106>,
|
||||
+ <&nsscc 107>;
|
||||
+ reset-names = "mac",
|
||||
+ "rx",
|
||||
+ "tx";
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
@ -1,227 +0,0 @@
|
||||
From 9973b6610830146af1a12fe02d2d6440eb80b0f9 Mon Sep 17 00:00:00 2001
|
||||
From: Lei Wei <quic_leiwei@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:36 +0800
|
||||
Subject: [PATCH] docs: networking: Add PPE driver documentation for Qualcomm
|
||||
IPQ9574 SoC
|
||||
|
||||
Add description and high-level diagram for PPE, driver overview and
|
||||
module enable/debug information.
|
||||
|
||||
Signed-off-by: Lei Wei <quic_leiwei@quicinc.com>
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
.../device_drivers/ethernet/index.rst | 1 +
|
||||
.../ethernet/qualcomm/ppe/ppe.rst | 197 ++++++++++++++++++
|
||||
2 files changed, 198 insertions(+)
|
||||
create mode 100644 Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst
|
||||
|
||||
--- a/Documentation/networking/device_drivers/ethernet/index.rst
|
||||
+++ b/Documentation/networking/device_drivers/ethernet/index.rst
|
||||
@@ -49,6 +49,7 @@ Contents:
|
||||
neterion/s2io
|
||||
netronome/nfp
|
||||
pensando/ionic
|
||||
+ qualcomm/ppe/ppe
|
||||
smsc/smc9
|
||||
stmicro/stmmac
|
||||
ti/cpsw
|
||||
--- /dev/null
|
||||
+++ b/Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst
|
||||
@@ -0,0 +1,197 @@
|
||||
+.. SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+===============================================
|
||||
+PPE Ethernet Driver for Qualcomm IPQ SoC Family
|
||||
+===============================================
|
||||
+
|
||||
+Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
+
|
||||
+Author: Lei Wei <quic_leiwei@quicinc.com>
|
||||
+
|
||||
+
|
||||
+Contents
|
||||
+========
|
||||
+
|
||||
+- `PPE Overview`_
|
||||
+- `PPE Driver Overview`_
|
||||
+- `PPE Driver Supported SoCs`_
|
||||
+- `Enabling the Driver`_
|
||||
+- `Debugging`_
|
||||
+
|
||||
+
|
||||
+PPE Overview
|
||||
+============
|
||||
+
|
||||
+IPQ (Qualcomm Internet Processor) SoC (System-on-Chip) series is Qualcomm's series of
|
||||
+networking SoC for Wi-Fi access points. The PPE (Packet Process Engine) is the Ethernet
|
||||
+packet process engine in the IPQ SoC.
|
||||
+
|
||||
+Below is a simplified hardware diagram of IPQ9574 SoC which includes the PPE engine and
|
||||
+other blocks which are in the SoC but outside the PPE engine. These blocks work together
|
||||
+to enable the Ethernet for the IPQ SoC::
|
||||
+
|
||||
+ +------+ +------+ +------+ +------+ +------+ +------+ start +-------+
|
||||
+ |netdev| |netdev| |netdev| |netdev| |netdev| |netdev|<------|PHYLINK|
|
||||
+ +------+ +------+ +------+ +------+ +------+ +------+ stop +-+-+-+-+
|
||||
+ | | | ^
|
||||
+ +-------+ +-------------------------+--------+----------------------+ | | |
|
||||
+ | GCC | | | EDMA | | | | |
|
||||
+ +---+---+ | PPE +---+----+ | | | |
|
||||
+ | clk | | | | | |
|
||||
+ +------>| +-----------------------+------+-----+---------------+ | | | |
|
||||
+ | | Switch Core |Port0 | |Port7(EIP FIFO)| | | | |
|
||||
+ | | +---+--+ +------+--------+ | | | |
|
||||
+ | | | | | | | | |
|
||||
+ +-------+ | | +------+---------------+----+ | | | | |
|
||||
+ |CMN PLL| | | +---+ +---+ +----+ | +--------+ | | | | | |
|
||||
+ +---+---+ | | |BM | |QM | |SCH | | | L2/L3 | ....... | | | | | |
|
||||
+ | | | | +---+ +---+ +----+ | +--------+ | | | | | |
|
||||
+ | | | | +------+--------------------+ | | | | |
|
||||
+ | | | | | | | | | |
|
||||
+ | v | | +-----+-+-----+-+-----+-+-+---+--+-----+-+-----+ | | | | |
|
||||
+ | +------+ | | |Port1| |Port2| |Port3| |Port4| |Port5| |Port6| | | | | |
|
||||
+ | |NSSCC | | | +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ | | mac| | |
|
||||
+ | +-+-+--+ | | |MAC0 | |MAC1 | |MAC2 | |MAC3 | |MAC4 | |MAC5 | | |<---+ | |
|
||||
+ | ^ | |clk | | +-----+-+-----+-+-----+-+-----+--+-----+-+-----+ | | ops | |
|
||||
+ | | | +---->| +----|------|-------|-------|---------|--------|-----+ | | |
|
||||
+ | | | +---------------------------------------------------------+ | |
|
||||
+ | | | | | | | | | | |
|
||||
+ | | | MII clk | QSGMII USXGMII USXGMII | |
|
||||
+ | | +------------->| | | | | | | |
|
||||
+ | | +-------------------------+ +---------+ +---------+ | |
|
||||
+ | |125/312.5M clk| (PCS0) | | (PCS1) | | (PCS2) | pcs ops | |
|
||||
+ | +--------------+ UNIPHY0 | | UNIPHY1 | | UNIPHY2 |<--------+ |
|
||||
+ +--------------->| | | | | | |
|
||||
+ | 31.25M ref clk +-------------------------+ +---------+ +---------+ |
|
||||
+ | | | | | | | |
|
||||
+ | +-----------------------------------------------------+ |
|
||||
+ |25/50M ref clk| +-------------------------+ +------+ +------+ | link |
|
||||
+ +------------->| | QUAD PHY | | PHY4 | | PHY5 | |---------+
|
||||
+ | +-------------------------+ +------+ +------+ | change
|
||||
+ | |
|
||||
+ | MDIO bus |
|
||||
+ +-----------------------------------------------------+
|
||||
+
|
||||
+The CMN (Common) PLL, NSSCC (Networking Sub System Clock Controller) and GCC (Global
|
||||
+Clock Controller) blocks are in the SoC and act as clock providers.
|
||||
+
|
||||
+The UNIPHY block is in the SoC and provides the PCS (Physical Coding Sublayer) and
|
||||
+XPCS (10-Gigabit Physical Coding Sublayer) functions to support different interface
|
||||
+modes between the PPE MAC and the external PHY.
|
||||
+
|
||||
+This documentation focuses on the descriptions of PPE engine and the PPE driver.
|
||||
+
|
||||
+The Ethernet functionality in the PPE (Packet Process Engine) is comprised of three
|
||||
+components: the switch core, port wrapper and Ethernet DMA.
|
||||
+
|
||||
+The Switch core in the IPQ9574 PPE has maximum of 6 front panel ports and two FIFO
|
||||
+interfaces. One of the two FIFO interfaces is used for Ethernet port to host CPU
|
||||
+communication using Ethernet DMA. The other is used communicating to the EIP engine
|
||||
+which is used for IPsec offload. On the IPQ9574, the PPE includes 6 GMAC/XGMACs that
|
||||
+can be connected with external Ethernet PHY. Switch core also includes BM (Buffer
|
||||
+Management), QM (Queue Management) and SCH (Scheduler) modules for supporting the
|
||||
+packet processing.
|
||||
+
|
||||
+The port wrapper provides connections from the 6 GMAC/XGMACS to UNIPHY (PCS) supporting
|
||||
+various modes such as SGMII/QSGMII/PSGMII/USXGMII/10G-BASER. There are 3 UNIPHY (PCS)
|
||||
+instances supported on the IPQ9574.
|
||||
+
|
||||
+Ethernet DMA is used to transmit and receive packets between the Ethernet subsystem
|
||||
+and ARM host CPU.
|
||||
+
|
||||
+The following lists the main blocks in the PPE engine which will be driven by this
|
||||
+PPE driver:
|
||||
+
|
||||
+- BM
|
||||
+ BM is the hardware buffer manager for the PPE switch ports.
|
||||
+- QM
|
||||
+ Queue Manager for managing the egress hardware queues of the PPE switch ports.
|
||||
+- SCH
|
||||
+ The scheduler which manages the hardware traffic scheduling for the PPE switch ports.
|
||||
+- L2
|
||||
+ The L2 block performs the packet bridging in the switch core. The bridge domain is
|
||||
+ represented by the VSI (Virtual Switch Instance) domain in PPE. FDB learning can be
|
||||
+ enabled based on the VSI domain and bridge forwarding occurs within the VSI domain.
|
||||
+- MAC
|
||||
+ The PPE in the IPQ9574 supports up to six MACs (MAC0 to MAC5) which are corresponding
|
||||
+ to six switch ports (port1 to port6). The MAC block is connected with external PHY
|
||||
+ through the UNIPHY PCS block. Each MAC block includes the GMAC and XGMAC blocks and
|
||||
+ the switch port can select to use GMAC or XMAC through a MUX selection according to
|
||||
+ the external PHY's capability.
|
||||
+- EDMA (Ethernet DMA)
|
||||
+ The Ethernet DMA is used to transmit and receive Ethernet packets between the PPE
|
||||
+ ports and the ARM cores.
|
||||
+
|
||||
+The received packet on a PPE MAC port can be forwarded to another PPE MAC port. It can
|
||||
+be also forwarded to internal switch port0 so that the packet can be delivered to the
|
||||
+ARM cores using the Ethernet DMA (EDMA) engine. The Ethernet DMA driver will deliver the
|
||||
+packet to the corresponding 'netdevice' interface.
|
||||
+
|
||||
+The software instantiations of the PPE MAC (netdevice), PCS and external PHYs interact
|
||||
+with the Linux PHYLINK framework to manage the connectivity between the PPE ports and
|
||||
+the connected PHYs, and the port link states. This is also illustrated in above diagram.
|
||||
+
|
||||
+
|
||||
+PPE Driver Overview
|
||||
+===================
|
||||
+PPE driver is Ethernet driver for the Qualcomm IPQ SoC. It is a single platform driver
|
||||
+which includes the PPE part and Ethernet DMA part. The PPE part initializes and drives the
|
||||
+various blocks in PPE switch core such as BM/QM/L2 blocks and the PPE MACs. The EDMA part
|
||||
+drives the Ethernet DMA for packet transfer between PPE ports and ARM cores, and enables
|
||||
+the netdevice driver for the PPE ports.
|
||||
+
|
||||
+The PPE driver files in drivers/net/ethernet/qualcomm/ppe/ are listed as below:
|
||||
+
|
||||
+- Makefile
|
||||
+- ppe.c
|
||||
+- ppe.h
|
||||
+- ppe_config.c
|
||||
+- ppe_config.h
|
||||
+- ppe_debugfs.c
|
||||
+- ppe_debugfs.h
|
||||
+- ppe_regs.h
|
||||
+
|
||||
+The ppe.c file contains the main PPE platform driver and undertakes the initialization of
|
||||
+PPE switch core blocks such as QM, BM and L2. The configuration APIs for these hardware
|
||||
+blocks are provided in the ppe_config.c file.
|
||||
+
|
||||
+The ppe.h defines the PPE device data structure which will be used by PPE driver functions.
|
||||
+
|
||||
+The ppe_debugfs.c enables the PPE statistics counters such as PPE port Rx and Tx counters,
|
||||
+CPU code counters and queue counters.
|
||||
+
|
||||
+
|
||||
+PPE Driver Supported SoCs
|
||||
+=========================
|
||||
+
|
||||
+The PPE driver supports the following IPQ SoC:
|
||||
+
|
||||
+- IPQ9574
|
||||
+
|
||||
+
|
||||
+Enabling the Driver
|
||||
+===================
|
||||
+
|
||||
+The driver is located in the menu structure at:
|
||||
+
|
||||
+ -> Device Drivers
|
||||
+ -> Network device support (NETDEVICES [=y])
|
||||
+ -> Ethernet driver support
|
||||
+ -> Qualcomm devices
|
||||
+ -> Qualcomm Technologies, Inc. PPE Ethernet support
|
||||
+
|
||||
+If this driver is built as a module, we can use below commands to install and remove it:
|
||||
+
|
||||
+- insmod qcom-ppe.ko
|
||||
+- rmmod qcom-ppe.ko
|
||||
+
|
||||
+The PPE driver functionally depends on the CMN PLL and NSSCC clock controller drivers.
|
||||
+Please make sure the dependent modules are installed before installing the PPE driver
|
||||
+module.
|
||||
+
|
||||
+
|
||||
+Debugging
|
||||
+=========
|
||||
+
|
||||
+The PPE hardware counters are available in the debugfs and can be checked by the command
|
||||
+``cat /sys/kernel/debug/ppe/packet_counters``.
|
||||
@ -1,339 +0,0 @@
|
||||
From d1158f0282304c89217894aa346fc45364b95542 Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:37 +0800
|
||||
Subject: [PATCH] net: ethernet: qualcomm: Add PPE driver for IPQ9574 SoC
|
||||
|
||||
The PPE (Packet Process Engine) hardware block is available
|
||||
on Qualcomm IPQ SoC that support PPE architecture, such as
|
||||
IPQ9574.
|
||||
|
||||
The PPE in IPQ9574 includes six integrated ethernet MAC
|
||||
(for 6 PPE ports), buffer management, queue management and
|
||||
scheduler functions. The MACs can connect with the external
|
||||
PHY or switch devices using the UNIPHY PCS block available
|
||||
in the SoC.
|
||||
|
||||
The PPE also includes various packet processing offload
|
||||
capabilities such as L3 routing and L2 bridging, VLAN and
|
||||
tunnel processing offload. It also includes Ethernet DMA
|
||||
function for transferring packets between ARM cores and
|
||||
PPE ethernet ports.
|
||||
|
||||
This patch adds the base source files and Makefiles for
|
||||
the PPE driver such as platform driver registration,
|
||||
clock initialization, and PPE reset routines.
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
drivers/net/ethernet/qualcomm/Kconfig | 15 ++
|
||||
drivers/net/ethernet/qualcomm/Makefile | 1 +
|
||||
drivers/net/ethernet/qualcomm/ppe/Makefile | 7 +
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe.c | 218 +++++++++++++++++++++
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe.h | 36 ++++
|
||||
5 files changed, 277 insertions(+)
|
||||
create mode 100644 drivers/net/ethernet/qualcomm/ppe/Makefile
|
||||
create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe.c
|
||||
create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe.h
|
||||
|
||||
--- a/drivers/net/ethernet/qualcomm/Kconfig
|
||||
+++ b/drivers/net/ethernet/qualcomm/Kconfig
|
||||
@@ -61,6 +61,21 @@ config QCOM_EMAC
|
||||
low power, Receive-Side Scaling (RSS), and IEEE 1588-2008
|
||||
Precision Clock Synchronization Protocol.
|
||||
|
||||
+config QCOM_PPE
|
||||
+ tristate "Qualcomm Technologies, Inc. PPE Ethernet support"
|
||||
+ depends on HAS_IOMEM && OF
|
||||
+ depends on COMMON_CLK
|
||||
+ select REGMAP_MMIO
|
||||
+ help
|
||||
+ This driver supports the Qualcomm Technologies, Inc. packet
|
||||
+ process engine (PPE) available with IPQ SoC. The PPE includes
|
||||
+ the ethernet MACs, Ethernet DMA (EDMA) and switch core that
|
||||
+ supports L3 flow offload, L2 switch function, RSS and tunnel
|
||||
+ offload.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here. The module
|
||||
+ will be called qcom-ppe.
|
||||
+
|
||||
source "drivers/net/ethernet/qualcomm/rmnet/Kconfig"
|
||||
|
||||
endif # NET_VENDOR_QUALCOMM
|
||||
--- a/drivers/net/ethernet/qualcomm/Makefile
|
||||
+++ b/drivers/net/ethernet/qualcomm/Makefile
|
||||
@@ -11,4 +11,5 @@ qcauart-objs := qca_uart.o
|
||||
|
||||
obj-y += emac/
|
||||
|
||||
+obj-$(CONFIG_QCOM_PPE) += ppe/
|
||||
obj-$(CONFIG_RMNET) += rmnet/
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile
|
||||
@@ -0,0 +1,7 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0-only
|
||||
+#
|
||||
+# Makefile for the device driver of PPE (Packet Process Engine) in IPQ SoC
|
||||
+#
|
||||
+
|
||||
+obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o
|
||||
+qcom-ppe-objs := ppe.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
|
||||
@@ -0,0 +1,218 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+/* PPE platform device probe, DTSI parser and PPE clock initializations. */
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/interconnect.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/reset.h>
|
||||
+
|
||||
+#include "ppe.h"
|
||||
+
|
||||
+#define PPE_PORT_MAX 8
|
||||
+#define PPE_CLK_RATE 353000000
|
||||
+
|
||||
+/* ICC clocks for enabling PPE device. The avg_bw and peak_bw with value 0
|
||||
+ * will be updated by the clock rate of PPE.
|
||||
+ */
|
||||
+static const struct icc_bulk_data ppe_icc_data[] = {
|
||||
+ {
|
||||
+ .name = "ppe",
|
||||
+ .avg_bw = 0,
|
||||
+ .peak_bw = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "ppe_cfg",
|
||||
+ .avg_bw = 0,
|
||||
+ .peak_bw = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "qos_gen",
|
||||
+ .avg_bw = 6000,
|
||||
+ .peak_bw = 6000,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "timeout_ref",
|
||||
+ .avg_bw = 6000,
|
||||
+ .peak_bw = 6000,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "nssnoc_memnoc",
|
||||
+ .avg_bw = 533333,
|
||||
+ .peak_bw = 533333,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "memnoc_nssnoc",
|
||||
+ .avg_bw = 533333,
|
||||
+ .peak_bw = 533333,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "memnoc_nssnoc_1",
|
||||
+ .avg_bw = 533333,
|
||||
+ .peak_bw = 533333,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_range ppe_readable_ranges[] = {
|
||||
+ regmap_reg_range(0x0, 0x1ff), /* Global */
|
||||
+ regmap_reg_range(0x400, 0x5ff), /* LPI CSR */
|
||||
+ regmap_reg_range(0x1000, 0x11ff), /* GMAC0 */
|
||||
+ regmap_reg_range(0x1200, 0x13ff), /* GMAC1 */
|
||||
+ regmap_reg_range(0x1400, 0x15ff), /* GMAC2 */
|
||||
+ regmap_reg_range(0x1600, 0x17ff), /* GMAC3 */
|
||||
+ regmap_reg_range(0x1800, 0x19ff), /* GMAC4 */
|
||||
+ regmap_reg_range(0x1a00, 0x1bff), /* GMAC5 */
|
||||
+ regmap_reg_range(0xb000, 0xefff), /* PRX CSR */
|
||||
+ regmap_reg_range(0xf000, 0x1efff), /* IPE */
|
||||
+ regmap_reg_range(0x20000, 0x5ffff), /* PTX CSR */
|
||||
+ regmap_reg_range(0x60000, 0x9ffff), /* IPE L2 CSR */
|
||||
+ regmap_reg_range(0xb0000, 0xeffff), /* IPO CSR */
|
||||
+ regmap_reg_range(0x100000, 0x17ffff), /* IPE PC */
|
||||
+ regmap_reg_range(0x180000, 0x1bffff), /* PRE IPO CSR */
|
||||
+ regmap_reg_range(0x1d0000, 0x1dffff), /* Tunnel parser */
|
||||
+ regmap_reg_range(0x1e0000, 0x1effff), /* Ingress parse */
|
||||
+ regmap_reg_range(0x200000, 0x2fffff), /* IPE L3 */
|
||||
+ regmap_reg_range(0x300000, 0x3fffff), /* IPE tunnel */
|
||||
+ regmap_reg_range(0x400000, 0x4fffff), /* Scheduler */
|
||||
+ regmap_reg_range(0x500000, 0x503fff), /* XGMAC0 */
|
||||
+ regmap_reg_range(0x504000, 0x507fff), /* XGMAC1 */
|
||||
+ regmap_reg_range(0x508000, 0x50bfff), /* XGMAC2 */
|
||||
+ regmap_reg_range(0x50c000, 0x50ffff), /* XGMAC3 */
|
||||
+ regmap_reg_range(0x510000, 0x513fff), /* XGMAC4 */
|
||||
+ regmap_reg_range(0x514000, 0x517fff), /* XGMAC5 */
|
||||
+ regmap_reg_range(0x600000, 0x6fffff), /* BM */
|
||||
+ regmap_reg_range(0x800000, 0x9fffff), /* QM */
|
||||
+ regmap_reg_range(0xb00000, 0xbef800), /* EDMA */
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_access_table ppe_reg_table = {
|
||||
+ .yes_ranges = ppe_readable_ranges,
|
||||
+ .n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges),
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_config regmap_config_ipq9574 = {
|
||||
+ .reg_bits = 32,
|
||||
+ .reg_stride = 4,
|
||||
+ .val_bits = 32,
|
||||
+ .rd_table = &ppe_reg_table,
|
||||
+ .wr_table = &ppe_reg_table,
|
||||
+ .max_register = 0xbef800,
|
||||
+ .fast_io = true,
|
||||
+};
|
||||
+
|
||||
+static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ unsigned long ppe_rate = ppe_dev->clk_rate;
|
||||
+ struct device *dev = ppe_dev->dev;
|
||||
+ struct reset_control *rstc;
|
||||
+ struct clk_bulk_data *clks;
|
||||
+ struct clk *clk;
|
||||
+ int ret, i;
|
||||
+
|
||||
+ for (i = 0; i < ppe_dev->num_icc_paths; i++) {
|
||||
+ ppe_dev->icc_paths[i].name = ppe_icc_data[i].name;
|
||||
+ ppe_dev->icc_paths[i].avg_bw = ppe_icc_data[i].avg_bw ? :
|
||||
+ Bps_to_icc(ppe_rate);
|
||||
+ ppe_dev->icc_paths[i].peak_bw = ppe_icc_data[i].peak_bw ? :
|
||||
+ Bps_to_icc(ppe_rate);
|
||||
+ }
|
||||
+
|
||||
+ ret = devm_of_icc_bulk_get(dev, ppe_dev->num_icc_paths,
|
||||
+ ppe_dev->icc_paths);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = icc_bulk_set_bw(ppe_dev->num_icc_paths, ppe_dev->icc_paths);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* The PPE clocks have a common parent clock. Setting the clock
|
||||
+ * rate of "ppe" ensures the clock rate of all PPE clocks is
|
||||
+ * configured to the same rate.
|
||||
+ */
|
||||
+ clk = devm_clk_get(dev, "ppe");
|
||||
+ if (IS_ERR(clk))
|
||||
+ return PTR_ERR(clk);
|
||||
+
|
||||
+ ret = clk_set_rate(clk, ppe_rate);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = devm_clk_bulk_get_all_enable(dev, &clks);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Reset the PPE. */
|
||||
+ rstc = devm_reset_control_get_exclusive(dev, NULL);
|
||||
+ if (IS_ERR(rstc))
|
||||
+ return PTR_ERR(rstc);
|
||||
+
|
||||
+ ret = reset_control_assert(rstc);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* The delay 10 ms of assert is necessary for resetting PPE. */
|
||||
+ usleep_range(10000, 11000);
|
||||
+
|
||||
+ return reset_control_deassert(rstc);
|
||||
+}
|
||||
+
|
||||
+static int qcom_ppe_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct ppe_device *ppe_dev;
|
||||
+ void __iomem *base;
|
||||
+ int ret, num_icc;
|
||||
+
|
||||
+ num_icc = ARRAY_SIZE(ppe_icc_data);
|
||||
+ ppe_dev = devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!ppe_dev)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(base))
|
||||
+ return dev_err_probe(dev, PTR_ERR(base), "PPE ioremap failed\n");
|
||||
+
|
||||
+ ppe_dev->regmap = devm_regmap_init_mmio(dev, base, ®map_config_ipq9574);
|
||||
+ if (IS_ERR(ppe_dev->regmap))
|
||||
+ return dev_err_probe(dev, PTR_ERR(ppe_dev->regmap),
|
||||
+ "PPE initialize regmap failed\n");
|
||||
+ ppe_dev->dev = dev;
|
||||
+ ppe_dev->clk_rate = PPE_CLK_RATE;
|
||||
+ ppe_dev->num_ports = PPE_PORT_MAX;
|
||||
+ ppe_dev->num_icc_paths = num_icc;
|
||||
+
|
||||
+ ret = ppe_clock_init_and_reset(ppe_dev);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "PPE clock config failed\n");
|
||||
+
|
||||
+ platform_set_drvdata(pdev, ppe_dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id qcom_ppe_of_match[] = {
|
||||
+ { .compatible = "qcom,ipq9574-ppe" },
|
||||
+ {}
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, qcom_ppe_of_match);
|
||||
+
|
||||
+static struct platform_driver qcom_ppe_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "qcom_ppe",
|
||||
+ .of_match_table = qcom_ppe_of_match,
|
||||
+ },
|
||||
+ .probe = qcom_ppe_probe,
|
||||
+};
|
||||
+module_platform_driver(qcom_ppe_driver);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ PPE driver");
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h
|
||||
@@ -0,0 +1,36 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-only
|
||||
+ *
|
||||
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __PPE_H__
|
||||
+#define __PPE_H__
|
||||
+
|
||||
+#include <linux/compiler.h>
|
||||
+#include <linux/interconnect.h>
|
||||
+
|
||||
+struct device;
|
||||
+struct regmap;
|
||||
+
|
||||
+/**
|
||||
+ * struct ppe_device - PPE device private data.
|
||||
+ * @dev: PPE device structure.
|
||||
+ * @regmap: PPE register map.
|
||||
+ * @clk_rate: PPE clock rate.
|
||||
+ * @num_ports: Number of PPE ports.
|
||||
+ * @num_icc_paths: Number of interconnect paths.
|
||||
+ * @icc_paths: Interconnect path array.
|
||||
+ *
|
||||
+ * PPE device is the instance of PPE hardware, which is used to
|
||||
+ * configure PPE packet process modules such as BM (buffer management),
|
||||
+ * QM (queue management), and scheduler.
|
||||
+ */
|
||||
+struct ppe_device {
|
||||
+ struct device *dev;
|
||||
+ struct regmap *regmap;
|
||||
+ unsigned long clk_rate;
|
||||
+ unsigned int num_ports;
|
||||
+ unsigned int num_icc_paths;
|
||||
+ struct icc_bulk_data icc_paths[] __counted_by(num_icc_paths);
|
||||
+};
|
||||
+#endif
|
||||
@ -1,328 +0,0 @@
|
||||
From 6e639ab45348ee7a697db8b481fa6f8555280f58 Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:38 +0800
|
||||
Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE buffer management for
|
||||
IPQ9574
|
||||
|
||||
The BM (Buffer Management) config controls the pause frame generated
|
||||
on the PPE port. There are maximum 15 BM ports and 4 groups supported,
|
||||
all BM ports are assigned to group 0 by default. The number of hardware
|
||||
buffers configured for the port influence the threshold of the flow
|
||||
control for that port.
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +-
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe.c | 5 +
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.c | 195 ++++++++++++++++++
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.h | 12 ++
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 59 ++++++
|
||||
5 files changed, 272 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/Makefile
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile
|
||||
@@ -4,4 +4,4 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o
|
||||
-qcom-ppe-objs := ppe.o
|
||||
+qcom-ppe-objs := ppe.o ppe_config.o
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include "ppe.h"
|
||||
+#include "ppe_config.h"
|
||||
|
||||
#define PPE_PORT_MAX 8
|
||||
#define PPE_CLK_RATE 353000000
|
||||
@@ -194,6 +195,10 @@ static int qcom_ppe_probe(struct platfor
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "PPE clock config failed\n");
|
||||
|
||||
+ ret = ppe_hw_config(ppe_dev);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "PPE HW config failed\n");
|
||||
+
|
||||
platform_set_drvdata(pdev, ppe_dev);
|
||||
|
||||
return 0;
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
@@ -0,0 +1,195 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+/* PPE HW initialization configs such as BM(buffer management),
|
||||
+ * QM(queue management) and scheduler configs.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/bits.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+
|
||||
+#include "ppe.h"
|
||||
+#include "ppe_config.h"
|
||||
+#include "ppe_regs.h"
|
||||
+
|
||||
+/**
|
||||
+ * struct ppe_bm_port_config - PPE BM port configuration.
|
||||
+ * @port_id_start: The fist BM port ID to configure.
|
||||
+ * @port_id_end: The last BM port ID to configure.
|
||||
+ * @pre_alloc: BM port dedicated buffer number.
|
||||
+ * @in_fly_buf: Buffer number for receiving the packet after pause frame sent.
|
||||
+ * @ceil: Ceil to generate the back pressure.
|
||||
+ * @weight: Weight value.
|
||||
+ * @resume_offset: Resume offset from the threshold value.
|
||||
+ * @resume_ceil: Ceil to resume from the back pressure state.
|
||||
+ * @dynamic: Dynamic threshold used or not.
|
||||
+ *
|
||||
+ * The is for configuring the threshold that impacts the port
|
||||
+ * flow control.
|
||||
+ */
|
||||
+struct ppe_bm_port_config {
|
||||
+ unsigned int port_id_start;
|
||||
+ unsigned int port_id_end;
|
||||
+ unsigned int pre_alloc;
|
||||
+ unsigned int in_fly_buf;
|
||||
+ unsigned int ceil;
|
||||
+ unsigned int weight;
|
||||
+ unsigned int resume_offset;
|
||||
+ unsigned int resume_ceil;
|
||||
+ bool dynamic;
|
||||
+};
|
||||
+
|
||||
+/* Assign the share buffer number 1550 to group 0 by default. */
|
||||
+static const int ipq9574_ppe_bm_group_config = 1550;
|
||||
+
|
||||
+/* The buffer configurations per PPE port. There are 15 BM ports and
|
||||
+ * 4 BM groups supported by PPE. BM port (0-7) is for EDMA port 0,
|
||||
+ * BM port (8-13) is for PPE physical port 1-6 and BM port 14 is for
|
||||
+ * EIP port.
|
||||
+ */
|
||||
+static const struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = {
|
||||
+ {
|
||||
+ /* Buffer configuration for the BM port ID 0 of EDMA. */
|
||||
+ .port_id_start = 0,
|
||||
+ .port_id_end = 0,
|
||||
+ .pre_alloc = 0,
|
||||
+ .in_fly_buf = 100,
|
||||
+ .ceil = 1146,
|
||||
+ .weight = 7,
|
||||
+ .resume_offset = 8,
|
||||
+ .resume_ceil = 0,
|
||||
+ .dynamic = true,
|
||||
+ },
|
||||
+ {
|
||||
+ /* Buffer configuration for the BM port ID 1-7 of EDMA. */
|
||||
+ .port_id_start = 1,
|
||||
+ .port_id_end = 7,
|
||||
+ .pre_alloc = 0,
|
||||
+ .in_fly_buf = 100,
|
||||
+ .ceil = 250,
|
||||
+ .weight = 4,
|
||||
+ .resume_offset = 36,
|
||||
+ .resume_ceil = 0,
|
||||
+ .dynamic = true,
|
||||
+ },
|
||||
+ {
|
||||
+ /* Buffer configuration for the BM port ID 8-13 of PPE ports. */
|
||||
+ .port_id_start = 8,
|
||||
+ .port_id_end = 13,
|
||||
+ .pre_alloc = 0,
|
||||
+ .in_fly_buf = 128,
|
||||
+ .ceil = 250,
|
||||
+ .weight = 4,
|
||||
+ .resume_offset = 36,
|
||||
+ .resume_ceil = 0,
|
||||
+ .dynamic = true,
|
||||
+ },
|
||||
+ {
|
||||
+ /* Buffer configuration for the BM port ID 14 of EIP. */
|
||||
+ .port_id_start = 14,
|
||||
+ .port_id_end = 14,
|
||||
+ .pre_alloc = 0,
|
||||
+ .in_fly_buf = 40,
|
||||
+ .ceil = 250,
|
||||
+ .weight = 4,
|
||||
+ .resume_offset = 36,
|
||||
+ .resume_ceil = 0,
|
||||
+ .dynamic = true,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
|
||||
+ const struct ppe_bm_port_config port_cfg)
|
||||
+{
|
||||
+ u32 reg, val, bm_fc_val[2];
|
||||
+ int ret;
|
||||
+
|
||||
+ reg = PPE_BM_PORT_FC_CFG_TBL_ADDR + PPE_BM_PORT_FC_CFG_TBL_INC * bm_port_id;
|
||||
+ ret = regmap_bulk_read(ppe_dev->regmap, reg,
|
||||
+ bm_fc_val, ARRAY_SIZE(bm_fc_val));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Configure BM flow control related threshold. */
|
||||
+ PPE_BM_PORT_FC_SET_WEIGHT(bm_fc_val, port_cfg.weight);
|
||||
+ PPE_BM_PORT_FC_SET_RESUME_OFFSET(bm_fc_val, port_cfg.resume_offset);
|
||||
+ PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(bm_fc_val, port_cfg.resume_ceil);
|
||||
+ PPE_BM_PORT_FC_SET_DYNAMIC(bm_fc_val, port_cfg.dynamic);
|
||||
+ PPE_BM_PORT_FC_SET_REACT_LIMIT(bm_fc_val, port_cfg.in_fly_buf);
|
||||
+ PPE_BM_PORT_FC_SET_PRE_ALLOC(bm_fc_val, port_cfg.pre_alloc);
|
||||
+
|
||||
+ /* Configure low/high bits of the ceiling for the BM port. */
|
||||
+ val = FIELD_GET(GENMASK(2, 0), port_cfg.ceil);
|
||||
+ PPE_BM_PORT_FC_SET_CEILING_LOW(bm_fc_val, val);
|
||||
+ val = FIELD_GET(GENMASK(10, 3), port_cfg.ceil);
|
||||
+ PPE_BM_PORT_FC_SET_CEILING_HIGH(bm_fc_val, val);
|
||||
+
|
||||
+ ret = regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ bm_fc_val, ARRAY_SIZE(bm_fc_val));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Assign the default group ID 0 to the BM port. */
|
||||
+ val = FIELD_PREP(PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, 0);
|
||||
+ reg = PPE_BM_PORT_GROUP_ID_ADDR + PPE_BM_PORT_GROUP_ID_INC * bm_port_id;
|
||||
+ ret = regmap_update_bits(ppe_dev->regmap, reg,
|
||||
+ PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID,
|
||||
+ val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Enable BM port flow control. */
|
||||
+ reg = PPE_BM_PORT_FC_MODE_ADDR + PPE_BM_PORT_FC_MODE_INC * bm_port_id;
|
||||
+
|
||||
+ return regmap_set_bits(ppe_dev->regmap, reg, PPE_BM_PORT_FC_MODE_EN);
|
||||
+}
|
||||
+
|
||||
+/* Configure the buffer threshold for the port flow control function. */
|
||||
+static int ppe_config_bm(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ const struct ppe_bm_port_config *port_cfg;
|
||||
+ unsigned int i, bm_port_id, port_cfg_cnt;
|
||||
+ u32 reg, val;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Configure the allocated buffer number only for group 0.
|
||||
+ * The buffer number of group 1-3 is already cleared to 0
|
||||
+ * after PPE reset during the probe of PPE driver.
|
||||
+ */
|
||||
+ reg = PPE_BM_SHARED_GROUP_CFG_ADDR;
|
||||
+ val = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,
|
||||
+ ipq9574_ppe_bm_group_config);
|
||||
+ ret = regmap_update_bits(ppe_dev->regmap, reg,
|
||||
+ PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT,
|
||||
+ val);
|
||||
+ if (ret)
|
||||
+ goto bm_config_fail;
|
||||
+
|
||||
+ /* Configure buffer thresholds for the BM ports. */
|
||||
+ port_cfg = ipq9574_ppe_bm_port_config;
|
||||
+ port_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config);
|
||||
+ for (i = 0; i < port_cfg_cnt; i++) {
|
||||
+ for (bm_port_id = port_cfg[i].port_id_start;
|
||||
+ bm_port_id <= port_cfg[i].port_id_end; bm_port_id++) {
|
||||
+ ret = ppe_config_bm_threshold(ppe_dev, bm_port_id,
|
||||
+ port_cfg[i]);
|
||||
+ if (ret)
|
||||
+ goto bm_config_fail;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+bm_config_fail:
|
||||
+ dev_err(ppe_dev->dev, "PPE BM config error %d\n", ret);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int ppe_hw_config(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ return ppe_config_bm(ppe_dev);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
@@ -0,0 +1,12 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-only
|
||||
+ *
|
||||
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __PPE_CONFIG_H__
|
||||
+#define __PPE_CONFIG_H__
|
||||
+
|
||||
+#include "ppe.h"
|
||||
+
|
||||
+int ppe_hw_config(struct ppe_device *ppe_dev);
|
||||
+#endif
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
@@ -0,0 +1,59 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-only
|
||||
+ *
|
||||
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+/* PPE hardware register and table declarations. */
|
||||
+#ifndef __PPE_REGS_H__
|
||||
+#define __PPE_REGS_H__
|
||||
+
|
||||
+#include <linux/bitfield.h>
|
||||
+
|
||||
+/* There are 15 BM ports and 4 BM groups supported by PPE.
|
||||
+ * BM port (0-7) is for EDMA port 0, BM port (8-13) is for
|
||||
+ * PPE physical port 1-6 and BM port 14 is for EIP port.
|
||||
+ */
|
||||
+#define PPE_BM_PORT_FC_MODE_ADDR 0x600100
|
||||
+#define PPE_BM_PORT_FC_MODE_ENTRIES 15
|
||||
+#define PPE_BM_PORT_FC_MODE_INC 0x4
|
||||
+#define PPE_BM_PORT_FC_MODE_EN BIT(0)
|
||||
+
|
||||
+#define PPE_BM_PORT_GROUP_ID_ADDR 0x600180
|
||||
+#define PPE_BM_PORT_GROUP_ID_ENTRIES 15
|
||||
+#define PPE_BM_PORT_GROUP_ID_INC 0x4
|
||||
+#define PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID GENMASK(1, 0)
|
||||
+
|
||||
+#define PPE_BM_SHARED_GROUP_CFG_ADDR 0x600290
|
||||
+#define PPE_BM_SHARED_GROUP_CFG_ENTRIES 4
|
||||
+#define PPE_BM_SHARED_GROUP_CFG_INC 0x4
|
||||
+#define PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT GENMASK(10, 0)
|
||||
+
|
||||
+#define PPE_BM_PORT_FC_CFG_TBL_ADDR 0x601000
|
||||
+#define PPE_BM_PORT_FC_CFG_TBL_ENTRIES 15
|
||||
+#define PPE_BM_PORT_FC_CFG_TBL_INC 0x10
|
||||
+#define PPE_BM_PORT_FC_W0_REACT_LIMIT GENMASK(8, 0)
|
||||
+#define PPE_BM_PORT_FC_W0_RESUME_THRESHOLD GENMASK(17, 9)
|
||||
+#define PPE_BM_PORT_FC_W0_RESUME_OFFSET GENMASK(28, 18)
|
||||
+#define PPE_BM_PORT_FC_W0_CEILING_LOW GENMASK(31, 29)
|
||||
+#define PPE_BM_PORT_FC_W1_CEILING_HIGH GENMASK(7, 0)
|
||||
+#define PPE_BM_PORT_FC_W1_WEIGHT GENMASK(10, 8)
|
||||
+#define PPE_BM_PORT_FC_W1_DYNAMIC BIT(11)
|
||||
+#define PPE_BM_PORT_FC_W1_PRE_ALLOC GENMASK(22, 12)
|
||||
+
|
||||
+#define PPE_BM_PORT_FC_SET_REACT_LIMIT(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_REACT_LIMIT)
|
||||
+#define PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_RESUME_THRESHOLD)
|
||||
+#define PPE_BM_PORT_FC_SET_RESUME_OFFSET(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_RESUME_OFFSET)
|
||||
+#define PPE_BM_PORT_FC_SET_CEILING_LOW(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_CEILING_LOW)
|
||||
+#define PPE_BM_PORT_FC_SET_CEILING_HIGH(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_CEILING_HIGH)
|
||||
+#define PPE_BM_PORT_FC_SET_WEIGHT(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_WEIGHT)
|
||||
+#define PPE_BM_PORT_FC_SET_DYNAMIC(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_DYNAMIC)
|
||||
+#define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC)
|
||||
+#endif
|
||||
@ -1,320 +0,0 @@
|
||||
From 9be6c3590ef3c241e6a3cfd05291304a1f973bcf Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:39 +0800
|
||||
Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE queue management for
|
||||
IPQ9574
|
||||
|
||||
QM (queue management) configurations decide the length of PPE
|
||||
queues and the queue depth for these queues which are used to
|
||||
drop packets in events of congestion.
|
||||
|
||||
There are two types of PPE queues - unicast queues (0-255) and
|
||||
multicast queues (256-299). These queue types are used to forward
|
||||
different types of traffic, and are configured with different
|
||||
lengths.
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.c | 177 +++++++++++++++++-
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 85 +++++++++
|
||||
2 files changed, 261 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
@@ -43,6 +43,29 @@ struct ppe_bm_port_config {
|
||||
bool dynamic;
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * struct ppe_qm_queue_config - PPE queue config.
|
||||
+ * @queue_start: PPE start of queue ID.
|
||||
+ * @queue_end: PPE end of queue ID.
|
||||
+ * @prealloc_buf: Queue dedicated buffer number.
|
||||
+ * @ceil: Ceil to start drop packet from queue.
|
||||
+ * @weight: Weight value.
|
||||
+ * @resume_offset: Resume offset from the threshold.
|
||||
+ * @dynamic: Threshold value is decided dynamically or statically.
|
||||
+ *
|
||||
+ * Queue configuration decides the threshold to drop packet from PPE
|
||||
+ * hardware queue.
|
||||
+ */
|
||||
+struct ppe_qm_queue_config {
|
||||
+ unsigned int queue_start;
|
||||
+ unsigned int queue_end;
|
||||
+ unsigned int prealloc_buf;
|
||||
+ unsigned int ceil;
|
||||
+ unsigned int weight;
|
||||
+ unsigned int resume_offset;
|
||||
+ bool dynamic;
|
||||
+};
|
||||
+
|
||||
/* Assign the share buffer number 1550 to group 0 by default. */
|
||||
static const int ipq9574_ppe_bm_group_config = 1550;
|
||||
|
||||
@@ -102,6 +125,33 @@ static const struct ppe_bm_port_config i
|
||||
},
|
||||
};
|
||||
|
||||
+/* Default QM group settings for IPQ9754. */
|
||||
+static const int ipq9574_ppe_qm_group_config = 2000;
|
||||
+
|
||||
+/* Default QM settings for unicast and multicast queues for IPQ9754. */
|
||||
+static const struct ppe_qm_queue_config ipq9574_ppe_qm_queue_config[] = {
|
||||
+ {
|
||||
+ /* QM settings for unicast queues 0 to 255. */
|
||||
+ .queue_start = 0,
|
||||
+ .queue_end = 255,
|
||||
+ .prealloc_buf = 0,
|
||||
+ .ceil = 1200,
|
||||
+ .weight = 7,
|
||||
+ .resume_offset = 36,
|
||||
+ .dynamic = true,
|
||||
+ },
|
||||
+ {
|
||||
+ /* QM settings for multicast queues 256 to 299. */
|
||||
+ .queue_start = 256,
|
||||
+ .queue_end = 299,
|
||||
+ .prealloc_buf = 0,
|
||||
+ .ceil = 250,
|
||||
+ .weight = 0,
|
||||
+ .resume_offset = 36,
|
||||
+ .dynamic = false,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
|
||||
const struct ppe_bm_port_config port_cfg)
|
||||
{
|
||||
@@ -189,7 +239,132 @@ bm_config_fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* Configure PPE hardware queue depth, which is decided by the threshold
|
||||
+ * of queue.
|
||||
+ */
|
||||
+static int ppe_config_qm(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ const struct ppe_qm_queue_config *queue_cfg;
|
||||
+ int ret, i, queue_id, queue_cfg_count;
|
||||
+ u32 reg, multicast_queue_cfg[5];
|
||||
+ u32 unicast_queue_cfg[4];
|
||||
+ u32 group_cfg[3];
|
||||
+
|
||||
+ /* Assign the buffer number to the group 0 by default. */
|
||||
+ reg = PPE_AC_GRP_CFG_TBL_ADDR;
|
||||
+ ret = regmap_bulk_read(ppe_dev->regmap, reg,
|
||||
+ group_cfg, ARRAY_SIZE(group_cfg));
|
||||
+ if (ret)
|
||||
+ goto qm_config_fail;
|
||||
+
|
||||
+ PPE_AC_GRP_SET_BUF_LIMIT(group_cfg, ipq9574_ppe_qm_group_config);
|
||||
+
|
||||
+ ret = regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ group_cfg, ARRAY_SIZE(group_cfg));
|
||||
+ if (ret)
|
||||
+ goto qm_config_fail;
|
||||
+
|
||||
+ queue_cfg = ipq9574_ppe_qm_queue_config;
|
||||
+ queue_cfg_count = ARRAY_SIZE(ipq9574_ppe_qm_queue_config);
|
||||
+ for (i = 0; i < queue_cfg_count; i++) {
|
||||
+ queue_id = queue_cfg[i].queue_start;
|
||||
+
|
||||
+ /* Configure threshold for dropping packets separately for
|
||||
+ * unicast and multicast PPE queues.
|
||||
+ */
|
||||
+ while (queue_id <= queue_cfg[i].queue_end) {
|
||||
+ if (queue_id < PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES) {
|
||||
+ reg = PPE_AC_UNICAST_QUEUE_CFG_TBL_ADDR +
|
||||
+ PPE_AC_UNICAST_QUEUE_CFG_TBL_INC * queue_id;
|
||||
+
|
||||
+ ret = regmap_bulk_read(ppe_dev->regmap, reg,
|
||||
+ unicast_queue_cfg,
|
||||
+ ARRAY_SIZE(unicast_queue_cfg));
|
||||
+ if (ret)
|
||||
+ goto qm_config_fail;
|
||||
+
|
||||
+ PPE_AC_UNICAST_QUEUE_SET_EN(unicast_queue_cfg, true);
|
||||
+ PPE_AC_UNICAST_QUEUE_SET_GRP_ID(unicast_queue_cfg, 0);
|
||||
+ PPE_AC_UNICAST_QUEUE_SET_PRE_LIMIT(unicast_queue_cfg,
|
||||
+ queue_cfg[i].prealloc_buf);
|
||||
+ PPE_AC_UNICAST_QUEUE_SET_DYNAMIC(unicast_queue_cfg,
|
||||
+ queue_cfg[i].dynamic);
|
||||
+ PPE_AC_UNICAST_QUEUE_SET_WEIGHT(unicast_queue_cfg,
|
||||
+ queue_cfg[i].weight);
|
||||
+ PPE_AC_UNICAST_QUEUE_SET_THRESHOLD(unicast_queue_cfg,
|
||||
+ queue_cfg[i].ceil);
|
||||
+ PPE_AC_UNICAST_QUEUE_SET_GRN_RESUME(unicast_queue_cfg,
|
||||
+ queue_cfg[i].resume_offset);
|
||||
+
|
||||
+ ret = regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ unicast_queue_cfg,
|
||||
+ ARRAY_SIZE(unicast_queue_cfg));
|
||||
+ if (ret)
|
||||
+ goto qm_config_fail;
|
||||
+ } else {
|
||||
+ reg = PPE_AC_MULTICAST_QUEUE_CFG_TBL_ADDR +
|
||||
+ PPE_AC_MULTICAST_QUEUE_CFG_TBL_INC * queue_id;
|
||||
+
|
||||
+ ret = regmap_bulk_read(ppe_dev->regmap, reg,
|
||||
+ multicast_queue_cfg,
|
||||
+ ARRAY_SIZE(multicast_queue_cfg));
|
||||
+ if (ret)
|
||||
+ goto qm_config_fail;
|
||||
+
|
||||
+ PPE_AC_MULTICAST_QUEUE_SET_EN(multicast_queue_cfg, true);
|
||||
+ PPE_AC_MULTICAST_QUEUE_SET_GRN_GRP_ID(multicast_queue_cfg, 0);
|
||||
+ PPE_AC_MULTICAST_QUEUE_SET_GRN_PRE_LIMIT(multicast_queue_cfg,
|
||||
+ queue_cfg[i].prealloc_buf);
|
||||
+ PPE_AC_MULTICAST_QUEUE_SET_GRN_THRESHOLD(multicast_queue_cfg,
|
||||
+ queue_cfg[i].ceil);
|
||||
+ PPE_AC_MULTICAST_QUEUE_SET_GRN_RESUME(multicast_queue_cfg,
|
||||
+ queue_cfg[i].resume_offset);
|
||||
+
|
||||
+ ret = regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ multicast_queue_cfg,
|
||||
+ ARRAY_SIZE(multicast_queue_cfg));
|
||||
+ if (ret)
|
||||
+ goto qm_config_fail;
|
||||
+ }
|
||||
+
|
||||
+ /* Enable enqueue. */
|
||||
+ reg = PPE_ENQ_OPR_TBL_ADDR + PPE_ENQ_OPR_TBL_INC * queue_id;
|
||||
+ ret = regmap_clear_bits(ppe_dev->regmap, reg,
|
||||
+ PPE_ENQ_OPR_TBL_ENQ_DISABLE);
|
||||
+ if (ret)
|
||||
+ goto qm_config_fail;
|
||||
+
|
||||
+ /* Enable dequeue. */
|
||||
+ reg = PPE_DEQ_OPR_TBL_ADDR + PPE_DEQ_OPR_TBL_INC * queue_id;
|
||||
+ ret = regmap_clear_bits(ppe_dev->regmap, reg,
|
||||
+ PPE_DEQ_OPR_TBL_DEQ_DISABLE);
|
||||
+ if (ret)
|
||||
+ goto qm_config_fail;
|
||||
+
|
||||
+ queue_id++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Enable queue counter for all PPE hardware queues. */
|
||||
+ ret = regmap_set_bits(ppe_dev->regmap, PPE_EG_BRIDGE_CONFIG_ADDR,
|
||||
+ PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN);
|
||||
+ if (ret)
|
||||
+ goto qm_config_fail;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+qm_config_fail:
|
||||
+ dev_err(ppe_dev->dev, "PPE QM config error %d\n", ret);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int ppe_hw_config(struct ppe_device *ppe_dev)
|
||||
{
|
||||
- return ppe_config_bm(ppe_dev);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ppe_config_bm(ppe_dev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ppe_config_qm(ppe_dev);
|
||||
}
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
@@ -9,6 +9,16 @@
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
+/* PPE queue counters enable/disable control. */
|
||||
+#define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044
|
||||
+#define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2)
|
||||
+
|
||||
+/* Table addresses for per-queue dequeue setting. */
|
||||
+#define PPE_DEQ_OPR_TBL_ADDR 0x430000
|
||||
+#define PPE_DEQ_OPR_TBL_ENTRIES 300
|
||||
+#define PPE_DEQ_OPR_TBL_INC 0x10
|
||||
+#define PPE_DEQ_OPR_TBL_DEQ_DISABLE BIT(0)
|
||||
+
|
||||
/* There are 15 BM ports and 4 BM groups supported by PPE.
|
||||
* BM port (0-7) is for EDMA port 0, BM port (8-13) is for
|
||||
* PPE physical port 1-6 and BM port 14 is for EIP port.
|
||||
@@ -56,4 +66,79 @@
|
||||
u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_DYNAMIC)
|
||||
#define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \
|
||||
u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC)
|
||||
+
|
||||
+/* PPE unicast queue (0-255) configurations. */
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_TBL_ADDR 0x848000
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES 256
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_TBL_INC 0x10
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_W0_EN BIT(0)
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_W0_WRED_EN BIT(1)
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_W0_FC_EN BIT(2)
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_W0_CLR_AWARE BIT(3)
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_W0_GRP_ID GENMASK(5, 4)
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_W0_PRE_LIMIT GENMASK(16, 6)
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_W0_DYNAMIC BIT(17)
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_W0_WEIGHT GENMASK(20, 18)
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_W0_THRESHOLD GENMASK(31, 21)
|
||||
+#define PPE_AC_UNICAST_QUEUE_CFG_W3_GRN_RESUME GENMASK(23, 13)
|
||||
+
|
||||
+#define PPE_AC_UNICAST_QUEUE_SET_EN(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_EN)
|
||||
+#define PPE_AC_UNICAST_QUEUE_SET_GRP_ID(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_GRP_ID)
|
||||
+#define PPE_AC_UNICAST_QUEUE_SET_PRE_LIMIT(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_PRE_LIMIT)
|
||||
+#define PPE_AC_UNICAST_QUEUE_SET_DYNAMIC(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_DYNAMIC)
|
||||
+#define PPE_AC_UNICAST_QUEUE_SET_WEIGHT(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_WEIGHT)
|
||||
+#define PPE_AC_UNICAST_QUEUE_SET_THRESHOLD(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_THRESHOLD)
|
||||
+#define PPE_AC_UNICAST_QUEUE_SET_GRN_RESUME(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x3, value, PPE_AC_UNICAST_QUEUE_CFG_W3_GRN_RESUME)
|
||||
+
|
||||
+/* PPE multicast queue (256-299) configurations. */
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_ADDR 0x84a000
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_ENTRIES 44
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_INC 0x10
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_EN BIT(0)
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_FC_EN BIT(1)
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_CLR_AWARE BIT(2)
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_GRP_ID GENMASK(4, 3)
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_PRE_LIMIT GENMASK(15, 5)
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_THRESHOLD GENMASK(26, 16)
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CFG_W2_RESUME GENMASK(17, 7)
|
||||
+
|
||||
+#define PPE_AC_MULTICAST_QUEUE_SET_EN(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_EN)
|
||||
+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_GRP_ID(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_GRP_ID)
|
||||
+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_PRE_LIMIT(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_PRE_LIMIT)
|
||||
+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_THRESHOLD(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_THRESHOLD)
|
||||
+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_RESUME(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x2, value, PPE_AC_MULTICAST_QUEUE_CFG_W2_RESUME)
|
||||
+
|
||||
+/* PPE admission control group (0-3) configurations */
|
||||
+#define PPE_AC_GRP_CFG_TBL_ADDR 0x84c000
|
||||
+#define PPE_AC_GRP_CFG_TBL_ENTRIES 0x4
|
||||
+#define PPE_AC_GRP_CFG_TBL_INC 0x10
|
||||
+#define PPE_AC_GRP_W0_AC_EN BIT(0)
|
||||
+#define PPE_AC_GRP_W0_AC_FC_EN BIT(1)
|
||||
+#define PPE_AC_GRP_W0_CLR_AWARE BIT(2)
|
||||
+#define PPE_AC_GRP_W0_THRESHOLD_LOW GENMASK(31, 25)
|
||||
+#define PPE_AC_GRP_W1_THRESHOLD_HIGH GENMASK(3, 0)
|
||||
+#define PPE_AC_GRP_W1_BUF_LIMIT GENMASK(14, 4)
|
||||
+#define PPE_AC_GRP_W2_RESUME_GRN GENMASK(15, 5)
|
||||
+#define PPE_AC_GRP_W2_PRE_ALLOC GENMASK(26, 16)
|
||||
+
|
||||
+#define PPE_AC_GRP_SET_BUF_LIMIT(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_AC_GRP_W1_BUF_LIMIT)
|
||||
+
|
||||
+/* Table addresses for per-queue enqueue setting. */
|
||||
+#define PPE_ENQ_OPR_TBL_ADDR 0x85c000
|
||||
+#define PPE_ENQ_OPR_TBL_ENTRIES 300
|
||||
+#define PPE_ENQ_OPR_TBL_INC 0x10
|
||||
+#define PPE_ENQ_OPR_TBL_ENQ_DISABLE BIT(0)
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,522 +0,0 @@
|
||||
From 63874f7c2e46f192e43e6214d66236372e36396c Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:41 +0800
|
||||
Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE queue settings
|
||||
|
||||
Configure unicast and multicast hardware queues for the PPE
|
||||
ports to enable packet forwarding between the ports.
|
||||
|
||||
Each PPE port is assigned with a range of queues. The queue ID
|
||||
selection for a packet is decided by the queue base and queue
|
||||
offset that is configured based on the internal priority and
|
||||
the RSS hash value of the packet.
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.c | 356 +++++++++++++++++-
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.h | 63 ++++
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 21 ++
|
||||
3 files changed, 439 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
@@ -128,6 +128,34 @@ struct ppe_scheduler_port_config {
|
||||
unsigned int drr_node_id;
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * struct ppe_port_schedule_resource - PPE port scheduler resource.
|
||||
+ * @ucastq_start: Unicast queue start ID.
|
||||
+ * @ucastq_end: Unicast queue end ID.
|
||||
+ * @mcastq_start: Multicast queue start ID.
|
||||
+ * @mcastq_end: Multicast queue end ID.
|
||||
+ * @flow_id_start: Flow start ID.
|
||||
+ * @flow_id_end: Flow end ID.
|
||||
+ * @l0node_start: Scheduler node start ID for queue level.
|
||||
+ * @l0node_end: Scheduler node end ID for queue level.
|
||||
+ * @l1node_start: Scheduler node start ID for flow level.
|
||||
+ * @l1node_end: Scheduler node end ID for flow level.
|
||||
+ *
|
||||
+ * PPE scheduler resource allocated among the PPE ports.
|
||||
+ */
|
||||
+struct ppe_port_schedule_resource {
|
||||
+ unsigned int ucastq_start;
|
||||
+ unsigned int ucastq_end;
|
||||
+ unsigned int mcastq_start;
|
||||
+ unsigned int mcastq_end;
|
||||
+ unsigned int flow_id_start;
|
||||
+ unsigned int flow_id_end;
|
||||
+ unsigned int l0node_start;
|
||||
+ unsigned int l0node_end;
|
||||
+ unsigned int l1node_start;
|
||||
+ unsigned int l1node_end;
|
||||
+};
|
||||
+
|
||||
/* Assign the share buffer number 1550 to group 0 by default. */
|
||||
static const int ipq9574_ppe_bm_group_config = 1550;
|
||||
|
||||
@@ -676,6 +704,111 @@ static const struct ppe_scheduler_port_c
|
||||
},
|
||||
};
|
||||
|
||||
+/* The scheduler resource is applied to each PPE port, The resource
|
||||
+ * includes the unicast & multicast queues, flow nodes and DRR nodes.
|
||||
+ */
|
||||
+static const struct ppe_port_schedule_resource ppe_scheduler_res[] = {
|
||||
+ { .ucastq_start = 0,
|
||||
+ .ucastq_end = 63,
|
||||
+ .mcastq_start = 256,
|
||||
+ .mcastq_end = 271,
|
||||
+ .flow_id_start = 0,
|
||||
+ .flow_id_end = 0,
|
||||
+ .l0node_start = 0,
|
||||
+ .l0node_end = 7,
|
||||
+ .l1node_start = 0,
|
||||
+ .l1node_end = 0,
|
||||
+ },
|
||||
+ { .ucastq_start = 144,
|
||||
+ .ucastq_end = 159,
|
||||
+ .mcastq_start = 272,
|
||||
+ .mcastq_end = 275,
|
||||
+ .flow_id_start = 36,
|
||||
+ .flow_id_end = 39,
|
||||
+ .l0node_start = 48,
|
||||
+ .l0node_end = 63,
|
||||
+ .l1node_start = 8,
|
||||
+ .l1node_end = 11,
|
||||
+ },
|
||||
+ { .ucastq_start = 160,
|
||||
+ .ucastq_end = 175,
|
||||
+ .mcastq_start = 276,
|
||||
+ .mcastq_end = 279,
|
||||
+ .flow_id_start = 40,
|
||||
+ .flow_id_end = 43,
|
||||
+ .l0node_start = 64,
|
||||
+ .l0node_end = 79,
|
||||
+ .l1node_start = 12,
|
||||
+ .l1node_end = 15,
|
||||
+ },
|
||||
+ { .ucastq_start = 176,
|
||||
+ .ucastq_end = 191,
|
||||
+ .mcastq_start = 280,
|
||||
+ .mcastq_end = 283,
|
||||
+ .flow_id_start = 44,
|
||||
+ .flow_id_end = 47,
|
||||
+ .l0node_start = 80,
|
||||
+ .l0node_end = 95,
|
||||
+ .l1node_start = 16,
|
||||
+ .l1node_end = 19,
|
||||
+ },
|
||||
+ { .ucastq_start = 192,
|
||||
+ .ucastq_end = 207,
|
||||
+ .mcastq_start = 284,
|
||||
+ .mcastq_end = 287,
|
||||
+ .flow_id_start = 48,
|
||||
+ .flow_id_end = 51,
|
||||
+ .l0node_start = 96,
|
||||
+ .l0node_end = 111,
|
||||
+ .l1node_start = 20,
|
||||
+ .l1node_end = 23,
|
||||
+ },
|
||||
+ { .ucastq_start = 208,
|
||||
+ .ucastq_end = 223,
|
||||
+ .mcastq_start = 288,
|
||||
+ .mcastq_end = 291,
|
||||
+ .flow_id_start = 52,
|
||||
+ .flow_id_end = 55,
|
||||
+ .l0node_start = 112,
|
||||
+ .l0node_end = 127,
|
||||
+ .l1node_start = 24,
|
||||
+ .l1node_end = 27,
|
||||
+ },
|
||||
+ { .ucastq_start = 224,
|
||||
+ .ucastq_end = 239,
|
||||
+ .mcastq_start = 292,
|
||||
+ .mcastq_end = 295,
|
||||
+ .flow_id_start = 56,
|
||||
+ .flow_id_end = 59,
|
||||
+ .l0node_start = 128,
|
||||
+ .l0node_end = 143,
|
||||
+ .l1node_start = 28,
|
||||
+ .l1node_end = 31,
|
||||
+ },
|
||||
+ { .ucastq_start = 240,
|
||||
+ .ucastq_end = 255,
|
||||
+ .mcastq_start = 296,
|
||||
+ .mcastq_end = 299,
|
||||
+ .flow_id_start = 60,
|
||||
+ .flow_id_end = 63,
|
||||
+ .l0node_start = 144,
|
||||
+ .l0node_end = 159,
|
||||
+ .l1node_start = 32,
|
||||
+ .l1node_end = 35,
|
||||
+ },
|
||||
+ { .ucastq_start = 64,
|
||||
+ .ucastq_end = 143,
|
||||
+ .mcastq_start = 0,
|
||||
+ .mcastq_end = 0,
|
||||
+ .flow_id_start = 1,
|
||||
+ .flow_id_end = 35,
|
||||
+ .l0node_start = 8,
|
||||
+ .l0node_end = 47,
|
||||
+ .l1node_start = 1,
|
||||
+ .l1node_end = 7,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
/* Set the PPE queue level scheduler configuration. */
|
||||
static int ppe_scheduler_l0_queue_map_set(struct ppe_device *ppe_dev,
|
||||
int node_id, int port,
|
||||
@@ -807,6 +940,149 @@ int ppe_queue_scheduler_set(struct ppe_d
|
||||
port, scheduler_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
|
||||
+ * @queue_base: PPE queue base ID
|
||||
+ * @profile_id: Profile ID
|
||||
+ *
|
||||
+ * The PPE unicast queue base ID and profile ID are configured based on the
|
||||
+ * destination port information that can be service code or CPU code or the
|
||||
+ * destination port.
|
||||
+ *
|
||||
+ * Return: 0 on success, negative error code on failure.
|
||||
+ */
|
||||
+int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev,
|
||||
+ struct ppe_queue_ucast_dest queue_dst,
|
||||
+ int queue_base, int profile_id)
|
||||
+{
|
||||
+ int index, profile_size;
|
||||
+ u32 val, reg;
|
||||
+
|
||||
+ profile_size = queue_dst.src_profile << 8;
|
||||
+ if (queue_dst.service_code_en)
|
||||
+ index = PPE_QUEUE_BASE_SERVICE_CODE + profile_size +
|
||||
+ queue_dst.service_code;
|
||||
+ else if (queue_dst.cpu_code_en)
|
||||
+ index = PPE_QUEUE_BASE_CPU_CODE + profile_size +
|
||||
+ queue_dst.cpu_code;
|
||||
+ else
|
||||
+ index = profile_size + queue_dst.dest_port;
|
||||
+
|
||||
+ val = FIELD_PREP(PPE_UCAST_QUEUE_MAP_TBL_PROFILE_ID, profile_id);
|
||||
+ val |= FIELD_PREP(PPE_UCAST_QUEUE_MAP_TBL_QUEUE_ID, queue_base);
|
||||
+ reg = PPE_UCAST_QUEUE_MAP_TBL_ADDR + index * PPE_UCAST_QUEUE_MAP_TBL_INC;
|
||||
+
|
||||
+ return regmap_write(ppe_dev->regmap, reg, val);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * ppe_queue_ucast_offset_pri_set - Set PPE unicast queue offset based on priority
|
||||
+ * @ppe_dev: PPE device
|
||||
+ * @profile_id: Profile ID
|
||||
+ * @priority: PPE internal priority to be used to set queue offset
|
||||
+ * @queue_offset: Queue offset used for calculating the destination queue ID
|
||||
+ *
|
||||
+ * The PPE unicast queue offset is configured based on the PPE
|
||||
+ * internal priority.
|
||||
+ *
|
||||
+ * Return: 0 on success, negative error code on failure.
|
||||
+ */
|
||||
+int ppe_queue_ucast_offset_pri_set(struct ppe_device *ppe_dev,
|
||||
+ int profile_id,
|
||||
+ int priority,
|
||||
+ int queue_offset)
|
||||
+{
|
||||
+ u32 val, reg;
|
||||
+ int index;
|
||||
+
|
||||
+ index = (profile_id << 4) + priority;
|
||||
+ val = FIELD_PREP(PPE_UCAST_PRIORITY_MAP_TBL_CLASS, queue_offset);
|
||||
+ reg = PPE_UCAST_PRIORITY_MAP_TBL_ADDR + index * PPE_UCAST_PRIORITY_MAP_TBL_INC;
|
||||
+
|
||||
+ return regmap_write(ppe_dev->regmap, reg, val);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * ppe_queue_ucast_offset_hash_set - Set PPE unicast queue offset based on hash
|
||||
+ * @ppe_dev: PPE device
|
||||
+ * @profile_id: Profile ID
|
||||
+ * @rss_hash: Packet hash value to be used to set queue offset
|
||||
+ * @queue_offset: Queue offset used for calculating the destination queue ID
|
||||
+ *
|
||||
+ * The PPE unicast queue offset is configured based on the RSS hash value.
|
||||
+ *
|
||||
+ * Return: 0 on success, negative error code on failure.
|
||||
+ */
|
||||
+int ppe_queue_ucast_offset_hash_set(struct ppe_device *ppe_dev,
|
||||
+ int profile_id,
|
||||
+ int rss_hash,
|
||||
+ int queue_offset)
|
||||
+{
|
||||
+ u32 val, reg;
|
||||
+ int index;
|
||||
+
|
||||
+ index = (profile_id << 8) + rss_hash;
|
||||
+ val = FIELD_PREP(PPE_UCAST_HASH_MAP_TBL_HASH, queue_offset);
|
||||
+ reg = PPE_UCAST_HASH_MAP_TBL_ADDR + index * PPE_UCAST_HASH_MAP_TBL_INC;
|
||||
+
|
||||
+ return regmap_write(ppe_dev->regmap, reg, val);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * ppe_port_resource_get - Get PPE resource per port
|
||||
+ * @ppe_dev: PPE device
|
||||
+ * @port: PPE port
|
||||
+ * @type: Resource type
|
||||
+ * @res_start: Resource start ID returned
|
||||
+ * @res_end: Resource end ID returned
|
||||
+ *
|
||||
+ * PPE resource is assigned per PPE port, which is acquired for QoS scheduler.
|
||||
+ *
|
||||
+ * Return: 0 on success, negative error code on failure.
|
||||
+ */
|
||||
+int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,
|
||||
+ enum ppe_resource_type type,
|
||||
+ int *res_start, int *res_end)
|
||||
+{
|
||||
+ struct ppe_port_schedule_resource res;
|
||||
+
|
||||
+ /* The reserved resource with the maximum port ID of PPE is
|
||||
+ * also allowed to be acquired.
|
||||
+ */
|
||||
+ if (port > ppe_dev->num_ports)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ res = ppe_scheduler_res[port];
|
||||
+ switch (type) {
|
||||
+ case PPE_RES_UCAST:
|
||||
+ *res_start = res.ucastq_start;
|
||||
+ *res_end = res.ucastq_end;
|
||||
+ break;
|
||||
+ case PPE_RES_MCAST:
|
||||
+ *res_start = res.mcastq_start;
|
||||
+ *res_end = res.mcastq_end;
|
||||
+ break;
|
||||
+ case PPE_RES_FLOW_ID:
|
||||
+ *res_start = res.flow_id_start;
|
||||
+ *res_end = res.flow_id_end;
|
||||
+ break;
|
||||
+ case PPE_RES_L0_NODE:
|
||||
+ *res_start = res.l0node_start;
|
||||
+ *res_end = res.l0node_end;
|
||||
+ break;
|
||||
+ case PPE_RES_L1_NODE:
|
||||
+ *res_start = res.l1node_start;
|
||||
+ *res_end = res.l1node_end;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
|
||||
const struct ppe_bm_port_config port_cfg)
|
||||
{
|
||||
@@ -1140,6 +1416,80 @@ sch_config_fail:
|
||||
return ret;
|
||||
};
|
||||
|
||||
+/* Configure PPE queue destination of each PPE port. */
|
||||
+static int ppe_queue_dest_init(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ int ret, port_id, index, q_base, q_offset, res_start, res_end, pri_max;
|
||||
+ struct ppe_queue_ucast_dest queue_dst;
|
||||
+
|
||||
+ for (port_id = 0; port_id < ppe_dev->num_ports; port_id++) {
|
||||
+ memset(&queue_dst, 0, sizeof(queue_dst));
|
||||
+
|
||||
+ ret = ppe_port_resource_get(ppe_dev, port_id, PPE_RES_UCAST,
|
||||
+ &res_start, &res_end);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ q_base = res_start;
|
||||
+ queue_dst.dest_port = port_id;
|
||||
+
|
||||
+ /* Configure queue base ID and profile ID that is same as
|
||||
+ * physical port ID.
|
||||
+ */
|
||||
+ ret = ppe_queue_ucast_base_set(ppe_dev, queue_dst,
|
||||
+ q_base, port_id);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Queue priority range supported by each PPE port */
|
||||
+ ret = ppe_port_resource_get(ppe_dev, port_id, PPE_RES_L0_NODE,
|
||||
+ &res_start, &res_end);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ pri_max = res_end - res_start;
|
||||
+
|
||||
+ /* Redirect ARP reply packet with the max priority on CPU port,
|
||||
+ * which keeps the ARP reply directed to CPU (CPU code is 101)
|
||||
+ * with highest priority queue of EDMA.
|
||||
+ */
|
||||
+ if (port_id == 0) {
|
||||
+ memset(&queue_dst, 0, sizeof(queue_dst));
|
||||
+
|
||||
+ queue_dst.cpu_code_en = true;
|
||||
+ queue_dst.cpu_code = 101;
|
||||
+ ret = ppe_queue_ucast_base_set(ppe_dev, queue_dst,
|
||||
+ q_base + pri_max,
|
||||
+ 0);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Initialize the queue offset of internal priority. */
|
||||
+ for (index = 0; index < PPE_QUEUE_INTER_PRI_NUM; index++) {
|
||||
+ q_offset = index > pri_max ? pri_max : index;
|
||||
+
|
||||
+ ret = ppe_queue_ucast_offset_pri_set(ppe_dev, port_id,
|
||||
+ index, q_offset);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Initialize the queue offset of RSS hash as 0 to avoid the
|
||||
+ * random hardware value that will lead to the unexpected
|
||||
+ * destination queue generated.
|
||||
+ */
|
||||
+ for (index = 0; index < PPE_QUEUE_HASH_NUM; index++) {
|
||||
+ ret = ppe_queue_ucast_offset_hash_set(ppe_dev, port_id,
|
||||
+ index, 0);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int ppe_hw_config(struct ppe_device *ppe_dev)
|
||||
{
|
||||
int ret;
|
||||
@@ -1152,5 +1502,9 @@ int ppe_hw_config(struct ppe_device *ppe
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- return ppe_config_scheduler(ppe_dev);
|
||||
+ ret = ppe_config_scheduler(ppe_dev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ppe_queue_dest_init(ppe_dev);
|
||||
}
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
@@ -8,6 +8,16 @@
|
||||
|
||||
#include "ppe.h"
|
||||
|
||||
+/* There are different table index ranges for configuring queue base ID of
|
||||
+ * the destination port, CPU code and service code.
|
||||
+ */
|
||||
+#define PPE_QUEUE_BASE_DEST_PORT 0
|
||||
+#define PPE_QUEUE_BASE_CPU_CODE 1024
|
||||
+#define PPE_QUEUE_BASE_SERVICE_CODE 2048
|
||||
+
|
||||
+#define PPE_QUEUE_INTER_PRI_NUM 16
|
||||
+#define PPE_QUEUE_HASH_NUM 256
|
||||
+
|
||||
/**
|
||||
* enum ppe_scheduler_frame_mode - PPE scheduler frame mode.
|
||||
* @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG,
|
||||
@@ -42,8 +52,61 @@ struct ppe_scheduler_cfg {
|
||||
enum ppe_scheduler_frame_mode frame_mode;
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * enum ppe_resource_type - PPE resource type.
|
||||
+ * @PPE_RES_UCAST: Unicast queue resource.
|
||||
+ * @PPE_RES_MCAST: Multicast queue resource.
|
||||
+ * @PPE_RES_L0_NODE: Level 0 for queue based node resource.
|
||||
+ * @PPE_RES_L1_NODE: Level 1 for flow based node resource.
|
||||
+ * @PPE_RES_FLOW_ID: Flow based node resource.
|
||||
+ */
|
||||
+enum ppe_resource_type {
|
||||
+ PPE_RES_UCAST,
|
||||
+ PPE_RES_MCAST,
|
||||
+ PPE_RES_L0_NODE,
|
||||
+ PPE_RES_L1_NODE,
|
||||
+ PPE_RES_FLOW_ID,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct ppe_queue_ucast_dest - PPE unicast queue destination.
|
||||
+ * @src_profile: Source profile.
|
||||
+ * @service_code_en: Enable service code to map the queue base ID.
|
||||
+ * @service_code: Service code.
|
||||
+ * @cpu_code_en: Enable CPU code to map the queue base ID.
|
||||
+ * @cpu_code: CPU code.
|
||||
+ * @dest_port: destination port.
|
||||
+ *
|
||||
+ * PPE egress queue ID is decided by the service code if enabled, otherwise
|
||||
+ * by the CPU code if enabled, or by destination port if both service code
|
||||
+ * and CPU code are disabled.
|
||||
+ */
|
||||
+struct ppe_queue_ucast_dest {
|
||||
+ int src_profile;
|
||||
+ bool service_code_en;
|
||||
+ int service_code;
|
||||
+ bool cpu_code_en;
|
||||
+ int cpu_code;
|
||||
+ int dest_port;
|
||||
+};
|
||||
+
|
||||
int ppe_hw_config(struct ppe_device *ppe_dev);
|
||||
int ppe_queue_scheduler_set(struct ppe_device *ppe_dev,
|
||||
int node_id, bool flow_level, int port,
|
||||
struct ppe_scheduler_cfg scheduler_cfg);
|
||||
+int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev,
|
||||
+ struct ppe_queue_ucast_dest queue_dst,
|
||||
+ int queue_base,
|
||||
+ int profile_id);
|
||||
+int ppe_queue_ucast_offset_pri_set(struct ppe_device *ppe_dev,
|
||||
+ int profile_id,
|
||||
+ int priority,
|
||||
+ int queue_offset);
|
||||
+int ppe_queue_ucast_offset_hash_set(struct ppe_device *ppe_dev,
|
||||
+ int profile_id,
|
||||
+ int rss_hash,
|
||||
+ int queue_offset);
|
||||
+int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,
|
||||
+ enum ppe_resource_type type,
|
||||
+ int *res_start, int *res_end);
|
||||
#endif
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
@@ -164,6 +164,27 @@
|
||||
#define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \
|
||||
u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC)
|
||||
|
||||
+/* The queue base configurations based on destination port,
|
||||
+ * service code or CPU code.
|
||||
+ */
|
||||
+#define PPE_UCAST_QUEUE_MAP_TBL_ADDR 0x810000
|
||||
+#define PPE_UCAST_QUEUE_MAP_TBL_ENTRIES 3072
|
||||
+#define PPE_UCAST_QUEUE_MAP_TBL_INC 0x10
|
||||
+#define PPE_UCAST_QUEUE_MAP_TBL_PROFILE_ID GENMASK(3, 0)
|
||||
+#define PPE_UCAST_QUEUE_MAP_TBL_QUEUE_ID GENMASK(11, 4)
|
||||
+
|
||||
+/* The queue offset configurations based on RSS hash value. */
|
||||
+#define PPE_UCAST_HASH_MAP_TBL_ADDR 0x830000
|
||||
+#define PPE_UCAST_HASH_MAP_TBL_ENTRIES 4096
|
||||
+#define PPE_UCAST_HASH_MAP_TBL_INC 0x10
|
||||
+#define PPE_UCAST_HASH_MAP_TBL_HASH GENMASK(7, 0)
|
||||
+
|
||||
+/* The queue offset configurations based on PPE internal priority. */
|
||||
+#define PPE_UCAST_PRIORITY_MAP_TBL_ADDR 0x842000
|
||||
+#define PPE_UCAST_PRIORITY_MAP_TBL_ENTRIES 256
|
||||
+#define PPE_UCAST_PRIORITY_MAP_TBL_INC 0x10
|
||||
+#define PPE_UCAST_PRIORITY_MAP_TBL_CLASS GENMASK(3, 0)
|
||||
+
|
||||
/* PPE unicast queue (0-255) configurations. */
|
||||
#define PPE_AC_UNICAST_QUEUE_CFG_TBL_ADDR 0x848000
|
||||
#define PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES 256
|
||||
@ -1,384 +0,0 @@
|
||||
From 4147ce0d95816bded5c5e6cb276b1aa9f2620045 Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:42 +0800
|
||||
Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE service code settings
|
||||
|
||||
PPE service code is a special code (0-255) that is defined by PPE for
|
||||
PPE's packet processing stages, as per the network functions required
|
||||
for the packet.
|
||||
|
||||
For packet being sent out by ARM cores on Ethernet ports, The service
|
||||
code 1 is used as the default service code. This service code is used
|
||||
to bypass most of packet processing stages of the PPE before the packet
|
||||
transmitted out PPE port, since the software network stack has already
|
||||
processed the packet.
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.c | 95 +++++++++++-
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.h | 145 ++++++++++++++++++
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 53 +++++++
|
||||
3 files changed, 292 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
+#include <linux/bitmap.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/regmap.h>
|
||||
@@ -1083,6 +1084,75 @@ int ppe_port_resource_get(struct ppe_dev
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * ppe_sc_config_set - Set PPE service code configuration
|
||||
+ * @ppe_dev: PPE device
|
||||
+ * @sc: Service ID, 0-255 supported by PPE
|
||||
+ * @cfg: Service code configuration
|
||||
+ *
|
||||
+ * PPE service code is used by the PPE during its packet processing stages,
|
||||
+ * to perform or bypass certain selected packet operations on the packet.
|
||||
+ *
|
||||
+ * Return: 0 on success, negative error code on failure.
|
||||
+ */
|
||||
+int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, struct ppe_sc_cfg cfg)
|
||||
+{
|
||||
+ u32 val, reg, servcode_val[2] = {};
|
||||
+ unsigned long bitmap_value;
|
||||
+ int ret;
|
||||
+
|
||||
+ val = FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_PORT_ID_VALID, cfg.dest_port_valid);
|
||||
+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_PORT_ID, cfg.dest_port);
|
||||
+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_DIRECTION, cfg.is_src);
|
||||
+
|
||||
+ bitmap_value = bitmap_read(cfg.bitmaps.egress, 0, PPE_SC_BYPASS_EGRESS_SIZE);
|
||||
+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_BYPASS_BITMAP, bitmap_value);
|
||||
+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_RX_CNT_EN,
|
||||
+ test_bit(PPE_SC_BYPASS_COUNTER_RX, cfg.bitmaps.counter));
|
||||
+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_TX_CNT_EN,
|
||||
+ test_bit(PPE_SC_BYPASS_COUNTER_TX, cfg.bitmaps.counter));
|
||||
+ reg = PPE_IN_L2_SERVICE_TBL_ADDR + PPE_IN_L2_SERVICE_TBL_INC * sc;
|
||||
+
|
||||
+ ret = regmap_write(ppe_dev->regmap, reg, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ bitmap_value = bitmap_read(cfg.bitmaps.ingress, 0, PPE_SC_BYPASS_INGRESS_SIZE);
|
||||
+ PPE_SERVICE_SET_BYPASS_BITMAP(servcode_val, bitmap_value);
|
||||
+ PPE_SERVICE_SET_RX_CNT_EN(servcode_val,
|
||||
+ test_bit(PPE_SC_BYPASS_COUNTER_RX_VLAN, cfg.bitmaps.counter));
|
||||
+ reg = PPE_SERVICE_TBL_ADDR + PPE_SERVICE_TBL_INC * sc;
|
||||
+
|
||||
+ ret = regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ servcode_val, ARRAY_SIZE(servcode_val));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ reg = PPE_EG_SERVICE_TBL_ADDR + PPE_EG_SERVICE_TBL_INC * sc;
|
||||
+ ret = regmap_bulk_read(ppe_dev->regmap, reg,
|
||||
+ servcode_val, ARRAY_SIZE(servcode_val));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ PPE_EG_SERVICE_SET_NEXT_SERVCODE(servcode_val, cfg.next_service_code);
|
||||
+ PPE_EG_SERVICE_SET_UPDATE_ACTION(servcode_val, cfg.eip_field_update_bitmap);
|
||||
+ PPE_EG_SERVICE_SET_HW_SERVICE(servcode_val, cfg.eip_hw_service);
|
||||
+ PPE_EG_SERVICE_SET_OFFSET_SEL(servcode_val, cfg.eip_offset_sel);
|
||||
+ PPE_EG_SERVICE_SET_TX_CNT_EN(servcode_val,
|
||||
+ test_bit(PPE_SC_BYPASS_COUNTER_TX_VLAN, cfg.bitmaps.counter));
|
||||
+
|
||||
+ ret = regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ servcode_val, ARRAY_SIZE(servcode_val));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ bitmap_value = bitmap_read(cfg.bitmaps.tunnel, 0, PPE_SC_BYPASS_TUNNEL_SIZE);
|
||||
+ val = FIELD_PREP(PPE_TL_SERVICE_TBL_BYPASS_BITMAP, bitmap_value);
|
||||
+ reg = PPE_TL_SERVICE_TBL_ADDR + PPE_TL_SERVICE_TBL_INC * sc;
|
||||
+
|
||||
+ return regmap_write(ppe_dev->regmap, reg, val);
|
||||
+}
|
||||
+
|
||||
static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
|
||||
const struct ppe_bm_port_config port_cfg)
|
||||
{
|
||||
@@ -1490,6 +1560,25 @@ static int ppe_queue_dest_init(struct pp
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* Initialize the service code 1 used by CPU port. */
|
||||
+static int ppe_servcode_init(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ struct ppe_sc_cfg sc_cfg = {};
|
||||
+
|
||||
+ bitmap_zero(sc_cfg.bitmaps.counter, PPE_SC_BYPASS_COUNTER_SIZE);
|
||||
+ bitmap_zero(sc_cfg.bitmaps.tunnel, PPE_SC_BYPASS_TUNNEL_SIZE);
|
||||
+
|
||||
+ bitmap_fill(sc_cfg.bitmaps.ingress, PPE_SC_BYPASS_INGRESS_SIZE);
|
||||
+ clear_bit(PPE_SC_BYPASS_INGRESS_FAKE_MAC_HEADER, sc_cfg.bitmaps.ingress);
|
||||
+ clear_bit(PPE_SC_BYPASS_INGRESS_SERVICE_CODE, sc_cfg.bitmaps.ingress);
|
||||
+ clear_bit(PPE_SC_BYPASS_INGRESS_FAKE_L2_PROTO, sc_cfg.bitmaps.ingress);
|
||||
+
|
||||
+ bitmap_fill(sc_cfg.bitmaps.egress, PPE_SC_BYPASS_EGRESS_SIZE);
|
||||
+ clear_bit(PPE_SC_BYPASS_EGRESS_ACL_POST_ROUTING_CHECK, sc_cfg.bitmaps.egress);
|
||||
+
|
||||
+ return ppe_sc_config_set(ppe_dev, PPE_EDMA_SC_BYPASS_ID, sc_cfg);
|
||||
+}
|
||||
+
|
||||
int ppe_hw_config(struct ppe_device *ppe_dev)
|
||||
{
|
||||
int ret;
|
||||
@@ -1506,5 +1595,9 @@ int ppe_hw_config(struct ppe_device *ppe
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- return ppe_queue_dest_init(ppe_dev);
|
||||
+ ret = ppe_queue_dest_init(ppe_dev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ppe_servcode_init(ppe_dev);
|
||||
}
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
@@ -6,6 +6,8 @@
|
||||
#ifndef __PPE_CONFIG_H__
|
||||
#define __PPE_CONFIG_H__
|
||||
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
#include "ppe.h"
|
||||
|
||||
/* There are different table index ranges for configuring queue base ID of
|
||||
@@ -18,6 +20,9 @@
|
||||
#define PPE_QUEUE_INTER_PRI_NUM 16
|
||||
#define PPE_QUEUE_HASH_NUM 256
|
||||
|
||||
+/* The service code is used by EDMA port to transmit packet to PPE. */
|
||||
+#define PPE_EDMA_SC_BYPASS_ID 1
|
||||
+
|
||||
/**
|
||||
* enum ppe_scheduler_frame_mode - PPE scheduler frame mode.
|
||||
* @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG,
|
||||
@@ -90,6 +95,144 @@ struct ppe_queue_ucast_dest {
|
||||
int dest_port;
|
||||
};
|
||||
|
||||
+/* Hardware bitmaps for bypassing features of the ingress packet. */
|
||||
+enum ppe_sc_ingress_type {
|
||||
+ PPE_SC_BYPASS_INGRESS_VLAN_TAG_FMT_CHECK = 0,
|
||||
+ PPE_SC_BYPASS_INGRESS_VLAN_MEMBER_CHECK = 1,
|
||||
+ PPE_SC_BYPASS_INGRESS_VLAN_TRANSLATE = 2,
|
||||
+ PPE_SC_BYPASS_INGRESS_MY_MAC_CHECK = 3,
|
||||
+ PPE_SC_BYPASS_INGRESS_DIP_LOOKUP = 4,
|
||||
+ PPE_SC_BYPASS_INGRESS_FLOW_LOOKUP = 5,
|
||||
+ PPE_SC_BYPASS_INGRESS_FLOW_ACTION = 6,
|
||||
+ PPE_SC_BYPASS_INGRESS_ACL = 7,
|
||||
+ PPE_SC_BYPASS_INGRESS_FAKE_MAC_HEADER = 8,
|
||||
+ PPE_SC_BYPASS_INGRESS_SERVICE_CODE = 9,
|
||||
+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L2 = 10,
|
||||
+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L3_IPV4 = 11,
|
||||
+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L3_IPV6 = 12,
|
||||
+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L4 = 13,
|
||||
+ PPE_SC_BYPASS_INGRESS_FLOW_SERVICE_CODE = 14,
|
||||
+ PPE_SC_BYPASS_INGRESS_ACL_SERVICE_CODE = 15,
|
||||
+ PPE_SC_BYPASS_INGRESS_FAKE_L2_PROTO = 16,
|
||||
+ PPE_SC_BYPASS_INGRESS_PPPOE_TERMINATION = 17,
|
||||
+ PPE_SC_BYPASS_INGRESS_DEFAULT_VLAN = 18,
|
||||
+ PPE_SC_BYPASS_INGRESS_DEFAULT_PCP = 19,
|
||||
+ PPE_SC_BYPASS_INGRESS_VSI_ASSIGN = 20,
|
||||
+ /* Values 21-23 are not specified by hardware. */
|
||||
+ PPE_SC_BYPASS_INGRESS_VLAN_ASSIGN_FAIL = 24,
|
||||
+ PPE_SC_BYPASS_INGRESS_SOURCE_GUARD = 25,
|
||||
+ PPE_SC_BYPASS_INGRESS_MRU_MTU_CHECK = 26,
|
||||
+ PPE_SC_BYPASS_INGRESS_FLOW_SRC_CHECK = 27,
|
||||
+ PPE_SC_BYPASS_INGRESS_FLOW_QOS = 28,
|
||||
+ /* This must be last as it determines the size of the BITMAP. */
|
||||
+ PPE_SC_BYPASS_INGRESS_SIZE,
|
||||
+};
|
||||
+
|
||||
+/* Hardware bitmaps for bypassing features of the egress packet. */
|
||||
+enum ppe_sc_egress_type {
|
||||
+ PPE_SC_BYPASS_EGRESS_VLAN_MEMBER_CHECK = 0,
|
||||
+ PPE_SC_BYPASS_EGRESS_VLAN_TRANSLATE = 1,
|
||||
+ PPE_SC_BYPASS_EGRESS_VLAN_TAG_FMT_CTRL = 2,
|
||||
+ PPE_SC_BYPASS_EGRESS_FDB_LEARN = 3,
|
||||
+ PPE_SC_BYPASS_EGRESS_FDB_REFRESH = 4,
|
||||
+ PPE_SC_BYPASS_EGRESS_L2_SOURCE_SECURITY = 5,
|
||||
+ PPE_SC_BYPASS_EGRESS_MANAGEMENT_FWD = 6,
|
||||
+ PPE_SC_BYPASS_EGRESS_BRIDGING_FWD = 7,
|
||||
+ PPE_SC_BYPASS_EGRESS_IN_STP_FLTR = 8,
|
||||
+ PPE_SC_BYPASS_EGRESS_EG_STP_FLTR = 9,
|
||||
+ PPE_SC_BYPASS_EGRESS_SOURCE_FLTR = 10,
|
||||
+ PPE_SC_BYPASS_EGRESS_POLICER = 11,
|
||||
+ PPE_SC_BYPASS_EGRESS_L2_PKT_EDIT = 12,
|
||||
+ PPE_SC_BYPASS_EGRESS_L3_PKT_EDIT = 13,
|
||||
+ PPE_SC_BYPASS_EGRESS_ACL_POST_ROUTING_CHECK = 14,
|
||||
+ PPE_SC_BYPASS_EGRESS_PORT_ISOLATION = 15,
|
||||
+ PPE_SC_BYPASS_EGRESS_PRE_ACL_QOS = 16,
|
||||
+ PPE_SC_BYPASS_EGRESS_POST_ACL_QOS = 17,
|
||||
+ PPE_SC_BYPASS_EGRESS_DSCP_QOS = 18,
|
||||
+ PPE_SC_BYPASS_EGRESS_PCP_QOS = 19,
|
||||
+ PPE_SC_BYPASS_EGRESS_PREHEADER_QOS = 20,
|
||||
+ PPE_SC_BYPASS_EGRESS_FAKE_MAC_DROP = 21,
|
||||
+ PPE_SC_BYPASS_EGRESS_TUNL_CONTEXT = 22,
|
||||
+ PPE_SC_BYPASS_EGRESS_FLOW_POLICER = 23,
|
||||
+ /* This must be last as it determines the size of the BITMAP. */
|
||||
+ PPE_SC_BYPASS_EGRESS_SIZE,
|
||||
+};
|
||||
+
|
||||
+/* Hardware bitmaps for bypassing counter of packet. */
|
||||
+enum ppe_sc_counter_type {
|
||||
+ PPE_SC_BYPASS_COUNTER_RX_VLAN = 0,
|
||||
+ PPE_SC_BYPASS_COUNTER_RX = 1,
|
||||
+ PPE_SC_BYPASS_COUNTER_TX_VLAN = 2,
|
||||
+ PPE_SC_BYPASS_COUNTER_TX = 3,
|
||||
+ /* This must be last as it determines the size of the BITMAP. */
|
||||
+ PPE_SC_BYPASS_COUNTER_SIZE,
|
||||
+};
|
||||
+
|
||||
+/* Hardware bitmaps for bypassing features of tunnel packet. */
|
||||
+enum ppe_sc_tunnel_type {
|
||||
+ PPE_SC_BYPASS_TUNNEL_SERVICE_CODE = 0,
|
||||
+ PPE_SC_BYPASS_TUNNEL_TUNNEL_HANDLE = 1,
|
||||
+ PPE_SC_BYPASS_TUNNEL_L3_IF_CHECK = 2,
|
||||
+ PPE_SC_BYPASS_TUNNEL_VLAN_CHECK = 3,
|
||||
+ PPE_SC_BYPASS_TUNNEL_DMAC_CHECK = 4,
|
||||
+ PPE_SC_BYPASS_TUNNEL_UDP_CSUM_0_CHECK = 5,
|
||||
+ PPE_SC_BYPASS_TUNNEL_TBL_DE_ACCE_CHECK = 6,
|
||||
+ PPE_SC_BYPASS_TUNNEL_PPPOE_MC_TERM_CHECK = 7,
|
||||
+ PPE_SC_BYPASS_TUNNEL_TTL_EXCEED_CHECK = 8,
|
||||
+ PPE_SC_BYPASS_TUNNEL_MAP_SRC_CHECK = 9,
|
||||
+ PPE_SC_BYPASS_TUNNEL_MAP_DST_CHECK = 10,
|
||||
+ PPE_SC_BYPASS_TUNNEL_LPM_DST_LOOKUP = 11,
|
||||
+ PPE_SC_BYPASS_TUNNEL_LPM_LOOKUP = 12,
|
||||
+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L2 = 13,
|
||||
+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L3_IPV4 = 14,
|
||||
+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L3_IPV6 = 15,
|
||||
+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L4 = 16,
|
||||
+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_TUNNEL = 17,
|
||||
+ /* Values 18-19 are not specified by hardware. */
|
||||
+ PPE_SC_BYPASS_TUNNEL_PRE_IPO = 20,
|
||||
+ /* This must be last as it determines the size of the BITMAP. */
|
||||
+ PPE_SC_BYPASS_TUNNEL_SIZE,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct ppe_sc_bypass - PPE service bypass bitmaps
|
||||
+ * @ingress: Bitmap of features that can be bypassed on the ingress packet.
|
||||
+ * @egress: Bitmap of features that can be bypassed on the egress packet.
|
||||
+ * @counter: Bitmap of features that can be bypassed on the counter type.
|
||||
+ * @tunnel: Bitmap of features that can be bypassed on the tunnel packet.
|
||||
+ */
|
||||
+struct ppe_sc_bypass {
|
||||
+ DECLARE_BITMAP(ingress, PPE_SC_BYPASS_INGRESS_SIZE);
|
||||
+ DECLARE_BITMAP(egress, PPE_SC_BYPASS_EGRESS_SIZE);
|
||||
+ DECLARE_BITMAP(counter, PPE_SC_BYPASS_COUNTER_SIZE);
|
||||
+ DECLARE_BITMAP(tunnel, PPE_SC_BYPASS_TUNNEL_SIZE);
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct ppe_sc_cfg - PPE service code configuration.
|
||||
+ * @dest_port_valid: Generate destination port or not.
|
||||
+ * @dest_port: Destination port ID.
|
||||
+ * @bitmaps: Bitmap of bypass features.
|
||||
+ * @is_src: Destination port acts as source port, packet sent to CPU.
|
||||
+ * @next_service_code: New service code generated.
|
||||
+ * @eip_field_update_bitmap: Fields updated as actions taken for EIP.
|
||||
+ * @eip_hw_service: Selected hardware functions for EIP.
|
||||
+ * @eip_offset_sel: Packet offset selection, using packet's layer 4 offset
|
||||
+ * or using packet's layer 3 offset for EIP.
|
||||
+ *
|
||||
+ * Service code is generated during the packet passing through PPE.
|
||||
+ */
|
||||
+struct ppe_sc_cfg {
|
||||
+ bool dest_port_valid;
|
||||
+ int dest_port;
|
||||
+ struct ppe_sc_bypass bitmaps;
|
||||
+ bool is_src;
|
||||
+ int next_service_code;
|
||||
+ int eip_field_update_bitmap;
|
||||
+ int eip_hw_service;
|
||||
+ int eip_offset_sel;
|
||||
+};
|
||||
+
|
||||
int ppe_hw_config(struct ppe_device *ppe_dev);
|
||||
int ppe_queue_scheduler_set(struct ppe_device *ppe_dev,
|
||||
int node_id, bool flow_level, int port,
|
||||
@@ -109,4 +252,6 @@ int ppe_queue_ucast_offset_hash_set(stru
|
||||
int ppe_port_resource_get(struct ppe_device *ppe_dev, int port,
|
||||
enum ppe_resource_type type,
|
||||
int *res_start, int *res_end);
|
||||
+int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc,
|
||||
+ struct ppe_sc_cfg cfg);
|
||||
#endif
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
@@ -25,10 +25,63 @@
|
||||
#define PPE_BM_SCH_CFG_TBL_SECOND_PORT_VALID BIT(6)
|
||||
#define PPE_BM_SCH_CFG_TBL_SECOND_PORT GENMASK(11, 8)
|
||||
|
||||
+/* PPE service code configuration for the ingress direction functions,
|
||||
+ * including bypass configuration for relevant PPE switch core functions
|
||||
+ * such as flow entry lookup bypass.
|
||||
+ */
|
||||
+#define PPE_SERVICE_TBL_ADDR 0x15000
|
||||
+#define PPE_SERVICE_TBL_ENTRIES 256
|
||||
+#define PPE_SERVICE_TBL_INC 0x10
|
||||
+#define PPE_SERVICE_W0_BYPASS_BITMAP GENMASK(31, 0)
|
||||
+#define PPE_SERVICE_W1_RX_CNT_EN BIT(0)
|
||||
+
|
||||
+#define PPE_SERVICE_SET_BYPASS_BITMAP(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_SERVICE_W0_BYPASS_BITMAP)
|
||||
+#define PPE_SERVICE_SET_RX_CNT_EN(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_SERVICE_W1_RX_CNT_EN)
|
||||
+
|
||||
/* PPE queue counters enable/disable control. */
|
||||
#define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044
|
||||
#define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2)
|
||||
|
||||
+/* PPE service code configuration on the egress direction. */
|
||||
+#define PPE_EG_SERVICE_TBL_ADDR 0x43000
|
||||
+#define PPE_EG_SERVICE_TBL_ENTRIES 256
|
||||
+#define PPE_EG_SERVICE_TBL_INC 0x10
|
||||
+#define PPE_EG_SERVICE_W0_UPDATE_ACTION GENMASK(31, 0)
|
||||
+#define PPE_EG_SERVICE_W1_NEXT_SERVCODE GENMASK(7, 0)
|
||||
+#define PPE_EG_SERVICE_W1_HW_SERVICE GENMASK(13, 8)
|
||||
+#define PPE_EG_SERVICE_W1_OFFSET_SEL BIT(14)
|
||||
+#define PPE_EG_SERVICE_W1_TX_CNT_EN BIT(15)
|
||||
+
|
||||
+#define PPE_EG_SERVICE_SET_UPDATE_ACTION(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_EG_SERVICE_W0_UPDATE_ACTION)
|
||||
+#define PPE_EG_SERVICE_SET_NEXT_SERVCODE(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_NEXT_SERVCODE)
|
||||
+#define PPE_EG_SERVICE_SET_HW_SERVICE(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_HW_SERVICE)
|
||||
+#define PPE_EG_SERVICE_SET_OFFSET_SEL(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_OFFSET_SEL)
|
||||
+#define PPE_EG_SERVICE_SET_TX_CNT_EN(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_TX_CNT_EN)
|
||||
+
|
||||
+/* PPE service code configuration for destination port and counter. */
|
||||
+#define PPE_IN_L2_SERVICE_TBL_ADDR 0x66000
|
||||
+#define PPE_IN_L2_SERVICE_TBL_ENTRIES 256
|
||||
+#define PPE_IN_L2_SERVICE_TBL_INC 0x10
|
||||
+#define PPE_IN_L2_SERVICE_TBL_DST_PORT_ID_VALID BIT(0)
|
||||
+#define PPE_IN_L2_SERVICE_TBL_DST_PORT_ID GENMASK(4, 1)
|
||||
+#define PPE_IN_L2_SERVICE_TBL_DST_DIRECTION BIT(5)
|
||||
+#define PPE_IN_L2_SERVICE_TBL_DST_BYPASS_BITMAP GENMASK(29, 6)
|
||||
+#define PPE_IN_L2_SERVICE_TBL_RX_CNT_EN BIT(30)
|
||||
+#define PPE_IN_L2_SERVICE_TBL_TX_CNT_EN BIT(31)
|
||||
+
|
||||
+/* PPE service code configuration for the tunnel packet. */
|
||||
+#define PPE_TL_SERVICE_TBL_ADDR 0x306000
|
||||
+#define PPE_TL_SERVICE_TBL_ENTRIES 256
|
||||
+#define PPE_TL_SERVICE_TBL_INC 4
|
||||
+#define PPE_TL_SERVICE_TBL_BYPASS_BITMAP GENMASK(31, 0)
|
||||
+
|
||||
/* Port scheduler global config. */
|
||||
#define PPE_PSCH_SCH_DEPTH_CFG_ADDR 0x400000
|
||||
#define PPE_PSCH_SCH_DEPTH_CFG_INC 4
|
||||
@ -1,215 +0,0 @@
|
||||
From 63af46200da794acda25cf8083bde0c1576b0859 Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:43 +0800
|
||||
Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE port control settings
|
||||
|
||||
1. Enable port specific counters in PPE.
|
||||
2. Configure the default action as drop when the packet size
|
||||
is more than the configured MTU of physical port.
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.c | 86 ++++++++++++++++++-
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.h | 15 ++++
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 47 ++++++++++
|
||||
3 files changed, 147 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
@@ -1153,6 +1153,44 @@ int ppe_sc_config_set(struct ppe_device
|
||||
return regmap_write(ppe_dev->regmap, reg, val);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * ppe_counter_enable_set - Set PPE port counter enabled
|
||||
+ * @ppe_dev: PPE device
|
||||
+ * @port: PPE port ID
|
||||
+ *
|
||||
+ * Enable PPE counters on the given port for the unicast packet, multicast
|
||||
+ * packet and VLAN packet received and transmitted by PPE.
|
||||
+ *
|
||||
+ * Return: 0 on success, negative error code on failure.
|
||||
+ */
|
||||
+int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port)
|
||||
+{
|
||||
+ u32 reg, mru_mtu_val[3];
|
||||
+ int ret;
|
||||
+
|
||||
+ reg = PPE_MRU_MTU_CTRL_TBL_ADDR + PPE_MRU_MTU_CTRL_TBL_INC * port;
|
||||
+ ret = regmap_bulk_read(ppe_dev->regmap, reg,
|
||||
+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ PPE_MRU_MTU_CTRL_SET_RX_CNT_EN(mru_mtu_val, true);
|
||||
+ PPE_MRU_MTU_CTRL_SET_TX_CNT_EN(mru_mtu_val, true);
|
||||
+ ret = regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ reg = PPE_MC_MTU_CTRL_TBL_ADDR + PPE_MC_MTU_CTRL_TBL_INC * port;
|
||||
+ ret = regmap_set_bits(ppe_dev->regmap, reg, PPE_MC_MTU_CTRL_TBL_TX_CNT_EN);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ reg = PPE_PORT_EG_VLAN_TBL_ADDR + PPE_PORT_EG_VLAN_TBL_INC * port;
|
||||
+
|
||||
+ return regmap_set_bits(ppe_dev->regmap, reg, PPE_PORT_EG_VLAN_TBL_TX_COUNTING_EN);
|
||||
+}
|
||||
+
|
||||
static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
|
||||
const struct ppe_bm_port_config port_cfg)
|
||||
{
|
||||
@@ -1579,6 +1617,48 @@ static int ppe_servcode_init(struct ppe_
|
||||
return ppe_sc_config_set(ppe_dev, PPE_EDMA_SC_BYPASS_ID, sc_cfg);
|
||||
}
|
||||
|
||||
+/* Initialize PPE port configurations. */
|
||||
+static int ppe_port_config_init(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ u32 reg, val, mru_mtu_val[3];
|
||||
+ int i, ret;
|
||||
+
|
||||
+ /* MTU and MRU settings are not required for CPU port 0. */
|
||||
+ for (i = 1; i < ppe_dev->num_ports; i++) {
|
||||
+ /* Enable Ethernet port counter */
|
||||
+ ret = ppe_counter_enable_set(ppe_dev, i);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ reg = PPE_MRU_MTU_CTRL_TBL_ADDR + PPE_MRU_MTU_CTRL_TBL_INC * i;
|
||||
+ ret = regmap_bulk_read(ppe_dev->regmap, reg,
|
||||
+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Drop the packet when the packet size is more than
|
||||
+ * the MTU or MRU of the physical interface.
|
||||
+ */
|
||||
+ PPE_MRU_MTU_CTRL_SET_MRU_CMD(mru_mtu_val, PPE_ACTION_DROP);
|
||||
+ PPE_MRU_MTU_CTRL_SET_MTU_CMD(mru_mtu_val, PPE_ACTION_DROP);
|
||||
+ ret = regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ reg = PPE_MC_MTU_CTRL_TBL_ADDR + PPE_MC_MTU_CTRL_TBL_INC * i;
|
||||
+ val = FIELD_PREP(PPE_MC_MTU_CTRL_TBL_MTU_CMD, PPE_ACTION_DROP);
|
||||
+ ret = regmap_update_bits(ppe_dev->regmap, reg,
|
||||
+ PPE_MC_MTU_CTRL_TBL_MTU_CMD,
|
||||
+ val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Enable CPU port counters. */
|
||||
+ return ppe_counter_enable_set(ppe_dev, 0);
|
||||
+}
|
||||
+
|
||||
int ppe_hw_config(struct ppe_device *ppe_dev)
|
||||
{
|
||||
int ret;
|
||||
@@ -1599,5 +1679,9 @@ int ppe_hw_config(struct ppe_device *ppe
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- return ppe_servcode_init(ppe_dev);
|
||||
+ ret = ppe_servcode_init(ppe_dev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ppe_port_config_init(ppe_dev);
|
||||
}
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
@@ -233,6 +233,20 @@ struct ppe_sc_cfg {
|
||||
int eip_offset_sel;
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * enum ppe_action_type - PPE action of the received packet.
|
||||
+ * @PPE_ACTION_FORWARD: Packet forwarded per L2/L3 process.
|
||||
+ * @PPE_ACTION_DROP: Packet dropped by PPE.
|
||||
+ * @PPE_ACTION_COPY_TO_CPU: Packet copied to CPU port per multicast queue.
|
||||
+ * @PPE_ACTION_REDIRECT_TO_CPU: Packet redirected to CPU port per unicast queue.
|
||||
+ */
|
||||
+enum ppe_action_type {
|
||||
+ PPE_ACTION_FORWARD = 0,
|
||||
+ PPE_ACTION_DROP = 1,
|
||||
+ PPE_ACTION_COPY_TO_CPU = 2,
|
||||
+ PPE_ACTION_REDIRECT_TO_CPU = 3,
|
||||
+};
|
||||
+
|
||||
int ppe_hw_config(struct ppe_device *ppe_dev);
|
||||
int ppe_queue_scheduler_set(struct ppe_device *ppe_dev,
|
||||
int node_id, bool flow_level, int port,
|
||||
@@ -254,4 +268,5 @@ int ppe_port_resource_get(struct ppe_dev
|
||||
int *res_start, int *res_end);
|
||||
int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc,
|
||||
struct ppe_sc_cfg cfg);
|
||||
+int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port);
|
||||
#endif
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
@@ -40,6 +40,18 @@
|
||||
#define PPE_SERVICE_SET_RX_CNT_EN(tbl_cfg, value) \
|
||||
u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_SERVICE_W1_RX_CNT_EN)
|
||||
|
||||
+/* PPE port egress VLAN configurations. */
|
||||
+#define PPE_PORT_EG_VLAN_TBL_ADDR 0x20020
|
||||
+#define PPE_PORT_EG_VLAN_TBL_ENTRIES 8
|
||||
+#define PPE_PORT_EG_VLAN_TBL_INC 4
|
||||
+#define PPE_PORT_EG_VLAN_TBL_VLAN_TYPE BIT(0)
|
||||
+#define PPE_PORT_EG_VLAN_TBL_CTAG_MODE GENMASK(2, 1)
|
||||
+#define PPE_PORT_EG_VLAN_TBL_STAG_MODE GENMASK(4, 3)
|
||||
+#define PPE_PORT_EG_VLAN_TBL_VSI_TAG_MODE_EN BIT(5)
|
||||
+#define PPE_PORT_EG_VLAN_TBL_PCP_PROP_CMD BIT(6)
|
||||
+#define PPE_PORT_EG_VLAN_TBL_DEI_PROP_CMD BIT(7)
|
||||
+#define PPE_PORT_EG_VLAN_TBL_TX_COUNTING_EN BIT(8)
|
||||
+
|
||||
/* PPE queue counters enable/disable control. */
|
||||
#define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044
|
||||
#define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2)
|
||||
@@ -65,6 +77,41 @@
|
||||
#define PPE_EG_SERVICE_SET_TX_CNT_EN(tbl_cfg, value) \
|
||||
u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_TX_CNT_EN)
|
||||
|
||||
+/* PPE port control configurations for the traffic to the multicast queues. */
|
||||
+#define PPE_MC_MTU_CTRL_TBL_ADDR 0x60a00
|
||||
+#define PPE_MC_MTU_CTRL_TBL_ENTRIES 8
|
||||
+#define PPE_MC_MTU_CTRL_TBL_INC 4
|
||||
+#define PPE_MC_MTU_CTRL_TBL_MTU GENMASK(13, 0)
|
||||
+#define PPE_MC_MTU_CTRL_TBL_MTU_CMD GENMASK(15, 14)
|
||||
+#define PPE_MC_MTU_CTRL_TBL_TX_CNT_EN BIT(16)
|
||||
+
|
||||
+/* PPE port control configurations for the traffic to the unicast queues. */
|
||||
+#define PPE_MRU_MTU_CTRL_TBL_ADDR 0x65000
|
||||
+#define PPE_MRU_MTU_CTRL_TBL_ENTRIES 256
|
||||
+#define PPE_MRU_MTU_CTRL_TBL_INC 0x10
|
||||
+#define PPE_MRU_MTU_CTRL_W0_MRU GENMASK(13, 0)
|
||||
+#define PPE_MRU_MTU_CTRL_W0_MRU_CMD GENMASK(15, 14)
|
||||
+#define PPE_MRU_MTU_CTRL_W0_MTU GENMASK(29, 16)
|
||||
+#define PPE_MRU_MTU_CTRL_W0_MTU_CMD GENMASK(31, 30)
|
||||
+#define PPE_MRU_MTU_CTRL_W1_RX_CNT_EN BIT(0)
|
||||
+#define PPE_MRU_MTU_CTRL_W1_TX_CNT_EN BIT(1)
|
||||
+#define PPE_MRU_MTU_CTRL_W1_SRC_PROFILE GENMASK(3, 2)
|
||||
+#define PPE_MRU_MTU_CTRL_W1_INNER_PREC_LOW BIT(31)
|
||||
+#define PPE_MRU_MTU_CTRL_W2_INNER_PREC_HIGH GENMASK(1, 0)
|
||||
+
|
||||
+#define PPE_MRU_MTU_CTRL_SET_MRU(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MRU)
|
||||
+#define PPE_MRU_MTU_CTRL_SET_MRU_CMD(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MRU_CMD)
|
||||
+#define PPE_MRU_MTU_CTRL_SET_MTU(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MTU)
|
||||
+#define PPE_MRU_MTU_CTRL_SET_MTU_CMD(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MTU_CMD)
|
||||
+#define PPE_MRU_MTU_CTRL_SET_RX_CNT_EN(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_MRU_MTU_CTRL_W1_RX_CNT_EN)
|
||||
+#define PPE_MRU_MTU_CTRL_SET_TX_CNT_EN(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_MRU_MTU_CTRL_W1_TX_CNT_EN)
|
||||
+
|
||||
/* PPE service code configuration for destination port and counter. */
|
||||
#define PPE_IN_L2_SERVICE_TBL_ADDR 0x66000
|
||||
#define PPE_IN_L2_SERVICE_TBL_ENTRIES 256
|
||||
@ -1,344 +0,0 @@
|
||||
From 796be78fffeebe77237a6464da7ebe9807d670f0 Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:44 +0800
|
||||
Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE RSS hash settings
|
||||
|
||||
PPE RSS hash is generated during PPE receive, based on the packet
|
||||
content (3 tuples or 5 tuples) and as per the configured RSS seed.
|
||||
The hash is then used to select the queue to transmit the packet
|
||||
to the ARM CPU.
|
||||
|
||||
This patch initializes the RSS hash settings that are used to
|
||||
generate the hash for the packet during PPE packet receive.
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.c | 194 +++++++++++++++++-
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.h | 39 ++++
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 40 ++++
|
||||
3 files changed, 272 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
@@ -1191,6 +1191,143 @@ int ppe_counter_enable_set(struct ppe_de
|
||||
return regmap_set_bits(ppe_dev->regmap, reg, PPE_PORT_EG_VLAN_TBL_TX_COUNTING_EN);
|
||||
}
|
||||
|
||||
+static int ppe_rss_hash_ipv4_config(struct ppe_device *ppe_dev, int index,
|
||||
+ struct ppe_rss_hash_cfg cfg)
|
||||
+{
|
||||
+ u32 reg, val;
|
||||
+
|
||||
+ switch (index) {
|
||||
+ case 0:
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_sip_mix[0]);
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_dip_mix[0]);
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_protocol_mix);
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_dport_mix);
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_sport_mix);
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ reg = PPE_RSS_HASH_MIX_IPV4_ADDR + index * PPE_RSS_HASH_MIX_IPV4_INC;
|
||||
+
|
||||
+ return regmap_write(ppe_dev->regmap, reg, val);
|
||||
+}
|
||||
+
|
||||
+static int ppe_rss_hash_ipv6_config(struct ppe_device *ppe_dev, int index,
|
||||
+ struct ppe_rss_hash_cfg cfg)
|
||||
+{
|
||||
+ u32 reg, val;
|
||||
+
|
||||
+ switch (index) {
|
||||
+ case 0 ... 3:
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_sip_mix[index]);
|
||||
+ break;
|
||||
+ case 4 ... 7:
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_dip_mix[index - 4]);
|
||||
+ break;
|
||||
+ case 8:
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_protocol_mix);
|
||||
+ break;
|
||||
+ case 9:
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_dport_mix);
|
||||
+ break;
|
||||
+ case 10:
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_sport_mix);
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ reg = PPE_RSS_HASH_MIX_ADDR + index * PPE_RSS_HASH_MIX_INC;
|
||||
+
|
||||
+ return regmap_write(ppe_dev->regmap, reg, val);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * ppe_rss_hash_config_set - Configure the PPE hash settings for the packet received.
|
||||
+ * @ppe_dev: PPE device.
|
||||
+ * @mode: Configure RSS hash for the packet type IPv4 and IPv6.
|
||||
+ * @cfg: RSS hash configuration.
|
||||
+ *
|
||||
+ * PPE RSS hash settings are configured for the packet type IPv4 and IPv6.
|
||||
+ *
|
||||
+ * Return: 0 on success, negative error code on failure.
|
||||
+ */
|
||||
+int ppe_rss_hash_config_set(struct ppe_device *ppe_dev, int mode,
|
||||
+ struct ppe_rss_hash_cfg cfg)
|
||||
+{
|
||||
+ u32 val, reg;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ if (mode & PPE_RSS_HASH_MODE_IPV4) {
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MASK_IPV4_HASH_MASK, cfg.hash_mask);
|
||||
+ val |= FIELD_PREP(PPE_RSS_HASH_MASK_IPV4_FRAGMENT, cfg.hash_fragment_mode);
|
||||
+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_MASK_IPV4_ADDR, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_SEED_IPV4_VAL, cfg.hash_seed);
|
||||
+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_SEED_IPV4_ADDR, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ for (i = 0; i < PPE_RSS_HASH_MIX_IPV4_ENTRIES; i++) {
|
||||
+ ret = ppe_rss_hash_ipv4_config(ppe_dev, i, cfg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_RSS_HASH_FIN_IPV4_ENTRIES; i++) {
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_FIN_IPV4_INNER, cfg.hash_fin_inner[i]);
|
||||
+ val |= FIELD_PREP(PPE_RSS_HASH_FIN_IPV4_OUTER, cfg.hash_fin_outer[i]);
|
||||
+ reg = PPE_RSS_HASH_FIN_IPV4_ADDR + i * PPE_RSS_HASH_FIN_IPV4_INC;
|
||||
+
|
||||
+ ret = regmap_write(ppe_dev->regmap, reg, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (mode & PPE_RSS_HASH_MODE_IPV6) {
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_MASK_HASH_MASK, cfg.hash_mask);
|
||||
+ val |= FIELD_PREP(PPE_RSS_HASH_MASK_FRAGMENT, cfg.hash_fragment_mode);
|
||||
+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_MASK_ADDR, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_SEED_VAL, cfg.hash_seed);
|
||||
+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_SEED_ADDR, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ for (i = 0; i < PPE_RSS_HASH_MIX_ENTRIES; i++) {
|
||||
+ ret = ppe_rss_hash_ipv6_config(ppe_dev, i, cfg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_RSS_HASH_FIN_ENTRIES; i++) {
|
||||
+ val = FIELD_PREP(PPE_RSS_HASH_FIN_INNER, cfg.hash_fin_inner[i]);
|
||||
+ val |= FIELD_PREP(PPE_RSS_HASH_FIN_OUTER, cfg.hash_fin_outer[i]);
|
||||
+ reg = PPE_RSS_HASH_FIN_ADDR + i * PPE_RSS_HASH_FIN_INC;
|
||||
+
|
||||
+ ret = regmap_write(ppe_dev->regmap, reg, val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
|
||||
const struct ppe_bm_port_config port_cfg)
|
||||
{
|
||||
@@ -1659,6 +1796,57 @@ static int ppe_port_config_init(struct p
|
||||
return ppe_counter_enable_set(ppe_dev, 0);
|
||||
}
|
||||
|
||||
+/* Initialize the PPE RSS configuration for IPv4 and IPv6 packet receive.
|
||||
+ * RSS settings are to calculate the random RSS hash value generated during
|
||||
+ * packet receive. This hash is then used to generate the queue offset used
|
||||
+ * to determine the queue used to transmit the packet.
|
||||
+ */
|
||||
+static int ppe_rss_hash_init(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ u16 fins[PPE_RSS_HASH_TUPLES] = { 0x205, 0x264, 0x227, 0x245, 0x201 };
|
||||
+ u8 ips[PPE_RSS_HASH_IP_LENGTH] = { 0x13, 0xb, 0x13, 0xb };
|
||||
+ struct ppe_rss_hash_cfg hash_cfg;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ hash_cfg.hash_seed = get_random_u32();
|
||||
+ hash_cfg.hash_mask = 0xfff;
|
||||
+
|
||||
+ /* Use 5 tuple as RSS hash key for the first fragment of TCP, UDP
|
||||
+ * and UDP-Lite packets.
|
||||
+ */
|
||||
+ hash_cfg.hash_fragment_mode = false;
|
||||
+
|
||||
+ /* The final common seed configs used to calculate the RSS has value,
|
||||
+ * which is available for both IPv4 and IPv6 packet.
|
||||
+ */
|
||||
+ for (i = 0; i < ARRAY_SIZE(fins); i++) {
|
||||
+ hash_cfg.hash_fin_inner[i] = fins[i] & 0x1f;
|
||||
+ hash_cfg.hash_fin_outer[i] = fins[i] >> 5;
|
||||
+ }
|
||||
+
|
||||
+ /* RSS seeds for IP protocol, L4 destination & source port and
|
||||
+ * destination & source IP used to calculate the RSS hash value.
|
||||
+ */
|
||||
+ hash_cfg.hash_protocol_mix = 0x13;
|
||||
+ hash_cfg.hash_dport_mix = 0xb;
|
||||
+ hash_cfg.hash_sport_mix = 0x13;
|
||||
+ hash_cfg.hash_dip_mix[0] = 0xb;
|
||||
+ hash_cfg.hash_sip_mix[0] = 0x13;
|
||||
+
|
||||
+ /* Configure RSS seed configs for IPv4 packet. */
|
||||
+ ret = ppe_rss_hash_config_set(ppe_dev, PPE_RSS_HASH_MODE_IPV4, hash_cfg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(ips); i++) {
|
||||
+ hash_cfg.hash_sip_mix[i] = ips[i];
|
||||
+ hash_cfg.hash_dip_mix[i] = ips[i];
|
||||
+ }
|
||||
+
|
||||
+ /* Configure RSS seed configs for IPv6 packet. */
|
||||
+ return ppe_rss_hash_config_set(ppe_dev, PPE_RSS_HASH_MODE_IPV6, hash_cfg);
|
||||
+}
|
||||
+
|
||||
int ppe_hw_config(struct ppe_device *ppe_dev)
|
||||
{
|
||||
int ret;
|
||||
@@ -1683,5 +1871,9 @@ int ppe_hw_config(struct ppe_device *ppe
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- return ppe_port_config_init(ppe_dev);
|
||||
+ ret = ppe_port_config_init(ppe_dev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ppe_rss_hash_init(ppe_dev);
|
||||
}
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
@@ -23,6 +23,12 @@
|
||||
/* The service code is used by EDMA port to transmit packet to PPE. */
|
||||
#define PPE_EDMA_SC_BYPASS_ID 1
|
||||
|
||||
+/* The PPE RSS hash configured for IPv4 and IPv6 packet separately. */
|
||||
+#define PPE_RSS_HASH_MODE_IPV4 BIT(0)
|
||||
+#define PPE_RSS_HASH_MODE_IPV6 BIT(1)
|
||||
+#define PPE_RSS_HASH_IP_LENGTH 4
|
||||
+#define PPE_RSS_HASH_TUPLES 5
|
||||
+
|
||||
/**
|
||||
* enum ppe_scheduler_frame_mode - PPE scheduler frame mode.
|
||||
* @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG,
|
||||
@@ -247,6 +253,37 @@ enum ppe_action_type {
|
||||
PPE_ACTION_REDIRECT_TO_CPU = 3,
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * struct ppe_rss_hash_cfg - PPE RSS hash configuration.
|
||||
+ * @hash_mask: Mask of the generated hash value.
|
||||
+ * @hash_fragment_mode: Hash generation mode for the first fragment of TCP,
|
||||
+ * UDP and UDP-Lite packets, to use either 3 tuple or 5 tuple for RSS hash
|
||||
+ * key computation.
|
||||
+ * @hash_seed: Seed to generate RSS hash.
|
||||
+ * @hash_sip_mix: Source IP selection.
|
||||
+ * @hash_dip_mix: Destination IP selection.
|
||||
+ * @hash_protocol_mix: Protocol selection.
|
||||
+ * @hash_sport_mix: Source L4 port selection.
|
||||
+ * @hash_dport_mix: Destination L4 port selection.
|
||||
+ * @hash_fin_inner: RSS hash value first selection.
|
||||
+ * @hash_fin_outer: RSS hash value second selection.
|
||||
+ *
|
||||
+ * PPE RSS hash value is generated for the packet based on the RSS hash
|
||||
+ * configured.
|
||||
+ */
|
||||
+struct ppe_rss_hash_cfg {
|
||||
+ u32 hash_mask;
|
||||
+ bool hash_fragment_mode;
|
||||
+ u32 hash_seed;
|
||||
+ u8 hash_sip_mix[PPE_RSS_HASH_IP_LENGTH];
|
||||
+ u8 hash_dip_mix[PPE_RSS_HASH_IP_LENGTH];
|
||||
+ u8 hash_protocol_mix;
|
||||
+ u8 hash_sport_mix;
|
||||
+ u8 hash_dport_mix;
|
||||
+ u8 hash_fin_inner[PPE_RSS_HASH_TUPLES];
|
||||
+ u8 hash_fin_outer[PPE_RSS_HASH_TUPLES];
|
||||
+};
|
||||
+
|
||||
int ppe_hw_config(struct ppe_device *ppe_dev);
|
||||
int ppe_queue_scheduler_set(struct ppe_device *ppe_dev,
|
||||
int node_id, bool flow_level, int port,
|
||||
@@ -269,4 +306,6 @@ int ppe_port_resource_get(struct ppe_dev
|
||||
int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc,
|
||||
struct ppe_sc_cfg cfg);
|
||||
int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port);
|
||||
+int ppe_rss_hash_config_set(struct ppe_device *ppe_dev, int mode,
|
||||
+ struct ppe_rss_hash_cfg hash_cfg);
|
||||
#endif
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
@@ -16,6 +16,46 @@
|
||||
#define PPE_BM_SCH_CTRL_SCH_OFFSET GENMASK(14, 8)
|
||||
#define PPE_BM_SCH_CTRL_SCH_EN BIT(31)
|
||||
|
||||
+/* RSS settings are to calculate the random RSS hash value generated during
|
||||
+ * packet receive to ARM cores. This hash is then used to generate the queue
|
||||
+ * offset used to determine the queue used to transmit the packet to ARM cores.
|
||||
+ */
|
||||
+#define PPE_RSS_HASH_MASK_ADDR 0xb4318
|
||||
+#define PPE_RSS_HASH_MASK_HASH_MASK GENMASK(20, 0)
|
||||
+#define PPE_RSS_HASH_MASK_FRAGMENT BIT(28)
|
||||
+
|
||||
+#define PPE_RSS_HASH_SEED_ADDR 0xb431c
|
||||
+#define PPE_RSS_HASH_SEED_VAL GENMASK(31, 0)
|
||||
+
|
||||
+#define PPE_RSS_HASH_MIX_ADDR 0xb4320
|
||||
+#define PPE_RSS_HASH_MIX_ENTRIES 11
|
||||
+#define PPE_RSS_HASH_MIX_INC 4
|
||||
+#define PPE_RSS_HASH_MIX_VAL GENMASK(4, 0)
|
||||
+
|
||||
+#define PPE_RSS_HASH_FIN_ADDR 0xb4350
|
||||
+#define PPE_RSS_HASH_FIN_ENTRIES 5
|
||||
+#define PPE_RSS_HASH_FIN_INC 4
|
||||
+#define PPE_RSS_HASH_FIN_INNER GENMASK(4, 0)
|
||||
+#define PPE_RSS_HASH_FIN_OUTER GENMASK(9, 5)
|
||||
+
|
||||
+#define PPE_RSS_HASH_MASK_IPV4_ADDR 0xb4380
|
||||
+#define PPE_RSS_HASH_MASK_IPV4_HASH_MASK GENMASK(20, 0)
|
||||
+#define PPE_RSS_HASH_MASK_IPV4_FRAGMENT BIT(28)
|
||||
+
|
||||
+#define PPE_RSS_HASH_SEED_IPV4_ADDR 0xb4384
|
||||
+#define PPE_RSS_HASH_SEED_IPV4_VAL GENMASK(31, 0)
|
||||
+
|
||||
+#define PPE_RSS_HASH_MIX_IPV4_ADDR 0xb4390
|
||||
+#define PPE_RSS_HASH_MIX_IPV4_ENTRIES 5
|
||||
+#define PPE_RSS_HASH_MIX_IPV4_INC 4
|
||||
+#define PPE_RSS_HASH_MIX_IPV4_VAL GENMASK(4, 0)
|
||||
+
|
||||
+#define PPE_RSS_HASH_FIN_IPV4_ADDR 0xb43b0
|
||||
+#define PPE_RSS_HASH_FIN_IPV4_ENTRIES 5
|
||||
+#define PPE_RSS_HASH_FIN_IPV4_INC 4
|
||||
+#define PPE_RSS_HASH_FIN_IPV4_INNER GENMASK(4, 0)
|
||||
+#define PPE_RSS_HASH_FIN_IPV4_OUTER GENMASK(9, 5)
|
||||
+
|
||||
#define PPE_BM_SCH_CFG_TBL_ADDR 0xc000
|
||||
#define PPE_BM_SCH_CFG_TBL_ENTRIES 128
|
||||
#define PPE_BM_SCH_CFG_TBL_INC 0x10
|
||||
@ -1,122 +0,0 @@
|
||||
From c4a321bc120fabc318df165a7fcdeddfcf052253 Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:45 +0800
|
||||
Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE queue to Ethernet DMA
|
||||
ring mapping
|
||||
|
||||
Configure the selected queues to map with an Ethernet DMA ring for the
|
||||
packet to receive on ARM cores.
|
||||
|
||||
As default initialization, all queues assigned to CPU port 0 are mapped
|
||||
to the EDMA ring 0. This configuration is later updated during Ethernet
|
||||
DMA initialization.
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.c | 47 ++++++++++++++++++-
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.h | 6 +++
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 5 ++
|
||||
3 files changed, 57 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
@@ -1328,6 +1328,28 @@ int ppe_rss_hash_config_set(struct ppe_d
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * ppe_ring_queue_map_set - Set the PPE queue to Ethernet DMA ring mapping
|
||||
+ * @ppe_dev: PPE device
|
||||
+ * @ring_id: Ethernet DMA ring ID
|
||||
+ * @queue_map: Bit map of queue IDs to given Ethernet DMA ring
|
||||
+ *
|
||||
+ * Configure the mapping from a set of PPE queues to a given Ethernet DMA ring.
|
||||
+ *
|
||||
+ * Return: 0 on success, negative error code on failure.
|
||||
+ */
|
||||
+int ppe_ring_queue_map_set(struct ppe_device *ppe_dev, int ring_id, u32 *queue_map)
|
||||
+{
|
||||
+ u32 reg, queue_bitmap_val[PPE_RING_TO_QUEUE_BITMAP_WORD_CNT];
|
||||
+
|
||||
+ memcpy(queue_bitmap_val, queue_map, sizeof(queue_bitmap_val));
|
||||
+ reg = PPE_RING_Q_MAP_TBL_ADDR + PPE_RING_Q_MAP_TBL_INC * ring_id;
|
||||
+
|
||||
+ return regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ queue_bitmap_val,
|
||||
+ ARRAY_SIZE(queue_bitmap_val));
|
||||
+}
|
||||
+
|
||||
static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id,
|
||||
const struct ppe_bm_port_config port_cfg)
|
||||
{
|
||||
@@ -1847,6 +1869,25 @@ static int ppe_rss_hash_init(struct ppe_
|
||||
return ppe_rss_hash_config_set(ppe_dev, PPE_RSS_HASH_MODE_IPV6, hash_cfg);
|
||||
}
|
||||
|
||||
+/* Initialize mapping between PPE queues assigned to CPU port 0
|
||||
+ * to Ethernet DMA ring 0.
|
||||
+ */
|
||||
+static int ppe_queues_to_ring_init(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ u32 queue_bmap[PPE_RING_TO_QUEUE_BITMAP_WORD_CNT] = {};
|
||||
+ int ret, queue_id, queue_max;
|
||||
+
|
||||
+ ret = ppe_port_resource_get(ppe_dev, 0, PPE_RES_UCAST,
|
||||
+ &queue_id, &queue_max);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ for (; queue_id <= queue_max; queue_id++)
|
||||
+ queue_bmap[queue_id / 32] |= BIT_MASK(queue_id % 32);
|
||||
+
|
||||
+ return ppe_ring_queue_map_set(ppe_dev, 0, queue_bmap);
|
||||
+}
|
||||
+
|
||||
int ppe_hw_config(struct ppe_device *ppe_dev)
|
||||
{
|
||||
int ret;
|
||||
@@ -1875,5 +1916,9 @@ int ppe_hw_config(struct ppe_device *ppe
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- return ppe_rss_hash_init(ppe_dev);
|
||||
+ ret = ppe_rss_hash_init(ppe_dev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ppe_queues_to_ring_init(ppe_dev);
|
||||
}
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
|
||||
@@ -29,6 +29,9 @@
|
||||
#define PPE_RSS_HASH_IP_LENGTH 4
|
||||
#define PPE_RSS_HASH_TUPLES 5
|
||||
|
||||
+/* PPE supports 300 queues, each bit presents as one queue. */
|
||||
+#define PPE_RING_TO_QUEUE_BITMAP_WORD_CNT 10
|
||||
+
|
||||
/**
|
||||
* enum ppe_scheduler_frame_mode - PPE scheduler frame mode.
|
||||
* @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG,
|
||||
@@ -308,4 +311,7 @@ int ppe_sc_config_set(struct ppe_device
|
||||
int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port);
|
||||
int ppe_rss_hash_config_set(struct ppe_device *ppe_dev, int mode,
|
||||
struct ppe_rss_hash_cfg hash_cfg);
|
||||
+int ppe_ring_queue_map_set(struct ppe_device *ppe_dev,
|
||||
+ int ring_id,
|
||||
+ u32 *queue_map);
|
||||
#endif
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
@@ -207,6 +207,11 @@
|
||||
#define PPE_L0_COMP_CFG_TBL_SHAPER_METER_LEN GENMASK(1, 0)
|
||||
#define PPE_L0_COMP_CFG_TBL_NODE_METER_LEN GENMASK(3, 2)
|
||||
|
||||
+/* PPE queue to Ethernet DMA ring mapping table. */
|
||||
+#define PPE_RING_Q_MAP_TBL_ADDR 0x42a000
|
||||
+#define PPE_RING_Q_MAP_TBL_ENTRIES 24
|
||||
+#define PPE_RING_Q_MAP_TBL_INC 0x40
|
||||
+
|
||||
/* Table addresses for per-queue dequeue setting. */
|
||||
#define PPE_DEQ_OPR_TBL_ADDR 0x430000
|
||||
#define PPE_DEQ_OPR_TBL_ENTRIES 300
|
||||
@ -1,193 +0,0 @@
|
||||
From cf7282d1e5712953516fa1cc0ffaae405491b3ca Mon Sep 17 00:00:00 2001
|
||||
From: Lei Wei <quic_leiwei@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:46 +0800
|
||||
Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE L2 bridge settings
|
||||
|
||||
Initialize the L2 bridge settings for the PPE ports to only enable
|
||||
L2 frame forwarding between CPU port and PPE Ethernet ports.
|
||||
|
||||
The per-port L2 bridge settings are initialized as follows:
|
||||
For PPE CPU port, the PPE bridge TX is enabled and FDB learning is
|
||||
disabled. For PPE physical ports, the default L2 forwarding action
|
||||
is initialized to forward to CPU port only.
|
||||
|
||||
L2/FDB learning and forwarding will not be enabled for PPE physical
|
||||
ports yet, since the port's VSI (Virtual Switch Instance) and VSI
|
||||
membership are not yet configured, which are required for FDB
|
||||
forwarding. The VSI and FDB forwarding will later be enabled when
|
||||
switchdev is enabled.
|
||||
|
||||
Signed-off-by: Lei Wei <quic_leiwei@quicinc.com>
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
.../net/ethernet/qualcomm/ppe/ppe_config.c | 80 ++++++++++++++++++-
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 50 ++++++++++++
|
||||
2 files changed, 129 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
|
||||
@@ -1888,6 +1888,80 @@ static int ppe_queues_to_ring_init(struc
|
||||
return ppe_ring_queue_map_set(ppe_dev, 0, queue_bmap);
|
||||
}
|
||||
|
||||
+/* Initialize PPE bridge settings to only enable L2 frame receive and
|
||||
+ * transmit between CPU port and PPE Ethernet ports.
|
||||
+ */
|
||||
+static int ppe_bridge_init(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ u32 reg, mask, port_cfg[4], vsi_cfg[2];
|
||||
+ int ret, i;
|
||||
+
|
||||
+ /* Configure the following settings for CPU port0:
|
||||
+ * a.) Enable Bridge TX
|
||||
+ * b.) Disable FDB new address learning
|
||||
+ * c.) Disable station move address learning
|
||||
+ */
|
||||
+ mask = PPE_PORT_BRIDGE_TXMAC_EN;
|
||||
+ mask |= PPE_PORT_BRIDGE_NEW_LRN_EN;
|
||||
+ mask |= PPE_PORT_BRIDGE_STA_MOVE_LRN_EN;
|
||||
+ ret = regmap_update_bits(ppe_dev->regmap,
|
||||
+ PPE_PORT_BRIDGE_CTRL_ADDR,
|
||||
+ mask,
|
||||
+ PPE_PORT_BRIDGE_TXMAC_EN);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ for (i = 1; i < ppe_dev->num_ports; i++) {
|
||||
+ /* Enable invalid VSI forwarding for all the physical ports
|
||||
+ * to CPU port0, in case no VSI is assigned to the physical
|
||||
+ * port.
|
||||
+ */
|
||||
+ reg = PPE_L2_VP_PORT_TBL_ADDR + PPE_L2_VP_PORT_TBL_INC * i;
|
||||
+ ret = regmap_bulk_read(ppe_dev->regmap, reg,
|
||||
+ port_cfg, ARRAY_SIZE(port_cfg));
|
||||
+
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ PPE_L2_PORT_SET_INVALID_VSI_FWD_EN(port_cfg, true);
|
||||
+ PPE_L2_PORT_SET_DST_INFO(port_cfg, 0);
|
||||
+
|
||||
+ ret = regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ port_cfg, ARRAY_SIZE(port_cfg));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_VSI_TBL_ENTRIES; i++) {
|
||||
+ /* Set the VSI forward membership to include only CPU port0.
|
||||
+ * FDB learning and forwarding take place only after switchdev
|
||||
+ * is supported later to create the VSI and join the physical
|
||||
+ * ports to the VSI port member.
|
||||
+ */
|
||||
+ reg = PPE_VSI_TBL_ADDR + PPE_VSI_TBL_INC * i;
|
||||
+ ret = regmap_bulk_read(ppe_dev->regmap, reg,
|
||||
+ vsi_cfg, ARRAY_SIZE(vsi_cfg));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ PPE_VSI_SET_MEMBER_PORT_BITMAP(vsi_cfg, BIT(0));
|
||||
+ PPE_VSI_SET_UUC_BITMAP(vsi_cfg, BIT(0));
|
||||
+ PPE_VSI_SET_UMC_BITMAP(vsi_cfg, BIT(0));
|
||||
+ PPE_VSI_SET_BC_BITMAP(vsi_cfg, BIT(0));
|
||||
+ PPE_VSI_SET_NEW_ADDR_LRN_EN(vsi_cfg, true);
|
||||
+ PPE_VSI_SET_NEW_ADDR_FWD_CMD(vsi_cfg, PPE_ACTION_FORWARD);
|
||||
+ PPE_VSI_SET_STATION_MOVE_LRN_EN(vsi_cfg, true);
|
||||
+ PPE_VSI_SET_STATION_MOVE_FWD_CMD(vsi_cfg, PPE_ACTION_FORWARD);
|
||||
+
|
||||
+ ret = regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ vsi_cfg, ARRAY_SIZE(vsi_cfg));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int ppe_hw_config(struct ppe_device *ppe_dev)
|
||||
{
|
||||
int ret;
|
||||
@@ -1920,5 +1994,9 @@ int ppe_hw_config(struct ppe_device *ppe
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- return ppe_queues_to_ring_init(ppe_dev);
|
||||
+ ret = ppe_queues_to_ring_init(ppe_dev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ppe_bridge_init(ppe_dev);
|
||||
}
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
@@ -117,6 +117,14 @@
|
||||
#define PPE_EG_SERVICE_SET_TX_CNT_EN(tbl_cfg, value) \
|
||||
u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_TX_CNT_EN)
|
||||
|
||||
+/* PPE port bridge configuration */
|
||||
+#define PPE_PORT_BRIDGE_CTRL_ADDR 0x60300
|
||||
+#define PPE_PORT_BRIDGE_CTRL_ENTRIES 8
|
||||
+#define PPE_PORT_BRIDGE_CTRL_INC 4
|
||||
+#define PPE_PORT_BRIDGE_NEW_LRN_EN BIT(0)
|
||||
+#define PPE_PORT_BRIDGE_STA_MOVE_LRN_EN BIT(3)
|
||||
+#define PPE_PORT_BRIDGE_TXMAC_EN BIT(16)
|
||||
+
|
||||
/* PPE port control configurations for the traffic to the multicast queues. */
|
||||
#define PPE_MC_MTU_CTRL_TBL_ADDR 0x60a00
|
||||
#define PPE_MC_MTU_CTRL_TBL_ENTRIES 8
|
||||
@@ -125,6 +133,36 @@
|
||||
#define PPE_MC_MTU_CTRL_TBL_MTU_CMD GENMASK(15, 14)
|
||||
#define PPE_MC_MTU_CTRL_TBL_TX_CNT_EN BIT(16)
|
||||
|
||||
+/* PPE VSI configurations */
|
||||
+#define PPE_VSI_TBL_ADDR 0x63800
|
||||
+#define PPE_VSI_TBL_ENTRIES 64
|
||||
+#define PPE_VSI_TBL_INC 0x10
|
||||
+#define PPE_VSI_W0_MEMBER_PORT_BITMAP GENMASK(7, 0)
|
||||
+#define PPE_VSI_W0_UUC_BITMAP GENMASK(15, 8)
|
||||
+#define PPE_VSI_W0_UMC_BITMAP GENMASK(23, 16)
|
||||
+#define PPE_VSI_W0_BC_BITMAP GENMASK(31, 24)
|
||||
+#define PPE_VSI_W1_NEW_ADDR_LRN_EN BIT(0)
|
||||
+#define PPE_VSI_W1_NEW_ADDR_FWD_CMD GENMASK(2, 1)
|
||||
+#define PPE_VSI_W1_STATION_MOVE_LRN_EN BIT(3)
|
||||
+#define PPE_VSI_W1_STATION_MOVE_FWD_CMD GENMASK(5, 4)
|
||||
+
|
||||
+#define PPE_VSI_SET_MEMBER_PORT_BITMAP(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_MEMBER_PORT_BITMAP)
|
||||
+#define PPE_VSI_SET_UUC_BITMAP(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_UUC_BITMAP)
|
||||
+#define PPE_VSI_SET_UMC_BITMAP(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_UMC_BITMAP)
|
||||
+#define PPE_VSI_SET_BC_BITMAP(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_BC_BITMAP)
|
||||
+#define PPE_VSI_SET_NEW_ADDR_LRN_EN(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_NEW_ADDR_LRN_EN)
|
||||
+#define PPE_VSI_SET_NEW_ADDR_FWD_CMD(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_NEW_ADDR_FWD_CMD)
|
||||
+#define PPE_VSI_SET_STATION_MOVE_LRN_EN(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_STATION_MOVE_LRN_EN)
|
||||
+#define PPE_VSI_SET_STATION_MOVE_FWD_CMD(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_STATION_MOVE_FWD_CMD)
|
||||
+
|
||||
/* PPE port control configurations for the traffic to the unicast queues. */
|
||||
#define PPE_MRU_MTU_CTRL_TBL_ADDR 0x65000
|
||||
#define PPE_MRU_MTU_CTRL_TBL_ENTRIES 256
|
||||
@@ -163,6 +201,18 @@
|
||||
#define PPE_IN_L2_SERVICE_TBL_RX_CNT_EN BIT(30)
|
||||
#define PPE_IN_L2_SERVICE_TBL_TX_CNT_EN BIT(31)
|
||||
|
||||
+/* L2 Port configurations */
|
||||
+#define PPE_L2_VP_PORT_TBL_ADDR 0x98000
|
||||
+#define PPE_L2_VP_PORT_TBL_ENTRIES 256
|
||||
+#define PPE_L2_VP_PORT_TBL_INC 0x10
|
||||
+#define PPE_L2_VP_PORT_W0_INVALID_VSI_FWD_EN BIT(0)
|
||||
+#define PPE_L2_VP_PORT_W0_DST_INFO GENMASK(9, 2)
|
||||
+
|
||||
+#define PPE_L2_PORT_SET_INVALID_VSI_FWD_EN(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_L2_VP_PORT_W0_INVALID_VSI_FWD_EN)
|
||||
+#define PPE_L2_PORT_SET_DST_INFO(tbl_cfg, value) \
|
||||
+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_L2_VP_PORT_W0_DST_INFO)
|
||||
+
|
||||
/* PPE service code configuration for the tunnel packet. */
|
||||
#define PPE_TL_SERVICE_TBL_ADDR 0x306000
|
||||
#define PPE_TL_SERVICE_TBL_ENTRIES 256
|
||||
@ -1,950 +0,0 @@
|
||||
From fc25088f79cccb934d69e563221068589565926f Mon Sep 17 00:00:00 2001
|
||||
From: Luo Jie <quic_luoj@quicinc.com>
|
||||
Date: Sun, 9 Feb 2025 22:29:47 +0800
|
||||
Subject: [PATCH] net: ethernet: qualcomm: Add PPE debugfs support for PPE
|
||||
counters
|
||||
|
||||
The PPE hardware counters maintain counters for packets handled by
|
||||
the various functional blocks of PPE. They help in tracing the packets
|
||||
passed through PPE and debugging any packet drops.
|
||||
|
||||
The counters displayed by this debugfs file are ones that are common
|
||||
for all Ethernet ports, and they do not include the counters that are
|
||||
specific for a MAC port. Hence they cannot be displayed using ethtool.
|
||||
The per-MAC counters will be supported using "ethtool -S" along with
|
||||
the netdevice driver.
|
||||
|
||||
The PPE hardware packet counters are made available through
|
||||
the debugfs entry "/sys/kernel/debug/ppe/packet_counters".
|
||||
|
||||
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
|
||||
---
|
||||
drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +-
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe.c | 11 +
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe.h | 3 +
|
||||
.../net/ethernet/qualcomm/ppe/ppe_debugfs.c | 692 ++++++++++++++++++
|
||||
.../net/ethernet/qualcomm/ppe/ppe_debugfs.h | 16 +
|
||||
drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 102 +++
|
||||
6 files changed, 825 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c
|
||||
create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.h
|
||||
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/Makefile
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile
|
||||
@@ -4,4 +4,4 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o
|
||||
-qcom-ppe-objs := ppe.o ppe_config.o
|
||||
+qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "ppe.h"
|
||||
#include "ppe_config.h"
|
||||
+#include "ppe_debugfs.h"
|
||||
|
||||
#define PPE_PORT_MAX 8
|
||||
#define PPE_CLK_RATE 353000000
|
||||
@@ -199,11 +200,20 @@ static int qcom_ppe_probe(struct platfor
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "PPE HW config failed\n");
|
||||
|
||||
+ ppe_debugfs_setup(ppe_dev);
|
||||
platform_set_drvdata(pdev, ppe_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void qcom_ppe_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct ppe_device *ppe_dev;
|
||||
+
|
||||
+ ppe_dev = platform_get_drvdata(pdev);
|
||||
+ ppe_debugfs_teardown(ppe_dev);
|
||||
+}
|
||||
+
|
||||
static const struct of_device_id qcom_ppe_of_match[] = {
|
||||
{ .compatible = "qcom,ipq9574-ppe" },
|
||||
{}
|
||||
@@ -216,6 +226,7 @@ static struct platform_driver qcom_ppe_d
|
||||
.of_match_table = qcom_ppe_of_match,
|
||||
},
|
||||
.probe = qcom_ppe_probe,
|
||||
+ .remove = qcom_ppe_remove,
|
||||
};
|
||||
module_platform_driver(qcom_ppe_driver);
|
||||
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
struct device;
|
||||
struct regmap;
|
||||
+struct dentry;
|
||||
|
||||
/**
|
||||
* struct ppe_device - PPE device private data.
|
||||
@@ -18,6 +19,7 @@ struct regmap;
|
||||
* @regmap: PPE register map.
|
||||
* @clk_rate: PPE clock rate.
|
||||
* @num_ports: Number of PPE ports.
|
||||
+ * @debugfs_root: Debugfs root entry.
|
||||
* @num_icc_paths: Number of interconnect paths.
|
||||
* @icc_paths: Interconnect path array.
|
||||
*
|
||||
@@ -30,6 +32,7 @@ struct ppe_device {
|
||||
struct regmap *regmap;
|
||||
unsigned long clk_rate;
|
||||
unsigned int num_ports;
|
||||
+ struct dentry *debugfs_root;
|
||||
unsigned int num_icc_paths;
|
||||
struct icc_bulk_data icc_paths[] __counted_by(num_icc_paths);
|
||||
};
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c
|
||||
@@ -0,0 +1,692 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+/* PPE debugfs routines for display of PPE counters useful for debug. */
|
||||
+
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/debugfs.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/seq_file.h>
|
||||
+
|
||||
+#include "ppe.h"
|
||||
+#include "ppe_config.h"
|
||||
+#include "ppe_debugfs.h"
|
||||
+#include "ppe_regs.h"
|
||||
+
|
||||
+#define PPE_PKT_CNT_TBL_SIZE 3
|
||||
+#define PPE_DROP_PKT_CNT_TBL_SIZE 5
|
||||
+
|
||||
+#define PPE_W0_PKT_CNT GENMASK(31, 0)
|
||||
+#define PPE_W2_DROP_PKT_CNT_LOW GENMASK(31, 8)
|
||||
+#define PPE_W3_DROP_PKT_CNT_HIGH GENMASK(7, 0)
|
||||
+
|
||||
+#define PPE_GET_PKT_CNT(tbl_cnt) \
|
||||
+ u32_get_bits(*((u32 *)(tbl_cnt)), PPE_W0_PKT_CNT)
|
||||
+#define PPE_GET_DROP_PKT_CNT_LOW(tbl_cnt) \
|
||||
+ u32_get_bits(*((u32 *)(tbl_cnt) + 0x2), PPE_W2_DROP_PKT_CNT_LOW)
|
||||
+#define PPE_GET_DROP_PKT_CNT_HIGH(tbl_cnt) \
|
||||
+ u32_get_bits(*((u32 *)(tbl_cnt) + 0x3), PPE_W3_DROP_PKT_CNT_HIGH)
|
||||
+
|
||||
+#define PRINT_COUNTER_PREFIX(desc, cnt_type) \
|
||||
+ seq_printf(seq, "%-16s %16s", desc, cnt_type)
|
||||
+
|
||||
+#define PRINT_CPU_CODE_COUNTER(cnt, code) \
|
||||
+ seq_printf(seq, "%10u(cpucode:%d)", cnt, code)
|
||||
+
|
||||
+#define PRINT_DROP_CODE_COUNTER(cnt, port, code) \
|
||||
+ seq_printf(seq, "%10u(port=%d),dropcode:%d", cnt, port, code)
|
||||
+
|
||||
+#define PRINT_SINGLE_COUNTER(tag, cnt, str, index) \
|
||||
+do { \
|
||||
+ if (!((tag) % 4)) \
|
||||
+ seq_printf(seq, "\n%-16s %16s", "", ""); \
|
||||
+ seq_printf(seq, "%10u(%s=%04d)", cnt, str, index); \
|
||||
+} while (0)
|
||||
+
|
||||
+#define PRINT_TWO_COUNTERS(tag, cnt0, cnt1, str, index) \
|
||||
+do { \
|
||||
+ if (!((tag) % 4)) \
|
||||
+ seq_printf(seq, "\n%-16s %16s", "", ""); \
|
||||
+ seq_printf(seq, "%10u/%u(%s=%04d)", cnt0, cnt1, str, index); \
|
||||
+} while (0)
|
||||
+
|
||||
+/**
|
||||
+ * enum ppe_cnt_size_type - PPE counter size type
|
||||
+ * @PPE_PKT_CNT_SIZE_1WORD: Counter size with single register
|
||||
+ * @PPE_PKT_CNT_SIZE_3WORD: Counter size with table of 3 words
|
||||
+ * @PPE_PKT_CNT_SIZE_5WORD: Counter size with table of 5 words
|
||||
+ *
|
||||
+ * PPE takes the different register size to record the packet counters.
|
||||
+ * It uses single register, or register table with 3 words or 5 words.
|
||||
+ * The counter with table size 5 words also records the drop counter.
|
||||
+ * There are also some other counter types occupying sizes less than 32
|
||||
+ * bits, which is not covered by this enumeration type.
|
||||
+ */
|
||||
+enum ppe_cnt_size_type {
|
||||
+ PPE_PKT_CNT_SIZE_1WORD,
|
||||
+ PPE_PKT_CNT_SIZE_3WORD,
|
||||
+ PPE_PKT_CNT_SIZE_5WORD,
|
||||
+};
|
||||
+
|
||||
+static int ppe_pkt_cnt_get(struct ppe_device *ppe_dev, u32 reg,
|
||||
+ enum ppe_cnt_size_type cnt_type,
|
||||
+ u32 *cnt, u32 *drop_cnt)
|
||||
+{
|
||||
+ u32 drop_pkt_cnt[PPE_DROP_PKT_CNT_TBL_SIZE];
|
||||
+ u32 pkt_cnt[PPE_PKT_CNT_TBL_SIZE];
|
||||
+ u32 value;
|
||||
+ int ret;
|
||||
+
|
||||
+ switch (cnt_type) {
|
||||
+ case PPE_PKT_CNT_SIZE_1WORD:
|
||||
+ ret = regmap_read(ppe_dev->regmap, reg, &value);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ *cnt = value;
|
||||
+ break;
|
||||
+ case PPE_PKT_CNT_SIZE_3WORD:
|
||||
+ ret = regmap_bulk_read(ppe_dev->regmap, reg,
|
||||
+ pkt_cnt, ARRAY_SIZE(pkt_cnt));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ *cnt = PPE_GET_PKT_CNT(pkt_cnt);
|
||||
+ break;
|
||||
+ case PPE_PKT_CNT_SIZE_5WORD:
|
||||
+ ret = regmap_bulk_read(ppe_dev->regmap, reg,
|
||||
+ drop_pkt_cnt, ARRAY_SIZE(drop_pkt_cnt));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ *cnt = PPE_GET_PKT_CNT(drop_pkt_cnt);
|
||||
+
|
||||
+ /* Drop counter with low 24 bits. */
|
||||
+ value = PPE_GET_DROP_PKT_CNT_LOW(drop_pkt_cnt);
|
||||
+ *drop_cnt = FIELD_PREP(GENMASK(23, 0), value);
|
||||
+
|
||||
+ /* Drop counter with high 8 bits. */
|
||||
+ value = PPE_GET_DROP_PKT_CNT_HIGH(drop_pkt_cnt);
|
||||
+ *drop_cnt |= FIELD_PREP(GENMASK(31, 24), value);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void ppe_tbl_pkt_cnt_clear(struct ppe_device *ppe_dev, u32 reg,
|
||||
+ enum ppe_cnt_size_type cnt_type)
|
||||
+{
|
||||
+ u32 drop_pkt_cnt[PPE_DROP_PKT_CNT_TBL_SIZE] = {};
|
||||
+ u32 pkt_cnt[PPE_PKT_CNT_TBL_SIZE] = {};
|
||||
+
|
||||
+ switch (cnt_type) {
|
||||
+ case PPE_PKT_CNT_SIZE_1WORD:
|
||||
+ regmap_write(ppe_dev->regmap, reg, 0);
|
||||
+ break;
|
||||
+ case PPE_PKT_CNT_SIZE_3WORD:
|
||||
+ regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ pkt_cnt, ARRAY_SIZE(pkt_cnt));
|
||||
+ break;
|
||||
+ case PPE_PKT_CNT_SIZE_5WORD:
|
||||
+ regmap_bulk_write(ppe_dev->regmap, reg,
|
||||
+ drop_pkt_cnt, ARRAY_SIZE(drop_pkt_cnt));
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* The number of packets dropped because of no buffer available, no PPE
|
||||
+ * buffer assigned to these packets.
|
||||
+ */
|
||||
+static void ppe_port_rx_drop_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, drop_cnt = 0;
|
||||
+ int ret, i, tag = 0;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("PRX_DROP_CNT", "SILENT_DROP:");
|
||||
+ for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC;
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD,
|
||||
+ &drop_cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (drop_cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_SINGLE_COUNTER(tag, drop_cnt, "port", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of packets dropped because hardware buffers were available
|
||||
+ * only partially for the packet.
|
||||
+ */
|
||||
+static void ppe_port_rx_bm_drop_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, pkt_cnt = 0;
|
||||
+ int ret, i, tag = 0;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("PRX_BM_DROP_CNT", "OVERFLOW_DROP:");
|
||||
+ for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i;
|
||||
+
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
|
||||
+ &pkt_cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (pkt_cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_SINGLE_COUNTER(tag, pkt_cnt, "port", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of currently occupied buffers, that can't be flushed. */
|
||||
+static void ppe_port_rx_bm_port_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ int used_cnt, react_cnt;
|
||||
+ int ret, i, tag = 0;
|
||||
+ u32 reg, val;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("PRX_BM_PORT_CNT", "USED/REACT:");
|
||||
+ for (i = 0; i < PPE_BM_USED_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_BM_USED_CNT_TBL_ADDR + i * PPE_BM_USED_CNT_TBL_INC;
|
||||
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* The number of PPE buffers used for caching the received
|
||||
+ * packets before the pause frame sent.
|
||||
+ */
|
||||
+ used_cnt = FIELD_GET(PPE_BM_USED_CNT_VAL, val);
|
||||
+
|
||||
+ reg = PPE_BM_REACT_CNT_TBL_ADDR + i * PPE_BM_REACT_CNT_TBL_INC;
|
||||
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* The number of PPE buffers used for caching the received
|
||||
+ * packets after pause frame sent out.
|
||||
+ */
|
||||
+ react_cnt = FIELD_GET(PPE_BM_REACT_CNT_VAL, val);
|
||||
+
|
||||
+ if (used_cnt > 0 || react_cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_TWO_COUNTERS(tag, used_cnt, react_cnt, "port", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of packets processed by the ingress parser module of PPE. */
|
||||
+static void ppe_parse_pkt_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, cnt = 0, tunnel_cnt = 0;
|
||||
+ int i, ret, tag = 0;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("IPR_PKT_CNT", "TPRX/IPRX:");
|
||||
+ for (i = 0; i < PPE_IPR_PKT_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_TPR_PKT_CNT_TBL_ADDR + i * PPE_TPR_PKT_CNT_TBL_INC;
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD,
|
||||
+ &tunnel_cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ reg = PPE_IPR_PKT_CNT_TBL_ADDR + i * PPE_IPR_PKT_CNT_TBL_INC;
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD,
|
||||
+ &cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (tunnel_cnt > 0 || cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_TWO_COUNTERS(tag, tunnel_cnt, cnt, "port", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of packets received or dropped on the ingress direction. */
|
||||
+static void ppe_port_rx_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, pkt_cnt = 0, drop_cnt = 0;
|
||||
+ int ret, i, tag = 0;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("PORT_RX_CNT", "RX/RX_DROP:");
|
||||
+ for (i = 0; i < PPE_PHY_PORT_RX_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_PHY_PORT_RX_CNT_TBL_ADDR + PPE_PHY_PORT_RX_CNT_TBL_INC * i;
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD,
|
||||
+ &pkt_cnt, &drop_cnt);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (pkt_cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of packets received or dropped by the port. */
|
||||
+static void ppe_vp_rx_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, pkt_cnt = 0, drop_cnt = 0;
|
||||
+ int ret, i, tag = 0;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("VPORT_RX_CNT", "RX/RX_DROP:");
|
||||
+ for (i = 0; i < PPE_PORT_RX_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_PORT_RX_CNT_TBL_ADDR + PPE_PORT_RX_CNT_TBL_INC * i;
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD,
|
||||
+ &pkt_cnt, &drop_cnt);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (pkt_cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of packets received or dropped by layer 2 processing. */
|
||||
+static void ppe_pre_l2_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, pkt_cnt = 0, drop_cnt = 0;
|
||||
+ int ret, i, tag = 0;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("PRE_L2_CNT", "RX/RX_DROP:");
|
||||
+ for (i = 0; i < PPE_PRE_L2_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_PRE_L2_CNT_TBL_ADDR + PPE_PRE_L2_CNT_TBL_INC * i;
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD,
|
||||
+ &pkt_cnt, &drop_cnt);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (pkt_cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "vsi", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of VLAN packets received by PPE. */
|
||||
+static void ppe_vlan_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, pkt_cnt = 0;
|
||||
+ int ret, i, tag = 0;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("VLAN_CNT", "RX:");
|
||||
+ for (i = 0; i < PPE_VLAN_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_VLAN_CNT_TBL_ADDR + PPE_VLAN_CNT_TBL_INC * i;
|
||||
+
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
|
||||
+ &pkt_cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (pkt_cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_SINGLE_COUNTER(tag, pkt_cnt, "vsi", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of packets handed to CPU by PPE. */
|
||||
+static void ppe_cpu_code_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, pkt_cnt = 0;
|
||||
+ int ret, i;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("CPU_CODE_CNT", "CODE:");
|
||||
+ for (i = 0; i < PPE_DROP_CPU_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_DROP_CPU_CNT_TBL_ADDR + PPE_DROP_CPU_CNT_TBL_INC * i;
|
||||
+
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
|
||||
+ &pkt_cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!pkt_cnt)
|
||||
+ continue;
|
||||
+
|
||||
+ /* There are 256 CPU codes saved in the first 256 entries
|
||||
+ * of register table, and 128 drop codes for each PPE port
|
||||
+ * (0-7), the total entries is 256 + 8 * 128.
|
||||
+ */
|
||||
+ if (i < 256)
|
||||
+ PRINT_CPU_CODE_COUNTER(pkt_cnt, i);
|
||||
+ else
|
||||
+ PRINT_DROP_CODE_COUNTER(pkt_cnt, (i - 256) % 8,
|
||||
+ (i - 256) / 8);
|
||||
+ seq_putc(seq, '\n');
|
||||
+ PRINT_COUNTER_PREFIX("", "");
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of packets forwarded by VLAN on the egress direction. */
|
||||
+static void ppe_eg_vsi_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, pkt_cnt = 0;
|
||||
+ int ret, i, tag = 0;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("EG_VSI_CNT", "TX:");
|
||||
+ for (i = 0; i < PPE_EG_VSI_COUNTER_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_EG_VSI_COUNTER_TBL_ADDR + PPE_EG_VSI_COUNTER_TBL_INC * i;
|
||||
+
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
|
||||
+ &pkt_cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (pkt_cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_SINGLE_COUNTER(tag, pkt_cnt, "vsi", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of packets trasmitted or dropped by port. */
|
||||
+static void ppe_vp_tx_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, pkt_cnt = 0, drop_cnt = 0;
|
||||
+ int ret, i, tag = 0;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("VPORT_TX_CNT", "TX/TX_DROP:");
|
||||
+ for (i = 0; i < PPE_VPORT_TX_COUNTER_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_VPORT_TX_COUNTER_TBL_ADDR + PPE_VPORT_TX_COUNTER_TBL_INC * i;
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
|
||||
+ &pkt_cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ reg = PPE_VPORT_TX_DROP_CNT_TBL_ADDR + PPE_VPORT_TX_DROP_CNT_TBL_INC * i;
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
|
||||
+ &drop_cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (pkt_cnt > 0 || drop_cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of packets trasmitted or dropped on the egress direction. */
|
||||
+static void ppe_port_tx_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, pkt_cnt = 0, drop_cnt = 0;
|
||||
+ int ret, i, tag = 0;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("PORT_TX_CNT", "TX/TX_DROP:");
|
||||
+ for (i = 0; i < PPE_PORT_TX_COUNTER_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_PORT_TX_COUNTER_TBL_ADDR + PPE_PORT_TX_COUNTER_TBL_INC * i;
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
|
||||
+ &pkt_cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ reg = PPE_PORT_TX_DROP_CNT_TBL_ADDR + PPE_PORT_TX_DROP_CNT_TBL_INC * i;
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
|
||||
+ &drop_cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (pkt_cnt > 0 || drop_cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* The number of packets transmitted or pending by the PPE queue. */
|
||||
+static void ppe_queue_tx_counter_get(struct ppe_device *ppe_dev,
|
||||
+ struct seq_file *seq)
|
||||
+{
|
||||
+ u32 reg, val, pkt_cnt = 0, pend_cnt = 0;
|
||||
+ int ret, i, tag = 0;
|
||||
+
|
||||
+ PRINT_COUNTER_PREFIX("QUEUE_TX_CNT", "TX/PEND:");
|
||||
+ for (i = 0; i < PPE_QUEUE_TX_COUNTER_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_QUEUE_TX_COUNTER_TBL_ADDR + PPE_QUEUE_TX_COUNTER_TBL_INC * i;
|
||||
+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD,
|
||||
+ &pkt_cnt, NULL);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (i < PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES) {
|
||||
+ reg = PPE_AC_UNICAST_QUEUE_CNT_TBL_ADDR +
|
||||
+ PPE_AC_UNICAST_QUEUE_CNT_TBL_INC * i;
|
||||
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ pend_cnt = FIELD_GET(PPE_AC_UNICAST_QUEUE_CNT_TBL_PEND_CNT, val);
|
||||
+ } else {
|
||||
+ reg = PPE_AC_MULTICAST_QUEUE_CNT_TBL_ADDR +
|
||||
+ PPE_AC_MULTICAST_QUEUE_CNT_TBL_INC *
|
||||
+ (i - PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES);
|
||||
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
|
||||
+ if (ret) {
|
||||
+ seq_printf(seq, "ERROR %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ pend_cnt = FIELD_GET(PPE_AC_MULTICAST_QUEUE_CNT_TBL_PEND_CNT, val);
|
||||
+ }
|
||||
+
|
||||
+ if (pkt_cnt > 0 || pend_cnt > 0) {
|
||||
+ tag++;
|
||||
+ PRINT_TWO_COUNTERS(tag, pkt_cnt, pend_cnt, "queue", i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ seq_putc(seq, '\n');
|
||||
+}
|
||||
+
|
||||
+/* Display the various packet counters of PPE. */
|
||||
+static int ppe_packet_counter_show(struct seq_file *seq, void *v)
|
||||
+{
|
||||
+ struct ppe_device *ppe_dev = seq->private;
|
||||
+
|
||||
+ ppe_port_rx_drop_counter_get(ppe_dev, seq);
|
||||
+ ppe_port_rx_bm_drop_counter_get(ppe_dev, seq);
|
||||
+ ppe_port_rx_bm_port_counter_get(ppe_dev, seq);
|
||||
+ ppe_parse_pkt_counter_get(ppe_dev, seq);
|
||||
+ ppe_port_rx_counter_get(ppe_dev, seq);
|
||||
+ ppe_vp_rx_counter_get(ppe_dev, seq);
|
||||
+ ppe_pre_l2_counter_get(ppe_dev, seq);
|
||||
+ ppe_vlan_counter_get(ppe_dev, seq);
|
||||
+ ppe_cpu_code_counter_get(ppe_dev, seq);
|
||||
+ ppe_eg_vsi_counter_get(ppe_dev, seq);
|
||||
+ ppe_vp_tx_counter_get(ppe_dev, seq);
|
||||
+ ppe_port_tx_counter_get(ppe_dev, seq);
|
||||
+ ppe_queue_tx_counter_get(ppe_dev, seq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ppe_packet_counter_open(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ return single_open(file, ppe_packet_counter_show, inode->i_private);
|
||||
+}
|
||||
+
|
||||
+static ssize_t ppe_packet_counter_clear(struct file *file,
|
||||
+ const char __user *buf,
|
||||
+ size_t count, loff_t *pos)
|
||||
+{
|
||||
+ struct ppe_device *ppe_dev = file_inode(file)->i_private;
|
||||
+ u32 reg;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_IPR_PKT_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_IPR_PKT_CNT_TBL_ADDR + i * PPE_IPR_PKT_CNT_TBL_INC;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD);
|
||||
+
|
||||
+ reg = PPE_TPR_PKT_CNT_TBL_ADDR + i * PPE_TPR_PKT_CNT_TBL_INC;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_VLAN_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_VLAN_CNT_TBL_ADDR + PPE_VLAN_CNT_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_PRE_L2_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_PRE_L2_CNT_TBL_ADDR + PPE_PRE_L2_CNT_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_PORT_TX_COUNTER_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_PORT_TX_DROP_CNT_TBL_ADDR + PPE_PORT_TX_DROP_CNT_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
|
||||
+
|
||||
+ reg = PPE_PORT_TX_COUNTER_TBL_ADDR + PPE_PORT_TX_COUNTER_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_EG_VSI_COUNTER_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_EG_VSI_COUNTER_TBL_ADDR + PPE_EG_VSI_COUNTER_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_VPORT_TX_COUNTER_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_VPORT_TX_COUNTER_TBL_ADDR + PPE_VPORT_TX_COUNTER_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
|
||||
+
|
||||
+ reg = PPE_VPORT_TX_DROP_CNT_TBL_ADDR + PPE_VPORT_TX_DROP_CNT_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_QUEUE_TX_COUNTER_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_QUEUE_TX_COUNTER_TBL_ADDR + PPE_QUEUE_TX_COUNTER_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
|
||||
+ }
|
||||
+
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, PPE_EPE_DBG_IN_CNT_ADDR, PPE_PKT_CNT_SIZE_1WORD);
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, PPE_EPE_DBG_OUT_CNT_ADDR, PPE_PKT_CNT_SIZE_1WORD);
|
||||
+
|
||||
+ for (i = 0; i < PPE_DROP_CPU_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_DROP_CPU_CNT_TBL_ADDR + PPE_DROP_CPU_CNT_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_PORT_RX_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_PORT_RX_CNT_TBL_ADDR + PPE_PORT_RX_CNT_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < PPE_PHY_PORT_RX_CNT_TBL_ENTRIES; i++) {
|
||||
+ reg = PPE_PHY_PORT_RX_CNT_TBL_ADDR + PPE_PHY_PORT_RX_CNT_TBL_INC * i;
|
||||
+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD);
|
||||
+ }
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations ppe_debugfs_packet_counter_fops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .open = ppe_packet_counter_open,
|
||||
+ .read = seq_read,
|
||||
+ .llseek = seq_lseek,
|
||||
+ .release = single_release,
|
||||
+ .write = ppe_packet_counter_clear,
|
||||
+};
|
||||
+
|
||||
+void ppe_debugfs_setup(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ ppe_dev->debugfs_root = debugfs_create_dir("ppe", NULL);
|
||||
+ debugfs_create_file("packet_counters", 0444,
|
||||
+ ppe_dev->debugfs_root,
|
||||
+ ppe_dev,
|
||||
+ &ppe_debugfs_packet_counter_fops);
|
||||
+}
|
||||
+
|
||||
+void ppe_debugfs_teardown(struct ppe_device *ppe_dev)
|
||||
+{
|
||||
+ debugfs_remove_recursive(ppe_dev->debugfs_root);
|
||||
+ ppe_dev->debugfs_root = NULL;
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.h
|
||||
@@ -0,0 +1,16 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-only
|
||||
+ *
|
||||
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+/* PPE debugfs counters setup. */
|
||||
+
|
||||
+#ifndef __PPE_DEBUGFS_H__
|
||||
+#define __PPE_DEBUGFS_H__
|
||||
+
|
||||
+#include "ppe.h"
|
||||
+
|
||||
+void ppe_debugfs_setup(struct ppe_device *ppe_dev);
|
||||
+void ppe_debugfs_teardown(struct ppe_device *ppe_dev);
|
||||
+
|
||||
+#endif
|
||||
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
|
||||
@@ -16,6 +16,39 @@
|
||||
#define PPE_BM_SCH_CTRL_SCH_OFFSET GENMASK(14, 8)
|
||||
#define PPE_BM_SCH_CTRL_SCH_EN BIT(31)
|
||||
|
||||
+/* PPE drop counters. */
|
||||
+#define PPE_DROP_CNT_TBL_ADDR 0xb024
|
||||
+#define PPE_DROP_CNT_TBL_ENTRIES 8
|
||||
+#define PPE_DROP_CNT_TBL_INC 4
|
||||
+
|
||||
+/* BM port drop counters. */
|
||||
+#define PPE_DROP_STAT_TBL_ADDR 0xe000
|
||||
+#define PPE_DROP_STAT_TBL_ENTRIES 30
|
||||
+#define PPE_DROP_STAT_TBL_INC 0x10
|
||||
+
|
||||
+#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
|
||||
+#define PPE_EG_VSI_COUNTER_TBL_INC 0x10
|
||||
+
|
||||
+/* Port TX counters. */
|
||||
+#define PPE_PORT_TX_COUNTER_TBL_ADDR 0x45000
|
||||
+#define PPE_PORT_TX_COUNTER_TBL_ENTRIES 8
|
||||
+#define PPE_PORT_TX_COUNTER_TBL_INC 0x10
|
||||
+
|
||||
+/* Virtual port TX counters. */
|
||||
+#define PPE_VPORT_TX_COUNTER_TBL_ADDR 0x47000
|
||||
+#define PPE_VPORT_TX_COUNTER_TBL_ENTRIES 256
|
||||
+#define PPE_VPORT_TX_COUNTER_TBL_INC 0x10
|
||||
+
|
||||
+/* Queue counters. */
|
||||
+#define PPE_QUEUE_TX_COUNTER_TBL_ADDR 0x4a000
|
||||
+#define PPE_QUEUE_TX_COUNTER_TBL_ENTRIES 300
|
||||
+#define PPE_QUEUE_TX_COUNTER_TBL_INC 0x10
|
||||
+
|
||||
/* RSS settings are to calculate the random RSS hash value generated during
|
||||
* packet receive to ARM cores. This hash is then used to generate the queue
|
||||
* offset used to determine the queue used to transmit the packet to ARM cores.
|
||||
@@ -213,6 +246,51 @@
|
||||
#define PPE_L2_PORT_SET_DST_INFO(tbl_cfg, value) \
|
||||
u32p_replace_bits((u32 *)tbl_cfg, value, PPE_L2_VP_PORT_W0_DST_INFO)
|
||||
|
||||
+/* Port RX and RX drop counters. */
|
||||
+#define PPE_PORT_RX_CNT_TBL_ADDR 0x150000
|
||||
+#define PPE_PORT_RX_CNT_TBL_ENTRIES 256
|
||||
+#define PPE_PORT_RX_CNT_TBL_INC 0x20
|
||||
+
|
||||
+/* Physical port RX and RX drop counters. */
|
||||
+#define PPE_PHY_PORT_RX_CNT_TBL_ADDR 0x156000
|
||||
+#define PPE_PHY_PORT_RX_CNT_TBL_ENTRIES 8
|
||||
+#define PPE_PHY_PORT_RX_CNT_TBL_INC 0x20
|
||||
+
|
||||
+/* Counters for the packet to CPU port. */
|
||||
+#define PPE_DROP_CPU_CNT_TBL_ADDR 0x160000
|
||||
+#define PPE_DROP_CPU_CNT_TBL_ENTRIES 1280
|
||||
+#define PPE_DROP_CPU_CNT_TBL_INC 0x10
|
||||
+
|
||||
+/* VLAN counters. */
|
||||
+#define PPE_VLAN_CNT_TBL_ADDR 0x178000
|
||||
+#define PPE_VLAN_CNT_TBL_ENTRIES 64
|
||||
+#define PPE_VLAN_CNT_TBL_INC 0x10
|
||||
+
|
||||
+/* PPE L2 counters. */
|
||||
+#define PPE_PRE_L2_CNT_TBL_ADDR 0x17c000
|
||||
+#define PPE_PRE_L2_CNT_TBL_ENTRIES 64
|
||||
+#define PPE_PRE_L2_CNT_TBL_INC 0x20
|
||||
+
|
||||
+/* Port TX drop counters. */
|
||||
+#define PPE_PORT_TX_DROP_CNT_TBL_ADDR 0x17d000
|
||||
+#define PPE_PORT_TX_DROP_CNT_TBL_ENTRIES 8
|
||||
+#define PPE_PORT_TX_DROP_CNT_TBL_INC 0x10
|
||||
+
|
||||
+/* Virtual port TX counters. */
|
||||
+#define PPE_VPORT_TX_DROP_CNT_TBL_ADDR 0x17e000
|
||||
+#define PPE_VPORT_TX_DROP_CNT_TBL_ENTRIES 256
|
||||
+#define PPE_VPORT_TX_DROP_CNT_TBL_INC 0x10
|
||||
+
|
||||
+/* Counters for the tunnel packet. */
|
||||
+#define PPE_TPR_PKT_CNT_TBL_ADDR 0x1d0080
|
||||
+#define PPE_TPR_PKT_CNT_TBL_ENTRIES 8
|
||||
+#define PPE_TPR_PKT_CNT_TBL_INC 4
|
||||
+
|
||||
+/* Counters for the all packet received. */
|
||||
+#define PPE_IPR_PKT_CNT_TBL_ADDR 0x1e0080
|
||||
+#define PPE_IPR_PKT_CNT_TBL_ENTRIES 8
|
||||
+#define PPE_IPR_PKT_CNT_TBL_INC 4
|
||||
+
|
||||
/* PPE service code configuration for the tunnel packet. */
|
||||
#define PPE_TL_SERVICE_TBL_ADDR 0x306000
|
||||
#define PPE_TL_SERVICE_TBL_ENTRIES 256
|
||||
@@ -325,6 +403,18 @@
|
||||
#define PPE_BM_PORT_GROUP_ID_INC 0x4
|
||||
#define PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID GENMASK(1, 0)
|
||||
|
||||
+/* Counters for PPE buffers used for packets cached. */
|
||||
+#define PPE_BM_USED_CNT_TBL_ADDR 0x6001c0
|
||||
+#define PPE_BM_USED_CNT_TBL_ENTRIES 15
|
||||
+#define PPE_BM_USED_CNT_TBL_INC 0x4
|
||||
+#define PPE_BM_USED_CNT_VAL GENMASK(10, 0)
|
||||
+
|
||||
+/* Counters for PPE buffers used for packets received after pause frame sent. */
|
||||
+#define PPE_BM_REACT_CNT_TBL_ADDR 0x600240
|
||||
+#define PPE_BM_REACT_CNT_TBL_ENTRIES 15
|
||||
+#define PPE_BM_REACT_CNT_TBL_INC 0x4
|
||||
+#define PPE_BM_REACT_CNT_VAL GENMASK(8, 0)
|
||||
+
|
||||
#define PPE_BM_SHARED_GROUP_CFG_ADDR 0x600290
|
||||
#define PPE_BM_SHARED_GROUP_CFG_ENTRIES 4
|
||||
#define PPE_BM_SHARED_GROUP_CFG_INC 0x4
|
||||
@@ -449,6 +539,18 @@
|
||||
#define PPE_AC_GRP_SET_BUF_LIMIT(tbl_cfg, value) \
|
||||
u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_AC_GRP_W1_BUF_LIMIT)
|
||||
|
||||
+/* Counters for packets handled by unicast queues (0-255). */
|
||||
+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_ADDR 0x84e000
|
||||
+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_ENTRIES 256
|
||||
+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_INC 0x10
|
||||
+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_PEND_CNT GENMASK(12, 0)
|
||||
+
|
||||
+/* Counters for packets handled by multicast queues (256-299). */
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_ADDR 0x852000
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_ENTRIES 44
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_INC 0x10
|
||||
+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_PEND_CNT GENMASK(12, 0)
|
||||
+
|
||||
/* Table addresses for per-queue enqueue setting. */
|
||||
#define PPE_ENQ_OPR_TBL_ADDR 0x85c000
|
||||
#define PPE_ENQ_OPR_TBL_ENTRIES 300
|
||||
Loading…
Reference in New Issue
Block a user