| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- From cba0aba37d2228556e0d1f776d403435868cdbfa Mon Sep 17 00:00:00 2001
- From: Russell King <[email protected]>
- Date: Tue, 28 May 2019 10:57:23 +0100
- Subject: [PATCH 607/660] net: phylink: support for link gpio interrupt
- 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().
- Reviewed-by: Florian Fainelli <[email protected]>
- Signed-off-by: Russell King <[email protected]>
- Signed-off-by: David S. Miller <[email protected]>
- Signed-off-by: Russell King <[email protected]>
- ---
- drivers/net/phy/phylink.c | 36 ++++++++++++++++++++++++++++++++----
- 1 file changed, 32 insertions(+), 4 deletions(-)
- --- a/drivers/net/phy/phylink.c
- +++ b/drivers/net/phy/phylink.c
- @@ -59,6 +59,7 @@ struct phylink {
- phy_interface_t cur_interface;
-
- 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);
- @@ -645,7 +646,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);
- @@ -912,6 +913,15 @@ void phylink_mac_change(struct phylink *
- }
- 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()
- @@ -947,7 +957,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);
- @@ -973,8 +998,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);
- }
|