* [PATCH v13 2/3] of: Factor arguments passed to of_map_id() into a struct
From: Vijayanand Jitta @ 2026-04-08 10:03 UTC (permalink / raw)
To: Nipun Gupta, Nikhil Agarwal, Joerg Roedel, Will Deacon,
Robin Murphy, Marc Zyngier, Lorenzo Pieralisi, Thomas Gleixner,
Saravana Kannan, Richard Zhu, Lucas Stach,
Krzysztof Wilczyński, Manivannan Sadhasivam, Bjorn Helgaas,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko,
Dmitry Baryshkov, Konrad Dybcio, Bjorn Andersson, Rob Herring,
Conor Dooley, Krzysztof Kozlowski, Prakash Gupta, Vikash Garodia
Cc: linux-kernel, iommu, linux-arm-kernel, devicetree, linux-pci, imx,
xen-devel, linux-arm-msm, Vijayanand Jitta, Charan Teja Kalla
In-Reply-To: <20260408-parse_iommu_cells-v13-0-fa921e92661b@oss.qualcomm.com>
From: Charan Teja Kalla <charan.kalla@oss.qualcomm.com>
Change of_map_id() to take a pointer to struct of_phandle_args
instead of passing target device node and translated IDs separately.
Update all callers accordingly.
Add an explicit filter_np parameter to of_map_id() and of_map_msi_id()
to separate the filter input from the output. Previously, the target
parameter served dual purpose: as an input filter (if non-NULL, only
match entries targeting that node) and as an output (receiving the
matched node with a reference held). Now filter_np is the explicit
input filter and arg->np is the pure output.
Previously, of_map_id() would call of_node_put() on the matched node
when a filter was provided, making reference ownership inconsistent.
Remove this internal of_node_put() call so that of_map_id() now always
transfers ownership of the matched node reference to the caller via
arg->np. Callers are now consistently responsible for releasing this
reference with of_node_put(arg->np) when done.
Acked-by: Frank Li <Frank.Li@nxp.com>
Suggested-by: Rob Herring (Arm) <robh@kernel.org>
Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Charan Teja Kalla <charan.kalla@oss.qualcomm.com>
Signed-off-by: Vijayanand Jitta <vijayanand.jitta@oss.qualcomm.com>
---
drivers/cdx/cdx_msi.c | 7 ++--
drivers/iommu/of_iommu.c | 4 +-
drivers/irqchip/irq-gic-its-msi-parent.c | 11 ++++--
drivers/of/base.c | 68 +++++++++++++++++---------------
drivers/of/irq.c | 10 ++++-
drivers/pci/controller/dwc/pci-imx6.c | 32 +++++++--------
drivers/pci/controller/pcie-apple.c | 5 ++-
drivers/xen/grant-dma-ops.c | 4 +-
include/linux/of.h | 14 ++++---
9 files changed, 89 insertions(+), 66 deletions(-)
diff --git a/drivers/cdx/cdx_msi.c b/drivers/cdx/cdx_msi.c
index 63b3544ec997..6924e07c7528 100644
--- a/drivers/cdx/cdx_msi.c
+++ b/drivers/cdx/cdx_msi.c
@@ -121,22 +121,23 @@ static int cdx_msi_prepare(struct irq_domain *msi_domain,
struct device *dev,
int nvec, msi_alloc_info_t *info)
{
+ struct of_phandle_args msi_spec = {};
struct cdx_device *cdx_dev = to_cdx_device(dev);
struct device *parent = cdx_dev->cdx->dev;
struct msi_domain_info *msi_info;
- u32 dev_id;
int ret;
/* Retrieve device ID from requestor ID using parent device */
- ret = of_map_msi_id(parent->of_node, cdx_dev->msi_dev_id, NULL, &dev_id);
+ ret = of_map_msi_id(parent->of_node, cdx_dev->msi_dev_id, NULL, &msi_spec);
if (ret) {
dev_err(dev, "of_map_id failed for MSI: %d\n", ret);
return ret;
}
+ of_node_put(msi_spec.np);
#ifdef GENERIC_MSI_DOMAIN_OPS
/* Set the device Id to be passed to the GIC-ITS */
- info->scratchpad[0].ul = dev_id;
+ info->scratchpad[0].ul = msi_spec.args[0];
#endif
msi_info = msi_get_domain_info(msi_domain->parent);
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index a511ecf21fcd..a18bb60f6f3d 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -45,10 +45,10 @@ static int of_iommu_configure_dev_id(struct device_node *master_np,
struct device *dev,
const u32 *id)
{
- struct of_phandle_args iommu_spec = { .args_count = 1 };
+ struct of_phandle_args iommu_spec = {};
int err;
- err = of_map_iommu_id(master_np, *id, &iommu_spec.np, iommu_spec.args);
+ err = of_map_iommu_id(master_np, *id, &iommu_spec);
if (err)
return err;
diff --git a/drivers/irqchip/irq-gic-its-msi-parent.c b/drivers/irqchip/irq-gic-its-msi-parent.c
index b63343a227a9..dd5f84b6470a 100644
--- a/drivers/irqchip/irq-gic-its-msi-parent.c
+++ b/drivers/irqchip/irq-gic-its-msi-parent.c
@@ -152,6 +152,8 @@ static int its_v5_pci_msi_prepare(struct irq_domain *domain, struct device *dev,
static int of_pmsi_get_msi_info(struct irq_domain *domain, struct device *dev, u32 *dev_id,
phys_addr_t *pa)
{
+ struct device_node *msi_ctrl __free(device_node) = NULL;
+ struct of_phandle_args msi_spec = {};
struct of_phandle_iterator it;
int ret;
@@ -178,9 +180,12 @@ static int of_pmsi_get_msi_info(struct irq_domain *domain, struct device *dev, u
}
}
- struct device_node *msi_ctrl __free(device_node) = NULL;
-
- return of_map_msi_id(dev->of_node, dev->id, &msi_ctrl, dev_id);
+ ret = of_map_msi_id(dev->of_node, dev->id, NULL, &msi_spec);
+ if (!ret) {
+ msi_ctrl = msi_spec.np;
+ *dev_id = msi_spec.args[0];
+ }
+ return ret;
}
static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
diff --git a/drivers/of/base.c b/drivers/of/base.c
index ae04487bd614..b3d002015192 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2102,36 +2102,37 @@ int of_find_last_cache_level(unsigned int cpu)
* @id: device ID to map.
* @map_name: property name of the map to use.
* @map_mask_name: optional property name of the mask to use.
- * @target: optional pointer to a target device node.
- * @id_out: optional pointer to receive the translated ID.
+ * @filter_np: optional device node to filter matches by, or NULL to match any.
+ * If non-NULL, only map entries targeting this node will be matched.
+ * @arg: pointer to a &struct of_phandle_args for the result. On success,
+ * @arg->args[0] will contain the translated ID. If a map entry was
+ * matched, @arg->np will be set to the target node with a reference
+ * held that the caller must release with of_node_put().
*
* Given a device ID, look up the appropriate implementation-defined
* platform ID and/or the target device which receives transactions on that
- * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
- * @id_out may be NULL if only the other is required. If @target points to
- * a non-NULL device node pointer, only entries targeting that node will be
- * matched; if it points to a NULL value, it will receive the device node of
- * the first matching target phandle, with a reference held.
+ * ID, as per the "iommu-map" and "msi-map" bindings.
*
* Return: 0 on success or a standard error code on failure.
*/
int of_map_id(const struct device_node *np, u32 id,
const char *map_name, const char *map_mask_name,
- struct device_node **target, u32 *id_out)
+ const struct device_node *filter_np, struct of_phandle_args *arg)
{
u32 map_mask, masked_id;
int map_len;
const __be32 *map = NULL;
- if (!np || !map_name || (!target && !id_out))
+ if (!np || !map_name || !arg)
return -EINVAL;
map = of_get_property(np, map_name, &map_len);
if (!map) {
- if (target)
+ if (filter_np)
return -ENODEV;
/* Otherwise, no map implies no translation */
- *id_out = id;
+ arg->args[0] = id;
+ arg->args_count = 1;
return 0;
}
@@ -2173,18 +2174,14 @@ int of_map_id(const struct device_node *np, u32 id,
if (!phandle_node)
return -ENODEV;
- if (target) {
- if (*target)
- of_node_put(phandle_node);
- else
- *target = phandle_node;
-
- if (*target != phandle_node)
- continue;
+ if (filter_np && filter_np != phandle_node) {
+ of_node_put(phandle_node);
+ continue;
}
- if (id_out)
- *id_out = masked_id - id_base + out_base;
+ arg->np = phandle_node;
+ arg->args[0] = masked_id - id_base + out_base;
+ arg->args_count = 1;
pr_debug("%pOF: %s, using mask %08x, id-base: %08x, out-base: %08x, length: %08x, id: %08x -> %08x\n",
np, map_name, map_mask, id_base, out_base,
@@ -2193,11 +2190,11 @@ int of_map_id(const struct device_node *np, u32 id,
}
pr_info("%pOF: no %s translation for id 0x%x on %pOF\n", np, map_name,
- id, target && *target ? *target : NULL);
+ id, filter_np);
/* Bypasses translation */
- if (id_out)
- *id_out = id;
+ arg->args[0] = id;
+ arg->args_count = 1;
return 0;
}
EXPORT_SYMBOL_GPL(of_map_id);
@@ -2207,17 +2204,19 @@ EXPORT_SYMBOL_GPL(of_map_id);
* @np: root complex device node.
* @id: Requester ID of the device (e.g. PCI RID/BDF or a platform
* stream/device ID) used as the lookup key in the iommu-map table.
- * @target: optional pointer to a target device node.
- * @id_out: optional pointer to receive the translated ID.
+ * @arg: pointer to a &struct of_phandle_args for the result. On success,
+ * @arg->args[0] contains the translated ID. If a map entry was matched,
+ * @arg->np holds a reference to the target node that the caller must
+ * release with of_node_put().
*
* Convenience wrapper around of_map_id() using "iommu-map" and "iommu-map-mask".
*
* Return: 0 on success or a standard error code on failure.
*/
int of_map_iommu_id(const struct device_node *np, u32 id,
- struct device_node **target, u32 *id_out)
+ struct of_phandle_args *arg)
{
- return of_map_id(np, id, "iommu-map", "iommu-map-mask", target, id_out);
+ return of_map_id(np, id, "iommu-map", "iommu-map-mask", NULL, arg);
}
EXPORT_SYMBOL_GPL(of_map_iommu_id);
@@ -2226,16 +2225,21 @@ EXPORT_SYMBOL_GPL(of_map_iommu_id);
* @np: root complex device node.
* @id: Requester ID of the device (e.g. PCI RID/BDF or a platform
* stream/device ID) used as the lookup key in the msi-map table.
- * @target: optional pointer to a target device node.
- * @id_out: optional pointer to receive the translated ID.
+ * @filter_np: optional MSI controller node to filter matches by, or NULL
+ * to match any. If non-NULL, only map entries targeting this node will
+ * be matched.
+ * @arg: pointer to a &struct of_phandle_args for the result. On success,
+ * @arg->args[0] contains the translated ID. If a map entry was matched,
+ * @arg->np holds a reference to the target node that the caller must
+ * release with of_node_put().
*
* Convenience wrapper around of_map_id() using "msi-map" and "msi-map-mask".
*
* Return: 0 on success or a standard error code on failure.
*/
int of_map_msi_id(const struct device_node *np, u32 id,
- struct device_node **target, u32 *id_out)
+ const struct device_node *filter_np, struct of_phandle_args *arg)
{
- return of_map_id(np, id, "msi-map", "msi-map-mask", target, id_out);
+ return of_map_id(np, id, "msi-map", "msi-map-mask", filter_np, arg);
}
EXPORT_SYMBOL_GPL(of_map_msi_id);
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index e37c1b3f8736..f86a56bd81fc 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -817,8 +817,16 @@ u32 of_msi_xlate(struct device *dev, struct device_node **msi_np, u32 id_in)
* "msi-map" or an "msi-parent" property.
*/
for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) {
- if (!of_map_msi_id(parent_dev->of_node, id_in, msi_np, &id_out))
+ struct of_phandle_args msi_spec = {};
+
+ if (!of_map_msi_id(parent_dev->of_node, id_in, *msi_np, &msi_spec)) {
+ id_out = msi_spec.args[0];
+ if (!*msi_np)
+ *msi_np = msi_spec.np;
+ else
+ of_node_put(msi_spec.np);
break;
+ }
if (!of_check_msi_parent(parent_dev->of_node, msi_np))
break;
}
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index bff8289f804a..c0544d9c0921 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -1137,30 +1137,32 @@ static void imx_pcie_remove_lut(struct imx_pcie *imx_pcie, u16 rid)
static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
{
+ struct of_phandle_args iommu_spec = {};
+ struct of_phandle_args msi_spec = {};
struct device *dev = imx_pcie->pci->dev;
- struct device_node *target;
u32 sid_i, sid_m;
int err_i, err_m;
u32 sid = 0;
- target = NULL;
- err_i = of_map_iommu_id(dev->of_node, rid, &target, &sid_i);
- if (target) {
- of_node_put(target);
- } else {
+ err_i = of_map_iommu_id(dev->of_node, rid, &iommu_spec);
+ if (!err_i)
+ sid_i = iommu_spec.args[0];
+ of_node_put(iommu_spec.np);
+ if (!err_i && !iommu_spec.np) {
/*
- * "target == NULL && err_i == 0" means RID out of map range.
- * Use 1:1 map RID to streamID. Hardware can't support this
- * because the streamID is only 6 bits
+ * "iommu_spec.np == NULL && err_i == 0" means RID out of map
+ * range. Use 1:1 map RID to streamID. Hardware can't support
+ * this because the streamID is only 6 bits.
*/
err_i = -EINVAL;
}
- target = NULL;
- err_m = of_map_msi_id(dev->of_node, rid, &target, &sid_m);
-
+ err_m = of_map_msi_id(dev->of_node, rid, NULL, &msi_spec);
+ if (!err_m)
+ sid_m = msi_spec.args[0];
+ of_node_put(msi_spec.np);
/*
- * err_m target
+ * err_m msi_spec.np
* 0 NULL RID out of range. Use 1:1 map RID to
* streamID, Current hardware can't
* support it, so return -EINVAL.
@@ -1168,10 +1170,8 @@ static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
* 0 != NULL Get correct streamID from RID
* != 0 != NULL Invalid combination
*/
- if (!err_m && !target)
+ if (!err_m && !msi_spec.np)
return -EINVAL;
- else if (target)
- of_node_put(target); /* Find streamID map entry for RID in msi-map */
/*
* msi-map iommu-map
diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index a0937b7b3c4d..c2cffc0659f4 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -755,6 +755,7 @@ static int apple_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_d
{
u32 sid, rid = pci_dev_id(pdev);
struct apple_pcie_port *port;
+ struct of_phandle_args iommu_spec = {};
int idx, err;
port = apple_pcie_get_port(pdev);
@@ -764,10 +765,12 @@ static int apple_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_d
dev_dbg(&pdev->dev, "added to bus %s, index %d\n",
pci_name(pdev->bus->self), port->idx);
- err = of_map_iommu_id(port->pcie->dev->of_node, rid, NULL, &sid);
+ err = of_map_iommu_id(port->pcie->dev->of_node, rid, &iommu_spec);
if (err)
return err;
+ of_node_put(iommu_spec.np);
+ sid = iommu_spec.args[0];
mutex_lock(&port->pcie->lock);
idx = bitmap_find_free_region(port->sid_map, port->sid_map_sz, 0);
diff --git a/drivers/xen/grant-dma-ops.c b/drivers/xen/grant-dma-ops.c
index 1b7696b2d762..2aa1a772a0ff 100644
--- a/drivers/xen/grant-dma-ops.c
+++ b/drivers/xen/grant-dma-ops.c
@@ -319,13 +319,13 @@ static int xen_dt_grant_init_backend_domid(struct device *dev,
struct device_node *np,
domid_t *backend_domid)
{
- struct of_phandle_args iommu_spec = { .args_count = 1 };
+ struct of_phandle_args iommu_spec = {};
if (dev_is_pci(dev)) {
struct pci_dev *pdev = to_pci_dev(dev);
u32 rid = PCI_DEVID(pdev->bus->number, pdev->devfn);
- if (of_map_iommu_id(np, rid, &iommu_spec.np, iommu_spec.args)) {
+ if (of_map_iommu_id(np, rid, &iommu_spec)) {
dev_dbg(dev, "Cannot translate ID\n");
return -ESRCH;
}
diff --git a/include/linux/of.h b/include/linux/of.h
index fe841f3cc747..8548cd9eb4f1 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -463,13 +463,13 @@ bool of_console_check(const struct device_node *dn, char *name, int index);
int of_map_id(const struct device_node *np, u32 id,
const char *map_name, const char *map_mask_name,
- struct device_node **target, u32 *id_out);
+ const struct device_node *filter_np, struct of_phandle_args *arg);
int of_map_iommu_id(const struct device_node *np, u32 id,
- struct device_node **target, u32 *id_out);
+ struct of_phandle_args *arg);
int of_map_msi_id(const struct device_node *np, u32 id,
- struct device_node **target, u32 *id_out);
+ const struct device_node *filter_np, struct of_phandle_args *arg);
phys_addr_t of_dma_get_max_cpu_address(struct device_node *np);
@@ -935,19 +935,21 @@ static inline void of_property_clear_flag(struct property *p, unsigned long flag
static inline int of_map_id(const struct device_node *np, u32 id,
const char *map_name, const char *map_mask_name,
- struct device_node **target, u32 *id_out)
+ const struct device_node *filter_np,
+ struct of_phandle_args *arg)
{
return -EINVAL;
}
static inline int of_map_iommu_id(const struct device_node *np, u32 id,
- struct device_node **target, u32 *id_out)
+ struct of_phandle_args *arg)
{
return -EINVAL;
}
static inline int of_map_msi_id(const struct device_node *np, u32 id,
- struct device_node **target, u32 *id_out)
+ const struct device_node *filter_np,
+ struct of_phandle_args *arg)
{
return -EINVAL;
}
--
2.34.1
^ permalink raw reply related
* [PATCH v13 1/3] of: Add convenience wrappers for of_map_id()
From: Vijayanand Jitta @ 2026-04-08 10:03 UTC (permalink / raw)
To: Nipun Gupta, Nikhil Agarwal, Joerg Roedel, Will Deacon,
Robin Murphy, Marc Zyngier, Lorenzo Pieralisi, Thomas Gleixner,
Saravana Kannan, Richard Zhu, Lucas Stach,
Krzysztof Wilczyński, Manivannan Sadhasivam, Bjorn Helgaas,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko,
Dmitry Baryshkov, Konrad Dybcio, Bjorn Andersson, Rob Herring,
Conor Dooley, Krzysztof Kozlowski, Prakash Gupta, Vikash Garodia
Cc: linux-kernel, iommu, linux-arm-kernel, devicetree, linux-pci, imx,
xen-devel, linux-arm-msm, Vijayanand Jitta
In-Reply-To: <20260408-parse_iommu_cells-v13-0-fa921e92661b@oss.qualcomm.com>
From: Robin Murphy <robin.murphy@arm.com>
Since we now have quite a few users parsing "iommu-map" and "msi-map"
properties, give them some wrappers to conveniently encapsulate the
appropriate sets of property names. This will also make it easier to
then change of_map_id() to correctly account for specifier cells.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Acked-by: Marc Zyngier <maz@kernel.org>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Vijayanand Jitta <vijayanand.jitta@oss.qualcomm.com>
---
drivers/cdx/cdx_msi.c | 3 +--
drivers/iommu/of_iommu.c | 4 +---
drivers/irqchip/irq-gic-its-msi-parent.c | 2 +-
drivers/of/base.c | 38 ++++++++++++++++++++++++++++++++
drivers/of/irq.c | 3 +--
drivers/pci/controller/dwc/pci-imx6.c | 6 ++---
drivers/pci/controller/pcie-apple.c | 3 +--
drivers/xen/grant-dma-ops.c | 3 +--
include/linux/of.h | 18 +++++++++++++++
9 files changed, 64 insertions(+), 16 deletions(-)
diff --git a/drivers/cdx/cdx_msi.c b/drivers/cdx/cdx_msi.c
index 91b95422b263..63b3544ec997 100644
--- a/drivers/cdx/cdx_msi.c
+++ b/drivers/cdx/cdx_msi.c
@@ -128,8 +128,7 @@ static int cdx_msi_prepare(struct irq_domain *msi_domain,
int ret;
/* Retrieve device ID from requestor ID using parent device */
- ret = of_map_id(parent->of_node, cdx_dev->msi_dev_id, "msi-map", "msi-map-mask",
- NULL, &dev_id);
+ ret = of_map_msi_id(parent->of_node, cdx_dev->msi_dev_id, NULL, &dev_id);
if (ret) {
dev_err(dev, "of_map_id failed for MSI: %d\n", ret);
return ret;
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 6b989a62def2..a511ecf21fcd 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -48,9 +48,7 @@ static int of_iommu_configure_dev_id(struct device_node *master_np,
struct of_phandle_args iommu_spec = { .args_count = 1 };
int err;
- err = of_map_id(master_np, *id, "iommu-map",
- "iommu-map-mask", &iommu_spec.np,
- iommu_spec.args);
+ err = of_map_iommu_id(master_np, *id, &iommu_spec.np, iommu_spec.args);
if (err)
return err;
diff --git a/drivers/irqchip/irq-gic-its-msi-parent.c b/drivers/irqchip/irq-gic-its-msi-parent.c
index d36b278ae66c..b63343a227a9 100644
--- a/drivers/irqchip/irq-gic-its-msi-parent.c
+++ b/drivers/irqchip/irq-gic-its-msi-parent.c
@@ -180,7 +180,7 @@ static int of_pmsi_get_msi_info(struct irq_domain *domain, struct device *dev, u
struct device_node *msi_ctrl __free(device_node) = NULL;
- return of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &msi_ctrl, dev_id);
+ return of_map_msi_id(dev->of_node, dev->id, &msi_ctrl, dev_id);
}
static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 57420806c1a2..ae04487bd614 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2201,3 +2201,41 @@ int of_map_id(const struct device_node *np, u32 id,
return 0;
}
EXPORT_SYMBOL_GPL(of_map_id);
+
+/**
+ * of_map_iommu_id - Translate an ID using "iommu-map" bindings.
+ * @np: root complex device node.
+ * @id: Requester ID of the device (e.g. PCI RID/BDF or a platform
+ * stream/device ID) used as the lookup key in the iommu-map table.
+ * @target: optional pointer to a target device node.
+ * @id_out: optional pointer to receive the translated ID.
+ *
+ * Convenience wrapper around of_map_id() using "iommu-map" and "iommu-map-mask".
+ *
+ * Return: 0 on success or a standard error code on failure.
+ */
+int of_map_iommu_id(const struct device_node *np, u32 id,
+ struct device_node **target, u32 *id_out)
+{
+ return of_map_id(np, id, "iommu-map", "iommu-map-mask", target, id_out);
+}
+EXPORT_SYMBOL_GPL(of_map_iommu_id);
+
+/**
+ * of_map_msi_id - Translate an ID using "msi-map" bindings.
+ * @np: root complex device node.
+ * @id: Requester ID of the device (e.g. PCI RID/BDF or a platform
+ * stream/device ID) used as the lookup key in the msi-map table.
+ * @target: optional pointer to a target device node.
+ * @id_out: optional pointer to receive the translated ID.
+ *
+ * Convenience wrapper around of_map_id() using "msi-map" and "msi-map-mask".
+ *
+ * Return: 0 on success or a standard error code on failure.
+ */
+int of_map_msi_id(const struct device_node *np, u32 id,
+ struct device_node **target, u32 *id_out)
+{
+ return of_map_id(np, id, "msi-map", "msi-map-mask", target, id_out);
+}
+EXPORT_SYMBOL_GPL(of_map_msi_id);
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 6367c67732d2..e37c1b3f8736 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -817,8 +817,7 @@ u32 of_msi_xlate(struct device *dev, struct device_node **msi_np, u32 id_in)
* "msi-map" or an "msi-parent" property.
*/
for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) {
- if (!of_map_id(parent_dev->of_node, id_in, "msi-map",
- "msi-map-mask", msi_np, &id_out))
+ if (!of_map_msi_id(parent_dev->of_node, id_in, msi_np, &id_out))
break;
if (!of_check_msi_parent(parent_dev->of_node, msi_np))
break;
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index a5b8d0b71677..bff8289f804a 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -1144,8 +1144,7 @@ static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
u32 sid = 0;
target = NULL;
- err_i = of_map_id(dev->of_node, rid, "iommu-map", "iommu-map-mask",
- &target, &sid_i);
+ err_i = of_map_iommu_id(dev->of_node, rid, &target, &sid_i);
if (target) {
of_node_put(target);
} else {
@@ -1158,8 +1157,7 @@ static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
}
target = NULL;
- err_m = of_map_id(dev->of_node, rid, "msi-map", "msi-map-mask",
- &target, &sid_m);
+ err_m = of_map_msi_id(dev->of_node, rid, &target, &sid_m);
/*
* err_m target
diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index 2d92fc79f6dd..a0937b7b3c4d 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -764,8 +764,7 @@ static int apple_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_d
dev_dbg(&pdev->dev, "added to bus %s, index %d\n",
pci_name(pdev->bus->self), port->idx);
- err = of_map_id(port->pcie->dev->of_node, rid, "iommu-map",
- "iommu-map-mask", NULL, &sid);
+ err = of_map_iommu_id(port->pcie->dev->of_node, rid, NULL, &sid);
if (err)
return err;
diff --git a/drivers/xen/grant-dma-ops.c b/drivers/xen/grant-dma-ops.c
index c2603e700178..1b7696b2d762 100644
--- a/drivers/xen/grant-dma-ops.c
+++ b/drivers/xen/grant-dma-ops.c
@@ -325,8 +325,7 @@ static int xen_dt_grant_init_backend_domid(struct device *dev,
struct pci_dev *pdev = to_pci_dev(dev);
u32 rid = PCI_DEVID(pdev->bus->number, pdev->devfn);
- if (of_map_id(np, rid, "iommu-map", "iommu-map-mask", &iommu_spec.np,
- iommu_spec.args)) {
+ if (of_map_iommu_id(np, rid, &iommu_spec.np, iommu_spec.args)) {
dev_dbg(dev, "Cannot translate ID\n");
return -ESRCH;
}
diff --git a/include/linux/of.h b/include/linux/of.h
index be6ec4916adf..fe841f3cc747 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -465,6 +465,12 @@ int of_map_id(const struct device_node *np, u32 id,
const char *map_name, const char *map_mask_name,
struct device_node **target, u32 *id_out);
+int of_map_iommu_id(const struct device_node *np, u32 id,
+ struct device_node **target, u32 *id_out);
+
+int of_map_msi_id(const struct device_node *np, u32 id,
+ struct device_node **target, u32 *id_out);
+
phys_addr_t of_dma_get_max_cpu_address(struct device_node *np);
struct kimage;
@@ -934,6 +940,18 @@ static inline int of_map_id(const struct device_node *np, u32 id,
return -EINVAL;
}
+static inline int of_map_iommu_id(const struct device_node *np, u32 id,
+ struct device_node **target, u32 *id_out)
+{
+ return -EINVAL;
+}
+
+static inline int of_map_msi_id(const struct device_node *np, u32 id,
+ struct device_node **target, u32 *id_out)
+{
+ return -EINVAL;
+}
+
static inline phys_addr_t of_dma_get_max_cpu_address(struct device_node *np)
{
return PHYS_ADDR_MAX;
--
2.34.1
^ permalink raw reply related
* [PATCH v13 0/3] of: parsing of multi #{iommu,msi}-cells in maps
From: Vijayanand Jitta @ 2026-04-08 10:03 UTC (permalink / raw)
To: Nipun Gupta, Nikhil Agarwal, Joerg Roedel, Will Deacon,
Robin Murphy, Marc Zyngier, Lorenzo Pieralisi, Thomas Gleixner,
Saravana Kannan, Richard Zhu, Lucas Stach,
Krzysztof Wilczyński, Manivannan Sadhasivam, Bjorn Helgaas,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko,
Dmitry Baryshkov, Konrad Dybcio, Bjorn Andersson, Rob Herring,
Conor Dooley, Krzysztof Kozlowski, Prakash Gupta, Vikash Garodia
Cc: linux-kernel, iommu, linux-arm-kernel, devicetree, linux-pci, imx,
xen-devel, linux-arm-msm, Vijayanand Jitta, Charan Teja Kalla
So far our parsing of {iommu,msi}-map properties has always blindly
assumed that the output specifiers will always have exactly 1 cell.
This typically does happen to be the case, but is not actually enforced
(and the PCI msi-map binding even explicitly states support for 0 or 1
cells) - as a result we've now ended up with dodgy DTs out in the field
which depend on this behaviour to map a 1-cell specifier for a 2-cell
provider, despite that being bogus per the bindings themselves.
Since there is some potential use[1] in being able to map at least
single input IDs to multi-cell output specifiers (and properly support
0-cell outputs as well), add support for properly parsing and using the
target nodes' #cells values, albeit with the unfortunate complication of
still having to work around expectations of the old behaviour too.
-- Robin.
Unlike single #{}-cell, it is complex to establish a linear relation
between input 'id' and output specifier for multi-cell properties, thus
it is always expected that len never going to be > 1.
These changes have been tested on QEMU for the arm64 architecture.
Since, this would also need update in dt-schema, raised PR[2] for the
same.
[1] https://lore.kernel.org/all/20250627-video_cb-v3-0-51e18c0ffbce@quicinc.com/
[2] PR for iommu-map dtschema: https://github.com/devicetree-org/dt-schema/pull/184
Robin,
Could this series be pulled into an immutable branch/tag, if it doesn't make
it into the v7.1 merge window? There are client changes dependent on it,
So it would help to get them moving forward rather than waiting another
cycle.
Thanks,
Vijay
V13:
- Fix bad_map handling in of_map_id(): 'cells' is re-initialized to 0
on each loop iteration, so the !bad_map guard was insufficient, cells
stayed 0 for all entries after the first. Fix by explicitly setting
cells=1 when bad_map is true on every iteration.
- Collected Acked-by from Frank Li.
Link to v12:
https://patch.msgid.link/20260331-parse_iommu_cells-v12-0-decfd305eea9@oss.qualcomm.com
V12:
- Call of_node_put() unconditionally in imx_pcie_add_lut_by_rid()
thereby addressing comments from Bjorn Helgaas.
Link to v11:
https://lore.kernel.org/r/20260325-parse_iommu_cells-v11-0-1fefa5c0e82c@oss.qualcomm.com
V11:
- Added explicit filter_np parameter to of_map_id() and of_map_msi_id()
per Dmitry Baryshkov's review feedback, making the filter explicit
instead of overloading arg->np as both input filter and output parameter.
- Removed of_node_put() from inside of_map_id(), making the caller responsible
for reference management. Updated of_msi_xlate() to properly handle reference counting.
- Collected ACKed by tags, and fixed minor typos.
Link to v10:
https://lore.kernel.org/r/20260309-parse_iommu_cells-v10-0-c62fcaa5a1d8@oss.qualcomm.com
V10:
- Move of_map_iommu_id()/of_map_msi_id() from include/linux/of.h to
drivers/of/base.c as out-of-line helpers per feedback from Marc Zyngier
and Rob Herring.
- Add kernel-doc to document both helpers for discoverability and
usage clarity.
- Fix of_map_msi_id() wrapper and all its callers (cdx_msi.c,
irq-gic-its-msi-parent.c, drivers/of/irq.c) to correctly use the new
struct of_phandle_args-based API with proper of_node_put() handling
as per feeback from Dmitry.
Link to v9:
https://lore.kernel.org/r/20260301-parse_iommu_cells-v9-0-4d1bceecc5e1@oss.qualcomm.com
V9:
- Updated TO/CC list based on feedback to include all relevant
maintainers.
- No functional changes to the patches themselves.
Link to V8:
https://lore.kernel.org/all/20260226074245.3098486-1-vijayanand.jitta@oss.qualcomm.com/
V8:
- Removed mentions of of_map_args from commit message to match code.
Link to V7:
https://lore.kernel.org/all/20260210101157.2145113-1-vijayanand.jitta@oss.qualcomm.com/
V7:
- Removed of_map_id_args structure and replaced it with
of_phandle_args as suggested by Dmitry.
Link to V6:
https://lore.kernel.org/all/20260121055400.937856-1-vijayanand.jitta@oss.qualcomm.com/
V6:
- Fixed build error reported by kernel test bot.
Link to V5:
https://lore.kernel.org/all/20260118181125.1436036-1-vijayanand.jitta@oss.qualcomm.com/
V5:
- Fixed Build Warnings.
- Raised PR for iommu-map dtschema: https://github.com/devicetree-org/dt-schema/pull/184
Link to V4:
https://lore.kernel.org/all/20251231114257.2382820-1-vijayanand.jitta@oss.qualcomm.com/
V4:
- Added Reviewed-by tag.
- Resolved warnings reported by kernel test bot, minor code
reorganization.
Link to V3:
https://lore.kernel.org/all/20251221213602.2413124-1-vijayanand.jitta@oss.qualcomm.com/
V3:
- Added Reviewed-by tag.
- Updated of_map_id_args struct as a wrapper to of_phandle_args and
added comment description as suggested by Rob Herring.
Link to V2:
https://lore.kernel.org/all/20251204095530.8627-1-vijayanand.jitta@oss.qualcomm.com/
V2:
- Incorporated the patches from Robin that does the clean implementation.
- Dropped the patches the were adding multi-map support from this series
as suggested.
V1:
https://lore.kernel.org/all/cover.1762235099.git.charan.kalla@oss.qualcomm.com/
RFC:
https://lore.kernel.org/all/20250928171718.436440-1-charan.kalla@oss.qualcomm.com/#r
Signed-off-by: Vijayanand Jitta <vijayanand.jitta@oss.qualcomm.com>
---
---
Charan Teja Kalla (1):
of: Factor arguments passed to of_map_id() into a struct
Robin Murphy (2):
of: Add convenience wrappers for of_map_id()
of: Respect #{iommu,msi}-cells in maps
drivers/cdx/cdx_msi.c | 8 +-
drivers/iommu/of_iommu.c | 6 +-
drivers/irqchip/irq-gic-its-msi-parent.c | 11 +-
drivers/of/base.c | 215 ++++++++++++++++++++++++-------
drivers/of/irq.c | 11 +-
drivers/pci/controller/dwc/pci-imx6.c | 34 +++--
drivers/pci/controller/pcie-apple.c | 6 +-
drivers/xen/grant-dma-ops.c | 5 +-
include/linux/of.h | 30 ++++-
9 files changed, 242 insertions(+), 84 deletions(-)
---
base-commit: 3fa5e5702a82d259897bd7e209469bc06368bf31
change-id: 20260301-parse_iommu_cells-1c33768aebba
Best regards,
--
Vijayanand Jitta <vijayanand.jitta@oss.qualcomm.com>
^ permalink raw reply
* RE: [PATCH v4 net-next 11/14] net: dsa: netc: add phylink MAC operations
From: Wei Fang @ 2026-04-08 9:44 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Claudiu Manoil, Vladimir Oltean, Clark Wang,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
pabeni@redhat.com, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, f.fainelli@gmail.com, Frank Li,
chleroy@kernel.org, horms@kernel.org, linux@armlinux.org.uk,
andrew@lunn.ch, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev
In-Reply-To: <20260403011740.1795694-1-kuba@kernel.org>
> > +static void netc_port_mac_rx_enable(struct netc_port *np)
> > +{
> > + netc_port_rmw(np, NETC_POR, PCR_RXDIS, 0);
> > + netc_mac_port_rmw(np, NETC_PM_CMD_CFG(0), PM_CMD_CFG_RX_EN,
> > + PM_CMD_CFG_RX_EN);
> > +}
>
> Pseudo ports (like the CPU port) bypass PMAC register accesses during
> graceful stop via is_netc_pseudo_port(). Should there be a similar check
> here, and in netc_port_set_mac_mode(), to prevent accessing physical MAC
> registers on pseudo ports?
netc_mac_port_rmw() has checked whether the port is pseudo MAC. See
below.
static void netc_mac_port_rmw(struct netc_port *np, u32 reg,
u32 mask, u32 val)
{
u32 old, new;
if (is_netc_pseudo_port(np))
return;
[...]
}
>
> Additionally, when np->caps.pmac is true, netc_port_mac_rx_graceful_stop()
> disables the preemption MAC via NETC_PM_CMD_CFG(1). Should this function
> re-enable it when bringing the link back up?
netc_mac_port_rmw() also set preemption MAC if the port supports preemtion.
static void netc_mac_port_rmw(struct netc_port *np, u32 reg,
u32 mask, u32 val)
{
[...]
if (np->caps.pmac)
netc_port_wr(np, reg + NETC_PMAC_OFFSET, new);
}
>
> > +static void netc_port_wait_rx_empty(struct netc_port *np, int mac)
> > +{
> > + u32 val;
> > +
> > + if (read_poll_timeout(netc_port_rd, val, val & PM_IEVENT_RX_EMPTY,
> > + 100, 10000, false, np, NETC_PM_IEVENT(mac)))
> > + dev_warn(np->switch_priv->dev,
> > + "MAC %d of swp%d RX is not empty\n", mac,
> > + np->dp->index);
> > +}
>
> Is NETC_PM_IEVENT a sticky write-1-to-clear register? If the RX FIFO had
> previously emptied during normal operation, could this bit already be set,
> causing read_poll_timeout() to return immediately without waiting?
NETC_PM_IEVENT[RX_EMPTY] is a read only bit. It will be cleared
if Rx FIFO not empty or Rx packet receive in process. And it will be
set if Rx FIFO is empty and no Rx packet receive in process.
>
> > +static void netc_port_mac_rx_graceful_stop(struct netc_port *np)
> > +{
> > + u32 val;
> > +
> > + if (is_netc_pseudo_port(np))
> > + goto check_rx_busy;
> > +
> > + if (np->caps.pmac) {
> > + netc_port_rmw(np, NETC_PM_CMD_CFG(1), PM_CMD_CFG_RX_EN,
> 0);
> > + netc_port_wait_rx_empty(np, 1);
> > + }
> > +
> > + netc_port_rmw(np, NETC_PM_CMD_CFG(0), PM_CMD_CFG_RX_EN, 0);
> > + netc_port_wait_rx_empty(np, 0);
> > +
> > +check_rx_busy:
> > + if (read_poll_timeout(netc_port_rd, val, !(val & PSR_RX_BUSY),
> > + 100, 10000, false, np, NETC_PSR))
> > + dev_warn(np->switch_priv->dev, "swp%d RX is busy\n",
> > + np->dp->index);
> > +
> > + netc_port_rmw(np, NETC_POR, PCR_RXDIS, PCR_RXDIS);
> > +}
>
> For pseudo ports, the code jumps directly to check_rx_busy and polls for
> PSR_RX_BUSY to clear. Since PCR_RXDIS is only set after the polling
> completes, will the RX pipeline continue accepting traffic and cause this
> poll to always timeout on an active link?
For the pseudo ports, no need to check the PSR_RX_BUSY bit, only need
to set PCR_RXDIS bit to discard RX packets. I will improve it.
>
> > +static void netc_mac_link_up(struct phylink_config *config,
> > + struct phy_device *phy, unsigned int mode,
> > + phy_interface_t interface, int speed,
> > + int duplex, bool tx_pause, bool rx_pause)
> > +{
> > + struct dsa_port *dp = dsa_phylink_to_port(config);
> > + struct netc_port *np;
> > +
> > + np = NETC_PORT(dp->ds, dp->index);
> > + netc_port_set_speed(np, speed);
> > +
> > + if (phy_interface_mode_is_rgmii(interface))
> > + netc_port_set_rgmii_mac(np, speed, duplex);
> > +
> > + if (interface == PHY_INTERFACE_MODE_RMII ||
> > + interface == PHY_INTERFACE_MODE_REVMII ||
> > + interface == PHY_INTERFACE_MODE_MII)
> > + netc_port_set_rmii_mii_mac(np, speed, duplex);
> > +
> > + netc_port_mac_rx_enable(np);
> > +}
>
> The callback imx94_switch_phylink_get_caps() advertises MAC_ASYM_PAUSE
> and
> MAC_SYM_PAUSE capabilities. Is it expected that tx_pause and rx_pause are
> ignored here? If flow control is implemented in a subsequent patch, should
> the advertisement be deferred until then?
Okay, I will move the advertisement to the subsequent patch.
^ permalink raw reply
* [PATCH v5 4/4] perf arm_spe: Improve SIMD flags setting
From: Leo Yan @ 2026-04-08 9:42 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Namhyung Kim, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Mark Rutland
Cc: Arnaldo Carvalho de Melo, linux-perf-users, linux-arm-kernel,
Leo Yan
In-Reply-To: <20260408-perf_support_arm_spev1-3-v5-0-b5bcea6217bb@arm.com>
Fill in ASE and SME operations for the SIMD arch field.
Also set the predicate flags for SVE and SME, but differences between
them: SME does not have a predicate flag, so the setting is based on
events. SVE provides a predicate flag to indicate whether the predicate
is disabled, which allows it to be distinguished into four cases: full
predicates, empty predicates, fully predicated, and disabled predicates.
After:
perf report -s +simd
...
0.06% 0.06% sve-test sve-test [.] setz [p] SVE
0.06% 0.06% sve-test [kernel.kallsyms] [k] do_raw_spin_lock
0.06% 0.06% sve-test sve-test [.] getz [p] SVE
0.06% 0.06% sve-test [kernel.kallsyms] [k] timekeeping_advance
0.06% 0.06% sve-test sve-test [.] getz [d] SVE
0.06% 0.06% sve-test [kernel.kallsyms] [k] update_load_avg
0.06% 0.06% sve-test sve-test [.] getz [e] SVE
0.05% 0.05% sve-test sve-test [.] setz [e] SVE
0.05% 0.05% sve-test [kernel.kallsyms] [k] update_curr
0.05% 0.05% sve-test sve-test [.] setz [d] SVE
0.05% 0.05% sve-test [kernel.kallsyms] [k] do_raw_spin_unlock
0.05% 0.05% sve-test [kernel.kallsyms] [k] timekeeping_update_from_shadow.constprop.0
0.05% 0.05% sve-test sve-test [.] getz [f] SVE
0.05% 0.05% sve-test sve-test [.] setz [f] SVE
Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Leo Yan <leo.yan@arm.com>
---
tools/perf/util/arm-spe.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
index 70dd9bee47c755f19a51b80c6df3499180de9540..e5835042acdf7685f95e19665cd45f97ed868275 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -353,12 +353,26 @@ static struct simd_flags arm_spe__synth_simd_flags(const struct arm_spe_record *
if (record->op & ARM_SPE_OP_SVE)
simd_flags.arch |= SIMD_OP_FLAGS_ARCH_SVE;
-
- if (record->type & ARM_SPE_SVE_PARTIAL_PRED)
- simd_flags.pred |= SIMD_OP_FLAGS_PRED_PARTIAL;
-
- if (record->type & ARM_SPE_SVE_EMPTY_PRED)
- simd_flags.pred |= SIMD_OP_FLAGS_PRED_EMPTY;
+ else if (record->op & ARM_SPE_OP_SME)
+ simd_flags.arch |= SIMD_OP_FLAGS_ARCH_SME;
+ else if (record->op & (ARM_SPE_OP_ASE | ARM_SPE_OP_SIMD_FP))
+ simd_flags.arch |= SIMD_OP_FLAGS_ARCH_ASE;
+
+ if (record->op & ARM_SPE_OP_SVE) {
+ if (!(record->op & ARM_SPE_OP_PRED))
+ simd_flags.pred = SIMD_OP_FLAGS_PRED_DISABLED;
+ else if (record->type & ARM_SPE_SVE_PARTIAL_PRED)
+ simd_flags.pred = SIMD_OP_FLAGS_PRED_PARTIAL;
+ else if (record->type & ARM_SPE_SVE_EMPTY_PRED)
+ simd_flags.pred = SIMD_OP_FLAGS_PRED_EMPTY;
+ else
+ simd_flags.pred = SIMD_OP_FLAGS_PRED_FULL;
+ } else {
+ if (record->type & ARM_SPE_SVE_PARTIAL_PRED)
+ simd_flags.pred = SIMD_OP_FLAGS_PRED_PARTIAL;
+ else if (record->type & ARM_SPE_SVE_EMPTY_PRED)
+ simd_flags.pred = SIMD_OP_FLAGS_PRED_EMPTY;
+ }
return simd_flags;
}
--
2.34.1
^ permalink raw reply related
* [PATCH RFC net-next 09/10] net: stmmac: clean up test for rx_coe debug printing
From: Russell King (Oracle) @ 2026-04-08 9:27 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai, David S. Miller,
Eric Dumazet, Jakub Kicinski, Jitendra Vegiraju, linux-arm-kernel,
linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <adYfPBHsXxQUsMyr@shell.armlinux.org.uk>
The test for printing rx_coe as opposed to rx_coe_type[12] and
rxfifo_over_2048 has checked for an XGMAC core or the Synopssys IP
version (snpsver) >= v4.0.
Since the Synopsys IP version depends on the core type, avoid using it.
The GMAC4 core type uses dwmac4_get_hw_feature(), which populates
rx_coe but not rx_coe_type[12] or rxfifo_over_2048. XGMAC is the same
but via dwxgmac2_get_hw_feature().
dwmac-motorcomm populates rx_coe but not the others, and sets the core
type to GMAC4. The Synopsys IP version is likely >= 4, but in any case
printing rx_coe is clearly more correct.
Lastly, dwmac-sun8i is an oddball - it sets rx_coe, but does not set
core_type, leaving it as the defeault DWMAC_CORE_MAC100 since as far
as I can see, none of the .dtsi files for this platform use any of the
versioned snps,gmac-* compatibles. Moreover, sun8i_dwmac_setup() sets
snpsver to zero (which stmmac_get_version() will have already done) so
this has always used the rx_coe_type[12] path.
Change the test to check for GMAC4 or XGMAC which covers the cases
where rx_coe is set from the core hardware features.
Also add a comment for the GMAC to GMAC4+ rx_coe feature translation in
stmmac_hw_init(), and document rx_coe in struct plat_stmmacenet_data.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 11 +++++++++--
include/linux/stmmac.h | 7 +++++++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index e47321119c83..93c031b3cfd5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -6624,11 +6624,15 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v)
seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
seq_printf(seq, "\tChecksum Offload in TX: %s\n",
(priv->dma_cap.tx_coe) ? "Y" : "N");
- if (priv->snpsver >= DWMAC_CORE_4_00 ||
- priv->plat->core_type == DWMAC_CORE_XGMAC) {
+ if (dwmac_is_xmac(priv->plat->core_type)) {
+ /* gmac4, xgmac, and motorcomm populate this. */
seq_printf(seq, "\tIP Checksum Offload in RX: %s\n",
(priv->dma_cap.rx_coe) ? "Y" : "N");
} else {
+ /* only dwmac1000 has these three. sun8i sets rx_coe, but
+ * sets snpsver to zero and leaves core_Type as MAC100, so
+ * uses this path.
+ */
seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
(priv->dma_cap.rx_coe_type1) ? "Y" : "N");
seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
@@ -7441,6 +7445,9 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
/* In case of GMAC4 rx_coe is from HW cap register. */
priv->plat->rx_coe = priv->dma_cap.rx_coe;
+ /* GMAC (dwmac1000) has separate bits for the Rx COE type.
+ * Translate to the GMAC4/XGMAC rx_coe feature code.
+ */
if (priv->dma_cap.rx_coe_type2)
priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
else if (priv->dma_cap.rx_coe_type1)
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 4430b967abde..c80d45de0067 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -256,6 +256,13 @@ struct plat_stmmacenet_data {
bool force_sf_dma_mode;
bool force_thresh_dma_mode;
bool riwt_off;
+ /* rx_coe:
+ * for dwmac100, rx_coe does not appear to be defined.
+ * for dwmac1000, rx_coe takes one of the STMMAC_RX_COE_* constants,
+ * which will be derived from the RXTYP[12]COE hardware feature bits.
+ * for dwmac4 and xgmac, rx_coe is a boolean from the RXCOESEL hardware
+ * feature bit.
+ */
int rx_coe;
int max_speed;
int maxmtu;
--
2.47.3
^ permalink raw reply related
* [PATCH v5 3/4] perf report: Update document for SIMD flags
From: Leo Yan @ 2026-04-08 9:42 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Namhyung Kim, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Mark Rutland
Cc: Arnaldo Carvalho de Melo, linux-perf-users, linux-arm-kernel,
Leo Yan
In-Reply-To: <20260408-perf_support_arm_spev1-3-v5-0-b5bcea6217bb@arm.com>
Update SIMD architecture and predicate flags.
Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Leo Yan <leo.yan@arm.com>
---
tools/perf/Documentation/perf-report.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 52f316628e43ac9851ecaa85f706e22c26294649..22f87eaa3279653836eaaa07a358c14f2e0afa75 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -136,7 +136,10 @@ OPTIONS
- addr: (Full) virtual address of the sampled instruction
- retire_lat: On X86, this reports pipeline stall of this instruction compared
to the previous instruction in cycles. And currently supported only on X86
- - simd: Flags describing a SIMD operation. "e" for empty Arm SVE predicate. "p" for partial Arm SVE predicate
+ - simd: Flags describing a SIMD operation. The architecture type can be Arm's
+ ASE (Advanced SIMD extension), SVE, SME. It provides an extra tag for
+ predicate: "e" for empty predicate, "p" for partial predicate, "d" for
+ predicate disabled, and "f" for full predicate.
- type: Data type of sample memory access.
- typeoff: Offset in the data type of sample memory access.
- symoff: Offset in the symbol.
--
2.34.1
^ permalink raw reply related
* [PATCH v5 2/4] perf sort: Sort disabled and full predicated flags
From: Leo Yan @ 2026-04-08 9:42 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Namhyung Kim, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Mark Rutland
Cc: Arnaldo Carvalho de Melo, linux-perf-users, linux-arm-kernel,
Leo Yan
In-Reply-To: <20260408-perf_support_arm_spev1-3-v5-0-b5bcea6217bb@arm.com>
According to the Arm ARM (ARM DDI 0487, L.a), section D18.2.6
"Events packet", apart from the empty predicate and partial
predicates, an SVE or SME operation can be predicate-disabled
or full predicated.
To provide complete results, introduce two predicate types for
these cases.
Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Leo Yan <leo.yan@arm.com>
---
tools/perf/util/sample.h | 13 +++++++++----
tools/perf/util/sort.c | 15 ++++++++++-----
2 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/tools/perf/util/sample.h b/tools/perf/util/sample.h
index 0e5ee7e0fb94f2d36c35df15de7c4ea00547a6c2..ca0c407c4423a4bc0b8098c657238b50ff5a3a17 100644
--- a/tools/perf/util/sample.h
+++ b/tools/perf/util/sample.h
@@ -72,8 +72,8 @@ struct aux_sample {
struct simd_flags {
u8 arch: 2, /* architecture (isa) */
- pred: 2, /* predication */
- resv: 4; /* reserved */
+ pred: 3, /* predication */
+ resv: 3; /* reserved */
};
/* simd architecture flags */
@@ -85,8 +85,13 @@ enum simd_op_flags {
};
/* simd predicate flags */
-#define SIMD_OP_FLAGS_PRED_PARTIAL 0x01 /* partial predicate */
-#define SIMD_OP_FLAGS_PRED_EMPTY 0x02 /* empty predicate */
+enum simd_pred_flags {
+ SIMD_OP_FLAGS_PRED_NONE = 0x0, /* Not available */
+ SIMD_OP_FLAGS_PRED_PARTIAL, /* partial predicate */
+ SIMD_OP_FLAGS_PRED_EMPTY, /* empty predicate */
+ SIMD_OP_FLAGS_PRED_FULL, /* full predicate */
+ SIMD_OP_FLAGS_PRED_DISABLED, /* disabled predicate */
+};
/**
* struct perf_sample
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 69ecc5be0488c749a11fe9912375d8e5408175bf..5b88613992484d53c5caa47724f5fa29dd650515 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -209,18 +209,23 @@ static int hist_entry__simd_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width __maybe_unused)
{
const char *name;
+ const char *pred_str = ".";
if (!he->simd_flags.arch)
return repsep_snprintf(bf, size, "");
name = hist_entry__get_simd_name(&he->simd_flags);
- if (he->simd_flags.pred & SIMD_OP_FLAGS_PRED_EMPTY)
- return repsep_snprintf(bf, size, "[e] %s", name);
- else if (he->simd_flags.pred & SIMD_OP_FLAGS_PRED_PARTIAL)
- return repsep_snprintf(bf, size, "[p] %s", name);
+ if (he->simd_flags.pred == SIMD_OP_FLAGS_PRED_EMPTY)
+ pred_str = "e";
+ else if (he->simd_flags.pred == SIMD_OP_FLAGS_PRED_PARTIAL)
+ pred_str = "p";
+ else if (he->simd_flags.pred == SIMD_OP_FLAGS_PRED_DISABLED)
+ pred_str = "d";
+ else if (he->simd_flags.pred == SIMD_OP_FLAGS_PRED_FULL)
+ pred_str = "f";
- return repsep_snprintf(bf, size, "[.] %s", name);
+ return repsep_snprintf(bf, size, "[%s] %s", pred_str, name);
}
struct sort_entry sort_simd = {
--
2.34.1
^ permalink raw reply related
* [PATCH v5 0/4] perf arm_spe: Extend SIMD operations
From: Leo Yan @ 2026-04-08 9:42 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Namhyung Kim, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Mark Rutland
Cc: Arnaldo Carvalho de Melo, linux-perf-users, linux-arm-kernel,
Leo Yan
This series extends SIMD flag for Arm SPE and updated the document.
Since I failed to get perf core maintainer's review for uAPI header
updating for data source fields (since last year's Sepetember), this
series I dropped uAPI changes and sent only SIMD flag changes, hope
it is easier for perf tool maintainer's picking up.
Anyway, uAPI patches will be sent out separately.
This version is rebased onto the latest perf-tools-next branch.
Signed-off-by: Leo Yan <leo.yan@arm.com>
---
Changes in v5:
- Dropped uAPI header changes for data source fields updating.
- Link to v4: https://lore.kernel.org/r/20260106-perf_support_arm_spev1-3-v4-0-b887bb999f6e@arm.com
Changes in v4 (resend):
- Updated for Ian and James' review tags.
- Link to v4: https://lore.kernel.org/r/20260106-perf_support_arm_spev1-3-v4-0-bb2d143b3860@arm.com
Changes in v4:
- Updated for Ian and James' review tags.
- Rebased on the latest perf-tools-next branch.
- Link to v3: https://lore.kernel.org/r/20251112-perf_support_arm_spev1-3-v3-0-e63c9829f9d9@arm.com
Changes in v3:
- Rebased on the latest perf-tools-next branch.
- Link to v2: https://lore.kernel.org/r/20251017-perf_support_arm_spev1-3-v2-0-2d41e4746e1b@arm.com
Changes in v2:
- Refined to use enums for 2nd operation types. (James)
- Avoided adjustment bit positions for operations. (James)
- Used enum for extended operation type in uapi header and defined
individual bit field for operation details in uaip header. (James)
- Refined SIMD flag definitions. (James)
- Extracted a separate commit for updating tool's header. (James/Arnaldo)
- Minor improvement for printing memory events.
- Rebased on the latest perf-tools-next branch.
- Link to v1: https://lore.kernel.org/r/20250929-perf_support_arm_spev1-3-v1-0-1150b3c83857@arm.com
---
Leo Yan (4):
perf sort: Support sort ASE and SME
perf sort: Sort disabled and full predicated flags
perf report: Update document for SIMD flags
perf arm_spe: Improve SIMD flags setting
tools/perf/Documentation/perf-report.txt | 5 ++++-
tools/perf/util/arm-spe.c | 26 ++++++++++++++++++++------
tools/perf/util/sample.h | 21 ++++++++++++++++-----
tools/perf/util/sort.c | 21 +++++++++++++++------
4 files changed, 55 insertions(+), 18 deletions(-)
---
base-commit: dc647eb00969cd213c84d6caee90c480317e857d
change-id: 20250820-perf_support_arm_spev1-3-b6efd6fc77b2
Best regards,
--
Leo Yan <leo.yan@arm.com>
^ permalink raw reply
* [PATCH v5 1/4] perf sort: Support sort ASE and SME
From: Leo Yan @ 2026-04-08 9:42 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Namhyung Kim, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, Mark Rutland
Cc: Arnaldo Carvalho de Melo, linux-perf-users, linux-arm-kernel,
Leo Yan
In-Reply-To: <20260408-perf_support_arm_spev1-3-v5-0-b5bcea6217bb@arm.com>
Support sort Advance SIMD extension (ASE) and SME.
Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Leo Yan <leo.yan@arm.com>
---
tools/perf/util/sample.h | 12 +++++++++---
tools/perf/util/sort.c | 6 +++++-
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/tools/perf/util/sample.h b/tools/perf/util/sample.h
index 3d27a0daef8fb2d72ffa8510923857e73130dd40..0e5ee7e0fb94f2d36c35df15de7c4ea00547a6c2 100644
--- a/tools/perf/util/sample.h
+++ b/tools/perf/util/sample.h
@@ -71,12 +71,18 @@ struct aux_sample {
};
struct simd_flags {
- u8 arch:1, /* architecture (isa) */
- pred:2; /* predication */
+ u8 arch: 2, /* architecture (isa) */
+ pred: 2, /* predication */
+ resv: 4; /* reserved */
};
/* simd architecture flags */
-#define SIMD_OP_FLAGS_ARCH_SVE 0x01 /* ARM SVE */
+enum simd_op_flags {
+ SIMD_OP_FLAGS_ARCH_NONE = 0x0, /* No SIMD operation */
+ SIMD_OP_FLAGS_ARCH_SVE, /* Arm SVE */
+ SIMD_OP_FLAGS_ARCH_SME, /* Arm SME */
+ SIMD_OP_FLAGS_ARCH_ASE, /* Arm Advanced SIMD */
+};
/* simd predicate flags */
#define SIMD_OP_FLAGS_PRED_PARTIAL 0x01 /* partial predicate */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5c9656cc4f9dacdb66351543c103ddd3cee6860a..69ecc5be0488c749a11fe9912375d8e5408175bf 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -195,8 +195,12 @@ static const char *hist_entry__get_simd_name(struct simd_flags *simd_flags)
{
u64 arch = simd_flags->arch;
- if (arch & SIMD_OP_FLAGS_ARCH_SVE)
+ if (arch == SIMD_OP_FLAGS_ARCH_SVE)
return "SVE";
+ else if (arch == SIMD_OP_FLAGS_ARCH_SME)
+ return "SME";
+ else if (arch == SIMD_OP_FLAGS_ARCH_ASE)
+ return "ASE";
else
return "n/a";
}
--
2.34.1
^ permalink raw reply related
* [PATCH RFC net-next 08/10] net: stmmac: simplify stmmac_get_ethtool_stats()
From: Russell King (Oracle) @ 2026-04-08 9:27 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai, David S. Miller,
Eric Dumazet, Jakub Kicinski, Jitendra Vegiraju, linux-arm-kernel,
linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <adYfPBHsXxQUsMyr@shell.armlinux.org.uk>
As documented, stmmac_dma_diagnostic_fr() will return non-zero for
all non-DWMAC_CORE_MAC100 core types.
However, as DWMAC_CORE_MAC100 core types do not have DMA capabilities,
priv->dma_cap.rmon and priv->dma_cap.eee will be zero, and thus there
is no need to make this also conditional on the
stmmac_dma_diagnostic_fr() return value.
Remove this test and unindent the code, and remove unnecessary parens.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
.../ethernet/stmicro/stmmac/stmmac_ethtool.c | 60 +++++++++----------
1 file changed, 28 insertions(+), 32 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 0caa5b992519..77cb67f4c63c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -519,9 +519,9 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
u32 rx_queues_count = priv->plat->rx_queues_to_use;
u32 tx_queues_count = priv->plat->tx_queues_to_use;
u64 napi_poll = 0, normal_irq_n = 0;
- int i, j = 0, pos, ret;
unsigned long count;
unsigned int start;
+ int i, j = 0, pos;
if (priv->dma_cap.asp) {
for (i = 0; i < STMMAC_SAFETY_FEAT_SIZE; i++) {
@@ -531,42 +531,38 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
}
}
- /* Update the DMA HW counters for dwmac10/100 (DWMAC_CORE_MAC100),
- * where this will return zero. Other core types will have a non-zero
- * return value.
- */
- ret = stmmac_dma_diagnostic_fr(priv, &priv->xstats, priv->ioaddr);
- if (ret) {
- /* If supported, for new GMAC chips expose the MMC counters */
- if (priv->dma_cap.rmon) {
- stmmac_mmc_read(priv, priv->mmcaddr, &priv->mmc);
+ /* Update the DMA HW counters for dwmac10/100 (DWMAC_CORE_MAC100). */
+ stmmac_dma_diagnostic_fr(priv, &priv->xstats, priv->ioaddr);
- for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) {
- char *p;
- p = (char *)priv + stmmac_mmc[i].stat_offset;
+ /* If supported, for new GMAC chips expose the MMC counters */
+ if (priv->dma_cap.rmon) {
+ stmmac_mmc_read(priv, priv->mmcaddr, &priv->mmc);
- data[j++] = (stmmac_mmc[i].sizeof_stat ==
- sizeof(u64)) ? (*(u64 *)p) :
- (*(u32 *)p);
- }
- }
- if (priv->dma_cap.eee) {
- int val = phylink_get_eee_err(priv->phylink);
- if (val)
- priv->xstats.phy_eee_wakeup_error_n = val;
+ for (i = 0; i < STMMAC_MMC_STATS_LEN; i++) {
+ char *p = (char *)priv + stmmac_mmc[i].stat_offset;
+
+ data[j++] = stmmac_mmc[i].sizeof_stat == sizeof(u64) ?
+ *(u64 *)p : *(u32 *)p;
}
+ }
- /* Only dwmac1000 and dwmac4 implements the MAC .debug() method.
- * As there are different version spaces depending on core_type,
- * make this conditional on the appropriate core type.
- */
- if ((priv->plat->core_type == DWMAC_CORE_GMAC ||
- priv->plat->core_type == DWMAC_CORE_GMAC4) &&
- priv->snpsver >= DWMAC_CORE_3_50)
- stmmac_mac_debug(priv, priv->ioaddr,
- (void *)&priv->xstats,
- rx_queues_count, tx_queues_count);
+ if (priv->dma_cap.eee) {
+ int val = phylink_get_eee_err(priv->phylink);
+ if (val)
+ priv->xstats.phy_eee_wakeup_error_n = val;
}
+
+ /* Only dwmac1000 and dwmac4 implements the MAC .debug() method.
+ * As there are different version spaces depending on core_type,
+ * make this conditional on the appropriate core type.
+ */
+ if ((priv->plat->core_type == DWMAC_CORE_GMAC ||
+ priv->plat->core_type == DWMAC_CORE_GMAC4) &&
+ priv->snpsver >= DWMAC_CORE_3_50)
+ stmmac_mac_debug(priv, priv->ioaddr,
+ (void *)&priv->xstats,
+ rx_queues_count, tx_queues_count);
+
for (i = 0; i < STMMAC_STATS_LEN; i++) {
char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
data[j++] = (stmmac_gstrings_stats[i].sizeof_stat ==
--
2.47.3
^ permalink raw reply related
* [GIT PULL] Reset controller fixes for v7.0, part 3
From: Philipp Zabel @ 2026-04-08 9:41 UTC (permalink / raw)
To: soc; +Cc: linux-arm-kernel, kernel, Philipp Zabel
Dear arm-soc maintainers,
The following changes since commit a0e0c2f8c5f32b675f58e25a9338283cedb5ad2b:
reset: spacemit: k3: Decouple composite reset lines (2026-03-23 12:25:47 +0100)
are available in the Git repository at:
https://git.pengutronix.de/git/pza/linux.git tags/reset-fixes-for-v7.0-3
for you to fetch changes up to 9797524ef2b69c6b187b55bd844eb72a8c1cbd99:
reset: amlogic: t7: Fix null reset ops (2026-03-31 17:19:18 +0200)
----------------------------------------------------------------
Reset controller fixes for v7.0, part 3
* Add missing reset ops for amlogic,t7-reset to the reset-meson driver.
The resets are unused as of now, but as soon as they are, the driver
would otherwise run into a NULL pointer dereference.
----------------------------------------------------------------
Ronald Claveau (1):
reset: amlogic: t7: Fix null reset ops
drivers/reset/amlogic/reset-meson.c | 1 +
1 file changed, 1 insertion(+)
^ permalink raw reply
* [PATCH RFC net-next 10/10] net: stmmac: only print receive COE type for GMAC cores
From: Russell King (Oracle) @ 2026-04-08 9:27 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai, David S. Miller,
Eric Dumazet, Jakub Kicinski, Jitendra Vegiraju, linux-arm-kernel,
linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <adYfPBHsXxQUsMyr@shell.armlinux.org.uk>
As identified in the previous commit, only GMAC cores have a COE type,
but priv->snpsver's numberspace is core specific. Change the test for
printing this to check the core type instead of checking for the
Synopssys IP version being < v4.0, which will incorrectly match XGMAC
cores.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 93c031b3cfd5..f5fe97c1abd4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7461,7 +7461,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
if (priv->plat->rx_coe) {
priv->hw->rx_csum = priv->plat->rx_coe;
dev_info(priv->device, "RX Checksum Offload Engine supported\n");
- if (priv->snpsver < DWMAC_CORE_4_00)
+ if (priv->plat->core_type == DWMAC_CORE_GMAC)
dev_info(priv->device, "COE Type %d\n", priv->hw->rx_csum);
}
if (priv->plat->tx_coe)
--
2.47.3
^ permalink raw reply related
* [PATCH RFC net-next 07/10] net: stmmac: limit MAC .debug() to dwmac1000 and dwmac4
From: Russell King (Oracle) @ 2026-04-08 9:27 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai, David S. Miller,
Eric Dumazet, Jakub Kicinski, Jitendra Vegiraju, linux-arm-kernel,
linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <adYfPBHsXxQUsMyr@shell.armlinux.org.uk>
Avoid a bare test against snpsver which has multiple different number
spaces depending on the core type by testing for core types that
implement the .debug() method. This documents that these statistics
are only available on dwmac1000 and dwmac4 cores.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 343cf903c0bf..0caa5b992519 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -531,7 +531,10 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
}
}
- /* Update the DMA HW counters for dwmac10/100 */
+ /* Update the DMA HW counters for dwmac10/100 (DWMAC_CORE_MAC100),
+ * where this will return zero. Other core types will have a non-zero
+ * return value.
+ */
ret = stmmac_dma_diagnostic_fr(priv, &priv->xstats, priv->ioaddr);
if (ret) {
/* If supported, for new GMAC chips expose the MMC counters */
@@ -553,7 +556,13 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
priv->xstats.phy_eee_wakeup_error_n = val;
}
- if (priv->snpsver >= DWMAC_CORE_3_50)
+ /* Only dwmac1000 and dwmac4 implements the MAC .debug() method.
+ * As there are different version spaces depending on core_type,
+ * make this conditional on the appropriate core type.
+ */
+ if ((priv->plat->core_type == DWMAC_CORE_GMAC ||
+ priv->plat->core_type == DWMAC_CORE_GMAC4) &&
+ priv->snpsver >= DWMAC_CORE_3_50)
stmmac_mac_debug(priv, priv->ioaddr,
(void *)&priv->xstats,
rx_queues_count, tx_queues_count);
--
2.47.3
^ permalink raw reply related
* Re: [PATCH mt76] wifi: mt76: mt76x2u: Add support for ELECOM WDC-867SU3S
From: Lorenzo Bianconi @ 2026-04-08 9:34 UTC (permalink / raw)
To: Zenm Chen
Cc: nbd, ryder.lee, shayne.chen, sean.wang, matthias.bgg,
angelogioacchino.delregno, linux-wireless, linux-kernel,
linux-arm-kernel, linux-mediatek, stable
In-Reply-To: <20260407154430.9184-1-zenmchen@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1628 bytes --]
On Apr 07, Zenm Chen wrote:
> Add the ID 056e:400a to the table to support an additional MT7612U
> adapter: ELECOM WDC-867SU3S.
>
> Compile tested only.
>
> Cc: stable@vger.kernel.org # 5.10.x
I do not think this material for stable. Anyway:
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Signed-off-by: Zenm Chen <zenmchen@gmail.com>
> ---
> This ID was found from [1] and adding it to the device table should be
> enough to make it work. Hardware probes at [2] can prove its existence.
>
> [1] https://bushowhige.blogspot.com/2019/08/ubuntu-1804-mediatek-usb-wi-fi.html
> [2] https://linux-hardware.org/?id=usb:056e-400a
> ---
> drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
> index 01cb3b283..459c4044f 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
> @@ -16,6 +16,7 @@ static const struct usb_device_id mt76x2u_device_table[] = {
> { USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USBAC1200 - Alfa AWUS036ACM */
> { USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */
> { USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */
> + { USB_DEVICE(0x056e, 0x400a) }, /* ELECOM WDC-867SU3S */
> { USB_DEVICE(0x0e8d, 0x7632) }, /* HC-M7662BU1 */
> { USB_DEVICE(0x0471, 0x2126) }, /* LiteOn WN4516R module, nonstandard USB connector */
> { USB_DEVICE(0x0471, 0x7600) }, /* LiteOn WN4519R module, nonstandard USB connector */
> --
> 2.53.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH RFC net-next 06/10] net: stmmac: dche is only for GMAC4 cores
From: Russell King (Oracle) @ 2026-04-08 9:27 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai, David S. Miller,
Eric Dumazet, Jakub Kicinski, Jitendra Vegiraju, linux-arm-kernel,
linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <adYfPBHsXxQUsMyr@shell.armlinux.org.uk>
dma_cfg->dche is only read by dwmac4_dma_init(), which is only called
for the DWMAC_CORE_GMAC4 core type. Rather than having a bare IP
version check that can match any core type, make this conditional on
DWMAC_CORE_GMAC4 to make it clear that it's a GMAC4 feature.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 295d31d7b28b..e47321119c83 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7895,9 +7895,10 @@ static int __stmmac_dvr_probe(struct device *device,
if (ret)
goto error_hw_init;
- /* Only DWMAC core version 5.20 onwards supports HW descriptor prefetch.
+ /* Only DWMAC4 core version 5.20 onwards support HW descriptor prefetch.
*/
- if (priv->snpsver < DWMAC_CORE_5_20)
+ if (priv->plat->core_type != DWMAC_CORE_GMAC4 ||
+ priv->snpsver < DWMAC_CORE_5_20)
priv->plat->dma_cfg->dche = false;
stmmac_check_ether_addr(priv);
--
2.47.3
^ permalink raw reply related
* [PATCH RFC net-next 05/10] net: stmmac: rename confusing synopsys_id
From: Russell King (Oracle) @ 2026-04-08 9:27 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai, David S. Miller,
Eric Dumazet, Jakub Kicinski, Jitendra Vegiraju, linux-arm-kernel,
linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <adYfPBHsXxQUsMyr@shell.armlinux.org.uk>
priv->synopsys_id is the Synopsys IP version, defined by snpsver in
the databook. This is made up of the major version in bits 7:4 and
the first digit of the minor version in bits 3:0. Change the type
for synopsys_id to be a u8 and rename to snpsver.
For reference, the values for snpsver:
GMAC100 cores do not have a readable snpsver number.
GMAC cores generally have a snpsver number less than 0x40.
GMAC4 cores may have a version number that overlaps GMAC cores
(see first entry for DWMAC_CORE_GMAC4).
XGMAC and XLGMAC cores each have an entirely separate IP version
number space from GMAC and GMAC4, which are distinguished by their
respective userver.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/hwif.c | 10 +++++-----
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 12 ++++++------
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 8 ++++----
8 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index eb14c197d6ae..789b384a2838 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -326,7 +326,7 @@ static int loongson_dwmac_setup(void *apriv, struct mac_device_info *mac)
* original value so the correct HW-interface would be selected.
*/
if (ld->multichan) {
- priv->synopsys_id = DWMAC_CORE_3_70;
+ priv->snpsver = DWMAC_CORE_3_70;
*dma = dwmac1000_dma_ops;
dma->init_chan = loongson_dwmac_dma_init_channel;
dma->dma_interrupt = loongson_dwmac_dma_interrupt;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 48c52eb96233..4bff7592c652 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1069,7 +1069,7 @@ static int sun8i_dwmac_setup(void *ppriv, struct mac_device_info *mac)
mac->unicast_filter_entries = 8;
/* Synopsys Id is not available */
- priv->synopsys_id = 0;
+ priv->snpsver = 0;
return 0;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
index 03437f1cf3df..635d711a554e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
@@ -380,7 +380,7 @@ static int dwxgmac2_get_hw_feature(void __iomem *ioaddr,
dma_cap->vlhash = (hw_cap & XGMAC_HWFEAT_VLHASH) >> 4;
dma_cap->half_duplex = (hw_cap & XGMAC_HWFEAT_HDSEL) >> 3;
dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1;
- if (dma_cap->mbps_1000 && priv->synopsys_id >= DWXGMAC_CORE_2_20)
+ if (dma_cap->mbps_1000 && priv->snpsver >= DWXGMAC_CORE_2_20)
dma_cap->mbps_10_100 = 1;
/* MAC HW feature 1 */
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 7f95a2a5be4c..e5629afc391f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -72,7 +72,7 @@ static int stmmac_dwmac1_quirks(struct stmmac_priv *priv)
dev_info(priv->device, "Enhanced/Alternate descriptors\n");
/* GMAC older than 3.50 has no extended descriptors */
- if (priv->synopsys_id >= DWMAC_CORE_3_50) {
+ if (priv->snpsver >= DWMAC_CORE_3_50) {
dev_info(priv->device, "Enabled extended descriptors\n");
priv->extend_desc = true;
} else {
@@ -299,7 +299,7 @@ stmmac_hwif_find(enum dwmac_core_type core_type, u8 snpsver, u8 userver)
if (core_type != entry->core_type)
continue;
- /* Use synopsys_id var because some setups can override this */
+ /* Use snpsver var because some setups can override this */
if (snpsver < entry->min_snpsver)
continue;
if (core_type == DWMAC_CORE_XGMAC &&
@@ -324,7 +324,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
stmmac_get_version(priv, &version);
/* Save ID for later use */
- priv->synopsys_id = version.snpsver;
+ priv->snpsver = version.snpsver;
/* Lets assume some safe values first */
if (core_type == DWMAC_CORE_GMAC4) {
@@ -355,8 +355,8 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
/* Fallback to generic HW */
- /* Use synopsys_id var because some setups can override this */
- entry = stmmac_hwif_find(core_type, priv->synopsys_id, version.userver);
+ /* Use snpsver var because some setups can override this */
+ entry = stmmac_hwif_find(core_type, priv->snpsver, version.userver);
if (!entry) {
dev_err(priv->device,
"Failed to find HW IF (id=0x%x, gmac=%d/%d)\n",
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 8ba8f03e1ce0..9a5d9c404e4f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -304,7 +304,7 @@ struct stmmac_priv {
struct dma_features dma_cap;
struct stmmac_counters mmc;
int hw_cap_support;
- int synopsys_id;
+ u8 snpsver;
u32 msg_enable;
/* Our MAC Wake-on-Lan options */
int wolopts;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 92585d27ab88..343cf903c0bf 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -553,7 +553,7 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
priv->xstats.phy_eee_wakeup_error_n = val;
}
- if (priv->synopsys_id >= DWMAC_CORE_3_50)
+ if (priv->snpsver >= DWMAC_CORE_3_50)
stmmac_mac_debug(priv, priv->ioaddr,
(void *)&priv->xstats,
rx_queues_count, tx_queues_count);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 01a983001ab4..295d31d7b28b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -755,7 +755,7 @@ static int stmmac_hwtstamp_set(struct net_device *dev,
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
ptp_v2 = PTP_TCR_TSVER2ENA;
snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
- if (priv->synopsys_id < DWMAC_CORE_4_10)
+ if (priv->snpsver < DWMAC_CORE_4_10)
ts_event_en = PTP_TCR_TSEVNTENA;
ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
@@ -6624,7 +6624,7 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v)
seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
seq_printf(seq, "\tChecksum Offload in TX: %s\n",
(priv->dma_cap.tx_coe) ? "Y" : "N");
- if (priv->synopsys_id >= DWMAC_CORE_4_00 ||
+ if (priv->snpsver >= DWMAC_CORE_4_00 ||
priv->plat->core_type == DWMAC_CORE_XGMAC) {
seq_printf(seq, "\tIP Checksum Offload in RX: %s\n",
(priv->dma_cap.rx_coe) ? "Y" : "N");
@@ -7454,7 +7454,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
if (priv->plat->rx_coe) {
priv->hw->rx_csum = priv->plat->rx_coe;
dev_info(priv->device, "RX Checksum Offload Engine supported\n");
- if (priv->synopsys_id < DWMAC_CORE_4_00)
+ if (priv->snpsver < DWMAC_CORE_4_00)
dev_info(priv->device, "COE Type %d\n", priv->hw->rx_csum);
}
if (priv->plat->tx_coe)
@@ -7520,7 +7520,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
* has to be disable and this can be done by passing the
* riwt_off field from the platform.
*/
- if ((priv->synopsys_id >= DWMAC_CORE_3_50 ||
+ if ((priv->snpsver >= DWMAC_CORE_3_50 ||
priv->plat->core_type == DWMAC_CORE_XGMAC) &&
!priv->plat->riwt_off) {
priv->use_riwt = 1;
@@ -7897,7 +7897,7 @@ static int __stmmac_dvr_probe(struct device *device,
/* Only DWMAC core version 5.20 onwards supports HW descriptor prefetch.
*/
- if (priv->synopsys_id < DWMAC_CORE_5_20)
+ if (priv->snpsver < DWMAC_CORE_5_20)
priv->plat->dma_cfg->dche = false;
stmmac_check_ether_addr(priv);
@@ -7997,7 +7997,7 @@ static int __stmmac_dvr_probe(struct device *device,
if (priv->plat->core_type == DWMAC_CORE_XGMAC)
ndev->max_mtu = XGMAC_JUMBO_LEN;
- else if (priv->plat->enh_desc || priv->synopsys_id >= DWMAC_CORE_4_00)
+ else if (priv->plat->enh_desc || priv->snpsver >= DWMAC_CORE_4_00)
ndev->max_mtu = JUMBO_LEN;
else
ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index afe98ff5bdcb..0107119f68d2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -74,7 +74,7 @@ static void stmmac_xgmac2_c22_format(struct stmmac_priv *priv, int phyaddr,
{
u32 tmp = 0;
- if (priv->synopsys_id < DWXGMAC_CORE_2_20) {
+ if (priv->snpsver < DWXGMAC_CORE_2_20) {
/* Until ver 2.20 XGMAC does not support C22 addr >= 4. Those
* bits above bit 3 of XGMAC_MDIO_C22P register are reserved.
*/
@@ -136,7 +136,7 @@ static int stmmac_xgmac2_mdio_read_c22(struct mii_bus *bus, int phyaddr,
u32 addr;
/* Until ver 2.20 XGMAC does not support C22 addr >= 4 */
- if (priv->synopsys_id < DWXGMAC_CORE_2_20 &&
+ if (priv->snpsver < DWXGMAC_CORE_2_20 &&
phyaddr > MII_XGMAC_MAX_C22ADDR)
return -ENODEV;
@@ -199,7 +199,7 @@ static int stmmac_xgmac2_mdio_write_c22(struct mii_bus *bus, int phyaddr,
u32 addr;
/* Until ver 2.20 XGMAC does not support C22 addr >= 4 */
- if (priv->synopsys_id < DWXGMAC_CORE_2_20 &&
+ if (priv->snpsver < DWXGMAC_CORE_2_20 &&
phyaddr > MII_XGMAC_MAX_C22ADDR)
return -ENODEV;
@@ -625,7 +625,7 @@ int stmmac_mdio_register(struct net_device *ndev)
new_bus->read_c45 = &stmmac_xgmac2_mdio_read_c45;
new_bus->write_c45 = &stmmac_xgmac2_mdio_write_c45;
- if (priv->synopsys_id < DWXGMAC_CORE_2_20) {
+ if (priv->snpsver < DWXGMAC_CORE_2_20) {
/* Right now only C22 phys are supported */
max_addr = MII_XGMAC_MAX_C22ADDR;
--
2.47.3
^ permalink raw reply related
* [PATCH RFC net-next 04/10] net: stmmac: use ver->userver and ver->snpsver to print version
From: Russell King (Oracle) @ 2026-04-08 9:26 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai, David S. Miller,
Eric Dumazet, Jakub Kicinski, Jitendra Vegiraju, linux-arm-kernel,
linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <adYfPBHsXxQUsMyr@shell.armlinux.org.uk>
Rather than using FIELD_GET() twice, reorder the code to extract the
version fields into struct stmmac_version, and then print them.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/stmicro/stmmac/hwif.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index aacf78d4a2ee..7f95a2a5be4c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -42,12 +42,11 @@ static void stmmac_get_version(struct stmmac_priv *priv,
return;
}
- dev_info(priv->device, "User ID: 0x%x, Synopsys ID: 0x%x\n",
- FIELD_GET(DWMAC_USERVER, version),
- FIELD_GET(DWMAC_SNPSVER, version));
-
ver->snpsver = FIELD_GET(DWMAC_SNPSVER, version);
ver->userver = FIELD_GET(DWMAC_USERVER, version);
+
+ dev_info(priv->device, "User ID: 0x%x, Synopsys ID: 0x%x\n",
+ ver->userver, ver->snpsver);
}
static void stmmac_dwmac_mode_quirk(struct stmmac_priv *priv)
--
2.47.3
^ permalink raw reply related
* [PATCH RFC net-next 03/10] net: stmmac: always fill in ver->userver
From: Russell King (Oracle) @ 2026-04-08 9:26 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai, David S. Miller,
Eric Dumazet, Jakub Kicinski, Jitendra Vegiraju, linux-arm-kernel,
linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <adYfPBHsXxQUsMyr@shell.armlinux.org.uk>
Always fill in ver->userver irrespective of the core type. This has no
functional impact but tidies up the code by removing an unnecessary
conditional.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/stmicro/stmmac/hwif.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 830ff816ab4f..aacf78d4a2ee 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -47,8 +47,7 @@ static void stmmac_get_version(struct stmmac_priv *priv,
FIELD_GET(DWMAC_SNPSVER, version));
ver->snpsver = FIELD_GET(DWMAC_SNPSVER, version);
- if (core_type == DWMAC_CORE_XGMAC)
- ver->userver = FIELD_GET(DWMAC_USERVER, version);
+ ver->userver = FIELD_GET(DWMAC_USERVER, version);
}
static void stmmac_dwmac_mode_quirk(struct stmmac_priv *priv)
--
2.47.3
^ permalink raw reply related
* [PATCH RFC net-next 02/10] net: stmmac: rename dev_id to userver
From: Russell King (Oracle) @ 2026-04-08 9:26 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai, David S. Miller,
Eric Dumazet, Jakub Kicinski, Jitendra Vegiraju, linux-arm-kernel,
linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <adYfPBHsXxQUsMyr@shell.armlinux.org.uk>
The Synopsys Databook and several implementation TRMs identify bits
15:8 of the version register in dwmac v3.xx and v4.xx as "userver".
We even print its value with "User ID". Rather than using "dev_id",
use "userver" instead.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/stmicro/stmmac/hwif.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 3774af66db48..830ff816ab4f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -15,7 +15,7 @@
struct stmmac_version {
u8 snpsver;
- u8 dev_id;
+ u8 userver;
};
static void stmmac_get_version(struct stmmac_priv *priv,
@@ -26,7 +26,7 @@ static void stmmac_get_version(struct stmmac_priv *priv,
u32 version;
ver->snpsver = 0;
- ver->dev_id = 0;
+ ver->userver = 0;
if (core_type == DWMAC_CORE_MAC100)
return;
@@ -48,7 +48,7 @@ static void stmmac_get_version(struct stmmac_priv *priv,
ver->snpsver = FIELD_GET(DWMAC_SNPSVER, version);
if (core_type == DWMAC_CORE_XGMAC)
- ver->dev_id = FIELD_GET(DWMAC_USERVER, version);
+ ver->userver = FIELD_GET(DWMAC_USERVER, version);
}
static void stmmac_dwmac_mode_quirk(struct stmmac_priv *priv)
@@ -111,7 +111,7 @@ int stmmac_reset(struct stmmac_priv *priv)
static const struct stmmac_hwif_entry {
enum dwmac_core_type core_type;
u32 min_snpsver;
- u32 dev_id;
+ u32 userver;
const struct stmmac_regs_off regs;
const void *desc;
const void *dma;
@@ -247,7 +247,7 @@ static const struct stmmac_hwif_entry {
}, {
.core_type = DWMAC_CORE_XGMAC,
.min_snpsver = DWXGMAC_CORE_2_10,
- .dev_id = DWXGMAC_ID,
+ .userver = DWXGMAC_ID,
.regs = {
.ptp_off = PTP_XGMAC_OFFSET,
.mmc_off = MMC_XGMAC_OFFSET,
@@ -269,7 +269,7 @@ static const struct stmmac_hwif_entry {
}, {
.core_type = DWMAC_CORE_XGMAC,
.min_snpsver = DWXLGMAC_CORE_2_00,
- .dev_id = DWXLGMAC_ID,
+ .userver = DWXLGMAC_ID,
.regs = {
.ptp_off = PTP_XGMAC_OFFSET,
.mmc_off = MMC_XGMAC_OFFSET,
@@ -291,7 +291,7 @@ static const struct stmmac_hwif_entry {
};
static const struct stmmac_hwif_entry *
-stmmac_hwif_find(enum dwmac_core_type core_type, u8 snpsver, u8 dev_id)
+stmmac_hwif_find(enum dwmac_core_type core_type, u8 snpsver, u8 userver)
{
const struct stmmac_hwif_entry *entry;
int i;
@@ -305,7 +305,7 @@ stmmac_hwif_find(enum dwmac_core_type core_type, u8 snpsver, u8 dev_id)
if (snpsver < entry->min_snpsver)
continue;
if (core_type == DWMAC_CORE_XGMAC &&
- dev_id != entry->dev_id)
+ userver != entry->userver)
continue;
return entry;
@@ -358,7 +358,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
/* Fallback to generic HW */
/* Use synopsys_id var because some setups can override this */
- entry = stmmac_hwif_find(core_type, priv->synopsys_id, version.dev_id);
+ entry = stmmac_hwif_find(core_type, priv->synopsys_id, version.userver);
if (!entry) {
dev_err(priv->device,
"Failed to find HW IF (id=0x%x, gmac=%d/%d)\n",
--
2.47.3
^ permalink raw reply related
* [PATCH RFC net-next 01/10] net: stmmac: rename min_id to min_snpsver
From: Russell King (Oracle) @ 2026-04-08 9:26 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai, David S. Miller,
Eric Dumazet, Jakub Kicinski, Jitendra Vegiraju, linux-arm-kernel,
linux-stm32, linux-sunxi, netdev, Paolo Abeni, Samuel Holland
In-Reply-To: <adYfPBHsXxQUsMyr@shell.armlinux.org.uk>
min_id is the minimum Synopsys IP version that the hwif entry will
match. Name it min_snpsver so that it's clear which part of the
version ID it is related to.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/stmicro/stmmac/hwif.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 511b0fd5e834..3774af66db48 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -110,7 +110,7 @@ int stmmac_reset(struct stmmac_priv *priv)
static const struct stmmac_hwif_entry {
enum dwmac_core_type core_type;
- u32 min_id;
+ u32 min_snpsver;
u32 dev_id;
const struct stmmac_regs_off regs;
const void *desc;
@@ -129,7 +129,7 @@ static const struct stmmac_hwif_entry {
/* NOTE: New HW versions shall go to the end of this table */
{
.core_type = DWMAC_CORE_MAC100,
- .min_id = 0,
+ .min_snpsver = 0,
.regs = {
.ptp_off = PTP_GMAC3_X_OFFSET,
.mmc_off = MMC_GMAC3_X_OFFSET,
@@ -146,7 +146,7 @@ static const struct stmmac_hwif_entry {
.quirks = stmmac_dwmac1_quirks,
}, {
.core_type = DWMAC_CORE_GMAC,
- .min_id = 0,
+ .min_snpsver = 0,
.regs = {
.ptp_off = PTP_GMAC3_X_OFFSET,
.mmc_off = MMC_GMAC3_X_OFFSET,
@@ -163,7 +163,7 @@ static const struct stmmac_hwif_entry {
.quirks = stmmac_dwmac1_quirks,
}, {
.core_type = DWMAC_CORE_GMAC4,
- .min_id = 0,
+ .min_snpsver = 0,
.regs = {
.ptp_off = PTP_GMAC4_OFFSET,
.mmc_off = MMC_GMAC4_OFFSET,
@@ -183,7 +183,7 @@ static const struct stmmac_hwif_entry {
.quirks = stmmac_dwmac4_quirks,
}, {
.core_type = DWMAC_CORE_GMAC4,
- .min_id = DWMAC_CORE_4_00,
+ .min_snpsver = DWMAC_CORE_4_00,
.regs = {
.ptp_off = PTP_GMAC4_OFFSET,
.mmc_off = MMC_GMAC4_OFFSET,
@@ -204,7 +204,7 @@ static const struct stmmac_hwif_entry {
.quirks = NULL,
}, {
.core_type = DWMAC_CORE_GMAC4,
- .min_id = DWMAC_CORE_4_10,
+ .min_snpsver = DWMAC_CORE_4_10,
.regs = {
.ptp_off = PTP_GMAC4_OFFSET,
.mmc_off = MMC_GMAC4_OFFSET,
@@ -225,7 +225,7 @@ static const struct stmmac_hwif_entry {
.quirks = NULL,
}, {
.core_type = DWMAC_CORE_GMAC4,
- .min_id = DWMAC_CORE_5_10,
+ .min_snpsver = DWMAC_CORE_5_10,
.regs = {
.ptp_off = PTP_GMAC4_OFFSET,
.mmc_off = MMC_GMAC4_OFFSET,
@@ -246,7 +246,7 @@ static const struct stmmac_hwif_entry {
.quirks = NULL,
}, {
.core_type = DWMAC_CORE_XGMAC,
- .min_id = DWXGMAC_CORE_2_10,
+ .min_snpsver = DWXGMAC_CORE_2_10,
.dev_id = DWXGMAC_ID,
.regs = {
.ptp_off = PTP_XGMAC_OFFSET,
@@ -268,7 +268,7 @@ static const struct stmmac_hwif_entry {
.quirks = NULL,
}, {
.core_type = DWMAC_CORE_XGMAC,
- .min_id = DWXLGMAC_CORE_2_00,
+ .min_snpsver = DWXLGMAC_CORE_2_00,
.dev_id = DWXLGMAC_ID,
.regs = {
.ptp_off = PTP_XGMAC_OFFSET,
@@ -302,7 +302,7 @@ stmmac_hwif_find(enum dwmac_core_type core_type, u8 snpsver, u8 dev_id)
if (core_type != entry->core_type)
continue;
/* Use synopsys_id var because some setups can override this */
- if (snpsver < entry->min_id)
+ if (snpsver < entry->min_snpsver)
continue;
if (core_type == DWMAC_CORE_XGMAC &&
dev_id != entry->dev_id)
--
2.47.3
^ permalink raw reply related
* [PATCH RFC net-next 00/10] net: stmmac: clean up / fix synopsys IP version checks
From: Russell King (Oracle) @ 2026-04-08 9:26 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, Chen-Yu Tsai, David S. Miller,
Eric Dumazet, Jakub Kicinski, linux-arm-kernel, linux-stm32,
linux-sunxi, netdev, Paolo Abeni, Samuel Holland,
Jitendra Vegiraju
Oh lookie, another relatively large stmmac patch series as a result of
reviewing Jitendra Vegiraju's patch series! Yay! :(
This series cleans up and in some cases fixes the Synopsys IP version
checks, which is a per-core numberspace.
For example, for dwmac1000 and dwmac4, we have versions such as v3.4 to
up v5.2, which are represented by two BCD digits. For XGMAC, we have
versions v2.1 and v2.2 represented by 0x21 and 0x22 respectively. For
XLGMAC, we have v2.0, which is 0x20.
Note that hwif.c supports GMAC4 core type with the IP version in the
range 0..0x40, which overlaps with the GMAC core type.
Thus, testing the Synopsys IP version for <= v4.0 will match dwmac1000,
potentially some dwmac4, and all xgmac and xlgmac cores. In some cases,
the latter two are provably incorrect.
The Synopsys IP version is named "synopsys_id" in the driver - as
stated, it is the Synopsys IP version, and the register field is called
snpsver. Use this name throughout the driver to avoid confusion. Also,
dev_id seems to actually be userver.
The first decision making change is for dche, which is only looked at
by the dwmac4 DMA code which requires core_type == DWMAC_CORE_GMAC4.
Thus, it makes no sense to merely look at the IP version. Since setting
this to true makes no sense for non-GMAC4 cores, force it to false for
non-DWMAC_CORE_GMAC4 cores.
The MAC .debug() method is only populated by the dwmac1000 and dwmac4
cores, yet the test checks only for the IP version >= v3.5. While this
works today, it may not work in the future given the different version
numberspaces. Make this conditional on DWMAC_CORE_GMAC or GMAC4 core
types to limit the version check. Ideally, it would be better to
move the version check inside the .dwbug() method implementation, but
that would require the method signature to change.
As getting to that point involved quite a bit of research, add comments
into stmmac_get_ethtool_stats() so others don't have to re-analyse the
code.
Clean up the resulting code in stmmac_get_ethtool_stats() given the
complexity, adding documentation for each test.
Address the rx_coe handling, which checks for IP version >= v4.0 or
the XGMAC core type. However, the members being printed are only
present in the GMAC4 and XGMAC core type in one path, and GMAC in
the other. There is an odd-ball which is sun8i, but we preserve its
current behaviour. Also, given the research, add documentation in
appropriate places. Note that priv->plat->rx_coe (and also
priv->hw->rx_csum) has different value spaces depending on the core
type - which is not nice.
Lastly, make the printing of the COE type, which as identified above,
depend on the GMAC core type.
This leaves four locations unaddressed:
1) PTP filter code:
case HWTSTAMP_FILTER_PTP_V2_EVENT:
/* PTP v2/802.AS1 any layer, any kind of event packet */
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
ptp_v2 = PTP_TCR_TSVER2ENA;
snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
if (priv->snpsver < DWMAC_CORE_4_10)
ts_event_en = PTP_TCR_TSEVNTENA;
I don't yet have an answer for this one, but it does mean that
PTP_TCR_TSEVNTENA will be set for XGMAC cores for
HWTSTAMP_FILTER_PTP_V2_EVENT... if they have PTP support.
2) riwt watchdog:
/* Rx Watchdog is available in the COREs newer than the 3.40.
* In some case, for example on bugged HW this feature
* has to be disable and this can be done by passing the
* riwt_off field from the platform.
*/
if ((priv->snpsver >= DWMAC_CORE_3_50 ||
priv->plat->core_type == DWMAC_CORE_XGMAC) &&
!priv->plat->riwt_off) {
priv->use_riwt = 1;
This to me looks like the version check is only really applicable for
the DWMAC_CORE_GMAC core type. So, I'm thinking that:
if (priv->plat->core_type >= DWMAC_CORE_GMAC4 ||
(priv->plat->core_type == DWMAC_CORE_GMAC &&
priv->snpsver >= DWMAC_CORE_3_50)) {
if (!priv->plat->rwit_off) {
...
would be clearer (note the splitting of the if() conditions which seems
to me would be more readable than trying to munge it all into one
expression.)
3) max_mtu setup:
/* Set the maximum MTU.
* For XGMAC cores, 16KiB.
* For cores using enhanced descriptors or GMAC cores >= v4.00, 9kB.
* For everything else, PAGE_SIZE - NET_SKB_PAD - NET_IP_ALIGN -
* aligned skb_shared_info.
*/
if (priv->plat->core_type == DWMAC_CORE_XGMAC)
ndev->max_mtu = XGMAC_JUMBO_LEN;
else if (priv->plat->enh_desc || priv->snpsver >= DWMAC_CORE_4_00)
ndev->max_mtu = JUMBO_LEN;
else
ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
which I've previously identified is very buggy, and I'm not sure what
the real tests here should be. I'm quite certain that the max_mtu
values are basically completely wrong, especially in the last case.
This needs a lot of analysis and comparing with documentation to get
to the bottom of what the tests and resulting max_mtu values should
actually be.
.../net/ethernet/stmicro/stmmac/dwmac-loongson.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/hwif.c | 54 +++++++++++-----------
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +-
.../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 51 +++++++++++---------
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 24 ++++++----
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 8 ++--
include/linux/stmmac.h | 7 +++
9 files changed, 85 insertions(+), 67 deletions(-)
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply
* Re: [PATCH 00/10] arm64/entry:
From: Peter Zijlstra @ 2026-04-08 9:19 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Mark Rutland, vladimir.murzin, Catalin Marinas, ruanjinjie,
linux-kernel, Andy Lutomirski, Will Deacon, linux-arm-kernel
In-Reply-To: <87cy0a4gx7.ffs@tglx>
On Tue, Apr 07, 2026 at 11:08:36PM +0200, Thomas Gleixner wrote:
> On Tue, Apr 07 2026 at 14:16, Mark Rutland wrote:
> > I've split the series into a prefix of changes for generic irqentry,
> > followed by changes to the arm64 code. I'm hoping that we can queue the
> > generic irqentry patches onto a stable branch, or take those via arm64.
> > The patches are as follows:
> >
> > * Patches 1 and 2 are cleanup to the generic irqentry code. These have no
> > functional impact, and I think these can be taken regardless of the
> > rest of the series.
> >
> > * Patches 3 to 5 refactor the generic irqentry code as described above,
> > providing separate irqentry_{enter,exit}() functions and providing a
> > split form of irqentry_exit_to_kernel_mode() similar to what exists
> > for irqentry_exit_to_user_mode(). These patches alone should have no
> > functional impact.
>
> I looked through them and I can't find any problem with them. I queued
> them localy and added the missing kernel doc as I promised you on IRC.
>
> As I have quite a conflict pending in the tip tree with other changes
> related to the generic entry code, I suggest that I queue 1-5, tag them
> for arm64 consumption and merge them into the conflicting branch to
> avoid trouble with pull request ordering and headaches for the -next
> people.
FWIW, for those 1-5
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
^ permalink raw reply
* Re: [PATCH 1/2] coresight: etm4x: fix inconsistencies with sysfs configration
From: Yeoreum Yun @ 2026-04-08 9:17 UTC (permalink / raw)
To: Leo Yan
Cc: coresight, linux-arm-kernel, linux-kernel, suzuki.poulose,
mike.leach, james.clark, alexander.shishkin
In-Reply-To: <20260407143028.GM356832@e132581.arm.com>
Hi Leo,
> On Tue, Mar 17, 2026 at 06:17:04PM +0000, Yeoreum Yun wrote:
> > The current ETM4x configuration via sysfs can lead to the following
> > inconsistencies:
> >
> > - If a configuration is modified via sysfs while a perf session is
> > active, the running configuration may differ between before
> > a sched-out and after a subsequent sched-in.
> >
> > - Once a perf session is enabled, some read-only register fields
> > (e.g., TRCSSCSR<n>) may not be reported correctly,
> > because drvdata->config is cleared while enabling with perf mode,
> > even though the information was previously read via etm4_init_arch_data().
> >
> > To resolve these inconsistencies, the configuration should be separated into:
> >
> > - active_config, which represents the currently applied configuration
> > - config, which stores the settings configured via sysfs.
> >
> > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> > ---
> > .../hwtracing/coresight/coresight-etm4x-cfg.c | 2 +-
> > .../coresight/coresight-etm4x-core.c | 45 +++++++++++--------
> > drivers/hwtracing/coresight/coresight-etm4x.h | 2 +
> > 3 files changed, 30 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
> > index c302072b293a..84213d40d1ae 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
> > +++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
> > @@ -47,7 +47,7 @@ static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
> > struct cscfg_regval_csdev *reg_csdev, u32 offset)
> > {
> > int err = -EINVAL, idx;
> > - struct etmv4_config *drvcfg = &drvdata->config;
> > + struct etmv4_config *drvcfg = &drvdata->active_config;
>
> I'd suggest we leave out complex cfg things, we can refactor it
> later.
>
> In this series, let us first separate active_config and config, and
> keep using drvdata->config to save complex cfg ?
Yes. but I think we should include the separation of ss_status in
this patchset.
>
> > u32 off_mask;
> >
> > if (((offset >= TRCEVENTCTL0R) && (offset <= TRCVIPCSSCTLR)) ||
> > diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > index d565a73f0042..c552129c4a0c 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > @@ -88,9 +88,11 @@ static int etm4_probe_cpu(unsigned int cpu);
> > */
> > static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
> > {
> > + struct etmv4_config *config = &drvdata->active_config;
> > +
> > return (n < drvdata->nr_ss_cmp) &&
> > drvdata->nr_pe &&
> > - (drvdata->config.ss_status[n] & TRCSSCSRn_PC);
> > + (config->ss_status[n] & TRCSSCSRn_PC);
>
> As Suzuki suggested in another reply, we need to extract capabilities
> into a separate structure. I'd also extract status related registers
> into a new structure:
>
> struct etm4_cap {
> int nr_ss_cmp;
> bool pe_comparator; // TRCSSCSRn.PC
> bool dv_comparator; // TRCSSCSRn.DV
> bool da_comparator; // TRCSSCSRn.DA
> bool inst_comparator; // TRCSSCSRn.INST
>
> int ns_ex_level;
> int nr_pe;
> int nr_pe_cmp;
> int nr_resource;
> ...
> }
>
> struct etm4_status_reg {
> u32 ss_status[ETM_MAX_SS_CMP];
> u32 cntr_val[ETMv4_MAX_CNTR];
> }
Thanks. I'll take with this as reference.
>
> [...]
>
> > @@ -911,14 +915,17 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
> >
> > /* enable any config activated by configfs */
> > cscfg_config_sysfs_get_active_cfg(&cfg_hash, &preset);
> > +
> > + raw_spin_lock(&drvdata->spinlock);
> > +
> > + drvdata->active_config = drvdata->config;
>
> This is not an issue introduced by this patch, but we might need to
> consider to copy active config until it has acquired SYSFS mode.
> Otherwise, it might update config here but will disturb a perf session
> has been running.
Good catch. I think we should access "active_config" after taking a
mode. That means cscfg_csdev_enable/disable_active_config() should
be called after/before taking mode like PERF session otherwise
active_config could be a race if perf and sysfs session are enabled parallely.
>
> > @@ -2246,7 +2254,8 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg)
> > if (!desc.name)
> > return -ENOMEM;
> >
> > - etm4_set_default(&drvdata->config);
> > + etm4_set_default(&drvdata->active_config);
>
> Should we set default values to drvdata->config ?
>
> My understanding is drvdata->active_config would be always set at the
> runtime, but "drvdata->config" should be initialized properly so it
> can be consumed by sysfs knobs.
Right. I've only thought about perf case not a sysfs knobs for this.
Thanks.
--
Sincerely,
Yeoreum Yun
^ permalink raw reply
* Re: [PATCH 05/10] entry: Split preemption from irqentry_exit_to_kernel_mode()
From: Jinjie Ruan @ 2026-04-08 9:17 UTC (permalink / raw)
To: Mark Rutland, linux-arm-kernel, Andy Lutomirski, Peter Zijlstra,
Thomas Gleixner
Cc: vladimir.murzin, will, linux-kernel, catalin.marinas
In-Reply-To: <20260407131650.3813777-6-mark.rutland@arm.com>
On 2026/4/7 21:16, Mark Rutland wrote:
> Some architecture-specific work needs to be performed between the state
> management for exception entry/exit and the "real" work to handle the
> exception. For example, arm64 needs to manipulate a number of exception
> masking bits, with different exceptions requiring different masking.
>
> Generally this can all be hidden in the architecture code, but for arm64
> the current structure of irqentry_exit_to_kernel_mode() makes this
> particularly difficult to handle in a way that is correct, maintainable,
> and efficient.
>
> The gory details are described in the thread surrounding:
>
> https://lore.kernel.org/lkml/acPAzdtjK5w-rNqC@J2N7QTR9R3/
>
> The summary is:
>
> * Currently, irqentry_exit_to_kernel_mode() handles both involuntary
> preemption AND state management necessary for exception return.
>
> * When scheduling (including involuntary preemption), arm64 needs to
> have all arm64-specific exceptions unmasked, though regular interrupts
> must be masked.
>
> * Prior to the state management for exception return, arm64 needs to
> mask a number of arm64-specific exceptions, and perform some work with
> these exceptions masked (with RCU watching, etc).
>
> While in theory it is possible to handle this with a new arch_*() hook
> called somewhere under irqentry_exit_to_kernel_mode(), this is fragile
> and complicated, and doesn't match the flow used for exception return to
> user mode, which has a separate 'prepare' step (where preemption can
> occur) prior to the state management.
>
> To solve this, refactor irqentry_exit_to_kernel_mode() to match the
> style of {irqentry,syscall}_exit_to_user_mode(), moving preemption logic
> into a new irqentry_exit_to_kernel_mode_preempt() function, and moving
> state management in a new irqentry_exit_to_kernel_mode_after_preempt()
> function. The existing irqentry_exit_to_kernel_mode() is left as a
> caller of both of these, avoiding the need to modify existing callers.
>
> There should be no functional change as a result of this patch.
>
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Jinjie Ruan <ruanjinjie@huawei.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Thomas Gleixner <tglx@kernel.org>
> Cc: Vladimir Murzin <vladimir.murzin@arm.com>
> Cc: Will Deacon <will@kernel.org>
> ---
> include/linux/irq-entry-common.h | 26 +++++++++++++++++++++-----
> 1 file changed, 21 insertions(+), 5 deletions(-)
>
> Thomas/Peter/Andy, as mentioned on IRC, I haven't created kerneldoc
> comments for these new functions because the existing comments don't
> seem all that consistent (e.g. for user mode vs kernel mode), and I
> suspect we want to rewrite them all in one go for wider consistency.
>
> I'm happy to respin this, or to follow-up with that as per your
> preference.
>
> Mark.
>
> diff --git a/include/linux/irq-entry-common.h b/include/linux/irq-entry-common.h
> index 2206150e526d8..24830baa539c6 100644
> --- a/include/linux/irq-entry-common.h
> +++ b/include/linux/irq-entry-common.h
> @@ -421,10 +421,18 @@ static __always_inline irqentry_state_t irqentry_enter_from_kernel_mode(struct p
> return ret;
> }
>
> -static __always_inline void irqentry_exit_to_kernel_mode(struct pt_regs *regs, irqentry_state_t state)
> +static inline void irqentry_exit_to_kernel_mode_preempt(struct pt_regs *regs, irqentry_state_t state)
> {
> - lockdep_assert_irqs_disabled();
> + if (regs_irqs_disabled(regs) || state.exit_rcu)
> + return;
> +
> + if (IS_ENABLED(CONFIG_PREEMPTION))
> + irqentry_exit_cond_resched();
> +}
>
> +static __always_inline void
> +irqentry_exit_to_kernel_mode_after_preempt(struct pt_regs *regs, irqentry_state_t state)
> +{
> if (!regs_irqs_disabled(regs)) {
> /*
> * If RCU was not watching on entry this needs to be done
> @@ -443,9 +451,6 @@ static __always_inline void irqentry_exit_to_kernel_mode(struct pt_regs *regs, i
> }
>
> instrumentation_begin();
> - if (IS_ENABLED(CONFIG_PREEMPTION))
> - irqentry_exit_cond_resched();
> -
> /* Covers both tracing and lockdep */
> trace_hardirqs_on();
> instrumentation_end();
> @@ -459,6 +464,17 @@ static __always_inline void irqentry_exit_to_kernel_mode(struct pt_regs *regs, i
> }
> }
>
> +static __always_inline void irqentry_exit_to_kernel_mode(struct pt_regs *regs, irqentry_state_t state)
> +{
> + lockdep_assert_irqs_disabled();
> +
> + instrumentation_begin();
> + irqentry_exit_to_kernel_mode_preempt(regs, state);
> + instrumentation_end();
I think the below AI's feedback makes sense. Directly calling
irqentry_exit_to_kernel_mode_preempt() on arm64/other archs could lead
to missing instrumentation_begin()/end() markers.
https://sashiko.dev/#/patchset/20260407131650.3813777-1-mark.rutland%40arm.com
> +
> + irqentry_exit_to_kernel_mode_after_preempt(regs, state);
> +}
> +
> /**
> * irqentry_enter - Handle state tracking on ordinary interrupt entries
> * @regs: Pointer to pt_regs of interrupted context
^ 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