From: Wolfgang Grandegger <[email protected]>

The driver requires a separate kernel patch implementing a common
real-time capable Memory Access Layer (MAL). Furthermore, the
PHY interface is also used directly from the Linux kernel.

Signed-off-by: Wolfgang Grandegger <[email protected]>
---
 configure.ac                        |   12 +
 drivers/GNUmakefile.am              |    4 +
 drivers/ibm_newemac/GNUmakefile.am  |   49 ++++
 drivers/ibm_newemac/Makefile.kbuild |   10 +
 drivers/ibm_newemac/core.c          |  443 ++++++++++++++++++++++++-----------
 drivers/ibm_newemac/core.h          |   24 ++-
 6 files changed, 399 insertions(+), 143 deletions(-)
 create mode 100644 drivers/ibm_newemac/GNUmakefile.am
 create mode 100644 drivers/ibm_newemac/Makefile.kbuild

diff --git a/configure.ac b/configure.ac
index c50811e..6afe868 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1049,6 +1049,16 @@ AC_ARG_ENABLE(igb,
 AC_MSG_RESULT([${CONFIG_RTNET_DRV_IGB:-n}])
 AM_CONDITIONAL(CONFIG_RTNET_DRV_IGB,[test "$CONFIG_RTNET_DRV_IGB" = "y"])
 
+AC_MSG_CHECKING([whether to build IBM EMAC (Gigabit) driver])
+AC_ARG_ENABLE(ibm-emac,
+    AS_HELP_STRING([--enable-ibm-emac], [build IBM EMAC driver]),
+    [case "$enableval" in
+        y | yes) CONFIG_RTNET_DRV_IBM_EMAC=y ;;
+        *) CONFIG_RTNET_DRV_IBM_EMAC=n ;;
+    esac])
+AC_MSG_RESULT([${CONFIG_RTNET_DRV_IBM_EMAC:-n}])
+AM_CONDITIONAL(CONFIG_RTNET_DRV_IBM_EMAC,[test "$CONFIG_RTNET_DRV_IBM_EMAC" = 
"y"])
+
 dnl ======================================================================
 dnl             Stack parameters
 dnl ======================================================================
@@ -1448,6 +1458,7 @@ if test x$CONFIG_KBUILD = xy; then
         drivers/mpc52xx_fec \
         drivers/tulip \
         drivers/igb \
+        drivers/ibm_newemac \
         drivers/experimental \
         drivers/experimental/rt2500 \
         drivers/experimental/e1000 \
@@ -1532,6 +1543,7 @@ AC_CONFIG_FILES([ \
     drivers/mpc52xx_fec/GNUmakefile \
     drivers/tulip/GNUmakefile \
     drivers/igb/GNUmakefile \
+    drivers/ibm_newemac/GNUmakefile \
     drivers/experimental/GNUmakefile \
     drivers/experimental/rt2500/GNUmakefile \
     drivers/experimental/e1000/GNUmakefile \
diff --git a/drivers/GNUmakefile.am b/drivers/GNUmakefile.am
index 9ebb290..669a2d6 100644
--- a/drivers/GNUmakefile.am
+++ b/drivers/GNUmakefile.am
@@ -20,6 +20,10 @@ if CONFIG_RTNET_DRV_IGB
 OPTDIRS += igb
 endif
 
+if CONFIG_RTNET_DRV_IBM_EMAC
+OPTDIRS += ibm_newemac
+endif
+
 SUBDIRS = experimental $(OPTDIRS)
 
 moduledir = $(DESTDIR)$(RTNET_MODULE_DIR)
diff --git a/drivers/ibm_newemac/GNUmakefile.am 
b/drivers/ibm_newemac/GNUmakefile.am
new file mode 100644
index 0000000..c23c773
--- /dev/null
+++ b/drivers/ibm_newemac/GNUmakefile.am
@@ -0,0 +1,49 @@
+moduledir = $(DESTDIR)$(RTNET_MODULE_DIR)
+modext = $(RTNET_MODULE_EXT)
+
+EXTRA_LIBRARIES = libkernel_ibm_emac.a
+
+libkernel_ibm_emac_a_CPPFLAGS = \
+       $(RTEXT_KMOD_CFLAGS) \
+       -I$(top_srcdir)/stack/include \
+       -I$(top_builddir)/stack/include
+
+libkernel_ibm_emac_a_SOURCES = \
+       core.h  \
+       core.c
+
+# ethtool
+
+OBJS = rt_ibm_emac$(modext)
+
+rt_ibm_emac.o: libkernel_ibm_emac.a
+       $(LD) --whole-archive $< -r -o $@
+
+all-local: all-local$(modext)
+
+# 2.4 build
+all-local.o: $(OBJS)
+
+# 2.6 build
+all-local.ko: @RTNET_KBUILD_ENV@
+all-local.ko: $(libkernel_ibm_emac_a_SOURCES) FORCE
+       $(RTNET_KBUILD_CMD)
+
+install-exec-local: $(OBJS)
+       $(mkinstalldirs) $(moduledir)
+       $(INSTALL_DATA) $^ $(moduledir)
+
+uninstall-local:
+       for MOD in $(OBJS); do $(RM) $(moduledir)/$$MOD; done
+
+clean-local: $(libkernel_ibm_emac_a_SOURCES)
+       $(RTNET_KBUILD_CLEAN)
+
+distclean-local:
+       $(RTNET_KBUILD_DISTCLEAN)
+
+EXTRA_DIST = Makefile.kbuild
+
+DISTCLEANFILES = Makefile
+
+.PHONY: FORCE
diff --git a/drivers/ibm_newemac/Makefile.kbuild 
b/drivers/ibm_newemac/Makefile.kbuild
new file mode 100644
index 0000000..57b7bca
--- /dev/null
+++ b/drivers/ibm_newemac/Makefile.kbuild
@@ -0,0 +1,10 @@
+EXTRA_CFLAGS += \
+       -Idrivers/net/ibm_newemac \
+       $(rtext_kmod_cflags) \
+       -I$(top_srcdir)/stack/include \
+       -I$(top_builddir)/stack/include \
+       -I$(srcdir)
+
+obj-m += $(build_targets)
+
+rt_ibm_emac-objs := $(build_objs)
diff --git a/drivers/ibm_newemac/core.c b/drivers/ibm_newemac/core.c
index 519e19e..357f1ab 100644
--- a/drivers/ibm_newemac/core.c
+++ b/drivers/ibm_newemac/core.c
@@ -32,7 +32,6 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/etherdevice.h>
-#include <linux/skbuff.h>
 #include <linux/crc32.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -67,9 +66,9 @@
  * at the same time and didn't come up with code I liked :(.                
--ebs
  */
 
-#define DRV_NAME        "emac"
+#define DRV_NAME        "rt-emac"
 #define DRV_VERSION     "3.54"
-#define DRV_DESC        "PPC 4xx OCP EMAC driver"
+#define DRV_DESC        "RTnet: PPC 4xx OCP EMAC driver"
 
 MODULE_DESCRIPTION(DRV_DESC);
 MODULE_AUTHOR
@@ -89,7 +88,7 @@ MODULE_LICENSE("GPL");
 /* If packet size is less than this number, we allocate small skb and copy 
packet
  * contents into it instead of just sending original big skb up
  */
-#define EMAC_RX_COPY_THRESH            CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD
+#define EMAC_RX_COPY_THRESH            0 //256
 
 /* Since multiple EMACs share MDIO lines in various ways, we need
  * to avoid re-using the same PHY ID in cases where the arch didn't
@@ -99,7 +98,7 @@ MODULE_LICENSE("GPL");
  * EMAC "sets" (multiple ASICs containing several EMACs) though we can
  * probably require in that case to have explicit PHY IDs in the device-tree
  */
-static u32 busy_phy_map;
+extern u32 busy_phy_map;
 static DEFINE_MUTEX(emac_phy_map_lock);
 
 /* This is the wait queue used to wait on any event related to probe, that
@@ -174,9 +173,11 @@ static inline void emac_rx_clk_default(struct 
emac_instance *dev)
 #define STOP_TIMEOUT_1000      13
 #define STOP_TIMEOUT_1000_JUMBO        73
 
+#ifdef WITH_MULTICAST
 static unsigned char default_mcast_addr[] = {
        0x01, 0x80, 0xC2, 0x00, 0x00, 0x01
 };
+#endif
 
 /* Please, keep in sync with struct ibm_emac_stats/ibm_emac_error_stats */
 static const char emac_stats_keys[EMAC_ETHTOOL_STATS_COUNT][ETH_GSTRING_LEN] = 
{
@@ -197,9 +198,15 @@ static const char 
emac_stats_keys[EMAC_ETHTOOL_STATS_COUNT][ETH_GSTRING_LEN] = {
        "tx_errors"
 };
 
+#ifdef ORIGINAL
 static irqreturn_t emac_irq(int irq, void *dev_instance);
+#else
+static int emac_irq(rtdm_irq_t *irq_handle);
+#endif
 static void emac_clean_tx_ring(struct emac_instance *dev);
+#ifdef WITH_MULTICAST
 static void __emac_set_multicast_list(struct emac_instance *dev);
+#endif
 
 static inline int emac_phy_supports_gige(int phy_mode)
 {
@@ -300,27 +307,42 @@ static void emac_rx_disable(struct emac_instance *dev)
 
 static inline void emac_netif_stop(struct emac_instance *dev)
 {
+#ifdef ORIGINAL
        netif_tx_lock_bh(dev->ndev);
        netif_addr_lock(dev->ndev);
+#endif
+#ifdef WITH_MULTICAST
        dev->no_mcast = 1;
+#endif
+#ifdef ORIGINAL
        netif_addr_unlock(dev->ndev);
        netif_tx_unlock_bh(dev->ndev);
        dev->ndev->trans_start = jiffies;       /* prevent tx timeout */
        mal_poll_disable(dev->mal, &dev->commac);
        netif_tx_disable(dev->ndev);
+#else
+       mal_poll_disable(dev->mal, &dev->commac);
+       rtnetif_stop_queue(dev->ndev);
+#endif
 }
 
 static inline void emac_netif_start(struct emac_instance *dev)
 {
+#ifdef ORIGINAL
        netif_tx_lock_bh(dev->ndev);
        netif_addr_lock(dev->ndev);
+#endif
+#ifdef WITH_MULTICAST
        dev->no_mcast = 0;
-       if (dev->mcast_pending && netif_running(dev->ndev))
+       if (dev->mcast_pending && rtnetif_running(dev->ndev))
                __emac_set_multicast_list(dev);
+#endif
+#ifdef ORIGINAL
        netif_addr_unlock(dev->ndev);
        netif_tx_unlock_bh(dev->ndev);
+#endif
 
-       netif_wake_queue(dev->ndev);
+       rtnetif_wake_queue(dev->ndev);
 
        /* NOTE: unconditional netif_wake_queue is only appropriate
         * so long as all callers are assured to have free tx slots
@@ -385,6 +407,7 @@ static int emac_reset(struct emac_instance *dev)
        }
 }
 
+#ifdef ORIGINAL
 static void emac_hash_mc(struct emac_instance *dev)
 {
        const int regs = EMAC_XAHT_REGS(dev);
@@ -412,10 +435,11 @@ static void emac_hash_mc(struct emac_instance *dev)
        for (i = 0; i < regs; i++)
                out_be32(gaht_base + i, gaht_temp[i]);
 }
+#endif
 
-static inline u32 emac_iff2rmr(struct net_device *ndev)
+static inline u32 emac_iff2rmr(struct rtnet_device *ndev)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        u32 r;
 
        r = EMAC_RMR_SP | EMAC_RMR_SFCS | EMAC_RMR_IAE | EMAC_RMR_BAE;
@@ -427,11 +451,13 @@ static inline u32 emac_iff2rmr(struct net_device *ndev)
 
        if (ndev->flags & IFF_PROMISC)
                r |= EMAC_RMR_PME;
+#ifdef ORIGINAL
        else if (ndev->flags & IFF_ALLMULTI ||
                         (netdev_mc_count(ndev) > EMAC_XAHT_SLOTS(dev)))
                r |= EMAC_RMR_PMME;
        else if (!netdev_mc_empty(ndev))
                r |= EMAC_RMR_MAE;
+#endif
 
        return r;
 }
@@ -533,8 +559,8 @@ static inline u32 emac_calc_rwmr(struct emac_instance *dev,
 static int emac_configure(struct emac_instance *dev)
 {
        struct emac_regs __iomem *p = dev->emacp;
-       struct net_device *ndev = dev->ndev;
-       int tx_size, rx_size, link = netif_carrier_ok(dev->ndev);
+       struct rtnet_device *ndev = dev->ndev;
+       int tx_size, rx_size, link = rtnetif_carrier_ok(dev->ndev);
        u32 r, mr1 = 0;
 
        DBG(dev, "configure" NL);
@@ -633,8 +659,10 @@ static int emac_configure(struct emac_instance *dev)
 
        /* Receive mode register */
        r = emac_iff2rmr(ndev);
+#ifdef ORIGINAL
        if (r & EMAC_RMR_MAE)
                emac_hash_mc(dev);
+#endif
        out_be32(&p->rmr, r);
 
        /* FIFOs thresholds */
@@ -736,15 +764,16 @@ static void emac_reset_work(struct work_struct *work)
        mutex_unlock(&dev->link_lock);
 }
 
-static void emac_tx_timeout(struct net_device *ndev)
+#ifdef ORIGINAL
+static void emac_tx_timeout(struct rtnet_device *ndev)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
 
        DBG(dev, "tx_timeout" NL);
 
        schedule_work(&dev->reset_work);
 }
-
+#endif
 
 static inline int emac_phy_done(struct emac_instance *dev, u32 stacr)
 {
@@ -888,9 +917,9 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 
id, u8 reg,
        mutex_unlock(&dev->mdio_lock);
 }
 
-static int emac_mdio_read(struct net_device *ndev, int id, int reg)
+static int emac_mdio_read(struct rtnet_device *ndev, int id, int reg)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        int res;
 
        res = __emac_mdio_read((dev->mdio_instance &&
@@ -900,9 +929,9 @@ static int emac_mdio_read(struct net_device *ndev, int id, 
int reg)
        return res;
 }
 
-static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
+static void emac_mdio_write(struct rtnet_device *ndev, int id, int reg, int 
val)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
 
        __emac_mdio_write((dev->mdio_instance &&
                           dev->phy.gpcs_address != id) ?
@@ -910,6 +939,7 @@ static void emac_mdio_write(struct net_device *ndev, int 
id, int reg, int val)
                          (u8) id, (u8) reg, (u16) val);
 }
 
+#ifdef ORIGINAL
 /* Tx lock BH */
 static void __emac_set_multicast_list(struct emac_instance *dev)
 {
@@ -944,13 +974,13 @@ static void __emac_set_multicast_list(struct 
emac_instance *dev)
 }
 
 /* Tx lock BH */
-static void emac_set_multicast_list(struct net_device *ndev)
+static void emac_set_multicast_list(struct rtnet_device *ndev)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
 
        DBG(dev, "multicast" NL);
 
-       BUG_ON(!netif_running(dev->ndev));
+       BUG_ON(!rtnetif_running(dev->ndev));
 
        if (dev->no_mcast) {
                dev->mcast_pending = 1;
@@ -958,7 +988,9 @@ static void emac_set_multicast_list(struct net_device *ndev)
        }
        __emac_set_multicast_list(dev);
 }
+#endif
 
+#ifdef ORIGINAL
 static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu)
 {
        int rx_sync_size = emac_rx_sync_size(new_mtu);
@@ -972,7 +1004,7 @@ static int emac_resize_rx_ring(struct emac_instance *dev, 
int new_mtu)
 
        if (dev->rx_sg_skb) {
                ++dev->estats.rx_dropped_resize;
-               dev_kfree_skb(dev->rx_sg_skb);
+               kfree_rtskb(dev->rx_sg_skb);
                dev->rx_sg_skb = NULL;
        }
 
@@ -995,16 +1027,19 @@ static int emac_resize_rx_ring(struct emac_instance 
*dev, int new_mtu)
 
        /* Second pass, allocate new skbs */
        for (i = 0; i < NUM_RX_BUFF; ++i) {
-               struct sk_buff *skb = alloc_skb(rx_skb_size, GFP_ATOMIC);
+               struct rtskb *skb = dev_alloc_rtskb(rx_skb_size,
+                                                   &dev->skb_pool);
                if (!skb) {
                        ret = -ENOMEM;
                        goto oom;
                }
 
                BUG_ON(!dev->rx_skb[i]);
-               dev_kfree_skb(dev->rx_skb[i]);
+               kfree_rtskb(dev->rx_skb[i]);
+
+               skb->rtdev = dev->ndev;
 
-               skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2);
+               rtskb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2);
                dev->rx_desc[i].data_ptr =
                    dma_map_single(&dev->ofdev->dev, skb->data - 2, 
rx_sync_size,
                                   DMA_FROM_DEVICE) + 2;
@@ -1032,11 +1067,13 @@ static int emac_resize_rx_ring(struct emac_instance 
*dev, int new_mtu)
 
        return ret;
 }
+#endif
 
+#ifdef ORIGINAL
 /* Process ctx, rtnl_lock semaphore */
-static int emac_change_mtu(struct net_device *ndev, int new_mtu)
+static int emac_change_mtu(struct rtnet_device *ndev, int new_mtu)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        int ret = 0;
 
        if (new_mtu < EMAC_MIN_MTU || new_mtu > dev->max_mtu)
@@ -1044,7 +1081,7 @@ static int emac_change_mtu(struct net_device *ndev, int 
new_mtu)
 
        DBG(dev, "change_mtu(%d)" NL, new_mtu);
 
-       if (netif_running(ndev)) {
+       if (rtnetif_running(ndev)) {
                /* Check if we really need to reinitialize RX ring */
                if (emac_rx_skb_size(ndev->mtu) != emac_rx_skb_size(new_mtu))
                        ret = emac_resize_rx_ring(dev, new_mtu);
@@ -1058,6 +1095,7 @@ static int emac_change_mtu(struct net_device *ndev, int 
new_mtu)
 
        return ret;
 }
+#endif
 
 static void emac_clean_tx_ring(struct emac_instance *dev)
 {
@@ -1065,7 +1103,7 @@ static void emac_clean_tx_ring(struct emac_instance *dev)
 
        for (i = 0; i < NUM_TX_BUFF; ++i) {
                if (dev->tx_skb[i]) {
-                       dev_kfree_skb(dev->tx_skb[i]);
+                       kfree_rtskb(dev->tx_skb[i]);
                        dev->tx_skb[i] = NULL;
                        if (dev->tx_desc[i].ctrl & MAL_TX_CTRL_READY)
                                ++dev->estats.tx_dropped;
@@ -1082,13 +1120,13 @@ static void emac_clean_rx_ring(struct emac_instance 
*dev)
        for (i = 0; i < NUM_RX_BUFF; ++i)
                if (dev->rx_skb[i]) {
                        dev->rx_desc[i].ctrl = 0;
-                       dev_kfree_skb(dev->rx_skb[i]);
+                       kfree_rtskb(dev->rx_skb[i]);
                        dev->rx_skb[i] = NULL;
                        dev->rx_desc[i].data_ptr = 0;
                }
 
        if (dev->rx_sg_skb) {
-               dev_kfree_skb(dev->rx_sg_skb);
+               kfree_rtskb(dev->rx_sg_skb);
                dev->rx_sg_skb = NULL;
        }
 }
@@ -1096,14 +1134,18 @@ static void emac_clean_rx_ring(struct emac_instance 
*dev)
 static inline int emac_alloc_rx_skb(struct emac_instance *dev, int slot,
                                    gfp_t flags)
 {
-       struct sk_buff *skb = alloc_skb(dev->rx_skb_size, flags);
+       struct rtskb *skb;
+
+       skb = dev_alloc_rtskb(dev->rx_skb_size, &dev->skb_pool);
        if (unlikely(!skb))
                return -ENOMEM;
 
        dev->rx_skb[slot] = skb;
        dev->rx_desc[slot].data_len = 0;
 
-       skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2);
+       skb->rtdev = dev->ndev;
+
+       rtskb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2);
        dev->rx_desc[slot].data_ptr =
            dma_map_single(&dev->ofdev->dev, skb->data - 2, dev->rx_sync_size,
                           DMA_FROM_DEVICE) + 2;
@@ -1116,7 +1158,7 @@ static inline int emac_alloc_rx_skb(struct emac_instance 
*dev, int slot,
 
 static void emac_print_link_status(struct emac_instance *dev)
 {
-       if (netif_carrier_ok(dev->ndev))
+       if (rtnetif_carrier_ok(dev->ndev))
                printk(KERN_INFO "%s: link is up, %d %s%s\n",
                       dev->ndev->name, dev->phy.speed,
                       dev->phy.duplex == DUPLEX_FULL ? "FDX" : "HDX",
@@ -1127,15 +1169,18 @@ static void emac_print_link_status(struct emac_instance 
*dev)
 }
 
 /* Process ctx, rtnl_lock semaphore */
-static int emac_open(struct net_device *ndev)
+static int emac_open(struct rtnet_device *ndev)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        int err, i;
 
        DBG(dev, "open" NL);
 
+       rt_stack_connect(ndev, &STACK_manager);
+
        /* Setup error IRQ handler */
-       err = request_irq(dev->emac_irq, emac_irq, 0, "EMAC", dev);
+       err = rtdm_irq_request(&dev->emac_irq_handle, dev->emac_irq,
+                              emac_irq, 0, "EMAC", dev);
        if (err) {
                printk(KERN_ERR "%s: failed to request IRQ %d\n",
                       ndev->name, dev->emac_irq);
@@ -1164,11 +1209,11 @@ static int emac_open(struct net_device *ndev)
                if (dev->phy.def->ops->poll_link(&dev->phy)) {
                        dev->phy.def->ops->read_link(&dev->phy);
                        emac_rx_clk_default(dev);
-                       netif_carrier_on(dev->ndev);
+                       rtnetif_carrier_on(dev->ndev);
                        link_poll_interval = PHY_POLL_LINK_ON;
                } else {
                        emac_rx_clk_tx(dev);
-                       netif_carrier_off(dev->ndev);
+                       rtnetif_carrier_off(dev->ndev);
                        link_poll_interval = PHY_POLL_LINK_OFF;
                }
                dev->link_polling = 1;
@@ -1176,10 +1221,12 @@ static int emac_open(struct net_device *ndev)
                schedule_delayed_work(&dev->link_work, link_poll_interval);
                emac_print_link_status(dev);
        } else
-               netif_carrier_on(dev->ndev);
+               rtnetif_carrier_on(dev->ndev);
 
+#ifdef ORIGINAL
        /* Required for Pause packet support in EMAC */
        dev_mc_add_global(ndev, default_mcast_addr);
+#endif
 
        emac_configure(dev);
        mal_poll_add(dev->mal, &dev->commac);
@@ -1195,7 +1242,7 @@ static int emac_open(struct net_device *ndev)
        return 0;
  oom:
        emac_clean_rx_ring(dev);
-       free_irq(dev->emac_irq, dev);
+       rtdm_irq_free(&dev->emac_irq_handle);
 
        return -ENOMEM;
 }
@@ -1247,12 +1294,12 @@ static void emac_link_timer(struct work_struct *work)
                goto bail;
 
        if (dev->phy.def->ops->poll_link(&dev->phy)) {
-               if (!netif_carrier_ok(dev->ndev)) {
+               if (!rtnetif_carrier_ok(dev->ndev)) {
                        emac_rx_clk_default(dev);
                        /* Get new link parameters */
                        dev->phy.def->ops->read_link(&dev->phy);
 
-                       netif_carrier_on(dev->ndev);
+                       rtnetif_carrier_on(dev->ndev);
                        emac_netif_stop(dev);
                        emac_full_tx_reset(dev);
                        emac_netif_start(dev);
@@ -1260,10 +1307,14 @@ static void emac_link_timer(struct work_struct *work)
                }
                link_poll_interval = PHY_POLL_LINK_ON;
        } else {
-               if (netif_carrier_ok(dev->ndev)) {
+               if (rtnetif_carrier_ok(dev->ndev)) {
                        emac_rx_clk_tx(dev);
-                       netif_carrier_off(dev->ndev);
+                       rtnetif_carrier_off(dev->ndev);
+#ifdef ORIGINAL
                        netif_tx_disable(dev->ndev);
+#else
+                       rtnetif_stop_queue(dev->ndev);
+#endif
                        emac_reinitialize(dev);
                        emac_print_link_status(dev);
                }
@@ -1274,33 +1325,45 @@ static void emac_link_timer(struct work_struct *work)
        mutex_unlock(&dev->link_lock);
 }
 
+#ifdef ORIGINAL
 static void emac_force_link_update(struct emac_instance *dev)
 {
-       netif_carrier_off(dev->ndev);
+       rtnetif_carrier_off(dev->ndev);
        smp_rmb();
        if (dev->link_polling) {
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,37)
                cancel_rearming_delayed_work(&dev->link_work);
+#else
+               cancel_delayed_work_sync(&dev->link_work);
+#endif
                if (dev->link_polling)
                        schedule_delayed_work(&dev->link_work,  
PHY_POLL_LINK_OFF);
        }
 }
+#endif
 
 /* Process ctx, rtnl_lock semaphore */
-static int emac_close(struct net_device *ndev)
+static int emac_close(struct rtnet_device *ndev)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
 
        DBG(dev, "close" NL);
 
        if (dev->phy.address >= 0) {
                dev->link_polling = 0;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,37)
                cancel_rearming_delayed_work(&dev->link_work);
+#else
+               cancel_delayed_work_sync(&dev->link_work);
+#endif
        }
        mutex_lock(&dev->link_lock);
        emac_netif_stop(dev);
        dev->opened = 0;
        mutex_unlock(&dev->link_lock);
 
+       rt_stack_disconnect(ndev);
+
        emac_rx_disable(dev);
        emac_tx_disable(dev);
        mal_disable_rx_channel(dev->mal, dev->mal_rx_chan);
@@ -1312,13 +1375,13 @@ static int emac_close(struct net_device *ndev)
 
        free_irq(dev->emac_irq, dev);
 
-       netif_carrier_off(ndev);
+       rtnetif_carrier_off(ndev);
 
        return 0;
 }
 
 static inline u16 emac_tx_csum(struct emac_instance *dev,
-                              struct sk_buff *skb)
+                              struct rtskb *skb)
 {
        if (emac_has_feature(dev, EMAC_FTR_HAS_TAH) &&
                (skb->ip_summed == CHECKSUM_PARTIAL)) {
@@ -1331,7 +1394,8 @@ static inline u16 emac_tx_csum(struct emac_instance *dev,
 static inline int emac_xmit_finish(struct emac_instance *dev, int len)
 {
        struct emac_regs __iomem *p = dev->emacp;
-       struct net_device *ndev = dev->ndev;
+       struct rtnet_device *ndev = dev->ndev;
+
 
        /* Send the packet out. If the if makes a significant perf
         * difference, then we can store the TMR0 value in "dev"
@@ -1343,11 +1407,13 @@ static inline int emac_xmit_finish(struct emac_instance 
*dev, int len)
                out_be32(&p->tmr0, EMAC_TMR0_XMIT);
 
        if (unlikely(++dev->tx_cnt == NUM_TX_BUFF)) {
-               netif_stop_queue(ndev);
+               rtnetif_stop_queue(ndev);
                DBG2(dev, "stopped TX queue" NL);
        }
 
+#ifdef ORIGINAL
        ndev->trans_start = jiffies;
+#endif
        ++dev->stats.tx_packets;
        dev->stats.tx_bytes += len;
 
@@ -1355,15 +1421,23 @@ static inline int emac_xmit_finish(struct emac_instance 
*dev, int len)
 }
 
 /* Tx lock BH */
-static int emac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+static int emac_start_xmit(struct rtskb *skb, struct rtnet_device *ndev)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        unsigned int len = skb->len;
-       int slot;
+       int slot, err;
+       u16 ctrl;
+       rtdm_lockctx_t context;
+
+       rtdm_lock_get_irqsave(&dev->lock, context);
 
-       u16 ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY |
+       ctrl = EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP | MAL_TX_CTRL_READY |
            MAL_TX_CTRL_LAST | emac_tx_csum(dev, skb);
 
+       if (skb->xmit_stamp)
+               *skb->xmit_stamp = cpu_to_be64(rtdm_clock_read() +
+                                              *skb->xmit_stamp);
+
        slot = dev->tx_slot++;
        if (dev->tx_slot == NUM_TX_BUFF) {
                dev->tx_slot = 0;
@@ -1380,7 +1454,11 @@ static int emac_start_xmit(struct sk_buff *skb, struct 
net_device *ndev)
        wmb();
        dev->tx_desc[slot].ctrl = ctrl;
 
-       return emac_xmit_finish(dev, len);
+       err = emac_xmit_finish(dev, len);
+
+       rtdm_lock_put_irqrestore(&dev->lock, context);
+
+       return err;
 }
 
 static inline int emac_xmit_split(struct emac_instance *dev, int slot,
@@ -1412,13 +1490,14 @@ static inline int emac_xmit_split(struct emac_instance 
*dev, int slot,
        return slot;
 }
 
+#ifdef ORIGINAL
 /* Tx lock BH disabled (SG version for TAH equipped EMACs) */
-static int emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev)
+static int emac_start_xmit_sg(struct rtskb *skb, struct rtnet_device *ndev)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        int nr_frags = skb_shinfo(skb)->nr_frags;
        int len = skb->len, chunk;
-       int slot, i;
+       int slot, i, err;
        u16 ctrl;
        u32 pd;
 
@@ -1476,7 +1555,7 @@ static int emac_start_xmit_sg(struct sk_buff *skb, struct 
net_device *ndev)
        dev->tx_desc[dev->tx_slot].ctrl = ctrl;
        dev->tx_slot = (slot + 1) % NUM_TX_BUFF;
 
-       return emac_xmit_finish(dev, skb->len);
+       return  emac_xmit_finish(dev, skb->len);
 
  undo_frame:
        /* Well, too bad. Our previous estimation was overly optimistic.
@@ -1491,10 +1570,11 @@ static int emac_start_xmit_sg(struct sk_buff *skb, 
struct net_device *ndev)
        ++dev->estats.tx_undo;
 
  stop_queue:
-       netif_stop_queue(ndev);
+       rtnetif_stop_queue(ndev);
        DBG2(dev, "stopped TX queue" NL);
        return NETDEV_TX_BUSY;
 }
+#endif
 
 /* Tx lock BHs */
 static void emac_parse_tx_error(struct emac_instance *dev, u16 ctrl)
@@ -1528,6 +1608,7 @@ static void emac_poll_tx(void *param)
 {
        struct emac_instance *dev = param;
        u32 bad_mask;
+        rtdm_lockctx_t context;
 
        DBG2(dev, "poll_tx, %d %d" NL, dev->tx_cnt, dev->ack_slot);
 
@@ -1536,18 +1617,22 @@ static void emac_poll_tx(void *param)
        else
                bad_mask = EMAC_IS_BAD_TX;
 
+#ifdef ORIGINAL
        netif_tx_lock_bh(dev->ndev);
+#else
+       rtdm_lock_get_irqsave(&dev->lock, context);
+#endif
        if (dev->tx_cnt) {
                u16 ctrl;
                int slot = dev->ack_slot, n = 0;
        again:
                ctrl = dev->tx_desc[slot].ctrl;
                if (!(ctrl & MAL_TX_CTRL_READY)) {
-                       struct sk_buff *skb = dev->tx_skb[slot];
+                       struct rtskb *skb = dev->tx_skb[slot];
                        ++n;
 
                        if (skb) {
-                               dev_kfree_skb(skb);
+                               kfree_rtskb(skb);
                                dev->tx_skb[slot] = NULL;
                        }
                        slot = (slot + 1) % NUM_TX_BUFF;
@@ -1560,20 +1645,24 @@ static void emac_poll_tx(void *param)
                }
                if (n) {
                        dev->ack_slot = slot;
-                       if (netif_queue_stopped(dev->ndev) &&
+                       if (rtnetif_queue_stopped(dev->ndev) &&
                            dev->tx_cnt < EMAC_TX_WAKEUP_THRESH)
-                               netif_wake_queue(dev->ndev);
+                               rtnetif_wake_queue(dev->ndev);
 
-                       DBG2(dev, "tx %d pkts" NL, n);
+                       DBG2(dev, "tx %d pkts, slot %d" NL, n, slot);
                }
        }
+#ifdef ORIGINAL
        netif_tx_unlock_bh(dev->ndev);
+#else
+       rtdm_lock_put_irqrestore(&dev->lock, context);
+#endif
 }
 
 static inline void emac_recycle_rx_skb(struct emac_instance *dev, int slot,
                                       int len)
 {
-       struct sk_buff *skb = dev->rx_skb[slot];
+       struct rtskb *skb = dev->rx_skb[slot];
 
        DBG2(dev, "recycle %d %d" NL, slot, len);
 
@@ -1615,7 +1704,7 @@ static void emac_parse_rx_error(struct emac_instance 
*dev, u16 ctrl)
 }
 
 static inline void emac_rx_csum(struct emac_instance *dev,
-                               struct sk_buff *skb, u16 ctrl)
+                               struct rtskb *skb, u16 ctrl)
 {
 #ifdef CONFIG_IBM_NEW_EMAC_TAH
        if (!ctrl && dev->tah_dev) {
@@ -1633,12 +1722,12 @@ static inline int emac_rx_sg_append(struct 
emac_instance *dev, int slot)
 
                if (unlikely(tot_len + 2 > dev->rx_skb_size)) {
                        ++dev->estats.rx_dropped_mtu;
-                       dev_kfree_skb(dev->rx_sg_skb);
+                       kfree_rtskb(dev->rx_sg_skb);
                        dev->rx_sg_skb = NULL;
                } else {
-                       cacheable_memcpy(skb_tail_pointer(dev->rx_sg_skb),
+                       cacheable_memcpy(rtskb_tail_pointer(dev->rx_sg_skb),
                                         dev->rx_skb[slot]->data, len);
-                       skb_put(dev->rx_sg_skb, len);
+                       rtskb_put(dev->rx_sg_skb, len);
                        emac_recycle_rx_skb(dev, slot, len);
                        return 0;
                }
@@ -1658,7 +1747,7 @@ static int emac_poll_rx(void *param, int budget)
  again:
        while (budget > 0) {
                int len;
-               struct sk_buff *skb;
+               struct rtskb *skb;
                u16 ctrl = dev->rx_desc[slot].ctrl;
 
                if (ctrl & MAL_RX_CTRL_EMPTY)
@@ -1687,12 +1776,15 @@ static int emac_poll_rx(void *param, int budget)
                }
 
                if (len && len < EMAC_RX_COPY_THRESH) {
-                       struct sk_buff *copy_skb =
-                           alloc_skb(len + EMAC_RX_SKB_HEADROOM + 2, 
GFP_ATOMIC);
+                       struct rtskb *copy_skb =
+                           dev_alloc_rtskb(len + EMAC_RX_SKB_HEADROOM + 2,
+                                           &dev->skb_pool);
                        if (unlikely(!copy_skb))
                                goto oom;
 
-                       skb_reserve(copy_skb, EMAC_RX_SKB_HEADROOM + 2);
+                       copy_skb->rtdev = dev->ndev;
+
+                       rtskb_reserve(copy_skb, EMAC_RX_SKB_HEADROOM + 2);
                        cacheable_memcpy(copy_skb->data - 2, skb->data - 2,
                                         len + 2);
                        emac_recycle_rx_skb(dev, slot, len);
@@ -1700,13 +1792,18 @@ static int emac_poll_rx(void *param, int budget)
                } else if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC)))
                        goto oom;
 
-               skb_put(skb, len);
+               rtskb_put(skb, len);
        push_packet:
-               skb->protocol = eth_type_trans(skb, dev->ndev);
+               skb->protocol = rt_eth_type_trans(skb, dev->ndev);
+               skb->time_stamp = dev->mal->time_stamp;
                emac_rx_csum(dev, skb, ctrl);
 
-               if (unlikely(netif_receive_skb(skb) == NET_RX_DROP))
+#ifdef ORIGINAL
+               if (unlikely(rtnetif_receive_skb(skb) == NET_RX_DROP))
                        ++dev->estats.rx_dropped_stack;
+#else
+               rtnetif_rx(skb);
+#endif
        next:
                ++dev->stats.rx_packets;
        skip:
@@ -1724,7 +1821,7 @@ static int emac_poll_rx(void *param, int budget)
                                emac_recycle_rx_skb(dev, slot, 0);
                        } else {
                                dev->rx_sg_skb = skb;
-                               skb_put(skb, len);
+                               rtskb_put(skb, len);
                        }
                } else if (!emac_rx_sg_append(dev, slot) &&
                           (ctrl & MAL_RX_CTRL_LAST)) {
@@ -1736,7 +1833,7 @@ static int emac_poll_rx(void *param, int budget)
                        if (unlikely(ctrl && ctrl != EMAC_RX_TAH_BAD_CSUM)) {
                                emac_parse_rx_error(dev, ctrl);
                                ++dev->estats.rx_dropped_error;
-                               dev_kfree_skb(skb);
+                               kfree_rtskb(skb);
                                len = 0;
                        } else
                                goto push_packet;
@@ -1766,7 +1863,7 @@ static int emac_poll_rx(void *param, int budget)
                if (dev->rx_sg_skb) {
                        DBG2(dev, "dropping partial rx packet" NL);
                        ++dev->estats.rx_dropped_error;
-                       dev_kfree_skb(dev->rx_sg_skb);
+                       kfree_rtskb(dev->rx_sg_skb);
                        dev->rx_sg_skb = NULL;
                }
 
@@ -1775,6 +1872,9 @@ static int emac_poll_rx(void *param, int budget)
                emac_rx_enable(dev);
                dev->rx_slot = 0;
        }
+
+       if (received)
+               rt_mark_stack_mgr(dev->ndev);
        return received;
 }
 
@@ -1817,14 +1917,17 @@ static void emac_rxde(void *param)
 }
 
 /* Hard IRQ */
-static irqreturn_t emac_irq(int irq, void *dev_instance)
+static int emac_irq(rtdm_irq_t *irq_handle)
 {
-       struct emac_instance *dev = dev_instance;
+       struct rtnet_device *netdev = rtdm_irq_get_arg(irq_handle,
+                                                      struct rtnet_device);
+       struct emac_instance *dev = rtnetdev_priv(netdev);
        struct emac_regs __iomem *p = dev->emacp;
        struct emac_error_stats *st = &dev->estats;
        u32 isr;
+       rtdm_lockctx_t context;
 
-       spin_lock(&dev->lock);
+       rtdm_lock_get_irqsave(&dev->lock, context);
 
        isr = in_be32(&p->isr);
        out_be32(&p->isr, isr);
@@ -1862,23 +1965,23 @@ static irqreturn_t emac_irq(int irq, void *dev_instance)
        if (isr & EMAC_ISR_TE)
                ++st->tx_errors;
 
-       spin_unlock(&dev->lock);
+       rtdm_lock_put_irqrestore(&dev->lock, context);
 
-       return IRQ_HANDLED;
+       return RTDM_IRQ_HANDLED;
 }
 
-static struct net_device_stats *emac_stats(struct net_device *ndev)
+static struct net_device_stats *emac_stats(struct rtnet_device *ndev)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        struct emac_stats *st = &dev->stats;
        struct emac_error_stats *est = &dev->estats;
        struct net_device_stats *nst = &dev->nstats;
-       unsigned long flags;
+       rtdm_lockctx_t context;
 
        DBG2(dev, "stats" NL);
 
        /* Compute "legacy" statistics */
-       spin_lock_irqsave(&dev->lock, flags);
+       rtdm_lock_get_irqsave(&dev->lock, context);
        nst->rx_packets = (unsigned long)st->rx_packets;
        nst->rx_bytes = (unsigned long)st->rx_bytes;
        nst->tx_packets = (unsigned long)st->tx_packets;
@@ -1916,7 +2019,7 @@ static struct net_device_stats *emac_stats(struct 
net_device *ndev)
                                          est->tx_bd_excessive_collisions +
                                          est->tx_bd_late_collision +
                                          est->tx_bd_multple_collisions);
-       spin_unlock_irqrestore(&dev->lock, flags);
+       rtdm_lock_put_irqrestore(&dev->lock, context);
        return nst;
 }
 
@@ -1934,11 +2037,12 @@ static struct mal_commac_ops emac_commac_sg_ops = {
        .rxde = &emac_rxde,
 };
 
+#ifdef ORIGINAL
 /* Ethtool support */
-static int emac_ethtool_get_settings(struct net_device *ndev,
+static int emac_ethtool_get_settings(struct rtnet_device *ndev,
                                     struct ethtool_cmd *cmd)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
 
        cmd->supported = dev->phy.features;
        cmd->port = PORT_MII;
@@ -1956,10 +2060,10 @@ static int emac_ethtool_get_settings(struct net_device 
*ndev,
        return 0;
 }
 
-static int emac_ethtool_set_settings(struct net_device *ndev,
+static int emac_ethtool_set_settings(struct rtnet_device *ndev,
                                     struct ethtool_cmd *cmd)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        u32 f = dev->phy.features;
 
        DBG(dev, "set_settings(%d, %d, %d, 0x%08x)" NL,
@@ -2027,17 +2131,17 @@ static int emac_ethtool_set_settings(struct net_device 
*ndev,
        return 0;
 }
 
-static void emac_ethtool_get_ringparam(struct net_device *ndev,
+static void emac_ethtool_get_ringparam(struct rtnet_device *ndev,
                                       struct ethtool_ringparam *rp)
 {
        rp->rx_max_pending = rp->rx_pending = NUM_RX_BUFF;
        rp->tx_max_pending = rp->tx_pending = NUM_TX_BUFF;
 }
 
-static void emac_ethtool_get_pauseparam(struct net_device *ndev,
+static void emac_ethtool_get_pauseparam(struct rtnet_device *ndev,
                                        struct ethtool_pauseparam *pp)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
 
        mutex_lock(&dev->link_lock);
        if ((dev->phy.features & SUPPORTED_Autoneg) &&
@@ -2053,9 +2157,9 @@ static void emac_ethtool_get_pauseparam(struct net_device 
*ndev,
        mutex_unlock(&dev->link_lock);
 }
 
-static u32 emac_ethtool_get_rx_csum(struct net_device *ndev)
+static u32 emac_ethtool_get_rx_csum(struct rtnet_device *ndev)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
 
        return dev->tah_dev != NULL;
 }
@@ -2070,9 +2174,9 @@ static int emac_get_regs_len(struct emac_instance *dev)
                        EMAC_ETHTOOL_REGS_SIZE(dev);
 }
 
-static int emac_ethtool_get_regs_len(struct net_device *ndev)
+static int emac_ethtool_get_regs_len(struct rtnet_device *ndev)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        int size;
 
        size = sizeof(struct emac_ethtool_regs_hdr) +
@@ -2103,10 +2207,10 @@ static void *emac_dump_regs(struct emac_instance *dev, 
void *buf)
        }
 }
 
-static void emac_ethtool_get_regs(struct net_device *ndev,
+static void emac_ethtool_get_regs(struct rtnet_device *ndev,
                                  struct ethtool_regs *regs, void *buf)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        struct emac_ethtool_regs_hdr *hdr = buf;
 
        hdr->components = 0;
@@ -2128,9 +2232,9 @@ static void emac_ethtool_get_regs(struct net_device *ndev,
        }
 }
 
-static int emac_ethtool_nway_reset(struct net_device *ndev)
+static int emac_ethtool_nway_reset(struct rtnet_device *ndev)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        int res = 0;
 
        DBG(dev, "nway_reset" NL);
@@ -2151,7 +2255,7 @@ static int emac_ethtool_nway_reset(struct net_device 
*ndev)
        return res;
 }
 
-static int emac_ethtool_get_sset_count(struct net_device *ndev, int stringset)
+static int emac_ethtool_get_sset_count(struct rtnet_device *ndev, int 
stringset)
 {
        if (stringset == ETH_SS_STATS)
                return EMAC_ETHTOOL_STATS_COUNT;
@@ -2159,28 +2263,28 @@ static int emac_ethtool_get_sset_count(struct 
net_device *ndev, int stringset)
                return -EINVAL;
 }
 
-static void emac_ethtool_get_strings(struct net_device *ndev, u32 stringset,
+static void emac_ethtool_get_strings(struct rtnet_device *ndev, u32 stringset,
                                     u8 * buf)
 {
        if (stringset == ETH_SS_STATS)
                memcpy(buf, &emac_stats_keys, sizeof(emac_stats_keys));
 }
 
-static void emac_ethtool_get_ethtool_stats(struct net_device *ndev,
+static void emac_ethtool_get_ethtool_stats(struct rtnet_device *ndev,
                                           struct ethtool_stats *estats,
                                           u64 * tmp_stats)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
 
        memcpy(tmp_stats, &dev->stats, sizeof(dev->stats));
        tmp_stats += sizeof(dev->stats) / sizeof(u64);
        memcpy(tmp_stats, &dev->estats, sizeof(dev->estats));
 }
 
-static void emac_ethtool_get_drvinfo(struct net_device *ndev,
+static void emac_ethtool_get_drvinfo(struct rtnet_device *ndev,
                                     struct ethtool_drvinfo *info)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
 
        strcpy(info->driver, "ibm_emac");
        strcpy(info->version, DRV_VERSION);
@@ -2214,9 +2318,9 @@ static const struct ethtool_ops emac_ethtool_ops = {
        .get_sg = ethtool_op_get_sg,
 };
 
-static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
+static int emac_ioctl(struct rtnet_device *ndev, struct ifreq *rq, int cmd)
 {
-       struct emac_instance *dev = netdev_priv(ndev);
+       struct emac_instance *dev = rtnetdev_priv(ndev);
        struct mii_ioctl_data *data = if_mii(rq);
 
        DBG(dev, "ioctl %08x" NL, cmd);
@@ -2241,6 +2345,7 @@ static int emac_ioctl(struct net_device *ndev, struct 
ifreq *rq, int cmd)
                return -EOPNOTSUPP;
        }
 }
+#endif
 
 struct emac_depentry {
        u32                     phandle;
@@ -2381,11 +2486,11 @@ static int __devinit emac_read_uint_prop(struct 
device_node *np, const char *nam
 static int __devinit emac_init_phy(struct emac_instance *dev)
 {
        struct device_node *np = dev->ofdev->dev.of_node;
-       struct net_device *ndev = dev->ndev;
+       struct rtnet_device *ndev = dev->ndev;
        u32 phy_map, adv;
        int i;
 
-       dev->phy.dev = ndev;
+       dev->phy.dev = (void *)ndev;
        dev->phy.mode = dev->phy_mode;
 
        /* PHY-less configuration.
@@ -2413,8 +2518,9 @@ static int __devinit emac_init_phy(struct emac_instance 
*dev)
 
        DBG(dev, "PHY maps %08x %08x" NL, dev->phy_map, busy_phy_map);
 
-       dev->phy.mdio_read = emac_mdio_read;
-       dev->phy.mdio_write = emac_mdio_write;
+       /* Dirty hack. Let's hope that the first parameter is not used inside */
+       dev->phy.mdio_read = (void *)emac_mdio_read;
+       dev->phy.mdio_write = (void *)emac_mdio_write;
 
        /* Enable internal clock source */
 #ifdef CONFIG_PPC_DCR_NATIVE
@@ -2455,7 +2561,6 @@ static int __devinit emac_init_phy(struct emac_instance 
*dev)
                if (!(phy_map & 1)) {
                        int r;
                        busy_phy_map |= 1 << i;
-
                        /* Quick check if there is a PHY at the address */
                        r = emac_mdio_read(dev->ndev, i, MII_BMCR);
                        if (r == 0xffff || r < 0)
@@ -2693,6 +2798,7 @@ static int __devinit emac_init_config(struct 
emac_instance *dev)
        return 0;
 }
 
+#ifdef ORIGINAL
 static const struct net_device_ops emac_netdev_ops = {
        .ndo_open               = emac_open,
        .ndo_stop               = emac_close,
@@ -2718,11 +2824,16 @@ static const struct net_device_ops emac_gige_netdev_ops 
= {
        .ndo_start_xmit         = emac_start_xmit_sg,
        .ndo_change_mtu         = emac_change_mtu,
 };
+#endif
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
 static int __devinit emac_probe(struct platform_device *ofdev,
                                const struct of_device_id *match)
+#else
+static int __devinit emac_probe(struct platform_device *ofdev)
+#endif
 {
-       struct net_device *ndev;
+       struct rtnet_device *ndev;
        struct emac_instance *dev;
        struct device_node *np = ofdev->dev.of_node;
        struct device_node **blist = NULL;
@@ -2742,22 +2853,31 @@ static int __devinit emac_probe(struct platform_device 
*ofdev,
 
        /* Allocate our net_device structure */
        err = -ENOMEM;
-       ndev = alloc_etherdev(sizeof(struct emac_instance));
+       ndev = rt_alloc_etherdev(sizeof(struct emac_instance));
        if (!ndev) {
                printk(KERN_ERR "%s: could not allocate ethernet device!\n",
                       np->full_name);
                goto err_gone;
        }
-       dev = netdev_priv(ndev);
+
+       rtdev_alloc_name(ndev, "rteth%d");
+       rt_rtdev_connect(ndev, &RTDEV_manager);
+       RTNET_SET_MODULE_OWNER(ndev);
+
+       ndev->vers = RTDEV_VERS_2_0;
+
+       dev = rtnetdev_priv(ndev);
        dev->ndev = ndev;
        dev->ofdev = ofdev;
        dev->blist = blist;
+#ifdef ORIGINAL
        SET_NETDEV_DEV(ndev, &ofdev->dev);
+#endif
 
        /* Initialize some embedded data structures */
        mutex_init(&dev->mdio_lock);
        mutex_init(&dev->link_lock);
-       spin_lock_init(&dev->lock);
+       rtdm_lock_init(&dev->lock);
        INIT_WORK(&dev->reset_work, emac_reset_work);
 
        /* Init various config data based on device-tree */
@@ -2804,6 +2924,7 @@ static int __devinit emac_probe(struct platform_device 
*ofdev,
                dev->mdio_instance = dev_get_drvdata(&dev->mdio_dev->dev);
 
        /* Register with MAL */
+       dev->commac.rtdm = 1;   /* use MAL from RDTM context */
        dev->commac.ops = &emac_commac_ops;
        dev->commac.dev = dev;
        dev->commac.tx_chan_mask = MAL_CHAN_MASK(dev->mal_tx_chan);
@@ -2829,8 +2950,8 @@ static int __devinit emac_probe(struct platform_device 
*ofdev,
        /* Clean rings */
        memset(dev->tx_desc, 0, NUM_TX_BUFF * sizeof(struct mal_descriptor));
        memset(dev->rx_desc, 0, NUM_RX_BUFF * sizeof(struct mal_descriptor));
-       memset(dev->tx_skb, 0, NUM_TX_BUFF * sizeof(struct sk_buff *));
-       memset(dev->rx_skb, 0, NUM_RX_BUFF * sizeof(struct sk_buff *));
+       memset(dev->tx_skb, 0, NUM_TX_BUFF * sizeof(struct rtskb *));
+       memset(dev->rx_skb, 0, NUM_RX_BUFF * sizeof(struct rtskb *));
 
        /* Attach to ZMII, if needed */
        if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII) &&
@@ -2862,6 +2983,7 @@ static int __devinit emac_probe(struct platform_device 
*ofdev,
 
        if (dev->tah_dev)
                ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+#ifdef ORIGINAL
        ndev->watchdog_timeo = 5 * HZ;
        if (emac_phy_supports_gige(dev->phy_mode)) {
                ndev->netdev_ops = &emac_gige_netdev_ops;
@@ -2869,11 +2991,26 @@ static int __devinit emac_probe(struct platform_device 
*ofdev,
        } else
                ndev->netdev_ops = &emac_netdev_ops;
        SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops);
+#else
+       if (emac_phy_supports_gige(dev->phy_mode))
+               dev->commac.ops = &emac_commac_sg_ops;
+       ndev->open = emac_open;
+       ndev->stop = emac_close;
+       ndev->get_stats = emac_stats;
+       ndev->hard_start_xmit = emac_start_xmit;
+#endif
 
-       netif_carrier_off(ndev);
-       netif_stop_queue(ndev);
+        if (rtskb_pool_init(&dev->skb_pool, NUM_RX_BUFF * 2) <
+           NUM_RX_BUFF * 2) {
+               rtskb_pool_release(&dev->skb_pool);
+               return -ENOMEM;
+        }
 
-       err = register_netdev(ndev);
+       rtnetif_carrier_off(ndev);
+       rtnetif_stop_queue(ndev);
+
+       strcpy(ndev->name, "rteth%d");
+       err = rt_register_rtnetdev(ndev);
        if (err) {
                printk(KERN_ERR "%s: failed to register net device (%d)!\n",
                       np->full_name, err);
@@ -2889,7 +3026,6 @@ static int __devinit emac_probe(struct platform_device 
*ofdev,
        /* There's a new kid in town ! Let's tell everybody */
        wake_up_all(&emac_probe_wait);
 
-
        printk(KERN_INFO "%s: EMAC-%d %s, MAC %pM\n",
               ndev->name, dev->cell_index, np->full_name, ndev->dev_addr);
 
@@ -2900,7 +3036,9 @@ static int __devinit emac_probe(struct platform_device 
*ofdev,
                printk("%s: found %s PHY (0x%02x)\n", ndev->name,
                       dev->phy.def->name, dev->phy.address);
 
+#ifdef ORIGINAL
        emac_dbg_register(dev);
+#endif
 
        /* Life is good */
        return 0;
@@ -2928,7 +3066,7 @@ static int __devinit emac_probe(struct platform_device 
*ofdev,
        if (dev->emac_irq != NO_IRQ)
                irq_dispose_mapping(dev->emac_irq);
  err_free:
-       free_netdev(ndev);
+       rtdev_free(ndev);
  err_gone:
        /* if we were on the bootlist, remove us as we won't show up and
         * wake up all waiters to notify them in case they were waiting
@@ -2949,9 +3087,13 @@ static int __devexit emac_remove(struct platform_device 
*ofdev)
 
        dev_set_drvdata(&ofdev->dev, NULL);
 
-       unregister_netdev(dev->ndev);
+       rt_unregister_rtnetdev(dev->ndev);
 
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,37)
        flush_scheduled_work();
+#else
+       cancel_work_sync(&dev->reset_work);
+#endif
 
        if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))
                tah_detach(dev->tah_dev, dev->tah_port);
@@ -2960,10 +3102,17 @@ static int __devexit emac_remove(struct platform_device 
*ofdev)
        if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII))
                zmii_detach(dev->zmii_dev, dev->zmii_port);
 
+       busy_phy_map &= ~(1 << dev->phy.address);
+       DBG(dev, "busy_phy_map now %#x" NL, busy_phy_map);
+
        mal_unregister_commac(dev->mal, &dev->commac);
        emac_put_deps(dev);
 
+       rtskb_pool_release(&dev->skb_pool);
+
+#ifdef ORIGINAL
        emac_dbg_unregister(dev);
+#endif
        iounmap(dev->emacp);
 
        if (dev->wol_irq != NO_IRQ)
@@ -2971,12 +3120,11 @@ static int __devexit emac_remove(struct platform_device 
*ofdev)
        if (dev->emac_irq != NO_IRQ)
                irq_dispose_mapping(dev->emac_irq);
 
-       free_netdev(dev->ndev);
+       rtdev_free(dev->ndev);
 
        return 0;
 }
 
-/* XXX Features in here should be replaced by properties... */
 static struct of_device_id emac_match[] =
 {
        {
@@ -2995,9 +3143,13 @@ static struct of_device_id emac_match[] =
 };
 MODULE_DEVICE_TABLE(of, emac_match);
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
 static struct of_platform_driver emac_driver = {
+#else
+static struct platform_driver emac_driver = {
+#endif
        .driver = {
-               .name = "emac",
+               .name = "rt-emac",
                .owner = THIS_MODULE,
                .of_match_table = emac_match,
        },
@@ -3047,16 +3199,21 @@ static void __init emac_make_bootlist(void)
 
 static int __init emac_init(void)
 {
+#ifdef ORIGINAL
        int rc;
+#endif
 
        printk(KERN_INFO DRV_DESC ", version " DRV_VERSION "\n");
 
+#ifdef ORIGINAL
        /* Init debug stuff */
        emac_init_debug();
+#endif
 
        /* Build EMAC boot list */
        emac_make_bootlist();
 
+#ifdef ORIGINAL
        /* Init submodules */
        rc = mal_init();
        if (rc)
@@ -3086,14 +3243,27 @@ static int __init emac_init(void)
        mal_exit();
  err:
        return rc;
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
+       return of_register_platform_driver(&emac_driver);
+#else
+       return platform_driver_register(&emac_driver);
+#endif
+#endif
 }
 
 static void __exit emac_exit(void)
 {
+#ifdef ORIGINAL
        int i;
-
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
        of_unregister_platform_driver(&emac_driver);
+#else
+       platform_driver_unregister(&emac_driver);
+#endif
 
+#ifdef ORIGINAL
        tah_exit();
        rgmii_exit();
        zmii_exit();
@@ -3104,6 +3274,7 @@ static void __exit emac_exit(void)
        for (i = 0; i < EMAC_BOOT_LIST_SIZE; i++)
                if (emac_boot_list[i])
                        of_node_put(emac_boot_list[i]);
+#endif
 }
 
 module_init(emac_init);
diff --git a/drivers/ibm_newemac/core.h b/drivers/ibm_newemac/core.h
index 9e37e3d..5f66d32 100644
--- a/drivers/ibm_newemac/core.h
+++ b/drivers/ibm_newemac/core.h
@@ -33,12 +33,15 @@
 #include <linux/netdevice.h>
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
+#include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 
 #include <asm/io.h>
 #include <asm/dcr.h>
 
+#include <rtnet_port.h>
+
 #include "emac.h"
 #include "phy.h"
 #include "zmii.h"
@@ -47,8 +50,8 @@
 #include "tah.h"
 #include "debug.h"
 
-#define NUM_TX_BUFF                    CONFIG_IBM_NEW_EMAC_TXB
-#define NUM_RX_BUFF                    CONFIG_IBM_NEW_EMAC_RXB
+#define NUM_TX_BUFF                    16
+#define NUM_RX_BUFF                    32
 
 /* Simple sanity check */
 #if NUM_TX_BUFF > 256 || NUM_RX_BUFF > 256
@@ -167,7 +170,8 @@ struct emac_error_stats {
                                         / sizeof(u64))
 
 struct emac_instance {
-       struct net_device               *ndev;
+       struct rtnet_device             *ndev;
+       struct rtskb_queue              skb_pool;
        struct resource                 rsrc_regs;
        struct emac_regs                __iomem *emacp;
        struct platform_device          *ofdev;
@@ -218,6 +222,7 @@ struct emac_instance {
        /* IRQs */
        int                             wol_irq;
        int                             emac_irq;
+       rtdm_irq_t                      emac_irq_handle;
 
        /* OPB bus frequency in Mhz */
        u32                             opb_bus_freq;
@@ -252,12 +257,12 @@ struct emac_instance {
 
        struct mal_descriptor           *rx_desc;
        int                             rx_slot;
-       struct sk_buff                  *rx_sg_skb;     /* 1 */
+       struct rtskb                    *rx_sg_skb;     /* 1 */
        int                             rx_skb_size;
        int                             rx_sync_size;
 
-       struct sk_buff                  *tx_skb[NUM_TX_BUFF];
-       struct sk_buff                  *rx_skb[NUM_RX_BUFF];
+       struct rtskb                    *tx_skb[NUM_TX_BUFF];
+       struct rtskb                    *rx_skb[NUM_RX_BUFF];
 
        /* Stats
         */
@@ -269,11 +274,13 @@ struct emac_instance {
         */
        int                             reset_failed;
        int                             stop_timeout;   /* in us */
+#ifdef WITH_MULTICAST
        int                             no_mcast;
        int                             mcast_pending;
+#endif
        int                             opened;
        struct work_struct              reset_work;
-       spinlock_t                      lock;
+       rtdm_lock_t                     lock;
 };
 
 /*
@@ -459,4 +466,7 @@ struct emac_ethtool_regs_subhdr {
 #define EMAC4_ETHTOOL_REGS_SIZE(dev)   ((dev)->rsrc_regs.end - \
                                         (dev)->rsrc_regs.start + 1)
 
+#define rtnetdev_priv(ndev)            (ndev)->priv
+#define rtskb_tail_pointer(skb)        (skb)->tail
+
 #endif /* __IBM_NEWEMAC_CORE_H */
-- 
1.7.4.1


------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure 
contains a definitive record of customers, application performance, 
security threats, fraudulent activity, and more. Splunk takes this 
data and makes sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-novd2d
_______________________________________________
RTnet-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rtnet-developers

Reply via email to