net: fec: Fix division by zero
commit 7f7d6c282
(net: fec: Ensure that initialization is done prior to
request_irq()) placed fec_ptp_init() into a point that ptp clock was not
available, which causes a division by zero in fec_ptp_start_cyclecounter():
[ 17.895723] Division by zero in kernel.
[ 17.899571] Backtrace:
[ 17.902094] [<80012564>] (dump_backtrace+0x0/0x10c) from [<8056deec>]
(dump_stack+0x18/0x1c)
[ 17.910539] r6:bfba8500 r5:8075c950 r4:bfba8000 r3:bfbd0000
[ 17.916284] [<8056ded4>] (dump_stack+0x0/0x1c) from [<80012688>]
(__div0+0x18/0x20)
[ 17.923968] [<80012670>] (__div0+0x0/0x20) from [<802829c4>] (Ldiv0+0x8/0x10)
[ 17.931140] [<80398534>] (fec_ptp_start_cyclecounter+0x0/0x110) from
[<80394f64>] (fec_restart+0x6c8/0x754)
[ 17.940898] [<8039489c>] (fec_restart+0x0/0x754) from [<803969a0>]
(fec_enet_adjust_link+0xdc/0x108)
[ 17.950046] [<803968c4>] (fec_enet_adjust_link+0x0/0x108) from [<80390bc4>]
(phy_state_machine+0x178/0x534)
...
Fix this by rearraging the code so that fec_ptp_init() is called only after
the clocks have been properly acquired.
Tested on both mx53 and mx6 platforms.
Reported-by: Jim Baxter <jim_baxter@mentor.com>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2bb60cb9b7
commit
e2f8d555ec
|
@ -1782,8 +1782,49 @@ fec_probe(struct platform_device *pdev)
|
|||
fep->phy_interface = ret;
|
||||
}
|
||||
|
||||
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
|
||||
if (IS_ERR(pinctrl)) {
|
||||
ret = PTR_ERR(pinctrl);
|
||||
goto failed_pin;
|
||||
}
|
||||
|
||||
fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
|
||||
if (IS_ERR(fep->clk_ipg)) {
|
||||
ret = PTR_ERR(fep->clk_ipg);
|
||||
goto failed_clk;
|
||||
}
|
||||
|
||||
fep->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
|
||||
if (IS_ERR(fep->clk_ahb)) {
|
||||
ret = PTR_ERR(fep->clk_ahb);
|
||||
goto failed_clk;
|
||||
}
|
||||
|
||||
fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
|
||||
fep->bufdesc_ex =
|
||||
pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
|
||||
if (IS_ERR(fep->clk_ptp)) {
|
||||
ret = PTR_ERR(fep->clk_ptp);
|
||||
fep->bufdesc_ex = 0;
|
||||
}
|
||||
|
||||
clk_prepare_enable(fep->clk_ahb);
|
||||
clk_prepare_enable(fep->clk_ipg);
|
||||
if (!IS_ERR(fep->clk_ptp))
|
||||
clk_prepare_enable(fep->clk_ptp);
|
||||
|
||||
reg_phy = devm_regulator_get(&pdev->dev, "phy");
|
||||
if (!IS_ERR(reg_phy)) {
|
||||
ret = regulator_enable(reg_phy);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to enable phy regulator: %d\n", ret);
|
||||
goto failed_regulator;
|
||||
}
|
||||
}
|
||||
|
||||
fec_reset_phy(pdev);
|
||||
|
||||
if (fep->bufdesc_ex)
|
||||
fec_ptp_init(ndev, pdev);
|
||||
|
||||
|
@ -1809,47 +1850,6 @@ fec_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
|
||||
if (IS_ERR(pinctrl)) {
|
||||
ret = PTR_ERR(pinctrl);
|
||||
goto failed_pin;
|
||||
}
|
||||
|
||||
fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
|
||||
if (IS_ERR(fep->clk_ipg)) {
|
||||
ret = PTR_ERR(fep->clk_ipg);
|
||||
goto failed_clk;
|
||||
}
|
||||
|
||||
fep->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
|
||||
if (IS_ERR(fep->clk_ahb)) {
|
||||
ret = PTR_ERR(fep->clk_ahb);
|
||||
goto failed_clk;
|
||||
}
|
||||
|
||||
fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
|
||||
if (IS_ERR(fep->clk_ptp)) {
|
||||
ret = PTR_ERR(fep->clk_ptp);
|
||||
fep->bufdesc_ex = 0;
|
||||
}
|
||||
|
||||
clk_prepare_enable(fep->clk_ahb);
|
||||
clk_prepare_enable(fep->clk_ipg);
|
||||
if (!IS_ERR(fep->clk_ptp))
|
||||
clk_prepare_enable(fep->clk_ptp);
|
||||
|
||||
reg_phy = devm_regulator_get(&pdev->dev, "phy");
|
||||
if (!IS_ERR(reg_phy)) {
|
||||
ret = regulator_enable(reg_phy);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to enable phy regulator: %d\n", ret);
|
||||
goto failed_regulator;
|
||||
}
|
||||
}
|
||||
|
||||
fec_reset_phy(pdev);
|
||||
|
||||
ret = fec_enet_mii_init(pdev);
|
||||
if (ret)
|
||||
goto failed_mii_init;
|
||||
|
@ -1866,6 +1866,13 @@ fec_probe(struct platform_device *pdev)
|
|||
failed_register:
|
||||
fec_enet_mii_remove(fep);
|
||||
failed_mii_init:
|
||||
failed_init:
|
||||
for (i = 0; i < FEC_IRQ_NUM; i++) {
|
||||
irq = platform_get_irq(pdev, i);
|
||||
if (irq > 0)
|
||||
free_irq(irq, ndev);
|
||||
}
|
||||
failed_irq:
|
||||
failed_regulator:
|
||||
clk_disable_unprepare(fep->clk_ahb);
|
||||
clk_disable_unprepare(fep->clk_ipg);
|
||||
|
@ -1873,14 +1880,7 @@ failed_regulator:
|
|||
clk_disable_unprepare(fep->clk_ptp);
|
||||
failed_pin:
|
||||
failed_clk:
|
||||
for (i = 0; i < FEC_IRQ_NUM; i++) {
|
||||
irq = platform_get_irq(pdev, i);
|
||||
if (irq > 0)
|
||||
free_irq(irq, ndev);
|
||||
}
|
||||
failed_irq:
|
||||
iounmap(fep->hwp);
|
||||
failed_init:
|
||||
failed_ioremap:
|
||||
free_netdev(ndev);
|
||||
failed_alloc_etherdev:
|
||||
|
|
Loading…
Reference in a new issue