* Re: [PATCH V4 0/7] PCI: imx6: Integrate pwrctrl API and update device trees
From: Frank.Li @ 2026-06-30 15:31 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, s.hauer, kernel, festevam, lpieralisi,
kwilczynski, mani, bhelgaas, hongxing.zhu, l.stach,
Sherry Sun (OSS)
Cc: Frank Li, imx, linux-pci, linux-arm-kernel, devicetree,
linux-kernel, sherry.sun
In-Reply-To: <20260630060710.3294811-1-sherry.sun@oss.nxp.com>
From: Frank Li <Frank.Li@nxp.com>
On Tue, 30 Jun 2026 14:07:03 +0800, Sherry Sun (OSS) wrote:
> From: Sherry Sun <sherry.sun@nxp.com>
>
> This series integrates the PCI pwrctrl framework into the pci-imx6
> driver and updates i.MX EVK board device trees to support it.
>
> Patches 2-8 update device trees for i.MX EVK boards which maintained
> by NXP to move power supply properties from the PCIe controller node
> to the Root Port child node, which is required for pwrctrl framework.
> Affected boards:
> - i.MX6Q/DL SABRESD
> - i.MX6SX SDB
> - i.MX8MM EVK
> - i.MX8MP EVK
> - i.MX8MQ EVK
> - i.MX8DXL/QM/QXP EVK
> - i.MX95 15x15/19x19 EVK
>
> [...]
Applied, thanks!
[1/7] arm: dts: imx6qdl-sabresd: Move power supply property to Root Port node
commit: b16fded592305f04ae40764f5fa91d5ac6f02a65
[2/7] arm: dts: imx6sx-sdb: Move power supply property to Root Port node
commit: a1af6cf5a6ce526ea41d4686fa14580a48b2e768
[3/7] arm64: dts: imx8mm-evk: Move power supply property to Root Port node
commit: b6a38d70bcbf0893ce5493f3daf0cb19e5102269
[4/7] arm64: dts: imx8mp-evk: Move power supply properties to Root Port node
commit: fde093c386a64c820a704abaab9ffd9ec738cd4d
[5/7] arm64: dts: imx8mq-evk: Move power supply properties to Root Port node
commit: 78610987333b0811a456f9a4782472fad00f4a19
[6/7] arm64: dts: imx8dxl/qm/qxp: Move power supply properties to Root Port node
commit: 240950f3ad76761066ffe399f62670321c1be1f1
[7/7] arm64: dts: imx95: Move power supply properties to Root Port node
commit: 6e53e8b854bc6f8330d07905b73e53ad02aff62b
Best regards,
--
Frank Li <Frank.Li@nxp.com>
^ permalink raw reply
* Re: [PATCH 2/3] arm64: dts: socfpga: agilex5: Add SoCDK TSN Config2 board
From: Andrew Lunn @ 2026-06-30 15:25 UTC (permalink / raw)
To: Nazle Asmade, Muhammad Nazim Amirul
Cc: dinguyen@kernel.org, maxime.chevallier@bootlin.com,
rmk+kernel@armlinux.org.uk, krzk+dt@kernel.org,
conor+dt@kernel.org, robh@kernel.org, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
andrew+netdev@lunn.ch, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <347c50ed-234a-4f29-b63a-1e0010c6b09d@altera.com>
On Tue, Jun 30, 2026 at 02:39:50PM +0000, Nazle Asmade, Muhammad Nazim Amirul wrote:
> On 30/6/2026 9:58 pm, Andrew Lunn wrote:
> >> + * gmac1 is the TSN port. The MAC operates in GMII mode internally
> >> + * while the PHY-side interface is RGMII, so mac-mode and phy-mode differ.
> >> + */
> >> +&gmac1 {
> >> + status = "okay";
> >> + phy-mode = "rgmii"; /* TX/RX clock delays provided by Agilex5 I/O hardware */
> > Could you provide more details about this. I want to understand the
> > big picture.
> >
> > Normally we talk about the PCB providing the delays. This sounds like
> > it is the FPGA? So i need convincing this is correct.
> Hi Andrew,
>
> Thanks for your quick review and yes, it is the FPGA — specifically a
> soft IP block in the FPGA fabric that implements the RGMII clock delays
> and is configured before Linux boots via the FPGA bitstream. The driver
> must not add additional delays on top.
So it depends on how the converter block is described, but ....
From a big picture, MAC and PHY pair, it is the MAC which
implements the delays.
https://elixir.bootlin.com/linux/v6.15/source/Documentation/devicetree/bindings/net/ethernet-controller.yaml#L346
# There are a small number of cases where the MAC has hard coded
# delays which cannot be disabled. The 'phy-mode' only describes the
# PCB. The inability to disable the delays in the MAC does not change
# the meaning of 'phy-mode'. It does however mean that a 'phy-mode' of
# 'rgmii' is now invalid, it cannot be supported, since both the PCB
# and the MAC and PHY adding delays cannot result in a functional
# link. Thus the MAC should report a fatal error for any modes which
# cannot be supported. When the MAC implements the delay, it must
# ensure that the PHY does not also implement the same delay. So it
# must modify the phy-mode it passes to the PHY, removing the delay it
# has added. Failure to remove the delay will result in a
# non-functioning link.
Andrew
---
pw-bot: cr
^ permalink raw reply
* Re: [PATCH v12 1/6] pinctrl: s32cc: add/fix some comments
From: Frank Li @ 2026-06-30 15:24 UTC (permalink / raw)
To: Khristine Andreea Barbulescu
Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chester Lin, Matthias Brugger,
Ghennadi Procopciuc, Larisa Grigore, Lee Jones, Shawn Guo,
Sascha Hauer, Fabio Estevam, Dong Aisheng, Jacky Bai,
Greg Kroah-Hartman, Rafael J. Wysocki, Srinivas Kandagatla,
Alberto Ruiz, Christophe Lizzi, devicetree, Enric Balletbo,
Eric Chanudet, imx, linux-arm-kernel, linux-gpio, linux-kernel,
NXP S32 Linux Team, Pengutronix Kernel Team, Vincent Guittot
In-Reply-To: <20260630125403.546375-2-khristineandreea.barbulescu@oss.nxp.com>
On Tue, Jun 30, 2026 at 02:53:58PM +0200, Khristine Andreea Barbulescu wrote:
> Add/fix some comments and print statements.
>
> Reviewed-by: Linus Walleij <linusw@kernel.org>
> Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> Signed-off-by: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>
> Signed-off-by: Khristine Andreea Barbulescu <khristineandreea.barbulescu@oss.nxp.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/pinctrl/nxp/pinctrl-s32cc.c | 20 ++++++++++++++------
> 1 file changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
> index 56be6e8d624e..2a32df932d8a 100644
> --- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
> +++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
> @@ -60,6 +60,12 @@ static u32 get_pin_func(u32 pinmux)
> return pinmux & GENMASK(3, 0);
> }
>
> +/*
> + * struct s32_pinctrl_mem_region - memory region for a set of SIUL2 registers
> + * @map: regmap used for this range
> + * @pin_range: the pins controlled by these registers
> + * @name: name of the current range
> + */
> struct s32_pinctrl_mem_region {
> struct regmap *map;
> const struct s32_pin_range *pin_range;
> @@ -67,7 +73,7 @@ struct s32_pinctrl_mem_region {
> };
>
> /*
> - * Holds pin configuration for GPIO's.
> + * struct gpio_pin_config - holds pin configuration for GPIO's
> * @pin_id: Pin ID for this GPIO
> * @config: Pin settings
> * @list: Linked list entry for each gpio pin
> @@ -79,20 +85,22 @@ struct gpio_pin_config {
> };
>
> /*
> - * Pad config save/restore for power suspend/resume.
> + * struct s32_pinctrl_context - pad config save/restore for suspend/resume
> + * @pads: saved values for the pards
> */
> struct s32_pinctrl_context {
> unsigned int *pads;
> };
>
> /*
> + * struct s32_pinctrl - private driver data
> * @dev: a pointer back to containing device
> * @pctl: a pointer to the pinctrl device structure
> * @regions: reserved memory regions with start/end pin
> * @info: structure containing information about the pin
> - * @gpio_configs: Saved configurations for GPIO pins
> - * @gpiop_configs_lock: lock for the `gpio_configs` list
> - * @s32_pinctrl_context: Configuration saved over system sleep
> + * @gpio_configs: saved configurations for GPIO pins
> + * @gpio_configs_lock: lock for the `gpio_configs` list
> + * @saved_context: configuration saved over system sleep
> */
> struct s32_pinctrl {
> struct device *dev;
> @@ -970,7 +978,7 @@ int s32_pinctrl_probe(struct platform_device *pdev,
> ipctl);
> if (IS_ERR(ipctl->pctl))
> return dev_err_probe(&pdev->dev, PTR_ERR(ipctl->pctl),
> - "could not register s32 pinctrl driver\n");
> + "Could not register s32 pinctrl driver\n");
>
> #ifdef CONFIG_PM_SLEEP
> saved_context = &ipctl->saved_context;
> --
> 2.34.1
>
>
^ permalink raw reply
* Re: (subset) [PATCH v7 0/3] Add root port reset to support link recovery
From: Manivannan Sadhasivam @ 2026-06-30 14:18 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, s.hauer, kernel, festevam, hongxing.zhu
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel
In-Reply-To: <20260618092100.3669556-1-hongxing.zhu@oss.nxp.com>
On Thu, 18 Jun 2026 17:20:57 +0800, hongxing.zhu@oss.nxp.com wrote:
> Based on the following patch-set[1] issued by Mani.
> Add support for resetting the Root Port for i.MX PCIe to enable link recovery.
>
> [1] [PATCH v8 0/5] PCI: Add support for resetting the Root Ports in a platform specific way
>
> PCIe links can go down due to various unexpected circumstances. This patch series
> adds root port reset support for link recovery on i.MX PCIe controllers when the
> optional "intr" interrupt is present.
>
> [...]
Applied, thanks!
[1/3] dt-bindings: imx6q-pcie: Add optional intr/aer/pme interrupts for i.MX95
commit: 7186ac21201a9a408ae80fcbb9c985c959b3febc
Best regards,
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH v12 2/6] pinctrl: s32cc: remove inline specifiers
From: Frank Li @ 2026-06-30 15:22 UTC (permalink / raw)
To: Khristine Andreea Barbulescu
Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chester Lin, Matthias Brugger,
Ghennadi Procopciuc, Larisa Grigore, Lee Jones, Shawn Guo,
Sascha Hauer, Fabio Estevam, Dong Aisheng, Jacky Bai,
Greg Kroah-Hartman, Rafael J. Wysocki, Srinivas Kandagatla,
Alberto Ruiz, Christophe Lizzi, devicetree, Enric Balletbo,
Eric Chanudet, imx, linux-arm-kernel, linux-gpio, linux-kernel,
NXP S32 Linux Team, Pengutronix Kernel Team, Vincent Guittot
In-Reply-To: <20260630125403.546375-3-khristineandreea.barbulescu@oss.nxp.com>
On Tue, Jun 30, 2026 at 02:53:59PM +0200, Khristine Andreea Barbulescu wrote:
> Remove unnecessary inline specifiers from static functions.
>
> Reviewed-by: Linus Walleij <linusw@kernel.org>
> Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> Signed-off-by: Andrei Stefanescu <andrei.stefanescu@oss.nxp.com>
> Signed-off-by: Khristine Andreea Barbulescu <khristineandreea.barbulescu@oss.nxp.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/pinctrl/nxp/pinctrl-s32cc.c | 14 +++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
> index 2a32df932d8a..8c5ec6a76a1f 100644
> --- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
> +++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
> @@ -131,13 +131,13 @@ s32_get_region(struct pinctrl_dev *pctldev, unsigned int pin)
> return NULL;
> }
>
> -static inline int s32_check_pin(struct pinctrl_dev *pctldev,
> - unsigned int pin)
> +static int s32_check_pin(struct pinctrl_dev *pctldev,
> + unsigned int pin)
> {
> return s32_get_region(pctldev, pin) ? 0 : -EINVAL;
> }
>
> -static inline int s32_regmap_read(struct pinctrl_dev *pctldev,
> +static int s32_regmap_read(struct pinctrl_dev *pctldev,
> unsigned int pin, unsigned int *val)
> {
> struct s32_pinctrl_mem_region *region;
> @@ -153,7 +153,7 @@ static inline int s32_regmap_read(struct pinctrl_dev *pctldev,
> return regmap_read(region->map, offset, val);
> }
>
> -static inline int s32_regmap_write(struct pinctrl_dev *pctldev,
> +static int s32_regmap_write(struct pinctrl_dev *pctldev,
> unsigned int pin,
> unsigned int val)
> {
> @@ -171,7 +171,7 @@ static inline int s32_regmap_write(struct pinctrl_dev *pctldev,
>
> }
>
> -static inline int s32_regmap_update(struct pinctrl_dev *pctldev, unsigned int pin,
> +static int s32_regmap_update(struct pinctrl_dev *pctldev, unsigned int pin,
> unsigned int mask, unsigned int val)
> {
> struct s32_pinctrl_mem_region *region;
> @@ -484,8 +484,8 @@ static int s32_get_slew_regval(int arg)
> return -EINVAL;
> }
>
> -static inline void s32_pin_set_pull(enum pin_config_param param,
> - unsigned int *mask, unsigned int *config)
> +static void s32_pin_set_pull(enum pin_config_param param,
> + unsigned int *mask, unsigned int *config)
> {
> switch (param) {
> case PIN_CONFIG_BIAS_DISABLE:
> --
> 2.34.1
>
>
^ permalink raw reply
* [PATCH 5/5] perf/arm-cmn: Support CMN S3 r2
From: Robin Murphy @ 2026-06-30 15:19 UTC (permalink / raw)
To: will, mark.rutland; +Cc: linux-arm-kernel, linux-perf-users, ilkka
In-Reply-To: <cover.1782830759.git.robin.murphy@arm.com>
If you were disappointed at how minimal the initial CMN S3 support
looked compared to previous versions, then oh boy is it time to put your
party hats on... The biggest batch of incompatible changes yet comes not
with a new CMN product, but a point release of an existing one. We've
got new filters, loads of changes to existing events, register fields
moved around for no good reason, and much, much more! On the upside, we
do at least gain a means of working around the isolation feature.
As such, for the sake of sanity in the driver it is easiest to split it
into a distict "model" for our internal abstractions despite it bearing
the same part number as r0/r1.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/perf/arm-cmn.c | 270 +++++++++++++++++++++++++++++------------
1 file changed, 193 insertions(+), 77 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index c935ddcf462a..a03e2a8ca41e 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -29,6 +29,7 @@
#define CMN_CI_CHILD_PTR_OFFSET GENMASK_ULL(31, 16)
#define CMN_CHILD_NODE_ADDR GENMASK(29, 0)
+#define CMN_CHILD_NODE_ISOLATED BIT(30)
#define CMN_CHILD_NODE_EXTERNAL BIT(31)
/* Some implementations use a mesh larger than the architectural max of 12 */
@@ -48,11 +49,16 @@
#define CMN_CFGM_INFO_GLOBAL 0x0900
#define CMN_INFO_MULTIPLE_DTM_EN BIT_ULL(63)
+#define CMN_S3_R2_MULTIPLE_DTM_EN BIT_ULL(59)
#define CMN_INFO_RSP_VC_NUM GENMASK_ULL(53, 52)
#define CMN_INFO_DAT_VC_NUM GENMASK_ULL(51, 50)
#define CMN_INFO_DEVICE_ISO_ENABLE BIT_ULL(44)
#define CMN_CFGM_INFO_GLOBAL_1 0x0908
+#define CMN_S3_R2_RSP_VC_NUM GENMASK_ULL(11, 9)
+#define CMN_S3_R2_DAT_VC_NUM GENMASK_ULL(8, 6)
+#define CMN_S3_R2_SNP_VC_NUM GENMASK_ULL(5, 3)
+#define CMN_S3_R2_REQ_VC_NUM GENMASK_ULL(2, 0)
#define CMN_INFO_SNP_VC_NUM GENMASK_ULL(3, 2)
#define CMN_INFO_REQ_VC_NUM GENMASK_ULL(1, 0)
@@ -78,6 +84,16 @@
/* Technically this is 4 bits wide on DNs, but we only use 2 there anyway */
#define CMN__PMU_OCCUP1_ID GENMASK_ULL(34, 32)
+/* But then... */
+#define CMN__PMU_EVICT_STATE_SEL GENMASK_ULL(54, 52)
+#define CMN__PMU_ENHANCED_HBT_LBT_SEL GENMASK_ULL(51, 48)
+#define CMN__PMU_SNP_VC_SEL GENMASK_ULL(47, 46)
+#define CMN__S3_R2_CBUSY_SNTHROTTLE_SEL GENMASK_ULL(45, 42)
+#define CMN__S3_R2_SN_HOME_SEL GENMASK_ULL(41, 40)
+#define CMN__S3_R2_HBT_LBT_SEL GENMASK_ULL(39, 38)
+#define CMN__S3_R2_CLASS_OCCUP_ID GENMASK_ULL(37, 36)
+#define CMN__S3_R2_OCCUP1_ID GENMASK_ULL(35, 32)
+
/* Some types are designed to coexist with another device in the same node */
#define CMN_CCLA_PMU_EVENT_SEL 0x008
#define CMN_HNP_PMU_EVENT_SEL 0x008
@@ -202,12 +218,14 @@ enum cmn_model {
CMN650 = 2,
CI700 = 4,
CMN700 = 8,
- CMNS3 = 16,
+ CMNS3R01 = 16,
+ CMNS3R2 = 32,
/* ...and then we can use bitmap tricks for commonality */
CMN_ANY = -1,
NOT_CMN600 = -2,
CMN_700ON = ~(CMN700 - 1),
CMN_650ON = CMN_700ON | CMN650,
+ CMNS3 = CMNS3R01 | CMNS3R2,
};
/* Actual part numbers and revision IDs defined by the hardware */
@@ -243,6 +261,10 @@ enum cmn_revision {
REV_CMNS3_R0P0 = 0,
REV_CMNS3_R0P1,
REV_CMNS3_R1P0,
+ REV_CMNS3_R2P0,
+ REV_CMNS3_R2P1,
+ REV_CMNS3_R2P2,
+ REV_CMNS3_R2P5,
REV_CI700_R0P0 = 0,
REV_CI700_R1P0,
REV_CI700_R2P0,
@@ -429,7 +451,9 @@ static enum cmn_model arm_cmn_model(const struct arm_cmn *cmn)
case PART_CI700:
return CI700;
case PART_CMN_S3:
- return CMNS3;
+ if (cmn->rev >= REV_CMNS3_R2P0)
+ return CMNS3R2;
+ return CMNS3R01;
default:
return 0;
};
@@ -609,8 +633,10 @@ enum cmn_filter_type {
FILT_OCCUP1_ID,
FILT_HNF_700,
FILT_HNS,
+ FILT_HNS_S3R2,
};
#define CMN_FILTER(_sel) [SEL_##_sel] = CMN__PMU_##_sel
+#define CMN_FILTER_V2(_sel) [SEL_##_sel] = CMN__S3_R2_##_sel
static const u64 arm_cmn_filters[][SEL_MAX] = {
[FILT_NONE] = {},
@@ -632,6 +658,17 @@ static const u64 arm_cmn_filters[][SEL_MAX] = {
CMN_FILTER(HBT_LBT_SEL),
CMN_FILTER(SN_HOME_SEL)
},
+ /* Newer HN-S */
+ [FILT_HNS_S3R2] = {
+ CMN_FILTER_V2(OCCUP1_ID),
+ CMN_FILTER_V2(CLASS_OCCUP_ID),
+ CMN_FILTER_V2(CBUSY_SNTHROTTLE_SEL),
+ CMN_FILTER_V2(HBT_LBT_SEL),
+ CMN_FILTER_V2(SN_HOME_SEL),
+ CMN_FILTER(SNP_VC_SEL),
+ CMN_FILTER(ENHANCED_HBT_LBT_SEL),
+ CMN_FILTER(EVICT_STATE_SEL)
+ }
};
static enum cmn_filter_type arm_cmn_filter(enum cmn_node_type node,
@@ -651,7 +688,9 @@ static enum cmn_filter_type arm_cmn_filter(enum cmn_node_type node,
return FILT_OCCUP1_ID;
return FILT_HNF_700;
case CMN_TYPE_HNS:
- return FILT_HNS;
+ if (model < CMNS3R2)
+ return FILT_HNS;
+ return FILT_HNS_S3R2;
};
}
@@ -732,7 +771,7 @@ struct arm_cmn_event_attr {
enum cmn_model model;
enum cmn_node_type type;
u16 eventid;
- struct arm_cmn_filter_attr filter[1];
+ struct arm_cmn_filter_attr filter[2];
};
struct arm_cmn_format_attr {
@@ -741,16 +780,16 @@ struct arm_cmn_format_attr {
int config;
};
-#define _CMN_EVENT_ATTR(_model, _name, _type, _eventid, _filter, ...) \
+#define _CMN_EVENT_ATTR(_model, _name, _type, _eventid, _fa, _fb, _fc, _fd, ...) \
(&((struct arm_cmn_event_attr[]) {{ \
.attr = __ATTR(_name, 0444, arm_cmn_event_show, NULL), \
.model = _model, \
.type = _type, \
.eventid = _eventid, \
- .filter = {{_filter}}, \
+ .filter = {{_fa, _fb}, {_fc, _fd}}, \
}})[0].attr.attr)
#define CMN_EVENT_ATTR(_model, _name, _type, _eventid, _filter...) \
- _CMN_EVENT_ATTR(_model, _name, _type, _eventid, ##_filter, 0, 0)
+ _CMN_EVENT_ATTR(_model, _name, _type, _eventid, ##_filter, 0, 0, 0, 0)
static ssize_t arm_cmn_event_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -769,6 +808,10 @@ static ssize_t arm_cmn_event_show(struct device *dev,
"type=0x%x,eventid=0x%x,wp_dev_sel=?,wp_chn_sel=?,wp_grp=?,wp_val=?,wp_mask=?\n",
eattr->type, eattr->eventid);
+ if (filter[1].sel)
+ return sysfs_emit(buf, "type=0x%x,eventid=0x%x,filter=0x%x,filter2=0x%x\n",
+ eattr->type, eattr->eventid, filter[0].val, filter[1].val);
+
if (filter[0].sel)
return sysfs_emit(buf, "type=0x%x,eventid=0x%x,filter=0x%x\n",
eattr->type, eattr->eventid, filter[0].val);
@@ -887,8 +930,8 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
CMN_EVENT_ATTR(_model, ccha_##_name, CMN_TYPE_CCHA, _event)
#define CMN_EVENT_CCLA(_name, _event) \
CMN_EVENT_ATTR(CMN_ANY, ccla_##_name, CMN_TYPE_CCLA, _event)
-#define CMN_EVENT_HNS(_name, _event) \
- CMN_EVENT_ATTR(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event)
+#define _CMN_EVENT_HNS(_model, _name, _event, _filter...) \
+ CMN_EVENT_ATTR(_model, hns_##_name, CMN_TYPE_HNS, _event, ##_filter)
#define CMN_EVENT_DVM_OCC(_model, _name, _event) \
CMN_EVENT_DVM(_model, _name##_all, _event, SEL_OCCUP1_ID, 0), \
@@ -913,7 +956,12 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
CMN_EVENT_ATTR(_model, _name##_group1_read, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 3), \
CMN_EVENT_ATTR(_model, _name##_group1_write, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 4), \
CMN_EVENT_ATTR(_model, _name##_read, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 5), \
- CMN_EVENT_ATTR(_model, _name##_write, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 6)
+ CMN_EVENT_ATTR(_model, _name##_write, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 6), \
+ CMN_EVENT_ATTR(CMNS3R2, _name##_ccg_read, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 9), \
+ CMN_EVENT_ATTR(CMNS3R2, _name##_ccg_write, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 10), \
+ CMN_EVENT_ATTR(CMNS3R2, _name##_lbt_read, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 11), \
+ CMN_EVENT_ATTR(CMNS3R2, _name##_lbt_write, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 12), \
+ CMN_EVENT_ATTR(CMNS3R2, _name##_lbt, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 13)
#define CMN_EVENT_HNF_OCC(_model, _name, _event) \
CMN_EVENT_HN_OCC(_model, hnf_##_name, CMN_TYPE_HNF, _event)
@@ -922,23 +970,75 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
#define CMN_EVENT_HNF_SNT(_model, _name, _event) \
CMN_EVENT_HN_SNT(_model, hnf_##_name, CMN_TYPE_HNF, _event)
-#define CMN_EVENT_HNS_OCC(_name, _event) \
- CMN_EVENT_HN_OCC(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event), \
- CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_rxsnp, CMN_TYPE_HNS, _event, SEL_OCCUP1_ID, 5), \
- CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_lbt, CMN_TYPE_HNS, _event, SEL_OCCUP1_ID, 6), \
- CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_hbt, CMN_TYPE_HNS, _event, SEL_OCCUP1_ID, 7)
+#define CMN_EVENT_HNS(_name, _event) \
+ _CMN_EVENT_HNS(CMN_ANY, _name, _event)
+#define CMN_EVENT_HNSR0(_name, _event) \
+ _CMN_EVENT_HNS(CMN700 | CMNS3R01, _name, _event)
+#define _CMN_EVENT_HNS_HBT(_model, _name, _event, _sel) \
+ _CMN_EVENT_HNS(_model, _name##_all, _event, _sel, 0), \
+ _CMN_EVENT_HNS(_model, _name##_hbt, _event, _sel, 1), \
+ _CMN_EVENT_HNS(_model, _name##_lbt, _event, _sel, 2)
+#define _CMN_EVENT_HNS_HBT2(_model, _name, _event, _fsel1, f1) \
+ _CMN_EVENT_HNS(_model, _name##_all, _event, _fsel1, f1, SEL_HBT_LBT_SEL, 0), \
+ _CMN_EVENT_HNS(_model, _name##_hbt, _event, _fsel1, f1, SEL_HBT_LBT_SEL, 1), \
+ _CMN_EVENT_HNS(_model, _name##_lbt, _event, _fsel1, f1, SEL_HBT_LBT_SEL, 2)
+
+#define CMN_EVENT_HNS_OCC(_model, _name, _event) \
+ CMN_EVENT_HN_OCC(_model, hns_##_name, CMN_TYPE_HNS, _event), \
+ _CMN_EVENT_HNS(_model, _name##_rxsnp, _event, SEL_OCCUP1_ID, 5), \
+ _CMN_EVENT_HNS(_model, _name##_lbt, _event, SEL_OCCUP1_ID, 6), \
+ _CMN_EVENT_HNS(_model, _name##_hbt, _event, SEL_OCCUP1_ID, 7), \
+ _CMN_EVENT_HNS(CMNS3R2, _name##_rnf, _event, SEL_OCCUP1_ID, 8), \
+ _CMN_EVENT_HNS(CMNS3R2, _name##_rni, _event, SEL_OCCUP1_ID, 9), \
+ _CMN_EVENT_HNS(CMNS3R2, _name##_ccglcn, _event, SEL_OCCUP1_ID, 10), \
+ _CMN_EVENT_HNS(CMNS3R2, _name##_ccgrn, _event, SEL_OCCUP1_ID, 11)
#define CMN_EVENT_HNS_CLS( _name, _event) \
CMN_EVENT_HN_CLS(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event)
-#define CMN_EVENT_HNS_SNT(_name, _event) \
- CMN_EVENT_HN_SNT(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event)
-#define CMN_EVENT_HNS_HBT(_name, _event) \
- CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_all, CMN_TYPE_HNS, _event, SEL_HBT_LBT_SEL, 0), \
- CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_hbt, CMN_TYPE_HNS, _event, SEL_HBT_LBT_SEL, 1), \
- CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_lbt, CMN_TYPE_HNS, _event, SEL_HBT_LBT_SEL, 2)
-#define CMN_EVENT_HNS_SNH(_name, _event) \
- CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_all, CMN_TYPE_HNS, _event, SEL_SN_HOME_SEL, 0), \
- CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_sn, CMN_TYPE_HNS, _event, SEL_SN_HOME_SEL, 1), \
- CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_home, CMN_TYPE_HNS, _event, SEL_SN_HOME_SEL, 2)
+#define CMN_EVENT_HNSR0_CLS( _name, _event) \
+ CMN_EVENT_HN_CLS(CMN700 | CMNS3R01, hns_##_name, CMN_TYPE_HNS, _event)
+#define CMN_EVENT_HNS_SNT(_model, _name, _event) \
+ CMN_EVENT_HN_SNT(_model, hns_##_name, CMN_TYPE_HNS, _event)
+#define CMN_EVENT_HNS_SNH(_model, _name, _event) \
+ _CMN_EVENT_HNS(_model, _name##_all, _event, SEL_SN_HOME_SEL, 0), \
+ _CMN_EVENT_HNS(_model, _name##_sn, _event, SEL_SN_HOME_SEL, 1), \
+ _CMN_EVENT_HNS(_model, _name##_home, _event, SEL_SN_HOME_SEL, 2)
+#define CMN_EVENT_HNS_VC(_name, _event) \
+ CMN_EVENT_HNSR0(_name, _event), \
+ _CMN_EVENT_HNS(CMNS3R2, _name##_vc0, _event, SEL_SNP_VC_SEL, 0), \
+ _CMN_EVENT_HNS(CMNS3R2, _name##_vc1, _event, SEL_SNP_VC_SEL, 1), \
+ _CMN_EVENT_HNS(CMNS3R2, _name##_vc2, _event, SEL_SNP_VC_SEL, 2)
+#define CMN_EVENT_HNS_ENHBT(_name, _event) \
+ _CMN_EVENT_HNS_HBT(CMNS3R2, _name, _event, SEL_ENHANCED_HBT_LBT_SEL), \
+ _CMN_EVENT_HNS(CMNS3R2, _name##_rnf, _event, SEL_ENHANCED_HBT_LBT_SEL, 3), \
+ _CMN_EVENT_HNS(CMNS3R2, _name##_rni, _event, SEL_ENHANCED_HBT_LBT_SEL, 4), \
+ _CMN_EVENT_HNS(CMNS3R2, _name##_ccglcn, _event, SEL_ENHANCED_HBT_LBT_SEL, 5), \
+ _CMN_EVENT_HNS(CMNS3R2, _name##_ccgrn, _event, SEL_ENHANCED_HBT_LBT_SEL, 6)
+#define CMN_EVENT_HNS_EVICT(_model, _name, _event) \
+ _CMN_EVENT_HNS_HBT2(_model, _name##_all, _event, SEL_EVICT_STATE_SEL, 0), \
+ _CMN_EVENT_HNS_HBT2(_model, _name##_eu, _event, SEL_EVICT_STATE_SEL, 1), \
+ _CMN_EVENT_HNS_HBT2(_model, _name##_en, _event, SEL_EVICT_STATE_SEL, 2), \
+ _CMN_EVENT_HNS_HBT2(_model, _name##_su, _event, SEL_EVICT_STATE_SEL, 3), \
+ _CMN_EVENT_HNS_HBT2(_model, _name##_sn, _event, SEL_EVICT_STATE_SEL, 4), \
+ _CMN_EVENT_HNS_HBT2(_model, _name##_mu, _event, SEL_EVICT_STATE_SEL, 5), \
+ _CMN_EVENT_HNS_HBT2(_model, _name##_mn, _event, SEL_EVICT_STATE_SEL, 6)
+
+#define CMN_EVENT_HNSR0_HBT(_name, _event) \
+ _CMN_EVENT_HNS_HBT(CMN700 | CMNS3R01, _name, _event, SEL_HBT_LBT_SEL)
+#define CMN_EVENT_HNS_R2SNH(_name, _event) \
+ CMN_EVENT_HNSR0(_name, _event), \
+ CMN_EVENT_HNS_SNH(CMNS3R2, _name, _event)
+#define CMN_EVENT_HNS_R2HBT(_name, _event) \
+ CMN_EVENT_HNSR0(_name, _event), \
+ _CMN_EVENT_HNS_HBT(CMNS3R2, _name, _event, SEL_HBT_LBT_SEL)
+#define CMN_EVENT_HNS_HBT_ENHBT(_name, _event) \
+ CMN_EVENT_HNSR0_HBT(_name, _event), \
+ CMN_EVENT_HNS_ENHBT(_name, _event)
+#define CMN_EVENT_HNS_HBT_OCC(_name, _event) \
+ CMN_EVENT_HNSR0_HBT(_name, _event), \
+ CMN_EVENT_HNS_OCC(CMNS3R2, _name, _event)
+#define CMN_EVENT_HNS_HBT_EVICT(_name, _event) \
+ CMN_EVENT_HNSR0_HBT(_name, _event), \
+ CMN_EVENT_HNS_EVICT(CMNS3R2, _name, _event)
#define _CMN_EVENT_XP_MESH(_name, _event) \
__CMN_EVENT_XP(e_##_name, (_event) | (0 << 2)), \
@@ -1288,65 +1388,72 @@ static struct attribute *arm_cmn_event_attrs[] = {
CMN_EVENT_CCLA(pfwd_sndr_stalls_static_crd, 0x2a),
CMN_EVENT_CCLA(pfwd_sndr_stalls_dynmaic_crd, 0x2b),
- CMN_EVENT_HNS_HBT(cache_miss, 0x01),
- CMN_EVENT_HNS_HBT(slc_sf_cache_access, 0x02),
- CMN_EVENT_HNS_HBT(cache_fill, 0x03),
- CMN_EVENT_HNS_HBT(pocq_retry, 0x04),
- CMN_EVENT_HNS_HBT(pocq_reqs_recvd, 0x05),
- CMN_EVENT_HNS_HBT(sf_hit, 0x06),
- CMN_EVENT_HNS_HBT(sf_evictions, 0x07),
- CMN_EVENT_HNS(dir_snoops_sent, 0x08),
- CMN_EVENT_HNS(brd_snoops_sent, 0x09),
- CMN_EVENT_HNS_HBT(slc_eviction, 0x0a),
- CMN_EVENT_HNS_HBT(slc_fill_invalid_way, 0x0b),
- CMN_EVENT_HNS(mc_retries_local, 0x0c),
- CMN_EVENT_HNS_SNH(mc_reqs_local, 0x0d),
+ CMN_EVENT_HNS_HBT_ENHBT(cache_miss, 0x01),
+ CMN_EVENT_HNS_HBT_ENHBT(slc_sf_cache_access, 0x02),
+ CMN_EVENT_HNS_HBT_ENHBT(cache_fill, 0x03),
+ CMN_EVENT_HNS_HBT_OCC(pocq_retry, 0x04),
+ CMN_EVENT_HNS_HBT_OCC(pocq_reqs_recvd, 0x05),
+ CMN_EVENT_HNS_HBT_ENHBT(sf_hit, 0x06),
+ CMN_EVENT_HNS_HBT_EVICT(sf_evictions, 0x07),
+ CMN_EVENT_HNS_VC(dir_snoops_sent, 0x08),
+ CMN_EVENT_HNS_VC(brd_snoops_sent, 0x09),
+ CMN_EVENT_HNS_HBT_EVICT(slc_eviction, 0x0a),
+ CMN_EVENT_HNS_HBT_ENHBT(slc_fill_invalid_way, 0x0b),
+ CMN_EVENT_HNS_R2SNH(mc_retries_local, 0x0c),
+ CMN_EVENT_HNS_SNH(CMN_ANY, mc_reqs_local, 0x0d),
CMN_EVENT_HNS(qos_hh_retry, 0x0e),
- CMN_EVENT_HNS_OCC(qos_pocq_occupancy, 0x0f),
- CMN_EVENT_HNS(pocq_addrhaz, 0x10),
- CMN_EVENT_HNS(pocq_atomic_addrhaz, 0x11),
- CMN_EVENT_HNS(ld_st_swp_adq_full, 0x12),
- CMN_EVENT_HNS(cmp_adq_full, 0x13),
+ CMN_EVENT_HNS_OCC(CMN_ANY, qos_pocq_occupancy, 0x0f),
+ CMN_EVENT_HNS_HBT_ENHBT(pocq_addrhaz, 0x10),
+ CMN_EVENT_HNS_HBT_ENHBT(pocq_atomic_addrhaz, 0x11),
+ CMN_EVENT_HNSR0(ld_st_swp_adq_full, 0x12),
+ CMN_EVENT_HNSR0(cmp_adq_full, 0x13),
CMN_EVENT_HNS(txdat_stall, 0x14),
CMN_EVENT_HNS(txrsp_stall, 0x15),
- CMN_EVENT_HNS(seq_full, 0x16),
+ CMN_EVENT_HNSR0(seq_full, 0x16),
CMN_EVENT_HNS(seq_hit, 0x17),
- CMN_EVENT_HNS(snp_sent, 0x18),
- CMN_EVENT_HNS(sfbi_dir_snp_sent, 0x19),
- CMN_EVENT_HNS(sfbi_brd_snp_sent, 0x1a),
+ CMN_EVENT_HNS_VC(snp_sent, 0x18),
+ CMN_EVENT_HNS_VC(sfbi_dir_snp_sent, 0x19),
+ CMN_EVENT_HNS_VC(sfbi_brd_snp_sent, 0x1a),
CMN_EVENT_HNS(intv_dirty, 0x1c),
- CMN_EVENT_HNS(stash_snp_sent, 0x1d),
- CMN_EVENT_HNS(stash_data_pull, 0x1e),
- CMN_EVENT_HNS(snp_fwded, 0x1f),
- CMN_EVENT_HNS(atomic_fwd, 0x20),
+ CMN_EVENT_HNSR0(stash_snp_sent, 0x1d),
+ CMN_EVENT_HNSR0(stash_data_pull, 0x1e),
+ CMN_EVENT_HNS_VC(snp_fwded, 0x1f),
+ CMN_EVENT_HNSR0(atomic_fwd, 0x20),
CMN_EVENT_HNS(mpam_hardlim, 0x21),
CMN_EVENT_HNS(mpam_softlim, 0x22),
- CMN_EVENT_HNS(snp_sent_cluster, 0x23),
- CMN_EVENT_HNS(sf_imprecise_evict, 0x24),
+ CMN_EVENT_HNS_VC(snp_sent_cluster, 0x23),
+ CMN_EVENT_HNS_R2HBT(sf_imprecise_evict, 0x24),
CMN_EVENT_HNS(sf_evict_shared_line, 0x25),
CMN_EVENT_HNS_CLS(pocq_class_occup, 0x26),
CMN_EVENT_HNS_CLS(pocq_class_retry, 0x27),
CMN_EVENT_HNS_CLS(class_mc_reqs_local, 0x28),
- CMN_EVENT_HNS_CLS(class_cgnt_cmin, 0x29),
- CMN_EVENT_HNS_SNT(sn_throttle, 0x2a),
- CMN_EVENT_HNS_SNT(sn_throttle_min, 0x2b),
+ CMN_EVENT_HNSR0_CLS(class_cgnt_cmin, 0x29),
+ CMN_EVENT_HNS_SNT(CMN_ANY, sn_throttle, 0x2a),
+ CMN_EVENT_HNS_SNT(CMN_ANY, sn_throttle_min, 0x2b),
CMN_EVENT_HNS(sf_precise_to_imprecise, 0x2c),
CMN_EVENT_HNS(snp_intv_cln, 0x2d),
CMN_EVENT_HNS(nc_excl, 0x2e),
- CMN_EVENT_HNS(excl_mon_ovfl, 0x2f),
+ CMN_EVENT_HNSR0(excl_mon_ovfl, 0x2f),
CMN_EVENT_HNS(snp_req_recvd, 0x30),
CMN_EVENT_HNS(snp_req_byp_pocq, 0x31),
CMN_EVENT_HNS(dir_ccgha_snp_sent, 0x32),
CMN_EVENT_HNS(brd_ccgha_snp_sent, 0x33),
- CMN_EVENT_HNS(ccgha_snp_stall, 0x34),
+ CMN_EVENT_HNSR0(ccgha_snp_stall, 0x34),
CMN_EVENT_HNS(lbt_req_hardlim, 0x35),
CMN_EVENT_HNS(hbt_req_hardlim, 0x36),
CMN_EVENT_HNS(sf_reupdate, 0x37),
- CMN_EVENT_HNS(excl_sf_imprecise, 0x38),
+ CMN_EVENT_HNS_R2HBT(excl_sf_imprecise, 0x38),
CMN_EVENT_HNS(snp_pocq_addrhaz, 0x39),
- CMN_EVENT_HNS(mc_retries_remote, 0x3a),
- CMN_EVENT_HNS_SNH(mc_reqs_remote, 0x3b),
+ CMN_EVENT_HNS_R2SNH(mc_retries_remote, 0x3a),
+ CMN_EVENT_HNS_SNH(CMN_ANY, mc_reqs_remote, 0x3b),
CMN_EVENT_HNS_CLS(class_mc_reqs_remote, 0x3c),
+ CMN_EVENT_HNS_ENHBT(readonce_hazard_detected, 0x3d),
+ CMN_EVENT_HNS_ENHBT(readonce_fwd_data_completed, 0x3e),
+ CMN_EVENT_HNS_SNT(CMNS3R2, cbusy00, 0x40),
+ CMN_EVENT_HNS_SNT(CMNS3R2, cbusy01, 0x41),
+ CMN_EVENT_HNS_SNT(CMNS3R2, cbusy10, 0x42),
+ CMN_EVENT_HNS_SNT(CMNS3R2, cbusy11, 0x43),
+ CMN_EVENT_HNS_ENHBT(ro_rnsd_new_alloc_hint, 0x44),
NULL
};
@@ -2431,21 +2538,33 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
/*
* With the device isolation feature, if firmware has neglected to enable
* an XP port then we risk locking up if we try to access anything behind
- * it; however we also have no way to tell from Non-Secure whether any
- * given port is disabled or not, so the only way to win is not to play...
+ * it; however prior to CMN S3 r2p0 we also have no way to tell from
+ * Non-Secure whether any given port is disabled or not, so in that case
+ * the only way to win is not to play...
*/
reg = readq_relaxed(cfg_region + CMN_CFGM_INFO_GLOBAL);
- if (reg & CMN_INFO_DEVICE_ISO_ENABLE) {
+ if (reg & CMN_INFO_DEVICE_ISO_ENABLE && model == CMNS3R01) {
dev_err(cmn->dev, "Device isolation enabled, not continuing due to risk of lockup\n");
return -ENODEV;
}
- cmn->multi_dtm = reg & CMN_INFO_MULTIPLE_DTM_EN;
- cmn->rsp_vc_num = FIELD_GET(CMN_INFO_RSP_VC_NUM, reg);
- cmn->dat_vc_num = FIELD_GET(CMN_INFO_DAT_VC_NUM, reg);
+ if (model < CMNS3R2) {
+ cmn->multi_dtm = reg & CMN_INFO_MULTIPLE_DTM_EN;
+ cmn->rsp_vc_num = FIELD_GET(CMN_INFO_RSP_VC_NUM, reg);
+ cmn->dat_vc_num = FIELD_GET(CMN_INFO_DAT_VC_NUM, reg);
+ } else {
+ cmn->multi_dtm = reg & CMN_S3_R2_MULTIPLE_DTM_EN;
+ }
reg = readq_relaxed(cfg_region + CMN_CFGM_INFO_GLOBAL_1);
- cmn->snp_vc_num = FIELD_GET(CMN_INFO_SNP_VC_NUM, reg);
- cmn->req_vc_num = FIELD_GET(CMN_INFO_REQ_VC_NUM, reg);
+ if (model < CMNS3R2) {
+ cmn->snp_vc_num = FIELD_GET(CMN_INFO_SNP_VC_NUM, reg);
+ cmn->req_vc_num = FIELD_GET(CMN_INFO_REQ_VC_NUM, reg);
+ } else {
+ cmn->rsp_vc_num = FIELD_GET(CMN_S3_R2_RSP_VC_NUM, reg);
+ cmn->dat_vc_num = FIELD_GET(CMN_S3_R2_DAT_VC_NUM, reg);
+ cmn->snp_vc_num = FIELD_GET(CMN_S3_R2_SNP_VC_NUM, reg);
+ cmn->req_vc_num = FIELD_GET(CMN_S3_R2_REQ_VC_NUM, reg);
+ }
reg = readq_relaxed(cfg_region + CMN_CHILD_INFO);
child_count = FIELD_GET(CMN_CI_CHILD_COUNT, reg);
@@ -2545,15 +2664,12 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
reg = readq_relaxed(xp_region + child_poff + j * 8);
/*
* Don't even try to touch anything external, since in general
- * we haven't a clue how to power up arbitrary CHI requesters.
- * As of CMN-600r1 these could only be RN-SAMs or CXLAs,
- * neither of which have any PMU events anyway.
- * (Actually, CXLAs do seem to have grown some events in r1p2,
- * but they don't go to regular XP DTMs, and they depend on
- * secure configuration which we can't easily deal with)
+ * we haven't a clue how to power up arbitrary CHI requesters,
+ * and none of them have standard PMU events anyway. Isolated
+ * nodes effectively just do not exist at all from our PoV.
*/
- if (reg & CMN_CHILD_NODE_EXTERNAL) {
- dev_dbg(cmn->dev, "ignoring external node %llx\n", reg);
+ if (reg & (CMN_CHILD_NODE_EXTERNAL | CMN_CHILD_NODE_ISOLATED)) {
+ dev_dbg(cmn->dev, "ignoring external/isolated node %llx\n", reg);
continue;
}
/*
--
2.54.0.dirty
^ permalink raw reply related
* [PATCH 4/5] perf/arm-cmn: Add new filters
From: Robin Murphy @ 2026-06-30 15:19 UTC (permalink / raw)
To: will, mark.rutland; +Cc: linux-arm-kernel, linux-perf-users, ilkka
In-Reply-To: <cover.1782830759.git.robin.murphy@arm.com>
Add the logic to handle events with the upcoming new filter controls.
Since for now we will have the sole invariant of all EVICT_STATE_SEL
events having HBT_LBT_SEL as a secondary filter, for the sake of
simplicity we can just special-case that, and save the complication
of a full abstraction until unavoidably necessary.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/perf/arm-cmn.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 4ba78df87045..c935ddcf462a 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -166,12 +166,14 @@
#define CMN_CONFIG_FILTER GENMASK_ULL(30, 27)
#define CMN_CONFIG_BYNODEID BIT_ULL(31)
#define CMN_CONFIG_NODEID GENMASK_ULL(47, 32)
+#define CMN_CONFIG_FILTER2 GENMASK_ULL(51, 48)
#define CMN_EVENT_TYPE(event) FIELD_GET(CMN_CONFIG_TYPE, (event)->attr.config)
#define CMN_EVENT_EVENTID(event) FIELD_GET(CMN_CONFIG_EVENTID, (event)->attr.config)
#define CMN_EVENT_FILTER(event) FIELD_GET(CMN_CONFIG_FILTER, (event)->attr.config)
#define CMN_EVENT_BYNODEID(event) FIELD_GET(CMN_CONFIG_BYNODEID, (event)->attr.config)
#define CMN_EVENT_NODEID(event) FIELD_GET(CMN_CONFIG_NODEID, (event)->attr.config)
+#define CMN_EVENT_FILTER2(event) FIELD_GET(CMN_CONFIG_FILTER2, (event)->attr.config)
#define CMN_CONFIG_WP_COMBINE GENMASK_ULL(30, 27)
#define CMN_CONFIG_WP_DEV_SEL GENMASK_ULL(50, 48)
@@ -284,6 +286,9 @@ enum cmn_filter_select {
SEL_CBUSY_SNTHROTTLE_SEL,
SEL_HBT_LBT_SEL,
SEL_SN_HOME_SEL,
+ SEL_SNP_VC_SEL,
+ SEL_ENHANCED_HBT_LBT_SEL,
+ SEL_EVICT_STATE_SEL,
SEL_MAX
};
@@ -1377,6 +1382,7 @@ static struct attribute *arm_cmn_format_attrs[] = {
CMN_FORMAT_ATTR(filter, CMN_CONFIG_FILTER),
CMN_FORMAT_ATTR(bynodeid, CMN_CONFIG_BYNODEID),
CMN_FORMAT_ATTR(nodeid, CMN_CONFIG_NODEID),
+ CMN_FORMAT_ATTR(filter2, CMN_CONFIG_FILTER2),
CMN_FORMAT_ATTR(wp_dev_sel, CMN_CONFIG_WP_DEV_SEL),
CMN_FORMAT_ATTR(wp_chn_sel, CMN_CONFIG_WP_CHN_SEL),
@@ -1745,6 +1751,8 @@ static void arm_cmn_val_add_event(struct arm_cmn *cmn, struct arm_cmn_val *val,
if (sel)
val->filter[dtm][sel] = CMN_EVENT_FILTER(event) + 1;
+ if (sel == SEL_EVICT_STATE_SEL)
+ val->filter[dtm][SEL_HBT_LBT_SEL] = CMN_EVENT_FILTER2(event) + 1;
if (type != CMN_TYPE_WP)
continue;
@@ -1799,6 +1807,10 @@ static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event)
val->filter[dtm][sel] != CMN_EVENT_FILTER(event) + 1)
goto done;
+ if (sel == SEL_EVICT_STATE_SEL && val->filter[dtm][SEL_HBT_LBT_SEL] &&
+ val->filter[dtm][SEL_HBT_LBT_SEL] != CMN_EVENT_FILTER2(event) + 1)
+ goto done;
+
if (type != CMN_TYPE_WP)
continue;
@@ -1943,6 +1955,8 @@ static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
if (hw->filter_sel)
hw->dn[i].filter[hw->filter_sel].count--;
+ if (hw->filter_sel == SEL_EVICT_STATE_SEL)
+ hw->dn[i].filter[SEL_HBT_LBT_SEL].count--;
dtm->pmu_config_low &= ~CMN__PMEVCNT_PAIRED(dtm_idx);
writel_relaxed(dtm->pmu_config_low, dtm->base + CMN_DTM_PMU_CONFIG);
@@ -1961,6 +1975,11 @@ static int arm_cmn_set_event_filter(struct arm_cmn_node *dn, struct perf_event *
if (fsel)
ret = arm_cmn_set_event_sel_hi(dn, fsel, CMN_EVENT_FILTER(event));
+ if (fsel == SEL_EVICT_STATE_SEL && !ret) {
+ ret = arm_cmn_set_event_sel_hi(dn, SEL_HBT_LBT_SEL, CMN_EVENT_FILTER2(event));
+ if (ret)
+ dn->filter[fsel].count--;
+ }
return ret;
}
--
2.54.0.dirty
^ permalink raw reply related
* [PATCH 3/5] perf/arm-cmn: Refactor event filter data
From: Robin Murphy @ 2026-06-30 15:19 UTC (permalink / raw)
To: will, mark.rutland; +Cc: linux-arm-kernel, linux-perf-users, ilkka
In-Reply-To: <cover.1782830759.git.robin.murphy@arm.com>
The ABI hole I have dug myself into requires the driver to know which
event encodings are associated with which particular filter control.
Since we will soon have a notion of multiple filters per event, refactor
the event data to encapsulate filters in an explicit structure, which
can then more easily scale as an array in future.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/perf/arm-cmn.c | 95 ++++++++++++++++++++++--------------------
1 file changed, 49 insertions(+), 46 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 14c267d2e2f9..4ba78df87045 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -717,13 +717,17 @@ static void arm_cmn_clear_idx(struct arm_cmn_hw_event *hw)
bitmap_zero(hw->wp_idx, CMN_MAX_XPS);
}
+struct arm_cmn_filter_attr {
+ enum cmn_filter_select sel;
+ u8 val;
+};
+
struct arm_cmn_event_attr {
struct device_attribute attr;
enum cmn_model model;
enum cmn_node_type type;
- enum cmn_filter_select fsel;
u16 eventid;
- u8 filter;
+ struct arm_cmn_filter_attr filter[1];
};
struct arm_cmn_format_attr {
@@ -732,24 +736,25 @@ struct arm_cmn_format_attr {
int config;
};
-#define _CMN_EVENT_ATTR(_model, _name, _type, _eventid, _filter, _fsel)\
+#define _CMN_EVENT_ATTR(_model, _name, _type, _eventid, _filter, ...) \
(&((struct arm_cmn_event_attr[]) {{ \
.attr = __ATTR(_name, 0444, arm_cmn_event_show, NULL), \
.model = _model, \
.type = _type, \
.eventid = _eventid, \
- .filter = _filter, \
- .fsel = _fsel, \
+ .filter = {{_filter}}, \
}})[0].attr.attr)
-#define CMN_EVENT_ATTR(_model, _name, _type, _eventid) \
- _CMN_EVENT_ATTR(_model, _name, _type, _eventid, 0, SEL_NONE)
+#define CMN_EVENT_ATTR(_model, _name, _type, _eventid, _filter...) \
+ _CMN_EVENT_ATTR(_model, _name, _type, _eventid, ##_filter, 0, 0)
static ssize_t arm_cmn_event_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct arm_cmn_event_attr *eattr;
+ struct arm_cmn_filter_attr *filter;
eattr = container_of(attr, typeof(*eattr), attr);
+ filter = eattr->filter;
if (eattr->type == CMN_TYPE_DTC)
return sysfs_emit(buf, "type=0x%x\n", eattr->type);
@@ -759,9 +764,9 @@ static ssize_t arm_cmn_event_show(struct device *dev,
"type=0x%x,eventid=0x%x,wp_dev_sel=?,wp_chn_sel=?,wp_grp=?,wp_val=?,wp_mask=?\n",
eattr->type, eattr->eventid);
- if (eattr->fsel)
+ if (filter[0].sel)
return sysfs_emit(buf, "type=0x%x,eventid=0x%x,filter=0x%x\n",
- eattr->type, eattr->eventid, eattr->filter);
+ eattr->type, eattr->eventid, filter[0].val);
return sysfs_emit(buf, "type=0x%x,eventid=0x%x\n", eattr->type,
eattr->eventid);
@@ -849,8 +854,8 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
return attr->mode;
}
-#define _CMN_EVENT_DVM(_model, _name, _event, _occup, _fsel) \
- _CMN_EVENT_ATTR(_model, dn_##_name, CMN_TYPE_DVM, _event, _occup, _fsel)
+#define CMN_EVENT_DVM(_model, _name, _event, _filter...) \
+ CMN_EVENT_ATTR(_model, dn_##_name, CMN_TYPE_DVM, _event, ##_filter)
#define CMN_EVENT_DTC(_name) \
CMN_EVENT_ATTR(CMN_ANY, dtc_##_name, CMN_TYPE_DTC, 0)
#define CMN_EVENT_HNF(_model, _name, _event) \
@@ -880,32 +885,30 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
#define CMN_EVENT_HNS(_name, _event) \
CMN_EVENT_ATTR(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event)
-#define CMN_EVENT_DVM(_model, _name, _event) \
- _CMN_EVENT_DVM(_model, _name, _event, 0, SEL_NONE)
#define CMN_EVENT_DVM_OCC(_model, _name, _event) \
- _CMN_EVENT_DVM(_model, _name##_all, _event, 0, SEL_OCCUP1_ID), \
- _CMN_EVENT_DVM(_model, _name##_dvmop, _event, 1, SEL_OCCUP1_ID), \
- _CMN_EVENT_DVM(_model, _name##_dvmsync, _event, 2, SEL_OCCUP1_ID)
+ CMN_EVENT_DVM(_model, _name##_all, _event, SEL_OCCUP1_ID, 0), \
+ CMN_EVENT_DVM(_model, _name##_dvmop, _event, SEL_OCCUP1_ID, 1), \
+ CMN_EVENT_DVM(_model, _name##_dvmsync, _event, SEL_OCCUP1_ID, 2)
#define CMN_EVENT_HN_OCC(_model, _name, _type, _event) \
- _CMN_EVENT_ATTR(_model, _name##_all, _type, _event, 0, SEL_OCCUP1_ID), \
- _CMN_EVENT_ATTR(_model, _name##_read, _type, _event, 1, SEL_OCCUP1_ID), \
- _CMN_EVENT_ATTR(_model, _name##_write, _type, _event, 2, SEL_OCCUP1_ID), \
- _CMN_EVENT_ATTR(_model, _name##_atomic, _type, _event, 3, SEL_OCCUP1_ID), \
- _CMN_EVENT_ATTR(_model, _name##_stash, _type, _event, 4, SEL_OCCUP1_ID)
+ CMN_EVENT_ATTR(_model, _name##_all, _type, _event, SEL_OCCUP1_ID, 0), \
+ CMN_EVENT_ATTR(_model, _name##_read, _type, _event, SEL_OCCUP1_ID, 1), \
+ CMN_EVENT_ATTR(_model, _name##_write, _type, _event, SEL_OCCUP1_ID, 2), \
+ CMN_EVENT_ATTR(_model, _name##_atomic, _type, _event, SEL_OCCUP1_ID, 3), \
+ CMN_EVENT_ATTR(_model, _name##_stash, _type, _event, SEL_OCCUP1_ID, 4)
#define CMN_EVENT_HN_CLS(_model, _name, _type, _event) \
- _CMN_EVENT_ATTR(_model, _name##_class0, _type, _event, 0, SEL_CLASS_OCCUP_ID), \
- _CMN_EVENT_ATTR(_model, _name##_class1, _type, _event, 1, SEL_CLASS_OCCUP_ID), \
- _CMN_EVENT_ATTR(_model, _name##_class2, _type, _event, 2, SEL_CLASS_OCCUP_ID), \
- _CMN_EVENT_ATTR(_model, _name##_class3, _type, _event, 3, SEL_CLASS_OCCUP_ID)
+ CMN_EVENT_ATTR(_model, _name##_class0, _type, _event, SEL_CLASS_OCCUP_ID, 0), \
+ CMN_EVENT_ATTR(_model, _name##_class1, _type, _event, SEL_CLASS_OCCUP_ID, 1), \
+ CMN_EVENT_ATTR(_model, _name##_class2, _type, _event, SEL_CLASS_OCCUP_ID, 2), \
+ CMN_EVENT_ATTR(_model, _name##_class3, _type, _event, SEL_CLASS_OCCUP_ID, 3)
#define CMN_EVENT_HN_SNT(_model, _name, _type, _event) \
- _CMN_EVENT_ATTR(_model, _name##_all, _type, _event, 0, SEL_CBUSY_SNTHROTTLE_SEL), \
- _CMN_EVENT_ATTR(_model, _name##_group0_read, _type, _event, 1, SEL_CBUSY_SNTHROTTLE_SEL), \
- _CMN_EVENT_ATTR(_model, _name##_group0_write, _type, _event, 2, SEL_CBUSY_SNTHROTTLE_SEL), \
- _CMN_EVENT_ATTR(_model, _name##_group1_read, _type, _event, 3, SEL_CBUSY_SNTHROTTLE_SEL), \
- _CMN_EVENT_ATTR(_model, _name##_group1_write, _type, _event, 4, SEL_CBUSY_SNTHROTTLE_SEL), \
- _CMN_EVENT_ATTR(_model, _name##_read, _type, _event, 5, SEL_CBUSY_SNTHROTTLE_SEL), \
- _CMN_EVENT_ATTR(_model, _name##_write, _type, _event, 6, SEL_CBUSY_SNTHROTTLE_SEL)
+ CMN_EVENT_ATTR(_model, _name##_all, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 0), \
+ CMN_EVENT_ATTR(_model, _name##_group0_read, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 1), \
+ CMN_EVENT_ATTR(_model, _name##_group0_write, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 2), \
+ CMN_EVENT_ATTR(_model, _name##_group1_read, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 3), \
+ CMN_EVENT_ATTR(_model, _name##_group1_write, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 4), \
+ CMN_EVENT_ATTR(_model, _name##_read, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 5), \
+ CMN_EVENT_ATTR(_model, _name##_write, _type, _event, SEL_CBUSY_SNTHROTTLE_SEL, 6)
#define CMN_EVENT_HNF_OCC(_model, _name, _event) \
CMN_EVENT_HN_OCC(_model, hnf_##_name, CMN_TYPE_HNF, _event)
@@ -916,21 +919,21 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
#define CMN_EVENT_HNS_OCC(_name, _event) \
CMN_EVENT_HN_OCC(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event), \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_rxsnp, CMN_TYPE_HNS, _event, 5, SEL_OCCUP1_ID), \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_lbt, CMN_TYPE_HNS, _event, 6, SEL_OCCUP1_ID), \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_hbt, CMN_TYPE_HNS, _event, 7, SEL_OCCUP1_ID)
+ CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_rxsnp, CMN_TYPE_HNS, _event, SEL_OCCUP1_ID, 5), \
+ CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_lbt, CMN_TYPE_HNS, _event, SEL_OCCUP1_ID, 6), \
+ CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_hbt, CMN_TYPE_HNS, _event, SEL_OCCUP1_ID, 7)
#define CMN_EVENT_HNS_CLS( _name, _event) \
CMN_EVENT_HN_CLS(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event)
#define CMN_EVENT_HNS_SNT(_name, _event) \
CMN_EVENT_HN_SNT(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event)
#define CMN_EVENT_HNS_HBT(_name, _event) \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_all, CMN_TYPE_HNS, _event, 0, SEL_HBT_LBT_SEL), \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_hbt, CMN_TYPE_HNS, _event, 1, SEL_HBT_LBT_SEL), \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_lbt, CMN_TYPE_HNS, _event, 2, SEL_HBT_LBT_SEL)
+ CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_all, CMN_TYPE_HNS, _event, SEL_HBT_LBT_SEL, 0), \
+ CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_hbt, CMN_TYPE_HNS, _event, SEL_HBT_LBT_SEL, 1), \
+ CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_lbt, CMN_TYPE_HNS, _event, SEL_HBT_LBT_SEL, 2)
#define CMN_EVENT_HNS_SNH(_name, _event) \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_all, CMN_TYPE_HNS, _event, 0, SEL_SN_HOME_SEL), \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_sn, CMN_TYPE_HNS, _event, 1, SEL_SN_HOME_SEL), \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_home, CMN_TYPE_HNS, _event, 2, SEL_SN_HOME_SEL)
+ CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_all, CMN_TYPE_HNS, _event, SEL_SN_HOME_SEL, 0), \
+ CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_sn, CMN_TYPE_HNS, _event, SEL_SN_HOME_SEL, 1), \
+ CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_home, CMN_TYPE_HNS, _event, SEL_SN_HOME_SEL, 2)
#define _CMN_EVENT_XP_MESH(_name, _event) \
__CMN_EVENT_XP(e_##_name, (_event) | (0 << 2)), \
@@ -1814,9 +1817,9 @@ static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event)
return ret;
}
-static enum cmn_filter_select arm_cmn_filter_sel(const struct arm_cmn *cmn,
- enum cmn_node_type type,
- unsigned int eventid)
+static enum cmn_filter_select arm_cmn_event_filter(const struct arm_cmn *cmn,
+ enum cmn_node_type type,
+ unsigned int eventid)
{
struct arm_cmn_event_attr *e;
enum cmn_model model = arm_cmn_model(cmn);
@@ -1824,7 +1827,7 @@ static enum cmn_filter_select arm_cmn_filter_sel(const struct arm_cmn *cmn,
for (int i = 0; i < ARRAY_SIZE(arm_cmn_event_attrs) - 1; i++) {
e = container_of(arm_cmn_event_attrs[i], typeof(*e), attr.attr);
if (e->model & model && e->type == type && e->eventid == eventid)
- return e->fsel;
+ return e->filter[0].sel;
}
return SEL_NONE;
}
@@ -1889,7 +1892,7 @@ static int arm_cmn_event_init(struct perf_event *event)
}
/* This is sufficiently annoying to recalculate, so cache it */
- hw->filter_sel = arm_cmn_filter_sel(cmn, type, eventid);
+ hw->filter_sel = arm_cmn_event_filter(cmn, type, eventid);
bynodeid = CMN_EVENT_BYNODEID(event);
nodeid = CMN_EVENT_NODEID(event);
--
2.54.0.dirty
^ permalink raw reply related
* [PATCH 2/5] perf/arm-cmn: Refactor event filter programming
From: Robin Murphy @ 2026-06-30 15:19 UTC (permalink / raw)
To: will, mark.rutland; +Cc: linux-arm-kernel, linux-perf-users, ilkka
In-Reply-To: <cover.1782830759.git.robin.murphy@arm.com>
We're soon going to need to cope with events having multiple filters,
plus the filter fields themselves moving around, wherein any more inline
if/else logic will struggle to scale. Add a more general abstraction for
the node-specific filter controls, and rejig the pmu_event_sel filter
programming around it in a more extensible manner.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/perf/arm-cmn.c | 139 ++++++++++++++++++++++++++++++-----------
1 file changed, 101 insertions(+), 38 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 2a8a67da72c3..14c267d2e2f9 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -278,8 +278,8 @@ enum cmn_node_type {
};
enum cmn_filter_select {
- SEL_NONE = -1,
- SEL_OCCUP1ID,
+ SEL_NONE,
+ SEL_OCCUP1_ID,
SEL_CLASS_OCCUP_ID,
SEL_CBUSY_SNTHROTTLE_SEL,
SEL_HBT_LBT_SEL,
@@ -599,6 +599,57 @@ static void arm_cmn_debugfs_init(struct arm_cmn *cmn, int id)
static void arm_cmn_debugfs_init(struct arm_cmn *cmn, int id) {}
#endif
+enum cmn_filter_type {
+ FILT_NONE,
+ FILT_OCCUP1_ID,
+ FILT_HNF_700,
+ FILT_HNS,
+};
+#define CMN_FILTER(_sel) [SEL_##_sel] = CMN__PMU_##_sel
+
+static const u64 arm_cmn_filters[][SEL_MAX] = {
+ [FILT_NONE] = {},
+ /* DVM etc. */
+ [FILT_OCCUP1_ID] = {
+ CMN_FILTER(OCCUP1_ID)
+ },
+ /* Newer HN-F */
+ [FILT_HNF_700] = {
+ CMN_FILTER(OCCUP1_ID),
+ CMN_FILTER(CLASS_OCCUP_ID),
+ CMN_FILTER(CBUSY_SNTHROTTLE_SEL)
+ },
+ /* HN-S */
+ [FILT_HNS] = {
+ CMN_FILTER(OCCUP1_ID),
+ CMN_FILTER(CLASS_OCCUP_ID),
+ CMN_FILTER(CBUSY_SNTHROTTLE_SEL),
+ CMN_FILTER(HBT_LBT_SEL),
+ CMN_FILTER(SN_HOME_SEL)
+ },
+};
+
+static enum cmn_filter_type arm_cmn_filter(enum cmn_node_type node,
+ enum cmn_model model)
+{
+ switch (node) {
+ default:
+ return FILT_NONE;
+ case CMN_TYPE_DVM:
+ case CMN_TYPE_CXRA:
+ case CMN_TYPE_CXHA:
+ case CMN_TYPE_CCRA:
+ case CMN_TYPE_CCHA:
+ return FILT_OCCUP1_ID;
+ case CMN_TYPE_HNF:
+ if (model < CMN700)
+ return FILT_OCCUP1_ID;
+ return FILT_HNF_700;
+ case CMN_TYPE_HNS:
+ return FILT_HNS;
+ };
+}
+
struct arm_cmn_hw_event {
struct arm_cmn_node *dn;
union {
@@ -708,7 +759,7 @@ static ssize_t arm_cmn_event_show(struct device *dev,
"type=0x%x,eventid=0x%x,wp_dev_sel=?,wp_chn_sel=?,wp_grp=?,wp_val=?,wp_mask=?\n",
eattr->type, eattr->eventid);
- if (eattr->fsel > SEL_NONE)
+ if (eattr->fsel)
return sysfs_emit(buf, "type=0x%x,eventid=0x%x,filter=0x%x\n",
eattr->type, eattr->eventid, eattr->filter);
@@ -832,16 +883,16 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
#define CMN_EVENT_DVM(_model, _name, _event) \
_CMN_EVENT_DVM(_model, _name, _event, 0, SEL_NONE)
#define CMN_EVENT_DVM_OCC(_model, _name, _event) \
- _CMN_EVENT_DVM(_model, _name##_all, _event, 0, SEL_OCCUP1ID), \
- _CMN_EVENT_DVM(_model, _name##_dvmop, _event, 1, SEL_OCCUP1ID), \
- _CMN_EVENT_DVM(_model, _name##_dvmsync, _event, 2, SEL_OCCUP1ID)
+ _CMN_EVENT_DVM(_model, _name##_all, _event, 0, SEL_OCCUP1_ID), \
+ _CMN_EVENT_DVM(_model, _name##_dvmop, _event, 1, SEL_OCCUP1_ID), \
+ _CMN_EVENT_DVM(_model, _name##_dvmsync, _event, 2, SEL_OCCUP1_ID)
#define CMN_EVENT_HN_OCC(_model, _name, _type, _event) \
- _CMN_EVENT_ATTR(_model, _name##_all, _type, _event, 0, SEL_OCCUP1ID), \
- _CMN_EVENT_ATTR(_model, _name##_read, _type, _event, 1, SEL_OCCUP1ID), \
- _CMN_EVENT_ATTR(_model, _name##_write, _type, _event, 2, SEL_OCCUP1ID), \
- _CMN_EVENT_ATTR(_model, _name##_atomic, _type, _event, 3, SEL_OCCUP1ID), \
- _CMN_EVENT_ATTR(_model, _name##_stash, _type, _event, 4, SEL_OCCUP1ID)
+ _CMN_EVENT_ATTR(_model, _name##_all, _type, _event, 0, SEL_OCCUP1_ID), \
+ _CMN_EVENT_ATTR(_model, _name##_read, _type, _event, 1, SEL_OCCUP1_ID), \
+ _CMN_EVENT_ATTR(_model, _name##_write, _type, _event, 2, SEL_OCCUP1_ID), \
+ _CMN_EVENT_ATTR(_model, _name##_atomic, _type, _event, 3, SEL_OCCUP1_ID), \
+ _CMN_EVENT_ATTR(_model, _name##_stash, _type, _event, 4, SEL_OCCUP1_ID)
#define CMN_EVENT_HN_CLS(_model, _name, _type, _event) \
_CMN_EVENT_ATTR(_model, _name##_class0, _type, _event, 0, SEL_CLASS_OCCUP_ID), \
_CMN_EVENT_ATTR(_model, _name##_class1, _type, _event, 1, SEL_CLASS_OCCUP_ID), \
@@ -865,9 +916,9 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
#define CMN_EVENT_HNS_OCC(_name, _event) \
CMN_EVENT_HN_OCC(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event), \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_rxsnp, CMN_TYPE_HNS, _event, 5, SEL_OCCUP1ID), \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_lbt, CMN_TYPE_HNS, _event, 6, SEL_OCCUP1ID), \
- _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_hbt, CMN_TYPE_HNS, _event, 7, SEL_OCCUP1ID)
+ _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_rxsnp, CMN_TYPE_HNS, _event, 5, SEL_OCCUP1_ID), \
+ _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_lbt, CMN_TYPE_HNS, _event, 6, SEL_OCCUP1_ID), \
+ _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_hbt, CMN_TYPE_HNS, _event, 7, SEL_OCCUP1_ID)
#define CMN_EVENT_HNS_CLS( _name, _event) \
CMN_EVENT_HN_CLS(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event)
#define CMN_EVENT_HNS_SNT(_name, _event) \
@@ -1547,27 +1598,20 @@ static void arm_cmn_event_read(struct perf_event *event)
}
static int arm_cmn_set_event_sel_hi(struct arm_cmn_node *dn,
- enum cmn_filter_select fsel, u8 filter)
+ enum cmn_filter_select fsel, u8 val)
{
- u64 reg;
-
- if (fsel == SEL_NONE)
- return 0;
-
if (!dn->filter[fsel].count) {
- dn->filter[fsel].val = filter;
- reg = FIELD_PREP(CMN__PMU_CBUSY_SNTHROTTLE_SEL,
- dn->filter[SEL_CBUSY_SNTHROTTLE_SEL].val) |
- FIELD_PREP(CMN__PMU_SN_HOME_SEL,
- dn->filter[SEL_SN_HOME_SEL].val) |
- FIELD_PREP(CMN__PMU_HBT_LBT_SEL,
- dn->filter[SEL_HBT_LBT_SEL].val) |
- FIELD_PREP(CMN__PMU_CLASS_OCCUP_ID,
- dn->filter[SEL_CLASS_OCCUP_ID].val) |
- FIELD_PREP(CMN__PMU_OCCUP1_ID,
- dn->filter[SEL_OCCUP1ID].val);
+ const u64 *filter = arm_cmn_filters[dn->filter[SEL_NONE].val];
+ u64 reg = 0;
+
+ dn->filter[fsel].val = val;
+ for (int i = SEL_OCCUP1_ID; i < SEL_MAX; i++) {
+ if (filter[i])
+ reg |= field_prep(filter[i], dn->filter[i].val);
+ }
+
writel_relaxed(reg >> 32, dn->pmu_base + CMN_PMU_EVENT_SEL + 4);
- } else if (dn->filter[fsel].val != filter) {
+ } else if (dn->filter[fsel].val != val) {
return -EBUSY;
}
dn->filter[fsel].count++;
@@ -1696,7 +1740,7 @@ static void arm_cmn_val_add_event(struct arm_cmn *cmn, struct arm_cmn_val *val,
val->dtm_count[dtm]++;
- if (sel > SEL_NONE)
+ if (sel)
val->filter[dtm][sel] = CMN_EVENT_FILTER(event) + 1;
if (type != CMN_TYPE_WP)
@@ -1748,7 +1792,7 @@ static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event)
if (val->dtm_count[dtm] == CMN_DTM_NUM_COUNTERS)
goto done;
- if (sel > SEL_NONE && val->filter[dtm][sel] &&
+ if (sel && val->filter[dtm][sel] &&
val->filter[dtm][sel] != CMN_EVENT_FILTER(event) + 1)
goto done;
@@ -1894,7 +1938,7 @@ static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
dtm->wp_event[wp_idx] = -1;
}
- if (hw->filter_sel > SEL_NONE)
+ if (hw->filter_sel)
hw->dn[i].filter[hw->filter_sel].count--;
dtm->pmu_config_low &= ~CMN__PMEVCNT_PAIRED(dtm_idx);
@@ -1906,6 +1950,17 @@ static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
cmn->dtc[j].counters[idx] = NULL;
}
+static int arm_cmn_set_event_filter(struct arm_cmn_node *dn, struct perf_event *event)
+{
+ enum cmn_filter_select fsel = to_cmn_hw(event)->filter_sel;
+ int ret = 0;
+
+ if (fsel)
+ ret = arm_cmn_set_event_sel_hi(dn, fsel, CMN_EVENT_FILTER(event));
+
+ return ret;
+}
+
static int arm_cmn_event_add(struct perf_event *event, int flags)
{
struct arm_cmn *cmn = to_cmn(event->pmu);
@@ -1981,7 +2036,7 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
input_sel = CMN__PMEVCNT0_INPUT_SEL_DEV + dtm_idx +
(nid.port << 4) + (nid.dev << 2);
- if (arm_cmn_set_event_sel_hi(dn, hw->filter_sel, CMN_EVENT_FILTER(event)))
+ if (arm_cmn_set_event_filter(dn, event))
goto free_dtms;
}
@@ -2311,6 +2366,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
void __iomem *cfg_region, __iomem *xp_region;
struct arm_cmn_node cfg, *dn;
struct arm_cmn_dtm *dtm;
+ enum cmn_model model;
enum cmn_part part;
u16 child_count, child_poff;
u64 reg;
@@ -2342,12 +2398,14 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
"Firmware binding mismatch: expected part number 0x%x, found 0x%x\n",
cmn->part, part);
cmn->part = part;
- if (!arm_cmn_model(cmn))
- dev_warn(cmn->dev, "Unknown part number: 0x%x\n", part);
reg = readl_relaxed(cfg_region + CMN_CFGM_PERIPH_ID_23);
cmn->rev = FIELD_GET(CMN_CFGM_PID2_REVISION, reg);
+ model = arm_cmn_model(cmn);
+ if (!model)
+ dev_warn(cmn->dev, "Unknown part number: 0x%x\n", part);
+
/*
* With the device isolation feature, if firmware has neglected to enable
* an XP port then we risk locking up if we try to access anything behind
@@ -2500,6 +2558,11 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
dev_err(cmn->dev, "Node ID invalid for supported CMN versions: %d\n", dn->logid);
return -ENODEV;
}
+ /*
+ * We can utilise the "wasted" filter array slot to store
+ * the index for referencing the filter encodings later.
+ */
+ dn->filter[SEL_NONE].val = arm_cmn_filter(dn->type, model);
switch (dn->type) {
case CMN_TYPE_DTC:
--
2.54.0.dirty
^ permalink raw reply related
* [PATCH 1/5] perf/arm-cmn: Rename filter variables for clarity
From: Robin Murphy @ 2026-06-30 15:19 UTC (permalink / raw)
To: will, mark.rutland; +Cc: linux-arm-kernel, linux-perf-users, ilkka
In-Reply-To: <cover.1782830759.git.robin.murphy@arm.com>
CMN has already grown many more event-specific filters than the original
Occupancy ID, but since they are all independent of each other we've
just overloaded them onto the same name. Before we add yet more, and
they begin to overlap, rename all our "occupid" variables to "filter" so
that things can be a bit clearer and more consistent (but leaving the
format attribute itself, to avoid UAPI concerns).
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/perf/arm-cmn.c | 53 ++++++++++++++++++++++--------------------
1 file changed, 28 insertions(+), 25 deletions(-)
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 50402bc4a21d..2a8a67da72c3 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -163,13 +163,13 @@
/* Event attributes */
#define CMN_CONFIG_TYPE GENMASK_ULL(15, 0)
#define CMN_CONFIG_EVENTID GENMASK_ULL(26, 16)
-#define CMN_CONFIG_OCCUPID GENMASK_ULL(30, 27)
+#define CMN_CONFIG_FILTER GENMASK_ULL(30, 27)
#define CMN_CONFIG_BYNODEID BIT_ULL(31)
#define CMN_CONFIG_NODEID GENMASK_ULL(47, 32)
#define CMN_EVENT_TYPE(event) FIELD_GET(CMN_CONFIG_TYPE, (event)->attr.config)
#define CMN_EVENT_EVENTID(event) FIELD_GET(CMN_CONFIG_EVENTID, (event)->attr.config)
-#define CMN_EVENT_OCCUPID(event) FIELD_GET(CMN_CONFIG_OCCUPID, (event)->attr.config)
+#define CMN_EVENT_FILTER(event) FIELD_GET(CMN_CONFIG_FILTER, (event)->attr.config)
#define CMN_EVENT_BYNODEID(event) FIELD_GET(CMN_CONFIG_BYNODEID, (event)->attr.config)
#define CMN_EVENT_NODEID(event) FIELD_GET(CMN_CONFIG_NODEID, (event)->attr.config)
@@ -301,7 +301,7 @@ struct arm_cmn_node {
struct {
u8 val : 4;
u8 count : 4;
- } occupid[SEL_MAX];
+ } filter[SEL_MAX];
union {
u8 event[4];
__le32 event_sel;
@@ -672,7 +672,7 @@ struct arm_cmn_event_attr {
enum cmn_node_type type;
enum cmn_filter_select fsel;
u16 eventid;
- u8 occupid;
+ u8 filter;
};
struct arm_cmn_format_attr {
@@ -681,13 +681,13 @@ struct arm_cmn_format_attr {
int config;
};
-#define _CMN_EVENT_ATTR(_model, _name, _type, _eventid, _occupid, _fsel)\
+#define _CMN_EVENT_ATTR(_model, _name, _type, _eventid, _filter, _fsel)\
(&((struct arm_cmn_event_attr[]) {{ \
.attr = __ATTR(_name, 0444, arm_cmn_event_show, NULL), \
.model = _model, \
.type = _type, \
.eventid = _eventid, \
- .occupid = _occupid, \
+ .filter = _filter, \
.fsel = _fsel, \
}})[0].attr.attr)
#define CMN_EVENT_ATTR(_model, _name, _type, _eventid) \
@@ -709,8 +709,8 @@ static ssize_t arm_cmn_event_show(struct device *dev,
eattr->type, eattr->eventid);
if (eattr->fsel > SEL_NONE)
- return sysfs_emit(buf, "type=0x%x,eventid=0x%x,occupid=0x%x\n",
- eattr->type, eattr->eventid, eattr->occupid);
+ return sysfs_emit(buf, "type=0x%x,eventid=0x%x,filter=0x%x\n",
+ eattr->type, eattr->eventid, eattr->filter);
return sysfs_emit(buf, "type=0x%x,eventid=0x%x\n", eattr->type,
eattr->eventid);
@@ -1320,7 +1320,7 @@ static ssize_t arm_cmn_format_show(struct device *dev,
static struct attribute *arm_cmn_format_attrs[] = {
CMN_FORMAT_ATTR(type, CMN_CONFIG_TYPE),
CMN_FORMAT_ATTR(eventid, CMN_CONFIG_EVENTID),
- CMN_FORMAT_ATTR(occupid, CMN_CONFIG_OCCUPID),
+ CMN_FORMAT_ATTR(filter, CMN_CONFIG_FILTER),
CMN_FORMAT_ATTR(bynodeid, CMN_CONFIG_BYNODEID),
CMN_FORMAT_ATTR(nodeid, CMN_CONFIG_NODEID),
@@ -1333,6 +1333,9 @@ static struct attribute *arm_cmn_format_attrs[] = {
_CMN_FORMAT_ATTR(wp_val, 1, CMN_CONFIG1_WP_VAL),
_CMN_FORMAT_ATTR(wp_mask, 2, CMN_CONFIG2_WP_MASK),
+ /* Old name for UAPI compatibility */
+ CMN_FORMAT_ATTR(occupid, CMN_CONFIG_FILTER),
+
NULL
};
@@ -1544,30 +1547,30 @@ static void arm_cmn_event_read(struct perf_event *event)
}
static int arm_cmn_set_event_sel_hi(struct arm_cmn_node *dn,
- enum cmn_filter_select fsel, u8 occupid)
+ enum cmn_filter_select fsel, u8 filter)
{
u64 reg;
if (fsel == SEL_NONE)
return 0;
- if (!dn->occupid[fsel].count) {
- dn->occupid[fsel].val = occupid;
+ if (!dn->filter[fsel].count) {
+ dn->filter[fsel].val = filter;
reg = FIELD_PREP(CMN__PMU_CBUSY_SNTHROTTLE_SEL,
- dn->occupid[SEL_CBUSY_SNTHROTTLE_SEL].val) |
+ dn->filter[SEL_CBUSY_SNTHROTTLE_SEL].val) |
FIELD_PREP(CMN__PMU_SN_HOME_SEL,
- dn->occupid[SEL_SN_HOME_SEL].val) |
+ dn->filter[SEL_SN_HOME_SEL].val) |
FIELD_PREP(CMN__PMU_HBT_LBT_SEL,
- dn->occupid[SEL_HBT_LBT_SEL].val) |
+ dn->filter[SEL_HBT_LBT_SEL].val) |
FIELD_PREP(CMN__PMU_CLASS_OCCUP_ID,
- dn->occupid[SEL_CLASS_OCCUP_ID].val) |
+ dn->filter[SEL_CLASS_OCCUP_ID].val) |
FIELD_PREP(CMN__PMU_OCCUP1_ID,
- dn->occupid[SEL_OCCUP1ID].val);
+ dn->filter[SEL_OCCUP1ID].val);
writel_relaxed(reg >> 32, dn->pmu_base + CMN_PMU_EVENT_SEL + 4);
- } else if (dn->occupid[fsel].val != occupid) {
+ } else if (dn->filter[fsel].val != filter) {
return -EBUSY;
}
- dn->occupid[fsel].count++;
+ dn->filter[fsel].count++;
return 0;
}
@@ -1649,7 +1652,7 @@ static void arm_cmn_event_stop(struct perf_event *event, int flags)
struct arm_cmn_val {
u8 dtm_count[CMN_MAX_DTMS];
- u8 occupid[CMN_MAX_DTMS][SEL_MAX];
+ u8 filter[CMN_MAX_DTMS][SEL_MAX];
u8 wp[CMN_MAX_DTMS][4];
u8 wp_combine[CMN_MAX_DTMS][2];
int dtc_count[CMN_MAX_DTCS];
@@ -1694,7 +1697,7 @@ static void arm_cmn_val_add_event(struct arm_cmn *cmn, struct arm_cmn_val *val,
val->dtm_count[dtm]++;
if (sel > SEL_NONE)
- val->occupid[dtm][sel] = CMN_EVENT_OCCUPID(event) + 1;
+ val->filter[dtm][sel] = CMN_EVENT_FILTER(event) + 1;
if (type != CMN_TYPE_WP)
continue;
@@ -1745,8 +1748,8 @@ static int arm_cmn_validate_group(struct arm_cmn *cmn, struct perf_event *event)
if (val->dtm_count[dtm] == CMN_DTM_NUM_COUNTERS)
goto done;
- if (sel > SEL_NONE && val->occupid[dtm][sel] &&
- val->occupid[dtm][sel] != CMN_EVENT_OCCUPID(event) + 1)
+ if (sel > SEL_NONE && val->filter[dtm][sel] &&
+ val->filter[dtm][sel] != CMN_EVENT_FILTER(event) + 1)
goto done;
if (type != CMN_TYPE_WP)
@@ -1892,7 +1895,7 @@ static void arm_cmn_event_clear(struct arm_cmn *cmn, struct perf_event *event,
}
if (hw->filter_sel > SEL_NONE)
- hw->dn[i].occupid[hw->filter_sel].count--;
+ hw->dn[i].filter[hw->filter_sel].count--;
dtm->pmu_config_low &= ~CMN__PMEVCNT_PAIRED(dtm_idx);
writel_relaxed(dtm->pmu_config_low, dtm->base + CMN_DTM_PMU_CONFIG);
@@ -1978,7 +1981,7 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
input_sel = CMN__PMEVCNT0_INPUT_SEL_DEV + dtm_idx +
(nid.port << 4) + (nid.dev << 2);
- if (arm_cmn_set_event_sel_hi(dn, hw->filter_sel, CMN_EVENT_OCCUPID(event)))
+ if (arm_cmn_set_event_sel_hi(dn, hw->filter_sel, CMN_EVENT_FILTER(event)))
goto free_dtms;
}
--
2.54.0.dirty
^ permalink raw reply related
* [PATCH 0/5] perf/arm-cmn: Support CMN S3 r2
From: Robin Murphy @ 2026-06-30 15:19 UTC (permalink / raw)
To: will, mark.rutland; +Cc: linux-arm-kernel, linux-perf-users, ilkka
Another year, another CMN - although arguably this was last year's
CMN, and is still the same in name as the year before that, but in
implementation the newer releases have significantly updated the HN-S
PMU features, pushing the previous filtering abstraction beyond its
breaking point. As before I've tried to break the refactoring and
functional changes up into reasonably logical chunks so there's some
vague hope of anyone being able to review it...
Cheers,
Robin.
Robin Murphy (5):
perf/arm-cmn: Rename filter variables for clarity
perf/arm-cmn: Refactor event filter programming
perf/arm-cmn: Refactor event filter data
perf/arm-cmn: Add new filters
perf/arm-cmn: Support CMN S3 r2
drivers/perf/arm-cmn.c | 490 +++++++++++++++++++++++++++++------------
1 file changed, 347 insertions(+), 143 deletions(-)
--
2.54.0.dirty
^ permalink raw reply
* Re: [PATCH 3/3] net: stmmac: dwmac-socfpga: Add mac-mode DT property support
From: Nazle Asmade, Muhammad Nazim Amirul @ 2026-06-30 15:13 UTC (permalink / raw)
To: Maxime Chevallier, Andrew Lunn
Cc: dinguyen@kernel.org, rmk+kernel@armlinux.org.uk,
krzk+dt@kernel.org, conor+dt@kernel.org, robh@kernel.org,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, andrew+netdev@lunn.ch,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <7c57bb08-b72d-44bf-be44-f1bcb2aa9a84@bootlin.com>
On 30/6/2026 10:04 pm, Maxime Chevallier wrote:
> On 6/30/26 16:02, Andrew Lunn wrote:
>> On Tue, Jun 30, 2026 at 06:31:08AM -0700, muhammad.nazim.amirul.nazle.asmade@altera.com wrote:
>>> From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
>>>
>>> Russell King's commit de696c63c1dc ("net: stmmac: socfpga: convert to
>>> use phy_interface") replaced mac_interface with phy_interface in
>>> socfpga_get_plat_phymode(), noting that no upstream DTS files set the
>>> "mac-mode" property, making the two values identical.
>>>
>>> The Agilex5 SoCDK TSN Config2 board is an exception: its gmac1 TSN
>>> port uses GMII internally in the MAC while the PHY-side interface is
>>> RGMII, so mac-mode and phy-mode differ.
>>
>> Maybe you need to represent the hardware block which magically
>> converts GMII to RGMII in DT?
>
> Yeah that's what we have on CycloneV, and we force the INTF_SEL to GMII if that
> HW block is present. I wonder if there's the same on agileX5 ?
Hi Maxime, Andrew
Yes, Agilex5 has the same concept. The GMII-to-RGMII converter is a
Quartus soft IP instantiated in the FPGA fabric — equivalent to the
CycloneV EMAC splitter. The XGMAC outputs GMII signals to the FPGA
fabric, the soft IP converts them to RGMII, and the RGMII signals then
go through the FPGA HVIO pins to the external Marvell 88E1512 PHY.
BR,
Nazim>
>>
>> Andrew
>
^ permalink raw reply
* [PATCH] arm64: dts: ti: Rename DM firmware reserved memory nodes
From: Paresh Bhagat @ 2026-06-30 15:09 UTC (permalink / raw)
To: nm, vigneshr
Cc: praneeth, kristo, robh, krzk+dt, conor+dt, linux-arm-kernel,
devicetree, linux-kernel, v-singh1, bb, u-kumar1, anshuld
Rename DM reserved memory nodes for K3 devices.
Example:
memory@xxxxxxxx -> to dm@xxxxxxxx
This allows U-Boot to identify and resize these regions using
fdt_fixup_reserved_memory() as done for TFA and optee.
Also drop unnecessary bootph-pre-ram property from AM62D2.
Signed-off-by: Paresh Bhagat <p-bhagat@ti.com>
---
arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am62-pocketbeagle2.dts | 2 +-
arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am625-tqma62xx.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am62a7-sk.dts | 2 +-
arch/arm64/boot/dts/ti/k3-am62d2-evm.dts | 3 +--
arch/arm64/boot/dts/ti/k3-am62p-verdin.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am62p5-sk.dts | 2 +-
arch/arm64/boot/dts/ti/k3-am62p5-var-som.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am67a-beagley-ai.dts | 2 +-
arch/arm64/boot/dts/ti/k3-am68-phycore-som.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am69-aquila.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-am69-sk.dts | 2 +-
arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts | 2 +-
arch/arm64/boot/dts/ti/k3-j721e-sk.dts | 2 +-
arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi | 2 +-
arch/arm64/boot/dts/ti/k3-j722s-evm.dts | 2 +-
arch/arm64/boot/dts/ti/k3-j784s4-j742s2-evm-common.dtsi | 2 +-
24 files changed, 24 insertions(+), 25 deletions(-)
diff --git a/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi
index 3baa653257bb..40148a37e294 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi
@@ -65,7 +65,7 @@ wkup_r5fss0_core0_dma_memory_region: memory@9da00000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@9db00000 {
+ wkup_r5fss0_core0_memory_region: dm@9db00000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9db00000 0x00 0xc00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am62-pocketbeagle2.dts b/arch/arm64/boot/dts/ti/k3-am62-pocketbeagle2.dts
index 7a4cffc27bda..90380bd8bb77 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-pocketbeagle2.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62-pocketbeagle2.dts
@@ -72,7 +72,7 @@ wkup_r5fss0_core0_dma_memory_region: memory@9da00000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@9db00000 {
+ wkup_r5fss0_core0_memory_region: dm@9db00000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9db00000 0x00 0xc00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
index e97b2b047d10..ef2afcc51578 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
@@ -212,7 +212,7 @@ wkup_r5fss0_core0_dma_memory_region: memory@9da00000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@9db00000 {
+ wkup_r5fss0_core0_memory_region: dm@9db00000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9db00000 0x00 0xc00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am625-tqma62xx.dtsi b/arch/arm64/boot/dts/ti/k3-am625-tqma62xx.dtsi
index 72288678cd01..c71297a6a818 100644
--- a/arch/arm64/boot/dts/ti/k3-am625-tqma62xx.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am625-tqma62xx.dtsi
@@ -55,7 +55,7 @@ wkup_r5fss0_core0_dma_memory_region: memory@9da00000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@9db00000 {
+ wkup_r5fss0_core0_memory_region: dm@9db00000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9db00000 0x00 0xc00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
index de4048a3564b..7af3c2ddeb22 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
@@ -65,7 +65,7 @@ wkup_r5fss0_core0_dma_memory_region: memory@9c800000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@9c900000 {
+ wkup_r5fss0_core0_memory_region: dm@9c900000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9c900000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
index 821a9705bb7d..83743a79ee60 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
@@ -59,7 +59,7 @@ wkup_r5fss0_core0_dma_memory_region: memory@9c800000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@9c900000 {
+ wkup_r5fss0_core0_memory_region: dm@9c900000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9c900000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am62d2-evm.dts b/arch/arm64/boot/dts/ti/k3-am62d2-evm.dts
index f5ceb6a1b5de..b06f0da35141 100644
--- a/arch/arm64/boot/dts/ti/k3-am62d2-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62d2-evm.dts
@@ -65,11 +65,10 @@ wkup_r5fss0_core0_dma_memory_region: memory@9c800000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@9c900000 {
+ wkup_r5fss0_core0_memory_region: dm@9c900000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9c900000 0x00 0xf00000>;
no-map;
- bootph-pre-ram;
};
secure_ddr: optee@9e800000 {
diff --git a/arch/arm64/boot/dts/ti/k3-am62p-verdin.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-verdin.dtsi
index 7ee894d59113..1688b003740f 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p-verdin.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p-verdin.dtsi
@@ -168,7 +168,7 @@ wkup_r5fss0_core0_dma_memory_region: memory@9c800000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@9c900000 {
+ wkup_r5fss0_core0_memory_region: dm@9c900000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9c900000 0x00 0x01e00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
index b770ed82be9d..a570d764ee3f 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
@@ -55,7 +55,7 @@ wkup_r5fss0_core0_dma_memory_region: memory@9c800000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@9c900000 {
+ wkup_r5fss0_core0_memory_region: dm@9c900000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9c900000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am62p5-var-som.dtsi b/arch/arm64/boot/dts/ti/k3-am62p5-var-som.dtsi
index fc5a3942cde0..48fa66ec08c1 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p5-var-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-var-som.dtsi
@@ -69,7 +69,7 @@ wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory@9c800000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: r5f-memory@9c900000 {
+ wkup_r5fss0_core0_memory_region: dm@9c900000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9c900000 0x00 0x01e00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
index ab9e58c2d225..03787bd4b857 100644
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
@@ -56,7 +56,7 @@ wkup_r5fss0_core0_dma_memory_region: memory@9da00000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@9db00000 {
+ wkup_r5fss0_core0_memory_region: dm@9db00000 {
compatible = "shared-dma-pool";
reg = <0x00 0x9db00000 0x00 0xc00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi
index f3ee73e64d69..78b4e5d61dfc 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi
@@ -53,7 +53,7 @@ mcu_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- mcu_r5fss0_core0_memory_region: memory@a0100000 {
+ mcu_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0 0xa0100000 0 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am67a-beagley-ai.dts b/arch/arm64/boot/dts/ti/k3-am67a-beagley-ai.dts
index 5255e04b9ac7..f0353cb2e508 100644
--- a/arch/arm64/boot/dts/ti/k3-am67a-beagley-ai.dts
+++ b/arch/arm64/boot/dts/ti/k3-am67a-beagley-ai.dts
@@ -56,7 +56,7 @@ wkup_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@a0100000 {
+ wkup_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am68-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am68-phycore-som.dtsi
index ab87767419fe..be581f03d1f8 100644
--- a/arch/arm64/boot/dts/ti/k3-am68-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am68-phycore-som.dtsi
@@ -55,7 +55,7 @@ mcu_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- mcu_r5fss0_core0_memory_region: memory@a0100000 {
+ mcu_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
index 6a6dc816b658..d49ab30658aa 100644
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
@@ -33,7 +33,7 @@ mcu_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- mcu_r5fss0_core0_memory_region: memory@a0100000 {
+ mcu_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am69-aquila.dtsi b/arch/arm64/boot/dts/ti/k3-am69-aquila.dtsi
index 5119baf62a4c..78b0b3214665 100644
--- a/arch/arm64/boot/dts/ti/k3-am69-aquila.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am69-aquila.dtsi
@@ -110,7 +110,7 @@ mcu_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- mcu_r5fss0_core0_memory_region: memory@a0100000 {
+ mcu_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-am69-sk.dts b/arch/arm64/boot/dts/ti/k3-am69-sk.dts
index e56772a334c5..a7c362dff589 100644
--- a/arch/arm64/boot/dts/ti/k3-am69-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am69-sk.dts
@@ -55,7 +55,7 @@ mcu_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- mcu_r5fss0_core0_memory_region: memory@a0100000 {
+ mcu_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi
index 5a8c2e707fde..cb41743d8f74 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi
@@ -35,7 +35,7 @@ mcu_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- mcu_r5fss0_core0_memory_region: memory@a0100000 {
+ mcu_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts
index 8040b6528c18..4a569b50f51a 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts
+++ b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts
@@ -57,7 +57,7 @@ mcu_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- mcu_r5fss0_core0_memory_region: memory@a0100000 {
+ mcu_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
index 689ba2ff81f7..3a3eed8d9a9e 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
@@ -54,7 +54,7 @@ mcu_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- mcu_r5fss0_core0_memory_region: memory@a0100000 {
+ mcu_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi
index c8073ee634b7..e6da4dbd91a6 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi
@@ -35,7 +35,7 @@ mcu_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- mcu_r5fss0_core0_memory_region: memory@a0100000 {
+ mcu_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
index a19e535f4946..3efca08c3ae7 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
@@ -37,7 +37,7 @@ mcu_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- mcu_r5fss0_core0_memory_region: memory@a0100000 {
+ mcu_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts
index e66330c71593..faf1dfbb53e1 100644
--- a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts
@@ -58,7 +58,7 @@ wkup_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- wkup_r5fss0_core0_memory_region: memory@a0100000 {
+ wkup_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-evm-common.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-evm-common.dtsi
index ff3a85cbc524..b2b04ef9bcaa 100644
--- a/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-evm-common.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-j742s2-evm-common.dtsi
@@ -41,7 +41,7 @@ mcu_r5fss0_core0_dma_memory_region: memory@a0000000 {
no-map;
};
- mcu_r5fss0_core0_memory_region: memory@a0100000 {
+ mcu_r5fss0_core0_memory_region: dm@a0100000 {
compatible = "shared-dma-pool";
reg = <0x00 0xa0100000 0x00 0xf00000>;
no-map;
--
2.34.1
^ permalink raw reply related
* [PATCH v3 5/8] ARM: remove unreachable invalid range check in kasan_init()
From: Sang-Heon Jeon @ 2026-06-30 15:04 UTC (permalink / raw)
To: rppt, Andrey Ryabinin, Russell King
Cc: linux-mm, Sang-Heon Jeon, Alexander Potapenko, Andrey Konovalov,
Dmitry Vyukov, kasan-dev, linux-arm-kernel, linux-kernel,
Vincenzo Frascino
In-Reply-To: <20260630150413.1718632-1-ekffu200098@gmail.com>
kasan_init() maps each memblock region with for_each_mem_range(), which
guarantees pa_start < pa_end. Then it skips any region with
pa_start >= arm_lowmem_limit, so pa_start < arm_lowmem_limit is guaranteed
as well.
When pa_end <= arm_lowmem_limit, pa_start < pa_end means start < end, so
the start >= end check is unreachable.
When pa_end > arm_lowmem_limit, end is clamped to __va(arm_lowmem_limit),
and pa_start < arm_lowmem_limit means start < end, so the check is
unreachable as well.
No functional change.
Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com>
---
arch/arm/mm/kasan_init.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c
index c6625e808bf8..1f7c74c5df9e 100644
--- a/arch/arm/mm/kasan_init.c
+++ b/arch/arm/mm/kasan_init.c
@@ -262,12 +262,6 @@ void __init kasan_init(void)
&pa_start, &pa_end, &arm_lowmem_limit);
end = __va(arm_lowmem_limit);
}
- if (start >= end) {
- pr_info("Skipping invalid memory block %pa-%pa (virtual %p-%p)\n",
- &pa_start, &pa_end, start, end);
- continue;
- }
-
create_mapping(start, end);
}
--
2.43.0
^ permalink raw reply related
* [PATCH v3 1/8] arm64: mm: remove unreachable invalid range check in kasan_init_shadow()
From: Sang-Heon Jeon @ 2026-06-30 15:04 UTC (permalink / raw)
To: rppt, Andrey Ryabinin, Catalin Marinas, Will Deacon
Cc: linux-mm, Sang-Heon Jeon, Alexander Potapenko, Andrey Konovalov,
Dmitry Vyukov, kasan-dev, linux-arm-kernel, linux-kernel,
Vincenzo Frascino
In-Reply-To: <20260630150413.1718632-1-ekffu200098@gmail.com>
kasan_init_shadow() maps each memblock region with for_each_mem_range()
and breaks the loop when start >= end. for_each_mem_range() never returns
an invalid range, so start < end always.
Therefore the start >= end check is unreachable, so remove it.
No functional change.
Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com>
Reviewed-by: Andrey Ryabinin <ryabinin.a.a@gmail.com>
---
arch/arm64/mm/kasan_init.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index 3fcad956fdf7..45fbdce684c8 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -353,9 +353,6 @@ static void __init kasan_init_shadow(void)
void *start = (void *)__phys_to_virt(pa_start);
void *end = (void *)__phys_to_virt(pa_end);
- if (start >= end)
- break;
-
kasan_map_populate((unsigned long)kasan_mem_to_shadow(start),
(unsigned long)kasan_mem_to_shadow(end),
early_pfn_to_nid(virt_to_pfn(start)));
--
2.43.0
^ permalink raw reply related
* [PATCH v3 0/8] treewide: remove unnecessary invalid range checks in memblock iteration loops
From: Sang-Heon Jeon @ 2026-06-30 15:04 UTC (permalink / raw)
To: rppt, Albert Ou, Andrew Morton, Andrey Ryabinin, Catalin Marinas,
Huacai Chen, Madhavan Srinivasan, Michael Ellerman, Muchun Song,
Oscar Salvador, Palmer Dabbelt, Paul Walmsley, Russell King,
Will Deacon
Cc: linux-mm, Sang-Heon Jeon, Alexander Potapenko, Alexandre Ghiti,
Andrey Konovalov, Christophe Leroy (CS GROUP), David Hildenbrand,
Dmitry Vyukov, kasan-dev, linux-arm-kernel, linux-kernel,
linuxppc-dev, linux-riscv, loongarch, Nicholas Piggin,
Vincenzo Frascino, WANG Xuerui
The memblock API guarantees that for_each_mem_range() and
for_each_mem_pfn_range() never return an invalid range, meaning start is
always less than end.
Several memblock callers still have unnecessary invalid range checks in
their loop bodies, so remove them.
Patches 1-6 cover for_each_mem_range() callers. memblock never stores a
zero-size region, so the range it returns always has start < end. Some
callers apply __va() or __phys_to_virt() before comparing, but these keep
start < end too, so the check is unreachable.
Patches 7-8 cover for_each_mem_pfn_range() callers. __next_mem_pfn_range()
skips any region that contains no whole page, so it only ever returns
start_pfn < end_pfn and the check is unnecessary.
For reference, commit 36ca7f4be809 ("arm64: mm: Remove bogus stop
condition from map_mem() loop") did a similar cleanup in arm64 map_mem().
All these checks are in different trees, so I split the change into one
patch per arch/subsystem. The patches are independent and can be applied
separately.
---
Changes from v1 [1]
- Add review-by, tested-by tags from v1
- Add missing simliar patches(5,6) to patch series
- Change base to rppt/for-next
Changes from v2 [2]
- Remove unused local variable and braces
[1] https://lore.kernel.org/all/20260621145919.1453-1-ekffu200098@gmail.com/
[2] https://lore.kernel.org/all/20260629163736.1606688-1-ekffu200098@gmail.com/
---
Sang-Heon Jeon (8):
arm64: mm: remove unreachable invalid range check in
kasan_init_shadow()
LoongArch: remove unreachable invalid range check in kasan_init()
riscv: remove unreachable invalid range check in
create_linear_mapping_page_table()
riscv: remove unreachable invalid range check in kasan_init()
ARM: remove unreachable invalid range check in kasan_init()
powerpc64/kasan: Remove unreachable invalid range check in
kasan_init_phys_region()
mm: remove unnecessary empty range check in
early_calculate_totalpages()
mm/hugetlb: remove unnecessary empty range check in
hugetlb_bootmem_set_nodes()
arch/arm/mm/kasan_init.c | 6 ------
arch/arm64/mm/kasan_init.c | 3 ---
arch/loongarch/mm/kasan_init.c | 3 ---
arch/powerpc/mm/kasan/init_book3e_64.c | 3 ---
arch/powerpc/mm/kasan/init_book3s_64.c | 3 ---
arch/riscv/mm/init.c | 2 --
arch/riscv/mm/kasan_init.c | 3 ---
mm/hugetlb.c | 7 ++-----
mm/mm_init.c | 3 +--
9 files changed, 3 insertions(+), 30 deletions(-)
--
2.43.0
^ permalink raw reply
* Re: [PATCH v2 06/13] KVM: arm64: dirty_bit: Add base FEAT_HACDBS cleaning routine
From: Leonardo Bras @ 2026-06-30 14:59 UTC (permalink / raw)
To: Oliver Upton
Cc: Leonardo Bras, Catalin Marinas, Will Deacon, Marc Zyngier,
Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Rafael J. Wysocki, Len Brown, Saket Dumbre, Paolo Bonzini,
Jonathan Cameron, Chengwen Feng, Kees Cook,
Mikołaj Lenczewski, James Morse, Zeng Heng, mrigendrachaubey,
Thomas Huth, Ryan Roberts, Yeoreum Yun, Mark Brown, Kevin Brodsky,
James Clark, Fuad Tabba, Raghavendra Rao Ananta,
Lorenzo Pieralisi, Sascha Bischoff, Anshuman Khandual, Tian Zheng,
linux-arm-kernel, linux-kernel, kvmarm, linux-acpi, acpica-devel,
kvm
In-Reply-To: <akKtKH8O5hngLenm@kernel.org>
On Mon, Jun 29, 2026 at 10:36:40AM -0700, Oliver Upton wrote:
> On Mon, Jun 29, 2026 at 12:17:54PM +0100, Leonardo Bras wrote:
> > Introduce the basic cleaning routine that is going to be used for both
> > dirty-bitmap and dirty-ring routines.
> >
> > It sets the required registers with the input buffer, and wait for
> > HACDBSIRQ to happen, which means either the task is done, or there was some
> > error during processing.
> >
> > It is ran with preemption disabled, as a task being scheduled in could
> > change the translation registers used by HACDBS and end up corrupting the
> > current dirty-bit tracking and the sched-in task's S2 pagetables.
> >
> > Signed-off-by: Leonardo Bras <leo.bras@arm.com>
> > ---
> > arch/arm64/kvm/dirty_bit.c | 81 ++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 81 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/dirty_bit.c b/arch/arm64/kvm/dirty_bit.c
> > index 789da8712b1b..e4283828b780 100644
> > --- a/arch/arm64/kvm/dirty_bit.c
> > +++ b/arch/arm64/kvm/dirty_bit.c
> > @@ -1,36 +1,117 @@
> > // SPDX-License-Identifier: GPL-2.0-only
> > /*
> > * Copyright (C) 2026 ARM Ltd.
> > * Author: Leonardo Bras <leo.bras@arm.com>
> > */
> >
> > #include <asm/kvm_dirty_bit.h>
> > +#include <asm/kvm_mmu.h>
> > #include <linux/kconfig.h>
> > #include <linux/acpi.h>
> >
> > DEFINE_PER_CPU(struct hacdbs, hacdbs_pcp) = {
> > .status = HACDBS_OFF,
> > .size = 0,
> > };
> >
> > /* HDBSS entry field definitions */
> > #define HDBSS_ENTRY_VALID BIT(0)
> > #define HDBSS_ENTRY_TTWL_SHIFT (1)
> > #define HDBSS_ENTRY_TTWL_MASK (GENMASK(3, 1))
> > #define HDBSS_ENTRY_TTWL(x) \
> > (((x) << HDBSS_ENTRY_TTWL_SHIFT) & HDBSS_ENTRY_TTWL_MASK)
> > #define HDBSS_ENTRY_TTWL_RESV HDBSS_ENTRY_TTWL(-4)
> > #define HDBSS_ENTRY_IPA GENMASK_ULL(55, 12)
> >
> > static __ro_after_init int hacdbsirq = -1;
> >
> > +static void hacdbs_start(u64 *hw_entries, int size)
> > +{
> > + u64 br;
> > + /* Each entry is 8 bytes */
> > + int size_b = size * sizeof(hw_entries[0]);
> > + int size_p2 = max(roundup_pow_of_two(size_b), PAGE_SIZE);
> > +
> > + /* If not using the full size of the array, put a stop entry at the end */
> > + if (size_b < size_p2)
> > + hw_entries[size] = HDBSS_ENTRY_VALID | HDBSS_ENTRY_TTWL_RESV;
> > +
> > + sysreg_clear_set_s(SYS_HACDBSCONS_EL2,
> > + HACDBSCONS_EL2_ERR_REASON | HACDBSCONS_EL2_INDEX, 0);
> > +
> > + br = (virt_to_phys(hw_entries) & HACDBSBR_EL2_BADDR_MASK) |
> > + FIELD_PREP(HACDBSBR_EL2_SZ, ilog2(size_p2) - 12) |
> > + FIELD_PREP(HACDBSBR_EL2_EN, 1);
> > +
> > + this_cpu_write(hacdbs_pcp.status, HACDBS_RUNNING);
> > + this_cpu_write(hacdbs_pcp.size, size);
> > + write_sysreg_s(br, SYS_HACDBSBR_EL2);
> > + isb();
> > +}
> > +
> > +static int hacdbs_stop(void)
> > +{
> > + write_sysreg_s(0, SYS_HACDBSBR_EL2);
> > + isb();
> > +
> > + if (this_cpu_read(hacdbs_pcp.status) == HACDBS_ERROR) {
> > + /* In case of error, HACDBSCONS_EL2.INDEX should point the faulty entry */
> > + u64 cons = read_sysreg_s(SYS_HACDBSCONS_EL2);
> > + int idx = FIELD_GET(HACDBSCONS_EL2_INDEX, cons);
> > +
> > + this_cpu_write(hacdbs_pcp.status, HACDBS_IDLE);
> > +
> > + return idx;
> > + }
> > +
> > + return this_cpu_read(hacdbs_pcp.size);
> > +}
> > +
> > +/*
> > + * Clears dirty-bits for an array of pages (hw_entries) using HACDBS
> > + * Returns the number of items cleaned from the array. If returns value < size,
> > + * there was an error in the processing.
> > + */
> > +static int dirty_bit_clear(struct kvm *kvm, u64 *hw_entries, int size)
> > +{
> > + u64 hcr_el2;
> > + int ret;
> > +
> > + preempt_disable();
> > +
> > + hcr_el2 = read_sysreg(HCR_EL2);
> > + write_sysreg(hcr_el2 | HCR_EL2_VM, HCR_EL2);
>
> sysreg_clear_set_hcr(). I'm pretty sure all the speculative AT errata
> depend on HCR_EL2.VM being set _after_ the stage-2 MMU has been loaded.
>
So, move this to after __load_stage2()?
ok
> > + __load_stage2(&kvm->arch.mmu);
>
> Pretty sure you need an ISB here to ensure loading the MMU is ordered
> with enabling HACDBS.
>
does not __load_stage2() have an isb() here?
In any case, will add an isb() after sysreg_clear_set_hcr(), which should
come after __load_stage2() IIUC.
> > + hacdbs_start(hw_entries, size);
> > +
> > + do {
> > + wfi();
> > + } while (this_cpu_read(hacdbs_pcp.status) == HACDBS_RUNNING);
>
> This is exactly why I said you should just poll hardware instead. It is
> entirely possible that the IRQ arrives before you WFI.
It should be fine with WFIT, though, right?
I understand the reason in pooling, and even done some workaround in
pooling for getting this to run in the model.
Based on the previous reply, do you think I should only use polling for
now, and implement the IRQ later?
>
> > + ret = hacdbs_stop();
> > +
> > + write_sysreg(hcr_el2, HCR_EL2);
>
> write_sysreg_hcr()
Sure!
Thanks for reviewing!
Leo
^ permalink raw reply
* Re: [PATCH v3 3/4] dt-bindings: PCI: mediatek-gen3: Split Airoha schema and document 2-lanes
From: Manivannan Sadhasivam @ 2026-06-30 14:54 UTC (permalink / raw)
To: Christian Marangi
Cc: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ryder Lee,
Michael Turquette, Stephen Boyd, Brian Masney, Philipp Zabel,
Matthias Brugger, AngeloGioacchino Del Regno, Jianjun Wang,
linux-pci, devicetree, linux-kernel, linux-mediatek, linux-clk,
linux-arm-kernel
In-Reply-To: <20260627121450.3529133-4-ansuelsmth@gmail.com>
On Sat, Jun 27, 2026 at 02:14:44PM +0200, Christian Marangi wrote:
> To permit proper documentation of required property to support PCIe
> configured for 2-lanes mode, split the Airoha schema part from the
> mediatek-gen3 schema to a dedicated schema.
>
> A PCIe configured for 2-lanes mode require an additional reg for the
> secondary PCIe to be configured and the airoha,scu phandle to correctly
> configure the PCIe MUX.
>
> Rework the mediatek-gen3 schema to drop any redundant constraint previsouly
> introduced for Airoha PCIe properties.
>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> ---
> .../bindings/pci/airoha,en7581-pcie.yaml | 251 ++++++++++++++++++
> .../bindings/pci/mediatek-pcie-gen3.yaml | 77 +-----
> 2 files changed, 256 insertions(+), 72 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/pci/airoha,en7581-pcie.yaml
>
> diff --git a/Documentation/devicetree/bindings/pci/airoha,en7581-pcie.yaml b/Documentation/devicetree/bindings/pci/airoha,en7581-pcie.yaml
> new file mode 100644
> index 000000000000..c690ba7f207c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/airoha,en7581-pcie.yaml
> @@ -0,0 +1,251 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pci/airoha,en7581-pcie.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Gen3 PCIe controller on Airoha SoCs
> +
> +maintainers:
> + - Christian Marangi <ansuelsmth@gmail.com>
> +
> +description: |+
> + PCIe Gen3 MAC controller for Airoha SoCs, it supports Gen3 speed
> + and compatible with Gen2, Gen1 speed.
> +
> + This PCIe controller supports up to 256 MSI vectors, the MSI hardware
> + block diagram is as follows:
> +
> + +-----+
> + | GIC |
> + +-----+
> + ^
> + |
> + port->irq
> + |
> + +-+-+-+-+-+-+-+-+
> + |0|1|2|3|4|5|6|7| (PCIe intc)
> + +-+-+-+-+-+-+-+-+
> + ^ ^ ^
> + | | ... |
> + +-------+ +------+ +-----------+
> + | | |
> + +-+-+---+--+--+ +-+-+---+--+--+ +-+-+---+--+--+
> + |0|1|...|30|31| |0|1|...|30|31| |0|1|...|30|31| (MSI sets)
> + +-+-+---+--+--+ +-+-+---+--+--+ +-+-+---+--+--+
> + ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
> + | | | | | | | | | | | | (MSI vectors)
> + | | | | | | | | | | | |
> +
> + (MSI SET0) (MSI SET1) ... (MSI SET7)
> +
> + With 256 MSI vectors supported, the MSI vectors are composed of 8 sets,
> + each set has its own address for MSI message, and supports 32 MSI vectors
> + to generate interrupt.
> +
> +properties:
> + compatible:
> + const: airoha,en7581-pcie
> +
> + reg:
> + minItems: 1
> + maxItems: 2
> +
> + reg-names:
> + minItems: 1
> + maxItems: 2
> +
> + interrupts:
> + maxItems: 1
> +
> + ranges:
> + minItems: 1
> + maxItems: 8
8 entries? Really?
> +
> + iommu-map:
> + maxItems: 1
> +
> + iommu-map-mask:
> + const: 0
Why these iommu properties are not present in the example?
> +
> + resets:
> + minItems: 1
> + maxItems: 4
> +
> + reset-names:
> + minItems: 1
> + maxItems: 4
> +
> + clocks:
> + maxItems: 1
> +
> + clock-names:
> + items:
> + - const: sys-ck
sys-clk?
> +
> + phys:
> + maxItems: 1
> +
> + phy-names:
> + items:
> + - const: pcie-phy
If there is going to be only one PHY, then I think you can drop the phy-names
property.
> +
> + num-lanes:
> + enum: [1, 2]
> +
> + mediatek,pbus-csr:
> + $ref: /schemas/types.yaml#/definitions/phandle-array
> + items:
> + - items:
> + - description: phandle to pbus-csr syscon
> + - description: offset of pbus-csr base address register
> + - description: offset of pbus-csr base address mask register
> + description:
> + Phandle with two arguments to the syscon node used to detect if
> + a given address is accessible on PCIe controller.
> +
> + airoha,scu:
> + $ref: /schemas/types.yaml#/definitions/phandle-array
> + items:
> + - items:
> + - description: phandle to airoha SCU syscon
> + description:
> + Phandle to SCU syscon to configure PCIe MUX for 2 lines support.
> +
> + '#interrupt-cells':
> + const: 1
> +
> + interrupt-controller:
> + description: Interrupt controller node for handling legacy PCI interrupts.
s/legacy/INTx
> + type: object
> + properties:
> + '#address-cells':
> + const: 0
> + '#interrupt-cells':
> + const: 1
> + interrupt-controller: true
> +
> + required:
> + - '#address-cells'
> + - '#interrupt-cells'
> + - interrupt-controller
> +
> + additionalProperties: false
> +
> +required:
> + - compatible
> + - reg
> + - reg-names
> + - interrupts
> + - ranges
> + - clocks
> + - clock-names
> + - '#interrupt-cells'
> + - interrupt-controller
> +
> +allOf:
> + - $ref: /schemas/pci/pci-host-bridge.yaml#
> + - if:
> + properties:
> + num-lanes:
> + const: 2
> + then:
> + properties:
> + reg:
> + minItems: 2
> +
> + reg-names:
> + items:
> + - const: pcie-mac
> + - const: sec-pcie-mac
> +
> + resets:
> + minItems: 4
> +
> + reset-names:
> + items:
> + - const: phy-lane0
> + - const: phy-lane1
> + - const: perstout
> + - const: sec-perstout
> +
> + required:
> + - airoha,scu
> +
> + else:
> + properties:
> + reg:
> + maxItems: 1
> +
> + reg-names:
> + items:
> + - const: pcie-mac
> +
> + resets:
> + minItems: 2
> + maxItems: 3
> +
> + reset-names:
> + minItems: 2
> + items:
> + - enum: [ phy-lane0, phy-lane1, phy-lane2 ]
> + - enum: [ phy-lane1, perstout ]
> + - const: phy-lane2
> +
> +unevaluatedProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/interrupt-controller/irq.h>
> +
> + bus {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
You can drop bus node.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH rc v7 0/7] iommu/arm-smmu-v3: Fix device crash on kdump kernel
From: Pranjal Shrivastava @ 2026-06-30 14:51 UTC (permalink / raw)
To: Mostafa Saleh
Cc: Nicolin Chen, will, robin.murphy, jgg, joro, kees, baolu.lu,
kevin.tian, miko.lenczewski, linux-arm-kernel, iommu,
linux-kernel, stable, jamien
In-Reply-To: <akPB6l-fuJUcg4a2@google.com>
On Tue, Jun 30, 2026 at 01:17:30PM +0000, Mostafa Saleh wrote:
> On Mon, Jun 29, 2026 at 11:15:33PM -0700, Nicolin Chen wrote:
> > When transitioning to a kdump kernel, the primary kernel might have crashed
> > while endpoint devices were actively bus-mastering DMA. Currently, the SMMU
> > driver aggressively resets the hardware during probe by clearing CR0_SMMUEN
> > and setting the Global Bypass Attribute (GBPA) to ABORT.
> >
> > In a kdump scenario, this aggressive reset is highly destructive:
> > a) If GBPA is set to ABORT, in-flight DMA will be aborted, generating fatal
> > PCIe AER or SErrors that may panic the kdump kernel
>
> Can you please clarify more on those errors, what conditions will
> trigger that?
> For example, patch 4 disables the EVTQ to avoid events as there might
> be a lot, why are they not fatal also?
>
> > b) If GBPA is set to BYPASS, in-flight DMA targeting some IOVAs will bypass
> > the SMMU and corrupt the physical memory at those 1:1 mapped IOVAs.
> >
> > To safely absorb in-flight DMA, the kdump kernel must leave SMMUEN=1 intact
> > and avoid modifying STRTAB_BASE. This allows HW to continue translating in-
> > flight DMA using the crashed kernel's page tables until the endpoint device
> > drivers probe and quiesce their respective hardware.
> >
> > However, the ARM SMMUv3 architecture specification states that updating the
> > SMMU_STRTAB_BASE register while SMMUEN == 1 is UNPREDICTABLE or ignored.
> >
> > This leaves a kdump kernel no choice but to adopt the stream table from the
> > crashed kernel.
>
> In many cases the patches assume that the CDs/STE might be corrupted,
> but still attempt to retrieve them with some validation
> (log2size/split...)
> However, the base address might be broken, TLBs state is unknown...
>
> IMO, although that might improve the status quo, there are still
> heuristics, in addition to noticeable complexity to transition the
> stream tables. I wonder if FW can deal with AER in that case before
> booting the kdump kernel.
I guess we're reading the base address from the HW register itself so
that should be fine? CDs are in-memory so that's why they could be
corrupted?
About the TLB state, I'm not sure what might pollute it, since this is a
kexec, I don't expect any non-kernel entity to gain program control
before the kdump kernel.. Hence, IMO, we can't configure FW to deal with
AER here..
Thanks,
Praan
^ permalink raw reply
* Re: [PATCH v2 05/13] KVM: arm64: Detect (via ACPI) and initialize HACDBSIRQ
From: Leonardo Bras @ 2026-06-30 14:50 UTC (permalink / raw)
To: Oliver Upton
Cc: Leonardo Bras, Catalin Marinas, Will Deacon, Marc Zyngier,
Joey Gouly, Steffen Eiden, Suzuki K Poulose, Zenghui Yu,
Rafael J. Wysocki, Len Brown, Saket Dumbre, Paolo Bonzini,
Jonathan Cameron, Chengwen Feng, Kees Cook,
Mikołaj Lenczewski, James Morse, Zeng Heng, mrigendrachaubey,
Thomas Huth, Ryan Roberts, Yeoreum Yun, Mark Brown, Kevin Brodsky,
James Clark, Fuad Tabba, Raghavendra Rao Ananta,
Lorenzo Pieralisi, Sascha Bischoff, Anshuman Khandual, Tian Zheng,
linux-arm-kernel, linux-kernel, kvmarm, linux-acpi, acpica-devel,
kvm
In-Reply-To: <akKpxDulRN7zDrgM@kernel.org>
On Mon, Jun 29, 2026 at 10:22:12AM -0700, Oliver Upton wrote:
> On Mon, Jun 29, 2026 at 12:17:53PM +0100, Leonardo Bras wrote:
> > Find via ACPI [1] the Id for HACDBSIRQ, initialize it as a per-cpu IRQ
> > and make sure any cpu able to run virtualization has it active.
> >
> > Introduce a per-cpu structure used by the HACDBSIRQ handler to keep track
> > of entries size and the status of HACDBS. Size is used to detect end of
> > processing in case the number of entries being processed is different of
> > the supported entries size.
> >
> > Status may look easily replaceable by checking HACDBS registers now, but
> > will make the OFF/IDLE detection easier in next patches.
> >
> > Signed-off-by: Leonardo Bras <leo.bras@arm.com>
> >
> > [1] https://github.com/tianocore/edk2/issues/12409
>
> Reference the ACPI specification instead please.
It's not accepted yet, unfortunately. I commented that into the cover
letter, but forgot to add it here.
> Any link you want to
> include in a changelog should use the Link: footer, the linkage to the
> inline citation will be obvious.
Sure, will remember that in the future.
>
> If we need to initialize the IRQ I'd really like to see device tree
> bindings for HACDBSIRQ as well. Pretty much any system us plebs can get
> our hands on is gonna be DT anyway.
Agree. I started out with ACPI because that's what the main target is, as
dirty-logging is focused in Live Migration, which is usually more
appreciated in the server space, which generally uses ACPI.
I spoke to some people, and I could not hear of anyone releasing a product
based in DT that would implement this yet, so I postponed the DT
enablement.
>
> > +static irqreturn_t hacdbsirq_handler(int irq, void *pcpu)
> > +{
> > + u64 cons = read_sysreg_s(SYS_HACDBSCONS_EL2);
> > + unsigned long err = FIELD_GET(HACDBSCONS_EL2_ERR_REASON, cons);
> > +
> > + switch (err) {
> > + case HACDBSCONS_EL2_ERR_REASON_NOF:
> > + this_cpu_write(hacdbs_pcp.status, HACDBS_IDLE);
> > + break;
> > + case HACDBSCONS_EL2_ERR_REASON_IPAHACF:
> > + /* When size not a power of two >= 4k, exit with reserved TTLW */
> > + int index = FIELD_GET(HACDBSCONS_EL2_INDEX, cons);
> > +
> > + if (index >= this_cpu_read(hacdbs_pcp.size)) {
> > + this_cpu_write(hacdbs_pcp.status, HACDBS_IDLE);
> > + break;
> > + }
> > + fallthrough;
> > + case HACDBSCONS_EL2_ERR_REASON_STRUCTF:
> > + case HACDBSCONS_EL2_ERR_REASON_IPAF:
> > + this_cpu_write(hacdbs_pcp.status, HACDBS_ERROR);
> > + break;
> > + }
> > +
> > + return IRQ_HANDLED;
> > +}
>
> I have a pretty extreme distaste for creating a state machine between
> the callsite and the IRQ handler. The callsite should poll HACDBS for
> completion. The thread has nothing better to do anyway.
Well, there is one argument it could just wait and save some energy, but I
agree it is not relevant in server space. The main reason I did this is
because I am planning on later doing an improved version of this that would
clean the dirty-bit *while* running the guest, and having the IRQ is needed
for exiting guest so we can notify userspace the cleaning is done. So I
laid the HACDBSIRQ infra here so we don't have both polling and IRQ options
happening.
That idea would require us to add new API (a return value for 'cleaned'),
and also a new flag for the clean ioctl. We also need the VMM to
implement that, but then we get a proper cpu usage of cleaning time.
I wanted to start with a backwards compatible version, and do the above
idea once I put my hands in hardware that implements HACDBS, so I can
properly measure how much performance we get on above strategy.
What do you think?
Thanks!
Leo
^ permalink raw reply
* Re: [ANNOUNCEMENT] LPC 2026: System Monitoring and Observability Microconference
From: Jason Xing @ 2026-06-30 14:49 UTC (permalink / raw)
To: Breno Leitao
Cc: linux-acpi, linux-hwmon, netdev, linux-kernel, linux-arm-kernel,
kernel-team, linux-mm, iipeace5, gavinguo, linux, amscanne, sj,
gpiccoli, Daniel Gomez, mfo, platform-driver-x86, acpica-devel
In-Reply-To: <aj5KJEIsTl6IK0nX@gmail.com>
On Fri, Jun 26, 2026 at 5:56 PM Breno Leitao <leitao@debian.org> wrote:
>
> We are pleased to announce the Call for Proposals (CFP) for another
> edition of System Monitoring and Observability Microconference, this
> time at the 2026 Linux Plumbers Conference (LPC), taking place in
> Prague, Czechia, from Oct 5-7, 2026.
>
> https://lpc.events/event/20/sessions/262/
>
> This microconference provides a valuable forum for key engineering areas
> such as:
>
> - Kernel Health and Runtime Monitoring
> - Hardware Integration and Error Detection
> - Correlation of Issues (crashes, stalls, bugs)
> - Virtualization Stack Monitoring
> - Memory Management Monitoring and Observability
> - Anomaly Detection Algorithms for System Behavior
> - Automated Analysis, Remediation and post mortem analyzes
>
> The purpose of each talk is to share challenges and discuss potential
> improvements. Sessions will last 20 to 30 minutes and aim to encourage
> brainstorming and open dialogue about ongoing issues rather than
> delivering immediate solutions.
>
> The conference acts as both a knowledge-sharing platform and a strategic
> venue for guiding the future of kernel technologies to better meet the
> demands of large-scale infrastructure.
>
> We invite you to submit your proposals here:
> https://lpc.events/event/20/abstracts/
>
> Please select track "Linux System Monitoring and Observability MC"
A kind reminder: at the bottom of the page [1], please click the
'Submit new abstract' button so that you will be able to quickly
submit a new proposal. (Admittedly, it's a bit easy to miss the entry
especially for the newcomers)
If you have any questions/suggestions/problems, please do not hesitate
to contact Breno or me.
Again, proposals are greatly appreciated :)
[1]: https://lpc.events/event/20/abstracts/
Thanks,
Jason
^ permalink raw reply
* Re: [PATCH 2/3] arm64: dts: socfpga: agilex5: Add SoCDK TSN Config2 board
From: Nazle Asmade, Muhammad Nazim Amirul @ 2026-06-30 14:39 UTC (permalink / raw)
To: Andrew Lunn
Cc: dinguyen@kernel.org, maxime.chevallier@bootlin.com,
rmk+kernel@armlinux.org.uk, krzk+dt@kernel.org,
conor+dt@kernel.org, robh@kernel.org, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
andrew+netdev@lunn.ch, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <edf84080-a5e0-478c-9977-af2376cb71c5@lunn.ch>
On 30/6/2026 9:58 pm, Andrew Lunn wrote:
>> + * gmac1 is the TSN port. The MAC operates in GMII mode internally
>> + * while the PHY-side interface is RGMII, so mac-mode and phy-mode differ.
>> + */
>> +&gmac1 {
>> + status = "okay";
>> + phy-mode = "rgmii"; /* TX/RX clock delays provided by Agilex5 I/O hardware */
> Could you provide more details about this. I want to understand the
> big picture.
>
> Normally we talk about the PCB providing the delays. This sounds like
> it is the FPGA? So i need convincing this is correct.
Hi Andrew,
Thanks for your quick review and yes, it is the FPGA — specifically a
soft IP block in the FPGA fabric that implements the RGMII clock delays
and is configured before Linux boots via the FPGA bitstream. The driver
must not add additional delays on top.
BR,
Nazim
^ permalink raw reply
* Re: [PATCH v4 1/2] arm64: errata: Workaround NVIDIA Olympus device store/load ordering
From: Will Deacon @ 2026-06-30 14:21 UTC (permalink / raw)
To: Shanker Donthineni
Cc: Catalin Marinas, Vladimir Murzin, Jason Gunthorpe,
linux-arm-kernel, Mark Rutland, linux-kernel, linux-doc,
Vikram Sethi, Jason Sequeira
In-Reply-To: <20260625182425.3194066-2-sdonthineni@nvidia.com>
On Thu, Jun 25, 2026 at 01:24:24PM -0500, Shanker Donthineni wrote:
> On systems with NVIDIA Olympus cores, a Device-nGnR* load can be
> observed by a peripheral before an older, non-overlapping Device-nGnR*
> store to the same peripheral. This breaks the program-order guarantee
> that software expects for Device-nGnR* accesses and can leave a
> peripheral in an incorrect state, as a load is observed before an
> earlier store takes effect.
>
> The erratum can occur only when all of the following apply:
>
> - A PE executes a Device-nGnR* store followed by a younger
> Device-nGnR* load.
> - The store is not a store-release.
> - The accesses target the same peripheral and do not overlap in bytes.
> - There is at most one intervening Device-nGnR* store in program
> order, and there are no intervening Device-nGnR* loads.
> - There is no DSB, and no DMB that orders loads, between the store and
> the load.
Does that mean that a DMB LD between the store and the load would
solve the problem?
It would be interesting to see how your benchmarks motivating patch 2
look if you leave __raw_writeX as-is and instead add a barrier in
__raw_readX before the load instruction.
Will
^ permalink raw reply
* Re: [PATCH] net: airoha: fix MIB stats collection to be lossless
From: Lorenzo Bianconi @ 2026-06-30 14:21 UTC (permalink / raw)
To: Aniket Negi
Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Christian Marangi, Simon Horman, linux-arm-kernel,
linux-mediatek, netdev, linux-kernel
In-Reply-To: <20260630111834.233643-1-aniket.negi03@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 15019 bytes --]
> The airoha_dev_get_hw_stats() function had two correctness issues in the
> way it collects hardware MIB counters.
>
> Bug 1: Read-clear race causes silent packet loss in statistics
>
> airoha_update_hw_stats() read all MIB registers and then cleared them
> via REG_FE_GDM_MIB_CLEAR. There is a time window between the last
> register read and the hardware clear. Any packet that the hardware
> counts during this window is lost: the register is incremented, then
> cleared, without the increment ever being read by software. Under
> sustained traffic this causes a permanent and growing undercount in all
> reported statistics.
>
> This is particularly misleading for tx_ok_pkts and tx_ok_bytes, which
> routers and traffic monitors use to detect packet forwarding loss
> between two points in a hardware-accelerated path (e.g., between two
> netdevs in the QDMA/PPE fast-path). An inaccurate count makes it
> impossible to reliably attribute drops in the forwarding pipeline
> without capturing traffic at both ends independently.
>
> Bug 2: 32-bit counter overflow causes stat corruption
>
> Several MIB registers are only 32 bits wide: tx_drops, tx_broadcast,
> tx_multicast, rx_drops, rx_broadcast, rx_multicast, rx_errors,
> rx_crc_error, rx_over_errors, rx_fragment, rx_jabber, and the runt and
> long buckets of the tx_len[]/rx_len[].
>
> The original code relied on MIB_CLEAR to keep register values small
> enough that a simple '+= val' per cycle did not lose data across a
> wrap. Once clearing is removed (to fix Bug 1), raw '+= val' silently
> corrupts the accumulated software counter on overflow.
>
> Fix both issues together:
>
> - 64-bit H+L register pairs (tx_ok_pkts, tx_ok_bytes, tx_len[1..5],
> rx_ok_pkts, rx_ok_bytes, rx_len[1..5]): read directly from hardware
> without clearing. Hardware accumulates the full running total; a
> single direct assignment per poll is correct and lossless.
>
> - 32-bit registers (tx_drops, tx_broadcast, tx_multicast, rx_drops,
> rx_broadcast, rx_multicast, rx_errors, rx_crc_error, rx_over_errors,
> rx_fragment, rx_jabber, and the runt/long buckets in tx_len[0]/[6]
> and rx_len[0]/[6]): track the previous hardware value in a new
> hw_prev_stats sub-struct inside airoha_hw_stats and accumulate
> (u32)(curr - prev) into the 64-bit software counter. Unsigned
> subtraction handles wrap-around transparently:
> prev=0xFFFFFF00, curr=0x00000010 -> delta=(u32)(0x10-0xFFFFFF00)=0x110
>
> Remove the REG_FE_GDM_MIB_CLEAR write from airoha_update_hw_stats()
> entirely. Because the driver no longer clears hardware counters, the
> read-clear race window is eliminated.
>
> The hw_prev_stats fields are zero-initialised by the existing
> devm_kzalloc() call in airoha_alloc_gdm_device().
>
> Fixes: 8f4695fb67b2 ("net: airoha: better handle MIBs for GDM ports with multiple devs attached")
> Signed-off-by: Aniket Negi <aniket.negi03@gmail.com>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 132 +++++++++++------------
> drivers/net/ethernet/airoha/airoha_eth.h | 22 ++++
> 2 files changed, 86 insertions(+), 68 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 1caf6766f2c0..7ae4e294478e 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -1696,133 +1696,133 @@ static void airoha_dev_get_hw_stats(struct airoha_gdm_dev *dev)
>
> u64_stats_update_begin(&dev->stats.syncp);
>
> - /* TX */
> + /* TX - 64-bit H+L registers: hw accumulates the total, read directly. */
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_H(port->id));
> - dev->stats.tx_ok_pkts += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_L(port->id));
> - dev->stats.tx_ok_pkts += val;
> + dev->stats.tx_ok_pkts = (u64)val << 32;
I guess it is more readable to store REG_FE_GDM_TX_OK_PKT_CNT_L() read in val
here. Something like:
val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_L(port->id));
dev->stats.tx_ok_pkts += val;
This apply even to occurrence below
> + dev->stats.tx_ok_pkts += airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_H(port->id));
> - dev->stats.tx_ok_bytes += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_L(port->id));
> - dev->stats.tx_ok_bytes += val;
> + dev->stats.tx_ok_bytes = (u64)val << 32;
> + dev->stats.tx_ok_bytes += airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_L(port->id));
>
> + /* TX - 32-bit registers: accumulate delta to handle wrap-around. */
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_DROP_CNT(port->id));
> - dev->stats.tx_drops += val;
> + dev->stats.tx_drops += (u32)(val - dev->stats.hw_prev_stats.tx_drops);
> + dev->stats.hw_prev_stats.tx_drops = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_BC_CNT(port->id));
> - dev->stats.tx_broadcast += val;
> + dev->stats.tx_broadcast += (u32)(val - dev->stats.hw_prev_stats.tx_broadcast);
> + dev->stats.hw_prev_stats.tx_broadcast = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_MC_CNT(port->id));
> - dev->stats.tx_multicast += val;
> + dev->stats.tx_multicast += (u32)(val - dev->stats.hw_prev_stats.tx_multicast);
> + dev->stats.hw_prev_stats.tx_multicast = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_RUNT_CNT(port->id));
> - dev->stats.tx_len[i] += val;
> + dev->stats.tx_len[i] += (u32)(val - dev->stats.hw_prev_stats.tx_len[i]);
> + dev->stats.hw_prev_stats.tx_len[i] = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_H(port->id));
> - dev->stats.tx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_L(port->id));
> - dev->stats.tx_len[i++] += val;
> + dev->stats.tx_len[i] += (u64)val << 32;
Since now we do not reset MIB counters, this is wrong, you can't use "+="
> + dev->stats.tx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_H(port->id));
> - dev->stats.tx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_L(port->id));
> - dev->stats.tx_len[i++] += val;
> + dev->stats.tx_len[i] = (u64)val << 32;
> + dev->stats.tx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_H(port->id));
> - dev->stats.tx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_L(port->id));
> - dev->stats.tx_len[i++] += val;
> + dev->stats.tx_len[i] = (u64)val << 32;
> + dev->stats.tx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_H(port->id));
> - dev->stats.tx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_L(port->id));
> - dev->stats.tx_len[i++] += val;
> + dev->stats.tx_len[i] = (u64)val << 32;
> + dev->stats.tx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_H(port->id));
> - dev->stats.tx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_L(port->id));
> - dev->stats.tx_len[i++] += val;
> + dev->stats.tx_len[i] = (u64)val << 32;
> + dev->stats.tx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_H(port->id));
> - dev->stats.tx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_L(port->id));
> - dev->stats.tx_len[i++] += val;
> + dev->stats.tx_len[i] = (u64)val << 32;
> + dev->stats.tx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_LONG_CNT(port->id));
> - dev->stats.tx_len[i++] += val;
> + dev->stats.tx_len[i] += (u32)(val - dev->stats.hw_prev_stats.tx_len[i]);
> + dev->stats.hw_prev_stats.tx_len[i++] = val;
>
> /* RX */
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_H(port->id));
> - dev->stats.rx_ok_pkts += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_L(port->id));
> - dev->stats.rx_ok_pkts += val;
> + dev->stats.rx_ok_pkts = (u64)val << 32;
> + dev->stats.rx_ok_pkts += airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_H(port->id));
> - dev->stats.rx_ok_bytes += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_L(port->id));
> - dev->stats.rx_ok_bytes += val;
> + dev->stats.rx_ok_bytes = (u64)val << 32;
> + dev->stats.rx_ok_bytes += airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_DROP_CNT(port->id));
> - dev->stats.rx_drops += val;
> + dev->stats.rx_drops += (u32)(val - dev->stats.hw_prev_stats.rx_drops);
> + dev->stats.hw_prev_stats.rx_drops = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_BC_CNT(port->id));
> - dev->stats.rx_broadcast += val;
> + dev->stats.rx_broadcast += (u32)(val - dev->stats.hw_prev_stats.rx_broadcast);
> + dev->stats.hw_prev_stats.rx_broadcast = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_MC_CNT(port->id));
> - dev->stats.rx_multicast += val;
> + dev->stats.rx_multicast += (u32)(val - dev->stats.hw_prev_stats.rx_multicast);
> + dev->stats.hw_prev_stats.rx_multicast = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ERROR_DROP_CNT(port->id));
> - dev->stats.rx_errors += val;
> + dev->stats.rx_errors += (u32)(val - dev->stats.hw_prev_stats.rx_errors);
> + dev->stats.hw_prev_stats.rx_errors = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_CRC_ERR_CNT(port->id));
> - dev->stats.rx_crc_error += val;
> + dev->stats.rx_crc_error += (u32)(val - dev->stats.hw_prev_stats.rx_crc_error);
> + dev->stats.hw_prev_stats.rx_crc_error = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_OVERFLOW_DROP_CNT(port->id));
> - dev->stats.rx_over_errors += val;
> + dev->stats.rx_over_errors += (u32)(val - dev->stats.hw_prev_stats.rx_over_errors);
> + dev->stats.hw_prev_stats.rx_over_errors = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_FRAG_CNT(port->id));
> - dev->stats.rx_fragment += val;
> + dev->stats.rx_fragment += (u32)(val - dev->stats.hw_prev_stats.rx_fragment);
> + dev->stats.hw_prev_stats.rx_fragment = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_JABBER_CNT(port->id));
> - dev->stats.rx_jabber += val;
> + dev->stats.rx_jabber += (u32)(val - dev->stats.hw_prev_stats.rx_jabber);
> + dev->stats.hw_prev_stats.rx_jabber = val;
>
> i = 0;
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_RUNT_CNT(port->id));
> - dev->stats.rx_len[i] += val;
> + dev->stats.rx_len[i] += (u32)(val - dev->stats.hw_prev_stats.rx_len[i]);
> + dev->stats.hw_prev_stats.rx_len[i] = val;
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_H(port->id));
> - dev->stats.rx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_L(port->id));
> - dev->stats.rx_len[i++] += val;
> + dev->stats.rx_len[i] += (u64)val << 32;
same here.
> + dev->stats.rx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_H(port->id));
> - dev->stats.rx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_L(port->id));
> - dev->stats.rx_len[i++] += val;
> + dev->stats.rx_len[i] = (u64)val << 32;
> + dev->stats.rx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_H(port->id));
> - dev->stats.rx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_L(port->id));
> - dev->stats.rx_len[i++] += val;
> + dev->stats.rx_len[i] = (u64)val << 32;
> + dev->stats.rx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_H(port->id));
> - dev->stats.rx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_L(port->id));
> - dev->stats.rx_len[i++] += val;
> + dev->stats.rx_len[i] = (u64)val << 32;
> + dev->stats.rx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_H(port->id));
> - dev->stats.rx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_L(port->id));
> - dev->stats.rx_len[i++] += val;
> + dev->stats.rx_len[i] = (u64)val << 32;
> + dev->stats.rx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_H(port->id));
> - dev->stats.rx_len[i] += ((u64)val << 32);
> - val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_L(port->id));
> - dev->stats.rx_len[i++] += val;
> + dev->stats.rx_len[i] = (u64)val << 32;
> + dev->stats.rx_len[i++] += airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_L(port->id));
>
> val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_LONG_CNT(port->id));
> - dev->stats.rx_len[i++] += val;
> + dev->stats.rx_len[i] += (u32)(val - dev->stats.hw_prev_stats.rx_len[i]);
> + dev->stats.hw_prev_stats.rx_len[i++] = val;
>
> u64_stats_update_end(&dev->stats.syncp);
> }
> @@ -1839,10 +1839,6 @@ static void airoha_update_hw_stats(struct airoha_gdm_dev *dev)
> airoha_dev_get_hw_stats(port->devs[i]);
> }
>
> - /* Reset MIB counters */
> - airoha_fe_set(dev->eth, REG_FE_GDM_MIB_CLEAR(port->id),
> - FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK);
> -
> spin_unlock(&port->stats_lock);
> }
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index 2765244d937c..af12ad6eac17 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -244,6 +244,28 @@ struct airoha_hw_stats {
> u64 rx_fragment;
> u64 rx_jabber;
> u64 rx_len[7];
> +
> + struct {
> + /* Previous HW register values for 32-bit counter delta tracking.
> + * Storing the last seen value and accumulating (u32)(curr - prev)
> + * in 64-bit software counter & handles wrap-around transparently
> + * via unsigned arithmetic. These fields are never reported to
> + * userspace.
> + */
can you please align the comment here?
> + u32 tx_drops;
> + u32 tx_broadcast;
> + u32 tx_multicast;
> + u32 tx_len[7];
> + u32 rx_drops;
> + u32 rx_broadcast;
> + u32 rx_multicast;
> + u32 rx_errors;
> + u32 rx_crc_error;
> + u32 rx_over_errors;
> + u32 rx_fragment;
> + u32 rx_jabber;
> + u32 rx_len[7];
> + } hw_prev_stats;
Maybe something like "prev_val32" ?
Regards,
Lorenzo
> };
>
> enum {
> --
> 2.43.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v4 2/2] arm64: io: apply the device store-release workaround once per block write
From: Will Deacon @ 2026-06-30 14:17 UTC (permalink / raw)
To: Shanker Donthineni
Cc: Vladimir Murzin, Catalin Marinas, Jason Gunthorpe,
linux-arm-kernel, Mark Rutland, linux-kernel, linux-doc,
Vikram Sethi, Jason Sequeira
In-Reply-To: <d75592c9-5292-4704-b024-6450ea0e8278@nvidia.com>
On Mon, Jun 29, 2026 at 06:09:11PM -0500, Shanker Donthineni wrote:
> On 6/29/2026 5:48 AM, Vladimir Murzin wrote:
> > > + : "memory");
> > > + src += sizeof(u64);
> > > + dst += sizeof(u64);
> > > + count -= sizeof(u64);
> > > + }
> > > + while (count) {
> > > + asm volatile("strb %w0, [%1]"
> > > + : : "rZ"(*(const u8 *)src), "r"(dst) : "memory");
> > > + src++;
> > > + dst++;
> > > + count--;
> > > + }
> > > +
> > > + iomem_block_store_barrier();
> > It is perhaps a matter of taste, but having the inline assembly
> > here (and in memset_io()) might make the code clearer. To a
> > casual reader, it would be obvious that the barrier is not
> > guaranteed and is only applicable to ARM64_WORKAROUND_DEVICE_STORE_RELEASE,
> > without having to jump back and forth through the code.
> >
> > Obliviously maintainers might have different preference ;)
Oblivious maintainer here :)
> Regarding the barrier, iomem_block_store_barrier() is declared
> static __always_inline, so it does not add a function call. The nop/dmb
> osh alternative is emitted directly in each caller. I used the helper to
> avoid duplicating the alternative sequence.
>
> I understand that placing the assembly directly in both functions could
> make its conditional nature more obvious. I do not have a strong preference
> and am happy to follow Will’s and Catalin’s preference here.
I agree with Vladimir that it would be clearer to inline the conditional
barrier.
It would be even better if we could avoid having to duplicate this code
to start with, but I can't immediately think of a better alternative.
Will
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox