gfar_write(®s->tctrl, tctrl);
 }
 
+static void gfar_configure_coalescing(struct gfar_private *priv,
+                              unsigned long tx_mask, unsigned long rx_mask)
+{
+       struct gfar __iomem *regs = priv->gfargrp[0].regs;
+       u32 __iomem *baddr;
+
+       if (priv->mode == MQ_MG_MODE) {
+               int i = 0;
+
+               baddr = ®s->txic0;
+               for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
+                       gfar_write(baddr + i, 0);
+                       if (likely(priv->tx_queue[i]->txcoalescing))
+                               gfar_write(baddr + i, priv->tx_queue[i]->txic);
+               }
+
+               baddr = ®s->rxic0;
+               for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
+                       gfar_write(baddr + i, 0);
+                       if (likely(priv->rx_queue[i]->rxcoalescing))
+                               gfar_write(baddr + i, priv->rx_queue[i]->rxic);
+               }
+       } else {
+               /* Backward compatible case -- even if we enable
+                * multiple queues, there's only single reg to program
+                */
+               gfar_write(®s->txic, 0);
+               if (likely(priv->tx_queue[0]->txcoalescing))
+                       gfar_write(®s->txic, priv->tx_queue[0]->txic);
+
+               gfar_write(®s->rxic, 0);
+               if (unlikely(priv->rx_queue[0]->rxcoalescing))
+                       gfar_write(®s->rxic, priv->rx_queue[0]->rxic);
+       }
+}
+
+void gfar_configure_coalescing_all(struct gfar_private *priv)
+{
+       gfar_configure_coalescing(priv, 0xFF, 0xFF);
+}
+
 static struct net_device_stats *gfar_get_stats(struct net_device *dev)
 {
        struct gfar_private *priv = netdev_priv(dev);
        priv->ndev->trans_start = jiffies; /* prevent tx timeout */
 }
 
-static void gfar_configure_coalescing(struct gfar_private *priv,
-                              unsigned long tx_mask, unsigned long rx_mask)
-{
-       struct gfar __iomem *regs = priv->gfargrp[0].regs;
-       u32 __iomem *baddr;
-
-       if (priv->mode == MQ_MG_MODE) {
-               int i = 0;
-
-               baddr = ®s->txic0;
-               for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
-                       gfar_write(baddr + i, 0);
-                       if (likely(priv->tx_queue[i]->txcoalescing))
-                               gfar_write(baddr + i, priv->tx_queue[i]->txic);
-               }
-
-               baddr = ®s->rxic0;
-               for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
-                       gfar_write(baddr + i, 0);
-                       if (likely(priv->rx_queue[i]->rxcoalescing))
-                               gfar_write(baddr + i, priv->rx_queue[i]->rxic);
-               }
-       } else {
-               /* Backward compatible case -- even if we enable
-                * multiple queues, there's only single reg to program
-                */
-               gfar_write(®s->txic, 0);
-               if (likely(priv->tx_queue[0]->txcoalescing))
-                       gfar_write(®s->txic, priv->tx_queue[0]->txic);
-
-               gfar_write(®s->rxic, 0);
-               if (unlikely(priv->rx_queue[0]->rxcoalescing))
-                       gfar_write(®s->rxic, priv->rx_queue[0]->rxic);
-       }
-}
-
-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);
                gfar_write(®s->rstat, gfargrp->rstat);
 
                gfar_write(®s->imask, IMASK_DEFAULT);
-
-               /* If we are coalescing interrupts, update the timer
-                * Otherwise, clear it
-                */
-               gfar_write(®s->txic, 0);
-               if (likely(tx_queue->txcoalescing))
-                       gfar_write(®s->txic, tx_queue->txic);
-
-               gfar_write(®s->rxic, 0);
-               if (unlikely(rx_queue->rxcoalescing))
-                       gfar_write(®s->rxic, rx_queue->rxic);
        }
 
        return work_done;
                gfar_write(®s->rstat, gfargrp->rstat);
 
                gfar_write(®s->imask, IMASK_DEFAULT);
-
-               /* If we are coalescing interrupts, update the timer
-                * Otherwise, clear it
-                */
-               gfar_configure_coalescing(priv, gfargrp->rx_bit_map,
-                                         gfargrp->tx_bit_map);
        }
 
        return work_done;
 
                          struct ethtool_coalesce *cvals)
 {
        struct gfar_private *priv = netdev_priv(dev);
-       int i = 0;
+       int i, err = 0;
 
        if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
                return -EOPNOTSUPP;
 
-       /* Set up rx coalescing */
-       /* As of now, we will enable/disable coalescing for all
-        * queues together in case of eTSEC2, this will be modified
-        * along with the ethtool interface
-        */
-       if ((cvals->rx_coalesce_usecs == 0) ||
-           (cvals->rx_max_coalesced_frames == 0)) {
-               for (i = 0; i < priv->num_rx_queues; i++)
-                       priv->rx_queue[i]->rxcoalescing = 0;
-       } else {
-               for (i = 0; i < priv->num_rx_queues; i++)
-                       priv->rx_queue[i]->rxcoalescing = 1;
-       }
-
        if (NULL == priv->phydev)
                return -ENODEV;
 
                return -EINVAL;
        }
 
+       /* Check the bounds of the values */
+       if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+               netdev_info(dev, "Coalescing is limited to %d microseconds\n",
+                           GFAR_MAX_COAL_USECS);
+               return -EINVAL;
+       }
+
+       if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+               netdev_info(dev, "Coalescing is limited to %d frames\n",
+                           GFAR_MAX_COAL_FRAMES);
+               return -EINVAL;
+       }
+
+       while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
+               cpu_relax();
+
+       /* Set up rx coalescing */
+       if ((cvals->rx_coalesce_usecs == 0) ||
+           (cvals->rx_max_coalesced_frames == 0)) {
+               for (i = 0; i < priv->num_rx_queues; i++)
+                       priv->rx_queue[i]->rxcoalescing = 0;
+       } else {
+               for (i = 0; i < priv->num_rx_queues; i++)
+                       priv->rx_queue[i]->rxcoalescing = 1;
+       }
+
        for (i = 0; i < priv->num_rx_queues; i++) {
                priv->rx_queue[i]->rxic = mk_ic_value(
                        cvals->rx_max_coalesced_frames,
                        priv->tx_queue[i]->txcoalescing = 1;
        }
 
-       /* Check the bounds of the values */
-       if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
-               netdev_info(dev, "Coalescing is limited to %d microseconds\n",
-                           GFAR_MAX_COAL_USECS);
-               return -EINVAL;
-       }
-
-       if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
-               netdev_info(dev, "Coalescing is limited to %d frames\n",
-                           GFAR_MAX_COAL_FRAMES);
-               return -EINVAL;
-       }
-
        for (i = 0; i < priv->num_tx_queues; i++) {
                priv->tx_queue[i]->txic = mk_ic_value(
                        cvals->tx_max_coalesced_frames,
                        gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));
        }
 
-       gfar_configure_coalescing_all(priv);
+       if (dev->flags & IFF_UP) {
+               stop_gfar(dev);
+               err = startup_gfar(dev);
+       } else {
+               gfar_mac_reset(priv);
+       }
 
-       return 0;
+       clear_bit_unlock(GFAR_RESETTING, &priv->state);
+
+       return err;
 }
 
 /* Fills in rvals with the current ring parameters.  Currently,