 net: phylink: add lock for serializing concurrent pl-&gt;phydev writes w… · gregkh/linux@0ba5b2f · 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 0ba5b2f Browse files Browse files vladimiroltean authored and kuba-moo committed net: phylink: add lock for serializing concurrent pl-&gt;phydev writes with resolver 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; 1 parent 03e79de commit 0ba5b2f Copy full SHA for 0ba5b2f 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 ; @@ -1591,8 +1593,11 @@ static void phylink_resolve(struct work_struct *w) 1591 1593 struct phylink_link_state link_state ; 1592 1594 bool mac_config = false; 1593 1595 bool retrigger = false; 1596 + struct phy_device * phy ; 1594 1597 bool cur_link_state ; 1595 1598 1599 + mutex_lock ( &amp; pl -&gt; phydev_mutex ); 1600 + phy = pl -&gt; phydev ; 1596 1601 mutex_lock ( &amp; pl -&gt; state_mutex ); 1597 1602 cur_link_state = phylink_link_is_up ( pl ); 1598 1603 @@ -1626,11 +1631,11 @@ static void phylink_resolve(struct work_struct *w) 1626 1631 /* If we have a phy, the &quot;up&quot; state is the union of both the 1627 1632 * PHY and the MAC 1628 1633 */ 1629 - if ( pl -&gt; phydev ) 1634 + if ( phy ) 1630 1635 link_state . link &amp;= pl -&gt; phy_state . link ; 1631 1636 1632 1637 /* Only update if the PHY link is up */ 1633 - if ( pl -&gt; phydev &amp;&amp; pl -&gt; phy_state . link ) { 1638 + if ( phy &amp;&amp; pl -&gt; phy_state . link ) { 1634 1639 /* If the interface has changed, force a link down 1635 1640 * event if the link isn&#39;t already down, and re-resolve. 1636 1641 */ @@ -1694,6 +1699,7 @@ static void phylink_resolve(struct work_struct *w) 1694 1699 queue_work ( system_power_efficient_wq , &amp; pl -&gt; resolve ); 1695 1700 } 1696 1701 mutex_unlock ( &amp; pl -&gt; state_mutex ); 1702 + mutex_unlock ( &amp; pl -&gt; phydev_mutex ); 1697 1703 } 1698 1704 1699 1705 static void phylink_run_resolve ( struct phylink * pl ) @@ -1829,6 +1835,7 @@ struct phylink *phylink_create(struct phylink_config *config, 1829 1835 if (! pl ) 1830 1836 return ERR_PTR ( - ENOMEM ); 1831 1837 1838 + mutex_init ( &amp; pl -&gt; phydev_mutex ); 1832 1839 mutex_init ( &amp; pl -&gt; state_mutex ); 1833 1840 INIT_WORK ( &amp; pl -&gt; resolve , phylink_resolve ); 1834 1841 @@ -2089,6 +2096,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, 2089 2096 dev_name ( &amp; phy -&gt; mdio . dev ), phy -&gt; drv -&gt; name , irq_str ); 2090 2097 kfree ( irq_str ); 2091 2098 2099 + mutex_lock ( &amp; pl -&gt; phydev_mutex ); 2092 2100 mutex_lock ( &amp; phy -&gt; lock ); 2093 2101 mutex_lock ( &amp; pl -&gt; state_mutex ); 2094 2102 pl -&gt; phydev = phy ; @@ -2134,6 +2142,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, 2134 2142 2135 2143 mutex_unlock ( &amp; pl -&gt; state_mutex ); 2136 2144 mutex_unlock ( &amp; phy -&gt; lock ); 2145 + mutex_unlock ( &amp; pl -&gt; phydev_mutex ); 2137 2146 2138 2147 phylink_dbg ( pl , 2139 2148 &quot;phy: %s setting supported %*pb advertising %*pb\n&quot; , @@ -2312,6 +2321,7 @@ void phylink_disconnect_phy(struct phylink *pl) 2312 2321 2313 2322 ASSERT_RTNL (); 2314 2323 2324 + mutex_lock ( &amp; pl -&gt; phydev_mutex ); 2315 2325 phy = pl -&gt; phydev ; 2316 2326 if ( phy ) { 2317 2327 mutex_lock ( &amp; phy -&gt; lock ); @@ -2321,8 +2331,11 @@ void phylink_disconnect_phy(struct phylink *pl) 2321 2331 pl -&gt; mac_tx_clk_stop = false; 2322 2332 mutex_unlock ( &amp; pl -&gt; state_mutex ); 2323 2333 mutex_unlock ( &amp; phy -&gt; lock ); 2324 - flush_work ( &amp; pl -&gt; resolve ); 2334 + } 2335 + mutex_unlock ( &amp; pl -&gt; phydev_mutex ); 2325 2336 2337 + if ( phy ) { 2338 + flush_work ( &amp; pl -&gt; resolve ); 2326 2339 phy_disconnect ( phy ); 2327 2340 } 2328 2341 } 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. 