diff options
author | Claudiu Manoil <claudiu.manoil@freescale.com> | 2014-02-24 12:13:44 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-24 19:38:20 -0500 |
commit | 80ec396cb6b522b23c69dfff32a2d12993e4bb30 (patch) | |
tree | 44a83f50b3077ceb3cca75a41657f9e9218ccdb6 /drivers/net | |
parent | 88302648be8c45af09694363be1b165680489137 (diff) |
gianfar: Don't free/request irqs on device reset
Resetting the device (stop_gfar()/startup_gfar()) should
be fast and to the point, in order to timely recover
from an error condition (like Tx timeout) or during
device reconfig. The irq free/ request routines are just
redundant here, and they should be part of the device
close/ open routines instead.
Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar.c | 77 |
1 files changed, 45 insertions, 32 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 728078fe400e..6c054b549fa1 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1715,18 +1715,10 @@ void gfar_halt(struct gfar_private *priv) gfar_write(®s->maccfg1, tempval); } -static void free_grp_irqs(struct gfar_priv_grp *grp) -{ - free_irq(gfar_irq(grp, TX)->irq, grp); - free_irq(gfar_irq(grp, RX)->irq, grp); - free_irq(gfar_irq(grp, ER)->irq, grp); -} - void stop_gfar(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); unsigned long flags; - int i; phy_stop(priv->phydev); @@ -1742,16 +1734,6 @@ void stop_gfar(struct net_device *dev) unlock_tx_qs(priv); local_irq_restore(flags); - /* Free the IRQs */ - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { - for (i = 0; i < priv->num_grps; i++) - free_grp_irqs(&priv->gfargrp[i]); - } else { - for (i = 0; i < priv->num_grps; i++) - free_irq(gfar_irq(&priv->gfargrp[i], TX)->irq, - &priv->gfargrp[i]); - } - free_skb_resources(priv); } @@ -1919,6 +1901,13 @@ void gfar_configure_coalescing_all(struct gfar_private *priv) gfar_configure_coalescing(priv, 0xFF, 0xFF); } +static void free_grp_irqs(struct gfar_priv_grp *grp) +{ + free_irq(gfar_irq(grp, TX)->irq, grp); + free_irq(gfar_irq(grp, RX)->irq, grp); + free_irq(gfar_irq(grp, ER)->irq, grp); +} + static int register_grp_irqs(struct gfar_priv_grp *grp) { struct gfar_private *priv = grp->priv; @@ -1975,11 +1964,42 @@ err_irq_fail: } +static void gfar_free_irq(struct gfar_private *priv) +{ + int i; + + /* Free the IRQs */ + if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { + for (i = 0; i < priv->num_grps; i++) + free_grp_irqs(&priv->gfargrp[i]); + } else { + for (i = 0; i < priv->num_grps; i++) + free_irq(gfar_irq(&priv->gfargrp[i], TX)->irq, + &priv->gfargrp[i]); + } +} + +static int gfar_request_irq(struct gfar_private *priv) +{ + int err, i, j; + + for (i = 0; i < priv->num_grps; i++) { + err = register_grp_irqs(&priv->gfargrp[i]); + if (err) { + for (j = 0; j < i; j++) + free_grp_irqs(&priv->gfargrp[j]); + return err; + } + } + + return 0; +} + /* Bring the controller up and running */ int startup_gfar(struct net_device *ndev) { struct gfar_private *priv = netdev_priv(ndev); - int err, i, j; + int err; gfar_mac_reset(priv); @@ -1989,25 +2009,12 @@ int startup_gfar(struct net_device *ndev) gfar_init_tx_rx_base(priv); - for (i = 0; i < priv->num_grps; i++) { - err = register_grp_irqs(&priv->gfargrp[i]); - if (err) { - for (j = 0; j < i; j++) - free_grp_irqs(&priv->gfargrp[j]); - goto irq_fail; - } - } - /* Start the controller */ gfar_start(priv); phy_start(priv->phydev); return 0; - -irq_fail: - free_skb_resources(priv); - return err; } /* Called when something needs to use the ethernet device @@ -2027,6 +2034,10 @@ static int gfar_enet_open(struct net_device *dev) return err; } + err = gfar_request_irq(priv); + if (err) + return err; + err = startup_gfar(dev); if (err) { disable_napi(priv); @@ -2369,6 +2380,8 @@ static int gfar_close(struct net_device *dev) netif_tx_stop_all_queues(dev); + gfar_free_irq(priv); + return 0; } |