Netdev List
 help / color / mirror / Atom feed
* Re: [RFC][PATCH] Fixing SA/SP dumps on netlink/af_key
From: Timo Teräs @ 2008-01-18  6:45 UTC (permalink / raw)
  To: Herbert Xu; +Cc: jamal, netdev, David Miller
In-Reply-To: <20080117213448.GA14716@gondor.apana.org.au>

Herbert Xu wrote:
> On Thu, Jan 17, 2008 at 03:31:14PM +0200, Timo Teräs wrote:
>> I guess the idea was that application should know about the SAs it
>> created. Though a SA dump needs to be done if you want to check
>> for existing entries (created by other processes, or if you are
>> recovering from a crash).
> 
> That's what SADB_GET is for.  In any case KMs cannot coexist so this
> is pointless.  After a crash you should simply flush all states and
> policies.

I thought KMs could coexist. Actually, in strongSwan you have two
daemons: charon and pluto. Both can run at the same time. The other
is for IKEv1 and the other one for IKEv2. It uses netlink, though.
Looking the way pfkey works, it looks like being designed to work
with multiple KMs (e.g. acquires are sent to all registered sockets).

>> SPD dumping is still a must if you want to work nicely with kernel.
> 
> No it isn't.  Look at how Openswan does it.  No dumping anywhere at all.

Then you have to have all policy/static association configuration in
the application configuration. ipsec-tools wanted separate that. As
this is more robust if someone decided to run multiple KMs.

My point (as an ipsec-tools developer) is that the patch would fix
a lot of problems until ipsec-tools is netlink enabled. It would
handle perfectly the dumping even as non-atomic. And that ipsec-tools
is the KM you get by default in almost all distributions.

But apparently you are too worried that all the so many other KMs
still using pfkey (is there others? I think most others use netlink
already) in Linux might break because the rely on an unspecified
feature of pfkey.

I'm also tired of arguing since this is going nowhere. I'll run my
patched kernel and try to get ipsec-tools fixed to use netlink...
eventually.


^ permalink raw reply

* Re: [PATCH 1/3] [NET] phy/fixed.c: rework to not duplicate PHY layer functionality
From: Kumar Gala @ 2008-01-18  6:45 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: Paul Mackerras, netdev, linuxppc-dev, netdev
In-Reply-To: <20071206225121.31080.86606.stgit@localhost.localdomain>

On Fri, 7 Dec 2007, Vitaly Bordug wrote:

>
> With that patch fixed.c now fully emulates MDIO bus, thus no need
> to duplicate PHY layer functionality. That, in turn, drastically
> simplifies the code, and drops down line count.
>
> As an additional bonus, now there is no need to register MDIO bus
> for each PHY, all emulated PHYs placed on the platform fixed MDIO bus.
> There is also no more need to pre-allocate PHYs via .config option,
> this is all now handled dynamically.
>
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
> Acked-by: Jeff Garzik <jeff@garzik.org>
>
> ---
>
>  drivers/net/phy/Kconfig   |   32 +--
>  drivers/net/phy/fixed.c   |  445 +++++++++++++++++----------------------------
>  include/linux/phy_fixed.h |   51 ++---
>  3 files changed, 195 insertions(+), 333 deletions(-)
>

applied.

- k

^ permalink raw reply

* Re: [PATCH 3/3] [POWERPC] MPC8349E-mITX: Vitesse 7385 PHY is not connected to the MDIO bus
From: Kumar Gala @ 2008-01-18  6:46 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: Paul Mackerras, netdev, linuxppc-dev, netdev
In-Reply-To: <20071206225139.31080.18384.stgit@localhost.localdomain>

On Fri, 7 Dec 2007, Vitaly Bordug wrote:

>
> ...thus use fixed-link to register proper "Fixed PHY"
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
>

applied.

- k

^ permalink raw reply

* Re: [PATCH 2/3] [POWERPC] fsl_soc: add support for gianfar for fixed-link property
From: Kumar Gala @ 2008-01-18  6:46 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: Paul Mackerras, netdev, linuxppc-dev, netdev
In-Reply-To: <20071206225131.31080.7872.stgit@localhost.localdomain>

On Fri, 7 Dec 2007, Vitaly Bordug wrote:

>
> fixed-link says: register new "Fixed/emulated PHY", i.e. PHY that
> not connected to the real MDIO bus.
>
> Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
>
> ---
>
>  Documentation/powerpc/booting-without-of.txt |    4 +
>  arch/powerpc/sysdev/fsl_soc.c                |   79 ++++++++++++++++++++------
>  2 files changed, 66 insertions(+), 17 deletions(-)
>

applied.

- k

^ permalink raw reply

* Re: [Bugme-new] [Bug 9773] New: pptp/ppp connection die at high speed on Athlon X2 6000+
From: Andrew Morton @ 2008-01-18  7:48 UTC (permalink / raw)
  To: netdev; +Cc: bugme-daemon, Paul Mackerras, wizard580
In-Reply-To: <bug-9773-10286@http.bugzilla.kernel.org/>

On Thu, 17 Jan 2008 23:33:54 -0800 (PST) bugme-daemon@bugzilla.kernel.org wrote:

> http://bugzilla.kernel.org/show_bug.cgi?id=9773
> 
>            Summary: pptp/ppp connection die at high speed on Athlon X2 6000+
>            Product: Networking
>            Version: 2.5
>      KernelVersion: 2.6.23.12
>           Platform: All
>         OS/Version: Linux
>               Tree: Mainline
>             Status: NEW
>           Severity: blocking
>           Priority: P1
>          Component: Other
>         AssignedTo: acme@ghostprotocols.net
>         ReportedBy: wizard580@gmail.com
> 
> 
> Distribution: debian sid, vanilla kernel
> Hardware Environment: Athlon64 X2 6000+ Nforce5
> Software Environment: pptp 1.7.0 pppd 2.4.4
> 
> Problem Description:
> when I download data at high speed (1,5 MB/s or more) connection (pptp dies)
> drops and reconnect begins (persist option used for pppd) and after reconnect
> it dies again and again. connection made by "pppd call provider"
> 
> before upgrade of hardware (was Athlon64 3500+ NForce4) all works fine at any
> speed.
> 
> Connection will be working if I do some CPU aggressive work such as kernel
> compile at the same time when I download. When CPU load become low it will drop
> again.
> 
> kernel 2.6.24rc8 makes it worst. As I see it just hangs my console with message
> something like "waiting for ppp0 finish" or so... I don't remember exactly
> message.
> 
> 
> Steps to reproduce:
> I think you can use any X2 Athlon, make pptp connection and try to download
> something...

(weird)

^ permalink raw reply

* Re: [patch for 2.6.24? 1/1] bonding: locking fix
From: Krzysztof Oledzki @ 2008-01-18  8:34 UTC (permalink / raw)
  To: Jay Vosburgh
  Cc: Andrew Morton, davem, jeff, shemminger, netdev, Andy Gospodarek
In-Reply-To: <27063.1200620733@death>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1857 bytes --]



On Thu, 17 Jan 2008, Jay Vosburgh wrote:

> Krzysztof Oledzki <olel@ans.pl> wrote:
>
>>> Andrew Morton <akpm@linux-foundation.org> wrote:
>>> [...]
>>>> Can we get this bug fixed please?  Today?  It has been known about for more
>>>> than two months.
>>>
>>> 	I just reposted the complete fix; it's #1 of the series of 7.
>>
>> Bad news. :( 2.6.24-rc7 + patch #1 (bonding: fix locking in sysfs
>> primary/active selection):
> [...]
>> =========================================================
>> [ INFO: possible irq lock inversion dependency detected ]
>> 2.6.24-rc7 #1
>> ---------------------------------------------------------
>> events/0/9 just changed the state of lock:
>> (&mc->mca_lock){-+..}, at: [<c041255a>] mld_ifc_timer_expire+0x130/0x1fb
>> but this lock took another, soft-read-irq-unsafe lock in the past:
>> (&bond->lock){-.--}
>
> 	None of the seven patches I posted just a bit ago will fix this
> lockdep warning (which is a different thing that the bug Andrew inquired
> about); I'm still working on that one.
>
> 	For that one, I had posted this work in progress patch:

Yes, this one works.

> 	which makes the warning go away, but Herbert Xu pointed out that
> there is a potential problem with bond_enslave accessing the mc_lists
> without sufficient locking.  It's not the only offender, either, and the
> bond->mc_list references really need to be protected by the bond_lock,
> and the whole thing probably ought to use dev_mc_sync/unsync instead of
> what it does now.
>
> 	Since the bond_enslave, et al, business isn't a new problem, and
> I've never heard of it being hit, I'm thinking now to just leave the
> bond_enslave part for 2.6.25, and fix the lockdep warning for 2.6.24.

It is a new problem, as it never happened with <=2.6.23.

Best regards,

 				Krzysztof Olędzki

^ permalink raw reply

* [PATCH] net: sh_eth: Add support for Renesas SuperH Ethernet
From: Yoshihiro Shimoda @ 2008-01-18  8:40 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linux-sh

Add support for Renesas SuperH Ethernet controller.
This driver supported SH7710 and SH7712.

Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
---
 Kconfig  |   12
 Makefile |    1
 sh_eth.c | 1175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sh_eth.h |  468 +++++++++++++++++++++++++
 4 files changed, 1656 insertions(+)

diff -uprN a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	2008-01-18 10:54:27.000000000 +0900
+++ b/drivers/net/Kconfig	2008-01-18 16:14:07.000000000 +0900
@@ -522,6 +522,18 @@ config STNIC

 	  If unsure, say N.

+config SH_ETH
+	tristate "Renesas SuperH Ethernet support"
+	depends on SUPERH && \
+		(CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712)
+	select CRC32
+	select MII
+	select MDIO_BITBANG
+	select PHYLIB
+	help
+	  Renesas SuperH Ethernet device driver.
+	  This driver support SH7710 and SH7712.
+
 config SUNLANCE
 	tristate "Sun LANCE support"
 	depends on SBUS
diff -uprN a/drivers/net/Makefile b/drivers/net/Makefile
--- a/drivers/net/Makefile	2008-01-18 10:54:27.000000000 +0900
+++ b/drivers/net/Makefile	2008-01-18 16:14:09.000000000 +0900
@@ -76,6 +76,7 @@ obj-$(CONFIG_VIA_RHINE) += via-rhine.o
 obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
 obj-$(CONFIG_RIONET) += rionet.o
+obj-$(CONFIG_SH_ETH) += sh_eth.o

 #
 # end link order section
diff -uprN a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
--- a/drivers/net/sh_eth.c	1970-01-01 09:00:00.000000000 +0900
+++ b/drivers/net/sh_eth.c	2008-01-18 16:14:10.000000000 +0900
@@ -0,0 +1,1175 @@
+/*
+ *  SuperH Ethernet device driver
+ *
+ *  Copyright (C) 2006,2007 Nobuhiro Iwamatsu
+ *  Copyright (C) 2008 Renesas Solutions Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms and conditions of the GNU General Public License,
+ *  version 2, as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  The full GNU General Public License is included in this distribution in
+ *  the file called "COPYING".
+ */
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mdio-bitbang.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include "sh_eth.h"
+
+/*
+ * Program the hardware MAC address from dev->dev_addr.
+ */
+static void __init update_mac_address(struct net_device *ndev)
+{
+	u32 ioaddr = ndev->base_addr;
+
+	ctrl_outl((ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
+		  (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]),
+		  ioaddr + MAHR);
+	ctrl_outl((ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]),
+		  ioaddr + MALR);
+}
+
+/*
+ * Get MAC address from SuperH MAC address register
+ *
+ * SuperH's Ethernet device doesn't have 'ROM' to MAC address.
+ * This driver get MAC address that use by bootloader(U-boot or sh-ipl+g).
+ * When you want use this device, you must set MAC address in bootloader.
+ *
+ */
+static void __init read_mac_address(struct net_device *ndev)
+{
+	u32 ioaddr = ndev->base_addr;
+
+	ndev->dev_addr[0] = (ctrl_inl(ioaddr + MAHR) >> 24);
+	ndev->dev_addr[1] = (ctrl_inl(ioaddr + MAHR) >> 16) & 0xFF;
+	ndev->dev_addr[2] = (ctrl_inl(ioaddr + MAHR) >> 8) & 0xFF;
+	ndev->dev_addr[3] = (ctrl_inl(ioaddr + MAHR) & 0xFF);
+	ndev->dev_addr[4] = (ctrl_inl(ioaddr + MALR) >> 8) & 0xFF;
+	ndev->dev_addr[5] = (ctrl_inl(ioaddr + MALR) & 0xFF);
+}
+
+struct bb_info {
+	struct mdiobb_ctrl ctrl;
+	u32 addr;
+	u32 mmd_msk;/* MMD */
+	u32 mdo_msk;
+	u32 mdi_msk;
+	u32 mdc_msk;
+};
+
+/* PHY bit set */
+static void bb_set(u32 addr, u32 msk)
+{
+	ctrl_outl(ctrl_inl(addr) | msk, addr);
+}
+
+/* PHY bit clear */
+static void bb_clr(u32 addr, u32 msk)
+{
+	ctrl_outl((ctrl_inl(addr) & ~msk), addr);
+}
+
+/* PHY bit read */
+static int bb_read(u32 addr, u32 msk)
+{
+	return (ctrl_inl(addr) & msk) != 0;
+}
+
+/* Data I/O pin control */
+static inline void sh__mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit)
+{
+	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
+	if (bit)
+		bb_set(bitbang->addr, bitbang->mmd_msk);
+	else
+		bb_clr(bitbang->addr, bitbang->mmd_msk);
+}
+
+/* Set bit data*/
+static inline void sh__set_mdio(struct mdiobb_ctrl *ctrl, int bit)
+{
+	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
+
+	if (bit)
+		bb_set(bitbang->addr, bitbang->mdo_msk);
+	else
+		bb_clr(bitbang->addr, bitbang->mdo_msk);
+}
+
+/* Get bit data*/
+static inline int sh__get_mdio(struct mdiobb_ctrl *ctrl)
+{
+	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
+	return bb_read(bitbang->addr, bitbang->mdi_msk);
+}
+
+/* MDC pin control */
+static inline void sh__mdc_ctrl(struct mdiobb_ctrl *ctrl, int bit)
+{
+	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
+
+	if (bit)
+		bb_set(bitbang->addr, bitbang->mdc_msk);
+	else
+		bb_clr(bitbang->addr, bitbang->mdc_msk);
+}
+
+/* mdio bus control struct */
+static struct mdiobb_ops bb_ops = {
+	.owner = THIS_MODULE,
+	.set_mdc = sh__mdc_ctrl,
+	.set_mdio_dir = sh__mmd_ctrl,
+	.set_mdio_data = sh__set_mdio,
+	.get_mdio_data = sh__get_mdio,
+};
+
+static void sh__eth_reset(struct net_device *ndev)
+{
+	u32 ioaddr = ndev->base_addr;
+
+	ctrl_outl(ctrl_inl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
+	mdelay(3);
+	ctrl_outl(ctrl_inl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR);
+}
+
+/* free skb and descriptor buffer */
+static void sh_eth_ring_free(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	int i;
+
+	/* Free Rx skb ringbuffer */
+	if (mdp->rx_skbuff) {
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			if (mdp->rx_skbuff[i])
+				dev_kfree_skb(mdp->rx_skbuff[i]);
+		}
+	}
+	kfree(mdp->rx_skbuff);
+
+	/* Free Tx skb ringbuffer */
+	if (mdp->tx_skbuff) {
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			if (mdp->tx_skbuff[i])
+				dev_kfree_skb(mdp->tx_skbuff[i]);
+		}
+	}
+	kfree(mdp->tx_skbuff);
+}
+
+/* format skb and descriptor buffer */
+static void sh_eth_ring_format(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	int i;
+	struct sk_buff *skb;
+	struct sh_eth_rxdesc *rxdesc = NULL;
+	struct sh_eth_txdesc *txdesc = NULL;
+	int rx_ringsize = sizeof(*rxdesc) * RX_RING_SIZE;
+	int tx_ringsize = sizeof(*txdesc) * TX_RING_SIZE;
+
+	mdp->cur_rx = mdp->cur_tx = 0;
+	mdp->dirty_rx = mdp->dirty_tx = 0;
+
+	memset(mdp->rx_ring, 0, rx_ringsize);
+
+	/* build Rx ring buffer */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		/* skb */
+		mdp->rx_skbuff[i] = NULL;
+		skb = dev_alloc_skb(mdp->rx_buf_sz);
+		mdp->rx_skbuff[i] = skb;
+		if (skb == NULL)
+			break;
+		skb->dev = ndev;	/* Mark as being used by this device. */
+		skb_reserve(skb, RX_OFFSET);
+
+		/* RX descriptor */
+		rxdesc = &mdp->rx_ring[i];
+		rxdesc->addr = (u32)skb->data & ~0x3UL;
+		rxdesc->status = cpu_to_le32(RD_RACT | RD_RFP);
+
+		/* The size of the buffer is 16 byte boundary. */
+		rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F;
+	}
+
+	mdp->dirty_rx = (u32) (i - RX_RING_SIZE);
+
+	/* Mark the last entry as wrapping the ring. */
+	rxdesc->status |= cpu_to_le32(RC_RDEL);
+
+	memset(mdp->tx_ring, 0, tx_ringsize);
+
+	/* build Tx ring buffer */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		mdp->tx_skbuff[i] = NULL;
+		txdesc = &mdp->tx_ring[i];
+		txdesc->status = cpu_to_le32(TD_TFP);
+		txdesc->buffer_length = 0;
+	}
+
+	txdesc->status |= cpu_to_le32(TD_TDLE);
+}
+
+/* Get skb and descriptor buffer */
+static int sh_eth_ring_init(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	int rx_ringsize, tx_ringsize, ret = 0;
+
+	/*
+	 * +26 gets the maximum ethernet encapsulation, +7 & ~7 because the
+	 * card needs room to do 8 byte alignment, +2 so we can reserve
+	 * the first 2 bytes, and +16 gets room for the status word from the
+	 * card.
+	 */
+	mdp->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ :
+			  (((ndev->mtu + 26 + 7) & ~7) + 2 + 16));
+
+	/* Allocate RX and TX skb rings */
+	mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * RX_RING_SIZE,
+				GFP_KERNEL);
+	if (!mdp->rx_skbuff) {
+		printk(KERN_ERR "%s: Cannot allocate Rx skb\n", ndev->name);
+		ret = -ENOMEM;
+		return ret;
+	}
+
+	mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * TX_RING_SIZE,
+				GFP_KERNEL);
+	if (!mdp->tx_skbuff) {
+		printk(KERN_ERR "%s: Cannot allocate Tx skb\n", ndev->name);
+		ret = -ENOMEM;
+		goto skb_ring_free;
+	}
+
+	/* Allocate all Rx descriptors. */
+	rx_ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
+	mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma,
+			GFP_KERNEL);
+
+	if (!mdp->rx_ring) {
+		printk(KERN_ERR "%s: Cannot allocate Rx Ring (size %d bytes)\n",
+			ndev->name, rx_ringsize);
+		ret = -ENOMEM;
+		goto desc_ring_free;
+	}
+
+	mdp->dirty_rx = 0;
+
+	/* Allocate all Tx descriptors. */
+	tx_ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
+	mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma,
+			GFP_KERNEL);
+	if (!mdp->tx_ring) {
+		printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
+			ndev->name, tx_ringsize);
+		ret = -ENOMEM;
+		goto desc_ring_free;
+	}
+	return ret;
+
+desc_ring_free:
+	/* free DMA buffer */
+	dma_free_coherent(NULL, rx_ringsize, mdp->rx_ring, mdp->rx_desc_dma);
+
+skb_ring_free:
+	/* Free Rx and Tx skb ring buffer */
+	sh_eth_ring_free(ndev);
+
+	return ret;
+}
+
+static int sh_eth_dev_init(struct net_device *ndev)
+{
+	int ret = 0;
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u32 ioaddr = ndev->base_addr;
+	u_int32_t rx_int_var, tx_int_var;
+	u32 val;
+
+	/* Soft Reset */
+	sh__eth_reset(ndev);
+
+	ctrl_outl(RPADIR_PADS1, ioaddr + RPADIR);	/* SH7712-DMA-RX-PAD2 */
+
+	/* all sh_eth int mask */
+	ctrl_outl(0, ioaddr + EESIPR);
+
+	/* FIFO size set */
+	ctrl_outl(0, ioaddr + EDMR);	/* Endian change */
+
+	ctrl_outl((FIFO_SIZE_T | FIFO_SIZE_R), ioaddr + FDR);
+	ctrl_outl(0, ioaddr + TFTR);
+
+	ctrl_outl(RMCR_RST, ioaddr + RMCR);
+
+	rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5;
+	tx_int_var = mdp->tx_int_var = DESC_I_TINT2;
+	ctrl_outl(rx_int_var | tx_int_var, ioaddr + TRSCER);
+
+	ctrl_outl((FIFO_F_D_RFF | FIFO_F_D_RFD), ioaddr + FCFTR);
+	ctrl_outl(0, ioaddr + TRIMD);
+
+	/* Descriptor format */
+	sh_eth_ring_format(ndev);
+
+	ctrl_outl((u32)mdp->rx_ring, ioaddr + RDLAR);
+	ctrl_outl((u32)mdp->tx_ring, ioaddr + TDLAR);
+
+	ctrl_outl(ctrl_inl(ioaddr + EESR), ioaddr + EESR);
+	ctrl_outl((DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff), ioaddr + EESIPR);
+
+	/* PAUSE Prohibition */
+	val = (ctrl_inl(ioaddr + ECMR) & ECMR_DM) |
+		ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE;
+
+	ctrl_outl(val, ioaddr + ECMR);
+	ctrl_outl(ECSR_BRCRX | ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD |
+		  ECSIPR_MPDIP, ioaddr + ECSR);
+	ctrl_outl(ECSIPR_BRCRXIP | ECSIPR_PSRTOIP | ECSIPR_LCHNGIP |
+		  ECSIPR_ICDIP | ECSIPR_MPDIP, ioaddr + ECSIPR);
+
+	/* Set MAC address */
+	update_mac_address(ndev);
+
+	/* mask reset */
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+	ctrl_outl(APR_AP, ioaddr + APR);
+	ctrl_outl(MPR_MP, ioaddr + MPR);
+	ctrl_outl(TPAUSER_UNLIMITED, ioaddr + TPAUSER);
+	ctrl_outl(BCFR_UNLIMITED, ioaddr + BCFR);
+#endif
+	/* Setting the Rx mode will start the Rx process. */
+	ctrl_outl(EDRRR_R, ioaddr + EDRRR);
+
+	netif_start_queue(ndev);
+
+	return ret;
+}
+
+/* free Tx skb function */
+static int sh_eth_txfree(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	struct sh_eth_txdesc *txdesc;
+	int freeNum = 0;
+	int entry = 0;
+
+	for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
+		entry = mdp->dirty_tx % TX_RING_SIZE;
+		txdesc = &mdp->tx_ring[entry];
+		if (txdesc->status & cpu_to_le32(TD_TACT))
+			break;
+		/* Free the original skb. */
+		if (mdp->tx_skbuff[entry]) {
+			dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
+			mdp->tx_skbuff[entry] = NULL;
+			freeNum++;
+		}
+		txdesc->status = cpu_to_le32(TD_TFP);
+		if (entry >= TX_RING_SIZE - 1)
+			txdesc->status |= cpu_to_le32(TD_TDLE);
+
+		mdp->stats.tx_packets++;
+		mdp->stats.tx_bytes += txdesc->buffer_length;
+	}
+	return freeNum;
+}
+
+/* Packet receive function */
+static int sh_eth_rx(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	struct sh_eth_rxdesc *rxdesc;
+
+	int entry = mdp->cur_rx % RX_RING_SIZE;
+	int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx;
+	struct sk_buff *skb;
+	u16 pkt_len = 0;
+	u32 desc_status;
+
+	rxdesc = &mdp->rx_ring[entry];
+	while (!(rxdesc->status & cpu_to_le32(RD_RACT))) {
+		desc_status = le32_to_cpu(rxdesc->status);
+		pkt_len = rxdesc->frame_length;
+
+		if (--boguscnt < 0)
+			break;
+
+		if (!(desc_status & RDFEND))
+			mdp->stats.rx_length_errors++;
+
+		if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
+				   RD_RFS5 | RD_RFS6 | RD_RFS10)) {
+			mdp->stats.rx_errors++;
+			if (desc_status & RD_RFS1)
+				mdp->stats.rx_crc_errors++;
+			if (desc_status & RD_RFS2)
+				mdp->stats.rx_frame_errors++;
+			if (desc_status & RD_RFS3)
+				mdp->stats.rx_length_errors++;
+			if (desc_status & RD_RFS4)
+				mdp->stats.rx_length_errors++;
+			if (desc_status & RD_RFS6)
+				mdp->stats.rx_missed_errors++;
+			if (desc_status & RD_RFS10)
+				mdp->stats.rx_over_errors++;
+		} else {
+			swaps((char *)(rxdesc->addr & ~0x3), pkt_len + 2);
+			skb = mdp->rx_skbuff[entry];
+			mdp->rx_skbuff[entry] = NULL;
+			skb_put(skb, pkt_len);
+			skb->protocol = eth_type_trans(skb, ndev);
+			netif_rx(skb);
+			ndev->last_rx = jiffies;
+			mdp->stats.rx_packets++;
+			mdp->stats.rx_bytes += pkt_len;
+		}
+		rxdesc->status |= cpu_to_le32(RD_RACT);
+		entry = (++mdp->cur_rx) % RX_RING_SIZE;
+	}
+
+	/* Refill the Rx ring buffers. */
+	for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
+		entry = mdp->dirty_rx % RX_RING_SIZE;
+		rxdesc = &mdp->rx_ring[entry];
+		if (mdp->rx_skbuff[entry] == NULL) {
+			skb = dev_alloc_skb(mdp->rx_buf_sz);
+			mdp->rx_skbuff[entry] = skb;
+			if (skb == NULL)
+				break;	/* Better luck next round. */
+			skb->dev = ndev;
+			skb_reserve(skb, RX_OFFSET);
+			rxdesc->addr = (u32)skb->data & ~0x3UL;
+		}
+		/* The size of the buffer is 16 byte boundary. */
+		rxdesc->buffer_length = (mdp->rx_buf_sz + 16) & ~0x0F;
+		if (entry >= RX_RING_SIZE - 1)
+			rxdesc->status |=
+			cpu_to_le32(RD_RACT | RD_RFP | RC_RDEL);
+		else
+			rxdesc->status |=
+			cpu_to_le32(RD_RACT | RD_RFP);
+	}
+
+	/* Restart Rx engine if stopped. */
+	/* If we don't need to check status, don't. -KDU */
+	ctrl_outl(EDRRR_R, ndev->base_addr + EDRRR);
+
+	return 0;
+}
+
+/* error control function */
+static void sh_eth_error(struct net_device *ndev, int intr_status)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u32 ioaddr = ndev->base_addr;
+	u32 felic_stat;
+
+	if (intr_status & EESR_ECI) {
+		felic_stat = ctrl_inl(ioaddr + ECSR);
+		ctrl_outl(felic_stat, ioaddr + ECSR);	/* clear int */
+		if (felic_stat & ECSR_ICD)
+			mdp->stats.tx_carrier_errors++;
+		if (felic_stat & ECSR_LCHNG) {
+			/* Link Changed */
+			u32 link_stat = (ctrl_inl(ioaddr + PSR));
+			if (!(link_stat & PHY_ST_LINK)) {
+				/* Link Down : disable tx and rx */
+				ctrl_outl(ctrl_inl(ioaddr + ECMR) &
+					  ~(ECMR_RE | ECMR_TE), ioaddr + ECMR);
+			} else {
+				/* Link Up */
+				ctrl_outl(ctrl_inl(ioaddr + EESIPR) &
+					  ~DMAC_M_ECI, ioaddr + EESIPR);
+				/*clear int */
+				ctrl_outl(ctrl_inl(ioaddr + ECSR),
+					  ioaddr + ECSR);
+				ctrl_outl(ctrl_inl(ioaddr + EESIPR) |
+					  DMAC_M_ECI, ioaddr + EESIPR);
+				/* enable tx and rx */
+				ctrl_outl(ctrl_inl(ioaddr + ECMR) |
+					  (ECMR_RE | ECMR_TE), ioaddr + ECMR);
+			}
+		}
+	}
+
+	if (intr_status & EESR_TWB) {
+		/* Write buck end. unused write back interrupt */
+		if (intr_status & EESR_TABT)	/* Transmit Abort int */
+			mdp->stats.tx_aborted_errors++;
+	}
+
+	if (intr_status & EESR_RABT) {
+		/* Receive Abort int */
+		if (intr_status & EESR_RFRMER) {
+			/* Receive Frame Overflow int */
+			mdp->stats.rx_frame_errors++;
+			printk(KERN_ERR "Receive Frame Overflow\n");
+		}
+	}
+
+	if (intr_status & EESR_ADE) {
+		if (intr_status & EESR_TDE) {
+			if (intr_status & EESR_TFE)
+				mdp->stats.tx_fifo_errors++;
+		}
+	}
+
+	if (intr_status & EESR_RDE) {
+		/* Receive Descriptor Empty int */
+		mdp->stats.rx_over_errors++;
+
+		if (ctrl_inl(ioaddr + EDRRR) ^ EDRRR_R)
+			ctrl_outl(EDRRR_R, ioaddr + EDRRR);
+		printk(KERN_ERR "Receive Descriptor Empty\n");
+	}
+	if (intr_status & EESR_RFE) {
+		/* Receive FIFO Overflow int */
+		mdp->stats.rx_fifo_errors++;
+		printk(KERN_ERR "Receive FIFO Overflow\n");
+	}
+	if (intr_status &
+	    (EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE)) {
+		/* Tx error */
+		u32 edtrr = ctrl_inl(ndev->base_addr + EDTRR);
+		/* dmesg */
+		printk(KERN_ERR "%s:TX error. status=%8.8x cur_tx=%8.8x ",
+				ndev->name, intr_status, mdp->cur_tx);
+		printk(KERN_ERR "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n",
+				mdp->dirty_tx, (u32) ndev->state, edtrr);
+		/* dirty buffer free */
+		sh_eth_txfree(ndev);
+
+		/* SH7712 BUG */
+		if (edtrr ^ EDTRR_TRNS) {
+			/* tx dma start */
+			ctrl_outl(EDTRR_TRNS, ndev->base_addr + EDTRR);
+		}
+		/* wakeup */
+		netif_wake_queue(ndev);
+	}
+}
+
+static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
+{
+	struct net_device *ndev = netdev;
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u32 ioaddr, boguscnt = RX_RING_SIZE;
+	u32 intr_status = 0;
+
+	ioaddr = ndev->base_addr;
+	spin_lock(&mdp->lock);
+
+	intr_status = ctrl_inl(ioaddr + EESR);
+	/* Clear interrupt */
+	ctrl_outl(intr_status, ioaddr + EESR);
+
+	if (intr_status & (EESR_FRC | EESR_RINT8 |
+			   EESR_RINT5 | EESR_RINT4 | EESR_RINT3 | EESR_RINT2 |
+			   EESR_RINT1))
+		sh_eth_rx(ndev);
+	if (intr_status & (EESR_FTC |
+			   EESR_TINT4 | EESR_TINT3 | EESR_TINT2 | EESR_TINT1)) {
+
+		sh_eth_txfree(ndev);
+		netif_wake_queue(ndev);
+	}
+
+	if (intr_status & EESR_ERR_CHECK)
+		sh_eth_error(ndev, intr_status);
+
+	if (--boguscnt < 0) {
+		printk(KERN_WARNING
+		       "%s: Too much work at interrupt, status=0x%4.4x.\n",
+		       ndev->name, intr_status);
+	}
+
+	spin_unlock(&mdp->lock);
+
+	return IRQ_HANDLED;
+}
+
+static void sh_eth_timer(unsigned long data)
+{
+	struct net_device *ndev = (struct net_device *)data;
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	int next_tick = 10 * HZ;
+
+	/* We could do something here... nah. */
+	mdp->timer.expires = jiffies + next_tick;
+	add_timer(&mdp->timer);
+}
+
+/* PHY state control function */
+static void sh_eth_adjust_link(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	struct phy_device *phydev = mdp->phydev;
+	u32 ioaddr = ndev->base_addr;
+	int new_state = 0;
+
+	if (phydev->link != PHY_DOWN) {
+		if (phydev->duplex != mdp->duplex) {
+			new_state = 1;
+			mdp->duplex = phydev->duplex;
+		}
+
+		if (phydev->speed != mdp->speed) {
+			new_state = 1;
+			mdp->speed = phydev->speed;
+		}
+		if (mdp->link == PHY_DOWN) {
+			ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_TXF)
+					| ECMR_DM, ioaddr + ECMR);
+			new_state = 1;
+			mdp->link = phydev->link;
+			netif_schedule(ndev);
+			netif_carrier_on(ndev);
+			netif_start_queue(ndev);
+		}
+	} else if (mdp->link) {
+		new_state = 1;
+		mdp->link = PHY_DOWN;
+		mdp->speed = 0;
+		mdp->duplex = -1;
+		netif_stop_queue(ndev);
+		netif_carrier_off(ndev);
+	}
+
+	if (new_state)
+		phy_print_status(phydev);
+}
+
+/* PHY init function */
+static int sh_eth_phy_init(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	char phy_id[BUS_ID_SIZE];
+	struct phy_device *phydev = NULL;
+
+	snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT,
+		mdp->mii_bus->id , mdp->phy_id);
+
+	mdp->link = PHY_DOWN;
+	mdp->speed = 0;
+	mdp->duplex = -1;
+
+	/* Try connect to PHY */
+	phydev = phy_connect(ndev, phy_id, &sh_eth_adjust_link,
+				0, PHY_INTERFACE_MODE_MII);
+	if (IS_ERR(phydev)) {
+		dev_err(&ndev->dev, "phy_connect failed\n");
+		return PTR_ERR(phydev);
+	}
+	dev_info(&ndev->dev, "attached phy %i to driver %s\n",
+	phydev->addr, phydev->drv->name);
+
+	mdp->phydev = phydev;
+
+	return 0;
+}
+
+/* PHY control start function */
+static int sh_eth_phy_start(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	int ret;
+
+	ret = sh_eth_phy_init(ndev);
+	if (ret)
+		return ret;
+
+	/* reset phy - this also wakes it from PDOWN */
+	phy_write(mdp->phydev, MII_BMCR, BMCR_RESET);
+	phy_start(mdp->phydev);
+
+	return 0;
+}
+
+/* network device open function */
+static int sh_eth_open(struct net_device *ndev)
+{
+	int ret = 0;
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
+	ret = request_irq(ndev->irq, &sh_eth_interrupt, 0, ndev->name, ndev);
+	if (ret) {
+		printk(KERN_ERR "Can not assign IRQ number to %s\n", CARDNAME);
+		return ret;
+	}
+
+	/* Descriptor set */
+	ret = sh_eth_ring_init(ndev);
+	if (ret)
+		goto out_free_irq;
+
+	/* device init */
+	ret = sh_eth_dev_init(ndev);
+	if (ret)
+		goto out_free_irq;
+
+	/* PHY control start*/
+	ret = sh_eth_phy_start(ndev);
+	if (ret)
+		goto out_free_irq;
+
+	/* Set the timer to check for link beat. */
+	init_timer(&mdp->timer);
+	mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
+	mdp->timer.data = (u32) ndev;
+	mdp->timer.function = sh_eth_timer;	/* timer handler */
+	add_timer(&mdp->timer);
+
+	return ret;
+
+out_free_irq:
+	free_irq(ndev->irq, ndev);
+	return ret;
+}
+
+/* Timeout function */
+static void sh_eth_tx_timeout(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u32 ioaddr = ndev->base_addr;
+	struct sh_eth_rxdesc *rxdesc;
+	int i;
+
+	netif_stop_queue(ndev);
+
+	/* worning message out. */
+	printk(KERN_WARNING "%s: transmit timed out, status %8.8x,"
+	       " resetting...\n", ndev->name, (int)ctrl_inl(ioaddr + EESR));
+
+	/* tx_errors count up */
+	mdp->stats.tx_errors++;
+
+	/* timer off */
+	del_timer_sync(&mdp->timer);
+
+	/* Free all the skbuffs in the Rx queue. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		rxdesc = &mdp->rx_ring[i];
+		rxdesc->status = 0;
+		rxdesc->addr = 0xBADF00D0;
+		if (mdp->rx_skbuff[i])
+			dev_kfree_skb(mdp->rx_skbuff[i]);
+		mdp->rx_skbuff[i] = NULL;
+	}
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		if (mdp->tx_skbuff[i])
+			dev_kfree_skb(mdp->tx_skbuff[i]);
+		mdp->tx_skbuff[i] = NULL;
+	}
+
+	/* device init */
+	sh_eth_dev_init(ndev);
+
+	/* timer on */
+	mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
+	add_timer(&mdp->timer);
+}
+
+/* Packet transmit function */
+static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	struct sh_eth_txdesc *txdesc;
+	u32 entry;
+	int flags;
+
+	spin_lock_irqsave(&mdp->lock, flags);
+	if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) {
+		if (!sh_eth_txfree(ndev)) {
+			netif_stop_queue(ndev);
+			spin_unlock_irqrestore(&mdp->lock, flags);
+			return 1;
+		}
+	}
+	spin_unlock_irqrestore(&mdp->lock, flags);
+
+	entry = mdp->cur_tx % TX_RING_SIZE;
+	mdp->tx_skbuff[entry] = skb;
+	txdesc = &mdp->tx_ring[entry];
+	txdesc->addr = (u32)(skb->data);
+	/* soft swap. */
+	swaps((char *)(txdesc->addr & ~0x3), skb->len + 2);
+	/* write back */
+	__flush_purge_region(skb->data, skb->len);
+	if (skb->len < ETHERSMALL)
+		txdesc->buffer_length = ETHERSMALL;
+	else
+		txdesc->buffer_length = skb->len;
+
+	if (entry >= TX_RING_SIZE - 1)
+		txdesc->status |= cpu_to_le32(TD_TACT | TD_TDLE);
+	else
+		txdesc->status |= cpu_to_le32(TD_TACT);
+
+	mdp->cur_tx++;
+
+	ctrl_outl(EDTRR_TRNS, ndev->base_addr + EDTRR);
+	ndev->trans_start = jiffies;
+
+	return 0;
+}
+
+/* device close function */
+static int sh_eth_close(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u32 ioaddr = ndev->base_addr;
+	int ringsize;
+
+	netif_stop_queue(ndev);
+
+	/* Disable interrupts by clearing the interrupt mask. */
+	ctrl_outl(0x0000, ioaddr + EESIPR);
+
+	/* Stop the chip's Tx and Rx processes. */
+	ctrl_outl(0, ioaddr + EDTRR);
+	ctrl_outl(0, ioaddr + EDRRR);
+
+	/* PHY Disconnect */
+	if (mdp->phydev) {
+		phy_stop(mdp->phydev);
+		phy_disconnect(mdp->phydev);
+	}
+
+	free_irq(ndev->irq, ndev);
+
+	del_timer_sync(&mdp->timer);
+
+	/* Free all the skbuffs in the Rx queue. */
+	sh_eth_ring_free(ndev);
+
+	/* free DMA buffer */
+	ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
+	dma_free_coherent(NULL, ringsize, mdp->rx_ring, mdp->rx_desc_dma);
+
+	/* free DMA buffer */
+	ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
+	dma_free_coherent(NULL, ringsize, mdp->tx_ring, mdp->tx_desc_dma);
+
+	return 0;
+}
+
+static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	u32 ioaddr = ndev->base_addr;
+
+	mdp->stats.tx_dropped += ctrl_inl(ioaddr + TROCR);
+	ctrl_outl(0, ioaddr + TROCR);	/* (write clear) */
+	mdp->stats.collisions += ctrl_inl(ioaddr + CDCR);
+	ctrl_outl(0, ioaddr + CDCR);	/* (write clear) */
+	mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + LCCR);
+	ctrl_outl(0, ioaddr + LCCR);	/* (write clear) */
+	mdp->stats.tx_carrier_errors += ctrl_inl(ioaddr + CNDCR);
+	ctrl_outl(0, ioaddr + CNDCR);	/* (write clear) */
+
+	return &mdp->stats;
+}
+
+/* ioctl to device funciotn*/
+static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq,
+				int cmd)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	struct phy_device *phydev = mdp->phydev;
+
+	if (!netif_running(ndev))
+		return -EINVAL;
+
+	if (!phydev)
+		return -ENODEV;
+
+	return phy_mii_ioctl(phydev, if_mii(rq), cmd);
+}
+
+
+/* Multicast reception directions set */
+static void sh_eth_set_multicast_list(struct net_device *ndev)
+{
+	u32 ioaddr = ndev->base_addr;
+
+	if (ndev->flags & IFF_PROMISC) {
+		/* Set promiscuous. */
+		ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_MCT) | ECMR_PRM,
+			  ioaddr + ECMR);
+	} else {
+		/* Normal, unicast/broadcast-only mode. */
+		ctrl_outl((ctrl_inl(ioaddr + ECMR) & ~ECMR_PRM) | ECMR_MCT,
+			  ioaddr + ECMR);
+	}
+}
+
+/* SuperH's TSU register init function */
+static void __init sh_eth_tsu_init(u32 ioaddr)
+{
+	ctrl_outl(0, ioaddr + TSU_FWEN0);	/* Disable forward(0->1) */
+	ctrl_outl(0, ioaddr + TSU_FWEN1);	/* Disable forward(1->0) */
+	ctrl_outl(0, ioaddr + TSU_FCM);	/* forward fifo 3k-3k */
+	ctrl_outl(0xc, ioaddr + TSU_BSYSL0);
+	ctrl_outl(0xc, ioaddr + TSU_BSYSL1);
+	ctrl_outl(0, ioaddr + TSU_PRISL0);
+	ctrl_outl(0, ioaddr + TSU_PRISL1);
+	ctrl_outl(0, ioaddr + TSU_FWSL0);
+	ctrl_outl(0, ioaddr + TSU_FWSL1);
+	ctrl_outl(TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, ioaddr + TSU_FWSLC);
+	ctrl_outl(0, ioaddr + TSU_QTAGM0);	/* Disable QTAG(0->1) */
+	ctrl_outl(0, ioaddr + TSU_QTAGM1);	/* Disable QTAG(1->0) */
+	ctrl_outl(0, ioaddr + TSU_FWSR);	/* all interrupt status clear */
+	ctrl_outl(0, ioaddr + TSU_FWINMK);	/* Disable all interrupt */
+	ctrl_outl(0, ioaddr + TSU_TEN);	/* Disable all CAM entry */
+	ctrl_outl(0, ioaddr + TSU_POST1);	/* Disable CAM entry [ 0- 7] */
+	ctrl_outl(0, ioaddr + TSU_POST2);	/* Disable CAM entry [ 8-15] */
+	ctrl_outl(0, ioaddr + TSU_POST3);	/* Disable CAM entry [16-23] */
+	ctrl_outl(0, ioaddr + TSU_POST4);	/* Disable CAM entry [24-31] */
+}
+
+/* MDIO bus release function */
+static int sh__mdio_release(struct net_device *ndev)
+{
+	struct mii_bus *bus = dev_get_drvdata(&ndev->dev);
+
+	/* unregister mdio bus */
+	mdiobus_unregister(bus);
+
+	/* remove mdio bus info from net_device */
+	dev_set_drvdata(&ndev->dev, NULL);
+
+	/* free bitbang info */
+	free_mdio_bitbang(bus);
+
+	return 0;
+}
+
+/* MDIO bus init function */
+static int sh__mdio_init(struct net_device *ndev, int id)
+{
+	int ret, i;
+	struct bb_info *bitbang;
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
+	/* create bit control struct for PHY */
+	bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
+	if (!bitbang) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* bitbang init */
+	bitbang->addr = ndev->base_addr + PIR;
+	bitbang->mdi_msk = 0x08;
+	bitbang->mdo_msk = 0x04;
+	bitbang->mmd_msk = 0x02;/* MMD */
+	bitbang->mdc_msk = 0x01;
+	bitbang->ctrl.ops = &bb_ops;
+
+	/* MII contorller setting */
+	mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl);
+	if (!mdp->mii_bus) {
+		ret = -ENOMEM;
+		goto out_free_bitbang;
+	}
+
+	/* Hook up MII support for ethtool */
+	mdp->mii_bus->name = "sh__mii";
+	mdp->mii_bus->dev = &ndev->dev;
+	mdp->mii_bus->id = id;
+
+	/* PHY IRQ */
+	mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+	if (!mdp->mii_bus->irq) {
+		ret = -ENOMEM;
+		goto out_free_bus;
+	}
+
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		mdp->mii_bus->irq[i] = PHY_POLL;
+
+	/* regist mdio bus */
+	ret = mdiobus_register(mdp->mii_bus);
+	if (ret)
+		goto out_free_irq;
+
+	dev_set_drvdata(&ndev->dev, mdp->mii_bus);
+
+	return 0;
+
+out_free_irq:
+	kfree(mdp->mii_bus->irq);
+
+out_free_bus:
+	kfree(mdp->mii_bus);
+
+out_free_bitbang:
+	kfree(bitbang);
+
+out:
+	return ret;
+}
+
+static int sh_eth_drv_probe(struct platform_device *pdev)
+{
+	int ret, i, devno = 0;
+	struct resource *res;
+	struct net_device *ndev = NULL;
+	struct sh_eth_private *mdp;
+
+	/* get base addr */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(res == NULL)) {
+		dev_err(&pdev->dev, "invalid resource\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ndev = alloc_etherdev(sizeof(struct sh_eth_private));
+	if (!ndev) {
+		printk(KERN_ERR "%s: could not allocate device.\n", CARDNAME);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* The sh Ether-specific entries in the device structure. */
+	ndev->base_addr = res->start;
+	devno = pdev->id;
+	if (devno < 0)
+		devno = 0;
+
+	ndev->dma = -1;
+	ndev->irq = platform_get_irq(pdev, 0);
+	if (ndev->irq < 0) {
+		ret = -ENODEV;
+		goto out_release;
+	}
+
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+
+	/* Fill in the fields of the device structure with ethernet values. */
+	ether_setup(ndev);
+
+	mdp = netdev_priv(ndev);
+	spin_lock_init(&mdp->lock);
+
+	/* get PHY ID */
+	mdp->phy_id = (int)pdev->dev.platform_data;
+
+	/* set function */
+	ndev->open = sh_eth_open;
+	ndev->hard_start_xmit = sh_eth_start_xmit;
+	ndev->stop = sh_eth_close;
+	ndev->get_stats = sh_eth_get_stats;
+	ndev->set_multicast_list = sh_eth_set_multicast_list;
+	ndev->do_ioctl = sh_eth_do_ioctl;
+	ndev->tx_timeout = sh_eth_tx_timeout;
+	ndev->watchdog_timeo = TX_TIMEOUT;
+
+	mdp->post_rx = POST_RX >> (devno << 1);
+	mdp->post_fw = POST_FW >> (devno << 1);
+
+	/* read and set MAC address */
+	read_mac_address(ndev);
+
+	/* reset device */
+	ctrl_outl(ARSTR_ARSTR, ndev->base_addr + ARSTR);
+	mdelay(1);
+
+	/* TSU init (Init only)*/
+	sh_eth_tsu_init(SH_TSU_ADDR);
+
+	/* network device register */
+	ret = register_netdev(ndev);
+	if (ret)
+		goto out_release;
+
+	/* mdio bus init */
+	ret = sh__mdio_init(ndev, pdev->id);
+	if (ret)
+		goto out_unregister;
+
+	/* pritnt device infomation */
+	printk(KERN_INFO "%s: %s at 0x%x, ",
+	       ndev->name, CARDNAME, (u32) ndev->base_addr);
+
+	for (i = 0; i < 5; i++)
+		printk(KERN_INFO "%2.2x:", ndev->dev_addr[i]);
+	printk(KERN_INFO "%2.2x, IRQ %d.\n", ndev->dev_addr[i], ndev->irq);
+
+	platform_set_drvdata(pdev, ndev);
+
+	return ret;
+
+out_unregister:
+	unregister_netdev(ndev);
+
+out_release:
+	/* net_dev free */
+	if (ndev)
+		free_netdev(ndev);
+
+out:
+	return ret;
+}
+
+static int sh_eth_drv_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+
+	sh__mdio_release(ndev);
+	unregister_netdev(ndev);
+	flush_scheduled_work();
+
+	free_netdev(ndev);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver sh_eth_driver = {
+	.probe = sh_eth_drv_probe,
+	.remove = sh_eth_drv_remove,
+	.driver = {
+		   .name = CARDNAME,
+	},
+};
+
+static int __init sh_eth_init(void)
+{
+	return platform_driver_register(&sh_eth_driver);
+}
+
+static void __exit sh_eth_cleanup(void)
+{
+	platform_driver_unregister(&sh_eth_driver);
+}
+
+module_init(sh_eth_init);
+module_exit(sh_eth_cleanup);
+
+MODULE_AUTHOR("Nobuhiro Iwamatsu, Yoshihiro Shimoda");
+MODULE_DESCRIPTION("Renesas SuperH Ethernet driver");
+MODULE_LICENSE("GPL v2");
diff -uprN a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h
--- a/drivers/net/sh_eth.h	1970-01-01 09:00:00.000000000 +0900
+++ b/drivers/net/sh_eth.h	2008-01-18 16:15:28.000000000 +0900
@@ -0,0 +1,468 @@
+/*
+ *  SuperH Ethernet device driver
+ *
+ *  Copyright (C) 2006-2008 Nobuhiro Iwamatsu
+ *  Copyright (C) 2008 Renesas Solutions Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms and conditions of the GNU General Public License,
+ *  version 2, as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  The full GNU General Public License is included in this distribution in
+ *  the file called "COPYING".
+ */
+
+#ifndef __SH_ETH_H__
+#define __SH_ETH_H__
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+
+#define CARDNAME	"sh-eth"
+#define TX_TIMEOUT	(5*HZ)
+
+#define TX_RING_SIZE	128	/* Tx ring size */
+#define RX_RING_SIZE	128	/* Rx ring size */
+#define RX_OFFSET		2	/* skb offset */
+#define ETHERSMALL		60
+#define PKT_BUF_SZ		1538
+
+/* Chip Base Address */
+#define SH_ETH0_BASE 0xA7000000
+#define SH_ETH1_BASE 0xA7000400
+#define SH_TSU_ADDR 0xA7000804
+
+/* Chip Registers */
+/* E-DMAC */
+#define EDMR	0x0000
+#define EDTRR	0x0004
+#define EDRRR	0x0008
+#define TDLAR	0x000C
+#define RDLAR	0x0010
+#define EESR	0x0014
+#define EESIPR	0x0018
+#define TRSCER	0x001C
+#define RMFCR	0x0020
+#define TFTR	0x0024
+#define FDR		0x0028
+#define RMCR	0x002C
+#define EDOCR	0x0030
+#define FCFTR	0x0034
+#define RPADIR	0x0038
+#define TRIMD	0x003C
+#define RBWAR	0x0040
+#define RDFAR	0x0044
+#define TBRAR	0x004C
+#define TDFAR	0x0050
+/* Ether Register */
+#define ECMR	0x0160
+#define ECSR	0x0164
+#define ECSIPR	0x0168
+#define PIR		0x016C
+#define MAHR	0x0170
+#define MALR	0x0174
+#define RFLR	0x0178
+#define PSR		0x017C
+#define TROCR	0x0180
+#define CDCR	0x0184
+#define LCCR	0x0188
+#define CNDCR	0x018C
+#define CEFCR	0x0194
+#define FRECR	0x0198
+#define TSFRCR	0x019C
+#define TLFRCR	0x01A0
+#define RFCR	0x01A4
+#define MAFCR	0x01A8
+#define IPGR	0x01B4
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+#define APR		0x01B8
+#define MPR 	0x01BC
+#define TPAUSER 0x1C4
+#define BCFR	0x1CC
+#endif /* CONFIG_CPU_SH7710 */
+
+#define ARSTR	0x0800
+
+/* TSU */
+#define TSU_CTRST	0x004
+#define TSU_FWEN0	0x010
+#define TSU_FWEN1	0x014
+#define TSU_FCM		0x018
+#define TSU_BSYSL0	0x020
+#define TSU_BSYSL1	0x024
+#define TSU_PRISL0	0x028
+#define TSU_PRISL1	0x02C
+#define TSU_FWSL0	0x030
+#define TSU_FWSL1	0x034
+#define TSU_FWSLC	0x038
+#define TSU_QTAGM0	0x040
+#define TSU_QTAGM1	0x044
+#define TSU_ADQT0 	0x048
+#define TSU_ADQT1	0x04C
+#define TSU_FWSR	0x050
+#define TSU_FWINMK	0x054
+#define TSU_ADSBSY	0x060
+#define TSU_TEN		0x064
+#define TSU_POST1	0x070
+#define TSU_POST2	0x074
+#define TSU_POST3	0x078
+#define TSU_POST4	0x07C
+#define TXNLCR0		0x080
+#define TXALCR0		0x084
+#define RXNLCR0		0x088
+#define RXALCR0		0x08C
+#define FWNLCR0		0x090
+#define FWALCR0		0x094
+#define TXNLCR1		0x0A0
+#define TXALCR1		0x0A4
+#define RXNLCR1		0x0A8
+#define RXALCR1		0x0AC
+#define FWNLCR1		0x0B0
+#define FWALCR1		0x0B4
+
+#define TSU_ADRH0	0x0100
+#define TSU_ADRL0	0x0104
+#define TSU_ADRL31	0x01FC
+
+/* Register's bits */
+
+/* EDMR */
+enum DMAC_M_BIT {
+	EDMR_DL1 = 0x20, EDMR_DL0 = 0x10, EDMR_SRST = 0x01,
+};
+
+/* EDTRR */
+enum DMAC_T_BIT {
+	EDTRR_TRNS = 0x01,
+};
+
+/* EDRRR*/
+enum EDRRR_R_BIT {
+	EDRRR_R = 0x01,
+};
+
+/* TPAUSER */
+enum TPAUSER_BIT {
+	TPAUSER_TPAUSE = 0x0000ffff,
+	TPAUSER_UNLIMITED = 0,
+};
+
+/* BCFR */
+enum BCFR_BIT {
+	BCFR_RPAUSE = 0x0000ffff,
+	BCFR_UNLIMITED = 0,
+};
+
+/* PIR */
+enum PIR_BIT {
+	PIR_MDI = 0x08, PIR_MDO = 0x04, PIR_MMD = 0x02, PIR_MDC = 0x01,
+};
+
+/* PSR */
+enum PHY_STATUS_BIT { PHY_ST_LINK = 0x01, };
+
+/* EESR */
+enum EESR_BIT {
+	EESR_TWB = 0x40000000, EESR_TABT = 0x04000000,
+	EESR_RABT = 0x02000000, EESR_RFRMER = 0x01000000,
+	EESR_ADE = 0x00800000, EESR_ECI = 0x00400000,
+	EESR_FTC = 0x00200000, EESR_TDE = 0x00100000,
+	EESR_TFE = 0x00080000, EESR_FRC = 0x00040000,
+	EESR_RDE = 0x00020000, EESR_RFE = 0x00010000,
+	EESR_TINT4 = 0x00000800, EESR_TINT3 = 0x00000400,
+	EESR_TINT2 = 0x00000200, EESR_TINT1 = 0x00000100,
+	EESR_RINT8 = 0x00000080, EESR_RINT5 = 0x00000010,
+	EESR_RINT4 = 0x00000008, EESR_RINT3 = 0x00000004,
+	EESR_RINT2 = 0x00000002, EESR_RINT1 = 0x00000001,
+};
+
+#define EESR_ERR_CHECK	(EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE \
+		| EESR_RFRMER | EESR_ADE | EESR_TFE | EESR_TDE | EESR_ECI)
+
+/* EESIPR */
+enum DMAC_IM_BIT {
+	DMAC_M_TWB = 0x40000000, DMAC_M_TABT = 0x04000000,
+	DMAC_M_RABT = 0x02000000,
+	DMAC_M_RFRMER = 0x01000000, DMAC_M_ADF = 0x00800000,
+	DMAC_M_ECI = 0x00400000, DMAC_M_FTC = 0x00200000,
+	DMAC_M_TDE = 0x00100000, DMAC_M_TFE = 0x00080000,
+	DMAC_M_FRC = 0x00040000, DMAC_M_RDE = 0x00020000,
+	DMAC_M_RFE = 0x00010000, DMAC_M_TINT4 = 0x00000800,
+	DMAC_M_TINT3 = 0x00000400, DMAC_M_TINT2 = 0x00000200,
+	DMAC_M_TINT1 = 0x00000100, DMAC_M_RINT8 = 0x00000080,
+	DMAC_M_RINT5 = 0x00000010, DMAC_M_RINT4 = 0x00000008,
+	DMAC_M_RINT3 = 0x00000004, DMAC_M_RINT2 = 0x00000002,
+	DMAC_M_RINT1 = 0x00000001,
+};
+
+/* Receive descriptor bit */
+enum RD_STS_BIT {
+	RD_RACT = 0x80000000, RC_RDEL = 0x40000000,
+	RC_RFP1 = 0x20000000, RC_RFP0 = 0x10000000,
+	RD_RFE = 0x08000000, RD_RFS10 = 0x00000200,
+	RD_RFS9 = 0x00000100, RD_RFS8 = 0x00000080,
+	RD_RFS7 = 0x00000040, RD_RFS6 = 0x00000020,
+	RD_RFS5 = 0x00000010, RD_RFS4 = 0x00000008,
+	RD_RFS3 = 0x00000004, RD_RFS2 = 0x00000002,
+	RD_RFS1 = 0x00000001,
+};
+#define RDF1ST	RC_RFP1
+#define RDFEND	RC_RFP0
+#define RD_RFP	(RC_RFP1|RC_RFP0)
+
+/* FCFTR */
+enum FCFTR_BIT {
+	FCFTR_RFF2 = 0x00040000, FCFTR_RFF1 = 0x00020000,
+	FCFTR_RFF0 = 0x00010000, FCFTR_RFD2 = 0x00000004,
+	FCFTR_RFD1 = 0x00000002, FCFTR_RFD0 = 0x00000001,
+};
+#define FIFO_F_D_RFF	(FCFTR_RFF2|FCFTR_RFF1|FCFTR_RFF0)
+#define FIFO_F_D_RFD	(FCFTR_RFD2|FCFTR_RFD1|FCFTR_RFD0)
+
+/* Transfer descriptor bit */
+enum TD_STS_BIT {
+	TD_TACT = 0x80000000, TD_TDLE = 0x40000000, TD_TFP1 = 0x20000000,
+	TD_TFP0 = 0x10000000,
+};
+#define TDF1ST	TD_TFP1
+#define TDFEND	TD_TFP0
+#define TD_TFP	(TD_TFP1|TD_TFP0)
+
+/* RMCR */
+enum RECV_RST_BIT { RMCR_RST = 0x01, };
+/* ECMR */
+enum FELIC_MODE_BIT {
+	ECMR_ZPF = 0x00080000, ECMR_PFR = 0x00040000, ECMR_RXF = 0x00020000,
+	ECMR_TXF = 0x00010000, ECMR_MCT = 0x00002000, ECMR_PRCEF = 0x00001000,
+	ECMR_PMDE = 0x00000200, ECMR_RE = 0x00000040, ECMR_TE = 0x00000020,
+	ECMR_ILB = 0x00000008, ECMR_ELB = 0x00000004, ECMR_DM = 0x00000002,
+	ECMR_PRM = 0x00000001,
+};
+
+/* ECSR */
+enum ECSR_STATUS_BIT {
+	ECSR_BRCRX = 0x20, ECSR_PSRTO = 0x10, ECSR_LCHNG = 0x04,
+	ECSR_MPD = 0x02, ECSR_ICD = 0x01,
+};
+
+/* ECSIPR */
+enum ECSIPR_STATUS_MASK_BIT {
+	ECSIPR_BRCRXIP = 0x20, ECSIPR_PSRTOIP = 0x10, ECSIPR_LCHNGIP = 0x04,
+	ECSIPR_MPDIP = 0x02, ECSIPR_ICDIP = 0x01,
+};
+
+/* APR */
+enum APR_BIT {
+	APR_AP = 0x00000001,
+};
+
+/* MPR */
+enum MPR_BIT {
+	MPR_MP = 0x00000001,
+};
+
+/* TRSCER */
+enum DESC_I_BIT {
+	DESC_I_TINT4 = 0x0800, DESC_I_TINT3 = 0x0400, DESC_I_TINT2 = 0x0200,
+	DESC_I_TINT1 = 0x0100, DESC_I_RINT8 = 0x0080, DESC_I_RINT5 = 0x0010,
+	DESC_I_RINT4 = 0x0008, DESC_I_RINT3 = 0x0004, DESC_I_RINT2 = 0x0002,
+	DESC_I_RINT1 = 0x0001,
+};
+
+/* RPADIR */
+enum RPADIR_BIT {
+	RPADIR_PADS1 = 0x20000, RPADIR_PADS0 = 0x10000,
+	RPADIR_PADR = 0x0003f,
+};
+
+/* FDR */
+enum FIFO_SIZE_BIT {
+	FIFO_SIZE_T = 0x00000700, FIFO_SIZE_R = 0x00000007,
+};
+enum phy_offsets {
+	PHY_CTRL = 0, PHY_STAT = 1, PHY_IDT1 = 2, PHY_IDT2 = 3,
+	PHY_ANA = 4, PHY_ANL = 5, PHY_ANE = 6,
+	PHY_16 = 16,
+};
+
+/* PHY_CTRL */
+enum PHY_CTRL_BIT {
+	PHY_C_RESET = 0x8000, PHY_C_LOOPBK = 0x4000, PHY_C_SPEEDSL = 0x2000,
+	PHY_C_ANEGEN = 0x1000, PHY_C_PWRDN = 0x0800, PHY_C_ISO = 0x0400,
+	PHY_C_RANEG = 0x0200, PHY_C_DUPLEX = 0x0100, PHY_C_COLT = 0x0080,
+};
+#define DM9161_PHY_C_ANEGEN 0	/* auto nego special */
+
+/* PHY_STAT */
+enum PHY_STAT_BIT {
+	PHY_S_100T4 = 0x8000, PHY_S_100X_F = 0x4000, PHY_S_100X_H = 0x2000,
+	PHY_S_10T_F = 0x1000, PHY_S_10T_H = 0x0800, PHY_S_ANEGC = 0x0020,
+	PHY_S_RFAULT = 0x0010, PHY_S_ANEGA = 0x0008, PHY_S_LINK = 0x0004,
+	PHY_S_JAB = 0x0002, PHY_S_EXTD = 0x0001,
+};
+
+/* PHY_ANA */
+enum PHY_ANA_BIT {
+	PHY_A_NP = 0x8000, PHY_A_ACK = 0x4000, PHY_A_RF = 0x2000,
+	PHY_A_FCS = 0x0400, PHY_A_T4 = 0x0200, PHY_A_FDX = 0x0100,
+	PHY_A_HDX = 0x0080, PHY_A_10FDX = 0x0040, PHY_A_10HDX = 0x0020,
+	PHY_A_SEL = 0x001f,
+};
+/* PHY_ANL */
+enum PHY_ANL_BIT {
+	PHY_L_NP = 0x8000, PHY_L_ACK = 0x4000, PHY_L_RF = 0x2000,
+	PHY_L_FCS = 0x0400, PHY_L_T4 = 0x0200, PHY_L_FDX = 0x0100,
+	PHY_L_HDX = 0x0080, PHY_L_10FDX = 0x0040, PHY_L_10HDX = 0x0020,
+	PHY_L_SEL = 0x001f,
+};
+
+/* PHY_ANE */
+enum PHY_ANE_BIT {
+	PHY_E_PDF = 0x0010, PHY_E_LPNPA = 0x0008, PHY_E_NPA = 0x0004,
+	PHY_E_PRX = 0x0002, PHY_E_LPANEGA = 0x0001,
+};
+
+/* DM9161 */
+enum PHY_16_BIT {
+	PHY_16_BP4B45 = 0x8000, PHY_16_BPSCR = 0x4000, PHY_16_BPALIGN = 0x2000,
+	PHY_16_BP_ADPOK = 0x1000, PHY_16_Repeatmode = 0x0800,
+	PHY_16_TXselect = 0x0400,
+	PHY_16_Rsvd = 0x0200, PHY_16_RMIIEnable = 0x0100,
+	PHY_16_Force100LNK = 0x0080,
+	PHY_16_APDLED_CTL = 0x0040, PHY_16_COLLED_CTL = 0x0020,
+	PHY_16_RPDCTR_EN = 0x0010,
+	PHY_16_ResetStMch = 0x0008, PHY_16_PreamSupr = 0x0004,
+	PHY_16_Sleepmode = 0x0002,
+	PHY_16_RemoteLoopOut = 0x0001,
+};
+
+#define POST_RX		0x08
+#define POST_FW		0x04
+#define POST0_RX	(POST_RX)
+#define POST0_FW	(POST_FW)
+#define POST1_RX	(POST_RX >> 2)
+#define POST1_FW	(POST_FW >> 2)
+#define POST_ALL	(POST0_RX | POST0_FW | POST1_RX | POST1_FW)
+
+/* ARSTR */
+enum ARSTR_BIT { ARSTR_ARSTR = 0x00000001, };
+
+/* TSU_FWEN0 */
+enum TSU_FWEN0_BIT {
+	TSU_FWEN0_0 = 0x00000001,
+};
+
+/* TSU_ADSBSY */
+enum TSU_ADSBSY_BIT {
+	TSU_ADSBSY_0 = 0x00000001,
+};
+
+/* TSU_TEN */
+enum TSU_TEN_BIT {
+	TSU_TEN_0 = 0x80000000,
+};
+
+/* TSU_FWSL0 */
+enum TSU_FWSL0_BIT {
+	TSU_FWSL0_FW50 = 0x1000, TSU_FWSL0_FW40 = 0x0800,
+	TSU_FWSL0_FW30 = 0x0400, TSU_FWSL0_FW20 = 0x0200,
+	TSU_FWSL0_FW10 = 0x0100, TSU_FWSL0_RMSA0 = 0x0010,
+};
+
+/* TSU_FWSLC */
+enum TSU_FWSLC_BIT {
+	TSU_FWSLC_POSTENU = 0x2000, TSU_FWSLC_POSTENL = 0x1000,
+	TSU_FWSLC_CAMSEL03 = 0x0080, TSU_FWSLC_CAMSEL02 = 0x0040,
+	TSU_FWSLC_CAMSEL01 = 0x0020, TSU_FWSLC_CAMSEL00 = 0x0010,
+	TSU_FWSLC_CAMSEL13 = 0x0008, TSU_FWSLC_CAMSEL12 = 0x0004,
+	TSU_FWSLC_CAMSEL11 = 0x0002, TSU_FWSLC_CAMSEL10 = 0x0001,
+};
+
+/*
+ * The sh ether Tx buffer descriptors.
+ * This structure should be 20 bytes.
+ */
+struct sh_eth_txdesc {
+	u32 status;		/* TD0 */
+#if defined(CONFIG_CPU_LITTLE_ENDIAN)
+	u16 pad0;		/* TD1 */
+	u16 buffer_length;	/* TD1 */
+#else
+	u16 buffer_length;	/* TD1 */
+	u16 pad0;		/* TD1 */
+#endif
+	u32 addr;		/* TD2 */
+	u32 pad1;		/* padding data */
+};
+
+/*
+ * The sh ether Rx buffer descriptors.
+ * This structure should be 20 bytes.
+ */
+struct sh_eth_rxdesc {
+	u32 status;		/* RD0 */
+#if defined(CONFIG_CPU_LITTLE_ENDIAN)
+	u16 frame_length;	/* RD1 */
+	u16 buffer_length;	/* RD1 */
+#else
+	u16 buffer_length;	/* RD1 */
+	u16 frame_length;	/* RD1 */
+#endif
+	u32 addr;		/* RD2 */
+	u32 pad0;		/* padding data */
+};
+
+struct sh_eth_private {
+	dma_addr_t rx_desc_dma;
+	dma_addr_t tx_desc_dma;
+	struct sh_eth_rxdesc *rx_ring;
+	struct sh_eth_txdesc *tx_ring;
+	struct sk_buff **rx_skbuff;
+	struct sk_buff **tx_skbuff;
+	struct net_device_stats stats;
+	struct timer_list timer;
+	spinlock_t lock;
+	u32 cur_rx, dirty_rx;	/* Producer/consumer ring indices */
+	u32 cur_tx, dirty_tx;
+	u32 rx_buf_sz;		/* Based on MTU+slack. */
+	/* MII transceiver section. */
+	u32 phy_id;					/* PHY ID */
+	struct mii_bus *mii_bus;	/* MDIO bus control */
+	struct phy_device *phydev;	/* PHY device control */
+	enum phy_state link;
+	int msg_enable;
+	int speed;
+	int duplex;
+	u32 rx_int_var, tx_int_var;	/* interrupt control variables */
+	char post_rx;		/* POST receive */
+	char post_fw;		/* POST forward */
+	struct net_device_stats tsu_stats;	/* TSU forward status */
+};
+
+#ifdef __LITTLE_ENDIAN__
+static inline void swaps(char *src, int len)
+{
+	u32 *p = (u32 *)src;
+	u32 *maxp;
+	maxp = p + ((len + sizeof(u32) - 1) / sizeof(u32));
+
+	for (; p < maxp; p++)
+		*p = swab32(*p);
+}
+#else
+#define swaps(x, y)
+#endif
+
+#endif /* __SH_ETH_H__ */


^ permalink raw reply

* Re: [PATCH 4/4] bonding: Fix some RTNL taking
From: Makito SHIOKAWA @ 2008-01-18  9:06 UTC (permalink / raw)
  To: Jarek Poplawski; +Cc: netdev, Makito SHIOKAWA
In-Reply-To: <20080117114655.GC1710@ff.dom.local>

> Probably the difference is not much, but since this all double locking,
> unlocking and something between could take a while, and such a check
> looks cheaper than re-queueing... But I don't persist in this.
Looks like this one is settled, thank you for your advice!

--
Makito SHIOKAWA
MIRACLE LINUX CORPORATION

^ permalink raw reply

* [PATCH] add modalias info to mv643xx_eth.ko
From: Olaf Hering @ 2008-01-18  9:38 UTC (permalink / raw)
  To: linuxppc-dev, netdev; +Cc: Dale Farnsworth

mv643xx_eth has an platform modalias file in sysfs.
But the module itself has no alias: line. Autoloading fails
without the alias info in the module.

Signed-off-by: Olaf Hering <olaf@aepfle.de>

---
 drivers/net/mv643xx_eth.c |    1 +
 1 file changed, 1 insertion(+)

--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -2099,6 +2099,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR(	"Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani"
 		" and Dale Farnsworth");
 MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX");
+MODULE_ALIAS("platform:mv643xx_eth");
 
 /*
  * The second part is the low level driver of the gigE ethernet ports.

^ permalink raw reply

* [PATCH] Fix module names in net/sched/Kconfig
From: Masato Miyagi @ 2008-01-18  9:04 UTC (permalink / raw)
  To: netdev; +Cc: kazuko-lpc

[-- Attachment #1: Type: text/plain, Size: 126 bytes --]

Hi,
This patch fixes the module names in net/sched/Kconfig ;)

Signed-Off-By: Masato Miyagi <miyagi-masato@msg.biglobe.ne.jp>

[-- Attachment #2: patch-net-sched-Kconfig.txt --]
[-- Type: text/plain, Size: 1977 bytes --]

--- linux-2.6.24-rc8-mm1/net/sched/Kconfig.orig	2008-01-18 16:55:33.000000000 +0900
+++ linux-2.6.24-rc8-mm1/net/sched/Kconfig	2008-01-18 17:04:57.000000000 +0900
@@ -404,7 +404,7 @@ config NET_ACT_POLICE
 	  module.
 
 	  To compile this code as a module, choose M here: the
-	  module will be called police.
+	  module will be called act_police.
 
 config NET_ACT_GACT
         tristate "Generic actions"
@@ -414,7 +414,7 @@ config NET_ACT_GACT
 	  accepting packets.
 
 	  To compile this code as a module, choose M here: the
-	  module will be called gact.
+	  module will be called act_gact.
 
 config GACT_PROB
         bool "Probability support"
@@ -430,7 +430,7 @@ config NET_ACT_MIRRED
 	  other devices.
 
 	  To compile this code as a module, choose M here: the
-	  module will be called mirred.
+	  module will be called act_mirred.
 
 config NET_ACT_IPT
         tristate "IPtables targets"
@@ -440,7 +440,7 @@ config NET_ACT_IPT
 	  classification.
 
 	  To compile this code as a module, choose M here: the
-	  module will be called ipt.
+	  module will be called act_ipt.
 
 config NET_ACT_NAT
         tristate "Stateless NAT"
@@ -450,7 +450,7 @@ config NET_ACT_NAT
 	  netfilter for NAT unless you know what you are doing.
 
 	  To compile this code as a module, choose M here: the
-	  module will be called nat.
+	  module will be called act_nat.
 
 config NET_ACT_PEDIT
         tristate "Packet Editing"
@@ -459,7 +459,7 @@ config NET_ACT_PEDIT
 	  Say Y here if you want to mangle the content of packets.
 
 	  To compile this code as a module, choose M here: the
-	  module will be called pedit.
+	  module will be called act_pedit.
 
 config NET_ACT_SIMP
         tristate "Simple Example (Debug)"
@@ -473,7 +473,7 @@ config NET_ACT_SIMP
 	  If unsure, say N.
 
 	  To compile this code as a module, choose M here: the
-	  module will be called simple.
+	  module will be called act_simple.
 
 config NET_CLS_POLICE
 	bool "Traffic Policing (obsolete)"

^ permalink raw reply

* [PATCH] Add LRO control to ethtool
From: Ben Hutchings @ 2008-01-18 11:01 UTC (permalink / raw)
  To: netdev

The kernel-side ethtool code supports ETHTOOL_{G,S}FLAGS commands
which can control various features; currently the only feature is LRO.
I didn't see any code to use these in the ethtool git repository
<git://git.kernel.org/pub/scm/network/ethtool/ethtool.git>.  So here's
a patch that adds that.  I tested this with the latest version of the
sfc driver, which we should be re-posting later today.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>

diff --git a/ethtool.c b/ethtool.c
index 3adf843..cfe7c9f 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -151,7 +151,8 @@ static struct option {
 		"		[ sg on|off ]\n"
 	        "		[ tso on|off ]\n"
 	        "		[ ufo on|off ]\n"
-	        "		[ gso on|off ]\n" },
+	        "		[ gso on|off ]\n"
+	        "		[ lro on|off ]\n" },
     { "-i", "--driver", MODE_GDRV, "Show driver information" },
     { "-d", "--register-dump", MODE_GREGS, "Do a register dump",
 		"		[ raw on|off ]\n"
@@ -200,6 +201,7 @@ static int off_sg_wanted = -1;
 static int off_tso_wanted = -1;
 static int off_ufo_wanted = -1;
 static int off_gso_wanted = -1;
+static int off_lro_wanted = -1;
 
 static struct ethtool_pauseparam epause;
 static int gpause_changed = 0;
@@ -310,6 +312,7 @@ static struct cmdline_info cmdline_offload[] = {
 	{ "tso", CMDL_BOOL, &off_tso_wanted, NULL },
 	{ "ufo", CMDL_BOOL, &off_ufo_wanted, NULL },
 	{ "gso", CMDL_BOOL, &off_gso_wanted, NULL },
+	{ "lro", CMDL_BOOL, &off_lro_wanted, NULL },
 };
 
 static struct cmdline_info cmdline_pause[] = {
@@ -1217,7 +1220,8 @@ static int dump_coalesce(void)
 	return 0;
 }
 
-static int dump_offload (int rx, int tx, int sg, int tso, int ufo, int gso)
+static int dump_offload (int rx, int tx, int sg, int tso, int ufo, int gso,
+			 int lro)
 {
 	fprintf(stdout,
 		"rx-checksumming: %s\n"
@@ -1225,13 +1229,15 @@ static int dump_offload (int rx, int tx, int sg, int tso, int ufo, int gso)
 		"scatter-gather: %s\n"
 		"tcp segmentation offload: %s\n"
 		"udp fragmentation offload: %s\n"
-		"generic segmentation offload: %s\n",
+		"generic segmentation offload: %s\n"
+		"large receive offload: %s\n",
 		rx ? "on" : "off",
 		tx ? "on" : "off",
 		sg ? "on" : "off",
 		tso ? "on" : "off",
 		ufo ? "on" : "off",
-		gso ? "on" : "off");
+		gso ? "on" : "off",
+		lro ? "on" : "off");
 
 	return 0;
 }
@@ -1495,7 +1501,8 @@ static int do_scoalesce(int fd, struct ifreq *ifr)
 static int do_goffload(int fd, struct ifreq *ifr)
 {
 	struct ethtool_value eval;
-	int err, allfail = 1, rx = 0, tx = 0, sg = 0, tso = 0, ufo = 0, gso = 0;
+	int err, allfail = 1;
+	int rx = 0, tx = 0, sg = 0, tso = 0, ufo = 0, gso = 0, lro = 0;
 
 	fprintf(stdout, "Offload parameters for %s:\n", devname);
 
@@ -1559,12 +1566,22 @@ static int do_goffload(int fd, struct ifreq *ifr)
 		allfail = 0;
 	}
 
+	eval.cmd = ETHTOOL_GFLAGS;
+	ifr->ifr_data = (caddr_t)&eval;
+	err = ioctl(fd, SIOCETHTOOL, ifr);
+	if (err)
+		perror("Cannot get device large receive offload settings");
+	else {
+		lro = (eval.data & ETH_FLAG_LRO) != 0;
+		allfail = 0;
+	}
+
 	if (allfail) {
 		fprintf(stdout, "no offload info available\n");
 		return 83;
 	}
 
-	return dump_offload(rx, tx, sg, tso, ufo, gso);
+	return dump_offload(rx, tx, sg, tso, ufo, gso, lro);
 }
 
 static int do_soffload(int fd, struct ifreq *ifr)
@@ -1641,6 +1658,17 @@ static int do_soffload(int fd, struct ifreq *ifr)
 			return 90;
 		}
 	}
+	if (off_lro_wanted >= 0) {
+		changed = 1;
+		eval.cmd = ETHTOOL_SFLAGS;
+		eval.data = (off_lro_wanted == 1) ? ETH_FLAG_LRO : 0;
+		ifr->ifr_data = (caddr_t)&eval;
+		err = ioctl(fd, SIOCETHTOOL, ifr);
+		if (err) {
+			perror("Cannot set device large receive offload settings");
+			return 91;
+		}
+	}
 	if (!changed) {
 		fprintf(stdout, "no offload settings changed\n");
 	}


-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.

^ permalink raw reply related

* Re: [FIB]: Fix rcu_dereference() abuses in fib_trie.c
From: David Miller @ 2008-01-18 11:31 UTC (permalink / raw)
  To: dada1; +Cc: netdev, stephen.hemminger, herbert
In-Reply-To: <20080115092940.311fb2c3.dada1@cosmosbay.com>

From: Eric Dumazet <dada1@cosmosbay.com>
Date: Tue, 15 Jan 2008 09:29:40 +0100

> node_parent() and tnode_get_child() currently use rcu_dereference().
> 
> These functions are called from both 
> - readers only paths (where rcu_dereference() is needed), and 
> - writer path (where rcu_dereference() is not needed)
> 
> To make explicit where rcu_dereference() is really needed, I introduced
> new node_parent_rcu() and tnode_get_child_rcu() functions which use
> rcu_dereference(), while node_parent() and tnode_get_child() dont use it.
> 
> Then I changed calling sites where rcu_dereference() was really needed to
> call the _rcu() variants.
> 
> This should have no impact but for alpha architecture, and may help future
> sparse checks.
> 
> Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>

Applied to net-2.6.25, thanks Eric.

^ permalink raw reply

* Re: [IPV4] FIB_HASH: Reduce memory needs and speedup lookups
From: David Miller @ 2008-01-18 11:33 UTC (permalink / raw)
  To: dada1; +Cc: netdev
In-Reply-To: <478DAB10.7030901@cosmosbay.com>

From: Eric Dumazet <dada1@cosmosbay.com>
Date: Wed, 16 Jan 2008 07:58:24 +0100

> [IPV4] FIB_HASH: Reduce memory needs and speedup lookups
 ...
> Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>

Applied to net-2.6.25, thanks Eric.

^ permalink raw reply

* Re: [PATCH 1/2] [IPV4] fib_hash: fix duplicated route issue
From: David Miller @ 2008-01-18 11:44 UTC (permalink / raw)
  To: joonwpark81; +Cc: netdev, stephen.hemminger, green
In-Reply-To: <12004820052610-git-send-email-joonwpark81@gmail.com>

From: Joonwoo Park <joonwpark81@gmail.com>
Date: Wed, 16 Jan 2008 20:13:25 +0900

> http://bugzilla.kernel.org/show_bug.cgi?id=9493
> 
> The fib allows making identical routes with 'ip route replace'.
> This patch makes the fib return -EEXIST if replacement would cause duplication.
> 
> Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH 2/2] [IPV4] fib_trie: fix duplicated route issue
From: David Miller @ 2008-01-18 11:45 UTC (permalink / raw)
  To: joonwpark81; +Cc: netdev, stephen.hemminger, green
In-Reply-To: <120048202988-git-send-email-joonwpark81@gmail.com>

From: Joonwoo Park <joonwpark81@gmail.com>
Date: Wed, 16 Jan 2008 20:13:49 +0900

> http://bugzilla.kernel.org/show_bug.cgi?id=9493
> 
> The fib allows making identical routes with 'ip route replace'.
> This patch makes the fib return -EEXIST if replacement would cause duplication.
> 
> Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>

Also applied, thanks.

^ permalink raw reply

* Re: [patch 1/2][NETNS][DST] dst: pass the dst_ops as parameter to the gc functions
From: David Miller @ 2008-01-18 11:57 UTC (permalink / raw)
  To: dlezcano; +Cc: netdev, den, benjamin.thery
In-Reply-To: <20080116150724.711756326@localhost.localdomain>

From: Daniel Lezcano <dlezcano@fr.ibm.com>
Date: Wed, 16 Jan 2008 15:54:17 +0100

> The garbage collection function receive the dst_ops structure as
> parameter. This is useful for the next incoming patchset because
> it will need the dst_ops (there will be several instances) and 
> the network namespace pointer (contained in the dst_ops).
> 
> The protocols which do not take care of the namespaces will not
> be impacted by this change (expect for the function signature),
> they do just ignore the parameter.
> 
> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>

Applied.

^ permalink raw reply

* Re: [patch 2/2][NETNS][DST] add the network namespace pointer in dst_ops
From: David Miller @ 2008-01-18 11:58 UTC (permalink / raw)
  To: dlezcano; +Cc: netdev, den, benjamin.thery
In-Reply-To: <20080116150733.443636890@localhost.localdomain>

From: Daniel Lezcano <dlezcano@fr.ibm.com>
Date: Wed, 16 Jan 2008 15:54:18 +0100

> The network namespace pointer can be stored into the dst_ops structure.
> This is usefull when there are multiple instances of the dst_ops for a
> protocol. When there are no several instances, this field will be never
> used in the protocol. So there is no impact for the protocols which do
> implement the network namespaces.
> 
> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>

Applied, thanks.

^ permalink raw reply

* RE: [PATCH 0/3] UCC TDM driver for MPC83xx platforms
From: Aggrwal Poonam @ 2008-01-18 11:58 UTC (permalink / raw)
  To: Kumar Gala, Andrew Morton
  Cc: Phillips Kim, sfr, rubini, linuxppc-dev, netdev, linux-kernel,
	Barkowski Michael, Kalra Ashish, Cutler Richard, Suresh PV
In-Reply-To: <5927F7A4-D42A-40F6-AE9C-EDA34738A752@kernel.crashing.org>

Hello All

The TDM driver just now does not have a proper framework. Probably the
interface cannot be generalised as such. Hence we could not decide
whether it would be right to think of a TDM framework. Infact the
interface this TDM driver(for MPC8323ERDB) supplies may not be usable
for some other client as such. Please suggest on this.

But you are right as far as Freescale PowerPC platforms are concerned
which have TDM devices. Like, 8315 also has a TDM driver which also
exposes similar interface as 8323 because the client it is talking to is
the same.

Following is the small description of the TDM driver along with
interface details:

The dts file keeps a track of the TDM devices present on the board.
Depending on them the TDM driver initializes those many driver instances
while coming up.

The driver on the upper level can plug to more than one tdm clients
depending on the availablity  of TDM devices. At every new request of
the TDM client to bind with a TDM device, a free driver  instance is
allocated to the client.

The interface can be described as follows.

tdm_register_client(struct tdm_client *)
	This API returns a pointer to the structure tdm_client which is
of type
	struct tdm_client {
                u32 driver_handle;
                u32 (*tdm_read)(u32 driver_handle, short chn_id, short
*pcm_buffer, short len);
                u32 (*tdm_write)(u32 driver_handle, short chn_id, short
*pcm_buffer, short len);
                wait_queue_head_t *wakeup_event;
        }

   It consists of:
   - driver_handle: It is basically to identify the particular TDM
device/driver instance.
   - tdm_read: It is a function pointer returned by the TDM driver to be
used to read TDM data  form a particular TDM channel.
   - tdm_write: It is a function pointer returned by the TDM driver to
be used to write TDM data  to a particular TDM channel.
   - wakeup_event: It is address of a wait_queue event on which the
client keeps on sleeping,  and the TDM driver wakes it up periodically.
The driver is configured to wake up the client  after every 10ms.

Once the TDM client gets registered to a TDM driver instance and a TDM
device, it interfaces  with the driver using tdm_read, tdm_write and
wakeup_event.

Note: The TDM driver can be used by only kernel level modules. The
driver does not expose any  file interface for User Applications. Can be
compared to the spi driver which interfaces with  the SPI clients
through some APIs.


I need your feedback on the interface details. Some changes were
suggested by Andrew for 32 bit tdm handle which I will modify.(Thanks
Andrew)

Please give your ideas about a TDM framework in the kernel and the
interface.

Waiting for your feedback.

Thanks and Regards
Poonam 
 
 

-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org] 
Sent: Tuesday, January 15, 2008 9:01 AM
To: Andrew Morton
Cc: Phillips Kim; Aggrwal Poonam; sfr@canb.auug.org.au;
rubini@vision.unipv.it; linux-ppcdev@ozlabs.kernel.org;
netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Barkowski Michael;
Kalra Ashish; Cutler Richard
Subject: Re: [PATCH 0/3] UCC TDM driver for MPC83xx platforms


On Jan 14, 2008, at 3:15 PM, Andrew Morton wrote:

> On Mon, 14 Jan 2008 12:00:51 -0600
> Kim Phillips <kim.phillips@freescale.com> wrote:
>
>> On Thu, 10 Jan 2008 21:41:20 -0700
>> "Aggrwal Poonam" <Poonam.Aggrwal@freescale.com> wrote:
>>
>>> Hello  All
>>>
>>> I am waiting for more feedback on the patches.
>>>
>>> If there are no objections please consider them for 2.6.25.
>>>
>> if this isn't going to go through Alessandro Rubini/misc drivers, can

>> it go through the akpm/mm tree?
>>
>
> That would work.  But it might be more appropriate to go Kumar-
> >paulus->Linus.

I'm ok w/taking the arch/powerpc bits, but I"m a bit concerned about  
the driver itself.  I'm wondering if we need a TDM framework in the  
kernel.

I guess if Poonam could possibly describe how this driver is actually  
used that would be helpful.  I see we have 8315 with a discrete TDM  
block and I'm guessing 82xx/85xx based CPM parts of some form of TDM  
as well.

- k

^ permalink raw reply

* Re: [REGRESSION] 2.6.24-rc7: e1000: Detected Tx Unit Hang
From: David Miller @ 2008-01-18 12:11 UTC (permalink / raw)
  To: Robert.Olsson; +Cc: elendil, jesse.brandeburg, slavon, netdev, linux-kernel
In-Reply-To: <18318.14810.877279.41815@robur.slu.se>

From: Robert Olsson <Robert.Olsson@data.slu.se>
Date: Wed, 16 Jan 2008 18:07:38 +0100

> 
> eth0 e1000_irq_enable sem = 1    <- High netload
> eth0 e1000_irq_enable sem = 1
> eth0 e1000_irq_enable sem = 1
> eth0 e1000_irq_enable sem = 1
> eth0 e1000_irq_enable sem = 1
> eth0 e1000_irq_enable sem = 1
> eth0 e1000_irq_enable sem = 1    <- ifconfig eth0 down
> eth0 e1000_irq_disable sem = 2
> 
> **e1000_open                     <- ifconfig eth0 up
> eth0 e1000_irq_disable sem = 3      Dead. irq's can't be enabled
> e1000_irq_enable miss
> eth0 e1000_irq_enable sem = 2
> e1000_irq_enable miss
> eth0 e1000_irq_enable sem = 1
> ADDRCONF(NETDEV_UP): eth0: link is not ready

Yes, this semaphore thing is highly problematic.  In the most crucial
areas where network driver consistency matters the most for ease of
understanding and debugging, the Intel drivers choose to be different
:-(

The way the napi_disable() logic breaks out from high packet load in
net_rx_action() is it simply returns even leaving interrupts disabled
when a pending napi_disable() is pending.

This is what trips up the semaphore logic.

Robert, give this patch a try.

In the long term this semaphore should be completely eliminated,
there is no justification for it.

Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 0c9a6f7..76c0fa6 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -632,6 +632,7 @@ e1000_down(struct e1000_adapter *adapter)
 
 #ifdef CONFIG_E1000_NAPI
 	napi_disable(&adapter->napi);
+	atomic_set(&adapter->irq_sem, 0);
 #endif
 	e1000_irq_disable(adapter);
 
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 2ab3bfb..9cc5a6b 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2183,6 +2183,7 @@ void e1000e_down(struct e1000_adapter *adapter)
 	msleep(10);
 
 	napi_disable(&adapter->napi);
+	atomic_set(&adapter->irq_sem, 0);
 	e1000_irq_disable(adapter);
 
 	del_timer_sync(&adapter->watchdog_timer);
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index d2fb88d..4f63839 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -296,6 +296,11 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
 {
 	struct net_device *netdev = adapter->netdev;
 
+#ifdef CONFIG_IXGB_NAPI
+	napi_disable(&adapter->napi);
+	atomic_set(&adapter->irq_sem, 0);
+#endif
+
 	ixgb_irq_disable(adapter);
 	free_irq(adapter->pdev->irq, netdev);
 
@@ -304,9 +309,7 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
 
 	if(kill_watchdog)
 		del_timer_sync(&adapter->watchdog_timer);
-#ifdef CONFIG_IXGB_NAPI
-	napi_disable(&adapter->napi);
-#endif
+
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
 	netif_carrier_off(netdev);
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index de3f45e..a4265bc 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1409,9 +1409,11 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
 	IXGBE_WRITE_FLUSH(&adapter->hw);
 	msleep(10);
 
+	napi_disable(&adapter->napi);
+	atomic_set(&adapter->irq_sem, 0);
+
 	ixgbe_irq_disable(adapter);
 
-	napi_disable(&adapter->napi);
 	del_timer_sync(&adapter->watchdog_timer);
 
 	netif_carrier_off(netdev);

^ permalink raw reply related

* RE: [PATCH 0/3] UCC TDM driver for MPC83xx platforms
From: Joakim Tjernlund @ 2008-01-18 12:18 UTC (permalink / raw)
  To: Aggrwal Poonam
  Cc: sfr, Phillips Kim, Barkowski Michael, netdev, Suresh PV, rubini,
	linux-kernel, linuxppc-dev, Kalra Ashish, Cutler Richard,
	Andrew Morton
In-Reply-To: <FBA61160C48B8D438F3323FEFB4EF2C279A908@zin33exm24.fsl.freescale.net>


On Fri, 2008-01-18 at 17:28 +0530, Aggrwal Poonam wrote:
> Hello All
> 
> The TDM driver just now does not have a proper framework. Probably the
> interface cannot be generalised as such. Hence we could not decide
> whether it would be right to think of a TDM framework. Infact the
> interface this TDM driver(for MPC8323ERDB) supplies may not be usable
> for some other client as such. Please suggest on this.
> 
> But you are right as far as Freescale PowerPC platforms are concerned
> which have TDM devices. Like, 8315 also has a TDM driver which also
> exposes similar interface as 8323 because the client it is talking to is
> the same.
> 
> Following is the small description of the TDM driver along with
> interface details:
> 
> The dts file keeps a track of the TDM devices present on the board.
> Depending on them the TDM driver initializes those many driver instances
> while coming up.
> 
> The driver on the upper level can plug to more than one tdm clients
> depending on the availablity  of TDM devices. At every new request of
> the TDM client to bind with a TDM device, a free driver  instance is
> allocated to the client.
> 
> The interface can be described as follows.
> 
> tdm_register_client(struct tdm_client *)
> 	This API returns a pointer to the structure tdm_client which is
> of type
> 	struct tdm_client {
>                 u32 driver_handle;
>                 u32 (*tdm_read)(u32 driver_handle, short chn_id, short
> *pcm_buffer, short len);
>                 u32 (*tdm_write)(u32 driver_handle, short chn_id, short
> *pcm_buffer, short len);
>                 wait_queue_head_t *wakeup_event;
>         }
> 
>    It consists of:
>    - driver_handle: It is basically to identify the particular TDM
> device/driver instance.
>    - tdm_read: It is a function pointer returned by the TDM driver to be
> used to read TDM data  form a particular TDM channel.
>    - tdm_write: It is a function pointer returned by the TDM driver to
> be used to write TDM data  to a particular TDM channel.
>    - wakeup_event: It is address of a wait_queue event on which the
> client keeps on sleeping,  and the TDM driver wakes it up periodically.
> The driver is configured to wake up the client  after every 10ms.
> 
> Once the TDM client gets registered to a TDM driver instance and a TDM
> device, it interfaces  with the driver using tdm_read, tdm_write and
> wakeup_event.
> 
> Note: The TDM driver can be used by only kernel level modules. The
> driver does not expose any  file interface for User Applications. Can be
> compared to the spi driver which interfaces with  the SPI clients
> through some APIs.
> 
> 
> I need your feedback on the interface details. Some changes were
> suggested by Andrew for 32 bit tdm handle which I will modify.(Thanks
> Andrew)
> 
> Please give your ideas about a TDM framework in the kernel and the
> interface.
> 
> Waiting for your feedback.
> 
> Thanks and Regards
> Poonam 

Hi Poonam

I may have to write a HDLC over QMC driver for 832x in the near future.
Although I haven't looked at much at the UCCs programming i/f I noticed
that QMC is supposed to run over TDM. Is your TDM driver suitable for
hooking up such a driver on top?

  Jocke

^ permalink raw reply

* Re: [IPV4] FIB_HASH : Avoid unecessary loop in fn_hash_dump_zone()
From: David Miller @ 2008-01-18 12:30 UTC (permalink / raw)
  To: dada1; +Cc: netdev, Robert.Olsson
In-Reply-To: <20080116181925.2c5c540f.dada1@cosmosbay.com>

From: Eric Dumazet <dada1@cosmosbay.com>
Date: Wed, 16 Jan 2008 18:19:25 +0100

> I noticed "ip route list" was slower than "cat /proc/net/route" on a machine with a full Internet
> routing table (214392 entries : Special thanks to Robert ;) )
> 
> This is similar to problem reported in commit d8c9283089287341c85a0a69de32c2287a990e71
> 
> Fix is to avoid scanning the begining of fz_hash table, but directly seek to the right offset.
> 
> Before patch :
> 
> time ip route >/tmp/ROUTE
> 
> real    0m1.285s
> user    0m0.712s
> sys     0m0.436s
> 
> After patch
> 
> # time ip route >/tmp/ROUTE
> 
> real    0m0.835s
> user    0m0.692s
> sys     0m0.124s
> 
> Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>

Applied, thanks Eric.

^ permalink raw reply

* Re: Please pull 'fixes-davem' branch of wireless-2.6
From: David Miller @ 2008-01-18 12:33 UTC (permalink / raw)
  To: linville-2XuSBdqkA4R54TAoqtyWWQ
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20080116212645.GD3164-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>

From: "John W. Linville" <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
Date: Wed, 16 Jan 2008 16:26:45 -0500

> One more fix for rfkill in 2.6.24...note that this branch is based
> on 2.6.24-rc8.

Pulled, thanks John.

^ permalink raw reply

* Re: sctp use-uninitialized warning in net-2.6.25
From: David Miller @ 2008-01-18 12:49 UTC (permalink / raw)
  To: akpm; +Cc: netdev, vladislav.yasevich
In-Reply-To: <20080116135957.4eb54958.akpm@linux-foundation.org>

From: Andrew Morton <akpm@linux-foundation.org>
Date: Wed, 16 Jan 2008 13:59:57 -0800

> net/sctp/sm_statefuns.c: In function 'sctp_sf_do_5_1C_ack':
> net/sctp/sm_statefuns.c:484: warning: 'error' may be used uninitialized in this function
> 
> It is not obvious that this is a false positive.

I'll check in the following for now.

Vlad, please take a look.

diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index b126751..6e12757 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -481,7 +481,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
 	sctp_init_chunk_t *initchunk;
 	struct sctp_chunk *err_chunk;
 	struct sctp_packet *packet;
-	sctp_error_t error;
+	sctp_error_t error = SCTP_ERROR_NO_ERROR;
 
 	if (!sctp_vtag_verify(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);

^ permalink raw reply related

* [PATCH 0/4 net-2.6.25] Proper netlink kernel sockets disposal.
From: Denis V. Lunev @ 2008-01-18 12:51 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Linux Containers, devel

Alexey Dobriyan found, that virtualized netlink kernel sockets (fibl &
rtnl) are leaked during namespace start/stop loop.

Leaking fix (simple and obvious) reveals that netlink kernel socket
disposal leads to OOPSes:
- nl_table[protocol]->listeners is double freed
- sometimes during namespace stop netlink_sock_destruct
  BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc)); is hit

This set address all these issues.

Signed-off-by: Denis V. Lunev <den@openvz.org>
Tested-by: Alexey Dobriayn <adobriyan@openvz.org>


^ permalink raw reply

* Re: [PATCH] atl1: fix frame length bug
From: Jay Cliburn @ 2008-01-18 12:52 UTC (permalink / raw)
  To: davem; +Cc: Jay Cliburn, jeff, csnook, netdev
In-Reply-To: <20080114200428.1c62e8fb@osprey.hogchain.net>

On Mon, 14 Jan 2008 20:04:28 -0600
Jay Cliburn <jacliburn@bellsouth.net> wrote:

> On Mon, 14 Jan 2008 19:56:41 -0600
> Jay Cliburn <jacliburn@bellsouth.net> wrote:
> 
> > The driver sets up the hardware to accept a frame with max length
> > equal to MTU + Ethernet header + FCS + VLAN tag, but we neglect to
> > add the VLAN tag size to the ingress buffer.  When a VLAN-tagged
> > frame arrives, the hardware passes it, but bad things happen
> > because the buffer is too small.  This patch fixes that.
> > 
> > Thanks to David Harris for reporting the bug and testing the fix.
> > 
> > Tested-by: David Harris <david.harris@cpni-inc.com>
> > Signed-off-by: Jay Cliburn <jacliburn@bellsouth.net>
> 
> Jeff, Dave,
> 
> This bugfix needs to go in for 2.6.24 if possible.

Dave,

I saw a message you sent awhile ago about Jeff handing off some netdev
stuff to you.  Since I haven't seen anything to rescind that notice,
I'll direct my request to you.

Could you please merge this patch for 2.6.24?
http://article.gmane.org/gmane.linux.network/83368

When the reporter hits the bug, the result is a locked up kernel.
Granted, it's triggered only in the presence of VLAN tagged frames, but
it's a serious bug and the fix is simple.

Jay

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox