Hello, On Mon, Aug 03, 2015 at 03:50:23PM +0200, Andrew Lunn wrote: > > The problem is that on i.MX27 there are two clocks involved that both > > must be on to send a packet, while on i.MX6 it's only a single one > > (abstracted by having ipg-clock = ahb-clock). With the suggested patch > > only a single one is asserted to be on. This is enough for i.MX6 but > > it's not for i.MX27 (and from looking at the device trees also i.MX25, > > i.MX28, and i.MX35 are affected). > > I don't think it is as simple as this. If you are sending a packet, > fec_enet_open() must of been called. This does a pm_runtime_get_sync() > to ensure the ipg-clock is ticking, and fec_enet_clk_enable() to > enable all other clocks. > > Can you debug this further to find out which clock is off, and where > it gets turned off? I added a call to pm_runtime_get_sync to fec_enet_start_xmit and put it back at its end. This way I was able to boot with NFS-root which resulted in an oops before. But this is wrong because if I set FEC_MDIO_PM_TIMEOUT to 0 I get an oops anyhow.
I added the following patch: diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 32e3807c650e..508c4af4fde8 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -64,6 +64,30 @@ #include "fec.h" +#define fec_pm_runtime_get_sync(_dev) ({ \ + dev_info((_dev), "%s: get_sync (%d)", __func__, (_dev)->power.usage_count.counter); \ + pm_runtime_get_sync((_dev)); \ +}) +#define pm_runtime_get_sync(_dev) fec_pm_runtime_get_sync(_dev) + +#define fec_pm_runtime_put_autosuspend(_dev) ({ \ + dev_info((_dev), "%s: put_autosuspend (%d)", __func__, (_dev)->power.usage_count.counter); \ + pm_runtime_put_autosuspend((_dev)); \ +}) +#define pm_runtime_put_autosuspend(_dev) fec_pm_runtime_put_autosuspend(_dev) + +#define fec_clk_prepare_enable(_clk) ({ \ + pr_info("%s: enable " #_clk "\n", __func__); \ + clk_prepare_enable((_clk)); \ +}) +#define clk_prepare_enable(_clk) fec_clk_prepare_enable(_clk) + +#define fec_clk_disable_unprepare(_clk) ({ \ + pr_info("%s: disable " #_clk "\n", __func__); \ + clk_disable_unprepare((_clk)); \ +}) +#define clk_disable_unprepare(_clk) fec_clk_disable_unprepare(_clk) + static void set_multicast_list(struct net_device *ndev); static void fec_enet_itr_coal_init(struct net_device *ndev); @@ -784,6 +808,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct netdev_queue *nq; int ret; + pr_info("%s\n", __func__); queue = skb_get_queue_mapping(skb); txq = fep->tx_queue[queue]; nq = netdev_get_tx_queue(ndev, queue); @@ -2864,6 +2889,7 @@ fec_enet_open(struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); int ret; + pr_info("%s\n", __func__); ret = pm_runtime_get_sync(&fep->pdev->dev); if (IS_ERR_VALUE(ret)) return ret; @@ -2932,6 +2958,8 @@ fec_enet_close(struct net_device *ndev) fec_enet_free_buffers(ndev); + pr_info("%s\n", __func__); + return 0; } @@ -3416,6 +3444,7 @@ fec_probe(struct platform_device *pdev) goto failed_clk; ret = clk_prepare_enable(fep->clk_ipg); + clk_prepare_enable(fep->clk_ipg); if (ret) goto failed_clk_ipg; Which produced the following output (piped through nl for better reference): 1 fec_enet_open 2 fec 1002b000.ethernet: fec_enet_open: get_sync (-1) 3 fec_runtime_resume: enable fep->clk_ipg 4 fec_enet_clk_enable: enable fep->clk_ahb 5 fec 1002b000.ethernet: fec_enet_mdio_write: get_sync (0) 6 fec 1002b000.ethernet: fec_enet_mdio_write: put_autosuspend (1) 7 mmc0: new SD card at address 0007 8 mmcblk0: mmc0:0007 SD01G 972 MiB (ro) 9 mmcblk0: p1 10 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 11 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 12 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 13 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 14 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 15 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 16 fec 1002b000.ethernet: fec_enet_mdio_write: get_sync (0) 17 fec 1002b000.ethernet: fec_enet_mdio_write: put_autosuspend (1) 18 fec 1002b000.ethernet eth0: Freescale FEC PHY driver [Generic PHY] (mii_bus:phy_addr=1002b000.etherne:00, irq=-1) 19 fec_runtime_suspend: disable fep->clk_ipg 20 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 21 fec_runtime_resume: enable fep->clk_ipg 22 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 23 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 24 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 25 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 26 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 27 fec_runtime_suspend: disable fep->clk_ipg 28 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 29 fec_runtime_resume: enable fep->clk_ipg 30 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 31 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 32 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 33 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 34 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 35 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 36 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 37 fec_runtime_suspend: disable fep->clk_ipg 38 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 39 fec_runtime_resume: enable fep->clk_ipg 40 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 41 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 42 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 43 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 44 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 45 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 46 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 47 fec 1002b000.ethernet: fec_enet_mdio_read: get_sync (0) 48 fec 1002b000.ethernet: fec_enet_mdio_read: put_autosuspend (1) 49 fec 1002b000.ethernet eth0: Link is Up - 100Mbps/Full - flow control off 50 Sending DHCP requests . 51 fec_enet_start_xmit 52 , 53 fec_enet_start_xmit 54 OK 55 IP-Config: Got DHCP answer from 192.168.23.4, my address is 192.168.24.64 56 IP-Config: Complete: 57 device=eth0, hwaddr=4a:5c:f5:cb:22:15, ipaddr=192.168.24.64, mask=255.255.0.0, gw=192.168.23.254 58 host=192.168.24.64, domain=lab.pengutronix.de, nis-domain=(none) 59 fec_runtime_suspend: disable fep->clk_ipg 60 bootserver=192.168.23.4, rootserver=192.168.23.4, rootpath= 61 nameserver0=192.168.23.254 62 fec_enet_start_xmit You see, fec_runtime_suspend is called even though _open was called. (And even though get_sync was called once more than put_autosuspend). Without the additional clk_prepare_enable in probe line 62 is where the machine barfs. I don't understand it starring at the code for a while. But the -1 in line 2 looks fishy. > > As I think it would be bold to fix this commit once more for 4.2, I > > suggest to revert 8fff755e9f8d0f70a595e79f248695ce6aef5cc3. > > (To be honest I wonder why v5 of this commit was even taken for -rc3.) > > > > The straight forward fix for the MDIO issue that was intended to be > > addressed by 8fff755e9f8d is to add clk_prepare_enable and matching > > _unprepare_disable calls to the mdio callbacks, right? > > You mean v1 of the patch? > > https://patchwork.ozlabs.org/patch/483668/ > > Or at least something similar. That idea got NACK because it is > thought to consume too much power. I didn't follow the discussion. But yes, that's what I'd do. I'm with Florian here. Best regards Uwe -- Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | http://www.pengutronix.de/ | -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html