From: Wolfgang Grandegger <wg...@de...>
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 <wg...@de...>
---
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
|