[PATCH net-next v3 3/3] net: stmmac: hold runtime PM reference in setup_tc

Lorenzo Bianconi lorenzo.bianconi at oss.qualcomm.com
Sat Aug 8 07:49:59 PDT 2026


The qdisc offload callbacks invoked by stmmac_setup_tc() program
MTL/MAC registers, but they can be reached while the interface is down,
when stmmac_release() has dropped the runtime PM usage counter and the
device may be suspended with its clocks gated. Accessing the registers
in that state can trigger a bus error.

Hold a runtime PM reference for the whole setup_tc() call so the device
is active, and its clocks enabled, whenever a qdisc offload is
configured or torn down. This covers all qdisc offloads, including the
pre-existing CBS/TAPRIO paths that had the same issue.

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at oss.qualcomm.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 39 ++++++++++++++++-------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index e19f75d8c393..5aee03ebe131 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -6443,28 +6443,45 @@ static int stmmac_setup_tc(struct net_device *ndev, enum tc_setup_type type,
 			   void *type_data)
 {
 	struct stmmac_priv *priv = netdev_priv(ndev);
+	int ret;
+
+	ret = pm_runtime_resume_and_get(priv->device);
+	if (ret < 0)
+		return ret;
 
 	switch (type) {
 	case TC_QUERY_CAPS:
-		return stmmac_tc_query_caps(priv, priv, type_data);
+		ret = stmmac_tc_query_caps(priv, priv, type_data);
+		break;
 	case TC_SETUP_QDISC_MQPRIO:
-		return stmmac_tc_setup_mqprio(priv, priv, type_data);
+		ret = stmmac_tc_setup_mqprio(priv, priv, type_data);
+		break;
 	case TC_SETUP_BLOCK:
-		return flow_block_cb_setup_simple(type_data,
-						  &stmmac_block_cb_list,
-						  stmmac_setup_tc_block_cb,
-						  priv, priv, true);
+		ret = flow_block_cb_setup_simple(type_data,
+						 &stmmac_block_cb_list,
+						 stmmac_setup_tc_block_cb,
+						 priv, priv, true);
+		break;
 	case TC_SETUP_QDISC_CBS:
-		return stmmac_tc_setup_cbs(priv, priv, type_data);
+		ret = stmmac_tc_setup_cbs(priv, priv, type_data);
+		break;
 	case TC_SETUP_QDISC_TAPRIO:
-		return stmmac_tc_setup_taprio(priv, priv, type_data);
+		ret = stmmac_tc_setup_taprio(priv, priv, type_data);
+		break;
 	case TC_SETUP_QDISC_ETF:
-		return stmmac_tc_setup_etf(priv, priv, type_data);
+		ret = stmmac_tc_setup_etf(priv, priv, type_data);
+		break;
 	case TC_SETUP_QDISC_ETS:
-		return stmmac_tc_setup_ets(priv, priv, type_data);
+		ret = stmmac_tc_setup_ets(priv, priv, type_data);
+		break;
 	default:
-		return -EOPNOTSUPP;
+		ret = -EOPNOTSUPP;
+		break;
 	}
+
+	pm_runtime_put(priv->device);
+
+	return ret;
 }
 
 static u16 stmmac_select_queue(struct net_device *dev, struct sk_buff *skb,

-- 
2.55.0




More information about the linux-arm-kernel mailing list