From: Wolfgang Grandegger <wg...@de...>
The IBM-EMACS driver requires a separate Linux kernel patch implementing
a common real-time capable Memory Access Layer (MAL) and providing
direct access to the PHY interface from the corresponding Linux driver.
Signed-off-by: Wolfgang Grandegger <wg...@de...>
---
drivers/ibm_newemac/README | 32 +
.../ibm_newemac/linux-2.6.36.4-rtdm-ibm-emac.patch | 875 ++++++++++++++++++++
.../ibm_newemac/linux-3.0.4-rtdm-ibm-emac.patch | 875 ++++++++++++++++++++
3 files changed, 1782 insertions(+), 0 deletions(-)
create mode 100644 drivers/ibm_newemac/README
create mode 100644 drivers/ibm_newemac/linux-2.6.36.4-rtdm-ibm-emac.patch
create mode 100644 drivers/ibm_newemac/linux-3.0.4-rtdm-ibm-emac.patch
diff --git a/drivers/ibm_newemac/README b/drivers/ibm_newemac/README
new file mode 100644
index 0000000..99e991e
--- /dev/null
+++ b/drivers/ibm_newemac/README
@@ -0,0 +1,32 @@
+This RTnet driver is for the EMAC Ethernet controllers on AMCC 4xx
+processors. It requires a *separate* Linux kernel patch to provide a
+real-time capable memory access layer (MAL). See chapter "Technical
+comments" below for further information. At the time of writing, the
+following patches are available in this directory:
+
+- linux-2.6.36.4-rtdm-ibm-emac.patch
+- linux-3.0.4-rtdm-ibm-emac.patch
+
+They also fix a cleanup issue to allow re-binding of the driver. After
+applying the patch, you need to enable "CONFIG_IBM_NEW_EMAC_MAL_RTDM".
+If you use RTnet and Linux networking drivers concurrently on different
+EMAC controllers, you need to unbind the Linux driver from the device
+before loading the RTnet EMAC driver:
+
+# echo "1ef600f00.ethernet" > \
+ /sys/bus/platform/devices/1ef600f00.ethernet/driver/unbind
+# insmod rt_ibm_emac.ko
+
+Technical comments:
+------------------
+
+The two IBM-EMAC on the AMCC 44x processors share a common memory
+access layer (MAL) for transferring packages from the EMAC to the
+memory and vise versa. Unfortunately, there is only one interrupt
+line for RX and TX, which requires handling these interrupts in the
+real-time context. This means, that the two EMACs do influence each
+other to some extend, e.g. heavy traffic on the EMAC used for Linux
+networking does influence the other EMAC used for RTnet traffic.
+So far, I did not see real problems. The maximum round-trip time
+measured with "rtt-sender <-> rtt-responder" did not increase 250us,
+even under heavy packet storms provoked on the EMAC used for Linux.
diff --git a/drivers/ibm_newemac/linux-2.6.36.4-rtdm-ibm-emac.patch b/drivers/ibm_newemac/linux-2.6.36.4-rtdm-ibm-emac.patch
new file mode 100644
index 0000000..bafc780
--- /dev/null
+++ b/drivers/ibm_newemac/linux-2.6.36.4-rtdm-ibm-emac.patch
@@ -0,0 +1,875 @@
+From 7b2172814c8a98d44f963159063707a391c74085 Mon Sep 17 00:00:00 2001
+From: Wolfgang Grandegger <wg...@gr...>
+Date: Thu, 17 Nov 2011 13:11:31 +0100
+Subject: [PATCH] net/ibm_newemac: provide real-time capable RTDM MAL driver
+
+Signed-off-by: Wolfgang Grandegger <wg...@gr...>
+---
+ drivers/net/ibm_newemac/Kconfig | 5 +
+ drivers/net/ibm_newemac/Makefile | 4 +
+ drivers/net/ibm_newemac/core.c | 5 +
+ drivers/net/ibm_newemac/mal.c | 358 ++++++++++++++++++++++++++++++++++---
+ drivers/net/ibm_newemac/mal.h | 27 +++
+ drivers/net/ibm_newemac/phy.c | 7 +
+ drivers/net/ibm_newemac/rgmii.c | 8 +
+ drivers/net/ibm_newemac/zmii.c | 9 +
+ 8 files changed, 394 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/net/ibm_newemac/Kconfig b/drivers/net/ibm_newemac/Kconfig
+index 78a1628..b5696e1 100644
+--- a/drivers/net/ibm_newemac/Kconfig
++++ b/drivers/net/ibm_newemac/Kconfig
+@@ -39,6 +39,11 @@ config IBM_NEW_EMAC_RX_SKB_HEADROOM
+
+ If unsure, set to 0.
+
++config IBM_NEW_EMAC_MAL_RTDM
++ bool "Real-time MAL"
++ depends on IBM_NEW_EMAC && XENO_SKIN_RTDM
++ default n
++
+ config IBM_NEW_EMAC_DEBUG
+ bool "Debugging"
+ depends on IBM_NEW_EMAC
+diff --git a/drivers/net/ibm_newemac/Makefile b/drivers/net/ibm_newemac/Makefile
+index 0b5c995..ab82084 100644
+--- a/drivers/net/ibm_newemac/Makefile
++++ b/drivers/net/ibm_newemac/Makefile
+@@ -2,6 +2,10 @@
+ # Makefile for the PowerPC 4xx on-chip ethernet driver
+ #
+
++ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++EXTRA_CFLAGS += -D__IN_XENOMAI__ -Iinclude/xenomai
++endif
++
+ obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac.o
+
+ ibm_newemac-y := mal.o core.o phy.o
+diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
+index 519e19e..55136b8 100644
+--- a/drivers/net/ibm_newemac/core.c
++++ b/drivers/net/ibm_newemac/core.c
+@@ -2960,6 +2960,9 @@ 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);
+
+@@ -3108,3 +3111,5 @@ static void __exit emac_exit(void)
+
+ module_init(emac_init);
+ module_exit(emac_exit);
++
++EXPORT_SYMBOL_GPL(busy_phy_map);
+diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
+index d5717e2..75f04b1 100644
+--- a/drivers/net/ibm_newemac/mal.c
++++ b/drivers/net/ibm_newemac/mal.c
+@@ -18,6 +18,10 @@
+ * Armin Kuster <ak...@mv...>
+ * Copyright 2002 MontaVista Softare Inc.
+ *
++ * Real-time extension required for the RTnet IBM EMAC driver
++ *
++ * Copyright 2011 Wolfgang Grandegger <wg...@de...>
++ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+@@ -31,6 +35,27 @@
+ #include "core.h"
+ #include <asm/dcr-regs.h>
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++#define MAL_IRQ_HANDLED RTDM_IRQ_HANDLED
++#define mal_spin_lock_irqsave(lock, flags) \
++ do { rtdm_lock_get_irqsave(lock, flags); } while (0)
++#define mal_spin_unlock_irqrestore(lock, flags) \
++ do { rtdm_lock_put_irqrestore(lock, flags); } while (0)
++#define mal_spin_lock_init(lock) \
++ do { rtdm_lock_init(lock); } while (0)
++static DEFINE_RTDM_RATELIMIT_STATE(mal_net_ratelimit_state, 5000000000LL, 10);
++#define mal_net_ratelimit() rtdm_ratelimit(&mal_net_ratelimit_state, __func__)
++#else
++#define MAL_IRQ_HANDLED IRQ_HANDLED
++#define mal_spin_lock_irqsave(lock, flags) \
++ do { spin_lock_irqsave(lock, flags);; } while (0)
++#define mal_spin_unlock_irqrestore(lock, flags) \
++ do { spin_unlock_irqrestore(lock, flags); } while (0)
++#define mal_spin_lock_init(lock) \
++ do { spin_lock_init(lock); } while (0)
++#define mal_net_ratelimit() net_ratelimit()
++#endif
++
+ static int mal_count;
+
+ int __devinit mal_register_commac(struct mal_instance *mal,
+@@ -38,27 +63,49 @@ int __devinit mal_register_commac(struct mal_instance *mal,
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&mal->lock, flags);
+-
++ mal_spin_lock_irqsave(&mal->lock, flags);
+ MAL_DBG(mal, "reg(%08x, %08x)" NL,
+ commac->tx_chan_mask, commac->rx_chan_mask);
+
+ /* Don't let multiple commacs claim the same channel(s) */
++
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (((mal->tx_chan_mask | mal->tx_chan_mask_rtdm) &
++ commac->tx_chan_mask) ||
++ ((mal->rx_chan_mask | mal->rx_chan_mask_rtdm) &
++ commac->rx_chan_mask)) {
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
++ printk(KERN_WARNING "mal%d: COMMAC channels conflict!\n",
++ mal->index);
++ return -EBUSY;
++ }
++#else
+ if ((mal->tx_chan_mask & commac->tx_chan_mask) ||
+ (mal->rx_chan_mask & commac->rx_chan_mask)) {
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ printk(KERN_WARNING "mal%d: COMMAC channels conflict!\n",
+ mal->index);
+ return -EBUSY;
+ }
++#endif
+
+ if (list_empty(&mal->list))
+ napi_enable(&mal->napi);
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (commac->rtdm) {
++ mal->tx_chan_mask_rtdm |= commac->tx_chan_mask;
++ mal->rx_chan_mask_rtdm |= commac->rx_chan_mask;
++ } else {
++ mal->tx_chan_mask |= commac->tx_chan_mask;
++ mal->rx_chan_mask |= commac->rx_chan_mask;
++ }
++#else
+ mal->tx_chan_mask |= commac->tx_chan_mask;
+ mal->rx_chan_mask |= commac->rx_chan_mask;
++#endif
+ list_add(&commac->list, &mal->list);
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+
+ return 0;
+ }
+@@ -68,18 +115,28 @@ void mal_unregister_commac(struct mal_instance *mal,
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&mal->lock, flags);
++ mal_spin_lock_irqsave(&mal->lock, flags);
+
+ MAL_DBG(mal, "unreg(%08x, %08x)" NL,
+ commac->tx_chan_mask, commac->rx_chan_mask);
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (commac->rtdm) {
++ mal->tx_chan_mask_rtdm &= ~commac->tx_chan_mask;
++ mal->rx_chan_mask_rtdm &= ~commac->rx_chan_mask;
++ } else {
++ mal->tx_chan_mask &= ~commac->tx_chan_mask;
++ mal->rx_chan_mask &= ~commac->rx_chan_mask;
++ }
++#else
+ mal->tx_chan_mask &= ~commac->tx_chan_mask;
+ mal->rx_chan_mask &= ~commac->rx_chan_mask;
++#endif
+ list_del_init(&commac->list);
+ if (list_empty(&mal->list))
+ napi_disable(&mal->napi);
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ }
+
+ int mal_set_rcbs(struct mal_instance *mal, int channel, unsigned long size)
+@@ -117,14 +174,14 @@ void mal_enable_tx_channel(struct mal_instance *mal, int channel)
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&mal->lock, flags);
++ mal_spin_lock_irqsave(&mal->lock, flags);
+
+ MAL_DBG(mal, "enable_tx(%d)" NL, channel);
+
+ set_mal_dcrn(mal, MAL_TXCASR,
+ get_mal_dcrn(mal, MAL_TXCASR) | MAL_CHAN_MASK(channel));
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ }
+
+ void mal_disable_tx_channel(struct mal_instance *mal, int channel)
+@@ -146,14 +203,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
+ if (!(channel % 8))
+ channel >>= 3;
+
+- spin_lock_irqsave(&mal->lock, flags);
++ mal_spin_lock_irqsave(&mal->lock, flags);
+
+ MAL_DBG(mal, "enable_rx(%d)" NL, channel);
+
+ set_mal_dcrn(mal, MAL_RXCASR,
+ get_mal_dcrn(mal, MAL_RXCASR) | MAL_CHAN_MASK(channel));
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ }
+
+ void mal_disable_rx_channel(struct mal_instance *mal, int channel)
+@@ -175,29 +232,36 @@ void mal_poll_add(struct mal_instance *mal, struct mal_commac *commac)
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&mal->lock, flags);
++ mal_spin_lock_irqsave(&mal->lock, flags);
+
+ MAL_DBG(mal, "poll_add(%p)" NL, commac);
+
+ /* starts disabled */
+ set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags);
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (commac->rtdm)
++ list_add_tail(&commac->poll_list, &mal->poll_list_rtdm);
++ else
++ list_add_tail(&commac->poll_list, &mal->poll_list);
++#else
+ list_add_tail(&commac->poll_list, &mal->poll_list);
++#endif
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ }
+
+ void mal_poll_del(struct mal_instance *mal, struct mal_commac *commac)
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&mal->lock, flags);
++ mal_spin_lock_irqsave(&mal->lock, flags);
+
+ MAL_DBG(mal, "poll_del(%p)" NL, commac);
+
+ list_del(&commac->poll_list);
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ }
+
+ /* synchronized by mal_poll() */
+@@ -218,9 +282,18 @@ static inline void mal_disable_eob_irq(struct mal_instance *mal)
+ MAL_DBG2(mal, "disable_irq" NL);
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++static int mal_serr(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_serr(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
+
+ u32 esr = get_mal_dcrn(mal, MAL_ESR);
+
+@@ -234,51 +307,99 @@ static irqreturn_t mal_serr(int irq, void *dev_instance)
+ /* We ignore Descriptor error,
+ * TXDE or RXDE interrupt will be generated anyway.
+ */
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
+ if (esr & MAL_ESR_PEIN) {
+ /* PLB error, it's probably buggy hardware or
+ * incorrect physical address in BD (i.e. bug)
+ */
+- if (net_ratelimit())
++ if (mal_net_ratelimit())
+ printk(KERN_ERR
+ "mal%d: system error, "
+ "PLB (ESR = 0x%08x)\n",
+ mal->index, esr);
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
+ /* OPB error, it's probably buggy hardware or incorrect
+ * EBC setup
+ */
+- if (net_ratelimit())
++ if (mal_net_ratelimit())
+ printk(KERN_ERR
+ "mal%d: system error, OPB (ESR = 0x%08x)\n",
+ mal->index, esr);
+ }
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++void mal_schedule_poll_nrt(rtdm_nrtsig_t nrt_sig, void* data)
++{
++ struct mal_instance *mal = (struct mal_instance *)data;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ if (likely(napi_schedule_prep(&mal->napi))) {
++ MAL_DBG2(mal, "schedule_poll" NL);
++ __napi_schedule(&mal->napi);
++ } else
++ MAL_DBG2(mal, "already in poll" NL);
++ local_irq_restore(flags);
++}
++#endif
+ static inline void mal_schedule_poll(struct mal_instance *mal)
+ {
+ if (likely(napi_schedule_prep(&mal->napi))) {
+ MAL_DBG2(mal, "schedule_poll" NL);
++#ifndef CONFIG_IBM_NEW_EMAC_MAL_RTDM
+ mal_disable_eob_irq(mal);
++#endif
+ __napi_schedule(&mal->napi);
+ } else
+ MAL_DBG2(mal, "already in poll" NL);
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++#ifdef OBSOLETE
++static nanosecs_abs_t tstart;
++#endif
++
++static int mal_txeob(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_txeob(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
+
++ struct list_head *l;
+ u32 r = get_mal_dcrn(mal, MAL_TXEOBISR);
+
+- MAL_DBG2(mal, "txeob %08x" NL, r);
++ MAL_DBG2(mal, "rt txeob %08x" NL, r);
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (r & mal->tx_chan_mask_rtdm) {
++ /* Process TX skbs */
++ list_for_each(l, &mal->poll_list_rtdm) {
++ struct mal_commac *mc =
++ list_entry(l, struct mal_commac, poll_list);
++#ifdef OBSOLETE
++ tstart = rtdm_clock_read();
++#endif
++ mc->ops->poll_tx(mc->dev);
++ }
++ }
++ if (r & mal->tx_chan_mask)
++ rtdm_nrtsig_pend(&mal->schedule_poll_nrt);
++#else
+ mal_schedule_poll(mal);
++#endif
++
+ set_mal_dcrn(mal, MAL_TXEOBISR, r);
+
+ #ifdef CONFIG_PPC_DCR_NATIVE
+@@ -287,18 +408,49 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance)
+ (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));
+ #endif
+
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++static int mal_rxeob(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
++ struct list_head *l;
++ u32 r;
+
+- u32 r = get_mal_dcrn(mal, MAL_RXEOBISR);
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ mal->time_stamp = rtdm_clock_read();
++#endif
++ r = get_mal_dcrn(mal, MAL_RXEOBISR);
+
+ MAL_DBG2(mal, "rxeob %08x" NL, r);
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (r & mal->rx_chan_mask_rtdm) {
++ list_for_each(l, &mal->poll_list_rtdm) {
++ struct mal_commac *mc =
++ list_entry(l, struct mal_commac, poll_list);
++ if (unlikely(test_bit(MAL_COMMAC_POLL_DISABLED,
++ &mc->flags))) {
++ MAL_DBG(mal, "mc->flags=%#lx\n", mc->flags);
++ continue;
++ }
++ mc->ops->poll_rx(mc->dev, 1024);
++ }
++ }
++ if (r & mal->rx_chan_mask)
++ rtdm_nrtsig_pend(&mal->schedule_poll_nrt);
++#else
+ mal_schedule_poll(mal);
++#endif
+ set_mal_dcrn(mal, MAL_RXEOBISR, r);
+
+ #ifdef CONFIG_PPC_DCR_NATIVE
+@@ -307,76 +459,149 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
+ (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));
+ #endif
+
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++static int mal_txde(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_txde(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
+
+ u32 deir = get_mal_dcrn(mal, MAL_TXDEIR);
+ set_mal_dcrn(mal, MAL_TXDEIR, deir);
+
+ MAL_DBG(mal, "txde %08x" NL, deir);
+
+- if (net_ratelimit())
++ if (mal_net_ratelimit())
+ printk(KERN_ERR
+ "mal%d: TX descriptor error (TXDEIR = 0x%08x)\n",
+ mal->index, deir);
+
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++static int mal_rxde(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_rxde(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++ int nrtsig_pend = 0;
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
+ struct list_head *l;
+
+ u32 deir = get_mal_dcrn(mal, MAL_RXDEIR);
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ mal->time_stamp = rtdm_clock_read();
++#endif
+ MAL_DBG(mal, "rxde %08x" NL, deir);
+
+ list_for_each(l, &mal->list) {
+ struct mal_commac *mc = list_entry(l, struct mal_commac, list);
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (deir & mc->rx_chan_mask) {
++ set_bit(MAL_COMMAC_RX_STOPPED, &mc->flags);
++ mc->ops->rxde(mc->dev);
++ if (mc->rtdm) {
++ mc->ops->poll_tx(mc->dev);
++ mc->ops->poll_rx(mc->dev, 1024);
++ } else {
++ nrtsig_pend++;
++ }
++ }
++#else
+ if (deir & mc->rx_chan_mask) {
+ set_bit(MAL_COMMAC_RX_STOPPED, &mc->flags);
+ mc->ops->rxde(mc->dev);
+ }
++#endif
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (nrtsig_pend)
++ rtdm_nrtsig_pend(&mal->schedule_poll_nrt);
++#else
+ mal_schedule_poll(mal);
++#endif
+ set_mal_dcrn(mal, MAL_RXDEIR, deir);
+
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++static int mal_int(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_int(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
+ u32 esr = get_mal_dcrn(mal, MAL_ESR);
+
++ MAL_DBG(mal, "int %08x" NL, esr);
++
+ if (esr & MAL_ESR_EVB) {
+ /* descriptor error */
+ if (esr & MAL_ESR_DE) {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (esr & MAL_ESR_CIDT)
++ return mal_rxde(irq_handle);
++ else
++ return mal_txde(irq_handle);
++#else
+ if (esr & MAL_ESR_CIDT)
+ return mal_rxde(irq, dev_instance);
+ else
+ return mal_txde(irq, dev_instance);
++#endif
+ } else { /* SERR */
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ return mal_serr(irq_handle);
++#else
+ return mal_serr(irq, dev_instance);
++#endif
+ }
+ }
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
+ void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (commac->rtdm) {
++ set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags);
++ } else {
++ while (test_and_set_bit(MAL_COMMAC_POLL_DISABLED,
++ &commac->flags))
++ msleep(1);
++ napi_synchronize(&mal->napi);
++ }
++#else
+ /* Spinlock-type semantics: only one caller disable poll at a time */
+ while (test_and_set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags))
+ msleep(1);
+
+ /* Synchronize with the MAL NAPI poller */
+ napi_synchronize(&mal->napi);
++#endif
+ }
+
+ void mal_poll_enable(struct mal_instance *mal, struct mal_commac *commac)
+@@ -389,7 +614,12 @@ void mal_poll_enable(struct mal_instance *mal, struct mal_commac *commac)
+ * probably be delayed until the next interrupt but that's mostly a
+ * non-issue in the context where this is called.
+ */
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (!commac->rtdm)
++ napi_schedule(&mal->napi);
++#else
+ napi_schedule(&mal->napi);
++#endif
+ }
+
+ static int mal_poll(struct napi_struct *napi, int budget)
+@@ -429,10 +659,15 @@ static int mal_poll(struct napi_struct *napi, int budget)
+ }
+
+ /* We need to disable IRQs to protect from RXDE IRQ here */
+- spin_lock_irqsave(&mal->lock, flags);
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ local_irq_save(flags);
+ __napi_complete(napi);
++ local_irq_restore(flags);
++#else
++ spin_lock_irqsave(&mal->lock, flags);
+ mal_enable_eob_irq(mal);
+ spin_unlock_irqrestore(&mal->lock, flags);
++#endif
+
+ /* Check for "rotting" packet(s) */
+ list_for_each(l, &mal->poll_list) {
+@@ -443,10 +678,15 @@ static int mal_poll(struct napi_struct *napi, int budget)
+ if (unlikely(mc->ops->peek_rx(mc->dev) ||
+ test_bit(MAL_COMMAC_RX_STOPPED, &mc->flags))) {
+ MAL_DBG2(mal, "rotting packet" NL);
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (!napi_reschedule(napi))
++ MAL_DBG2(mal, "already in poll list" NL);
++#else
+ if (napi_reschedule(napi))
+ mal_disable_eob_irq(mal);
+ else
+ MAL_DBG2(mal, "already in poll list" NL);
++#endif
+
+ if (budget > 0)
+ goto again;
+@@ -527,7 +767,11 @@ static int __devinit mal_probe(struct platform_device *ofdev,
+ const u32 *prop;
+ u32 cfg;
+ unsigned long irqflags;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ rtdm_irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
++#else
+ irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
++#endif
+
+ mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL);
+ if (!mal) {
+@@ -612,7 +856,18 @@ static int __devinit mal_probe(struct platform_device *ofdev,
+
+ INIT_LIST_HEAD(&mal->poll_list);
+ INIT_LIST_HEAD(&mal->list);
+- spin_lock_init(&mal->lock);
++ mal_spin_lock_init(&mal->lock);
++
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ INIT_LIST_HEAD(&mal->poll_list_rtdm);
++
++ if (rtdm_nrtsig_init(&mal->schedule_poll_nrt, mal_schedule_poll_nrt,
++ (void*)mal)) {
++ printk(KERN_ERR
++ "mal%d: couldn't init mal schedule handler !\n", index);
++ goto fail_unmap;
++ }
++#endif
+
+ init_dummy_netdev(&mal->dummy_dev);
+
+@@ -674,19 +929,44 @@ static int __devinit mal_probe(struct platform_device *ofdev,
+ hdlr_rxde = mal_rxde;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ err = rtdm_irq_request(&mal->serr_irq_handle, mal->serr_irq,
++ mal_serr, 0, "MAL SERR", mal);
++#else
+ err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal);
++#endif
+ if (err)
+ goto fail2;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ err = rtdm_irq_request(&mal->txde_irq_handle, mal->txde_irq,
++ mal_txde, 0, "MAL TX DE", mal);
++#else
+ err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal);
++#endif
+ if (err)
+ goto fail3;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ err = rtdm_irq_request(&mal->txeob_irq_handle, mal->txeob_irq,
++ mal_txeob, 0, "MAL TX EOB", mal);
++#else
+ err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
++#endif
+ if (err)
+ goto fail4;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ err = rtdm_irq_request(&mal->rxde_irq_handle, mal->rxde_irq,
++ mal_rxde, 0, "MAL RX DE", mal);
++#else
+ err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal);
++#endif
+ if (err)
+ goto fail5;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ err = rtdm_irq_request(&mal->rxeob_irq_handle, mal->rxeob_irq,
++ mal_rxeob, 0, "MAL RX EOB", mal);
++#else
+ err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);
++#endif
+ if (err)
+ goto fail6;
+
+@@ -715,7 +995,11 @@ static int __devinit mal_probe(struct platform_device *ofdev,
+ fail6:
+ free_irq(mal->rxde_irq, mal);
+ fail5:
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ rtdm_irq_free(&mal->txeob_irq_handle);
++#else
+ free_irq(mal->txeob_irq, mal);
++#endif
+ fail4:
+ free_irq(mal->txde_irq, mal);
+ fail3:
+@@ -808,3 +1092,19 @@ void mal_exit(void)
+ {
+ of_unregister_platform_driver(&mal_of_driver);
+ }
++
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++EXPORT_SYMBOL_GPL(mal_register_commac);
++EXPORT_SYMBOL_GPL(mal_unregister_commac);
++EXPORT_SYMBOL_GPL(mal_set_rcbs);
++EXPORT_SYMBOL_GPL(mal_tx_bd_offset);
++EXPORT_SYMBOL_GPL(mal_rx_bd_offset);
++EXPORT_SYMBOL_GPL(mal_enable_tx_channel);
++EXPORT_SYMBOL_GPL(mal_disable_tx_channel);
++EXPORT_SYMBOL_GPL(mal_enable_rx_channel);
++EXPORT_SYMBOL_GPL(mal_disable_rx_channel);
++EXPORT_SYMBOL_GPL(mal_poll_add);
++EXPORT_SYMBOL_GPL(mal_poll_del);
++EXPORT_SYMBOL_GPL(mal_poll_enable);
++EXPORT_SYMBOL_GPL(mal_poll_disable);
++#endif
+diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h
+index 6608421..0573c76 100644
+--- a/drivers/net/ibm_newemac/mal.h
++++ b/drivers/net/ibm_newemac/mal.h
+@@ -24,6 +24,10 @@
+ #ifndef __IBM_NEWEMAC_MAL_H
+ #define __IBM_NEWEMAC_MAL_H
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++#include <rtdm/rtdm_driver.h>
++#endif
++
+ /*
+ * There are some variations on the MAL, we express them in this driver as
+ * MAL Version 1 and 2 though that doesn't match any IBM terminology.
+@@ -186,6 +190,9 @@ struct mal_commac {
+ u32 tx_chan_mask;
+ u32 rx_chan_mask;
+ struct list_head list;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ int rtdm;
++#endif
+ };
+
+ struct mal_instance {
+@@ -199,20 +206,40 @@ struct mal_instance {
+ int txde_irq; /* TX Descriptor Error IRQ */
+ int rxde_irq; /* RX Descriptor Error IRQ */
+ int serr_irq; /* MAL System Error IRQ */
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ rtdm_irq_t txeob_irq_handle;
++ rtdm_irq_t rxeob_irq_handle;
++ rtdm_irq_t txde_irq_handle;
++ rtdm_irq_t rxde_irq_handle;
++ rtdm_irq_t serr_irq_handle;
++ rtdm_nrtsig_t schedule_poll_nrt;
++ nanosecs_abs_t time_stamp;
++#endif
+
+ struct list_head poll_list;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct list_head poll_list_rtdm;
++#endif
+ struct napi_struct napi;
+
+ struct list_head list;
+ u32 tx_chan_mask;
+ u32 rx_chan_mask;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ u32 tx_chan_mask_rtdm;
++ u32 rx_chan_mask_rtdm;
++#endif
+
+ dma_addr_t bd_dma;
+ struct mal_descriptor *bd_virt;
+
+ struct platform_device *ofdev;
+ int index;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ rtdm_lock_t lock;
++#else
+ spinlock_t lock;
++#endif
+
+ struct net_device dummy_dev;
+
+diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c
+index ac9d964..87a0a80 100644
+--- a/drivers/net/ibm_newemac/phy.c
++++ b/drivers/net/ibm_newemac/phy.c
+@@ -535,4 +535,11 @@ int emac_mii_phy_probe(struct mii_phy *phy, int address)
+ return 0;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++EXPORT_SYMBOL_GPL(emac_mii_phy_probe);
++EXPORT_SYMBOL_GPL(emac_mii_reset_gpcs);
++EXPORT_SYMBOL_GPL(emac_mii_reset_phy);
++#endif
++
++
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c
+index dd61798..9e0a673 100644
+--- a/drivers/net/ibm_newemac/rgmii.c
++++ b/drivers/net/ibm_newemac/rgmii.c
+@@ -337,3 +337,11 @@ void rgmii_exit(void)
+ {
+ of_unregister_platform_driver(&rgmii_driver);
+ }
++
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++EXPORT_SYMBOL_GPL(rgmii_attach);
++EXPORT_SYMBOL_GPL(rgmii_detach);
++EXPORT_SYMBOL_GPL(rgmii_set_speed);
++EXPORT_SYMBOL_GPL(rgmii_get_mdio);
++EXPORT_SYMBOL_GPL(rgmii_put_mdio);
++#endif
+diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ibm_newemac/zmii.c
+index 34ed6ee..130e62b 100644
+--- a/drivers/net/ibm_newemac/zmii.c
++++ b/drivers/net/ibm_newemac/zmii.c
+@@ -331,3 +331,12 @@ void zmii_exit(void)
+ {
+ of_unregister_platform_driver(&zmii_driver);
+ }
++
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++EXPORT_SYMBOL_GPL(zmii_attach);
++EXPORT_SYMBOL_GPL(zmii_detach);
++EXPORT_SYMBOL_GPL(zmii_get_mdio);
++EXPORT_SYMBOL_GPL(zmii_put_mdio);
++EXPORT_SYMBOL_GPL(zmii_set_speed);
++#endif
++
+--
+1.7.4.1
diff --git a/drivers/ibm_newemac/linux-3.0.4-rtdm-ibm-emac.patch b/drivers/ibm_newemac/linux-3.0.4-rtdm-ibm-emac.patch
new file mode 100644
index 0000000..000c4f7
--- /dev/null
+++ b/drivers/ibm_newemac/linux-3.0.4-rtdm-ibm-emac.patch
@@ -0,0 +1,875 @@
+From d230f5decc7b4fb8edf783de1738312e911ab1c3 Mon Sep 17 00:00:00 2001
+From: Wolfgang Grandegger <wg...@de...>
+Date: Thu, 17 Nov 2011 13:13:29 +0100
+Subject: [PATCH] net/ibm_newemac: provide real-time capable RTDM MAL driver
+
+Signed-off-by: Wolfgang Grandegger <wg...@de...>
+---
+ drivers/net/ibm_newemac/Kconfig | 5 +
+ drivers/net/ibm_newemac/Makefile | 4 +
+ drivers/net/ibm_newemac/core.c | 5 +
+ drivers/net/ibm_newemac/mal.c | 358 ++++++++++++++++++++++++++++++++++---
+ drivers/net/ibm_newemac/mal.h | 27 +++
+ drivers/net/ibm_newemac/phy.c | 7 +
+ drivers/net/ibm_newemac/rgmii.c | 8 +
+ drivers/net/ibm_newemac/zmii.c | 9 +
+ 8 files changed, 394 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/net/ibm_newemac/Kconfig b/drivers/net/ibm_newemac/Kconfig
+index 78a1628..b5696e1 100644
+--- a/drivers/net/ibm_newemac/Kconfig
++++ b/drivers/net/ibm_newemac/Kconfig
+@@ -39,6 +39,11 @@ config IBM_NEW_EMAC_RX_SKB_HEADROOM
+
+ If unsure, set to 0.
+
++config IBM_NEW_EMAC_MAL_RTDM
++ bool "Real-time MAL"
++ depends on IBM_NEW_EMAC && XENO_SKIN_RTDM
++ default n
++
+ config IBM_NEW_EMAC_DEBUG
+ bool "Debugging"
+ depends on IBM_NEW_EMAC
+diff --git a/drivers/net/ibm_newemac/Makefile b/drivers/net/ibm_newemac/Makefile
+index 0b5c995..ab82084 100644
+--- a/drivers/net/ibm_newemac/Makefile
++++ b/drivers/net/ibm_newemac/Makefile
+@@ -2,6 +2,10 @@
+ # Makefile for the PowerPC 4xx on-chip ethernet driver
+ #
+
++ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++EXTRA_CFLAGS += -D__IN_XENOMAI__ -Iinclude/xenomai
++endif
++
+ obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac.o
+
+ ibm_newemac-y := mal.o core.o phy.o
+diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
+index 079450f..bd45db6 100644
+--- a/drivers/net/ibm_newemac/core.c
++++ b/drivers/net/ibm_newemac/core.c
+@@ -2949,6 +2949,9 @@ 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);
+
+@@ -3097,3 +3100,5 @@ static void __exit emac_exit(void)
+
+ module_init(emac_init);
+ module_exit(emac_exit);
++
++EXPORT_SYMBOL_GPL(busy_phy_map);
+diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
+index d268f40..9a8f76b 100644
+--- a/drivers/net/ibm_newemac/mal.c
++++ b/drivers/net/ibm_newemac/mal.c
+@@ -18,6 +18,10 @@
+ * Armin Kuster <ak...@mv...>
+ * Copyright 2002 MontaVista Softare Inc.
+ *
++ * Real-time extension required for the RTnet IBM EMAC driver
++ *
++ * Copyright 2011 Wolfgang Grandegger <wg...@de...>
++ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+@@ -31,6 +35,27 @@
+ #include "core.h"
+ #include <asm/dcr-regs.h>
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++#define MAL_IRQ_HANDLED RTDM_IRQ_HANDLED
++#define mal_spin_lock_irqsave(lock, flags) \
++ do { rtdm_lock_get_irqsave(lock, flags); } while (0)
++#define mal_spin_unlock_irqrestore(lock, flags) \
++ do { rtdm_lock_put_irqrestore(lock, flags); } while (0)
++#define mal_spin_lock_init(lock) \
++ do { rtdm_lock_init(lock); } while (0)
++static DEFINE_RTDM_RATELIMIT_STATE(mal_net_ratelimit_state, 5000000000LL, 10);
++#define mal_net_ratelimit() rtdm_ratelimit(&mal_net_ratelimit_state, __func__)
++#else
++#define MAL_IRQ_HANDLED IRQ_HANDLED
++#define mal_spin_lock_irqsave(lock, flags) \
++ do { spin_lock_irqsave(lock, flags);; } while (0)
++#define mal_spin_unlock_irqrestore(lock, flags) \
++ do { spin_unlock_irqrestore(lock, flags); } while (0)
++#define mal_spin_lock_init(lock) \
++ do { spin_lock_init(lock); } while (0)
++#define mal_net_ratelimit() net_ratelimit()
++#endif
++
+ static int mal_count;
+
+ int __devinit mal_register_commac(struct mal_instance *mal,
+@@ -38,27 +63,49 @@ int __devinit mal_register_commac(struct mal_instance *mal,
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&mal->lock, flags);
+-
++ mal_spin_lock_irqsave(&mal->lock, flags);
+ MAL_DBG(mal, "reg(%08x, %08x)" NL,
+ commac->tx_chan_mask, commac->rx_chan_mask);
+
+ /* Don't let multiple commacs claim the same channel(s) */
++
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (((mal->tx_chan_mask | mal->tx_chan_mask_rtdm) &
++ commac->tx_chan_mask) ||
++ ((mal->rx_chan_mask | mal->rx_chan_mask_rtdm) &
++ commac->rx_chan_mask)) {
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
++ printk(KERN_WARNING "mal%d: COMMAC channels conflict!\n",
++ mal->index);
++ return -EBUSY;
++ }
++#else
+ if ((mal->tx_chan_mask & commac->tx_chan_mask) ||
+ (mal->rx_chan_mask & commac->rx_chan_mask)) {
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ printk(KERN_WARNING "mal%d: COMMAC channels conflict!\n",
+ mal->index);
+ return -EBUSY;
+ }
++#endif
+
+ if (list_empty(&mal->list))
+ napi_enable(&mal->napi);
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (commac->rtdm) {
++ mal->tx_chan_mask_rtdm |= commac->tx_chan_mask;
++ mal->rx_chan_mask_rtdm |= commac->rx_chan_mask;
++ } else {
++ mal->tx_chan_mask |= commac->tx_chan_mask;
++ mal->rx_chan_mask |= commac->rx_chan_mask;
++ }
++#else
+ mal->tx_chan_mask |= commac->tx_chan_mask;
+ mal->rx_chan_mask |= commac->rx_chan_mask;
++#endif
+ list_add(&commac->list, &mal->list);
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+
+ return 0;
+ }
+@@ -68,18 +115,28 @@ void mal_unregister_commac(struct mal_instance *mal,
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&mal->lock, flags);
++ mal_spin_lock_irqsave(&mal->lock, flags);
+
+ MAL_DBG(mal, "unreg(%08x, %08x)" NL,
+ commac->tx_chan_mask, commac->rx_chan_mask);
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (commac->rtdm) {
++ mal->tx_chan_mask_rtdm &= ~commac->tx_chan_mask;
++ mal->rx_chan_mask_rtdm &= ~commac->rx_chan_mask;
++ } else {
++ mal->tx_chan_mask &= ~commac->tx_chan_mask;
++ mal->rx_chan_mask &= ~commac->rx_chan_mask;
++ }
++#else
+ mal->tx_chan_mask &= ~commac->tx_chan_mask;
+ mal->rx_chan_mask &= ~commac->rx_chan_mask;
++#endif
+ list_del_init(&commac->list);
+ if (list_empty(&mal->list))
+ napi_disable(&mal->napi);
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ }
+
+ int mal_set_rcbs(struct mal_instance *mal, int channel, unsigned long size)
+@@ -117,14 +174,14 @@ void mal_enable_tx_channel(struct mal_instance *mal, int channel)
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&mal->lock, flags);
++ mal_spin_lock_irqsave(&mal->lock, flags);
+
+ MAL_DBG(mal, "enable_tx(%d)" NL, channel);
+
+ set_mal_dcrn(mal, MAL_TXCASR,
+ get_mal_dcrn(mal, MAL_TXCASR) | MAL_CHAN_MASK(channel));
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ }
+
+ void mal_disable_tx_channel(struct mal_instance *mal, int channel)
+@@ -146,14 +203,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
+ if (!(channel % 8))
+ channel >>= 3;
+
+- spin_lock_irqsave(&mal->lock, flags);
++ mal_spin_lock_irqsave(&mal->lock, flags);
+
+ MAL_DBG(mal, "enable_rx(%d)" NL, channel);
+
+ set_mal_dcrn(mal, MAL_RXCASR,
+ get_mal_dcrn(mal, MAL_RXCASR) | MAL_CHAN_MASK(channel));
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ }
+
+ void mal_disable_rx_channel(struct mal_instance *mal, int channel)
+@@ -175,29 +232,36 @@ void mal_poll_add(struct mal_instance *mal, struct mal_commac *commac)
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&mal->lock, flags);
++ mal_spin_lock_irqsave(&mal->lock, flags);
+
+ MAL_DBG(mal, "poll_add(%p)" NL, commac);
+
+ /* starts disabled */
+ set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags);
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (commac->rtdm)
++ list_add_tail(&commac->poll_list, &mal->poll_list_rtdm);
++ else
++ list_add_tail(&commac->poll_list, &mal->poll_list);
++#else
+ list_add_tail(&commac->poll_list, &mal->poll_list);
++#endif
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ }
+
+ void mal_poll_del(struct mal_instance *mal, struct mal_commac *commac)
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&mal->lock, flags);
++ mal_spin_lock_irqsave(&mal->lock, flags);
+
+ MAL_DBG(mal, "poll_del(%p)" NL, commac);
+
+ list_del(&commac->poll_list);
+
+- spin_unlock_irqrestore(&mal->lock, flags);
++ mal_spin_unlock_irqrestore(&mal->lock, flags);
+ }
+
+ /* synchronized by mal_poll() */
+@@ -218,9 +282,18 @@ static inline void mal_disable_eob_irq(struct mal_instance *mal)
+ MAL_DBG2(mal, "disable_irq" NL);
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++static int mal_serr(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_serr(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
+
+ u32 esr = get_mal_dcrn(mal, MAL_ESR);
+
+@@ -234,51 +307,99 @@ static irqreturn_t mal_serr(int irq, void *dev_instance)
+ /* We ignore Descriptor error,
+ * TXDE or RXDE interrupt will be generated anyway.
+ */
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
+ if (esr & MAL_ESR_PEIN) {
+ /* PLB error, it's probably buggy hardware or
+ * incorrect physical address in BD (i.e. bug)
+ */
+- if (net_ratelimit())
++ if (mal_net_ratelimit())
+ printk(KERN_ERR
+ "mal%d: system error, "
+ "PLB (ESR = 0x%08x)\n",
+ mal->index, esr);
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
+ /* OPB error, it's probably buggy hardware or incorrect
+ * EBC setup
+ */
+- if (net_ratelimit())
++ if (mal_net_ratelimit())
+ printk(KERN_ERR
+ "mal%d: system error, OPB (ESR = 0x%08x)\n",
+ mal->index, esr);
+ }
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++void mal_schedule_poll_nrt(rtdm_nrtsig_t nrt_sig, void* data)
++{
++ struct mal_instance *mal = (struct mal_instance *)data;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ if (likely(napi_schedule_prep(&mal->napi))) {
++ MAL_DBG2(mal, "schedule_poll" NL);
++ __napi_schedule(&mal->napi);
++ } else
++ MAL_DBG2(mal, "already in poll" NL);
++ local_irq_restore(flags);
++}
++#endif
+ static inline void mal_schedule_poll(struct mal_instance *mal)
+ {
+ if (likely(napi_schedule_prep(&mal->napi))) {
+ MAL_DBG2(mal, "schedule_poll" NL);
++#ifndef CONFIG_IBM_NEW_EMAC_MAL_RTDM
+ mal_disable_eob_irq(mal);
++#endif
+ __napi_schedule(&mal->napi);
+ } else
+ MAL_DBG2(mal, "already in poll" NL);
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++#ifdef OBSOLETE
++static nanosecs_abs_t tstart;
++#endif
++
++static int mal_txeob(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_txeob(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
+
++ struct list_head *l;
+ u32 r = get_mal_dcrn(mal, MAL_TXEOBISR);
+
+- MAL_DBG2(mal, "txeob %08x" NL, r);
++ MAL_DBG2(mal, "rt txeob %08x" NL, r);
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (r & mal->tx_chan_mask_rtdm) {
++ /* Process TX skbs */
++ list_for_each(l, &mal->poll_list_rtdm) {
++ struct mal_commac *mc =
++ list_entry(l, struct mal_commac, poll_list);
++#ifdef OBSOLETE
++ tstart = rtdm_clock_read();
++#endif
++ mc->ops->poll_tx(mc->dev);
++ }
++ }
++ if (r & mal->tx_chan_mask)
++ rtdm_nrtsig_pend(&mal->schedule_poll_nrt);
++#else
+ mal_schedule_poll(mal);
++#endif
++
+ set_mal_dcrn(mal, MAL_TXEOBISR, r);
+
+ #ifdef CONFIG_PPC_DCR_NATIVE
+@@ -287,18 +408,49 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance)
+ (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));
+ #endif
+
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++static int mal_rxeob(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
++ struct list_head *l;
++ u32 r;
+
+- u32 r = get_mal_dcrn(mal, MAL_RXEOBISR);
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ mal->time_stamp = rtdm_clock_read();
++#endif
++ r = get_mal_dcrn(mal, MAL_RXEOBISR);
+
+ MAL_DBG2(mal, "rxeob %08x" NL, r);
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (r & mal->rx_chan_mask_rtdm) {
++ list_for_each(l, &mal->poll_list_rtdm) {
++ struct mal_commac *mc =
++ list_entry(l, struct mal_commac, poll_list);
++ if (unlikely(test_bit(MAL_COMMAC_POLL_DISABLED,
++ &mc->flags))) {
++ MAL_DBG(mal, "mc->flags=%#lx\n", mc->flags);
++ continue;
++ }
++ mc->ops->poll_rx(mc->dev, 1024);
++ }
++ }
++ if (r & mal->rx_chan_mask)
++ rtdm_nrtsig_pend(&mal->schedule_poll_nrt);
++#else
+ mal_schedule_poll(mal);
++#endif
+ set_mal_dcrn(mal, MAL_RXEOBISR, r);
+
+ #ifdef CONFIG_PPC_DCR_NATIVE
+@@ -307,76 +459,149 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
+ (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));
+ #endif
+
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++static int mal_txde(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_txde(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
+
+ u32 deir = get_mal_dcrn(mal, MAL_TXDEIR);
+ set_mal_dcrn(mal, MAL_TXDEIR, deir);
+
+ MAL_DBG(mal, "txde %08x" NL, deir);
+
+- if (net_ratelimit())
++ if (mal_net_ratelimit())
+ printk(KERN_ERR
+ "mal%d: TX descriptor error (TXDEIR = 0x%08x)\n",
+ mal->index, deir);
+
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++static int mal_rxde(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_rxde(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++ int nrtsig_pend = 0;
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
+ struct list_head *l;
+
+ u32 deir = get_mal_dcrn(mal, MAL_RXDEIR);
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ mal->time_stamp = rtdm_clock_read();
++#endif
+ MAL_DBG(mal, "rxde %08x" NL, deir);
+
+ list_for_each(l, &mal->list) {
+ struct mal_commac *mc = list_entry(l, struct mal_commac, list);
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (deir & mc->rx_chan_mask) {
++ set_bit(MAL_COMMAC_RX_STOPPED, &mc->flags);
++ mc->ops->rxde(mc->dev);
++ if (mc->rtdm) {
++ mc->ops->poll_tx(mc->dev);
++ mc->ops->poll_rx(mc->dev, 1024);
++ } else {
++ nrtsig_pend++;
++ }
++ }
++#else
+ if (deir & mc->rx_chan_mask) {
+ set_bit(MAL_COMMAC_RX_STOPPED, &mc->flags);
+ mc->ops->rxde(mc->dev);
+ }
++#endif
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (nrtsig_pend)
++ rtdm_nrtsig_pend(&mal->schedule_poll_nrt);
++#else
+ mal_schedule_poll(mal);
++#endif
+ set_mal_dcrn(mal, MAL_RXDEIR, deir);
+
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++static int mal_int(rtdm_irq_t *irq_handle)
++#else
+ static irqreturn_t mal_int(int irq, void *dev_instance)
++#endif
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct mal_instance *mal = rtdm_irq_get_arg(irq_handle,
++ struct mal_instance);
++#else
+ struct mal_instance *mal = dev_instance;
++#endif
+ u32 esr = get_mal_dcrn(mal, MAL_ESR);
+
++ MAL_DBG(mal, "int %08x" NL, esr);
++
+ if (esr & MAL_ESR_EVB) {
+ /* descriptor error */
+ if (esr & MAL_ESR_DE) {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (esr & MAL_ESR_CIDT)
++ return mal_rxde(irq_handle);
++ else
++ return mal_txde(irq_handle);
++#else
+ if (esr & MAL_ESR_CIDT)
+ return mal_rxde(irq, dev_instance);
+ else
+ return mal_txde(irq, dev_instance);
++#endif
+ } else { /* SERR */
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ return mal_serr(irq_handle);
++#else
+ return mal_serr(irq, dev_instance);
++#endif
+ }
+ }
+- return IRQ_HANDLED;
++ return MAL_IRQ_HANDLED;
+ }
+
+ void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)
+ {
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (commac->rtdm) {
++ set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags);
++ } else {
++ while (test_and_set_bit(MAL_COMMAC_POLL_DISABLED,
++ &commac->flags))
++ msleep(1);
++ napi_synchronize(&mal->napi);
++ }
++#else
+ /* Spinlock-type semantics: only one caller disable poll at a time */
+ while (test_and_set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags))
+ msleep(1);
+
+ /* Synchronize with the MAL NAPI poller */
+ napi_synchronize(&mal->napi);
++#endif
+ }
+
+ void mal_poll_enable(struct mal_instance *mal, struct mal_commac *commac)
+@@ -389,7 +614,12 @@ void mal_poll_enable(struct mal_instance *mal, struct mal_commac *commac)
+ * probably be delayed until the next interrupt but that's mostly a
+ * non-issue in the context where this is called.
+ */
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (!commac->rtdm)
++ napi_schedule(&mal->napi);
++#else
+ napi_schedule(&mal->napi);
++#endif
+ }
+
+ static int mal_poll(struct napi_struct *napi, int budget)
+@@ -429,10 +659,15 @@ static int mal_poll(struct napi_struct *napi, int budget)
+ }
+
+ /* We need to disable IRQs to protect from RXDE IRQ here */
+- spin_lock_irqsave(&mal->lock, flags);
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ local_irq_save(flags);
+ __napi_complete(napi);
++ local_irq_restore(flags);
++#else
++ spin_lock_irqsave(&mal->lock, flags);
+ mal_enable_eob_irq(mal);
+ spin_unlock_irqrestore(&mal->lock, flags);
++#endif
+
+ /* Check for "rotting" packet(s) */
+ list_for_each(l, &mal->poll_list) {
+@@ -443,10 +678,15 @@ static int mal_poll(struct napi_struct *napi, int budget)
+ if (unlikely(mc->ops->peek_rx(mc->dev) ||
+ test_bit(MAL_COMMAC_RX_STOPPED, &mc->flags))) {
+ MAL_DBG2(mal, "rotting packet" NL);
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ if (!napi_reschedule(napi))
++ MAL_DBG2(mal, "already in poll list" NL);
++#else
+ if (napi_reschedule(napi))
+ mal_disable_eob_irq(mal);
+ else
+ MAL_DBG2(mal, "already in poll list" NL);
++#endif
+
+ if (budget > 0)
+ goto again;
+@@ -526,7 +766,11 @@ static int __devinit mal_probe(struct platform_device *ofdev)
+ const u32 *prop;
+ u32 cfg;
+ unsigned long irqflags;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ rtdm_irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
++#else
+ irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
++#endif
+
+ mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL);
+ if (!mal) {
+@@ -611,7 +855,18 @@ static int __devinit mal_probe(struct platform_device *ofdev)
+
+ INIT_LIST_HEAD(&mal->poll_list);
+ INIT_LIST_HEAD(&mal->list);
+- spin_lock_init(&mal->lock);
++ mal_spin_lock_init(&mal->lock);
++
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ INIT_LIST_HEAD(&mal->poll_list_rtdm);
++
++ if (rtdm_nrtsig_init(&mal->schedule_poll_nrt, mal_schedule_poll_nrt,
++ (void*)mal)) {
++ printk(KERN_ERR
++ "mal%d: couldn't init mal schedule handler !\n", index);
++ goto fail_unmap;
++ }
++#endif
+
+ init_dummy_netdev(&mal->dummy_dev);
+
+@@ -673,19 +928,44 @@ static int __devinit mal_probe(struct platform_device *ofdev)
+ hdlr_rxde = mal_rxde;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ err = rtdm_irq_request(&mal->serr_irq_handle, mal->serr_irq,
++ mal_serr, 0, "MAL SERR", mal);
++#else
+ err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal);
++#endif
+ if (err)
+ goto fail2;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ err = rtdm_irq_request(&mal->txde_irq_handle, mal->txde_irq,
++ mal_txde, 0, "MAL TX DE", mal);
++#else
+ err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal);
++#endif
+ if (err)
+ goto fail3;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ err = rtdm_irq_request(&mal->txeob_irq_handle, mal->txeob_irq,
++ mal_txeob, 0, "MAL TX EOB", mal);
++#else
+ err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
++#endif
+ if (err)
+ goto fail4;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ err = rtdm_irq_request(&mal->rxde_irq_handle, mal->rxde_irq,
++ mal_rxde, 0, "MAL RX DE", mal);
++#else
+ err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal);
++#endif
+ if (err)
+ goto fail5;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ err = rtdm_irq_request(&mal->rxeob_irq_handle, mal->rxeob_irq,
++ mal_rxeob, 0, "MAL RX EOB", mal);
++#else
+ err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);
++#endif
+ if (err)
+ goto fail6;
+
+@@ -714,7 +994,11 @@ static int __devinit mal_probe(struct platform_device *ofdev)
+ fail6:
+ free_irq(mal->rxde_irq, mal);
+ fail5:
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ rtdm_irq_free(&mal->txeob_irq_handle);
++#else
+ free_irq(mal->txeob_irq, mal);
++#endif
+ fail4:
+ free_irq(mal->txde_irq, mal);
+ fail3:
+@@ -807,3 +1091,19 @@ void mal_exit(void)
+ {
+ platform_driver_unregister(&mal_of_driver);
+ }
++
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++EXPORT_SYMBOL_GPL(mal_register_commac);
++EXPORT_SYMBOL_GPL(mal_unregister_commac);
++EXPORT_SYMBOL_GPL(mal_set_rcbs);
++EXPORT_SYMBOL_GPL(mal_tx_bd_offset);
++EXPORT_SYMBOL_GPL(mal_rx_bd_offset);
++EXPORT_SYMBOL_GPL(mal_enable_tx_channel);
++EXPORT_SYMBOL_GPL(mal_disable_tx_channel);
++EXPORT_SYMBOL_GPL(mal_enable_rx_channel);
++EXPORT_SYMBOL_GPL(mal_disable_rx_channel);
++EXPORT_SYMBOL_GPL(mal_poll_add);
++EXPORT_SYMBOL_GPL(mal_poll_del);
++EXPORT_SYMBOL_GPL(mal_poll_enable);
++EXPORT_SYMBOL_GPL(mal_poll_disable);
++#endif
+diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h
+index 6608421..0573c76 100644
+--- a/drivers/net/ibm_newemac/mal.h
++++ b/drivers/net/ibm_newemac/mal.h
+@@ -24,6 +24,10 @@
+ #ifndef __IBM_NEWEMAC_MAL_H
+ #define __IBM_NEWEMAC_MAL_H
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++#include <rtdm/rtdm_driver.h>
++#endif
++
+ /*
+ * There are some variations on the MAL, we express them in this driver as
+ * MAL Version 1 and 2 though that doesn't match any IBM terminology.
+@@ -186,6 +190,9 @@ struct mal_commac {
+ u32 tx_chan_mask;
+ u32 rx_chan_mask;
+ struct list_head list;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ int rtdm;
++#endif
+ };
+
+ struct mal_instance {
+@@ -199,20 +206,40 @@ struct mal_instance {
+ int txde_irq; /* TX Descriptor Error IRQ */
+ int rxde_irq; /* RX Descriptor Error IRQ */
+ int serr_irq; /* MAL System Error IRQ */
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ rtdm_irq_t txeob_irq_handle;
++ rtdm_irq_t rxeob_irq_handle;
++ rtdm_irq_t txde_irq_handle;
++ rtdm_irq_t rxde_irq_handle;
++ rtdm_irq_t serr_irq_handle;
++ rtdm_nrtsig_t schedule_poll_nrt;
++ nanosecs_abs_t time_stamp;
++#endif
+
+ struct list_head poll_list;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ struct list_head poll_list_rtdm;
++#endif
+ struct napi_struct napi;
+
+ struct list_head list;
+ u32 tx_chan_mask;
+ u32 rx_chan_mask;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ u32 tx_chan_mask_rtdm;
++ u32 rx_chan_mask_rtdm;
++#endif
+
+ dma_addr_t bd_dma;
+ struct mal_descriptor *bd_virt;
+
+ struct platform_device *ofdev;
+ int index;
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++ rtdm_lock_t lock;
++#else
+ spinlock_t lock;
++#endif
+
+ struct net_device dummy_dev;
+
+diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c
+index ac9d964..87a0a80 100644
+--- a/drivers/net/ibm_newemac/phy.c
++++ b/drivers/net/ibm_newemac/phy.c
+@@ -535,4 +535,11 @@ int emac_mii_phy_probe(struct mii_phy *phy, int address)
+ return 0;
+ }
+
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++EXPORT_SYMBOL_GPL(emac_mii_phy_probe);
++EXPORT_SYMBOL_GPL(emac_mii_reset_gpcs);
++EXPORT_SYMBOL_GPL(emac_mii_reset_phy);
++#endif
++
++
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c
+index 4fa53f3..4097c6b 100644
+--- a/drivers/net/ibm_newemac/rgmii.c
++++ b/drivers/net/ibm_newemac/rgmii.c
+@@ -336,3 +336,11 @@ void rgmii_exit(void)
+ {
+ platform_driver_unregister(&rgmii_driver);
+ }
++
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++EXPORT_SYMBOL_GPL(rgmii_attach);
++EXPORT_SYMBOL_GPL(rgmii_detach);
++EXPORT_SYMBOL_GPL(rgmii_set_speed);
++EXPORT_SYMBOL_GPL(rgmii_get_mdio);
++EXPORT_SYMBOL_GPL(rgmii_put_mdio);
++#endif
+diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ibm_newemac/zmii.c
+index 97449e7..4446b1e 100644
+--- a/drivers/net/ibm_newemac/zmii.c
++++ b/drivers/net/ibm_newemac/zmii.c
+@@ -330,3 +330,12 @@ void zmii_exit(void)
+ {
+ platform_driver_unregister(&zmii_driver);
+ }
++
++#ifdef CONFIG_IBM_NEW_EMAC_MAL_RTDM
++EXPORT_SYMBOL_GPL(zmii_attach);
++EXPORT_SYMBOL_GPL(zmii_detach);
++EXPORT_SYMBOL_GPL(zmii_get_mdio);
++EXPORT_SYMBOL_GPL(zmii_put_mdio);
++EXPORT_SYMBOL_GPL(zmii_set_speed);
++#endif
++
+--
+1.7.4.1
--
1.7.4.1
|