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

