On 06/15/2016 04:55 AM, Grygorii Strashko wrote: > The CPSW might be suspended by RPM if all ethX interfaces are down, > but it still could be accesible through ethtool interfce. In this case > ethtool operations, requiring registers access, will cause L3 errors and > CPSW crash. > > Hence, fix it by adding RPM get/put calls in ethtool callbcaks which > can access CPSW registers: .set_coalesce(), .get_ethtool_stats(), > .set_pauseparam(), .get_regs() Provided that you implement an ethtool_ops::begin, it will be called before each ethtool operation runs, so that could allow you to eliminate some of the duplication here. Conversely ethtool_ops::end terminates each operation and can be used for that purpose. > > Signed-off-by: Grygorii Strashko <grygorii.strashko@xxxxxx> > --- > drivers/net/ethernet/ti/cpsw.c | 36 +++++++++++++++++++++++++++++++++++- > 1 file changed, 35 insertions(+), 1 deletion(-) > > diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c > index ba81d4e..1ba0c09 100644 > --- a/drivers/net/ethernet/ti/cpsw.c > +++ b/drivers/net/ethernet/ti/cpsw.c > @@ -931,6 +931,13 @@ static int cpsw_set_coalesce(struct net_device *ndev, > u32 prescale = 0; > u32 addnl_dvdr = 1; > u32 coal_intvl = 0; > + int ret; > + > + ret = pm_runtime_get_sync(&priv->pdev->dev); > + if (ret < 0) { > + pm_runtime_put_noidle(&priv->pdev->dev); > + return ret; > + } > > coal_intvl = coal->rx_coalesce_usecs; > > @@ -985,6 +992,8 @@ update_return: > priv->coal_intvl = coal_intvl; > } > > + pm_runtime_put(&priv->pdev->dev); > + > return 0; > } > > @@ -1022,7 +1031,13 @@ static void cpsw_get_ethtool_stats(struct net_device *ndev, > struct cpdma_chan_stats tx_stats; > u32 val; > u8 *p; > - int i; > + int i, ret; > + > + ret = pm_runtime_get_sync(&priv->pdev->dev); > + if (ret < 0) { > + pm_runtime_put_noidle(&priv->pdev->dev); > + return; > + } > > /* Collect Davinci CPDMA stats for Rx and Tx Channel */ > cpdma_chan_get_stats(priv->rxch, &rx_stats); > @@ -1049,6 +1064,8 @@ static void cpsw_get_ethtool_stats(struct net_device *ndev, > break; > } > } > + > + pm_runtime_put(&priv->pdev->dev); > } > > static int cpsw_common_res_usage_state(struct cpsw_priv *priv) > @@ -1780,11 +1797,20 @@ static void cpsw_get_regs(struct net_device *ndev, > { > struct cpsw_priv *priv = netdev_priv(ndev); > u32 *reg = p; > + int ret; > + > + ret = pm_runtime_get_sync(&priv->pdev->dev); > + if (ret < 0) { > + pm_runtime_put_noidle(&priv->pdev->dev); > + return; > + } > > /* update CPSW IP version */ > regs->version = priv->version; > > cpsw_ale_dump(priv->ale, reg); > + > + pm_runtime_put(&priv->pdev->dev); > } > > static void cpsw_get_drvinfo(struct net_device *ndev, > @@ -1902,12 +1928,20 @@ static int cpsw_set_pauseparam(struct net_device *ndev, > { > struct cpsw_priv *priv = netdev_priv(ndev); > bool link; > + int ret; > + > + ret = pm_runtime_get_sync(&priv->pdev->dev); > + if (ret < 0) { > + pm_runtime_put_noidle(&priv->pdev->dev); > + return ret; > + } > > priv->rx_pause = pause->rx_pause ? true : false; > priv->tx_pause = pause->tx_pause ? true : false; > > for_each_slave(priv, _cpsw_adjust_link, priv, &link); > > + pm_runtime_put(&priv->pdev->dev); > return 0; > } > > -- Florian -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html