aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorFabio Estevam <fabio.estevam@freescale.com>2013-02-21 04:21:50 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-21 15:37:49 -0500
commit7f7d6c282e9d9b1721fdcdeac71383b7b0b60700 (patch)
treec0e78760d7ba9c788a16cc687ae0aa3dd454e64c /drivers/net
parentb531ed61a2a2a77eeb2f7c88b49aa5ec7d9880d8 (diff)
net: fec: Ensure that initialization is done prior to request_irq()
Currently request_irq() is called prior to fec_enet_init() and fec_ptp_init(), which causes the following crash on a mx53qsb: Unable to handle kernel NULL pointer dereference at virtual address 00000002 pgd = 80004000 [00000002] *pgd=00000000 Internal error: Oops: 5 [#1] SMP ARM Modules linked in: CPU: 0 Not tainted (3.8.0-rc7-next-20130215+ #346) PC is at fec_enet_interrupt+0xd0/0x348 LR is at fec_enet_interrupt+0xb8/0x348 pc : [<80372b7c>] lr : [<80372b64>] psr: 60000193 sp : df855c20 ip : df855c20 fp : df855c74 r10: 00000516 r9 : 1c000000 r8 : 00000000 r7 : 00000000 r6 : 00000000 r5 : 00000000 r4 : df9b7800 r3 : df9b7df4 r2 : 00000000 r1 : 00000000 r0 : df9b7d34 Ensure that such initialization functions are called prior to requesting the interrupts, so that all necessary the data structures are in place when the irqs occur. Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/freescale/fec.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index 29d82cf1528e..2dbb36c985c7 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -1782,6 +1782,15 @@ 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
1785 for (i = 0; i < FEC_IRQ_NUM; i++) { 1794 for (i = 0; i < FEC_IRQ_NUM; i++) {
1786 irq = platform_get_irq(pdev, i); 1795 irq = platform_get_irq(pdev, i);
1787 if (irq < 0) { 1796 if (irq < 0) {
@@ -1819,8 +1828,6 @@ fec_probe(struct platform_device *pdev)
1819 } 1828 }
1820 1829
1821 fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp"); 1830 fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
1822 fep->bufdesc_ex =
1823 pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
1824 if (IS_ERR(fep->clk_ptp)) { 1831 if (IS_ERR(fep->clk_ptp)) {
1825 ret = PTR_ERR(fep->clk_ptp); 1832 ret = PTR_ERR(fep->clk_ptp);
1826 fep->bufdesc_ex = 0; 1833 fep->bufdesc_ex = 0;
@@ -1843,13 +1850,6 @@ fec_probe(struct platform_device *pdev)
1843 1850
1844 fec_reset_phy(pdev); 1851 fec_reset_phy(pdev);
1845 1852
1846 if (fep->bufdesc_ex)
1847 fec_ptp_init(ndev, pdev);
1848
1849 ret = fec_enet_init(ndev);
1850 if (ret)
1851 goto failed_init;
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,7 +1866,6 @@ 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:
1870failed_regulator: 1869failed_regulator:
1871 clk_disable_unprepare(fep->clk_ahb); 1870 clk_disable_unprepare(fep->clk_ahb);
1872 clk_disable_unprepare(fep->clk_ipg); 1871 clk_disable_unprepare(fep->clk_ipg);
@@ -1881,6 +1880,7 @@ failed_clk:
1881 } 1880 }
1882failed_irq: 1881failed_irq:
1883 iounmap(fep->hwp); 1882 iounmap(fep->hwp);
1883failed_init:
1884failed_ioremap: 1884failed_ioremap:
1885 free_netdev(ndev); 1885 free_netdev(ndev);
1886failed_alloc_etherdev: 1886failed_alloc_etherdev:
@@ -1899,17 +1899,17 @@ fec_drv_remove(struct platform_device *pdev)
1899 1899
1900 unregister_netdev(ndev); 1900 unregister_netdev(ndev);
1901 fec_enet_mii_remove(fep); 1901 fec_enet_mii_remove(fep);
1902 for (i = 0; i < FEC_IRQ_NUM; i++) {
1903 int irq = platform_get_irq(pdev, i);
1904 if (irq > 0)
1905 free_irq(irq, ndev);
1906 }
1907 del_timer_sync(&fep->time_keep); 1902 del_timer_sync(&fep->time_keep);
1908 clk_disable_unprepare(fep->clk_ptp); 1903 clk_disable_unprepare(fep->clk_ptp);
1909 if (fep->ptp_clock) 1904 if (fep->ptp_clock)
1910 ptp_clock_unregister(fep->ptp_clock); 1905 ptp_clock_unregister(fep->ptp_clock);
1911 clk_disable_unprepare(fep->clk_ahb); 1906 clk_disable_unprepare(fep->clk_ahb);
1912 clk_disable_unprepare(fep->clk_ipg); 1907 clk_disable_unprepare(fep->clk_ipg);
1908 for (i = 0; i < FEC_IRQ_NUM; i++) {
1909 int irq = platform_get_irq(pdev, i);
1910 if (irq > 0)
1911 free_irq(irq, ndev);
1912 }
1913 iounmap(fep->hwp); 1913 iounmap(fep->hwp);
1914 free_netdev(ndev); 1914 free_netdev(ndev);
1915 1915