]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/davinci_emac.c
Merge branch 'master' into csb1725
[mv-sheeva.git] / drivers / net / davinci_emac.c
index 7fbd052ddb0a2b20e33bad64820fa9cc41dbbeb5..2a628d17d178f14a0167780c01c48b351c41550f 100644 (file)
@@ -63,6 +63,8 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 
+#include "davinci_cpdma.h"
+
 static int debug_level;
 module_param(debug_level, int, 0);
 MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)");
@@ -113,7 +115,7 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DEF_MAX_FRAME_SIZE                (1500 + 14 + 4 + 4)
 #define EMAC_DEF_TX_CH                 (0) /* Default 0th channel */
 #define EMAC_DEF_RX_CH                 (0) /* Default 0th channel */
-#define EMAC_DEF_MDIO_TICK_MS          (10) /* typically 1 tick=1 ms) */
+#define EMAC_DEF_RX_NUM_DESC           (128)
 #define EMAC_DEF_MAX_TX_CH             (1) /* Max TX channels configured */
 #define EMAC_DEF_MAX_RX_CH             (1) /* Max RX channels configured */
 #define EMAC_POLL_WEIGHT               (64) /* Default NAPI poll weight */
@@ -125,7 +127,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 /* EMAC register related defines */
 #define EMAC_ALL_MULTI_REG_VALUE       (0xFFFFFFFF)
 #define EMAC_NUM_MULTICAST_BITS                (64)
-#define EMAC_TEARDOWN_VALUE            (0xFFFFFFFC)
 #define EMAC_TX_CONTROL_TX_ENABLE_VAL  (0x1)
 #define EMAC_RX_CONTROL_RX_ENABLE_VAL  (0x1)
 #define EMAC_MAC_HOST_ERR_INTMASK_VAL  (0x2)
@@ -212,24 +213,10 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */
 
 /* EMAC Peripheral Device Register Memory Layout structure */
-#define EMAC_TXIDVER           0x0
-#define EMAC_TXCONTROL         0x4
-#define EMAC_TXTEARDOWN                0x8
-#define EMAC_RXIDVER           0x10
-#define EMAC_RXCONTROL         0x14
-#define EMAC_RXTEARDOWN                0x18
-#define EMAC_TXINTSTATRAW      0x80
-#define EMAC_TXINTSTATMASKED   0x84
-#define EMAC_TXINTMASKSET      0x88
-#define EMAC_TXINTMASKCLEAR    0x8C
 #define EMAC_MACINVECTOR       0x90
 
 #define EMAC_DM646X_MACEOIVECTOR       0x94
 
-#define EMAC_RXINTSTATRAW      0xA0
-#define EMAC_RXINTSTATMASKED   0xA4
-#define EMAC_RXINTMASKSET      0xA8
-#define EMAC_RXINTMASKCLEAR    0xAC
 #define EMAC_MACINTSTATRAW     0xB0
 #define EMAC_MACINTSTATMASKED  0xB4
 #define EMAC_MACINTMASKSET     0xB8
@@ -256,12 +243,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_MACADDRHI         0x504
 #define EMAC_MACINDEX          0x508
 
-/* EMAC HDP and Completion registors */
-#define EMAC_TXHDP(ch)         (0x600 + (ch * 4))
-#define EMAC_RXHDP(ch)         (0x620 + (ch * 4))
-#define EMAC_TXCP(ch)          (0x640 + (ch * 4))
-#define EMAC_RXCP(ch)          (0x660 + (ch * 4))
-
 /* EMAC statistics registers */
 #define EMAC_RXGOODFRAMES      0x200
 #define EMAC_RXBCASTFRAMES     0x204
@@ -303,25 +284,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DM644X_INTMIN_INTVL       0x1
 #define EMAC_DM644X_INTMAX_INTVL       (EMAC_DM644X_EWINTCNT_MASK)
 
-/* EMAC MDIO related */
-/* Mask & Control defines */
-#define MDIO_CONTROL_CLKDIV    (0xFF)
-#define MDIO_CONTROL_ENABLE    BIT(30)
-#define MDIO_USERACCESS_GO     BIT(31)
-#define MDIO_USERACCESS_WRITE  BIT(30)
-#define MDIO_USERACCESS_READ   (0)
-#define MDIO_USERACCESS_REGADR (0x1F << 21)
-#define MDIO_USERACCESS_PHYADR (0x1F << 16)
-#define MDIO_USERACCESS_DATA   (0xFFFF)
-#define MDIO_USERPHYSEL_LINKSEL        BIT(7)
-#define MDIO_VER_MODID         (0xFFFF << 16)
-#define MDIO_VER_REVMAJ                (0xFF   << 8)
-#define MDIO_VER_REVMIN                (0xFF)
-
-#define MDIO_USERACCESS(inst)  (0x80 + (inst * 8))
-#define MDIO_USERPHYSEL(inst)  (0x84 + (inst * 8))
-#define MDIO_CONTROL           (0x04)
-
 /* EMAC DM646X control module registers */
 #define EMAC_DM646X_CMINTCTRL  0x0C
 #define EMAC_DM646X_CMRXINTEN  0x14
@@ -345,120 +307,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 /* EMAC Stats Clear Mask */
 #define EMAC_STATS_CLR_MASK    (0xFFFFFFFF)
 
-/** net_buf_obj: EMAC network bufferdata structure
- *
- * EMAC network buffer data structure
- */
-struct emac_netbufobj {
-       void *buf_token;
-       char *data_ptr;
-       int length;
-};
-
-/** net_pkt_obj: EMAC network packet data structure
- *
- * EMAC network packet data structure - supports buffer list (for future)
- */
-struct emac_netpktobj {
-       void *pkt_token; /* data token may hold tx/rx chan id */
-       struct emac_netbufobj *buf_list; /* array of network buffer objects */
-       int num_bufs;
-       int pkt_length;
-};
-
-/** emac_tx_bd: EMAC TX Buffer descriptor data structure
- *
- * EMAC TX Buffer descriptor data structure
- */
-struct emac_tx_bd {
-       int h_next;
-       int buff_ptr;
-       int off_b_len;
-       int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */
-       struct emac_tx_bd __iomem *next;
-       void *buf_token;
-};
-
-/** emac_txch: EMAC TX Channel data structure
- *
- * EMAC TX Channel data structure
- */
-struct emac_txch {
-       /* Config related */
-       u32 num_bd;
-       u32 service_max;
-
-       /* CPPI specific */
-       u32 alloc_size;
-       void __iomem *bd_mem;
-       struct emac_tx_bd __iomem *bd_pool_head;
-       struct emac_tx_bd __iomem *active_queue_head;
-       struct emac_tx_bd __iomem *active_queue_tail;
-       struct emac_tx_bd __iomem *last_hw_bdprocessed;
-       u32 queue_active;
-       u32 teardown_pending;
-       u32 *tx_complete;
-
-       /** statistics */
-       u32 proc_count;     /* TX: # of times emac_tx_bdproc is called */
-       u32 mis_queued_packets;
-       u32 queue_reinit;
-       u32 end_of_queue_add;
-       u32 out_of_tx_bd;
-       u32 no_active_pkts; /* IRQ when there were no packets to process */
-       u32 active_queue_count;
-};
-
-/** emac_rx_bd: EMAC RX Buffer descriptor data structure
- *
- * EMAC RX Buffer descriptor data structure
- */
-struct emac_rx_bd {
-       int h_next;
-       int buff_ptr;
-       int off_b_len;
-       int mode;
-       struct emac_rx_bd __iomem *next;
-       void *data_ptr;
-       void *buf_token;
-};
-
-/** emac_rxch: EMAC RX Channel data structure
- *
- * EMAC RX Channel data structure
- */
-struct emac_rxch {
-       /* configuration info */
-       u32 num_bd;
-       u32 service_max;
-       u32 buf_size;
-       char mac_addr[6];
-
-       /** CPPI specific */
-       u32 alloc_size;
-       void __iomem *bd_mem;
-       struct emac_rx_bd __iomem *bd_pool_head;
-       struct emac_rx_bd __iomem *active_queue_head;
-       struct emac_rx_bd __iomem *active_queue_tail;
-       u32 queue_active;
-       u32 teardown_pending;
-
-       /* packet and buffer objects */
-       struct emac_netpktobj pkt_queue;
-       struct emac_netbufobj buf_queue;
-
-       /** statistics */
-       u32 proc_count; /* number of times emac_rx_bdproc is called */
-       u32 processed_bd;
-       u32 recycled_bd;
-       u32 out_of_rx_bd;
-       u32 out_of_rx_buffers;
-       u32 queue_reinit;
-       u32 end_of_queue_add;
-       u32 end_of_queue;
-       u32 mis_queued_packets;
-};
-
 /* emac_priv: EMAC private data structure
  *
  * EMAC adapter private data structure
@@ -469,17 +317,13 @@ struct emac_priv {
        struct platform_device *pdev;
        struct napi_struct napi;
        char mac_addr[6];
-       spinlock_t tx_lock;
-       spinlock_t rx_lock;
        void __iomem *remap_addr;
        u32 emac_base_phys;
        void __iomem *emac_base;
        void __iomem *ctrl_base;
-       void __iomem *emac_ctrl_ram;
-       u32 ctrl_ram_size;
-       u32 hw_ram_addr;
-       struct emac_txch *txch[EMAC_DEF_MAX_TX_CH];
-       struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH];
+       struct cpdma_ctlr *dma;
+       struct cpdma_chan *txchan;
+       struct cpdma_chan *rxchan;
        u32 link; /* 1=link on, 0=link off */
        u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */
        u32 duplex; /* Link duplex: 0=Half, 1=Full */
@@ -493,13 +337,7 @@ struct emac_priv {
        u32 mac_hash2;
        u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
        u32 rx_addr_type;
-       /* periodic timer required for MDIO polling */
-       struct timer_list periodic_timer;
-       u32 periodic_ticks;
-       u32 timer_active;
-       u32 phy_mask;
-       /* mii_bus,phy members */
-       struct mii_bus *mii_bus;
+       const char *phy_id;
        struct phy_device *phydev;
        spinlock_t lock;
        /*platform specific members*/
@@ -510,19 +348,6 @@ struct emac_priv {
 /* clock frequency for EMAC */
 static struct clk *emac_clk;
 static unsigned long emac_bus_frequency;
-static unsigned long mdio_max_freq;
-
-#define emac_virt_to_phys(addr, priv) \
-       (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \
-       + priv->hw_ram_addr)
-
-/* Cache macros - Packet buffers would be from skb pool which is cached */
-#define EMAC_VIRT_NOCACHE(addr) (addr)
-
-/* DM644x does not have BD's in cached memory - so no cache functions */
-#define BD_CACHE_INVALIDATE(addr, size)
-#define BD_CACHE_WRITEBACK(addr, size)
-#define BD_CACHE_WRITEBACK_INVALIDATE(addr, size)
 
 /* EMAC TX Host Error description strings */
 static char *emac_txhost_errcodes[16] = {
@@ -548,9 +373,6 @@ static char *emac_rxhost_errcodes[16] = {
 #define emac_ctrl_read(reg)      ioread32((priv->ctrl_base + (reg)))
 #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg)))
 
-#define emac_mdio_read(reg)      ioread32(bus->priv + (reg))
-#define emac_mdio_write(reg, val) iowrite32(val, (bus->priv + (reg)))
-
 /**
  * emac_dump_regs: Dump important EMAC registers to debug terminal
  * @priv: The DaVinci EMAC private adapter structure
@@ -569,20 +391,6 @@ static void emac_dump_regs(struct emac_priv *priv)
                        emac_ctrl_read(EMAC_CTRL_EWCTL),
                        emac_ctrl_read(EMAC_CTRL_EWINTTCNT));
        }
-       dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n",
-               emac_read(EMAC_TXIDVER),
-               ((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"),
-               emac_read(EMAC_RXIDVER),
-               ((emac_read(EMAC_RXCONTROL)) ? "enabled" : "disabled"));
-       dev_info(emac_dev, "EMAC: TXIntRaw:%08X, TxIntMasked: %08X, "\
-               "TxIntMasSet: %08X\n", emac_read(EMAC_TXINTSTATRAW),
-               emac_read(EMAC_TXINTSTATMASKED), emac_read(EMAC_TXINTMASKSET));
-       dev_info(emac_dev, "EMAC: RXIntRaw:%08X, RxIntMasked: %08X, "\
-               "RxIntMasSet: %08X\n", emac_read(EMAC_RXINTSTATRAW),
-               emac_read(EMAC_RXINTSTATMASKED), emac_read(EMAC_RXINTMASKSET));
-       dev_info(emac_dev, "EMAC: MacIntRaw:%08X, MacIntMasked: %08X, "\
-               "MacInVector=%08X\n", emac_read(EMAC_MACINTSTATRAW),
-               emac_read(EMAC_MACINTSTATMASKED), emac_read(EMAC_MACINVECTOR));
        dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n",
                emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL));
        dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\
@@ -591,8 +399,6 @@ static void emac_dump_regs(struct emac_priv *priv)
        dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\
                "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL),
                emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG));
-       dev_info(emac_dev, "EMAC: TXHDP[0]:%08X, RXHDP[0]: %08X\n",
-               emac_read(EMAC_TXHDP(0)), emac_read(EMAC_RXHDP(0)));
        dev_info(emac_dev, "EMAC Statistics\n");
        dev_info(emac_dev, "EMAC: rx_good_frames:%d\n",
                emac_read(EMAC_RXGOODFRAMES));
@@ -654,11 +460,10 @@ static void emac_dump_regs(struct emac_priv *priv)
                emac_read(EMAC_RXMOFOVERRUNS));
        dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n",
                emac_read(EMAC_RXDMAOVERRUNS));
+
+       cpdma_ctlr_dump(priv->dma);
 }
 
-/*************************************************************************
- *  EMAC MDIO/Phy Functionality
- *************************************************************************/
 /**
  * emac_get_drvinfo: Get EMAC driver information
  * @ndev: The DaVinci EMAC network adapter
@@ -686,7 +491,7 @@ static int emac_get_settings(struct net_device *ndev,
                             struct ethtool_cmd *ecmd)
 {
        struct emac_priv *priv = netdev_priv(ndev);
-       if (priv->phy_mask)
+       if (priv->phydev)
                return phy_ethtool_gset(priv->phydev, ecmd);
        else
                return -EOPNOTSUPP;
@@ -704,7 +509,7 @@ static int emac_get_settings(struct net_device *ndev,
 static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
 {
        struct emac_priv *priv = netdev_priv(ndev);
-       if (priv->phy_mask)
+       if (priv->phydev)
                return phy_ethtool_sset(priv->phydev, ecmd);
        else
                return -EOPNOTSUPP;
@@ -841,7 +646,7 @@ static void emac_update_phystatus(struct emac_priv *priv)
        mac_control = emac_read(EMAC_MACCONTROL);
        cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ?
                        DUPLEX_FULL : DUPLEX_HALF;
-       if (priv->phy_mask)
+       if (priv->phydev)
                new_duplex = priv->phydev->duplex;
        else
                new_duplex = DUPLEX_FULL;
@@ -1184,371 +989,68 @@ static irqreturn_t emac_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-/** EMAC on-chip buffer descriptor memory
- *
- * WARNING: Please note that the on chip memory is used for both TX and RX
- * buffer descriptor queues and is equally divided between TX and RX desc's
- * If the number of TX or RX descriptors change this memory pointers need
- * to be adjusted. If external memory is allocated then these pointers can
- * pointer to the memory
- *
- */
-#define EMAC_TX_BD_MEM(priv)   ((priv)->emac_ctrl_ram)
-#define EMAC_RX_BD_MEM(priv)   ((priv)->emac_ctrl_ram + \
-                               (((priv)->ctrl_ram_size) >> 1))
-
-/**
- * emac_init_txch: TX channel initialization
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device init to setup a TX channel (allocate buffer desc
- * create free pool and keep ready for transmission
- *
- * Returns success(0) or mem alloc failures error code
- */
-static int emac_init_txch(struct emac_priv *priv, u32 ch)
-{
-       struct device *emac_dev = &priv->ndev->dev;
-       u32 cnt, bd_size;
-       void __iomem *mem;
-       struct emac_tx_bd __iomem *curr_bd;
-       struct emac_txch *txch = NULL;
-
-       txch = kzalloc(sizeof(struct emac_txch), GFP_KERNEL);
-       if (NULL == txch) {
-               dev_err(emac_dev, "DaVinci EMAC: TX Ch mem alloc failed");
-               return -ENOMEM;
-       }
-       priv->txch[ch] = txch;
-       txch->service_max = EMAC_DEF_TX_MAX_SERVICE;
-       txch->active_queue_head = NULL;
-       txch->active_queue_tail = NULL;
-       txch->queue_active = 0;
-       txch->teardown_pending = 0;
-
-       /* allocate memory for TX CPPI channel on a 4 byte boundry */
-       txch->tx_complete = kzalloc(txch->service_max * sizeof(u32),
-                                   GFP_KERNEL);
-       if (NULL == txch->tx_complete) {
-               dev_err(emac_dev, "DaVinci EMAC: Tx service mem alloc failed");
-               kfree(txch);
-               return -ENOMEM;
-       }
-
-       /* allocate buffer descriptor pool align every BD on four word
-        * boundry for future requirements */
-       bd_size = (sizeof(struct emac_tx_bd) + 0xF) & ~0xF;
-       txch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size;
-       txch->alloc_size = (((bd_size * txch->num_bd) + 0xF) & ~0xF);
-
-       /* alloc TX BD memory */
-       txch->bd_mem = EMAC_TX_BD_MEM(priv);
-       __memzero((void __force *)txch->bd_mem, txch->alloc_size);
-
-       /* initialize the BD linked list */
-       mem = (void __force __iomem *)
-                       (((u32 __force) txch->bd_mem + 0xF) & ~0xF);
-       txch->bd_pool_head = NULL;
-       for (cnt = 0; cnt < txch->num_bd; cnt++) {
-               curr_bd = mem + (cnt * bd_size);
-               curr_bd->next = txch->bd_pool_head;
-               txch->bd_pool_head = curr_bd;
-       }
-
-       /* reset statistics counters */
-       txch->out_of_tx_bd = 0;
-       txch->no_active_pkts = 0;
-       txch->active_queue_count = 0;
-
-       return 0;
-}
-
-/**
- * emac_cleanup_txch: Book-keep function to clean TX channel resources
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number
- *
- * Called to clean up TX channel resources
- *
- */
-static void emac_cleanup_txch(struct emac_priv *priv, u32 ch)
+static struct sk_buff *emac_rx_alloc(struct emac_priv *priv)
 {
-       struct emac_txch *txch = priv->txch[ch];
-
-       if (txch) {
-               if (txch->bd_mem)
-                       txch->bd_mem = NULL;
-               kfree(txch->tx_complete);
-               kfree(txch);
-               priv->txch[ch] = NULL;
-       }
+       struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size);
+       if (WARN_ON(!skb))
+               return NULL;
+       skb->dev = priv->ndev;
+       skb_reserve(skb, NET_IP_ALIGN);
+       return skb;
 }
 
-/**
- * emac_net_tx_complete: TX packet completion function
- * @priv: The DaVinci EMAC private adapter structure
- * @net_data_tokens: packet token - skb pointer
- * @num_tokens: number of skb's to free
- * @ch: TX channel number
- *
- * Frees the skb once packet is transmitted
- *
- */
-static int emac_net_tx_complete(struct emac_priv *priv,
-                               void **net_data_tokens,
-                               int num_tokens, u32 ch)
+static void emac_rx_handler(void *token, int len, int status)
 {
-       struct net_device *ndev = priv->ndev;
-       u32 cnt;
-
-       if (unlikely(num_tokens && netif_queue_stopped(ndev)))
-               netif_start_queue(ndev);
-       for (cnt = 0; cnt < num_tokens; cnt++) {
-               struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt];
-               if (skb == NULL)
-                       continue;
-               ndev->stats.tx_packets++;
-               ndev->stats.tx_bytes += skb->len;
+       struct sk_buff          *skb = token;
+       struct net_device       *ndev = skb->dev;
+       struct emac_priv        *priv = netdev_priv(ndev);
+       struct device           *emac_dev = &ndev->dev;
+       int                     ret;
+
+       /* free and bail if we are shutting down */
+       if (unlikely(!netif_running(ndev))) {
                dev_kfree_skb_any(skb);
+               return;
        }
-       return 0;
-}
-
-/**
- * emac_txch_teardown: TX channel teardown
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number
- *
- * Called to teardown TX channel
- *
- */
-static void emac_txch_teardown(struct emac_priv *priv, u32 ch)
-{
-       struct device *emac_dev = &priv->ndev->dev;
-       u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */
-       struct emac_txch *txch = priv->txch[ch];
-       struct emac_tx_bd __iomem *curr_bd;
-
-       while ((emac_read(EMAC_TXCP(ch)) & EMAC_TEARDOWN_VALUE) !=
-              EMAC_TEARDOWN_VALUE) {
-               /* wait till tx teardown complete */
-               cpu_relax(); /* TODO: check if this helps ... */
-               --teardown_cnt;
-               if (0 == teardown_cnt) {
-                       dev_err(emac_dev, "EMAC: TX teardown aborted\n");
-                       break;
-               }
-       }
-       emac_write(EMAC_TXCP(ch), EMAC_TEARDOWN_VALUE);
-
-       /* process sent packets and return skb's to upper layer */
-       if (1 == txch->queue_active) {
-               curr_bd = txch->active_queue_head;
-               while (curr_bd != NULL) {
-                       dma_unmap_single(emac_dev, curr_bd->buff_ptr,
-                               curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
-                               DMA_TO_DEVICE);
-
-                       emac_net_tx_complete(priv, (void __force *)
-                                       &curr_bd->buf_token, 1, ch);
-                       if (curr_bd != txch->active_queue_tail)
-                               curr_bd = curr_bd->next;
-                       else
-                               break;
-               }
-               txch->bd_pool_head = txch->active_queue_head;
-               txch->active_queue_head =
-               txch->active_queue_tail = NULL;
-       }
-}
 
-/**
- * emac_stop_txch: Stop TX channel operation
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number
- *
- * Called to stop TX channel operation
- *
- */
-static void emac_stop_txch(struct emac_priv *priv, u32 ch)
-{
-       struct emac_txch *txch = priv->txch[ch];
-
-       if (txch) {
-               txch->teardown_pending = 1;
-               emac_write(EMAC_TXTEARDOWN, 0);
-               emac_txch_teardown(priv, ch);
-               txch->teardown_pending = 0;
-               emac_write(EMAC_TXINTMASKCLEAR, BIT(ch));
+       /* recycle on recieve error */
+       if (status < 0) {
+               ndev->stats.rx_errors++;
+               goto recycle;
        }
-}
 
-/**
- * emac_tx_bdproc: TX buffer descriptor (packet) processing
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number to process buffer descriptors for
- * @budget: number of packets allowed to process
- * @pending: indication to caller that packets are pending to process
- *
- * Processes TX buffer descriptors after packets are transmitted - checks
- * ownership bit on the TX * descriptor and requeues it to free pool & frees
- * the SKB buffer. Only "budget" number of packets are processed and
- * indication of pending packets provided to the caller
- *
- * Returns number of packets processed
- */
-static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
-{
-       struct device *emac_dev = &priv->ndev->dev;
-       unsigned long flags;
-       u32 frame_status;
-       u32 pkts_processed = 0;
-       u32 tx_complete_cnt = 0;
-       struct emac_tx_bd __iomem *curr_bd;
-       struct emac_txch *txch = priv->txch[ch];
-       u32 *tx_complete_ptr = txch->tx_complete;
-
-       if (unlikely(1 == txch->teardown_pending)) {
-               if (netif_msg_tx_err(priv) && net_ratelimit()) {
-                       dev_err(emac_dev, "DaVinci EMAC:emac_tx_bdproc: "\
-                               "teardown pending\n");
-               }
-               return 0;  /* dont handle any pkt completions */
-       }
+       /* feed received packet up the stack */
+       skb_put(skb, len);
+       skb->protocol = eth_type_trans(skb, ndev);
+       netif_receive_skb(skb);
+       ndev->stats.rx_bytes += len;
+       ndev->stats.rx_packets++;
 
-       ++txch->proc_count;
-       spin_lock_irqsave(&priv->tx_lock, flags);
-       curr_bd = txch->active_queue_head;
-       if (NULL == curr_bd) {
-               emac_write(EMAC_TXCP(ch),
-                          emac_virt_to_phys(txch->last_hw_bdprocessed, priv));
-               txch->no_active_pkts++;
-               spin_unlock_irqrestore(&priv->tx_lock, flags);
-               return 0;
+       /* alloc a new packet for receive */
+       skb = emac_rx_alloc(priv);
+       if (!skb) {
+               if (netif_msg_rx_err(priv) && net_ratelimit())
+                       dev_err(emac_dev, "failed rx buffer alloc\n");
+               return;
        }
-       BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-       frame_status = curr_bd->mode;
-       while ((curr_bd) &&
-             ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
-             (pkts_processed < budget)) {
-               emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv));
-               txch->active_queue_head = curr_bd->next;
-               if (frame_status & EMAC_CPPI_EOQ_BIT) {
-                       if (curr_bd->next) {    /* misqueued packet */
-                               emac_write(EMAC_TXHDP(ch), curr_bd->h_next);
-                               ++txch->mis_queued_packets;
-                       } else {
-                               txch->queue_active = 0; /* end of queue */
-                       }
-               }
 
-               dma_unmap_single(emac_dev, curr_bd->buff_ptr,
-                               curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
-                               DMA_TO_DEVICE);
-
-               *tx_complete_ptr = (u32) curr_bd->buf_token;
-               ++tx_complete_ptr;
-               ++tx_complete_cnt;
-               curr_bd->next = txch->bd_pool_head;
-               txch->bd_pool_head = curr_bd;
-               --txch->active_queue_count;
-               pkts_processed++;
-               txch->last_hw_bdprocessed = curr_bd;
-               curr_bd = txch->active_queue_head;
-               if (curr_bd) {
-                       BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-                       frame_status = curr_bd->mode;
-               }
-       } /* end of pkt processing loop */
-
-       emac_net_tx_complete(priv,
-                            (void *)&txch->tx_complete[0],
-                            tx_complete_cnt, ch);
-       spin_unlock_irqrestore(&priv->tx_lock, flags);
-       return pkts_processed;
+recycle:
+       ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
+                       skb_tailroom(skb), GFP_KERNEL);
+       if (WARN_ON(ret < 0))
+               dev_kfree_skb_any(skb);
 }
 
-#define EMAC_ERR_TX_OUT_OF_BD -1
-
-/**
- * emac_send: EMAC Transmit function (internal)
- * @priv: The DaVinci EMAC private adapter structure
- * @pkt: packet pointer (contains skb ptr)
- * @ch: TX channel number
- *
- * Called by the transmit function to queue the packet in EMAC hardware queue
- *
- * Returns success(0) or error code (typically out of desc's)
- */
-static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch)
+static void emac_tx_handler(void *token, int len, int status)
 {
-       unsigned long flags;
-       struct emac_tx_bd __iomem *curr_bd;
-       struct emac_txch *txch;
-       struct emac_netbufobj *buf_list;
-
-       txch = priv->txch[ch];
-       buf_list = pkt->buf_list;   /* get handle to the buffer array */
-
-       /* check packet size and pad if short */
-       if (pkt->pkt_length < EMAC_DEF_MIN_ETHPKTSIZE) {
-               buf_list->length += (EMAC_DEF_MIN_ETHPKTSIZE - pkt->pkt_length);
-               pkt->pkt_length = EMAC_DEF_MIN_ETHPKTSIZE;
-       }
+       struct sk_buff          *skb = token;
+       struct net_device       *ndev = skb->dev;
 
-       spin_lock_irqsave(&priv->tx_lock, flags);
-       curr_bd = txch->bd_pool_head;
-       if (curr_bd == NULL) {
-               txch->out_of_tx_bd++;
-               spin_unlock_irqrestore(&priv->tx_lock, flags);
-               return EMAC_ERR_TX_OUT_OF_BD;
-       }
-
-       txch->bd_pool_head = curr_bd->next;
-       curr_bd->buf_token = buf_list->buf_token;
-       curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buf_list->data_ptr,
-                       buf_list->length, DMA_TO_DEVICE);
-       curr_bd->off_b_len = buf_list->length;
-       curr_bd->h_next = 0;
-       curr_bd->next = NULL;
-       curr_bd->mode = (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT |
-                        EMAC_CPPI_EOP_BIT | pkt->pkt_length);
-
-       /* flush the packet from cache if write back cache is present */
-       BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-
-       /* send the packet */
-       if (txch->active_queue_head == NULL) {
-               txch->active_queue_head = curr_bd;
-               txch->active_queue_tail = curr_bd;
-               if (1 != txch->queue_active) {
-                       emac_write(EMAC_TXHDP(ch),
-                                       emac_virt_to_phys(curr_bd, priv));
-                       txch->queue_active = 1;
-               }
-               ++txch->queue_reinit;
-       } else {
-               register struct emac_tx_bd __iomem *tail_bd;
-               register u32 frame_status;
-
-               tail_bd = txch->active_queue_tail;
-               tail_bd->next = curr_bd;
-               txch->active_queue_tail = curr_bd;
-               tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
-               tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv);
-               frame_status = tail_bd->mode;
-               if (frame_status & EMAC_CPPI_EOQ_BIT) {
-                       emac_write(EMAC_TXHDP(ch),
-                               emac_virt_to_phys(curr_bd, priv));
-                       frame_status &= ~(EMAC_CPPI_EOQ_BIT);
-                       tail_bd->mode = frame_status;
-                       ++txch->end_of_queue_add;
-               }
-       }
-       txch->active_queue_count++;
-       spin_unlock_irqrestore(&priv->tx_lock, flags);
-       return 0;
+       if (unlikely(netif_queue_stopped(ndev)))
+               netif_start_queue(ndev);
+       ndev->stats.tx_packets++;
+       ndev->stats.tx_bytes += len;
+       dev_kfree_skb_any(skb);
 }
 
 /**
@@ -1565,42 +1067,36 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
        struct device *emac_dev = &ndev->dev;
        int ret_code;
-       struct emac_netbufobj tx_buf; /* buffer obj-only single frame support */
-       struct emac_netpktobj tx_packet;  /* packet object */
        struct emac_priv *priv = netdev_priv(ndev);
 
        /* If no link, return */
        if (unlikely(!priv->link)) {
                if (netif_msg_tx_err(priv) && net_ratelimit())
                        dev_err(emac_dev, "DaVinci EMAC: No link to transmit");
-               return NETDEV_TX_BUSY;
+               goto fail_tx;
+       }
+
+       ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE);
+       if (unlikely(ret_code < 0)) {
+               if (netif_msg_tx_err(priv) && net_ratelimit())
+                       dev_err(emac_dev, "DaVinci EMAC: packet pad failed");
+               goto fail_tx;
        }
 
-       /* Build the buffer and packet objects - Since only single fragment is
-        * supported, need not set length and token in both packet & object.
-        * Doing so for completeness sake & to show that this needs to be done
-        * in multifragment case
-        */
-       tx_packet.buf_list = &tx_buf;
-       tx_packet.num_bufs = 1; /* only single fragment supported */
-       tx_packet.pkt_length = skb->len;
-       tx_packet.pkt_token = (void *)skb;
-       tx_buf.length = skb->len;
-       tx_buf.buf_token = (void *)skb;
-       tx_buf.data_ptr = skb->data;
-       ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH);
+       ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len,
+                                    GFP_KERNEL);
        if (unlikely(ret_code != 0)) {
-               if (ret_code == EMAC_ERR_TX_OUT_OF_BD) {
-                       if (netif_msg_tx_err(priv) && net_ratelimit())
-                               dev_err(emac_dev, "DaVinci EMAC: xmit() fatal"\
-                                       " err. Out of TX BD's");
-                       netif_stop_queue(priv->ndev);
-               }
-               ndev->stats.tx_dropped++;
-               return NETDEV_TX_BUSY;
+               if (netif_msg_tx_err(priv) && net_ratelimit())
+                       dev_err(emac_dev, "DaVinci EMAC: desc submit failed");
+               goto fail_tx;
        }
 
        return NETDEV_TX_OK;
+
+fail_tx:
+       ndev->stats.tx_dropped++;
+       netif_stop_queue(ndev);
+       return NETDEV_TX_BUSY;
 }
 
 /**
@@ -1621,217 +1117,15 @@ static void emac_dev_tx_timeout(struct net_device *ndev)
        if (netif_msg_tx_err(priv))
                dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX");
 
+       emac_dump_regs(priv);
+
        ndev->stats.tx_errors++;
        emac_int_disable(priv);
-       emac_stop_txch(priv, EMAC_DEF_TX_CH);
-       emac_cleanup_txch(priv, EMAC_DEF_TX_CH);
-       emac_init_txch(priv, EMAC_DEF_TX_CH);
-       emac_write(EMAC_TXHDP(0), 0);
-       emac_write(EMAC_TXINTMASKSET, BIT(EMAC_DEF_TX_CH));
+       cpdma_chan_stop(priv->txchan);
+       cpdma_chan_start(priv->txchan);
        emac_int_enable(priv);
 }
 
-/**
- * emac_net_alloc_rx_buf: Allocate a skb for RX
- * @priv: The DaVinci EMAC private adapter structure
- * @buf_size: size of SKB data buffer to allocate
- * @data_token: data token returned (skb handle for storing in buffer desc)
- * @ch: RX channel number
- *
- * Called during RX channel setup - allocates skb buffer of required size
- * and provides the skb handle and allocated buffer data pointer to caller
- *
- * Returns skb data pointer or 0 on failure to alloc skb
- */
-static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size,
-               void **data_token, u32 ch)
-{
-       struct net_device *ndev = priv->ndev;
-       struct device *emac_dev = &ndev->dev;
-       struct sk_buff *p_skb;
-
-       p_skb = dev_alloc_skb(buf_size);
-       if (unlikely(NULL == p_skb)) {
-               if (netif_msg_rx_err(priv) && net_ratelimit())
-                       dev_err(emac_dev, "DaVinci EMAC: failed to alloc skb");
-               return NULL;
-       }
-
-       /* set device pointer in skb and reserve space for extra bytes */
-       p_skb->dev = ndev;
-       skb_reserve(p_skb, NET_IP_ALIGN);
-       *data_token = (void *) p_skb;
-       return p_skb->data;
-}
-
-/**
- * emac_init_rxch: RX channel initialization
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- * @param: mac address for RX channel
- *
- * Called during device init to setup a RX channel (allocate buffers and
- * buffer descriptors, create queue and keep ready for reception
- *
- * Returns success(0) or mem alloc failures error code
- */
-static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param)
-{
-       struct device *emac_dev = &priv->ndev->dev;
-       u32 cnt, bd_size;
-       void __iomem *mem;
-       struct emac_rx_bd __iomem *curr_bd;
-       struct emac_rxch *rxch = NULL;
-
-       rxch = kzalloc(sizeof(struct emac_rxch), GFP_KERNEL);
-       if (NULL == rxch) {
-               dev_err(emac_dev, "DaVinci EMAC: RX Ch mem alloc failed");
-               return -ENOMEM;
-       }
-       priv->rxch[ch] = rxch;
-       rxch->buf_size = priv->rx_buf_size;
-       rxch->service_max = EMAC_DEF_RX_MAX_SERVICE;
-       rxch->queue_active = 0;
-       rxch->teardown_pending = 0;
-
-       /* save mac address */
-       for (cnt = 0; cnt < 6; cnt++)
-               rxch->mac_addr[cnt] = param[cnt];
-
-       /* allocate buffer descriptor pool align every BD on four word
-        * boundry for future requirements */
-       bd_size = (sizeof(struct emac_rx_bd) + 0xF) & ~0xF;
-       rxch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size;
-       rxch->alloc_size = (((bd_size * rxch->num_bd) + 0xF) & ~0xF);
-       rxch->bd_mem = EMAC_RX_BD_MEM(priv);
-       __memzero((void __force *)rxch->bd_mem, rxch->alloc_size);
-       rxch->pkt_queue.buf_list = &rxch->buf_queue;
-
-       /* allocate RX buffer and initialize the BD linked list */
-       mem = (void __force __iomem *)
-                       (((u32 __force) rxch->bd_mem + 0xF) & ~0xF);
-       rxch->active_queue_head = NULL;
-       rxch->active_queue_tail = mem;
-       for (cnt = 0; cnt < rxch->num_bd; cnt++) {
-               curr_bd = mem + (cnt * bd_size);
-               /* for future use the last parameter contains the BD ptr */
-               curr_bd->data_ptr = emac_net_alloc_rx_buf(priv,
-                                   rxch->buf_size,
-                                   (void __force **)&curr_bd->buf_token,
-                                   EMAC_DEF_RX_CH);
-               if (curr_bd->data_ptr == NULL) {
-                       dev_err(emac_dev, "DaVinci EMAC: RX buf mem alloc " \
-                               "failed for ch %d\n", ch);
-                       kfree(rxch);
-                       return -ENOMEM;
-               }
-
-               /* populate the hardware descriptor */
-               curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head,
-                               priv);
-               curr_bd->buff_ptr = dma_map_single(emac_dev, curr_bd->data_ptr,
-                               rxch->buf_size, DMA_FROM_DEVICE);
-               curr_bd->off_b_len = rxch->buf_size;
-               curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
-
-               /* write back to hardware memory */
-               BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd,
-                                             EMAC_BD_LENGTH_FOR_CACHE);
-               curr_bd->next = rxch->active_queue_head;
-               rxch->active_queue_head = curr_bd;
-       }
-
-       /* At this point rxCppi->activeQueueHead points to the first
-          RX BD ready to be given to RX HDP and rxch->active_queue_tail
-          points to the last RX BD
-        */
-       return 0;
-}
-
-/**
- * emac_rxch_teardown: RX channel teardown
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device stop to teardown RX channel
- *
- */
-static void emac_rxch_teardown(struct emac_priv *priv, u32 ch)
-{
-       struct device *emac_dev = &priv->ndev->dev;
-       u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */
-
-       while ((emac_read(EMAC_RXCP(ch)) & EMAC_TEARDOWN_VALUE) !=
-              EMAC_TEARDOWN_VALUE) {
-               /* wait till tx teardown complete */
-               cpu_relax(); /* TODO: check if this helps ... */
-               --teardown_cnt;
-               if (0 == teardown_cnt) {
-                       dev_err(emac_dev, "EMAC: RX teardown aborted\n");
-                       break;
-               }
-       }
-       emac_write(EMAC_RXCP(ch), EMAC_TEARDOWN_VALUE);
-}
-
-/**
- * emac_stop_rxch: Stop RX channel operation
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device stop to stop RX channel operation
- *
- */
-static void emac_stop_rxch(struct emac_priv *priv, u32 ch)
-{
-       struct emac_rxch *rxch = priv->rxch[ch];
-
-       if (rxch) {
-               rxch->teardown_pending = 1;
-               emac_write(EMAC_RXTEARDOWN, ch);
-               /* wait for teardown complete */
-               emac_rxch_teardown(priv, ch);
-               rxch->teardown_pending = 0;
-               emac_write(EMAC_RXINTMASKCLEAR, BIT(ch));
-       }
-}
-
-/**
- * emac_cleanup_rxch: Book-keep function to clean RX channel resources
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device stop to clean up RX channel resources
- *
- */
-static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch)
-{
-       struct emac_rxch *rxch = priv->rxch[ch];
-       struct emac_rx_bd __iomem *curr_bd;
-
-       if (rxch) {
-               /* free the receive buffers previously allocated */
-               curr_bd = rxch->active_queue_head;
-               while (curr_bd) {
-                       if (curr_bd->buf_token) {
-                               dma_unmap_single(&priv->ndev->dev,
-                                       curr_bd->buff_ptr,
-                                       curr_bd->off_b_len
-                                               & EMAC_RX_BD_BUF_SIZE,
-                                       DMA_FROM_DEVICE);
-
-                               dev_kfree_skb_any((struct sk_buff *)\
-                                                 curr_bd->buf_token);
-                       }
-                       curr_bd = curr_bd->next;
-               }
-               if (rxch->bd_mem)
-                       rxch->bd_mem = NULL;
-               kfree(rxch);
-               priv->rxch[ch] = NULL;
-       }
-}
-
 /**
  * emac_set_type0addr: Set EMAC Type0 mac address
  * @priv: The DaVinci EMAC private adapter structure
@@ -1948,7 +1242,6 @@ static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr)
 static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
 {
        struct emac_priv *priv = netdev_priv(ndev);
-       struct emac_rxch *rxch = priv->rxch[EMAC_DEF_RX_CH];
        struct device *emac_dev = &priv->ndev->dev;
        struct sockaddr *sa = addr;
 
@@ -1959,11 +1252,10 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
        memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
        memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len);
 
-       /* If the interface is down - rxch is NULL. */
        /* MAC address is configured only after the interface is enabled. */
        if (netif_running(ndev)) {
-               memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len);
-               emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr);
+               memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
+               emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr);
        }
 
        if (netif_msg_drv(priv))
@@ -1973,194 +1265,6 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
        return 0;
 }
 
-/**
- * emac_addbd_to_rx_queue: Recycle RX buffer descriptor
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number to process buffer descriptors for
- * @curr_bd: current buffer descriptor
- * @buffer: buffer pointer for descriptor
- * @buf_token: buffer token (stores skb information)
- *
- * Prepares the recycled buffer descriptor and addes it to hardware
- * receive queue - if queue empty this descriptor becomes the head
- * else addes the descriptor to end of queue
- *
- */
-static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch,
-               struct emac_rx_bd __iomem *curr_bd,
-               char *buffer, void *buf_token)
-{
-       struct emac_rxch *rxch = priv->rxch[ch];
-
-       /* populate the hardware descriptor */
-       curr_bd->h_next = 0;
-       curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buffer,
-                               rxch->buf_size, DMA_FROM_DEVICE);
-       curr_bd->off_b_len = rxch->buf_size;
-       curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
-       curr_bd->next = NULL;
-       curr_bd->data_ptr = buffer;
-       curr_bd->buf_token = buf_token;
-
-       /* write back  */
-       BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-       if (rxch->active_queue_head == NULL) {
-               rxch->active_queue_head = curr_bd;
-               rxch->active_queue_tail = curr_bd;
-               if (0 != rxch->queue_active) {
-                       emac_write(EMAC_RXHDP(ch),
-                          emac_virt_to_phys(rxch->active_queue_head, priv));
-                       rxch->queue_active = 1;
-               }
-       } else {
-               struct emac_rx_bd __iomem *tail_bd;
-               u32 frame_status;
-
-               tail_bd = rxch->active_queue_tail;
-               rxch->active_queue_tail = curr_bd;
-               tail_bd->next = curr_bd;
-               tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
-               tail_bd->h_next = emac_virt_to_phys(curr_bd, priv);
-               frame_status = tail_bd->mode;
-               if (frame_status & EMAC_CPPI_EOQ_BIT) {
-                       emac_write(EMAC_RXHDP(ch),
-                                       emac_virt_to_phys(curr_bd, priv));
-                       frame_status &= ~(EMAC_CPPI_EOQ_BIT);
-                       tail_bd->mode = frame_status;
-                       ++rxch->end_of_queue_add;
-               }
-       }
-       ++rxch->recycled_bd;
-}
-
-/**
- * emac_net_rx_cb: Prepares packet and sends to upper layer
- * @priv: The DaVinci EMAC private adapter structure
- * @net_pkt_list: Network packet list (received packets)
- *
- * Invalidates packet buffer memory and sends the received packet to upper
- * layer
- *
- * Returns success or appropriate error code (none as of now)
- */
-static int emac_net_rx_cb(struct emac_priv *priv,
-                         struct emac_netpktobj *net_pkt_list)
-{
-       struct net_device *ndev = priv->ndev;
-       struct sk_buff *p_skb = net_pkt_list->pkt_token;
-       /* set length of packet */
-       skb_put(p_skb, net_pkt_list->pkt_length);
-       p_skb->protocol = eth_type_trans(p_skb, priv->ndev);
-       netif_receive_skb(p_skb);
-       ndev->stats.rx_bytes += net_pkt_list->pkt_length;
-       ndev->stats.rx_packets++;
-       return 0;
-}
-
-/**
- * emac_rx_bdproc: RX buffer descriptor (packet) processing
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number to process buffer descriptors for
- * @budget: number of packets allowed to process
- * @pending: indication to caller that packets are pending to process
- *
- * Processes RX buffer descriptors - checks ownership bit on the RX buffer
- * descriptor, sends the receive packet to upper layer, allocates a new SKB
- * and recycles the buffer descriptor (requeues it in hardware RX queue).
- * Only "budget" number of packets are processed and indication of pending
- * packets provided to the caller.
- *
- * Returns number of packets processed (and indication of pending packets)
- */
-static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
-{
-       unsigned long flags;
-       u32 frame_status;
-       u32 pkts_processed = 0;
-       char *new_buffer;
-       struct emac_rx_bd __iomem *curr_bd;
-       struct emac_rx_bd __iomem *last_bd;
-       struct emac_netpktobj *curr_pkt, pkt_obj;
-       struct emac_netbufobj buf_obj;
-       struct emac_netbufobj *rx_buf_obj;
-       void *new_buf_token;
-       struct emac_rxch *rxch = priv->rxch[ch];
-
-       if (unlikely(1 == rxch->teardown_pending))
-               return 0;
-       ++rxch->proc_count;
-       spin_lock_irqsave(&priv->rx_lock, flags);
-       pkt_obj.buf_list = &buf_obj;
-       curr_pkt = &pkt_obj;
-       curr_bd = rxch->active_queue_head;
-       BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-       frame_status = curr_bd->mode;
-
-       while ((curr_bd) &&
-              ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
-              (pkts_processed < budget)) {
-
-               new_buffer = emac_net_alloc_rx_buf(priv, rxch->buf_size,
-                                       &new_buf_token, EMAC_DEF_RX_CH);
-               if (unlikely(NULL == new_buffer)) {
-                       ++rxch->out_of_rx_buffers;
-                       goto end_emac_rx_bdproc;
-               }
-
-               /* populate received packet data structure */
-               rx_buf_obj = &curr_pkt->buf_list[0];
-               rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr;
-               rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE;
-               rx_buf_obj->buf_token = curr_bd->buf_token;
-
-               dma_unmap_single(&priv->ndev->dev, curr_bd->buff_ptr,
-                               curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
-                               DMA_FROM_DEVICE);
-
-               curr_pkt->pkt_token = curr_pkt->buf_list->buf_token;
-               curr_pkt->num_bufs = 1;
-               curr_pkt->pkt_length =
-                       (frame_status & EMAC_RX_BD_PKT_LENGTH_MASK);
-               emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv));
-               ++rxch->processed_bd;
-               last_bd = curr_bd;
-               curr_bd = last_bd->next;
-               rxch->active_queue_head = curr_bd;
-
-               /* check if end of RX queue ? */
-               if (frame_status & EMAC_CPPI_EOQ_BIT) {
-                       if (curr_bd) {
-                               ++rxch->mis_queued_packets;
-                               emac_write(EMAC_RXHDP(ch),
-                                          emac_virt_to_phys(curr_bd, priv));
-                       } else {
-                               ++rxch->end_of_queue;
-                               rxch->queue_active = 0;
-                       }
-               }
-
-               /* recycle BD */
-               emac_addbd_to_rx_queue(priv, ch, last_bd, new_buffer,
-                                      new_buf_token);
-
-               /* return the packet to the user - BD ptr passed in
-                * last parameter for potential *future* use */
-               spin_unlock_irqrestore(&priv->rx_lock, flags);
-               emac_net_rx_cb(priv, curr_pkt);
-               spin_lock_irqsave(&priv->rx_lock, flags);
-               curr_bd = rxch->active_queue_head;
-               if (curr_bd) {
-                       BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-                       frame_status = curr_bd->mode;
-               }
-               ++pkts_processed;
-       }
-
-end_emac_rx_bdproc:
-       spin_unlock_irqrestore(&priv->rx_lock, flags);
-       return pkts_processed;
-}
-
 /**
  * emac_hw_enable: Enable EMAC hardware for packet transmission/reception
  * @priv: The DaVinci EMAC private adapter structure
@@ -2172,7 +1276,7 @@ end_emac_rx_bdproc:
  */
 static int emac_hw_enable(struct emac_priv *priv)
 {
-       u32 ch, val, mbp_enable, mac_control;
+       u32 val, mbp_enable, mac_control;
 
        /* Soft reset */
        emac_write(EMAC_SOFTRESET, 1);
@@ -2215,26 +1319,9 @@ static int emac_hw_enable(struct emac_priv *priv)
        emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL);
        priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF;
 
-       val = emac_read(EMAC_TXCONTROL);
-       val |= EMAC_TX_CONTROL_TX_ENABLE_VAL;
-       emac_write(EMAC_TXCONTROL, val);
-       val = emac_read(EMAC_RXCONTROL);
-       val |= EMAC_RX_CONTROL_RX_ENABLE_VAL;
-       emac_write(EMAC_RXCONTROL, val);
        emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL);
 
-       for (ch = 0; ch < EMAC_DEF_MAX_TX_CH; ch++) {
-               emac_write(EMAC_TXHDP(ch), 0);
-               emac_write(EMAC_TXINTMASKSET, BIT(ch));
-       }
-       for (ch = 0; ch < EMAC_DEF_MAX_RX_CH; ch++) {
-               struct emac_rxch *rxch = priv->rxch[ch];
-               emac_setmac(priv, ch, rxch->mac_addr);
-               emac_write(EMAC_RXINTMASKSET, BIT(ch));
-               rxch->queue_active = 1;
-               emac_write(EMAC_RXHDP(ch),
-                          emac_virt_to_phys(rxch->active_queue_head, priv));
-       }
+       emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr);
 
        /* Enable MII */
        val = emac_read(EMAC_MACCONTROL);
@@ -2279,8 +1366,8 @@ static int emac_poll(struct napi_struct *napi, int budget)
                mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC;
 
        if (status & mask) {
-               num_tx_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH,
-                                         EMAC_DEF_TX_MAX_SERVICE);
+               num_tx_pkts = cpdma_chan_process(priv->txchan,
+                                             EMAC_DEF_TX_MAX_SERVICE);
        } /* TX processing */
 
        mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC;
@@ -2289,7 +1376,7 @@ static int emac_poll(struct napi_struct *napi, int budget)
                mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC;
 
        if (status & mask) {
-               num_rx_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget);
+               num_rx_pkts = cpdma_chan_process(priv->rxchan, budget);
        } /* RX processing */
 
        mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT;
@@ -2348,79 +1435,6 @@ void emac_poll_controller(struct net_device *ndev)
 }
 #endif
 
-/* PHY/MII bus related */
-
-/* Wait until mdio is ready for next command */
-#define MDIO_WAIT_FOR_USER_ACCESS\
-               while ((emac_mdio_read((MDIO_USERACCESS(0))) &\
-                       MDIO_USERACCESS_GO) != 0)
-
-static int emac_mii_read(struct mii_bus *bus, int phy_id, int phy_reg)
-{
-       unsigned int phy_data = 0;
-       unsigned int phy_control;
-
-       /* Wait until mdio is ready for next command */
-       MDIO_WAIT_FOR_USER_ACCESS;
-
-       phy_control = (MDIO_USERACCESS_GO |
-                      MDIO_USERACCESS_READ |
-                      ((phy_reg << 21) & MDIO_USERACCESS_REGADR) |
-                      ((phy_id << 16) & MDIO_USERACCESS_PHYADR) |
-                      (phy_data & MDIO_USERACCESS_DATA));
-       emac_mdio_write(MDIO_USERACCESS(0), phy_control);
-
-       /* Wait until mdio is ready for next command */
-       MDIO_WAIT_FOR_USER_ACCESS;
-
-       return emac_mdio_read(MDIO_USERACCESS(0)) & MDIO_USERACCESS_DATA;
-
-}
-
-static int emac_mii_write(struct mii_bus *bus, int phy_id,
-                         int phy_reg, u16 phy_data)
-{
-
-       unsigned int control;
-
-       /*  until mdio is ready for next command */
-       MDIO_WAIT_FOR_USER_ACCESS;
-
-       control = (MDIO_USERACCESS_GO |
-                  MDIO_USERACCESS_WRITE |
-                  ((phy_reg << 21) & MDIO_USERACCESS_REGADR) |
-                  ((phy_id << 16) & MDIO_USERACCESS_PHYADR) |
-                  (phy_data & MDIO_USERACCESS_DATA));
-       emac_mdio_write(MDIO_USERACCESS(0), control);
-
-       return 0;
-}
-
-static int emac_mii_reset(struct mii_bus *bus)
-{
-       unsigned int clk_div;
-       int mdio_bus_freq = emac_bus_frequency;
-
-       if (mdio_max_freq && mdio_bus_freq)
-               clk_div = ((mdio_bus_freq / mdio_max_freq) - 1);
-       else
-               clk_div = 0xFF;
-
-       clk_div &= MDIO_CONTROL_CLKDIV;
-
-       /* Set enable and clock divider in MDIOControl */
-       emac_mdio_write(MDIO_CONTROL, (clk_div | MDIO_CONTROL_ENABLE));
-
-       return 0;
-
-}
-
-static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, PHY_POLL };
-
-/* emac_driver: EMAC MII bus structure */
-
-static struct mii_bus *emac_mii;
-
 static void emac_adjust_link(struct net_device *ndev)
 {
        struct emac_priv *priv = netdev_priv(ndev);
@@ -2485,6 +1499,11 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
        return -EOPNOTSUPP;
 }
 
+static int match_first_device(struct device *dev, void *data)
+{
+       return 1;
+}
+
 /**
  * emac_dev_open: EMAC device open
  * @ndev: The DaVinci EMAC network adapter
@@ -2498,10 +1517,9 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
 static int emac_dev_open(struct net_device *ndev)
 {
        struct device *emac_dev = &ndev->dev;
-       u32 rc, cnt, ch;
-       int phy_addr;
+       u32 cnt;
        struct resource *res;
-       int q, m;
+       int q, m, ret;
        int i = 0;
        int k = 0;
        struct emac_priv *priv = netdev_priv(ndev);
@@ -2513,29 +1531,21 @@ static int emac_dev_open(struct net_device *ndev)
        /* Configuration items */
        priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN;
 
-       /* Clear basic hardware */
-       for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) {
-               emac_write(EMAC_TXHDP(ch), 0);
-               emac_write(EMAC_RXHDP(ch), 0);
-               emac_write(EMAC_RXHDP(ch), 0);
-               emac_write(EMAC_RXINTMASKCLEAR, EMAC_INT_MASK_CLEAR);
-               emac_write(EMAC_TXINTMASKCLEAR, EMAC_INT_MASK_CLEAR);
-       }
        priv->mac_hash1 = 0;
        priv->mac_hash2 = 0;
        emac_write(EMAC_MACHASH1, 0);
        emac_write(EMAC_MACHASH2, 0);
 
-       /* multi ch not supported - open 1 TX, 1RX ch by default */
-       rc = emac_init_txch(priv, EMAC_DEF_TX_CH);
-       if (0 != rc) {
-               dev_err(emac_dev, "DaVinci EMAC: emac_init_txch() failed");
-               return rc;
-       }
-       rc = emac_init_rxch(priv, EMAC_DEF_RX_CH, priv->mac_addr);
-       if (0 != rc) {
-               dev_err(emac_dev, "DaVinci EMAC: emac_init_rxch() failed");
-               return rc;
+       for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) {
+               struct sk_buff *skb = emac_rx_alloc(priv);
+
+               if (!skb)
+                       break;
+
+               ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
+                                       skb_tailroom(skb), GFP_KERNEL);
+               if (WARN_ON(ret < 0))
+                       break;
        }
 
        /* Request IRQ */
@@ -2560,28 +1570,28 @@ static int emac_dev_open(struct net_device *ndev)
                emac_set_coalesce(ndev, &coal);
        }
 
-       /* find the first phy */
+       cpdma_ctlr_start(priv->dma);
+
        priv->phydev = NULL;
-       if (priv->phy_mask) {
-               emac_mii_reset(priv->mii_bus);
-               for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
-                       if (priv->mii_bus->phy_map[phy_addr]) {
-                               priv->phydev = priv->mii_bus->phy_map[phy_addr];
-                               break;
-                       }
-               }
+       /* use the first phy on the bus if pdata did not give us a phy id */
+       if (!priv->phy_id) {
+               struct device *phy;
 
-               if (!priv->phydev) {
-                       printk(KERN_ERR "%s: no PHY found\n", ndev->name);
-                       return -1;
-               }
+               phy = bus_find_device(&mdio_bus_type, NULL, NULL,
+                                     match_first_device);
+               if (phy)
+                       priv->phy_id = dev_name(phy);
+       }
 
-               priv->phydev = phy_connect(ndev, dev_name(&priv->phydev->dev),
-                               &emac_adjust_link, 0, PHY_INTERFACE_MODE_MII);
+       if (priv->phy_id && *priv->phy_id) {
+               priv->phydev = phy_connect(ndev, priv->phy_id,
+                                          &emac_adjust_link, 0,
+                                          PHY_INTERFACE_MODE_MII);
 
                if (IS_ERR(priv->phydev)) {
-                       printk(KERN_ERR "%s: Could not attach to PHY\n",
-                                                               ndev->name);
+                       dev_err(emac_dev, "could not connect to phy %s\n",
+                               priv->phy_id);
+                       priv->phydev = NULL;
                        return PTR_ERR(priv->phydev);
                }
 
@@ -2589,12 +1599,13 @@ static int emac_dev_open(struct net_device *ndev)
                priv->speed = 0;
                priv->duplex = ~0;
 
-               printk(KERN_INFO "%s: attached PHY driver [%s] "
-                       "(mii_bus:phy_addr=%s, id=%x)\n", ndev->name,
+               dev_info(emac_dev, "attached PHY driver [%s] "
+                       "(mii_bus:phy_addr=%s, id=%x)\n",
                        priv->phydev->drv->name, dev_name(&priv->phydev->dev),
                        priv->phydev->phy_id);
-       } else{
+       } else {
                /* No PHY , fix the link, speed and duplex settings */
+               dev_notice(emac_dev, "no phy, defaulting to 100/full\n");
                priv->link = 1;
                priv->speed = SPEED_100;
                priv->duplex = DUPLEX_FULL;
@@ -2607,7 +1618,7 @@ static int emac_dev_open(struct net_device *ndev)
        if (netif_msg_drv(priv))
                dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name);
 
-       if (priv->phy_mask)
+       if (priv->phydev)
                phy_start(priv->phydev);
 
        return 0;
@@ -2648,10 +1659,7 @@ static int emac_dev_stop(struct net_device *ndev)
 
        netif_carrier_off(ndev);
        emac_int_disable(priv);
-       emac_stop_txch(priv, EMAC_DEF_TX_CH);
-       emac_stop_rxch(priv, EMAC_DEF_RX_CH);
-       emac_cleanup_txch(priv, EMAC_DEF_TX_CH);
-       emac_cleanup_rxch(priv, EMAC_DEF_RX_CH);
+       cpdma_ctlr_stop(priv->dma);
        emac_write(EMAC_SOFTRESET, 1);
 
        if (priv->phydev)
@@ -2756,9 +1764,10 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        struct resource *res;
        struct net_device *ndev;
        struct emac_priv *priv;
-       unsigned long size;
+       unsigned long size, hw_ram_addr;
        struct emac_platform_data *pdata;
        struct device *emac_dev;
+       struct cpdma_params dma_params;
 
        /* obtain emac clock from kernel */
        emac_clk = clk_get(&pdev->dev, NULL);
@@ -2782,8 +1791,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        priv->ndev = ndev;
        priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG);
 
-       spin_lock_init(&priv->tx_lock);
-       spin_lock_init(&priv->rx_lock);
        spin_lock_init(&priv->lock);
 
        pdata = pdev->dev.platform_data;
@@ -2794,7 +1801,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 
        /* MAC addr and PHY mask , RMII enable info from platform_data */
        memcpy(priv->mac_addr, pdata->mac_addr, 6);
-       priv->phy_mask = pdata->phy_mask;
+       priv->phy_id = pdata->phy_id;
        priv->rmii_en = pdata->rmii_en;
        priv->version = pdata->version;
        priv->int_enable = pdata->interrupt_enable;
@@ -2831,14 +1838,41 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        ndev->base_addr = (unsigned long)priv->remap_addr;
 
        priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
-       priv->ctrl_ram_size = pdata->ctrl_ram_size;
-       priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset;
 
-       if (pdata->hw_ram_addr)
-               priv->hw_ram_addr = pdata->hw_ram_addr;
-       else
-               priv->hw_ram_addr = (u32 __force)res->start +
-                                       pdata->ctrl_ram_offset;
+       hw_ram_addr = pdata->hw_ram_addr;
+       if (!hw_ram_addr)
+               hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset;
+
+       memset(&dma_params, 0, sizeof(dma_params));
+       dma_params.dev                  = emac_dev;
+       dma_params.dmaregs              = priv->emac_base;
+       dma_params.rxthresh             = priv->emac_base + 0x120;
+       dma_params.rxfree               = priv->emac_base + 0x140;
+       dma_params.txhdp                = priv->emac_base + 0x600;
+       dma_params.rxhdp                = priv->emac_base + 0x620;
+       dma_params.txcp                 = priv->emac_base + 0x640;
+       dma_params.rxcp                 = priv->emac_base + 0x660;
+       dma_params.num_chan             = EMAC_MAX_TXRX_CHANNELS;
+       dma_params.min_packet_size      = EMAC_DEF_MIN_ETHPKTSIZE;
+       dma_params.desc_mem_phys        = hw_ram_addr;
+       dma_params.desc_mem_size        = pdata->ctrl_ram_size;
+       dma_params.desc_align           = 16;
+
+       priv->dma = cpdma_ctlr_create(&dma_params);
+       if (!priv->dma) {
+               dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n");
+               rc = -ENOMEM;
+               goto no_dma;
+       }
+
+       priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH),
+                                      emac_tx_handler);
+       priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH),
+                                      emac_rx_handler);
+       if (WARN_ON(!priv->txchan || !priv->rxchan)) {
+               rc = -ENOMEM;
+               goto no_irq_res;
+       }
 
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!res) {
@@ -2871,32 +1905,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        }
 
 
-       /* MII/Phy intialisation, mdio bus registration */
-       emac_mii = mdiobus_alloc();
-       if (emac_mii == NULL) {
-               dev_err(emac_dev, "DaVinci EMAC: Error allocating mii_bus\n");
-               rc = -ENOMEM;
-               goto mdio_alloc_err;
-       }
-
-       priv->mii_bus = emac_mii;
-       emac_mii->name  = "emac-mii",
-       emac_mii->read  = emac_mii_read,
-       emac_mii->write = emac_mii_write,
-       emac_mii->reset = emac_mii_reset,
-       emac_mii->irq   = mii_irqs,
-       emac_mii->phy_mask = ~(priv->phy_mask);
-       emac_mii->parent = &pdev->dev;
-       emac_mii->priv = priv->remap_addr + pdata->mdio_reg_offset;
-       snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", priv->pdev->id);
-       mdio_max_freq = pdata->mdio_max_freq;
-       emac_mii->reset(emac_mii);
-
-       /* Register the MII bus */
-       rc = mdiobus_register(emac_mii);
-       if (rc)
-               goto mdiobus_quit;
-
        if (netif_msg_probe(priv)) {
                dev_notice(emac_dev, "DaVinci EMAC Probe found device "\
                           "(regs: %p, irq: %d)\n",
@@ -2904,13 +1912,15 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        }
        return 0;
 
-mdiobus_quit:
-       mdiobus_free(emac_mii);
-
 netdev_reg_err:
-mdio_alloc_err:
        clk_disable(emac_clk);
 no_irq_res:
+       if (priv->txchan)
+               cpdma_chan_destroy(priv->txchan);
+       if (priv->rxchan)
+               cpdma_chan_destroy(priv->rxchan);
+       cpdma_ctlr_destroy(priv->dma);
+no_dma:
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, res->end - res->start + 1);
        iounmap(priv->remap_addr);
@@ -2938,8 +1948,12 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       mdiobus_unregister(priv->mii_bus);
-       mdiobus_free(priv->mii_bus);
+
+       if (priv->txchan)
+               cpdma_chan_destroy(priv->txchan);
+       if (priv->rxchan)
+               cpdma_chan_destroy(priv->rxchan);
+       cpdma_ctlr_destroy(priv->dma);
 
        release_mem_region(res->start, res->end - res->start + 1);