regulator: Fix check of unsigned return value and transmit errors in wm831x_gp_ldo_ge...
[safe/jmp/linux-2.6] / drivers / net / fec.c
index 672566b..16a1d58 100644 (file)
@@ -172,6 +172,7 @@ struct fec_enet_private {
        /* The saved address of a sent-in-place packet/buffer, for skfree(). */
        unsigned char *tx_bounce[TX_RING_SIZE];
        struct  sk_buff* tx_skbuff[TX_RING_SIZE];
+       struct  sk_buff* rx_skbuff[RX_RING_SIZE];
        ushort  skb_cur;
        ushort  skb_dirty;
 
@@ -210,17 +211,13 @@ struct fec_enet_private {
        int     full_duplex;
 };
 
-static int fec_enet_open(struct net_device *dev);
-static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void fec_enet_mii(struct net_device *dev);
 static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
 static void fec_enet_tx(struct net_device *dev);
 static void fec_enet_rx(struct net_device *dev);
 static int fec_enet_close(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
 static void fec_restart(struct net_device *dev, int duplex);
 static void fec_stop(struct net_device *dev);
-static void fec_set_mac_address(struct net_device *dev);
 
 
 /* MII processing.  We keep this as simple as possible.  Requests are
@@ -288,12 +285,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        struct bufdesc *bdp;
+       void *bufaddr;
        unsigned short  status;
        unsigned long flags;
 
        if (!fep->link) {
                /* Link is down or autonegotiation is in progress. */
-               return 1;
+               return NETDEV_TX_BUSY;
        }
 
        spin_lock_irqsave(&fep->hw_lock, flags);
@@ -308,14 +306,14 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
                 */
                printk("%s: tx queue full!.\n", dev->name);
                spin_unlock_irqrestore(&fep->hw_lock, flags);
-               return 1;
+               return NETDEV_TX_BUSY;
        }
 
        /* Clear all of the status flags */
        status &= ~BD_ENET_TX_STATS;
 
        /* Set buffer length and buffer pointer */
-       bdp->cbd_bufaddr = __pa(skb->data);
+       bufaddr = skb->data;
        bdp->cbd_datlen = skb->len;
 
        /*
@@ -323,11 +321,11 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
         * 4-byte boundaries. Use bounce buffers to copy data
         * and get it aligned. Ugh.
         */
-       if (bdp->cbd_bufaddr & FEC_ALIGNMENT) {
+       if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
                unsigned int index;
                index = bdp - fep->tx_bd_base;
                memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len);
-               bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
+               bufaddr = fep->tx_bounce[index];
        }
 
        /* Save skb pointer */
@@ -339,8 +337,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Push the data cache so the CPM does not get stale memory
         * data.
         */
-       dma_sync_single(NULL, bdp->cbd_bufaddr,
-                       bdp->cbd_datlen, DMA_TO_DEVICE);
+       bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr,
+                       FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
 
        /* Send it on its way.  Tell FEC it's ready, interrupt when done,
         * it's the last BD of the frame, and to put the CRC on the end.
@@ -369,7 +367,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        spin_unlock_irqrestore(&fep->hw_lock, flags);
 
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static void
@@ -377,41 +375,8 @@ fec_timeout(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
 
-       printk("%s: transmit timed out.\n", dev->name);
        dev->stats.tx_errors++;
-#ifndef final_version
-       {
-       int     i;
-       struct bufdesc *bdp;
 
-       printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n",
-              (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "",
-              (unsigned long)fep->dirty_tx,
-              (unsigned long)fep->cur_rx);
-
-       bdp = fep->tx_bd_base;
-       printk(" tx: %u buffers\n",  TX_RING_SIZE);
-       for (i = 0 ; i < TX_RING_SIZE; i++) {
-               printk("  %08x: %04x %04x %08x\n",
-                      (uint) bdp,
-                      bdp->cbd_sc,
-                      bdp->cbd_datlen,
-                      (int) bdp->cbd_bufaddr);
-               bdp++;
-       }
-
-       bdp = fep->rx_bd_base;
-       printk(" rx: %lu buffers\n",  (unsigned long) RX_RING_SIZE);
-       for (i = 0 ; i < RX_RING_SIZE; i++) {
-               printk("  %08x: %04x %04x %08x\n",
-                      (uint) bdp,
-                      bdp->cbd_sc,
-                      bdp->cbd_datlen,
-                      (int) bdp->cbd_bufaddr);
-               bdp++;
-       }
-       }
-#endif
        fec_restart(dev, fep->full_duplex);
        netif_wake_queue(dev);
 }
@@ -462,11 +427,15 @@ fec_enet_tx(struct net_device *dev)
        struct  sk_buff *skb;
 
        fep = netdev_priv(dev);
-       spin_lock_irq(&fep->hw_lock);
+       spin_lock(&fep->hw_lock);
        bdp = fep->dirty_tx;
 
        while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
-               if (bdp == fep->cur_tx && fep->tx_full == 0) break;
+               if (bdp == fep->cur_tx && fep->tx_full == 0)
+                       break;
+
+               dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
+               bdp->cbd_bufaddr = 0;
 
                skb = fep->tx_skbuff[fep->skb_dirty];
                /* Check for errors. */
@@ -517,7 +486,7 @@ fec_enet_tx(struct net_device *dev)
                }
        }
        fep->dirty_tx = bdp;
-       spin_unlock_irq(&fep->hw_lock);
+       spin_unlock(&fep->hw_lock);
 }
 
 
@@ -540,7 +509,7 @@ fec_enet_rx(struct net_device *dev)
        flush_cache_all();
 #endif
 
-       spin_lock_irq(&fep->hw_lock);
+       spin_lock(&fep->hw_lock);
 
        /* First, grab all of the stats for the incoming packet.
         * These get messed up if we get called due to a busy condition.
@@ -590,26 +559,30 @@ fec_enet_rx(struct net_device *dev)
                dev->stats.rx_bytes += pkt_len;
                data = (__u8*)__va(bdp->cbd_bufaddr);
 
-               dma_sync_single(NULL, (unsigned long)__pa(data),
-                       pkt_len - 4, DMA_FROM_DEVICE);
+               dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
+                               DMA_FROM_DEVICE);
 
                /* This does 16 byte alignment, exactly what we need.
                 * The packet length includes FCS, but we don't want to
                 * include that when passing upstream as it messes up
                 * bridging applications.
                 */
-               skb = dev_alloc_skb(pkt_len - 4);
+               skb = dev_alloc_skb(pkt_len - 4 + NET_IP_ALIGN);
 
-               if (skb == NULL) {
+               if (unlikely(!skb)) {
                        printk("%s: Memory squeeze, dropping packet.\n",
                                        dev->name);
                        dev->stats.rx_dropped++;
                } else {
+                       skb_reserve(skb, NET_IP_ALIGN);
                        skb_put(skb, pkt_len - 4);      /* Make room */
                        skb_copy_to_linear_data(skb, data, pkt_len - 4);
                        skb->protocol = eth_type_trans(skb, dev);
                        netif_rx(skb);
                }
+
+               bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen,
+                       DMA_FROM_DEVICE);
 rx_processing_done:
                /* Clear the status flags for this buffer */
                status &= ~BD_ENET_RX_STATS;
@@ -631,7 +604,7 @@ rx_processing_done:
        }
        fep->cur_rx = bdp;
 
-       spin_unlock_irq(&fep->hw_lock);
+       spin_unlock(&fep->hw_lock);
 }
 
 /* called from interrupt context */
@@ -642,7 +615,7 @@ fec_enet_mii(struct net_device *dev)
        mii_list_t      *mip;
 
        fep = netdev_priv(dev);
-       spin_lock_irq(&fep->mii_lock);
+       spin_lock(&fep->mii_lock);
 
        if ((mip = mii_head) == NULL) {
                printk("MII and no head!\n");
@@ -660,20 +633,19 @@ fec_enet_mii(struct net_device *dev)
                writel(mip->mii_regval, fep->hwp + FEC_MII_DATA);
 
 unlock:
-       spin_unlock_irq(&fep->mii_lock);
+       spin_unlock(&fep->mii_lock);
 }
 
 static int
-mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *))
+mii_queue_unlocked(struct net_device *dev, int regval,
+               void (*func)(uint, struct net_device *))
 {
        struct fec_enet_private *fep;
-       unsigned long   flags;
        mii_list_t      *mip;
        int             retval;
 
        /* Add PHY address to register command */
        fep = netdev_priv(dev);
-       spin_lock_irqsave(&fep->mii_lock, flags);
 
        regval |= fep->phy_addr << 23;
        retval = 0;
@@ -694,6 +666,19 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi
                retval = 1;
        }
 
+       return retval;
+}
+
+static int
+mii_queue(struct net_device *dev, int regval,
+               void (*func)(uint, struct net_device *))
+{
+       struct fec_enet_private *fep;
+       unsigned long   flags;
+       int             retval;
+       fep = netdev_priv(dev);
+       spin_lock_irqsave(&fep->mii_lock, flags);
+       retval = mii_queue_unlocked(dev, regval, func);
        spin_unlock_irqrestore(&fep->mii_lock, flags);
        return retval;
 }
@@ -1169,20 +1154,11 @@ static void __inline__ fec_request_mii_intr(struct net_device *dev)
                printk("FEC: Could not allocate fec(MII) IRQ(66)!\n");
 }
 
-static void __inline__ fec_disable_phy_intr(void)
+static void __inline__ fec_disable_phy_intr(struct net_device *dev)
 {
-       volatile unsigned long *icrp;
-       icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-       *icrp = 0x08000000;
-}
-
-static void __inline__ fec_phy_ack_intr(void)
-{
-       volatile unsigned long *icrp;
-       /* Acknowledge the interrupt */
-       icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-       *icrp = 0x0d000000;
+       free_irq(66, dev);
 }
+#endif
 
 #ifdef CONFIG_M5272
 static void __inline__ fec_get_mac(struct net_device *dev)
@@ -1399,11 +1375,11 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
 
                        /* Got first part of ID, now get remainder */
                        fep->phy_id = phytype << 16;
-                       mii_queue(dev, mk_mii_read(MII_REG_PHYIR2),
+                       mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR2),
                                                        mii_discover_phy3);
                } else {
                        fep->phy_addr++;
-                       mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
+                       mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR1),
                                                        mii_discover_phy);
                }
        } else {
@@ -1412,7 +1388,7 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
                writel(0, fep->hwp + FEC_MII_SPEED);
                fep->phy_speed = 0;
 #ifdef HAVE_mii_link_interrupt
-               fec_disable_phy_intr();
+               fec_disable_phy_intr(dev);
 #endif
        }
 }
@@ -1425,8 +1401,6 @@ mii_link_interrupt(int irq, void * dev_id)
        struct  net_device *dev = dev_id;
        struct fec_enet_private *fep = netdev_priv(dev);
 
-       fec_phy_ack_intr();
-
        mii_do_cmd(dev, fep->phy->ack_int);
        mii_do_cmd(dev, phy_cmd_relink);  /* restart and display status */
 
@@ -1434,19 +1408,91 @@ mii_link_interrupt(int irq, void * dev_id)
 }
 #endif
 
+static void fec_enet_free_buffers(struct net_device *dev)
+{
+       struct fec_enet_private *fep = netdev_priv(dev);
+       int i;
+       struct sk_buff *skb;
+       struct bufdesc  *bdp;
+
+       bdp = fep->rx_bd_base;
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               skb = fep->rx_skbuff[i];
+
+               if (bdp->cbd_bufaddr)
+                       dma_unmap_single(&dev->dev, bdp->cbd_bufaddr,
+                                       FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+               if (skb)
+                       dev_kfree_skb(skb);
+               bdp++;
+       }
+
+       bdp = fep->tx_bd_base;
+       for (i = 0; i < TX_RING_SIZE; i++)
+               kfree(fep->tx_bounce[i]);
+}
+
+static int fec_enet_alloc_buffers(struct net_device *dev)
+{
+       struct fec_enet_private *fep = netdev_priv(dev);
+       int i;
+       struct sk_buff *skb;
+       struct bufdesc  *bdp;
+
+       bdp = fep->rx_bd_base;
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE);
+               if (!skb) {
+                       fec_enet_free_buffers(dev);
+                       return -ENOMEM;
+               }
+               fep->rx_skbuff[i] = skb;
+
+               bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+                               FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+               bdp->cbd_sc = BD_ENET_RX_EMPTY;
+               bdp++;
+       }
+
+       /* Set the last buffer to wrap. */
+       bdp--;
+       bdp->cbd_sc |= BD_SC_WRAP;
+
+       bdp = fep->tx_bd_base;
+       for (i = 0; i < TX_RING_SIZE; i++) {
+               fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
+
+               bdp->cbd_sc = 0;
+               bdp->cbd_bufaddr = 0;
+               bdp++;
+       }
+
+       /* Set the last buffer to wrap. */
+       bdp--;
+       bdp->cbd_sc |= BD_SC_WRAP;
+
+       return 0;
+}
+
 static int
 fec_enet_open(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
+       int ret;
 
        /* I should reset the ring buffers here, but I don't yet know
         * a simple way to do that.
         */
-       fec_set_mac_address(dev);
+
+       ret = fec_enet_alloc_buffers(dev);
+       if (ret)
+               return ret;
 
        fep->sequence_done = 0;
        fep->link = 0;
 
+       fec_restart(dev, 1);
+
        if (fep->phy) {
                mii_do_cmd(dev, fep->phy->ack_int);
                mii_do_cmd(dev, fep->phy->config);
@@ -1463,18 +1509,14 @@ fec_enet_open(struct net_device *dev)
                        schedule();
 
                mii_do_cmd(dev, fep->phy->startup);
-
-               /* Set the initial link state to true. A lot of hardware
-                * based on this device does not implement a PHY interrupt,
-                * so we are never notified of link change.
-                */
-               fep->link = 1;
-       } else {
-               fep->link = 1; /* lets just try it and see */
-               /* no phy,  go full duplex,  it's most likely a hub chip */
-               fec_restart(dev, 1);
        }
 
+       /* Set the initial link state to true. A lot of hardware
+        * based on this device does not implement a PHY interrupt,
+        * so we are never notified of link change.
+        */
+       fep->link = 1;
+
        netif_start_queue(dev);
        fep->opened = 1;
        return 0;
@@ -1490,6 +1532,8 @@ fec_enet_close(struct net_device *dev)
        netif_stop_queue(dev);
        fec_stop(dev);
 
+        fec_enet_free_buffers(dev);
+
        return 0;
 }
 
@@ -1517,85 +1561,104 @@ static void set_multicast_list(struct net_device *dev)
                tmp = readl(fep->hwp + FEC_R_CNTRL);
                tmp |= 0x8;
                writel(tmp, fep->hwp + FEC_R_CNTRL);
-       } else {
-               tmp = readl(fep->hwp + FEC_R_CNTRL);
-               tmp &= ~0x8;
-               writel(tmp, fep->hwp + FEC_R_CNTRL);
+               return;
+       }
 
-               if (dev->flags & IFF_ALLMULTI) {
-                       /* Catch all multicast addresses, so set the
-                        * filter to all 1's
-                        */
-                       writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-                       writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-               } else {
-                       /* Clear filter and add the addresses in hash register
-                        */
-                       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-                       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-
-                       dmi = dev->mc_list;
-
-                       for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) {
-                               /* Only support group multicast for now */
-                               if (!(dmi->dmi_addr[0] & 1))
-                                       continue;
-
-                               /* calculate crc32 value of mac address */
-                               crc = 0xffffffff;
-
-                               for (i = 0; i < dmi->dmi_addrlen; i++) {
-                                       data = dmi->dmi_addr[i];
-                                       for (bit = 0; bit < 8; bit++, data >>= 1) {
-                                               crc = (crc >> 1) ^
-                                               (((crc ^ data) & 1) ? CRC32_POLY : 0);
-                                       }
-                               }
-
-                               /* only upper 6 bits (HASH_BITS) are used
-                                * which point to specific bit in he hash registers
-                                */
-                               hash = (crc >> (32 - HASH_BITS)) & 0x3f;
-
-                               if (hash > 31) {
-                                       tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-                                       tmp |= 1 << (hash - 32);
-                                       writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-                               } else {
-                                       tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-                                       tmp |= 1 << hash;
-                                       writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-                               }
+       tmp = readl(fep->hwp + FEC_R_CNTRL);
+       tmp &= ~0x8;
+       writel(tmp, fep->hwp + FEC_R_CNTRL);
+
+       if (dev->flags & IFF_ALLMULTI) {
+               /* Catch all multicast addresses, so set the
+                * filter to all 1's
+                */
+               writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+               writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+
+               return;
+       }
+
+       /* Clear filter and add the addresses in hash register
+        */
+       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+
+       dmi = dev->mc_list;
+
+       for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) {
+               /* Only support group multicast for now */
+               if (!(dmi->dmi_addr[0] & 1))
+                       continue;
+
+               /* calculate crc32 value of mac address */
+               crc = 0xffffffff;
+
+               for (i = 0; i < dmi->dmi_addrlen; i++) {
+                       data = dmi->dmi_addr[i];
+                       for (bit = 0; bit < 8; bit++, data >>= 1) {
+                               crc = (crc >> 1) ^
+                               (((crc ^ data) & 1) ? CRC32_POLY : 0);
                        }
                }
+
+               /* only upper 6 bits (HASH_BITS) are used
+                * which point to specific bit in he hash registers
+                */
+               hash = (crc >> (32 - HASH_BITS)) & 0x3f;
+
+               if (hash > 31) {
+                       tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+                       tmp |= 1 << (hash - 32);
+                       writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+               } else {
+                       tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+                       tmp |= 1 << hash;
+                       writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+               }
        }
 }
 
 /* Set a MAC change in hardware. */
-static void
-fec_set_mac_address(struct net_device *dev)
+static int
+fec_set_mac_address(struct net_device *dev, void *p)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
+       struct sockaddr *addr = p;
+
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
-       /* Set station address. */
        writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
                (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),
                fep->hwp + FEC_ADDR_LOW);
        writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24),
                fep + FEC_ADDR_HIGH);
+       return 0;
 }
 
+static const struct net_device_ops fec_netdev_ops = {
+       .ndo_open               = fec_enet_open,
+       .ndo_stop               = fec_enet_close,
+       .ndo_start_xmit         = fec_enet_start_xmit,
+       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_tx_timeout         = fec_timeout,
+       .ndo_set_mac_address    = fec_set_mac_address,
+};
+
  /*
   * XXX:  We need to clean up on failure exits here.
   *
   * index is only used in legacy code
   */
-int __init fec_enet_init(struct net_device *dev, int index)
+static int fec_enet_init(struct net_device *dev, int index)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
-       unsigned long   mem_addr;
-       struct bufdesc *bdp, *cbd_base;
-       int             i, j;
+       struct bufdesc *cbd_base;
+       int i;
 
        /* Allocate memory for buffer descriptors. */
        cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
@@ -1612,10 +1675,6 @@ int __init fec_enet_init(struct net_device *dev, int index)
        fep->hwp = (void __iomem *)dev->base_addr;
        fep->netdev = dev;
 
-       /* Whack a reset.  We should wait for this. */
-       writel(1, fep->hwp + FEC_ECNTRL);
-       udelay(10);
-
        /* Set the Ethernet address */
 #ifdef CONFIG_M5272
        fec_get_mac(dev);
@@ -1637,100 +1696,22 @@ int __init fec_enet_init(struct net_device *dev, int index)
        fep->rx_bd_base = cbd_base;
        fep->tx_bd_base = cbd_base + RX_RING_SIZE;
 
-       fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
-       fep->cur_rx = fep->rx_bd_base;
-
-       fep->skb_cur = fep->skb_dirty = 0;
-
-       /* Initialize the receive buffer descriptors. */
-       bdp = fep->rx_bd_base;
-       for (i=0; i<FEC_ENET_RX_PAGES; i++) {
-
-               /* Allocate a page */
-               mem_addr = __get_free_page(GFP_KERNEL);
-               /* XXX: missing check for allocation failure */
-
-               /* Initialize the BD for every fragment in the page */
-               for (j=0; j<FEC_ENET_RX_FRPPG; j++) {
-                       bdp->cbd_sc = BD_ENET_RX_EMPTY;
-                       bdp->cbd_bufaddr = __pa(mem_addr);
-                       mem_addr += FEC_ENET_RX_FRSIZE;
-                       bdp++;
-               }
-       }
-
-       /* Set the last buffer to wrap */
-       bdp--;
-       bdp->cbd_sc |= BD_SC_WRAP;
-
-       /* ...and the same for transmit */
-       bdp = fep->tx_bd_base;
-       for (i=0, j=FEC_ENET_TX_FRPPG; i<TX_RING_SIZE; i++) {
-               if (j >= FEC_ENET_TX_FRPPG) {
-                       mem_addr = __get_free_page(GFP_KERNEL);
-                       j = 1;
-               } else {
-                       mem_addr += FEC_ENET_TX_FRSIZE;
-                       j++;
-               }
-               fep->tx_bounce[i] = (unsigned char *) mem_addr;
-
-               /* Initialize the BD for every fragment in the page */
-               bdp->cbd_sc = 0;
-               bdp->cbd_bufaddr = 0;
-               bdp++;
-       }
-
-       /* Set the last buffer to wrap */
-       bdp--;
-       bdp->cbd_sc |= BD_SC_WRAP;
-
-       /* Set receive and transmit descriptor base */
-       writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
-       writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE,
-                       fep->hwp + FEC_X_DES_START);
-
 #ifdef HAVE_mii_link_interrupt
        fec_request_mii_intr(dev);
 #endif
-
-       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-       writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
-       writel(2, fep->hwp + FEC_ECNTRL);
-       writel(0, fep->hwp + FEC_R_DES_ACTIVE);
-#ifndef CONFIG_M5272
-       writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
-       writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
-#endif
-
        /* The FEC Ethernet specific entries in the device structure */
-       dev->open = fec_enet_open;
-       dev->hard_start_xmit = fec_enet_start_xmit;
-       dev->tx_timeout = fec_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
-       dev->stop = fec_enet_close;
-       dev->set_multicast_list = set_multicast_list;
+       dev->netdev_ops = &fec_netdev_ops;
 
        for (i=0; i<NMII-1; i++)
                mii_cmds[i].mii_next = &mii_cmds[i+1];
        mii_free = mii_cmds;
 
-       /* setup MII interface */
-       writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL);
-       writel(0, fep->hwp + FEC_X_CNTRL);
-
        /* Set MII speed to 2.5 MHz */
        fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999)
                                        / 2500000) / 2) & 0x3F) << 1;
-       writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
        fec_restart(dev, 0);
 
-       /* Clear and enable interrupts */
-       writel(0xffc00000, fep->hwp + FEC_IEVENT);
-       writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII,
-                       fep->hwp + FEC_IMASK);
-
        /* Queue up command to detect the PHY and initialize the
         * remainder of the interface.
         */
@@ -1759,12 +1740,13 @@ fec_restart(struct net_device *dev, int duplex)
        /* Clear any outstanding interrupt. */
        writel(0xffc00000, fep->hwp + FEC_IEVENT);
 
-       /* Set station address. */
-       fec_set_mac_address(dev);
-
        /* Reset all multicast. */
        writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
        writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+#ifndef CONFIG_M5272
+       writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
+       writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
+#endif
 
        /* Set maximum receive buffer size. */
        writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);