net: fec: ptp: avoid register access when ipg clock is disabled
The current kernel hang on i.MX6SX with rootfs mount from MMC. The root cause is that ptp uses a periodic timer to access enet register even if ipg clock is disabled. FEC ptp driver start one period timer to read 1588 counter register in the ptp init function that is called after FEC driver is probed. To save power, after FEC probe finish, FEC driver disable all clocks including ipg clock that is needed for register access. i.MX5x, i.MX6q/dl/sl FEC register access don't cause system hang when ipg clock is disabled, just return zero value. But for i.MX6sx SOC, it cause system hang. To avoid the issue, we need to check ptp clock status before ptp timer count access. Signed-off-by: Fugang Duan <B38611@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
08f1a1b9d1
commit
91c0d987a9
@@ -1611,17 +1611,27 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
|
||||
goto failed_clk_enet_out;
|
||||
}
|
||||
if (fep->clk_ptp) {
|
||||
mutex_lock(&fep->ptp_clk_mutex);
|
||||
ret = clk_prepare_enable(fep->clk_ptp);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
mutex_unlock(&fep->ptp_clk_mutex);
|
||||
goto failed_clk_ptp;
|
||||
} else {
|
||||
fep->ptp_clk_on = true;
|
||||
}
|
||||
mutex_unlock(&fep->ptp_clk_mutex);
|
||||
}
|
||||
} else {
|
||||
clk_disable_unprepare(fep->clk_ahb);
|
||||
clk_disable_unprepare(fep->clk_ipg);
|
||||
if (fep->clk_enet_out)
|
||||
clk_disable_unprepare(fep->clk_enet_out);
|
||||
if (fep->clk_ptp)
|
||||
if (fep->clk_ptp) {
|
||||
mutex_lock(&fep->ptp_clk_mutex);
|
||||
clk_disable_unprepare(fep->clk_ptp);
|
||||
fep->ptp_clk_on = false;
|
||||
mutex_unlock(&fep->ptp_clk_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2625,6 +2635,8 @@ fec_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(fep->clk_enet_out))
|
||||
fep->clk_enet_out = NULL;
|
||||
|
||||
fep->ptp_clk_on = false;
|
||||
mutex_init(&fep->ptp_clk_mutex);
|
||||
fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
|
||||
fep->bufdesc_ex =
|
||||
pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
|
||||
@@ -2715,10 +2727,10 @@ fec_drv_remove(struct platform_device *pdev)
|
||||
struct net_device *ndev = platform_get_drvdata(pdev);
|
||||
struct fec_enet_private *fep = netdev_priv(ndev);
|
||||
|
||||
cancel_delayed_work_sync(&fep->time_keep);
|
||||
cancel_work_sync(&fep->tx_timeout_work);
|
||||
unregister_netdev(ndev);
|
||||
fec_enet_mii_remove(fep);
|
||||
del_timer_sync(&fep->time_keep);
|
||||
if (fep->reg_phy)
|
||||
regulator_disable(fep->reg_phy);
|
||||
if (fep->ptp_clock)
|
||||
|
Reference in New Issue
Block a user