[PATCH net-next v3 3/3] net: stmmac: hold runtime PM reference in setup_tc
Lorenzo Bianconi <[email protected]>
| Newsgroups | org.kernel.vger.netdev,org.infradead.lists.linux-arm-kernel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- 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