 net: phylink: add lock for serializing concurrent pl-&gt;phydev writes w… · gregkh/linux@56fe63b · GitHub Skip to content Navigation Menu Toggle navigation Sign in Appearance settings Platform AI CODE CREATION GitHub Copilot Write better code with AI GitHub Spark Build and deploy intelligent apps GitHub Models Manage and compare prompts MCP Registry New Integrate external tools DEVELOPER WORKFLOWS Actions Automate any workflow Codespaces Instant dev environments Issues Plan and track work Code Review Manage code changes APPLICATION SECURITY GitHub Advanced Security Find and fix vulnerabilities Code security Secure your code as you build Secret protection  EXPLORE Why GitHub Documentation Blog Changelog Marketplace View all features Solutions BY COMPANY SIZE Enterprises Small and medium teams Startups Nonprofits BY USE CASE App Modernization DevSecOps DevOps CI/CD View all use cases BY INDUSTRY Healthcare Financial services Manufacturing Government View all industries View all solutions Resources EXPLORE BY TOPIC AI Software Development DevOps Security View all topics EXPLORE BY TYPE Customer stories Events &amp; webinars Ebooks &amp; reports Business insights GitHub Skills SUPPORT &amp; SERVICES Documentation Customer support Community forum Trust center Partners View all resources Open Source COMMUNITY GitHub Sponsors Fund open source developers PROGRAMS Security Lab Maintainer Community Accelerator GitHub Stars Archive Program REPOSITORIES Topics Trending Collections Enterprise ENTERPRISE SOLUTIONS Enterprise platform AI-powered developer platform AVAILABLE ADD-ONS GitHub Advanced Security Enterprise-grade security features Copilot for Business Enterprise-grade AI features Premium Support Enterprise-grade 24/7 support Pricing Search or jump to... Search code, repositories, users, issues, pull requests... --> Search Clear Search syntax tips Provide feedback --> We read every piece of feedback, and take your input very seriously.  Cancel Submit feedback Saved searches Use saved searches to filter your results more quickly --> Name Query To see all available qualifiers, see our documentation . Cancel Create saved search Sign in Sign up Appearance settings Resetting focus You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. Dismiss alert {{ message }} gregkh / linux Public Notifications You must be signed in to change notification settings Fork 676 Star 636 Code Actions Security and quality 0 Insights Additional navigation options Code Actions Security and quality Insights Commit 56fe63b Browse files Browse files vladimiroltean authored and gregkh committed net: phylink: add lock for serializing concurrent pl-&gt;phydev writes with resolver [ Upstream commit 0ba5b2f ] Currently phylink_resolve() protects itself against concurrent phylink_bringup_phy() or phylink_disconnect_phy() calls which modify pl-&gt;phydev by relying on pl-&gt;state_mutex. The problem is that in phylink_resolve(), pl-&gt;state_mutex is in a lock inversion state with pl-&gt;phydev-&gt;lock. So pl-&gt;phydev-&gt;lock needs to be acquired prior to pl-&gt;state_mutex. But that requires dereferencing pl-&gt;phydev in the first place, and without pl-&gt;state_mutex, that is racy. Hence the reason for the extra lock. Currently it is redundant, but it will serve a functional purpose once mutex_lock(&amp;phy-&gt;lock) will be moved outside of the mutex_lock(&amp;pl-&gt;state_mutex) section. Another alternative considered would have been to let phylink_resolve() acquire the rtnl_mutex, which is also held when phylink_bringup_phy() and phylink_disconnect_phy() are called. But since phylink_disconnect_phy() runs under rtnl_lock(), it would deadlock with phylink_resolve() when calling flush_work(&amp;pl-&gt;resolve). Additionally, it would have been undesirable because it would have unnecessarily blocked many other call paths as well in the entire kernel, so the smaller-scoped lock was preferred. Link: https://lore.kernel.org/netdev/aLb6puGVzR29GpPx@shell.armlinux.org.uk/ Signed-off-by: Vladimir Oltean &lt;vladimir.oltean@nxp.com&gt; Reviewed-by: Russell King (Oracle) &lt;rmk+kernel@armlinux.org.uk&gt; Link: https://patch.msgid.link/20250904125238.193990-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt; Stable-dep-of: e2a10da ("net: phy: transfer phy_config_inband() locking responsibility to phylink") Signed-off-by: Sasha Levin &lt;sashal@kernel.org&gt; 1 parent eb148d8 commit 56fe63b Copy full SHA for 56fe63b 1 file changed + 16 - 3 Lines changed: 16 additions &amp; 3 deletions File tree Expand file tree Collapse file tree Open diff view settings Filter options drivers/net/phy phylink.c Expand file tree Collapse file tree Open diff view settings Collapse file ‎ drivers/net/phy/phylink.c ‎ Copy file name to clipboard Expand all lines: drivers/net/phy/phylink.c + 16 - 3 Lines changed: 16 additions &amp; 3 deletions Original file line number Diff line number Diff line change @@ -67,6 +67,8 @@ struct phylink { 67 67 struct timer_list link_poll ; 68 68 69 69 struct mutex state_mutex ; 70 + /* Serialize updates to pl-&gt;phydev with phylink_resolve() */ 71 + struct mutex phydev_mutex ; 70 72 struct phylink_link_state phy_state ; 71 73 unsigned int phy_ib_mode ; 72 74 struct work_struct resolve ; @@ -1568,8 +1570,11 @@ static void phylink_resolve(struct work_struct *w) 1568 1570 struct phylink_link_state link_state ; 1569 1571 bool mac_config = false; 1570 1572 bool retrigger = false; 1573 + struct phy_device * phy ; 1571 1574 bool cur_link_state ; 1572 1575 1576 + mutex_lock ( &amp; pl -&gt; phydev_mutex ); 1577 + phy = pl -&gt; phydev ; 1573 1578 mutex_lock ( &amp; pl -&gt; state_mutex ); 1574 1579 cur_link_state = phylink_link_is_up ( pl ); 1575 1580 @@ -1603,11 +1608,11 @@ static void phylink_resolve(struct work_struct *w) 1603 1608 /* If we have a phy, the &quot;up&quot; state is the union of both the 1604 1609 * PHY and the MAC 1605 1610 */ 1606 - if ( pl -&gt; phydev ) 1611 + if ( phy ) 1607 1612 link_state . link &amp;= pl -&gt; phy_state . link ; 1608 1613 1609 1614 /* Only update if the PHY link is up */ 1610 - if ( pl -&gt; phydev &amp;&amp; pl -&gt; phy_state . link ) { 1615 + if ( phy &amp;&amp; pl -&gt; phy_state . link ) { 1611 1616 /* If the interface has changed, force a link down 1612 1617 * event if the link isn&#39;t already down, and re-resolve. 1613 1618 */ @@ -1671,6 +1676,7 @@ static void phylink_resolve(struct work_struct *w) 1671 1676 queue_work ( system_power_efficient_wq , &amp; pl -&gt; resolve ); 1672 1677 } 1673 1678 mutex_unlock ( &amp; pl -&gt; state_mutex ); 1679 + mutex_unlock ( &amp; pl -&gt; phydev_mutex ); 1674 1680 } 1675 1681 1676 1682 static void phylink_run_resolve ( struct phylink * pl ) @@ -1806,6 +1812,7 @@ struct phylink *phylink_create(struct phylink_config *config, 1806 1812 if (! pl ) 1807 1813 return ERR_PTR ( - ENOMEM ); 1808 1814 1815 + mutex_init ( &amp; pl -&gt; phydev_mutex ); 1809 1816 mutex_init ( &amp; pl -&gt; state_mutex ); 1810 1817 INIT_WORK ( &amp; pl -&gt; resolve , phylink_resolve ); 1811 1818 @@ -2066,6 +2073,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, 2066 2073 dev_name ( &amp; phy -&gt; mdio . dev ), phy -&gt; drv -&gt; name , irq_str ); 2067 2074 kfree ( irq_str ); 2068 2075 2076 + mutex_lock ( &amp; pl -&gt; phydev_mutex ); 2069 2077 mutex_lock ( &amp; phy -&gt; lock ); 2070 2078 mutex_lock ( &amp; pl -&gt; state_mutex ); 2071 2079 pl -&gt; phydev = phy ; @@ -2111,6 +2119,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, 2111 2119 2112 2120 mutex_unlock ( &amp; pl -&gt; state_mutex ); 2113 2121 mutex_unlock ( &amp; phy -&gt; lock ); 2122 + mutex_unlock ( &amp; pl -&gt; phydev_mutex ); 2114 2123 2115 2124 phylink_dbg ( pl , 2116 2125 &quot;phy: %s setting supported %*pb advertising %*pb\n&quot; , @@ -2289,6 +2298,7 @@ void phylink_disconnect_phy(struct phylink *pl) 2289 2298 2290 2299 ASSERT_RTNL (); 2291 2300 2301 + mutex_lock ( &amp; pl -&gt; phydev_mutex ); 2292 2302 phy = pl -&gt; phydev ; 2293 2303 if ( phy ) { 2294 2304 mutex_lock ( &amp; phy -&gt; lock ); @@ -2298,8 +2308,11 @@ void phylink_disconnect_phy(struct phylink *pl) 2298 2308 pl -&gt; mac_tx_clk_stop = false; 2299 2309 mutex_unlock ( &amp; pl -&gt; state_mutex ); 2300 2310 mutex_unlock ( &amp; phy -&gt; lock ); 2301 - flush_work ( &amp; pl -&gt; resolve ); 2311 + } 2312 + mutex_unlock ( &amp; pl -&gt; phydev_mutex ); 2302 2313 2314 + if ( phy ) { 2315 + flush_work ( &amp; pl -&gt; resolve ); 2303 2316 phy_disconnect ( phy ); 2304 2317 } 2305 2318 } 0 commit comments Comments 0 ( 0 ) Footer &copy; 2026 GitHub,&nbsp;Inc. Footer navigation Terms Privacy Security Status Community Docs Contact Manage cookies Do not share my personal information You can’t perform that action at this time. 