lan966x pci device: Add support for SFPs, PCI part
Subsystems (11)
v9 cover lan966x pci device: Add support for SFPs, PCI part
Hi,
Previously, I sent a big picture series adding support for SFP ports available on the LAN966x PCI device [0].
In this series patches touch several parts and sub-system in the kernel. Reviews have be done and it makes sense to split the series and send parts separately.
This current series is the extraction of patches related to issues in the PCI subsystem. It has to be seen as a continuation of the big picture series but related to this specific core part.
Patches 1 to 6 introduce and use fw_devlink_set_device() in already existing code. No functional change but the introduction of the fw_devlink_set_device() wrapper.
Patch 7 avoid a dangling pointer.
Patches 8 and 9 fix fw_devlink issues specific to PCI and the device-tree nodes created during enumeration.
[0] https://lore.kernel.org/all/[email protected]/
Best regards,
Hervé
Changes:
v8 -> v9
v8: https://lore.kernel.org/all/[email protected]/
- Patch 7 (new patch in v9)
Clear fwnode->dev during root bridge node removal (avoid a dangling
pointer).- Patch 8 (patch 7 in v8)
Clear fwnode->dev during PCI device node removal.
v7 -> v8
v7: https://lore.kernel.org/all/[email protected]/
Rebase on top of v7.2-rc1
- patches 4 and 5
Add 'Reviewed-by: Andy Shevchenko'
- Other Patches
No other changes
v6 -> v7
Rebase on top of v7.1-rc1
- Patch 1
Add Cc stable. Needed for patches 11 and 12
- Patches 2 to 5
No changes
- Patch 6
Add Cc stable. Needed for patch 13
Add 'Acked-by: Bjorn Helgaas'
- Patch 7
Fix a typo in commit log
Add Fixes tag + Cc stable
Add 'Acked-by: Bjorn Helgaas'
- Patch 8
Add Fixes tag + Cc stable
Add 'Acked-by: Bjorn Helgaas'
Older iterations:
Patches 6 to 13 in the big picture series
https://lore.kernel.org/all/[email protected]/
Herve Codina (9):
driver core: fw_devlink: Introduce fw_devlink_set_device()
drivers: core: Use fw_devlink_set_device()
pinctrl: cs42l43: Use fw_devlink_set_device()
cxl/test: Use device_set_node()
cxl/test: Use fw_devlink_set_device()
PCI: of: Use fw_devlink_set_device()
PCI: of: Clear fwnode->dev during root bridge node removal
PCI: of: Set fwnode device of newly created PCI device nodes
PCI: of: Remove fwnode_dev_initialized() call for a PCI root bridge
node
drivers/base/core.c | 4 ++-- drivers/pci/of.c | 12 ++++++++++-- drivers/pinctrl/cirrus/pinctrl-cs42l43.c | 2 +- include/linux/fwnode.h | 6 ++++++ tools/testing/cxl/test/cxl.c | 4 ++-- 5 files changed, 21 insertions(+), 7 deletions(-)
Signature · 1 line
2.54.0
PATCH v9 1/9 driver core: fw_devlink: Introduce fw_devlink_set_device()
Setting fwnode->dev is specific to fw_devlink.
In order to avoid having a direct 'fwnode->dev = dev;' in several place in the kernel, introduce fw_devlink_set_device() helper to perform this operation.
Having this helper allows to hide the fwnode devlink related stuff behind the helper.
---
Cc stable because used by other patches with Fixes + Cc stable
--- include/linux/fwnode.h | 6 ++++++ 1 file changed, 6 insertions(+)
include/linux/fwnode.h +6 -0
@@ -256,4 +256,10 @@ void fw_devlink_purge_absent_suppliers(struct fwnode_handle *fwnode);void fw_devlink_refresh_fwnode (struct fwnode_handle *fwnode);bool fw_devlink_is_strict (void ); +static inline void fw_devlink_set_device (struct fwnode_handle *fwnode, +struct device *dev) +{ + fwnode->dev = dev; +} +#endif
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v9 1/9] driver core: fw_devlink: Introduce fw_devlink_set_device()
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 11 lines
Setting
fwnode->devis specific tofw_devlink.In order to avoid having a direct '
fwnode->dev= dev;' in several place in the kernel, introducefw_devlink_set_device()helper to perform this operation.Having this helper allows to hide the fwnode devlink related stuff behind the helper.
Signed-off-by Herve Codina <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
PATCH v9 2/9 drivers: core: Use fw_devlink_set_device()
In reply to Herve CodinaThe code set directly fwnode->dev field.
Use the dedicated fw_devlink_set_device() helper to perform this operation.
--- drivers/base/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/base/core.c +2 -2
@@ -3750,7 +3750,7 @@ int device_add(struct device *dev)* device and the driver sync_state callback is called for this device. */ if (dev->fwnode && !dev->fwnode->dev) { - dev->fwnode->dev = dev; +fw_devlink_set_device (dev->fwnode, dev);fw_devlink_link_device (dev); }
@@ -3925,7 +3925,7 @@ void device_del(struct device *dev)device_unlock (dev);if (dev->fwnode && dev->fwnode->dev == dev) - dev->fwnode->dev =NULL ; +fw_devlink_set_device (dev->fwnode,NULL );/* Notify clients of device removal. This call must come * before dpm_sysfs_remove().
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v9 2/9] drivers: core: Use fw_devlink_set_device()
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 6 lines
The code set directly
fwnode->devfield.Use the dedicated
fw_devlink_set_device()helper to perform this operation.Signed-off-by Herve Codina <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
PATCH v9 3/9 pinctrl: cs42l43: Use fw_devlink_set_device()
In reply to Herve CodinaThe code set directly fwnode->dev field.
Use the dedicated fw_devlink_set_device() helper to perform this operation.
--- drivers/pinctrl/cirrus/pinctrl-cs42l43.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/cirrus/pinctrl-cs42l43.c +1 -1
@@ -576,7 +576,7 @@ static int cs42l43_pin_probe(struct platform_device *pdev)return ret;if (!child->dev) - child->dev = priv->dev; +fw_devlink_set_device (child, priv->dev); fwnode = child; } }
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v9 3/9] pinctrl: cs42l43: Use fw_devlink_set_device()
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] The driver overwrites the platform device's fwnode and devlink device pointer during probe, but fails to restore them on probe failure or driver unbind, leading to a Use-After-Free. --
--- Patch [3]: [PATCH v9 3/9] pinctrl: cs42l43: Use fw_devlink_set_device() --- commit 80d27bc87210331a635e646eedd21068256104a4
Author: Herve Codina <[email protected]>
pinctrl: cs42l43: Use fw_devlink_set_device()
This patch updates the CS42L43 pinctrl driver to use the dedicated fw_devlink_set_device() helper instead of directly modifying the fwnode->dev field.
drivers/pinctrl/cirrus/pinctrl-cs42l43.c static int cs42l43_pin_probe(struct platform_device *pdev) · line 579
Quoted 10 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c +1
-1@@ -576,7 +576,7 @@ static int cs42l43_pin_probe(struct platform_device *pdev)return ret;if (!child->dev) - child->dev = priv->dev; +fw_devlink_set_device (child, priv->dev);
[Severity: High]
This isn't a bug introduced by this patch, but could this setup leave a dangling pointer that leads to a use-after-free on unbind?
If the device is instantiated via a Device Tree overlay, the driver fetches the child node, takes a reference to it, and registers a devres action (cs42l43_fwnode_put) to drop this reference on teardown.
Later in cs42l43_pin_probe(), the driver calls:
device_set_node(priv->dev, fwnode);
This overwrites the platform device's fwnode with the child node without taking an additional reference.
If the driver is unbound manually via sysfs or fails probe, the devres action drops the driver's reference to the child node, but pdev->dev.fwnode is left pointing to it. If the DT overlay is then removed, the OF core detaches the node, causing the child node to be freed.
Finally, the OF core notifier triggers platform device removal, and device_del() attempts to access dev->fwnode->dev to clear the devlink, dereferencing the freed child node.
Does this require a cleanup action to restore the original fwnode and devlink device pointer on teardown?
Quoted 3 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c +0
-0fwnode = child; } }
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
PATCH v9 4/9 cxl/test: Use device_set_node()
In reply to Herve CodinaThe code set directly dev->fwnode.
Use the dedicated helper to perform this operation.
--- tools/testing/cxl/test/cxl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/cxl/test/cxl.c +1 -1
@@ -1528,7 +1528,7 @@ static void mock_companion(struct acpi_device *adev, struct device *dev) {device_initialize (&adev->dev);fwnode_init (&adev->fwnode,NULL ); - dev->fwnode = &adev->fwnode; +device_set_node (dev, &adev->fwnode); adev->fwnode.dev = dev; }
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v9 4/9] cxl/test: Use device_set_node()
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 5 lines
The code set directly
dev->fwnode.Use the dedicated helper to perform this operation.
Signed-off-by Herve Codina <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
PATCH v9 5/9 cxl/test: Use fw_devlink_set_device()
In reply to Herve CodinaThe code set directly fwnode.dev field.
Use the dedicated fw_devlink_set_device() helper to perform this operation.
--- tools/testing/cxl/test/cxl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/cxl/test/cxl.c +1 -1
@@ -1529,7 +1529,7 @@ static void mock_companion(struct acpi_device *adev, struct device *dev)device_initialize (&adev->dev);fwnode_init (&adev->fwnode,NULL );device_set_node (dev, &adev->fwnode); - adev->fwnode.dev = dev; +fw_devlink_set_device (&adev->fwnode, dev); }#ifndef SZ_64G
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v9 5/9] cxl/test: Use fw_devlink_set_device()
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 6 lines
The code set directly fwnode.dev field.
Use the dedicated
fw_devlink_set_device()helper to perform this operation.Signed-off-by Herve Codina <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
PATCH v9 6/9 PCI: of: Use fw_devlink_set_device()
In reply to Herve CodinaThe code set directly fwnode.dev field.
Use the dedicated fw_devlink_set_device() helper to perform this operation.
---
Cc stable because used by other patches with Fixes + Cc stable
--- drivers/pci/of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/of.c +1 -1
@@ -803,7 +803,7 @@ void of_pci_make_host_bridge_node(struct pci_host_bridge *bridge)* bus. Avoid any new device creation. */ of_node_set_flag (np,OF_POPULATED ); - np->fwnode.dev = &bridge->dev; +fw_devlink_set_device (&np->fwnode, &bridge->dev);fwnode_dev_initialized (&np->fwnode, true); ret =of_changeset_apply (cset);
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v9 6/9] PCI: of: Use fw_devlink_set_device()
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Dangling pointer in np->fwnode.dev on error paths and during bridge removal, leading to a potential use-after-free. --
--- Patch [6]: [PATCH v9 6/9] PCI: of: Use fw_devlink_set_device() --- commit e05d94ee3b1f4fa9d5ff1b29db6b40e43eca7313
Author: Herve Codina <[email protected]>
PCI: of: Use fw_devlink_set_device()
The code directly set the fwnode.dev field. This commit updates the code to use the dedicated fw_devlink_set_device() helper to perform this operation.
drivers/pci/of.c void of_pci_make_host_bridge_node(struct pci_host_bridge *bridge) · line 806
Quoted 10 lines
drivers/pci/of.c +1
-1@@ -803,7 +803,7 @@ void of_pci_make_host_bridge_node(struct pci_host_bridge *bridge)* bus. Avoid any new device creation. */ of_node_set_flag (np,OF_POPULATED ); - np->fwnode.dev = &bridge->dev; +fw_devlink_set_device (&np->fwnode, &bridge->dev);
[Severity: High]
This isn't a bug introduced by this patch, but could this lead to a use-after-free on error paths?
In of_pci_make_host_bridge_node(), if an error occurs after setting up the fwnode (such as of_changeset_apply() or device_add_of_node() failing), the error path removes the node from the tree and releases its reference, but fails to clear the np->fwnode.dev pointer:
out_revert_cset:
np->data = NULL; of_changeset_revert(cset); out_free_node: of_node_put(np);
Because device_remove_of_node() only clears the forward pointer (dev->fwnode) and not the backpointer, np->fwnode.dev remains dangling. If another thread holds a reference to np, the node outlives the function. When the bridge is later freed, any concurrent access via get_dev_from_fwnode(&np->fwnode) could dereference freed memory.
The same dangling pointer issue appears to exist in of_pci_remove_host_bridge_node() during teardown:
void of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge) {
...
device_remove_of_node(&bridge->bus->dev); device_remove_of_node(&bridge->dev); of_changeset_revert(np->data); of_changeset_destroy(np->data); of_node_put(np); }
Quoted 3 lines
drivers/pci/of.c +0
-0fwnode_dev_initialized (&np->fwnode, true); ret =of_changeset_apply (cset);
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
Re: [PATCH v9 6/9] PCI: of: Use fw_devlink_set_device()
Hi,
Quoted 54 lines · On Wed, 08 Jul 2026 10:29:21 +0000 [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Dangling pointer innp->fwnode.devon error paths and during bridge removal, leading to a potential use-after-free. ----- Patch [6]: [PATCH v9 6/9] PCI: of: Use
fw_devlink_set_device()--- commite05d94ee3b1f4fa9d5ff1b29db6b40e43eca7313
Author: Herve Codina <[email protected]>PCI: of: Use
fw_devlink_set_device()The code directly set the fwnode.dev field. This commit updates the code to use the dedicated
fw_devlink_set_device()helper to perform this operation.drivers/pci/of.c void of_pci_make_host_bridge_node(struct pci_host_bridge *bridge) · line 806
Quoted 10 lines
drivers/pci/of.c +1
-1@@ -803,7 +803,7 @@ void of_pci_make_host_bridge_node(struct pci_host_bridge *bridge)* bus. Avoid any new device creation. */ of_node_set_flag (np,OF_POPULATED ); - np->fwnode.dev = &bridge->dev; +fw_devlink_set_device (&np->fwnode, &bridge->dev);[Severity: High]
This isn't a bug introduced by this patch, but could this lead to a use-after-free on error paths?In
of_pci_make_host_bridge_node(), if an error occurs after setting up the fwnode (such asof_changeset_apply()ordevice_add_of_node()failing), the error path removes the node from the tree and releases its reference, but fails to clear thenp->fwnode.devpointer:
out_revert_cset:np->data = NULL; of_changeset_revert(cset); out_free_node: of_node_put(np);Because
device_remove_of_node()only clears the forward pointer (dev->fwnode) and not the backpointer,np->fwnode.devremains dangling. If another thread holds a reference to np, the node outlives the function. When the bridge is later freed, any concurrent access viaget_dev_from_fwnode(&np->fwnode)could dereference freed memory.The same dangling pointer issue appears to exist in
of_pci_remove_host_bridge_node()during teardown:void
of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge){
...
Quoted 6 lines
device_remove_of_node(&bridge->bus->dev); device_remove_of_node(&bridge->dev); of_changeset_revert(np->data); of_changeset_destroy(np->data); of_node_put(np); }
This issue is relevant and clearing np->fwnode.dev in the error path will be take into account in the next iteration.
Hervé
PATCH v9 7/9 PCI: of: Clear fwnode->dev during root bridge node removal
In reply to Herve CodinaDuring the of_pci_make_host_bridge_node() call, an OF node is created dynamically and its fwnode device (fwnode->dev) is set to the PCI root bridge device using the fw_devlink_set_device(&np->fwnode, &bridge->dev) call.
On removal, of_pci_remove_host_bridge_node() is called and calls device_remove_of_node() which in turn set to NULL the related dev->fwnode.
Later in the removal sequence, device_del() is called and runs its cleanup logic:
if (dev->fwnode && dev->fwnode->dev == dev)
fw_devlink_set_device(dev->fwnode, NULL);Because dev->fwnode has been cleared earlier, fw_devlink_set_device() is not called and leaves fwnode->dev unchanged. This fwnode device (fwnode->dev) becomes an dangling pointer.
If any reference to the OF node is held after this removal, the pointer is still accessible using the OF node (np->fwnode.dev) but points to a freed area.
Avoid this dangling fwnode->dev pointer by clearing it in of_pci_remove_host_bridge_node().
--- drivers/pci/of.c | 1 + 1 file changed, 1 insertion(+)
drivers/pci/of.c +1 -0
@@ -743,6 +743,7 @@ void of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge)if (!np || !of_node_check_flag (np,OF_DYNAMIC ))return ; +fw_devlink_set_device (&np->fwnode,NULL );device_remove_of_node (&bridge->bus->dev);device_remove_of_node (&bridge->dev);of_changeset_revert (np->data);
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v9 7/9] PCI: of: Clear fwnode->dev during root bridge node removal
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Missing fw_devlink cleanup in the error path of of_pci_make_host_bridge_node(), leaving a dangling fwnode->dev pointer.
- [High] Kernel panic on removal of overlay-provided PCI host bridge nodes due to unsafe changeset revert. --
--- Patch [7]: [PATCH v9 7/9] PCI: of: Clear fwnode->dev during root bridge node removal --- commit 9e6873c21d6442ce4222fe6e9ac417348c8b3fbd
Author: Herve Codina <[email protected]>
PCI: of: Clear fwnode->dev during root bridge node removal
This commit clears fwnode->dev during of_pci_remove_host_bridge_node() to prevent a dangling pointer. It ensures fw_devlink_set_device() is called with a NULL device before the fwnode is cleared.
drivers/pci/of.c void of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge) · line 746
Quoted 9 lines
drivers/pci/of.c +1
-0@@ -743,6 +743,7 @@ void of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge)if (!np || !of_node_check_flag (np,OF_DYNAMIC ))return ; +fw_devlink_set_device (&np->fwnode,NULL );
[Severity: High]
This is a pre-existing issue, but does of_pci_make_host_bridge_node() also need to clear the fwnode->dev pointer on its error path?
If device_add_of_node() fails in of_pci_make_host_bridge_node(), it jumps to the error paths but leaves np->fwnode.dev pointing to the bridge device:
drivers/pci/of.c:of_pci_make_host_bridge_node() {
...
fw_devlink_set_device(&np->fwnode, &bridge->dev);
...
/* Add the of_node to host bridge and the root bus */
ret = device_add_of_node(&bridge->dev, np);
if (ret)
goto out_revert_cset;
ret = device_add_of_node(&bridge->bus->dev, np);
if (ret)
goto out_remove_bridge_dev_of_node;
...
out_remove_bridge_dev_of_node:
device_remove_of_node(&bridge->dev);
out_revert_cset:
np->data = NULL;
of_changeset_revert(cset);
out_free_node:
of_node_put(np);
...
}If a concurrent thread acquired a reference to np, could the node outlive the error path and result in a use-after-free where fwnode->dev points to freed memory?
drivers/pci/of.c void of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge) · line 749
Quoted 3 lines
drivers/pci/of.c +0
-0device_remove_of_node (&bridge->bus->dev);device_remove_of_node (&bridge->dev);of_changeset_revert (np->data);
[Severity: High]
This isn't a bug introduced by this patch, but does calling of_changeset_revert(np->data) unconditionally cause a crash when removing an overlay-provided PCI host bridge node?
When an overlay provides the device tree node for a PCI host bridge, the node inherently has the OF_DYNAMIC flag set. If the bridge is removed, of_pci_remove_host_bridge_node() assumes the node was created by of_pci_make_host_bridge_node() and executes of_changeset_revert(np->data).
Since np->data is NULL for standard overlay nodes, does this result in a NULL pointer dereference in __of_changeset_revert_entries() when it tries to evaluate &ocs->entries?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=7
Re: [PATCH v9 7/9] PCI: of: Clear fwnode->dev during root bridge node removal
Quoted 57 lines · On Wed, 08 Jul 2026 10:34:34 +0000 [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Missingfw_devlinkcleanup in the error path ofof_pci_make_host_bridge_node(), leaving a danglingfwnode->devpointer.
- [High] Kernel panic on removal of overlay-provided PCI host bridge nodes due to unsafe changeset revert. ----- Patch [7]: [PATCH v9 7/9] PCI: of: Clear
fwnode->devduring root bridge node removal --- commit9e6873c21d6442ce4222fe6e9ac417348c8b3fbd
Author: Herve Codina <[email protected]>PCI: of: Clear
fwnode->devduring root bridge node removalThis commit clears
fwnode->devduringof_pci_remove_host_bridge_node()to prevent a dangling pointer. It ensuresfw_devlink_set_device()is called with a NULL device before the fwnode is cleared.drivers/pci/of.c void of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge) · line 746
Quoted 9 lines
drivers/pci/of.c +1
-0@@ -743,6 +743,7 @@ void of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge)if (!np || !of_node_check_flag (np,OF_DYNAMIC ))return ; +fw_devlink_set_device (&np->fwnode,NULL );[Severity: High]
This is a pre-existing issue, but doesof_pci_make_host_bridge_node()also need to clear thefwnode->devpointer on its error path?If
device_add_of_node()fails inof_pci_make_host_bridge_node(), it jumps to the error paths but leavesnp->fwnode.devpointing to the bridge device:drivers/pci/of.c:of_pci_make_host_bridge_node() { ... fw_devlink_set_device(&np->fwnode, &bridge->dev); ... /* Add the of_node to host bridge and the root bus */ ret = device_add_of_node(&bridge->dev, np); if (ret) goto out_revert_cset; ret = device_add_of_node(&bridge->bus->dev, np); if (ret) goto out_remove_bridge_dev_of_node; ... out_remove_bridge_dev_of_node: device_remove_of_node(&bridge->dev); out_revert_cset: np->data = NULL; of_changeset_revert(cset); out_free_node: of_node_put(np); ... }
Quoted 3 lines
If a concurrent thread acquired a reference to np, could the node outlive the error path and result in a use-after-free where
fwnode->devpoints to freed memory?
This issue is relevant and clearing np->fwnode.dev in the error path will be take into account in the next iteration.
Quoted 10 lines
drivers/pci/of.c void of_pci_remove_host_bridge_node(struct pci_host_bridge *bridge) · line 749
Quoted 4 lines
drivers/pci/of.c +0
-0device_remove_of_node (&bridge->bus->dev);device_remove_of_node (&bridge->dev);of_changeset_revert (np->data);[Severity: High]
This isn't a bug introduced by this patch, but does callingof_changeset_revert(np->data)unconditionally cause a crash when removing an overlay-provided PCI host bridge node?
Quoted 9 lines
When an overlay provides the device tree node for a PCI host bridge, the node inherently has the
OF_DYNAMICflag set. If the bridge is removed,of_pci_remove_host_bridge_node()assumes the node was created byof_pci_make_host_bridge_node()and executesof_changeset_revert(np->data).Since
np->datais NULL for standard overlay nodes, does this result in a NULL pointer dereference in__of_changeset_revert_entries()when it tries to evaluate&ocs->entries?
This scenario should not exist but anyway, I will add a new patch in the series in order to have a more robust code checking for a NULL np->data in both of_pci_remove_host_bridge_node() and of_pci_remove_node().
Hervé
PATCH v9 8/9 PCI: of: Set fwnode device of newly created PCI device nodes
In reply to Herve CodinaDevice-tree node can be created when CONFIG_PCI_DYNAMIC_OF_NODES. Those nodes are created and filled based on PCI core information but the fwnode device field is not set.
When later an overlay is applied, this confuses fw_devlink. Indeed, without any device attached to the node, fw_devlink considers that this node will never become a device. When this node is pointed as a supplier, devlink looks at its ancestors in order to find a node with a device that could be used as the supplier.
In the PCI use case, this leads to links that wrongly use the PCI root bridge device as the supplier instead of the expected PCI device.
Setting the fwnode device to the device of the PCI device allows devlink to use this device as a supplier and so, correct links are created.
--- drivers/pci/of.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/pci/of.c +8 -0
@@ -657,6 +657,7 @@ void of_pci_remove_node(struct pci_dev *pdev)if (!np || !of_node_check_flag (np,OF_DYNAMIC ))return ; +fw_devlink_set_device (&np->fwnode,NULL );device_remove_of_node (&pdev->dev);of_changeset_revert (np->data);of_changeset_destroy (np->data);
@@ -709,6 +710,13 @@ void of_pci_make_dev_node(struct pci_dev *pdev)if (ret) goto out_free_node; +/* +* Set the fwnode device in order to have fw_devlink creating links +* pointing to this PCI device instead of walking up to the PCI host +* bridge. +*/ +fw_devlink_set_device (&np->fwnode, &pdev->dev); + ret =of_changeset_apply (cset);if (ret) goto out_free_node;
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v9 8/9] PCI: of: Set fwnode device of newly created PCI device nodes
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] The `fwnode->dev` pointer is not cleared in the error paths of `of_pci_make_dev_node()` and…
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The fwnode->dev pointer is not cleared in the error paths of of_pci_make_dev_node() and of_pci_make_host_bridge_node(), potentially leaving a dangling pointer. --
--- Patch [8]: [PATCH v9 8/9] PCI: of: Set fwnode device of newly created PCI device nodes --- commit deed8a4ace1f4465ff17d82fc17dc458281c89a1
Author: Herve Codina <[email protected]>
PCI: of: Set fwnode device of newly created PCI device nodes
This commit sets the fwnode device field for dynamically created PCI device nodes to prevent fw_devlink from incorrectly using the PCI root bridge as a supplier. It ensures proper links are created by pointing devlink directly to the PCI device.
Quoted 4 lines
drivers/pci/of.c +0
-0
[ ... ]
Quoted 4 lines
drivers/pci/of.c +0
-0@@ -709,6 +710,13 @@ void of_pci_make_dev_node(struct pci_dev *pdev)if (ret) goto out_free_node;
drivers/pci/of.c void of_pci_make_dev_node(struct pci_dev *pdev) · line 722
Quoted 10 lines
drivers/pci/of.c +7
-0+/* +* Set the fwnode device in order to have fw_devlink creating links +* pointing to this PCI device instead of walking up to the PCI host +* bridge. +*/ +fw_devlink_set_device (&np->fwnode, &pdev->dev); + ret =of_changeset_apply (cset);if (ret) goto out_free_node;
[Severity: High]
If of_changeset_apply() fails here, the code jumps to the out_free_node error path in of_pci_make_dev_node() without clearing the fwnode.dev pointer that was just set.
If the node survives due to an external reference acquired during partial application (such as from an OF_RECONFIG_ATTACH_NODE listener), could this leave np->fwnode.dev pointing to &pdev->dev?
When the PCI device is later freed, does this result in a dangling pointer and a potential use-after-free?
Should fw_devlink_set_device(&np->fwnode, NULL) be called in the error handling path to safely undo the assignment?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=8
PATCH v9 9/9 PCI: of: Remove fwnode_dev_initialized() call for a PCI root bridge node
In reply to Herve CodinaDuring the instantiation of devices described by a device-tree overlay applied on a PCI device, devlink displays the following kind of debug messages instead of creating the expected links:
'Not linking xxxx - might never become dev'
Without those expected links, the device removal order cannot be correct.
Those debug traces are printed by fw_devlink_create_devlink(). In our use case, they are all printed because the supplier of the link has at least one of its ancestor with its fwnode flag FWNODE_FLAG_INITIALIZED set.
The culprit ancestor is the PCI root bridge.
The fwnode related to the PCI root bridge is created dynamically by the of_pci_make_host_bridge_node() function. During this creation fwnode_dev_initialized() is called which set the FWNODE_FLAG_INITIALIZED flag.
Calling fwnode_dev_initialized() tells devlink that the device related to this node is handled out of the driver core. This is not correct in our case. Indeed the device related to this firmware node is handled using driver core mechanisms and is fully compliant devlink expectations.
Simply remove the fwnode_dev_initialized() call. With that done, the devlink debug messages are no more displayed and links that were missing are correctly created.
--- drivers/pci/of.c | 1 - 1 file changed, 1 deletion(-)
drivers/pci/of.c +0 -1
@@ -813,7 +813,6 @@ void of_pci_make_host_bridge_node(struct pci_host_bridge *bridge)*/ of_node_set_flag (np,OF_POPULATED );fw_devlink_set_device (&np->fwnode, &bridge->dev); -fwnode_dev_initialized (&np->fwnode, true); ret =of_changeset_apply (cset);if (ret)
Signature · 1 line
2.54.0
[email protected]
AI reviewRe: [PATCH v9 9/9] PCI: of: Remove fwnode_dev_initialized() call for a PCI root bridge node
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 13 lines
During the instantiation of devices described by a device-tree overlay applied on a PCI device, devlink displays the following kind of debug messages instead of creating the expected links:
'Not linking xxxx - might never become dev'Without those expected links, the device removal order cannot be correct.
Those debug traces are printed by
fw_devlink_create_devlink(). In our use case, they are all printed because the supplier of the link has at least one of its ancestor with its fwnode flagFWNODE_FLAG_INITIALIZEDset.
Quoted 8 lines
The culprit ancestor is the PCI root bridge.
[ ... ]
are correctly created.Fixes 1f340724419e ("PCI: of: Create device tree PCI host bridge node")Signed-off-by Herve Codina <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=9