From: Quanyang Wang <[email protected]> The phy->id is an unique id under &phy_ida after calling phy_create, but the s32g serdes driver uses it to save lane_id (0 or 1), this results that phy->id is not unique anymore and will trigger calltrace as below for being freed multiple times.
[ 129.135513] ida_free called for id=0 which is not allocated. [ 129.135668] WARNING: CPU: 3 PID: 46 at lib/idr.c:524 ida_free+0x13c/0x150 [ 129.135704] Modules linked in: [ 129.135718] CPU: 1 PID: 27 Comm: kworker/1:1 Not tainted 5.15.32-rt34-yocto-preempt-rt #1 [ 129.135729] Hardware name: Freescale S32G274A (DT) [ 129.135737] Workqueue: events kobject_delayed_cleanup [ 129.135751] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 129.135761] pc : ida_free+0x13c/0x150 [ 129.135769] lr : ida_free+0x13c/0x150 [ 129.135778] sp : ffffffc00bdfbc60 [ 129.135781] x29: ffffffc00bdfbc60 x28: ffffff885bffc205 x27: ffffffc009bfa0b8 [ 129.135793] x26: ffffffc00a49ed80 x25: 0000000000000000 x24: 0000000000000000 [ 129.135803] x23: ffffff880642e100 x22: 0000000000000000 x21: ffffff8801445a40 [ 129.135815] x20: 000000000000000c x19: 0000000000000000 x18: 0000000000000001 [ 129.135825] x17: 0000000000000000 x16: 0000000000000000 x15: ffffff8801445fb8 [ 129.135836] x14: ffffffffffffffff x13: 0a2e64657461636f x12: 6c6c6120746f6e20 [ 129.135847] x11: 656820747563205b x10: ffffffc009c4ac20 x9 : ffffffc0080d5850 [ 129.135858] x8 : ffffffc00bdfbc60 x7 : 0000000000000000 x6 : 0000000000000001 [ 129.135868] x5 : ffffffc009bfa000 x4 : ffffffc009bfaa18 x3 : 0000000000000000 [ 129.135878] x2 : ffffff8801445a40 x1 : 0000000000000000 x0 : 0000000000000000 [ 129.135889] Call trace: [ 129.135893] ida_free+0x13c/0x150 [ 129.135903] phy_release+0x38/0x50 [ 129.135913] device_release+0x3c/0x98 [ 129.135923] kobject_delayed_cleanup+0x68/0x1b0 [ 129.135932] process_one_work+0x294/0x760 [ 129.135944] worker_thread+0x54/0x408 [ 129.135951] kthread+0x178/0x190 [ 129.135963] ret_from_fork+0x10/0x20 Let's introduce a new function get_lane_id to retrieve lane_id instead of saving it in phy->id. Signed-off-by: Quanyang Wang <[email protected]> Signed-off-by: Bruce Ashfield <[email protected]> [Fix: change the file name from phy-fsl-s32gen1-serdes.c to phy-nxp-s32cc-serdes.c] Signed-off-by: Zhantao Tang <[email protected]> --- drivers/phy/freescale/phy-nxp-s32cc-serdes.c | 21 ++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/phy/freescale/phy-nxp-s32cc-serdes.c b/drivers/phy/freescale/phy-nxp-s32cc-serdes.c index e10665c6020d..4d06f19494d5 100644 --- a/drivers/phy/freescale/phy-nxp-s32cc-serdes.c +++ b/drivers/phy/freescale/phy-nxp-s32cc-serdes.c @@ -157,6 +157,19 @@ static int serdes_phy_reset(struct phy *p) return 0; } +static int get_lane_id(struct phy *phy) +{ + struct serdes *serdes = phy_get_drvdata(phy); + int i; + + for (i = 0; i < ARRAY_SIZE(serdes->phys); i++) + if (serdes->phys[i] == phy) + return i; + + WARN_ON(i == ARRAY_SIZE(serdes->phys)); + return 0; +} + static bool pcie_phy_is_locked(struct serdes *serdes) { u32 mplla = readl(serdes->ctrl.ss_base + PCIE_PHY_MPLLA_CTRL); @@ -603,8 +616,9 @@ struct s32cc_xpcs *s32cc_phy2xpcs(struct phy *phy) { struct serdes *serdes = phy_get_drvdata(phy); struct xpcs_ctrl *xpcs = &serdes->xpcs; + int lane_id = get_lane_id(phy); - return xpcs->phys[phy->id]; + return xpcs->phys[lane_id]; } EXPORT_SYMBOL_GPL(s32cc_phy2xpcs); @@ -613,9 +627,10 @@ static int xpcs_phy_configure(struct phy *phy, struct phylink_link_state *state) struct serdes *serdes = phy_get_drvdata(phy); struct xpcs_ctrl *xpcs = &serdes->xpcs; struct device *dev = serdes->dev; + int lane_id = get_lane_id(phy); int ret; - ret = xpcs->ops->config(xpcs->phys[phy->id], NULL); + ret = xpcs->ops->config(xpcs->phys[lane_id], NULL); if (ret) { dev_err(dev, "Failed to configure XPCS\n"); return ret; @@ -785,7 +800,6 @@ static struct phy *serdes_xlate(struct device *dev, return ERR_PTR(ret); phy = serdes->phys[lane_id]; - phy->id = lane_id; phy->attrs.mode = mode; return phy; @@ -1012,7 +1026,6 @@ static int serdes_probe(struct platform_device *pdev) if (IS_ERR(serdes->phys[i])) return PTR_ERR(serdes->phys[i]); phy_set_drvdata(serdes->phys[i], serdes); - serdes->phys[i]->id = i; } ret = ss_dt_init(pdev, serdes); -- 2.25.1
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#12320): https://lists.yoctoproject.org/g/linux-yocto/message/12320 Mute This Topic: https://lists.yoctoproject.org/mt/97898132/21656 Group Owner: [email protected] Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
