Netdev List
 help / color / mirror / Atom feed
* Re: IPV6_RTHDR with a type-0 routing header
From: Rémi Denis-Courmont @ 2009-08-20 11:29 UTC (permalink / raw)
  To: Steinar H. Gunderson; +Cc: netdev
In-Reply-To: <20090820111152.GA20295@uio.no>


On Thu, 20 Aug 2009 13:11:52 +0200, "Steinar H. Gunderson"
<sgunderson@bigfoot.com> wrote:
> I've tried attaching a type-0 routing header to my IPv6 packets with
> setsockopt(..., IPV6_RTHDR, ...), but the kernel just returns EINVAL.
> looking at the source, it seems it simply refuses anything that's not
> type-2;
> should that really be right? I found the following commit:

RT0 headers have been deprecated by IETF. The kernel refuses to use then on
purpose.

-- 
Rémi Denis-Courmont


^ permalink raw reply

* [PATCH 3/3] r6040: bump to version 0.25 and 20 August 2009 release date
From: Florian Fainelli @ 2009-08-20 11:26 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, mark, bifferos


Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 7238a6f..8068a07 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -49,8 +49,8 @@
 #include <asm/processor.h>
 
 #define DRV_NAME	"r6040"
-#define DRV_VERSION	"0.24"
-#define DRV_RELDATE	"08Jul2009"
+#define DRV_VERSION	"0.25"
+#define DRV_RELDATE	"20Aug2009"
 
 /* PHY CHIP Address */
 #define PHY1_ADDR	1	/* For MAC1 */

^ permalink raw reply related

* [PATCH 2/3] r6040: move down second PHY detection to r6040_init_one
From: Florian Fainelli @ 2009-08-20 11:26 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, mark, bifferos

From: Mark Kelly <mark@bifferos.com>

Instead of fully initializing an unusable second r6040
device, perform the PHY detection earlier and bail out
in r6040_init_one when we could not read the PHY identifier.

Signed-off-by: Mark Kelly <mark@bifferos.com>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 60bd010..7238a6f 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -750,14 +750,6 @@ static int r6040_up(struct net_device *dev)
 	struct r6040_private *lp = netdev_priv(dev);
 	void __iomem *ioaddr = lp->base;
 	int ret;
-	u16 val;
-
-	/* Check presence of a second PHY */
-	val = r6040_phy_read(ioaddr, lp->phy_addr, 2);
-	if (val == 0xFFFF) {
-		printk(KERN_ERR DRV_NAME " no second PHY attached\n");
-		return -EIO;
-	}
 
 	/* Initialise and alloc RX/TX buffers */
 	r6040_init_txbufs(dev);
@@ -1194,6 +1186,13 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
 	lp->mii_if.phy_id_mask = 0x1f;
 	lp->mii_if.reg_num_mask = 0x1f;
 
+	/* Check the vendor ID on the PHY, if 0xffff assume none attached */
+	if (r6040_phy_read(ioaddr, lp->phy_addr, 2) == 0xffff) {
+		printk(KERN_ERR DRV_NAME ": Failed to detect an attached PHY\n");
+		err = -ENODEV;
+		goto err_out_unmap;
+	}
+
 	/* Register net device. After this dev->name assign */
 	err = register_netdev(dev);
 	if (err) {

^ permalink raw reply related

* [PATCH 1/3] r6040: remove unused pioaddr variable
From: Florian Fainelli @ 2009-08-20 11:26 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, mark, bifferos

From: Mark Kelly <mark@bifferos.com>

This patch removes the unused pioaddr variable.

Signed-off-by: Mark Kelly <mark@bifferos.com>
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 840677f..60bd010 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -1091,7 +1091,6 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
 	int err, io_size = R6040_IO_SIZE;
 	static int card_idx = -1;
 	int bar = 0;
-	long pioaddr;
 	u16 *adrp;
 
 	printk(KERN_INFO "%s\n", version);
@@ -1121,7 +1120,6 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
 		goto err_out;
 	}
 
-	pioaddr = pci_resource_start(pdev, bar);	/* IO map base address */
 	pci_set_master(pdev);
 
 	dev = alloc_etherdev(sizeof(struct r6040_private));

^ permalink raw reply related

* IPV6_RTHDR with a type-0 routing header
From: Steinar H. Gunderson @ 2009-08-20 11:11 UTC (permalink / raw)
  To: brian.haley, davem; +Cc: netdev, shanwei

Hi,

I've tried attaching a type-0 routing header to my IPv6 packets with
setsockopt(..., IPV6_RTHDR, ...), but the kernel just returns EINVAL.
looking at the source, it seems it simply refuses anything that's not type-2;
should that really be right? I found the following commit:

  http://kerneltrap.org/mailarchive/linux-netdev/2008/11/11/4064594

However, it only seems to change EPERM into EINVAL. I don't see any
reasonable explanation why it should not be simply success; in fact, RFC 3452
only seems to talk about using type-0 headers with this option.

Any ideas?

/* Steinar */
-- 
Homepage: http://www.sesse.net/

^ permalink raw reply

* Re: [PATCH] netpoll: WARN_ONCE for start_xmit returns with interrupts enabled
From: DDD @ 2009-08-20 10:44 UTC (permalink / raw)
  To: Matt Mackall; +Cc: linux-kernel, Ingo Molnar, David Miller, netdev
In-Reply-To: <1250678596.3937.182.camel@calx>

On Wed, 2009-08-19 at 05:43 -0500, Matt Mackall wrote: 
> On Wed, 2009-08-19 at 18:43 +0800, DDD wrote:
> > The NETPOLL API requires that interrupts remain disabled in
> > netpoll_send_skb().
> > 
> > Add a WARN_ONCE when ndo_start_xmit returns with interrupts enabled
> > in netpoll_send_skb().
> > 
> > Signed-off-by: Dongdong Deng <dongdong.deng@windriver.com>
> > ---
> >  net/core/netpoll.c |    6 ++++++
> >  1 files changed, 6 insertions(+), 0 deletions(-)
> > 
> > diff --git a/net/core/netpoll.c b/net/core/netpoll.c
> > index df30feb..d38103f 100644
> > --- a/net/core/netpoll.c
> > +++ b/net/core/netpoll.c
> > @@ -319,6 +319,12 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
> >  
> >  			udelay(USEC_PER_POLL);
> >  		}
> > +
> > +		WARN_ONCE(!irqs_disabled(),
> > +			KERN_WARNING "netpoll_send_skb(): [net driver %s]"
> > +			"ndo_start_xmit() shouldn't return with interrupts"
> > +			"enabled!", dev->name);
> 
> Hmm, perhaps:
> 
> "netpoll_send_skb(): %s enabled interrupts in poll (%pF)\n",
> dev->name, ops->ndo_start_xmit
> 
> That'll give us a real function name and maybe even a module name.

Thanks, I will modify it as your suggestions.

When I test the WRAN_ONCE, I find that some net drivers still have this problem,
such as using local_irq_disable/local_irq_enable in ndo_start_xmit() or other cases.


I will do an new patch and hope it could fix this problem completely in all the net drivers that support NETPOLL.


I check the drivers that support NETPOLL one by one again(almost 100 drivers),
and following drivers's fix will be included by my patch:

1: ixp2000/ixpdev.c : 66 local_irq_disable

2: fec_mpc52xx.c : 319 spin_unlock_irq

3: macb.c:602 : 638 spin_unlock_irq

4: mlx4/en_netdev.c : 448 
mlx4_en_xmit() -> mlx4_en_xmit_poll() -> spin_trylock_irq

5: smc91x.c 
It seems that there is a lots work to let smc91x work well with netpoll.


Thanks,
Dongdong

> 

^ permalink raw reply

* Re: [Alacrityvm-devel] [PATCH v3 3/6] vbus: add a "vbus-proxy" bus model for vbus_driver objects
From: Avi Kivity @ 2009-08-20 10:08 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: Hollis Blanchard, Ira W. Snyder, Michael S. Tsirkin,
	Gregory Haskins, kvm, netdev, linux-kernel, alacrityvm-devel,
	Anthony Liguori, Ingo Molnar, Gregory Haskins
In-Reply-To: <fbd9d3990908200257ge4e13ceh32f28601bc0f762f@mail.gmail.com>

On 08/20/2009 12:57 PM, Stefan Hajnoczi wrote:
> Cross-platform virtio works when endianness is known in advance.  For
> a hypervisor and a guest:
> 1. virtio-pci I/O registers use PCI endianness
> 2. vring uses guest endianness (hypervisor must byteswap)
> 3. guest memory buffers use guest endianness (hypervisor must byteswap)
>
> I know of no existing way when endianness is not known in advance.
> Perhaps a transport bit could be added to mark the endianness of the
> guest/driver side.  This can be negotiated because virtio-pci has a
> known endianness.  After negotiation, the host knows whether or not
> byteswapping is necessary for structures in guest memory.
>
>    

Some processors are capable of switching their gender at runtime, so you 
cannot tell the guest endianness in advance.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply

* Re: [Alacrityvm-devel] [PATCH v3 3/6] vbus: add a "vbus-proxy" bus model for vbus_driver objects
From: Stefan Hajnoczi @ 2009-08-20  9:57 UTC (permalink / raw)
  To: Hollis Blanchard
  Cc: Avi Kivity, Ira W. Snyder, Michael S. Tsirkin, Gregory Haskins,
	kvm, netdev, linux-kernel, alacrityvm-devel, Anthony Liguori,
	Ingo Molnar, Gregory Haskins
In-Reply-To: <1250715920.4237.26.camel@slab.beaverton.ibm.com>

On Wed, Aug 19, 2009 at 10:05 PM, Hollis Blanchard<hollisb@us.ibm.com> wrote:
> On Wed, 2009-08-19 at 19:38 +0300, Avi Kivity wrote:
>> On 08/19/2009 07:29 PM, Ira W. Snyder wrote:
>> >>> That said, I'm not sure how qemu-system-ppc running on x86 could
>> >>> possibly communicate using virtio-net. This would mean the guest is an
>> >>> emulated big-endian PPC, while the host is a little-endian x86. I
>> >>> haven't actually tested this situation, so perhaps I am wrong.

Cross-platform virtio works when endianness is known in advance.  For
a hypervisor and a guest:
1. virtio-pci I/O registers use PCI endianness
2. vring uses guest endianness (hypervisor must byteswap)
3. guest memory buffers use guest endianness (hypervisor must byteswap)

I know of no existing way when endianness is not known in advance.
Perhaps a transport bit could be added to mark the endianness of the
guest/driver side.  This can be negotiated because virtio-pci has a
known endianness.  After negotiation, the host knows whether or not
byteswapping is necessary for structures in guest memory.

Stefan

^ permalink raw reply

* [PATCH] WAN/LMC: Fix type_trans().
From: Krzysztof Halasa @ 2009-08-20  9:56 UTC (permalink / raw)
  To: netdev

Fix lmc_proto_type() invocation.

Signed-off-by: Krzysztof Hałasa <khc@pm.waw.pl>

diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 45b1822..1b46d56 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -1657,7 +1657,7 @@ static int lmc_rx(struct net_device *dev)
             }
             skb_copy_from_linear_data(skb, skb_put(nsb, len), len);
             
-            nsb->protocol = lmc_proto_type(sc, skb);
+            nsb->protocol = lmc_proto_type(sc, nsb);
             skb_reset_mac_header(nsb);
             /* skb_reset_network_header(nsb); */
             nsb->dev = dev;

-- 
Krzysztof Halasa

^ permalink raw reply related

* Re: [PATCH] [V3] net: add Xilinx emac lite device driver
From: David Miller @ 2009-08-20  9:52 UTC (permalink / raw)
  To: john.linn
  Cc: netdev, linuxppc-dev, jgarzik, grant.likely, jwboyer,
	john.williams, michal.simek, sadanan
In-Reply-To: <20090820094956.02DFC45004F@mail96-dub.bigfish.com>

From: John Linn <john.linn@xilinx.com>
Date: Thu, 20 Aug 2009 03:49:51 -0600

> This patch adds support for the Xilinx Ethernet Lite device.  The
> soft logic core from Xilinx is typically used on Virtex and Spartan
> designs attached to either a PowerPC or a Microblaze processor.
> 
> Signed-off-by: Sadanand M <sadanan@xilinx.com>
> Signed-off-by: John Linn <john.linn@xilinx.com>

Applied, thanks.

^ permalink raw reply

* [PATCH] [V3] net: add Xilinx emac lite device driver
From: John Linn @ 2009-08-20  9:49 UTC (permalink / raw)
  To: netdev, linuxppc-dev, davem, jgarzik
  Cc: John Linn, Grant Likely, Josh Boyer, John Williams, Michal Simek,
	Sadanand M

This patch adds support for the Xilinx Ethernet Lite device.  The
soft logic core from Xilinx is typically used on Virtex and Spartan
designs attached to either a PowerPC or a Microblaze processor.

CC: Grant Likely <grant.likely@secretlab.ca>
CC: Josh Boyer <jwboyer@linux.vnet.ibm.com>
CC: John Williams <john.williams@petalogix.com>
CC: Michal Simek <michal.simek@petalogix.com>
Signed-off-by: Sadanand M <sadanan@xilinx.com>
Signed-off-by: John Linn <john.linn@xilinx.com>

---

V2 - cleanup based on review, added depends for ppc and mb in Kconfig
V3 - fixed bug, spin lock was not initialized
---
 drivers/net/Kconfig           |    6 +
 drivers/net/Makefile          |    1 +
 drivers/net/xilinx_emaclite.c | 1041 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1048 insertions(+), 0 deletions(-)
 create mode 100755 drivers/net/xilinx_emaclite.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5f6509a..ec77b69 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1926,6 +1926,12 @@ config ATL2
 	  To compile this driver as a module, choose M here.  The module
 	  will be called atl2.
 
+config XILINX_EMACLITE
+	tristate "Xilinx 10/100 Ethernet Lite support"
+	depends on PPC32 || MICROBLAZE
+	help
+	  This driver supports the 10/100 Ethernet Lite from Xilinx.
+
 source "drivers/net/fs_enet/Kconfig"
 
 endif # NET_ETHERNET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index ead8cab..99ae6d7 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -142,6 +142,7 @@ obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
 ll_temac-objs := ll_temac_main.o ll_temac_mdio.o
 obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o
+obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
 obj-$(CONFIG_QLA3XXX) += qla3xxx.o
 obj-$(CONFIG_QLGE) += qlge/
 
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
new file mode 100755
index 0000000..7e05b40
--- /dev/null
+++ b/drivers/net/xilinx_emaclite.c
@@ -0,0 +1,1041 @@
+/*
+ * Xilinx EmacLite Linux driver for the Xilinx Ethernet MAC Lite device.
+ *
+ * This is a new flat driver which is based on the original emac_lite
+ * driver from John Williams <john.williams@petalogix.com>.
+ *
+ * 2007-2009 (c) Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/io.h>
+
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#define DRIVER_NAME "xilinx_emaclite"
+
+/* Register offsets for the EmacLite Core */
+#define XEL_TXBUFF_OFFSET 	0x0		/* Transmit Buffer */
+#define XEL_GIER_OFFSET		0x07F8		/* GIE Register */
+#define XEL_TSR_OFFSET		0x07FC		/* Tx status */
+#define XEL_TPLR_OFFSET		0x07F4		/* Tx packet length */
+
+#define XEL_RXBUFF_OFFSET	0x1000		/* Receive Buffer */
+#define XEL_RPLR_OFFSET		0x100C		/* Rx packet length */
+#define XEL_RSR_OFFSET		0x17FC		/* Rx status */
+
+#define XEL_BUFFER_OFFSET	0x0800		/* Next Tx/Rx buffer's offset */
+
+/* Global Interrupt Enable Register (GIER) Bit Masks */
+#define XEL_GIER_GIE_MASK	0x80000000 	/* Global Enable */
+
+/* Transmit Status Register (TSR) Bit Masks */
+#define XEL_TSR_XMIT_BUSY_MASK	 0x00000001 	/* Tx complete */
+#define XEL_TSR_PROGRAM_MASK	 0x00000002 	/* Program the MAC address */
+#define XEL_TSR_XMIT_IE_MASK	 0x00000008 	/* Tx interrupt enable bit */
+#define XEL_TSR_XMIT_ACTIVE_MASK 0x80000000 	/* Buffer is active, SW bit
+						 * only. This is not documented
+						 * in the HW spec */
+
+/* Define for programming the MAC address into the EmacLite */
+#define XEL_TSR_PROG_MAC_ADDR	(XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_PROGRAM_MASK)
+
+/* Receive Status Register (RSR) */
+#define XEL_RSR_RECV_DONE_MASK	0x00000001 	/* Rx complete */
+#define XEL_RSR_RECV_IE_MASK	0x00000008 	/* Rx interrupt enable bit */
+
+/* Transmit Packet Length Register (TPLR) */
+#define XEL_TPLR_LENGTH_MASK	0x0000FFFF 	/* Tx packet length */
+
+/* Receive Packet Length Register (RPLR) */
+#define XEL_RPLR_LENGTH_MASK	0x0000FFFF 	/* Rx packet length */
+
+#define XEL_HEADER_OFFSET	12 		/* Offset to length field */
+#define XEL_HEADER_SHIFT	16 		/* Shift value for length */
+
+/* General Ethernet Definitions */
+#define XEL_ARP_PACKET_SIZE		28 	/* Max ARP packet size */
+#define XEL_HEADER_IP_LENGTH_OFFSET	16 	/* IP Length Offset */
+
+
+
+#define TX_TIMEOUT		(60*HZ)		/* Tx timeout is 60 seconds. */
+#define ALIGNMENT		4
+
+/* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */
+#define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT)
+
+/**
+ * struct net_local - Our private per device data
+ * @ndev:		instance of the network device
+ * @tx_ping_pong:	indicates whether Tx Pong buffer is configured in HW
+ * @rx_ping_pong:	indicates whether Rx Pong buffer is configured in HW
+ * @next_tx_buf_to_use:	next Tx buffer to write to
+ * @next_rx_buf_to_use:	next Rx buffer to read from
+ * @base_addr:		base address of the Emaclite device
+ * @reset_lock:		lock used for synchronization
+ * @deferred_skb:	holds an skb (for transmission at a later time) when the
+ *			Tx buffer is not free
+ */
+struct net_local {
+
+	struct net_device *ndev;
+
+	bool tx_ping_pong;
+	bool rx_ping_pong;
+	u32 next_tx_buf_to_use;
+	u32 next_rx_buf_to_use;
+	void __iomem *base_addr;
+
+	spinlock_t reset_lock;
+	struct sk_buff *deferred_skb;
+};
+
+
+/*************************/
+/* EmacLite driver calls */
+/*************************/
+
+/**
+ * xemaclite_enable_interrupts - Enable the interrupts for the EmacLite device
+ * @drvdata:	Pointer to the Emaclite device private data
+ *
+ * This function enables the Tx and Rx interrupts for the Emaclite device along
+ * with the Global Interrupt Enable.
+ */
+static void xemaclite_enable_interrupts(struct net_local *drvdata)
+{
+	u32 reg_data;
+
+	/* Enable the Tx interrupts for the first Buffer */
+	reg_data = in_be32(drvdata->base_addr + XEL_TSR_OFFSET);
+	out_be32(drvdata->base_addr + XEL_TSR_OFFSET,
+		 reg_data | XEL_TSR_XMIT_IE_MASK);
+
+	/* Enable the Tx interrupts for the second Buffer if
+	 * configured in HW */
+	if (drvdata->tx_ping_pong != 0) {
+		reg_data = in_be32(drvdata->base_addr +
+				   XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
+		out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
+			 XEL_TSR_OFFSET,
+			 reg_data | XEL_TSR_XMIT_IE_MASK);
+	}
+
+	/* Enable the Rx interrupts for the first buffer */
+	reg_data = in_be32(drvdata->base_addr + XEL_RSR_OFFSET);
+	out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
+		 reg_data | XEL_RSR_RECV_IE_MASK);
+
+	/* Enable the Rx interrupts for the second Buffer if
+	 * configured in HW */
+	if (drvdata->rx_ping_pong != 0) {
+		reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
+				   XEL_RSR_OFFSET);
+		out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
+			 XEL_RSR_OFFSET,
+			 reg_data | XEL_RSR_RECV_IE_MASK);
+	}
+
+	/* Enable the Global Interrupt Enable */
+	out_be32(drvdata->base_addr + XEL_GIER_OFFSET, XEL_GIER_GIE_MASK);
+}
+
+/**
+ * xemaclite_disable_interrupts - Disable the interrupts for the EmacLite device
+ * @drvdata:	Pointer to the Emaclite device private data
+ *
+ * This function disables the Tx and Rx interrupts for the Emaclite device,
+ * along with the Global Interrupt Enable.
+ */
+static void xemaclite_disable_interrupts(struct net_local *drvdata)
+{
+	u32 reg_data;
+
+	/* Disable the Global Interrupt Enable */
+	out_be32(drvdata->base_addr + XEL_GIER_OFFSET, XEL_GIER_GIE_MASK);
+
+	/* Disable the Tx interrupts for the first buffer */
+	reg_data = in_be32(drvdata->base_addr + XEL_TSR_OFFSET);
+	out_be32(drvdata->base_addr + XEL_TSR_OFFSET,
+		 reg_data & (~XEL_TSR_XMIT_IE_MASK));
+
+	/* Disable the Tx interrupts for the second Buffer
+	 * if configured in HW */
+	if (drvdata->tx_ping_pong != 0) {
+		reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
+				   XEL_TSR_OFFSET);
+		out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
+			 XEL_TSR_OFFSET,
+			 reg_data & (~XEL_TSR_XMIT_IE_MASK));
+	}
+
+	/* Disable the Rx interrupts for the first buffer */
+	reg_data = in_be32(drvdata->base_addr + XEL_RSR_OFFSET);
+	out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
+		 reg_data & (~XEL_RSR_RECV_IE_MASK));
+
+	/* Disable the Rx interrupts for the second buffer
+	 * if configured in HW */
+	if (drvdata->rx_ping_pong != 0) {
+
+		reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
+				   XEL_RSR_OFFSET);
+		out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
+			 XEL_RSR_OFFSET,
+			 reg_data & (~XEL_RSR_RECV_IE_MASK));
+	}
+}
+
+/**
+ * xemaclite_aligned_write - Write from 16-bit aligned to 32-bit aligned address
+ * @src_ptr:	Void pointer to the 16-bit aligned source address
+ * @dest_ptr:	Pointer to the 32-bit aligned destination address
+ * @length:	Number bytes to write from source to destination
+ *
+ * This function writes data from a 16-bit aligned buffer to a 32-bit aligned
+ * address in the EmacLite device.
+ */
+static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
+				    unsigned length)
+{
+	u32 align_buffer;
+	u32 *to_u32_ptr;
+	u16 *from_u16_ptr, *to_u16_ptr;
+
+	to_u32_ptr = dest_ptr;
+	from_u16_ptr = (u16 *) src_ptr;
+	align_buffer = 0;
+
+	for (; length > 3; length -= 4) {
+		to_u16_ptr = (u16 *) ((void *) &align_buffer);
+		*to_u16_ptr++ = *from_u16_ptr++;
+		*to_u16_ptr++ = *from_u16_ptr++;
+
+		/* Output a word */
+		*to_u32_ptr++ = align_buffer;
+	}
+	if (length) {
+		u8 *from_u8_ptr, *to_u8_ptr;
+
+		/* Set up to output the remaining data */
+		align_buffer = 0;
+		to_u8_ptr = (u8 *) &align_buffer;
+		from_u8_ptr = (u8 *) from_u16_ptr;
+
+		/* Output the remaining data */
+		for (; length > 0; length--)
+			*to_u8_ptr++ = *from_u8_ptr++;
+
+		*to_u32_ptr = align_buffer;
+	}
+}
+
+/**
+ * xemaclite_aligned_read - Read from 32-bit aligned to 16-bit aligned buffer
+ * @src_ptr:	Pointer to the 32-bit aligned source address
+ * @dest_ptr:	Pointer to the 16-bit aligned destination address
+ * @length:	Number bytes to read from source to destination
+ *
+ * This function reads data from a 32-bit aligned address in the EmacLite device
+ * to a 16-bit aligned buffer.
+ */
+static void xemaclite_aligned_read(u32 *src_ptr, u8 *dest_ptr,
+				   unsigned length)
+{
+	u16 *to_u16_ptr, *from_u16_ptr;
+	u32 *from_u32_ptr;
+	u32 align_buffer;
+
+	from_u32_ptr = src_ptr;
+	to_u16_ptr = (u16 *) dest_ptr;
+
+	for (; length > 3; length -= 4) {
+		/* Copy each word into the temporary buffer */
+		align_buffer = *from_u32_ptr++;
+		from_u16_ptr = (u16 *)&align_buffer;
+
+		/* Read data from source */
+		*to_u16_ptr++ = *from_u16_ptr++;
+		*to_u16_ptr++ = *from_u16_ptr++;
+	}
+
+	if (length) {
+		u8 *to_u8_ptr, *from_u8_ptr;
+
+		/* Set up to read the remaining data */
+		to_u8_ptr = (u8 *) to_u16_ptr;
+		align_buffer = *from_u32_ptr++;
+		from_u8_ptr = (u8 *) &align_buffer;
+
+		/* Read the remaining data */
+		for (; length > 0; length--)
+			*to_u8_ptr = *from_u8_ptr;
+	}
+}
+
+/**
+ * xemaclite_send_data - Send an Ethernet frame
+ * @drvdata:	Pointer to the Emaclite device private data
+ * @data:	Pointer to the data to be sent
+ * @byte_count:	Total frame size, including header
+ *
+ * This function checks if the Tx buffer of the Emaclite device is free to send
+ * data. If so, it fills the Tx buffer with data for transmission. Otherwise, it
+ * returns an error.
+ *
+ * Return:	0 upon success or -1 if the buffer(s) are full.
+ *
+ * Note:	The maximum Tx packet size can not be more than Ethernet header
+ *		(14 Bytes) + Maximum MTU (1500 bytes). This is excluding FCS.
+ */
+static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
+			       unsigned int byte_count)
+{
+	u32 reg_data;
+	void __iomem *addr;
+
+	/* Determine the expected Tx buffer address */
+	addr = drvdata->base_addr + drvdata->next_tx_buf_to_use;
+
+	/* If the length is too large, truncate it */
+	if (byte_count > ETH_FRAME_LEN)
+		byte_count = ETH_FRAME_LEN;
+
+	/* Check if the expected buffer is available */
+	reg_data = in_be32(addr + XEL_TSR_OFFSET);
+	if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
+	     XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
+
+		/* Switch to next buffer if configured */
+		if (drvdata->tx_ping_pong != 0)
+			drvdata->next_tx_buf_to_use ^= XEL_BUFFER_OFFSET;
+	} else if (drvdata->tx_ping_pong != 0) {
+		/* If the expected buffer is full, try the other buffer,
+		 * if it is configured in HW */
+
+		addr = (void __iomem __force *)((u32 __force)addr ^
+						 XEL_BUFFER_OFFSET);
+		reg_data = in_be32(addr + XEL_TSR_OFFSET);
+
+		if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
+		     XEL_TSR_XMIT_ACTIVE_MASK)) != 0)
+			return -1; /* Buffers were full, return failure */
+	} else
+		return -1; /* Buffer was full, return failure */
+
+	/* Write the frame to the buffer */
+	xemaclite_aligned_write(data, (u32 __force *) addr, byte_count);
+
+	out_be32(addr + XEL_TPLR_OFFSET, (byte_count & XEL_TPLR_LENGTH_MASK));
+
+	/* Update the Tx Status Register to indicate that there is a
+	 * frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which
+	 * is used by the interrupt handler to check whether a frame
+	 * has been transmitted */
+	reg_data = in_be32(addr + XEL_TSR_OFFSET);
+	reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK);
+	out_be32(addr + XEL_TSR_OFFSET, reg_data);
+
+	return 0;
+}
+
+/**
+ * xemaclite_recv_data - Receive a frame
+ * @drvdata:	Pointer to the Emaclite device private data
+ * @data:	Address where the data is to be received
+ *
+ * This function is intended to be called from the interrupt context or
+ * with a wrapper which waits for the receive frame to be available.
+ *
+ * Return:	Total number of bytes received
+ */
+static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
+{
+	void __iomem *addr;
+	u16 length, proto_type;
+	u32 reg_data;
+
+	/* Determine the expected buffer address */
+	addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use);
+
+	/* Verify which buffer has valid data */
+	reg_data = in_be32(addr + XEL_RSR_OFFSET);
+
+	if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
+		if (drvdata->rx_ping_pong != 0)
+			drvdata->next_rx_buf_to_use ^= XEL_BUFFER_OFFSET;
+	} else {
+		/* The instance is out of sync, try other buffer if other
+		 * buffer is configured, return 0 otherwise. If the instance is
+		 * out of sync, do not update the 'next_rx_buf_to_use' since it
+		 * will correct on subsequent calls */
+		if (drvdata->rx_ping_pong != 0)
+			addr = (void __iomem __force *)((u32 __force)addr ^
+							 XEL_BUFFER_OFFSET);
+		else
+			return 0;	/* No data was available */
+
+		/* Verify that buffer has valid data */
+		reg_data = in_be32(addr + XEL_RSR_OFFSET);
+		if ((reg_data & XEL_RSR_RECV_DONE_MASK) !=
+		     XEL_RSR_RECV_DONE_MASK)
+			return 0;	/* No data was available */
+	}
+
+	/* Get the protocol type of the ethernet frame that arrived */
+	proto_type = ((in_be32(addr + XEL_HEADER_OFFSET +
+			XEL_RXBUFF_OFFSET) >> XEL_HEADER_SHIFT) &
+			XEL_RPLR_LENGTH_MASK);
+
+	/* Check if received ethernet frame is a raw ethernet frame
+	 * or an IP packet or an ARP packet */
+	if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
+
+		if (proto_type == ETH_P_IP) {
+			length = ((in_be32(addr +
+					XEL_HEADER_IP_LENGTH_OFFSET +
+					XEL_RXBUFF_OFFSET) >>
+					XEL_HEADER_SHIFT) &
+					XEL_RPLR_LENGTH_MASK);
+			length += ETH_HLEN + ETH_FCS_LEN;
+
+		} else if (proto_type == ETH_P_ARP)
+			length = XEL_ARP_PACKET_SIZE + ETH_HLEN + ETH_FCS_LEN;
+		else
+			/* Field contains type other than IP or ARP, use max
+			 * frame size and let user parse it */
+			length = ETH_FRAME_LEN + ETH_FCS_LEN;
+	} else
+		/* Use the length in the frame, plus the header and trailer */
+		length = proto_type + ETH_HLEN + ETH_FCS_LEN;
+
+	/* Read from the EmacLite device */
+	xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET),
+				data, length);
+
+	/* Acknowledge the frame */
+	reg_data = in_be32(addr + XEL_RSR_OFFSET);
+	reg_data &= ~XEL_RSR_RECV_DONE_MASK;
+	out_be32(addr + XEL_RSR_OFFSET, reg_data);
+
+	return length;
+}
+
+/**
+ * xemaclite_set_mac_address - Set the MAC address for this device
+ * @drvdata:	Pointer to the Emaclite device private data
+ * @address_ptr:Pointer to the MAC address (MAC address is a 48-bit value)
+ *
+ * Tx must be idle and Rx should be idle for deterministic results.
+ * It is recommended that this function should be called after the
+ * initialization and before transmission of any packets from the device.
+ * The MAC address can be programmed using any of the two transmit
+ * buffers (if configured).
+ */
+static void xemaclite_set_mac_address(struct net_local *drvdata,
+				      u8 *address_ptr)
+{
+	void __iomem *addr;
+	u32 reg_data;
+
+	/* Determine the expected Tx buffer address */
+	addr = drvdata->base_addr + drvdata->next_tx_buf_to_use;
+
+	xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN);
+
+	out_be32(addr + XEL_TPLR_OFFSET, ETH_ALEN);
+
+	/* Update the MAC address in the EmacLite */
+	reg_data = in_be32(addr + XEL_TSR_OFFSET);
+	out_be32(addr + XEL_TSR_OFFSET, reg_data | XEL_TSR_PROG_MAC_ADDR);
+
+	/* Wait for EmacLite to finish with the MAC address update */
+	while ((in_be32(addr + XEL_TSR_OFFSET) &
+		XEL_TSR_PROG_MAC_ADDR) != 0)
+		;
+}
+
+/**
+ * xemaclite_tx_timeout - Callback for Tx Timeout
+ * @dev:	Pointer to the network device
+ *
+ * This function is called when Tx time out occurs for Emaclite device.
+ */
+static void xemaclite_tx_timeout(struct net_device *dev)
+{
+	struct net_local *lp = (struct net_local *) netdev_priv(dev);
+	unsigned long flags;
+
+	dev_err(&lp->ndev->dev, "Exceeded transmit timeout of %lu ms\n",
+		TX_TIMEOUT * 1000UL / HZ);
+
+	dev->stats.tx_errors++;
+
+	/* Reset the device */
+	spin_lock_irqsave(&lp->reset_lock, flags);
+
+	/* Shouldn't really be necessary, but shouldn't hurt */
+	netif_stop_queue(dev);
+
+	xemaclite_disable_interrupts(lp);
+	xemaclite_enable_interrupts(lp);
+
+	if (lp->deferred_skb) {
+		dev_kfree_skb(lp->deferred_skb);
+		lp->deferred_skb = NULL;
+		dev->stats.tx_errors++;
+	}
+
+	/* To exclude tx timeout */
+	dev->trans_start = 0xffffffff - TX_TIMEOUT - TX_TIMEOUT;
+
+	/* We're all ready to go. Start the queue */
+	netif_wake_queue(dev);
+	spin_unlock_irqrestore(&lp->reset_lock, flags);
+}
+
+/**********************/
+/* Interrupt Handlers */
+/**********************/
+
+/**
+ * xemaclite_tx_handler - Interrupt handler for frames sent
+ * @dev:	Pointer to the network device
+ *
+ * This function updates the number of packets transmitted and handles the
+ * deferred skb, if there is one.
+ */
+static void xemaclite_tx_handler(struct net_device *dev)
+{
+	struct net_local *lp = (struct net_local *) netdev_priv(dev);
+
+	dev->stats.tx_packets++;
+	if (lp->deferred_skb) {
+		if (xemaclite_send_data(lp,
+					(u8 *) lp->deferred_skb->data,
+					lp->deferred_skb->len) != 0)
+			return;
+		else {
+			dev->stats.tx_bytes += lp->deferred_skb->len;
+			dev_kfree_skb_irq(lp->deferred_skb);
+			lp->deferred_skb = NULL;
+			dev->trans_start = jiffies;
+			netif_wake_queue(dev);
+		}
+	}
+}
+
+/**
+ * xemaclite_rx_handler- Interrupt handler for frames received
+ * @dev:	Pointer to the network device
+ *
+ * This function allocates memory for a socket buffer, fills it with data
+ * received and hands it over to the TCP/IP stack.
+ */
+static void xemaclite_rx_handler(struct net_device *dev)
+{
+	struct net_local *lp = (struct net_local *) netdev_priv(dev);
+	struct sk_buff *skb;
+	unsigned int align;
+	u32 len;
+
+	len = ETH_FRAME_LEN + ETH_FCS_LEN;
+	skb = dev_alloc_skb(len + ALIGNMENT);
+	if (!skb) {
+		/* Couldn't get memory. */
+		dev->stats.rx_dropped++;
+		dev_err(&lp->ndev->dev, "Could not allocate receive buffer\n");
+		return;
+	}
+
+	/*
+	 * A new skb should have the data halfword aligned, but this code is
+	 * here just in case that isn't true. Calculate how many
+	 * bytes we should reserve to get the data to start on a word
+	 * boundary */
+	align = BUFFER_ALIGN(skb->data);
+	if (align)
+		skb_reserve(skb, align);
+
+	skb_reserve(skb, 2);
+
+	len = xemaclite_recv_data(lp, (u8 *) skb->data);
+
+	if (!len) {
+		dev->stats.rx_errors++;
+		dev_kfree_skb_irq(skb);
+		return;
+	}
+
+	skb_put(skb, len);	/* Tell the skb how much data we got */
+	skb->dev = dev;		/* Fill out required meta-data */
+
+	skb->protocol = eth_type_trans(skb, dev);
+	skb->ip_summed = CHECKSUM_NONE;
+
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += len;
+	dev->last_rx = jiffies;
+
+	netif_rx(skb);		/* Send the packet upstream */
+}
+
+/**
+ * xemaclite_interrupt - Interrupt handler for this driver
+ * @irq:	Irq of the Emaclite device
+ * @dev_id:	Void pointer to the network device instance used as callback
+ *		reference
+ *
+ * This function handles the Tx and Rx interrupts of the EmacLite device.
+ */
+static irqreturn_t xemaclite_interrupt(int irq, void *dev_id)
+{
+	bool tx_complete = 0;
+	struct net_device *dev = dev_id;
+	struct net_local *lp = (struct net_local *) netdev_priv(dev);
+	void __iomem *base_addr = lp->base_addr;
+	u32 tx_status;
+
+	/* Check if there is Rx Data available */
+	if ((in_be32(base_addr + XEL_RSR_OFFSET) & XEL_RSR_RECV_DONE_MASK) ||
+			(in_be32(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
+			 & XEL_RSR_RECV_DONE_MASK))
+
+		xemaclite_rx_handler(dev);
+
+	/* Check if the Transmission for the first buffer is completed */
+	tx_status = in_be32(base_addr + XEL_TSR_OFFSET);
+	if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
+		(tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
+
+		tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
+		out_be32(base_addr + XEL_TSR_OFFSET, tx_status);
+
+		tx_complete = 1;
+	}
+
+	/* Check if the Transmission for the second buffer is completed */
+	tx_status = in_be32(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
+	if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
+		(tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
+
+		tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
+		out_be32(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET,
+			 tx_status);
+
+		tx_complete = 1;
+	}
+
+	/* If there was a Tx interrupt, call the Tx Handler */
+	if (tx_complete != 0)
+		xemaclite_tx_handler(dev);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * xemaclite_open - Open the network device
+ * @dev:	Pointer to the network device
+ *
+ * This function sets the MAC address, requests an IRQ and enables interrupts
+ * for the Emaclite device and starts the Tx queue.
+ */
+static int xemaclite_open(struct net_device *dev)
+{
+	struct net_local *lp = (struct net_local *) netdev_priv(dev);
+	int retval;
+
+	/* Just to be safe, stop the device first */
+	xemaclite_disable_interrupts(lp);
+
+	/* Set the MAC address each time opened */
+	xemaclite_set_mac_address(lp, dev->dev_addr);
+
+	/* Grab the IRQ */
+	retval = request_irq(dev->irq, &xemaclite_interrupt, 0, dev->name, dev);
+	if (retval) {
+		dev_err(&lp->ndev->dev, "Could not allocate interrupt %d\n",
+			dev->irq);
+		return retval;
+	}
+
+	/* Enable Interrupts */
+	xemaclite_enable_interrupts(lp);
+
+	/* We're ready to go */
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+/**
+ * xemaclite_close - Close the network device
+ * @dev:	Pointer to the network device
+ *
+ * This function stops the Tx queue, disables interrupts and frees the IRQ for
+ * the Emaclite device.
+ */
+static int xemaclite_close(struct net_device *dev)
+{
+	struct net_local *lp = (struct net_local *) netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	xemaclite_disable_interrupts(lp);
+	free_irq(dev->irq, dev);
+
+	return 0;
+}
+
+/**
+ * xemaclite_get_stats - Get the stats for the net_device
+ * @dev:	Pointer to the network device
+ *
+ * This function returns the address of the 'net_device_stats' structure for the
+ * given network device. This structure holds usage statistics for the network
+ * device.
+ *
+ * Return:	Pointer to the net_device_stats structure.
+ */
+static struct net_device_stats *xemaclite_get_stats(struct net_device *dev)
+{
+	return &dev->stats;
+}
+
+/**
+ * xemaclite_send - Transmit a frame
+ * @orig_skb:	Pointer to the socket buffer to be transmitted
+ * @dev:	Pointer to the network device
+ *
+ * This function checks if the Tx buffer of the Emaclite device is free to send
+ * data. If so, it fills the Tx buffer with data from socket buffer data,
+ * updates the stats and frees the socket buffer. The Tx completion is signaled
+ * by an interrupt. If the Tx buffer isn't free, then the socket buffer is
+ * deferred and the Tx queue is stopped so that the deferred socket buffer can
+ * be transmitted when the Emaclite device is free to transmit data.
+ *
+ * Return:	0, always.
+ */
+static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev)
+{
+	struct net_local *lp = (struct net_local *) netdev_priv(dev);
+	struct sk_buff *new_skb;
+	unsigned int len;
+	unsigned long flags;
+
+	len = orig_skb->len;
+
+	new_skb = orig_skb;
+
+	spin_lock_irqsave(&lp->reset_lock, flags);
+	if (xemaclite_send_data(lp, (u8 *) new_skb->data, len) != 0) {
+		/* If the Emaclite Tx buffer is busy, stop the Tx queue and
+		 * defer the skb for transmission at a later point when the
+		 * current transmission is complete */
+		netif_stop_queue(dev);
+		lp->deferred_skb = new_skb;
+		spin_unlock_irqrestore(&lp->reset_lock, flags);
+		return 0;
+	}
+	spin_unlock_irqrestore(&lp->reset_lock, flags);
+
+	dev->stats.tx_bytes += len;
+	dev_kfree_skb(new_skb);
+	dev->trans_start = jiffies;
+
+	return 0;
+}
+
+/**
+ * xemaclite_ioctl - Perform IO Control operations on the network device
+ * @dev:	Pointer to the network device
+ * @rq:		Pointer to the interface request structure
+ * @cmd:	IOCTL command
+ *
+ * The only IOCTL operation supported by this function is setting the MAC
+ * address. An error is reported if any other operations are requested.
+ *
+ * Return:	0 to indicate success, or a negative error for failure.
+ */
+static int xemaclite_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct net_local *lp = (struct net_local *) netdev_priv(dev);
+	struct hw_addr_data *hw_addr = (struct hw_addr_data *) &rq->ifr_hwaddr;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return -EIO;
+
+	case SIOCSIFHWADDR:
+		dev_err(&lp->ndev->dev, "SIOCSIFHWADDR\n");
+
+		/* Copy MAC address in from user space */
+		copy_from_user((void __force *) dev->dev_addr,
+			       (void __user __force *) hw_addr,
+			       IFHWADDRLEN);
+		xemaclite_set_mac_address(lp, dev->dev_addr);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+/**
+ * xemaclite_remove_ndev - Free the network device
+ * @ndev:	Pointer to the network device to be freed
+ *
+ * This function un maps the IO region of the Emaclite device and frees the net
+ * device.
+ */
+static void xemaclite_remove_ndev(struct net_device *ndev)
+{
+	if (ndev) {
+		struct net_local *lp = (struct net_local *) netdev_priv(ndev);
+
+		if (lp->base_addr)
+			iounmap((void __iomem __force *) (lp->base_addr));
+		free_netdev(ndev);
+	}
+}
+
+/**
+ * get_bool - Get a parameter from the OF device
+ * @ofdev:	Pointer to OF device structure
+ * @s:		Property to be retrieved
+ *
+ * This function looks for a property in the device node and returns the value
+ * of the property if its found or 0 if the property is not found.
+ *
+ * Return:	Value of the parameter if the parameter is found, or 0 otherwise
+ */
+static bool get_bool(struct of_device *ofdev, const char *s)
+{
+	u32 *p = (u32 *)of_get_property(ofdev->node, s, NULL);
+
+	if (p) {
+		return (bool)*p;
+	} else {
+		dev_warn(&ofdev->dev, "Parameter %s not found,"
+			"defaulting to false\n", s);
+		return 0;
+	}
+}
+
+static struct net_device_ops xemaclite_netdev_ops;
+
+/**
+ * xemaclite_of_probe - Probe method for the Emaclite device.
+ * @ofdev:	Pointer to OF device structure
+ * @match:	Pointer to the structure used for matching a device
+ *
+ * This function probes for the Emaclite device in the device tree.
+ * It initializes the driver data structure and the hardware, sets the MAC
+ * address and registers the network device.
+ *
+ * Return:	0, if the driver is bound to the Emaclite device, or
+ *		a negative error if there is failure.
+ */
+static int __devinit xemaclite_of_probe(struct of_device *ofdev,
+					const struct of_device_id *match)
+{
+	struct resource r_irq; /* Interrupt resources */
+	struct resource r_mem; /* IO mem resources */
+	struct net_device *ndev = NULL;
+	struct net_local *lp = NULL;
+	struct device *dev = &ofdev->dev;
+	const void *mac_address;
+
+	int rc = 0;
+
+	dev_info(dev, "Device Tree Probing\n");
+
+	/* Get iospace for the device */
+	rc = of_address_to_resource(ofdev->node, 0, &r_mem);
+	if (rc) {
+		dev_err(dev, "invalid address\n");
+		return rc;
+	}
+
+	/* Get IRQ for the device */
+	rc = of_irq_to_resource(ofdev->node, 0, &r_irq);
+	if (rc == NO_IRQ) {
+		dev_err(dev, "no IRQ found\n");
+		return rc;
+	}
+
+	/* Create an ethernet device instance */
+	ndev = alloc_etherdev(sizeof(struct net_local));
+	if (!ndev) {
+		dev_err(dev, "Could not allocate network device\n");
+		return -ENOMEM;
+	}
+
+	dev_set_drvdata(dev, ndev);
+
+	ndev->irq = r_irq.start;
+	ndev->mem_start = r_mem.start;
+	ndev->mem_end = r_mem.end;
+
+	lp = netdev_priv(ndev);
+	lp->ndev = ndev;
+
+	if (!request_mem_region(ndev->mem_start,
+				ndev->mem_end - ndev->mem_start + 1,
+				DRIVER_NAME)) {
+		dev_err(dev, "Couldn't lock memory region at %p\n",
+			(void *)ndev->mem_start);
+		rc = -EBUSY;
+		goto error2;
+	}
+
+	/* Get the virtual base address for the device */
+	lp->base_addr = ioremap(r_mem.start, r_mem.end - r_mem.start + 1);
+	if (NULL == lp->base_addr) {
+		dev_err(dev, "EmacLite: Could not allocate iomem\n");
+		rc = -EIO;
+		goto error1;
+	}
+
+	spin_lock_init(&lp->reset_lock);
+	lp->next_tx_buf_to_use = 0x0;
+	lp->next_rx_buf_to_use = 0x0;
+	lp->tx_ping_pong = get_bool(ofdev, "xlnx,tx-ping-pong");
+	lp->rx_ping_pong = get_bool(ofdev, "xlnx,rx-ping-pong");
+	mac_address = of_get_mac_address(ofdev->node);
+
+	if (mac_address)
+		/* Set the MAC address. */
+		memcpy(ndev->dev_addr, mac_address, 6);
+	else
+		dev_warn(dev, "No MAC address found\n");
+
+	/* Clear the Tx CSR's in case this is a restart */
+	out_be32(lp->base_addr + XEL_TSR_OFFSET, 0);
+	out_be32(lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, 0);
+
+	/* Set the MAC address in the EmacLite device */
+	xemaclite_set_mac_address(lp, ndev->dev_addr);
+
+	dev_info(dev,
+		 "MAC address is now %2x:%2x:%2x:%2x:%2x:%2x\n",
+		 ndev->dev_addr[0], ndev->dev_addr[1],
+		 ndev->dev_addr[2], ndev->dev_addr[3],
+		 ndev->dev_addr[4], ndev->dev_addr[5]);
+
+	ndev->netdev_ops = &xemaclite_netdev_ops;
+	ndev->flags &= ~IFF_MULTICAST;
+	ndev->watchdog_timeo = TX_TIMEOUT;
+
+	/* Finally, register the device */
+	rc = register_netdev(ndev);
+	if (rc) {
+		dev_err(dev,
+			"Cannot register network device, aborting\n");
+		goto error1;
+	}
+
+	dev_info(dev,
+		 "Xilinx EmacLite at 0x%08X mapped to 0x%08X, irq=%d\n",
+		 (unsigned int __force)ndev->mem_start,
+		 (unsigned int __force)lp->base_addr, ndev->irq);
+	return 0;
+
+error1:
+	release_mem_region(ndev->mem_start, r_mem.end - r_mem.start + 1);
+
+error2:
+	xemaclite_remove_ndev(ndev);
+	return rc;
+}
+
+/**
+ * xemaclite_of_remove - Unbind the driver from the Emaclite device.
+ * @of_dev:	Pointer to OF device structure
+ *
+ * This function is called if a device is physically removed from the system or
+ * if the driver module is being unloaded. It frees any resources allocated to
+ * the device.
+ *
+ * Return:	0, always.
+ */
+static int __devexit xemaclite_of_remove(struct of_device *of_dev)
+{
+	struct device *dev = &of_dev->dev;
+	struct net_device *ndev = dev_get_drvdata(dev);
+
+	unregister_netdev(ndev);
+
+	release_mem_region(ndev->mem_start, ndev->mem_end-ndev->mem_start + 1);
+
+	xemaclite_remove_ndev(ndev);
+
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+static struct net_device_ops xemaclite_netdev_ops = {
+	.ndo_open		= xemaclite_open,
+	.ndo_stop		= xemaclite_close,
+	.ndo_start_xmit		= xemaclite_send,
+	.ndo_do_ioctl		= xemaclite_ioctl,
+	.ndo_tx_timeout		= xemaclite_tx_timeout,
+	.ndo_get_stats		= xemaclite_get_stats,
+};
+
+/* Match table for OF platform binding */
+static struct of_device_id xemaclite_of_match[] __devinitdata = {
+	{ .compatible = "xlnx,opb-ethernetlite-1.01.a", },
+	{ .compatible = "xlnx,opb-ethernetlite-1.01.b", },
+	{ .compatible = "xlnx,xps-ethernetlite-1.00.a", },
+	{ .compatible = "xlnx,xps-ethernetlite-2.00.a", },
+	{ .compatible = "xlnx,xps-ethernetlite-2.01.a", },
+	{ /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, xemaclite_of_match);
+
+static struct of_platform_driver xemaclite_of_driver = {
+	.name		= DRIVER_NAME,
+	.match_table	= xemaclite_of_match,
+	.probe		= xemaclite_of_probe,
+	.remove		= __devexit_p(xemaclite_of_remove),
+};
+
+/**
+ * xgpiopss_init - Initial driver registration call
+ *
+ * Return:	0 upon success, or a negative error upon failure.
+ */
+static int __init xemaclite_init(void)
+{
+	/* No kernel boot options used, we just need to register the driver */
+	return of_register_platform_driver(&xemaclite_of_driver);
+}
+
+/**
+ * xemaclite_cleanup - Driver un-registration call
+ */
+static void __exit xemaclite_cleanup(void)
+{
+	of_unregister_platform_driver(&xemaclite_of_driver);
+}
+
+module_init(xemaclite_init);
+module_exit(xemaclite_cleanup);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx Ethernet MAC Lite driver");
+MODULE_LICENSE("GPL");
-- 
1.6.2.1



This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.



^ permalink raw reply related

* RE: [PATCH] [V2] net: add Xilinx emac lite device driver
From: John Linn @ 2009-08-20  9:32 UTC (permalink / raw)
  To: David Miller, michal.simek
  Cc: netdev, linuxppc-dev, jgarzik, grant.likely, jwboyer,
	john.williams, Sadanand Mutyala
In-Reply-To: <20090820.023047.86718643.davem@davemloft.net>

> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Thursday, August 20, 2009 10:31 AM
> To: michal.simek@petalogix.com
> Cc: John Linn; netdev@vger.kernel.org; linuxppc-dev@ozlabs.org;
jgarzik@pobox.com;
> grant.likely@secretlab.ca; jwboyer@linux.vnet.ibm.com;
john.williams@petalogix.com; Sadanand Mutyala
> Subject: Re: [PATCH] [V2] net: add Xilinx emac lite device driver
> 
> From: Michal Simek <michal.simek@petalogix.com>
> Date: Thu, 20 Aug 2009 11:28:48 +0200
> 
> > There were one bug with spinlock which John L fixed but not send to
> > mainling list. :-(
> > He wanted to create new v3 version. :-(.
> > When he wake up, he send you that bug fix or v3 version with it.
> 
> Send a new version, I'll revert V2 from my tree as I didn't push it
> out yet.

I'll send a V3 version very soon, thanks. 

Sorry for the hassle as I thought there would be more comments and I'd
incorporate the bug fix into those.

Appreciate your help.

-- John

This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.



^ permalink raw reply

* [PATCH -next] cdc_ether: additional PID's to the whitelist
From: Torgny Johansson @ 2009-08-20  9:16 UTC (permalink / raw)
  To: david-b; +Cc: netdev

This patch adds seven PID's to the whitelist set of devices.

Devices added to the whitelist:

Ericsson Mobile Broadband Module variants (F3607gw and F3307)
Dell F3607gw variants
Toshiba F3607gw variants

Signed-off-by: Torgny Johansson <torgny.johansson@ericsson.com>

diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index c47237c..32d9356 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -174,7 +174,7 @@ config USB_NET_CDCETHER
 	    * Ericsson Mobile Broadband Module (all variants)
  	    * Motorola (DM100 and SB4100)
  	    * Broadcom Cable Modem (reference design)
-	    * Toshiba (PCX1100U and F3507g)
+	    * Toshiba (PCX1100U and F3507g/F3607gw)
 	    * ...
 
 	  This driver creates an interface named "ethX", where X depends on
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 4a6aff5..5d99106 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -544,20 +544,55 @@ static const struct usb_device_id	products [] = {
 			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
 	.driver_info = (unsigned long) &cdc_info,
 }, {
-	/* Ericsson F3307 */
+	/* Ericsson F3607gw ver 2 */
+	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1905, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
+}, {
+	/* Ericsson F3607gw ver 3 */
 	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1906, USB_CLASS_COMM,
 			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
 	.driver_info = (unsigned long) &cdc_info,
 }, {
+	/* Ericsson F3307 */
+	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x190a, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
+}, {
+	/* Ericsson F3307 ver 2 */
+	USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1909, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
+}, {
 	/* Toshiba F3507g */
 	USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130b, USB_CLASS_COMM,
 			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
 	.driver_info = (unsigned long) &cdc_info,
 }, {
+	/* Toshiba F3607gw */
+	USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130c, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
+}, {
+	/* Toshiba F3607gw ver 2 */
+	USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x1311, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
+}, {
 	/* Dell F3507g */
 	USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8147, USB_CLASS_COMM,
 			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
 	.driver_info = (unsigned long) &cdc_info,
+}, {
+	/* Dell F3607gw */
+	USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8183, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
+}, {
+	/* Dell F3607gw ver 2 */
+	USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8184, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &cdc_info,
 },
 	{ },		// END
 };



^ permalink raw reply related

* Re: [PATCH] [V2] net: add Xilinx emac lite device driver
From: David Miller @ 2009-08-20  9:30 UTC (permalink / raw)
  To: michal.simek
  Cc: john.linn, netdev, linuxppc-dev, jgarzik, grant.likely, jwboyer,
	john.williams, sadanan
In-Reply-To: <4A8D1750.4000804@petalogix.com>

From: Michal Simek <michal.simek@petalogix.com>
Date: Thu, 20 Aug 2009 11:28:48 +0200

> There were one bug with spinlock which John L fixed but not send to
> mainling list. :-(
> He wanted to create new v3 version. :-(.
> When he wake up, he send you that bug fix or v3 version with it.

Send a new version, I'll revert V2 from my tree as I didn't push it
out yet.

^ permalink raw reply

* Re: [PATCH] [V2] net: add Xilinx emac lite device driver
From: Michal Simek @ 2009-08-20  9:28 UTC (permalink / raw)
  To: David Miller
  Cc: john.linn, netdev, linuxppc-dev, jgarzik, grant.likely, jwboyer,
	john.williams, sadanan
In-Reply-To: <20090820.022536.264747725.davem@davemloft.net>

David Miller wrote:
> From: John Linn <john.linn@xilinx.com>
> Date: Wed, 19 Aug 2009 06:29:11 -0600
>
>   
>> This patch adds support for the Xilinx Ethernet Lite device.  The
>> soft logic core from Xilinx is typically used on Virtex and Spartan
>> designs attached to either a PowerPC or a Microblaze processor.
>>
>> Signed-off-by: Sadanand M <sadanan@xilinx.com>
>> Signed-off-by: John Linn <john.linn@xilinx.com>
>>     
>
> Looks good, applied to net-next-2.6, thanks!
>   
There were one bug with spinlock which John L fixed but not send to
mainling list. :-(
He wanted to create new v3 version. :-(.
When he wake up, he send you that bug fix or v3 version with it.

Regards,
Michal


-- 
Michal Simek, Ing. (M.Eng)
PetaLogix - Linux Solutions for a Reconfigurable World
w: www.petalogix.com p: +61-7-30090663,+42-0-721842854 f: +61-7-30090663


^ permalink raw reply

* Re: [PATCH] [V2] net: add Xilinx emac lite device driver
From: David Miller @ 2009-08-20  9:25 UTC (permalink / raw)
  To: john.linn
  Cc: netdev, linuxppc-dev, jgarzik, grant.likely, jwboyer,
	john.williams, michal.simek, sadanan
In-Reply-To: <20090819122920.37EE21728051@mail110-dub.bigfish.com>

From: John Linn <john.linn@xilinx.com>
Date: Wed, 19 Aug 2009 06:29:11 -0600

> This patch adds support for the Xilinx Ethernet Lite device.  The
> soft logic core from Xilinx is typically used on Virtex and Spartan
> designs attached to either a PowerPC or a Microblaze processor.
> 
> Signed-off-by: Sadanand M <sadanan@xilinx.com>
> Signed-off-by: John Linn <john.linn@xilinx.com>

Looks good, applied to net-next-2.6, thanks!

^ permalink raw reply

* Re: Strange network timeouts w/ 2.6.30.5
From: Krzysztof Halasa @ 2009-08-20  9:22 UTC (permalink / raw)
  To: David Miller; +Cc: walt, linux-kernel, netdev
In-Reply-To: <20090820.021330.151477484.davem@davemloft.net>

David Miller <davem@davemloft.net> writes:

> skb->data is where e100 puts it's descriptors. :-)
>
> But you know that.

Right. I will try to change that soon.
-- 
Krzysztof Halasa

^ permalink raw reply

* Re: [PATCH] ibm_newemac: emac_close() needs to call netif_carrier_off()
From: David Miller @ 2009-08-20  9:21 UTC (permalink / raw)
  To: pgynther; +Cc: benh, netdev
In-Reply-To: <20090819210000.D56AB254211@localhost>

From: Petri Gynther <pgynther@google.com>
Date: Wed, 19 Aug 2009 14:00:00 -0700 (PDT)

> When ibm_newemac netdev instance is shutdown with "ifconfig down",
> the netdev interface does not go properly down. netif_carrier_ok()
> keeps returning TRUE even after "ifconfig down".
> 
> The problem can be seen when ibm_newemac instances are slaves of
> a bonding interface. The bonding interface code uses netif_carrier_ok()
> to determine the link status of its slaves. When ibm_newemac slave is
> shutdown with "ifconfig down", the bonding interface won't detect any
> link status change because netif_carrier_ok() keeps returning TRUE.
> 
> Signed-off-by: Petri Gynther <pgynther@google.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH] ibm_newemac: emac_close() needs to call netif_carrier_off()
From: David Miller @ 2009-08-20  9:20 UTC (permalink / raw)
  To: benh; +Cc: pgynther, shemminger, netdev
In-Reply-To: <1250748142.10937.4.camel@pasglop>

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Thu, 20 Aug 2009 16:02:22 +1000

> On Wed, 2009-08-19 at 15:32 -0700, Petri Gynther wrote:
>> Stephen,
>> 
>> I think your suggestion of adding netif_running() check to
>> bond_check_dev_link() is valid and a good fix to the bonding driver.
>> We can do this in a separate patch.
>> 
>> However, I think that the change to ibm_newemac: emac_close() is
>> needed as well. ibm_newemac netdevs should not return
>> netif_carrier_ok() == TRUE when they have been shut down.
> 
> Well, we definitely don't do that in sungem either, since we continue
> the link polling while the interface is down... IE. interface up/down is
> the data path and is orthogonal to the PHY polling in sungem. I suppose
> we -could- stop the polling while the interface is down, though I think
> my initial implementation did only poll the link while the interface was
> up and that was causing endless problems with various laptop-net style
> tools (however that was years and years ago).

It just shows how few people use sungem with bonding :-)

Short term I'm going to add the ibm_newemac change.

Longer term we should probably add the netif_running() check to
bond_check_dev_link().

^ permalink raw reply

* Re: [net-next PATCH 1/3] qlge: Move TX completion processing to send path.
From: David Miller @ 2009-08-20  9:18 UTC (permalink / raw)
  To: ron.mercer; +Cc: netdev
In-Reply-To: <1250725991-7155-2-git-send-email-ron.mercer@qlogic.com>

From: Ron Mercer <ron.mercer@qlogic.com>
Date: Wed, 19 Aug 2009 16:53:09 -0700

> @@ -1205,6 +1205,7 @@ struct bq_desc {
>  };
>  
>  #define QL_TXQ_IDX(qdev, skb) (smp_processor_id()%(qdev->tx_ring_count))
> +#define TXQ_CLEAN_TIME (HZ/4)
>  
>  struct tx_ring {
>  	/*

Running this every 1/4 of a second, even when no TX activity is
happening, is very bad for power management.

And starting the timer in response to whether there are TX queue
entries active or not will add overhead and races.

This really isn't workable.

I really and truly believe that the best place for this is in NAPI
context.  So bring back the MSI-X vector for TX completions, and
make it schedule a NAPI poll.


^ permalink raw reply

* Re: Very strange issues with ethernet wake on lan
From: Maxim Levitsky @ 2009-08-20  9:16 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: netdev@vger.kernel.org, linux-pm@lists.linux-foundation.org
In-Reply-To: <200908172030.54505.rjw@sisk.pl>

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

On Mon, 2009-08-17 at 20:30 +0200, Rafael J. Wysocki wrote:
> On Monday 17 August 2009, Maxim Levitsky wrote:
> > On Sun, 2009-08-16 at 06:42 +0300, Maxim Levitsky wrote:
> > > Hi,
> > > 
> > > I have recently put back the davicom dm9009 ethernet card into my
> > > computer.
> > > 
> > > Some long time ago, I have written its suspend/resume routines.
> > > Now I see that few things have changed, like I need to enable wake in
> > > sysfs or better patch the code to do so, some nice helpers like
> > > pci_prepare_to_sleep have arrived, etc.
> > > 
> > > 
> > > I narrowed the strange issue down to following situation:
> > > 
> > > I reload dmfe.ko (and networkmanager is disabled)
> > > I don't ifup the device, thus pretty much no hardware initialization
> > > takes place (but this appears not to matter anyway)
> > > 
> > > I then suspend the system, and WOL doesn't work (I have patched the
> > > driver to enable WOL automaticly)
> > > 
> > > I then, suspend again. WOL works, and continues to work as long as I
> > > don't reload the driver. If I do, same situation repeats.
> > > 
> > > Also, after a boot, WOL works, so a reload cycle triggers that issue.
> > > 
> > > And most importantly, if I don't do a
> > > 
> > > pci_set_power_state(pci_dev, pci_choose_state (pci_dev, state));
> > > 
> > > in .suspend, then WOL always works.
> > > 
> > > and I have even tried to set state manually to PCI_D3hot or PCI_D3cold, 
> > > 
> > > I also tried to use pci_save_state
> > > 
> > > 
> > > I also have 2 copies of this card, and both have this issue.
> > > I also tried 2 pci slots.
> > > 
> > > Kernel is vanilla 2.6.31-rc5
> 
> I need a dmesg output containing at least one suspend-resume cycle
> (preferably two cycles, the first one where WoL worked and another one
> where it didn't).


I am really sorry for late reply.

I attach the dmesg.


dmesg1 - after a boot, and dmfe reload
dmesg2 - after first s2ram cycle (wol didn't work)
dmesg3  - after second s2ram cycle (wol did work)
dmesg4 - after third s2ram cycle (wol did work), this is just in case.



Also I attach changes I did to the driver to make it enable wol by
default.


Best regards,
	Maxim Levitsky




[-- Attachment #2: dmesg.tar.bz2 --]
[-- Type: application/x-bzip-compressed-tar, Size: 41750 bytes --]

[-- Attachment #3: dmfe-enable-wol-by-default --]
[-- Type: text/plain, Size: 638 bytes --]

DMFE: enable WOL by default

From: Maxim Levitsky <maximlevitsky@gmail.com>


---

 drivers/net/tulip/dmfe.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)


diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index e26a412..8a54a5b 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -444,7 +444,8 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
 	db->chip_id = ent->driver_data;
 	db->ioaddr = pci_resource_start(pdev, 0);
 	db->chip_revision = pdev->revision;
-	db->wol_mode = 0;
+	db->wol_mode = WAKE_MAGIC;
+	device_set_wakeup_enable(&pdev->dev, 1);
 
 	db->pdev = pdev;
 

^ permalink raw reply related

* Re: Strange network timeouts w/ 2.6.30.5
From: David Miller @ 2009-08-20  9:13 UTC (permalink / raw)
  To: khc; +Cc: walt, linux-kernel, netdev
In-Reply-To: <m3my5ueu2a.fsf@intrepid.localdomain>

From: Krzysztof Halasa <khc@pm.waw.pl>
Date: Thu, 20 Aug 2009 11:03:09 +0200

> The root problem is that the driver shouldn't use streaming allocations
> for its descriptors (they are written from both sides simultaneously).
> Only skb->data can be streaming.

skb->data is where e100 puts it's descriptors. :-)

But you know that.

^ permalink raw reply

* Re: Strange network timeouts w/ 2.6.30.5
From: Krzysztof Halasa @ 2009-08-20  9:03 UTC (permalink / raw)
  To: walt; +Cc: David Miller, linux-kernel, netdev
In-Reply-To: <20090819.211736.222582824.davem@davemloft.net>

> Since patching to 2.6.30.5 I'm experiencing periodic timeouts on my
> e100 which is used as my WAN interface on a server/router box. Nothing
> is reported in any logs and eventually the traffic resumes. It seems
> to happen at fairly regular intervals, although I've not timed them.
> The timeouts last for approx. 60-120 seconds and then traffic resumes
> normally with no hint of what happened.

x86-64, intel P965...

Can you provide "dmesg" output, please?

I wonder what additional side effect did the patch cause. Streaming
allocs on such x86 should already be coherent, no?

Perhaps you have more than 2 GB RAM (or so) and swiotlb has to provide
buffering? I think of something like:

- the driver does "sync for CPU" and examines status
- the descriptor is tested to be still empty
- meanwhile e100 chip changes the status in the descriptor
- the driver does "sync for device" (it's what the patch added)
- at this point swiotlb doesn't know the descriptor is clean and writes
  it out, thus dropping the change done by the e100 chip.

Does the above seem plausible? I admit I'm not swiotlb expert, it's
a pure guess that it simply and blindly moves data in and out.

If that's the case, I don't really know how could it work without the
patch in question. Perhaps the timings were just right?

What can we do with it? Rewriting to use consistent allocs, of course.
Temporarily adding #ifdef CONFIG_ARM around the
pci_dma_sync_single_for_device()? Not sure if other archs were affected.

The root problem is that the driver shouldn't use streaming allocations
for its descriptors (they are written from both sides simultaneously).
Only skb->data can be streaming.
-- 
Krzysztof Halasa

^ permalink raw reply

* Re: [Bugme-new] [Bug 14002] New: WARNING: at net/ipv4/af_inet.c:154 inet_sock_destruct+0x164/0x1c0()
From: Ralf Hildebrandt @ 2009-08-20  8:49 UTC (permalink / raw)
  To: Andrew Morton; +Cc: netdev, bugzilla-daemon, bugme-daemon
In-Reply-To: <20090819142145.b3c9fdc1.akpm@linux-foundation.org>

* Andrew Morton <akpm@linux-foundation.org>:

> > Aug 17 17:03:01 vpn-gw-int kernel: [507970.165477] 172.28.33.133IN=tun0
> > OUT=eth0 SRC=172.28.33.133 DST=141.80.40.193 LEN=67 TOS=0x00 PREC=0x00 TTL=127
> > ID=23900 PROTO=UDP
> > SPT=1026 DPT=53 LEN=47
> 
> Is it reproducible?  Still happening in current mainline?

I updated to 2.6.31-rc6 and haven't (yet) seen it.

-- 
Ralf Hildebrandt
  Geschäftsbereich IT | Abteilung Netzwerk
  Charité - Universitätsmedizin Berlin
  Campus Benjamin Franklin
  Hindenburgdamm 30 | D-12203 Berlin
  Tel. +49 30 450 570 155 | Fax: +49 30 450 570 962
  ralf.hildebrandt@charite.de | http://www.charite.de
	    

^ permalink raw reply

* Re: [PATCHv3 2/2] vhost_net: a kernel-level virtio server
From: Michael S. Tsirkin @ 2009-08-20  8:31 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: virtualization, netdev, kvm, linux-kernel, mingo, linux-mm, akpm,
	hpa, gregory.haskins, Or Gerlitz
In-Reply-To: <200908191727.07681.arnd@arndb.de>

On Wed, Aug 19, 2009 at 05:27:07PM +0200, Arnd Bergmann wrote:
> On Wednesday 19 August 2009, Michael S. Tsirkin wrote:
> > On Wed, Aug 19, 2009 at 03:46:44PM +0200, Arnd Bergmann wrote:
> > > On Wednesday 19 August 2009, Michael S. Tsirkin wrote:
> > >
> > > Leaving that aside for now, you could replace VHOST_NET_SET_SOCKET,
> > > VHOST_SET_OWNER, VHOST_RESET_OWNER
> > 
> > SET/RESET OWNER is still needed: otherwise if you share a descriptor
> > with another process, it can corrupt your memory.
> 
> How? The point of using user threads is that you only ever access the
> address space of the thread that called the ioctl.

Think about this example with processes A and B sharing an fd:
A does SET_USED_ADDRESS
B does SET_USED_ADDRESS
A does VHOST_NET_SPLICE
See how stuff gets written into a random place in memory of A?

> > > and your kernel thread with a new
> > > VHOST_NET_SPLICE blocking ioctl that does all the transfers in the
> > > context of the calling thread.
> > 
> > For one, you'd want a thread per virtqueue.
> 
> Don't understand why. The thread can be blocked on all four ends
> of the device and wake up whenever there is some work do to in
> any direction. If we have data to be transferred in both ways,
> we save one thread switch. It probably won't hurt much to have one
> thread per direction, but I don't see the point.
> > Second, an incoming traffic might arrive on another CPU, we want
> > to keep it local.  I guess you would also want ioctls to wake up
> > the threads spuriously ...
> 
> Outbound traffic should just stay on whatever CPU was sending it
> from the guest. For inbound traffic, we should only wake up
> the thread on the CPU that got the data to start with.

Exactly. Since we have RX and TX virtqueues, this would mean thread per
direction or virtqueue, same thing. OTOH if RX and TX happen to run on the
same CPU, thread switch would be just a waste of time: but userspace
does not know it, only guest and kernel know.

> Why would I wake up the threads spuriously? Do you mean for
> stopping the transmission or something else? I guess a pthread_kill
> would be enough for shutting it down.

If you kill and restart them you lost priority etc parameters, but maybe.

> > > This would improve the driver on various fronts:
> > > 
> > > - no need for playing tricks with use_mm/unuse_mm
> > > - possibly fewer global TLB flushes from switch_mm, which
> > >   may improve performance.
> > 
> > Why would there be less flushes?
> 
> I just read up on task->active_mm handling. There probably wouldn't
> be any. I got that wrong.
> 
> > > - based on that, the ability to use any kind of file
> > >   descriptor that can do writev/readv or sendmsg/recvmsg
> > >   without the nastiness you mentioned.
> > 
> > Yes, it's an interesting approach. As I said, need to tread very
> > carefully though, I don't think all issues are figured out. For example:
> > what happens if we pass our own fd here? Will refcount on file ever get
> > to 0 on exit?  There may be others ...
> 
> right.
> 
> > > The disadvantage of course is that you need to add a user
> > > thread for each guest device to make up for the workqueue
> > > that you save.
> > 
> > More importantly, you lose control of CPU locality.  Simply put, a
> > natural threading model in virtualization is one thread per guest vcpu.
> > Asking applications to add multiple helper threads just so they can
> > block forever is wrong, IMO, as userspace has no idea which CPU
> > they should be on, what priority to use, etc.
> 
> But the kernel also doesn't know this, you get the same problem in
> another way. If you have multiple guests running at different priorities,
> the kernel will use those priorities to do the more important transfers
> first, while with a global workqueue every guest gets the same priority.

We could create more threads if this becomes a problem. I just think it
should be transparent to userspace. Possibly it's useful to look at the
packet header as well to decide on priority: this is something userspace
can't do.

> You say that the natural model is to have one thread per guest
> CPU,

Sorry I was not clear. I think userspace should create thread per guest.
We can create as many as we need for networking but I think this should
be behind the scenes, so userspace shouldn't bother with host CPUs, it
will just get it wrong. Think of CPU hotplug, interrupts migrating
between CPUs, etc ...

> but you have a thread per host CPU instead. If the numbers
> are different, you probably lose either way.

The trick I used is to keep as much as possible local
TX done on the CPU that runs the guest,
RX done on the CPU that runs the NIC interrupt.
a smart SMP guest sees which cpu gets interrupts
from NIC and schedules RX there, and it shouldn't matter
if the numbers of CPUs are different.

> It gets worse if you try to apply NUMA policies.

I believe the best we could do is avoid switching CPUs
until we know the actual destination.

> > > > > to
> > > > > avoid some of the implications of kernel threads like the missing
> > > > > ability to handle transfer errors in user space.
> > > > 
> > > > Are you talking about TCP here?
> > > > Transfer errors are typically asynchronous - possibly eventfd
> > > > as I expose for vhost net is sufficient there.
> > > 
> > > I mean errors in general if we allow random file descriptors to be used.
> > > E.g. tun_chr_aio_read could return EBADFD, EINVAL, EFAULT, ERESTARTSYS,
> > > EIO, EAGAIN and possibly others. We can handle some in kernel, others
> > > should never happen with vhost_net, but if something unexpected happens
> > > it would be nice to just bail out to user space.
> > 
> > And note that there might be more than one error.  I guess, that's
> > another problem with trying to layer on top of vfs.
> 
> Why is that different from any other system call?

With other system calls nothing happens while you process the error.
Here, the guest (other queues) and the network keep running (unless
there is a thread per queue, maybe we can block a queue, but we both
agreed above we don't want that).

> We just return when
> we hit the first error condition.
> 
> 	Arnd <><

If you assume losing the code for the second error condition is OK, why
is the first one so important?  That's why I used a counter (eventfd)
per virtqueue, on error userspace can scan the ring and poll the socket
and discover what's wrong, and counter ensures we can detect that error
happened while we were not looking.

-- 
MST

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ 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