• Lukas Wunner's avatar
    usbnet: smsc95xx: Forward PHY interrupts to PHY driver to avoid polling · 1ce8b372
    Lukas Wunner authored
    Link status of SMSC LAN95xx chips is polled once per second, even though
    they're capable of signaling PHY interrupts through the MAC layer.
    
    Forward those interrupts to the PHY driver to avoid polling.  Benefits
    are reduced bus traffic, reduced CPU overhead and quicker interface
    bringup.
    
    Polling was introduced in 2016 by commit d69d1694 ("usbnet:
    smsc95xx: fix link detection for disabled autonegotiation").
    Back then, the LAN95xx driver neglected to enable the ENERGYON interrupt,
    hence couldn't detect link-up events when auto-negotiation was disabled.
    The proper solution would have been to enable the ENERGYON interrupt
    instead of polling.
    
    Since then, PHY handling was moved from the LAN95xx driver to the SMSC
    PHY driver with commit 05b35e7e ("smsc95xx: add phylib support").
    That PHY driver is capable of link detection with auto-negotiation
    disabled because it enables the ENERGYON interrupt.
    
    Note that signaling interrupts through the MAC layer not only works with
    the integrated PHY, but also with an external PHY, provided its
    interrupt pin is attached to LAN95xx's nPHY_INT pin.
    
    In the unlikely event that the interrupt pin of an external PHY is
    attached to a GPIO of the SoC (or not connected at all), the driver can
    be amended to retrieve the irq from the PHY's of_node.
    
    To forward PHY interrupts to phylib, it is not sufficient to call
    phy_mac_interrupt().  Instead, the PHY's interrupt handler needs to run
    so that PHY interrupts are cleared.  That's because according to page
    119 of the LAN950x datasheet, "The source of this interrupt is a level.
    The interrupt persists until it is cleared in the PHY."
    
    https://www.microchip.com/content/dam/mchp/documents/UNG/ProductDocuments/DataSheets/LAN950x-Data-Sheet-DS00001875D.pdf
    
    Therefore, create an IRQ domain with a single IRQ for the PHY.  In the
    future, the IRQ domain may be extended to support the 11 GPIOs on the
    LAN95xx.
    
    Normally the PHY interrupt should be masked until the PHY driver has
    cleared it.  However masking requires a (sleeping) USB transaction and
    interrupts are received in (non-sleepable) softirq context.  I decided
    not to mask the interrupt at all (by using the dummy_irq_chip's noop
    ->irq_mask() callback):  The USB interrupt endpoint is polled in 1 msec
    intervals and normally that's sufficient to wake the PHY driver's IRQ
    thread and have it clear the interrupt.  If it does take longer, worst
    thing that can happen is the IRQ thread is woken again.  No big deal.
    
    Because PHY interrupts are now perpetually enabled, there's no need to
    selectively enable them on suspend.  So remove all invocations of
    smsc95xx_enable_phy_wakeup_interrupts().
    
    In smsc95xx_resume(), move the call of phy_init_hw() before
    usbnet_resume() (which restarts the status URB) to ensure that the PHY
    is fully initialized when an interrupt is handled.
    
    Tested-by: Oleksij Rempel <o.rempel@pengutronix.de> # LAN9514/9512/9500
    Tested-by: Ferry Toth <fntoth@gmail.com> # LAN9514
    Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
    Reviewed-by: Andrew Lunn <andrew@lunn.ch> # from a PHY perspective
    Cc: Andre Edich <andre.edich@microchip.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    1ce8b372
smsc95xx.c 51.6 KB