gianfar: Split allocation and initialization steps out of startup_gfar()
Anton Vorontsov [Mon, 12 Oct 2009 06:00:34 +0000 (06:00 +0000)]
Two new functions implemented: gfar_alloc_skb_resources() and
gfar_init_mac(). We'll use gfar_init_mac() for restoring after
hibernation.

The patch just moves the code around, there should be no functional
changes.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

drivers/net/gianfar.c

index f849741..c873554 100644 (file)
@@ -147,6 +147,176 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc");
 MODULE_DESCRIPTION("Gianfar Ethernet Driver");
 MODULE_LICENSE("GPL");
 
+static int gfar_alloc_skb_resources(struct net_device *ndev)
+{
+       struct txbd8 *txbdp;
+       struct rxbd8 *rxbdp;
+       dma_addr_t addr = 0;
+       void *vaddr;
+       int i;
+       struct gfar_private *priv = netdev_priv(ndev);
+       struct device *dev = &priv->ofdev->dev;
+       struct gfar __iomem *regs = priv->regs;
+
+       /* Allocate memory for the buffer descriptors */
+       vaddr = dma_alloc_coherent(dev, sizeof(*txbdp) * priv->tx_ring_size +
+                                       sizeof(*rxbdp) * priv->rx_ring_size,
+                                  &addr, GFP_KERNEL);
+       if (!vaddr) {
+               if (netif_msg_ifup(priv))
+                       pr_err("%s: Could not allocate buffer descriptors!\n",
+                              ndev->name);
+               return -ENOMEM;
+       }
+
+       priv->tx_bd_base = vaddr;
+
+       /* enet DMA only understands physical addresses */
+       gfar_write(&regs->tbase0, addr);
+
+       /* Start the rx descriptor ring where the tx ring leaves off */
+       addr = addr + sizeof(*txbdp) * priv->tx_ring_size;
+       vaddr = vaddr + sizeof(*txbdp) * priv->tx_ring_size;
+       priv->rx_bd_base = vaddr;
+       gfar_write(&regs->rbase0, addr);
+
+       /* Setup the skbuff rings */
+       priv->tx_skbuff = kmalloc(sizeof(*priv->tx_skbuff) *
+                                 priv->tx_ring_size, GFP_KERNEL);
+       if (!priv->tx_skbuff) {
+               if (netif_msg_ifup(priv))
+                       pr_err("%s: Could not allocate tx_skbuff\n",
+                              ndev->name);
+               goto cleanup;
+       }
+
+       for (i = 0; i < priv->tx_ring_size; i++)
+               priv->tx_skbuff[i] = NULL;
+
+       priv->rx_skbuff = kmalloc(sizeof(*priv->rx_skbuff) *
+                                 priv->rx_ring_size, GFP_KERNEL);
+       if (!priv->rx_skbuff) {
+               if (netif_msg_ifup(priv))
+                       pr_err("%s: Could not allocate rx_skbuff\n",
+                              ndev->name);
+               goto cleanup;
+       }
+
+       for (i = 0; i < priv->rx_ring_size; i++)
+               priv->rx_skbuff[i] = NULL;
+
+       /* Initialize some variables in our dev structure */
+       priv->num_txbdfree = priv->tx_ring_size;
+       priv->dirty_tx = priv->cur_tx = priv->tx_bd_base;
+       priv->cur_rx = priv->rx_bd_base;
+       priv->skb_curtx = priv->skb_dirtytx = 0;
+       priv->skb_currx = 0;
+
+       /* Initialize Transmit Descriptor Ring */
+       txbdp = priv->tx_bd_base;
+       for (i = 0; i < priv->tx_ring_size; i++) {
+               txbdp->lstatus = 0;
+               txbdp->bufPtr = 0;
+               txbdp++;
+       }
+
+       /* Set the last descriptor in the ring to indicate wrap */
+       txbdp--;
+       txbdp->status |= TXBD_WRAP;
+
+       rxbdp = priv->rx_bd_base;
+       for (i = 0; i < priv->rx_ring_size; i++) {
+               struct sk_buff *skb;
+
+               skb = gfar_new_skb(ndev);
+               if (!skb) {
+                       pr_err("%s: Can't allocate RX buffers\n", ndev->name);
+                       goto cleanup;
+               }
+
+               priv->rx_skbuff[i] = skb;
+
+               gfar_new_rxbdp(ndev, rxbdp, skb);
+
+               rxbdp++;
+       }
+
+       return 0;
+
+cleanup:
+       free_skb_resources(priv);
+       return -ENOMEM;
+}
+
+static void gfar_init_mac(struct net_device *ndev)
+{
+       struct gfar_private *priv = netdev_priv(ndev);
+       struct gfar __iomem *regs = priv->regs;
+       u32 rctrl = 0;
+       u32 tctrl = 0;
+       u32 attrs = 0;
+
+       /* Configure the coalescing support */
+       gfar_write(&regs->txic, 0);
+       if (priv->txcoalescing)
+               gfar_write(&regs->txic, priv->txic);
+
+       gfar_write(&regs->rxic, 0);
+       if (priv->rxcoalescing)
+               gfar_write(&regs->rxic, priv->rxic);
+
+       if (priv->rx_csum_enable)
+               rctrl |= RCTRL_CHECKSUMMING;
+
+       if (priv->extended_hash) {
+               rctrl |= RCTRL_EXTHASH;
+
+               gfar_clear_exact_match(ndev);
+               rctrl |= RCTRL_EMEN;
+       }
+
+       if (priv->padding) {
+               rctrl &= ~RCTRL_PAL_MASK;
+               rctrl |= RCTRL_PADDING(priv->padding);
+       }
+
+       /* keep vlan related bits if it's enabled */
+       if (priv->vlgrp) {
+               rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
+               tctrl |= TCTRL_VLINS;
+       }
+
+       /* Init rctrl based on our settings */
+       gfar_write(&regs->rctrl, rctrl);
+
+       if (ndev->features & NETIF_F_IP_CSUM)
+               tctrl |= TCTRL_INIT_CSUM;
+
+       gfar_write(&regs->tctrl, tctrl);
+
+       /* Set the extraction length and index */
+       attrs = ATTRELI_EL(priv->rx_stash_size) |
+               ATTRELI_EI(priv->rx_stash_index);
+
+       gfar_write(&regs->attreli, attrs);
+
+       /* Start with defaults, and add stashing or locking
+        * depending on the approprate variables */
+       attrs = ATTR_INIT_SETTINGS;
+
+       if (priv->bd_stash_en)
+               attrs |= ATTR_BDSTASH;
+
+       if (priv->rx_stash_size != 0)
+               attrs |= ATTR_BUFSTASH;
+
+       gfar_write(&regs->attr, attrs);
+
+       gfar_write(&regs->fifo_tx_thr, priv->fifo_threshold);
+       gfar_write(&regs->fifo_tx_starve, priv->fifo_starve);
+       gfar_write(&regs->fifo_tx_starve_shutoff, priv->fifo_starve_off);
+}
+
 static const struct net_device_ops gfar_netdev_ops = {
        .ndo_open = gfar_enet_open,
        .ndo_start_xmit = gfar_start_xmit,
@@ -927,106 +1097,17 @@ void gfar_start(struct net_device *dev)
 /* Bring the controller up and running */
 int startup_gfar(struct net_device *ndev)
 {
-       struct txbd8 *txbdp;
-       struct rxbd8 *rxbdp;
-       dma_addr_t addr = 0;
-       void *vaddr;
-       int i;
        struct gfar_private *priv = netdev_priv(ndev);
-       struct device *dev = &priv->ofdev->dev;
        struct gfar __iomem *regs = priv->regs;
        int err;
-       u32 rctrl = 0;
-       u32 tctrl = 0;
-       u32 attrs = 0;
 
        gfar_write(&regs->imask, IMASK_INIT_CLEAR);
 
-       /* Allocate memory for the buffer descriptors */
-       vaddr = dma_alloc_coherent(dev, sizeof(*txbdp) * priv->tx_ring_size +
-                                       sizeof(*rxbdp) * priv->rx_ring_size,
-                                  &addr, GFP_KERNEL);
-       if (!vaddr) {
-               if (netif_msg_ifup(priv))
-                       pr_err("%s: Could not allocate buffer descriptors!\n",
-                              ndev->name);
-               return -ENOMEM;
-       }
-
-       priv->tx_bd_base = vaddr;
-
-       /* enet DMA only understands physical addresses */
-       gfar_write(&regs->tbase0, addr);
-
-       /* Start the rx descriptor ring where the tx ring leaves off */
-       addr = addr + sizeof(*txbdp) * priv->tx_ring_size;
-       vaddr = vaddr + sizeof(*txbdp) * priv->tx_ring_size;
-       priv->rx_bd_base = vaddr;
-       gfar_write(&regs->rbase0, addr);
-
-       /* Setup the skbuff rings */
-       priv->tx_skbuff = kmalloc(sizeof(*priv->tx_skbuff) *
-                                 priv->tx_ring_size, GFP_KERNEL);
-       if (!priv->tx_skbuff) {
-               if (netif_msg_ifup(priv))
-                       pr_err("%s: Could not allocate tx_skbuff\n",
-                              ndev->name);
-               err = -ENOMEM;
-               goto tx_skb_fail;
-       }
-
-       for (i = 0; i < priv->tx_ring_size; i++)
-               priv->tx_skbuff[i] = NULL;
-
-       priv->rx_skbuff = kmalloc(sizeof(*priv->rx_skbuff) *
-                                 priv->rx_ring_size, GFP_KERNEL);
-       if (!priv->rx_skbuff) {
-               if (netif_msg_ifup(priv))
-                       pr_err("%s: Could not allocate rx_skbuff\n",
-                              ndev->name);
-               err = -ENOMEM;
-               goto rx_skb_fail;
-       }
-
-       for (i = 0; i < priv->rx_ring_size; i++)
-               priv->rx_skbuff[i] = NULL;
-
-       /* Initialize some variables in our dev structure */
-       priv->num_txbdfree = priv->tx_ring_size;
-       priv->dirty_tx = priv->cur_tx = priv->tx_bd_base;
-       priv->cur_rx = priv->rx_bd_base;
-       priv->skb_curtx = priv->skb_dirtytx = 0;
-       priv->skb_currx = 0;
-
-       /* Initialize Transmit Descriptor Ring */
-       txbdp = priv->tx_bd_base;
-       for (i = 0; i < priv->tx_ring_size; i++) {
-               txbdp->lstatus = 0;
-               txbdp->bufPtr = 0;
-               txbdp++;
-       }
-
-       /* Set the last descriptor in the ring to indicate wrap */
-       txbdp--;
-       txbdp->status |= TXBD_WRAP;
-
-       rxbdp = priv->rx_bd_base;
-       for (i = 0; i < priv->rx_ring_size; i++) {
-               struct sk_buff *skb;
-
-               skb = gfar_new_skb(ndev);
-               if (!skb) {
-                       pr_err("%s: Can't allocate RX buffers\n", ndev->name);
-                       err = -ENOMEM;
-                       goto err_rxalloc_fail;
-               }
-
-               priv->rx_skbuff[i] = skb;
-
-               gfar_new_rxbdp(ndev, rxbdp, skb);
+       err = gfar_alloc_skb_resources(ndev);
+       if (err)
+               return err;
 
-               rxbdp++;
-       }
+       gfar_init_mac(ndev);
 
        /* If the device has multiple interrupts, register for
         * them.  Otherwise, only register for the one */
@@ -1070,71 +1151,11 @@ int startup_gfar(struct net_device *ndev)
                }
        }
 
-       phy_start(priv->phydev);
-
-       /* Configure the coalescing support */
-       gfar_write(&regs->txic, 0);
-       if (priv->txcoalescing)
-               gfar_write(&regs->txic, priv->txic);
-
-       gfar_write(&regs->rxic, 0);
-       if (priv->rxcoalescing)
-               gfar_write(&regs->rxic, priv->rxic);
-
-       if (priv->rx_csum_enable)
-               rctrl |= RCTRL_CHECKSUMMING;
-
-       if (priv->extended_hash) {
-               rctrl |= RCTRL_EXTHASH;
-
-               gfar_clear_exact_match(ndev);
-               rctrl |= RCTRL_EMEN;
-       }
-
-       if (priv->padding) {
-               rctrl &= ~RCTRL_PAL_MASK;
-               rctrl |= RCTRL_PADDING(priv->padding);
-       }
-
-       /* keep vlan related bits if it's enabled */
-       if (priv->vlgrp) {
-               rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
-               tctrl |= TCTRL_VLINS;
-       }
-
-       /* Init rctrl based on our settings */
-       gfar_write(&regs->rctrl, rctrl);
-
-       if (ndev->features & NETIF_F_IP_CSUM)
-               tctrl |= TCTRL_INIT_CSUM;
-
-       gfar_write(&regs->tctrl, tctrl);
-
-       /* Set the extraction length and index */
-       attrs = ATTRELI_EL(priv->rx_stash_size) |
-               ATTRELI_EI(priv->rx_stash_index);
-
-       gfar_write(&regs->attreli, attrs);
-
-       /* Start with defaults, and add stashing or locking
-        * depending on the approprate variables */
-       attrs = ATTR_INIT_SETTINGS;
-
-       if (priv->bd_stash_en)
-               attrs |= ATTR_BDSTASH;
-
-       if (priv->rx_stash_size != 0)
-               attrs |= ATTR_BUFSTASH;
-
-       gfar_write(&regs->attr, attrs);
-
-       gfar_write(&regs->fifo_tx_thr, priv->fifo_threshold);
-       gfar_write(&regs->fifo_tx_starve, priv->fifo_starve);
-       gfar_write(&regs->fifo_tx_starve_shutoff, priv->fifo_starve_off);
-
        /* Start the controller */
        gfar_start(ndev);
 
+       phy_start(priv->phydev);
+
        return 0;
 
 rx_irq_fail:
@@ -1142,9 +1163,6 @@ rx_irq_fail:
 tx_irq_fail:
        free_irq(priv->interruptError, ndev);
 err_irq_fail:
-err_rxalloc_fail:
-rx_skb_fail:
-tx_skb_fail:
        free_skb_resources(priv);
        return err;
 }