aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale
diff options
context:
space:
mode:
authorFabio Estevam <fabio.estevam@freescale.com>2013-02-22 01:40:45 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-22 15:10:19 -0500
commite2f8d555ec04a0beb965ea76e3a150993e8f0436 (patch)
treeac9a470badf6f6577e239353596709e2579c75ef /drivers/net/ethernet/freescale
parent2bb60cb9b7b997bdbc7fd6c8001dcca02a4ea2e1 (diff)
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>
Diffstat (limited to 'drivers/net/ethernet/freescale')
-rw-r--r--drivers/net/ethernet/freescale/fec.c68
1 files changed, 34 insertions, 34 deletions
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index 2dbb36c985c7..fccc3bf2141d 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -1782,33 +1782,6 @@ fec_probe(struct platform_device *pdev)
1782 fep->phy_interface = ret; 1782 fep->phy_interface = ret;
1783 } 1783 }
1784 1784
1785 fep->bufdesc_ex =
1786 pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
1787 if (fep->bufdesc_ex)
1788 fec_ptp_init(ndev, pdev);
1789
1790 ret = fec_enet_init(ndev);
1791 if (ret)
1792 goto failed_init;
1793
1794 for (i = 0; i < FEC_IRQ_NUM; i++) {
1795 irq = platform_get_irq(pdev, i);
1796 if (irq < 0) {
1797 if (i)
1798 break;
1799 ret = irq;
1800 goto failed_irq;
1801 }
1802 ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev);
1803 if (ret) {
1804 while (--i >= 0) {
1805 irq = platform_get_irq(pdev, i);
1806 free_irq(irq, ndev);
1807 }
1808 goto failed_irq;
1809 }
1810 }
1811
1812 pinctrl = devm_pinctrl_get_select_default(&pdev->dev); 1785 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
1813 if (IS_ERR(pinctrl)) { 1786 if (IS_ERR(pinctrl)) {
1814 ret = PTR_ERR(pinctrl); 1787 ret = PTR_ERR(pinctrl);
@@ -1828,6 +1801,8 @@ fec_probe(struct platform_device *pdev)
1828 } 1801 }
1829 1802
1830 fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp"); 1803 fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
1804 fep->bufdesc_ex =
1805 pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
1831 if (IS_ERR(fep->clk_ptp)) { 1806 if (IS_ERR(fep->clk_ptp)) {
1832 ret = PTR_ERR(fep->clk_ptp); 1807 ret = PTR_ERR(fep->clk_ptp);
1833 fep->bufdesc_ex = 0; 1808 fep->bufdesc_ex = 0;
@@ -1850,6 +1825,31 @@ fec_probe(struct platform_device *pdev)
1850 1825
1851 fec_reset_phy(pdev); 1826 fec_reset_phy(pdev);
1852 1827
1828 if (fep->bufdesc_ex)
1829 fec_ptp_init(ndev, pdev);
1830
1831 ret = fec_enet_init(ndev);
1832 if (ret)
1833 goto failed_init;
1834
1835 for (i = 0; i < FEC_IRQ_NUM; i++) {
1836 irq = platform_get_irq(pdev, i);
1837 if (irq < 0) {
1838 if (i)
1839 break;
1840 ret = irq;
1841 goto failed_irq;
1842 }
1843 ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev);
1844 if (ret) {
1845 while (--i >= 0) {
1846 irq = platform_get_irq(pdev, i);
1847 free_irq(irq, ndev);
1848 }
1849 goto failed_irq;
1850 }
1851 }
1852
1853 ret = fec_enet_mii_init(pdev); 1853 ret = fec_enet_mii_init(pdev);
1854 if (ret) 1854 if (ret)
1855 goto failed_mii_init; 1855 goto failed_mii_init;
@@ -1866,6 +1866,13 @@ fec_probe(struct platform_device *pdev)
1866failed_register: 1866failed_register:
1867 fec_enet_mii_remove(fep); 1867 fec_enet_mii_remove(fep);
1868failed_mii_init: 1868failed_mii_init:
1869failed_init:
1870 for (i = 0; i < FEC_IRQ_NUM; i++) {
1871 irq = platform_get_irq(pdev, i);
1872 if (irq > 0)
1873 free_irq(irq, ndev);
1874 }
1875failed_irq:
1869failed_regulator: 1876failed_regulator:
1870 clk_disable_unprepare(fep->clk_ahb); 1877 clk_disable_unprepare(fep->clk_ahb);
1871 clk_disable_unprepare(fep->clk_ipg); 1878 clk_disable_unprepare(fep->clk_ipg);
@@ -1873,14 +1880,7 @@ failed_regulator:
1873 clk_disable_unprepare(fep->clk_ptp); 1880 clk_disable_unprepare(fep->clk_ptp);
1874failed_pin: 1881failed_pin:
1875failed_clk: 1882failed_clk:
1876 for (i = 0; i < FEC_IRQ_NUM; i++) {
1877 irq = platform_get_irq(pdev, i);
1878 if (irq > 0)
1879 free_irq(irq, ndev);
1880 }
1881failed_irq:
1882 iounmap(fep->hwp); 1883 iounmap(fep->hwp);
1883failed_init:
1884failed_ioremap: 1884failed_ioremap:
1885 free_netdev(ndev); 1885 free_netdev(ndev);
1886failed_alloc_etherdev: 1886failed_alloc_etherdev: