Message ID | E1hSk6y-0000vs-Pj@rmk-PC.armlinux.org.uk |
---|---|
State | Deferred |
Delegated to: | David Miller |
Headers | show |
Series | phylink/sfp updates | expand |
On 5/20/19 8:22 AM, Russell King wrote: > Add support for using GPIO interrupts with a fixed-link GPIO rather than > polling the GPIO every second and invoking the phylink resolution. This > avoids unnecessary calls to mac_config(). > > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Just one comment, see below: [snip] > - if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio)) > - del_timer_sync(&pl->link_poll); > + del_timer_sync(&pl->link_poll); Removing a timer that was only set-up if pl->link_an_mode == MLO_AN_FIXED probably does not hurt, but this breaks symmetry a bit here.
On Mon, May 20, 2019 at 11:22:21AM -0700, Florian Fainelli wrote: > On 5/20/19 8:22 AM, Russell King wrote: > > Add support for using GPIO interrupts with a fixed-link GPIO rather than > > polling the GPIO every second and invoking the phylink resolution. This > > avoids unnecessary calls to mac_config(). > > > > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> > > Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> > > Just one comment, see below: > > [snip] > > > - if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio)) > > - del_timer_sync(&pl->link_poll); > > + del_timer_sync(&pl->link_poll); > > Removing a timer that was only set-up if pl->link_an_mode == > MLO_AN_FIXED probably does not hurt, but this breaks symmetry a bit here. The reason for this change is because that is no longer the only case that the timer would be running. The timer will be running if either of the following are true: 1. We are in fixed mode, and we have a get_fixed_state function registered. 2. We are in fixed mode, and have a GPIO, but are unable to get an interrupt for it. It's way simpler and less error-prone to just delete the timer here, rather than trying to keep track of whether we armed it.
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 74983593834b..bdee5f307a7f 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -52,6 +52,7 @@ struct phylink { /* The link configuration settings */ struct phylink_link_state link_config; struct gpio_desc *link_gpio; + unsigned int link_irq; struct timer_list link_poll; void (*get_fixed_state)(struct net_device *dev, struct phylink_link_state *s); @@ -608,7 +609,7 @@ void phylink_destroy(struct phylink *pl) { if (pl->sfp_bus) sfp_unregister_upstream(pl->sfp_bus); - if (!IS_ERR_OR_NULL(pl->link_gpio)) + if (pl->link_gpio) gpiod_put(pl->link_gpio); cancel_work_sync(&pl->resolve); @@ -871,6 +872,15 @@ void phylink_mac_change(struct phylink *pl, bool up) } EXPORT_SYMBOL_GPL(phylink_mac_change); +static irqreturn_t phylink_link_handler(int irq, void *data) +{ + struct phylink *pl = data; + + phylink_run_resolve(pl); + + return IRQ_HANDLED; +} + /** * phylink_start() - start a phylink instance * @pl: a pointer to a &struct phylink returned from phylink_create() @@ -906,7 +916,22 @@ void phylink_start(struct phylink *pl) clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); phylink_run_resolve(pl); - if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio)) + if (pl->link_an_mode == MLO_AN_FIXED && pl->link_gpio) { + int irq = gpiod_to_irq(pl->link_gpio); + + if (irq > 0) { + if (!request_irq(irq, phylink_link_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "netdev link", pl)) + pl->link_irq = irq; + else + irq = 0; + } + if (irq <= 0) + mod_timer(&pl->link_poll, jiffies + HZ); + } + if (pl->link_an_mode == MLO_AN_FIXED && pl->get_fixed_state) mod_timer(&pl->link_poll, jiffies + HZ); if (pl->sfp_bus) sfp_upstream_start(pl->sfp_bus); @@ -932,8 +957,11 @@ void phylink_stop(struct phylink *pl) phy_stop(pl->phydev); if (pl->sfp_bus) sfp_upstream_stop(pl->sfp_bus); - if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio)) - del_timer_sync(&pl->link_poll); + del_timer_sync(&pl->link_poll); + if (pl->link_irq) { + free_irq(pl->link_irq, pl); + pl->link_irq = 0; + } phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); }
Add support for using GPIO interrupts with a fixed-link GPIO rather than polling the GPIO every second and invoking the phylink resolution. This avoids unnecessary calls to mac_config(). Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> --- drivers/net/phy/phylink.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-)