Netdev List
 help / color / mirror / Atom feed
* [PATCH 1/7] o80211s: Export dev_seq_{start,stop,next} symbols.
From: Luis Carlos Cobo @ 2007-10-29 21:44 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA

This is the first patch of a series starting mesh wireless support (802.11s) for
wireless network cards with drivers using the mac80211 stack.

It is still in an early stage of development but some functionality (static
forwarding) is quite solid and we would like the code to be integrated in the
kernel the sooner the better. Please point out any section of the code that
could pose a problem towards integration. The patches apply against current
wireless-2.6/everything.

For more information, please visit: http://o11s.org/devel

This patches are being sent just to linux-wireless mailing list. I'm just
sending this one patch also to netdev since it is not wireless specific.

Signed-off-by: Luis Carlos Cobo <luisca-W/OLz77bvjtBDgjK7y7TUQ@public.gmane.org>
---
 net/core/dev.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 8726589..9c005f2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2348,6 +2348,7 @@ void *dev_seq_start(struct seq_file *seq, loff_t *pos)
 
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(dev_seq_start);
 
 void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
@@ -2356,11 +2357,13 @@ void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 	return v == SEQ_START_TOKEN ?
 		first_net_device(net) : next_net_device((struct net_device *)v);
 }
+EXPORT_SYMBOL_GPL(dev_seq_next);
 
 void dev_seq_stop(struct seq_file *seq, void *v)
 {
 	read_unlock(&dev_base_lock);
 }
+EXPORT_SYMBOL_GPL(dev_seq_stop);
 
 static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
 {
-- 
1.5.2.5

^ permalink raw reply related

* Re: [bug, 2.6.24-rc1] sysfs: duplicate filename 'eth0' can not be created
From: Ingo Molnar @ 2007-10-29 21:48 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: linux-kernel, netdev, David S. Miller, Jeff Garzik
In-Reply-To: <20071029144016.06c03b7c@freepuppy.rosehill>


* Stephen Hemminger <shemminger@linux-foundation.org> wrote:

> Already fixed post 2.6.24-rc1
> 
> commit c8d90dca3211966ba5189e0f3d4bccd558d9ae08
> Author: Stephen Hemminger <shemminger@linux-foundation.org>
> Date:   Fri Oct 26 03:53:42 2007 -0700
> 
>     [NET] dev_change_name: ignore changes to same name

ah, nice - that explains it. I just booted with very latest -git and the 
warning is gone.

	Ingo

^ permalink raw reply

* Re: [bug, 2.6.24-rc1] sysfs: duplicate filename 'eth0' can not be created
From: Rick Jones @ 2007-10-29 21:49 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Ingo Molnar, linux-kernel, netdev, David S. Miller
In-Reply-To: <4726520F.1020605@garzik.org>

Jeff Garzik wrote:
> Ingo Molnar wrote:
> 
>> hm, this seems to have popped up in the last few days, never had it 
>> before:
>>
>>   sysfs: duplicate filename 'eth0' can not be created
>>   WARNING: at fs/sysfs/dir.c:424 sysfs_add_one()
>>
>>   Call Trace:
>>    [<ffffffff802de00a>] sysfs_add_one+0x54/0xbd
>>    [<ffffffff802dee61>] sysfs_create_link+0xc6/0x11d
>>    [<ffffffff8047c491>] device_rename+0x175/0x1d6
>>    [<ffffffff806180a6>] dev_change_name+0x118/0x211
>>    [<ffffffff8061893c>] dev_ioctl+0x4fa/0x5f8
>>    [<ffffffff8062eb11>] netlink_insert+0x13c/0x14b
>>    [<ffffffff806a877f>] do_page_fault+0x3eb/0x73f
>>    [<ffffffff8060b909>] sock_ioctl+0x1f2/0x200
>>    [<ffffffff802a5a5d>] do_ioctl+0x21/0x6b
>>    [<ffffffff802a5cea>] vfs_ioctl+0x243/0x25c
>>    [<ffffffff802a5d54>] sys_ioctl+0x51/0x71
>>    [<ffffffff8020c02e>] system_call+0x7e/0x83
>>
>>    net eth0: device_rename: sysfs_create_symlink failed (-17)
>>
>> 32-bit bzImage kernel - config attached. (The 64-bit kernel even lost 
>> connectivity due to this and ifcfg-eth0 got renamed to ifcfg-eth0.bak 
>> by kudzu.)
>>
>> detected order of the interfaces is:
>>
>>   forcedeth 0000:00:0a.0: ifname eth0, PHY OUI 0x5043 @1
>>   eth1: RealTek RTL8139 at 0xffffc200001f2000
>>
>> and that's the ordering in /etc/sysconfig/network-scripts as well.
> 
> 
> Does your setup do anything like try to rename the interfaces?
> 
> I cannot think of anything that changed recently in this area in net, 
> off the top of my head.

Ingo -

You are not alone.  I see very similar stuff when I boot a system with a large 
number of interfaces.  At first it was almost every interface generating the 
messages or ones like them, but now with a patch applied (might have come via Jeff?)

hpcpc103:~/linux-2.6.24-rc1# more dev_change_name.patch
--- a/net/core/dev.c    2007-10-24 06:01:31.000000000 -0700
+++ b/net/core/dev.c    2007-10-24 06:41:18.000000000 -0700
@@ -885,6 +885,9 @@ int dev_change_name(struct net_device *d
         if (!dev_valid_name(newname))
                 return -EINVAL;

+       if (strncmp(newname, dev->name, IFNAMSIZ) == 0)
+               return 0;
+
         memcpy(oldname, dev->name, IFNAMSIZ);

         if (strchr(newname, '%')) {

I see far fewer of them:

GSI 60 (level, low) -> CPU 6 (0x0c00) vector 70
sysfs: duplicate filename 'eth6_rename' can not be created
WARNING: at fs/sysfs/dir.c:424 sysfs_add_one()
Call Trace:
  [<a0000001000137c0>] show_stack+0x40/0xa0
                                 sp=e000000159abfb90 bsp=e000000159ab8f48
  [<a000000100013850>] dump_stack+0x30/0x60
                                 sp=e000000159abfd60 bsp=e000000159ab8f30
  [<a000000100206d10>] sysfs_add_one+0xb0/0x240
                                 sp=e000000159abfd60 bsp=e000000159ab8f00
  [<a0000001002092c0>] sysfs_create_link+0x200/0x300
                                 sp=e000000159abfd60 bsp=e000000159ab8ed0
  [<a000000100396bb0>] device_rename+0x2d0/0x380
                                 sp=e000000159abfd80 bsp=e000000159ab8e78
  [<a00000010040b690>] dev_change_name+0x2b0/0x4a0
                                 sp=e000000159abfd80 bsp=e000000159ab8e30
  [<a00000010040bd80>] dev_ifsioc+0x500/0x6c0
                                 sp=e000000159abfd90 bsp=e000000159ab8e00
  [<a00000010040cda0>] dev_ioctl+0xe60/0x1160
                                 sp=e000000159abfda0 bsp=e000000159ab8da0
  [<a0000001003ea7f0>] sock_ioctl+0x610/0x660
                                 sp=e000000159abfe10 bsp=e000000159ab8d68
  [<a000000100170650>] do_ioctl+0x90/0x180
                                 sp=e000000159abfe10 bsp=e000000159ab8d28
  [<a000000100170fa0>] vfs_ioctl+0x860/0x8c0
                                 sp=e000000159abfe10 bsp=e000000159ab8ce0
  [<a0000001001710a0>] sys_ioctl+0xa0/0x120
                                 sp=e000000159abfe20 bsp=e000000159ab8c60
  [<a00000010000af20>] ia64_ret_from_syscall+0x0/0x20
                                 sp=e000000159abfe30 bsp=e000000159ab8c60
  [<a000000000010620>] __start_ivt_text+0xffffffff00010620/0x400
                                 sp=e000000159ac0000 bsp=e000000159ab8c60
:
net eth6_rename: device_rename: sysfs_create_symlink failed (-17)
sysfs: duplicate filename 'eth6' can not be created
WARNING: at fs/sysfs/dir.c:424 sysfs_add_one()

...
net eth6: device_rename: sysfs_create_symlink failed (-17)
udev: renamed network interface eth7 to eth6
sysfs: duplicate filename 'eth7' can not be created
WARNING: at fs/sysfs/dir.c:424 sysfs_add_one()

...

                                 sp=e000000159ac0000 bsp=e000000159ab8c60
net eth7: device_rename: sysfs_create_symlink failed (-17)
udev: renamed network interface eth6_rename to eth7
ACPI: PCI Interrupt 0000:14:01.0[A] -> GSI 60 (level, low) -> IRQ 70


Interestingly (?) when I look at my eth7 interface via ethtool I see:

hpcpc103:~/linux-2.6.24-rc1# ethtool -i eth7
driver: Neterion
version: 2.0.26.5
firmware-version:
bus-info: 0000:0f:01.0

but if I look for it in /proc/interrupts I don't see it:

hpcpc103:~/linux-2.6.24-rc1# cat /proc/interrupts | grep eth7
hpcpc103:~/linux-2.6.24-rc1#

and if I look at all of /proc/interrupts:

hpcpc103:~# cat /proc/interrupts
            CPU0       CPU1       CPU2       CPU3       CPU4       CPU5 
CPU6       CPU7
  28:         12         12         12         12         12         12 
12         12          LSAPIC  cpe_poll
  29:          0          0          0          0          0          0 
  0          0          LSAPIC  cmc_poll
  31:          0          0          0          0          0          0 
  0          0          LSAPIC  cmc_hndlr
  48:          0          0          0          0          0          0 
  0          0  IO-SAPIC-level  acpi
  50:          0          0       1065          0          0          0 
  0          0  IO-SAPIC-level  serial
  52:          0          0          0          0        328          0 
  0          0  IO-SAPIC-level  ehci_hcd:usb1
  54:          0          0          0          0          0          0 
32          0  IO-SAPIC-level  ohci_hcd:usb2
  57:          0          0          0          0          0          0 
  0          0  IO-SAPIC-level  ohci_hcd:usb3
  60:          0          0          0          0      11945          0 
  0          0  IO-SAPIC-level  eth6
  61:          0          0          0          0          0     101072 
  0          0  IO-SAPIC-level  eth6 Neterion 10 Gigabit Ethernet-SR Low Profile 
PCI-X 2.0 DDR A
  70:          0          0          0          0          0          0 
25580          0  IO-SAPIC-level  cciss0
232:          0          0          0          0          0          0 
0          0          LSAPIC  mca_rdzv
238:          0          0          0          0          0          0 
0          0          LSAPIC  perfmon
239:    2376190    2376079    2376009    2376005    2376127    2376121 
2375918    2373020          LSAPIC  timer
240:          0          0          0          0          0          0 
0          0          LSAPIC  mca_wkup
252:          0          0          0          0          0          0 
0          0          LSAPIC  tlb_flush
253:        586        255        449        315        448        982 
497        702          LSAPIC  resched
254:        123        162        161        166        168        154 
109        140          LSAPIC  IPI
ERR:          0

it appears as eth6.

rick jones
...


> 
>     Jeff
> 
> 
> 
> -
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply

* [PATCH][RFC] Add support for the RDC R6040 Fast Ethernet controller
From: Florian Fainelli @ 2007-10-29 21:51 UTC (permalink / raw)
  To: netdev

This patch adds support for the RDC R6040 MAC we can find in the RDC R-321x System-on-chips.
This driver really needs improvements especially on the NAPI part which probably does not
fully use the new NAPI structure.
You will need the RDC PCI identifiers if you want to test this driver which are the following ones :

RDC_PCI_VENDOR_ID = 0x17f3
RDC_PCI_DEVICE_ID_RDC_R6040 = 0x6040

Thank you very much in advance for your comments.

Signed-off-by: Sten Wang <sten.wang@rdc.com.tw>
Signed-off-by: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
Signed-off-by: Florian Fainelli <florian.fainelli@telecomint.eu>
---
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ce34b53..c8a5eef 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1643,6 +1643,24 @@ config 8139_OLD_RX_RESET
 	  experience problems, you can enable this option to restore the
 	  old RX-reset behavior.  If unsure, say N.
 
+config R6040
+	tristate "RDC R6040 Fast Ethernet Adapter support (EXPERIMENTAL)"
+	depends on NET_PCI && PCI && EXPERIMENTAL
+	select MII
+	help
+	  This is a driver for the R6040 Fast Ethernet MACs found in the
+	  the RDC R-321x System-on-chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called r6040. This is recommended.
+
+config R6040_NAPI
+	bool "NAPI support for R6040"
+	depends on R6040
+	default y
+	help
+	  Enable the NAPI polling for the R6040 driver.
+
 config SIS900
 	tristate "SiS 900/7016 PCI Fast Ethernet Adapter support"
 	depends on NET_PCI && PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 22f78cb..5fb95ca 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -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_R6040) += r6040.o
 
 #
 # end link order section
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
new file mode 100644
index 0000000..ada1b7f
--- /dev/null
+++ b/drivers/net/r6040.c
@@ -0,0 +1,970 @@
+/*
+ * RDC R6040 Fast Ethernet MAC support
+ *
+ * Copyright (C) 2004 Sten Wang <sten.wang@rdc.com.tw>
+ * Copyright (C) 2007 Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
+ * 			Florian Fainelli <florian@openwrt.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that 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 Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * 	Changelog :
+ *	----------	------------------------------------------------
+ *	10-07-2007	Clean up the driver using checkpatch
+ *	08-24-2006	Support at linux 2.6.10 above
+ *	03-24-2006	Support NAPI
+ *	03-21-2006	change spin_lock_irqsave(lp->lock, flags)
+ *			to spin_lock_irqsave(&lp->lock, flags)
+ *			in set_multicast_list
+ *	03-15-2006      Modify the set_multicast_list ,due to when re-plug the ethernet,
+ *			it will forget the previous setting
+ *	07-12-2005	modify the set_multicast_list
+ *	03-28-2005	modify some error mac register offset in
+ *			function set_multicast_list
+ *	03-27-2005	Add the internal state machine reset
+ *			If multicast address more than 4, enter PROM mode
+ *			Changed rdc to r6040
+ *	12-22-2004	Sten Init MAC MBCR register=0x012A
+ *			PHY_CAP = 0x01E1
+ *
+ *	Need to Do LIst:
+ *	1. If multicast address more than 4, use the multicast address hash
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/crc32.h>
+#include <linux/spinlock.h>
+
+#include <asm/processor.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define DRV_NAME	"r6040"
+#define DRV_VERSION	"0.14"
+#define DRV_RELDATE	"29Oct2007"
+
+/* PHY CHIP Address */
+#define PHY1_ADDR	1	/* For MAC1 */
+#define PHY2_ADDR	2	/* For MAC2 */
+#define PHY_MODE	0x3100	/* PHY CHIP Register 0 */
+#define PHY_CAP		0x01E1	/* PHY CHIP Register 4 */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  	(6000 * HZ / 1000)
+#define TIMER_WUT	(jiffies + HZ * 1)/* timer wakeup time : 1 second */
+
+/* RDC MAC ID */
+#define RDC_MAC_ID	0x6040
+
+/* RDC MAC I/O Size */
+#define R6040_IO_SIZE	256
+
+/* RDC Chip PCI Command */
+#define R6040_PCI_CMD	0x0005	/* IO, Master */
+
+/* MAX RDC MAC */
+#define MAX_MAC		2
+
+/* MAC setting */
+#define TX_DCNT		0x80	/* TX descriptor count */
+#define RX_DCNT		0x80	/* RX descriptor count */
+#define MAX_BUF_SIZE	0x600
+#define ALLOC_DESC_SIZE	((TX_DCNT+RX_DCNT) * sizeof(struct r6040_descriptor) + 0x10)
+#define MBCR_DEFAULT	0x012A	/* MAC Bus Control Register */
+
+/* PHY settings */
+#define ICPLUS_PHY_ID	0x0243
+
+MODULE_AUTHOR("Sten Wang <sten.wang@rdc.com.tw>, Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>, Florian Fainelli <florian@openwrt.org>");
+MODULE_LICENSE("GPL");
+#ifdef CONFIG_R6040_NAPI
+MODULE_DESCRIPTION("RDC R6040 NAPI PCI FastEthernet Driver");
+#else
+MODULE_DESCRIPTION("RDC R6040 PCI FastEthernet Driver");
+#endif
+
+#define RX_INT                         0x0001
+#define TX_INT                         0x0010
+#define RX_NO_DESC_INT                 0x0002
+#define R6040_INT_MASK                 (RX_INT | TX_INT)
+
+struct r6040_descriptor {
+	u16	status, len;		/* 0-3 */
+	u32	buf;			/* 4-7 */
+	u32	ndesc;			/* 8-B */
+	u32	rev1;			/* C-F */
+	char	*vbufp;			/* 10-13 */
+	struct r6040_descriptor *vndescp;	/* 14-17 */
+	struct sk_buff *skb_ptr;	/* 18-1B */
+	u32	rev2;			/* 1C-1F */
+} __attribute__((aligned(32)));
+
+struct r6040_private {
+	spinlock_t lock;		/* driver lock */
+	struct timer_list timer;
+	struct pci_dev *pdev;
+
+	struct r6040_descriptor *rx_insert_ptr;
+	struct r6040_descriptor *rx_remove_ptr;
+	struct r6040_descriptor *tx_insert_ptr;
+	struct r6040_descriptor *tx_remove_ptr;
+	u16	tx_free_desc, rx_free_desc, phy_addr, phy_mode;
+	u16	mcr0, mcr1;
+	dma_addr_t desc_dma;
+	char	*desc_pool;
+	u16	switch_sig;
+	struct net_device *dev;
+	struct mii_if_info mii_if;
+	struct napi_struct napi;
+};
+
+struct r6040_chip_info {
+	const char *name;
+	u16 pci_flags;
+	int io_size;
+	int drv_flags;
+};
+
+#ifdef CONFIG_R6040_NAPI
+static int NAPI_status;
+#endif
+
+#ifdef CONFIG_R6040_NAPI
+static char version[] __devinitdata =
+	KERN_INFO DRV_NAME ": RDC R6040 NAPI net driver, version "DRV_VERSION " (" DRV_RELDATE ")\n";
+#else
+static char version[] __devinitdata =
+	KERN_INFO DRV_NAME ": RDC R6040 net driver, version "DRV_VERSION " (" DRV_RELDATE ")\n";
+#endif
+static struct r6040_chip_info r6040_chip_info[] __devinitdata =
+{
+	{ "RDC R6040 Knight", R6040_PCI_CMD, R6040_IO_SIZE, 0}
+};
+static char *parent;
+
+static int NUM_MAC_TABLE = 2 ;
+module_param(parent, charp, 0444);
+MODULE_PARM_DESC(parent, "Parent network device name");
+
+static int phy_table[] = { 0x1, 0x2};
+
+static u8 adr_table[2][8] = {
+	{0x00, 0x00, 0x60, 0x00, 0x00, 0x01},
+	{0x00, 0x00, 0x60, 0x00, 0x00, 0x02}
+};
+
+module_param_array(adr_table, int, &NUM_MAC_TABLE, 0644);
+MODULE_PARM_DESC(adr_table, "MAC Address (assigned)");
+
+static int  mdio_read(struct net_device *dev, int phy_id, int location);
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
+static int r6040_open(struct net_device *dev);
+static int r6040_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static irqreturn_t r6040_interrupt(int irq, void *dev_id);
+static int r6040_close(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static struct ethtool_ops netdev_ethtool_ops;
+static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void r6040_down(struct net_device *dev);
+static void r6040_up(struct net_device *dev);
+static void r6040_tx_timeout(struct net_device *dev);
+static void r6040_timer(unsigned long);
+static void r6040_mac_address(struct net_device *dev);
+
+static int phy_mode_chk(struct net_device *dev);
+static int phy_read(int ioaddr, int phy_adr, int reg_idx);
+static void phy_write(int ioaddr, int phy_adr, int reg_idx, int dat);
+static void rx_buf_alloc(struct r6040_private *lp, struct net_device *dev);
+#ifdef CONFIG_R6040_NAPI
+static int r6040_poll(struct napi_struct *napi, int budget);
+#endif
+
+static int mdio_read(struct net_device *dev, int phy_id, int regnum)
+{
+	struct r6040_private *lp = netdev_priv(dev);
+	long ioaddr = dev->base_addr;
+	return  (phy_read(ioaddr, lp->phy_addr, regnum)) ;
+}
+
+static void mdio_write(struct net_device *dev, int phy_id, int regnum, int value)
+{
+	struct r6040_private *lp = netdev_priv(dev);
+	long ioaddr = dev->base_addr;
+
+	phy_write(ioaddr, lp->phy_addr, regnum, value);
+}
+
+static int __devinit r6040_init_one(struct pci_dev *pdev,
+					 const struct pci_device_id *ent)
+{
+	struct net_device *dev;
+	struct r6040_private *lp;
+	int ioaddr, io_size, err;
+	static int card_idx = -1;
+	int chip_id = (int)ent->driver_data;
+
+	printk(KERN_INFO "%s\n", version);
+
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+
+	/* this should always be supported */
+	if (pci_set_dma_mask(pdev, 0xffffffff)) {
+		printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses not supported by the card\n");
+		return  -ENODEV;
+	}
+
+	/* IO Size check */
+	io_size = r6040_chip_info[chip_id].io_size;
+	if (pci_resource_len(pdev, 0) < io_size)
+		return  -ENODEV;
+
+	ioaddr = pci_resource_start(pdev, 0);	/* IO map base address */
+	pci_set_master(pdev);
+
+	dev = alloc_etherdev(sizeof(struct r6040_private));
+	if (!dev)
+		return -ENOMEM;
+
+	if (pci_request_regions(pdev, DRV_NAME)) {
+		printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n");
+		err = -ENODEV;
+		goto err_out_disable;
+	}
+
+	/* Init system & device */
+	lp = dev->priv;
+	dev->base_addr = ioaddr;
+	dev->irq = pdev->irq;
+
+	spin_lock_init(&lp->lock);
+	pci_set_drvdata(pdev, dev);
+
+	/* Set MAC address */
+	card_idx++;
+
+	/* Check if the MAC address is 0xFFFFFFFFFFFF or 0 */
+	if (((inw(ioaddr + 0x68) == 0xFFFF) && (inw(ioaddr + 0x6A) == 0xFFFF) && (inw(ioaddr + 0x6C) == 0xFFFF)) ||
+		((inw(ioaddr + 0x68) == 0) && (inw(ioaddr + 0x6A) == 0) && (inw(ioaddr + 0x6C) == 0)))
+		memcpy(dev->dev_addr, (u8 *)&adr_table[card_idx][0], 6);
+	else {
+		u16 *adrp;
+		adrp = (u16 *) dev->dev_addr;
+		adrp[0] = inw(ioaddr + 0x68);
+		adrp[1] = inw(ioaddr + 0x6A);
+		adrp[2] = inw(ioaddr + 0x6C);
+	}
+
+	/* Link new device into r6040_root_dev */
+	lp->pdev = pdev;
+
+	/* Init RDC private data */
+	lp->mcr0 = 0x1002;
+	lp->phy_addr = phy_table[card_idx];
+	lp->switch_sig = 0;
+
+	/* The RDC-specific entries in the device structure. */
+	dev->open = &r6040_open;
+	dev->hard_start_xmit = &r6040_start_xmit;
+	dev->stop = &r6040_close;
+	dev->set_multicast_list = &set_multicast_list;
+	dev->do_ioctl = &r6040_ioctl;
+	dev->ethtool_ops = &netdev_ethtool_ops;
+	dev->tx_timeout = &r6040_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_R6040_NAPI
+	netif_napi_add(dev, &lp->napi, r6040_poll, 64);
+#endif
+	lp->mii_if.dev = dev;
+	lp->mii_if.mdio_read = mdio_read;
+	lp->mii_if.mdio_write = mdio_write;
+	lp->mii_if.phy_id = lp->phy_addr;
+	lp->mii_if.phy_id_mask = 0x1f;
+	lp->mii_if.reg_num_mask = 0x1f;
+
+	/* Register net device. After this dev->name assign */
+	err = register_netdev(dev);
+	if (err) {
+		printk(KERN_ERR DRV_NAME ": Failed to register net device\n");
+		goto err_out_res;
+	}
+
+	netif_carrier_on(dev);
+	return 0;
+
+err_out_res:
+	pci_release_regions(pdev);
+err_out_disable:
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+	kfree(dev);
+
+	return err;
+}
+
+static void __devexit r6040_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	unregister_netdev(dev);
+	pci_release_regions(pdev);
+	kfree(dev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+}
+
+static int
+r6040_open(struct net_device *dev)
+{
+	struct r6040_private *lp = dev->priv;
+	int i;
+
+	/* Request IRQ and Register interrupt handler */
+	i = request_irq(dev->irq, &r6040_interrupt, IRQF_SHARED, dev->name, dev);
+	if (i)
+		return i;
+	/* Set MAC address */
+	r6040_mac_address(dev);
+	/* Allocate Descriptor memory */
+	lp->desc_pool = pci_alloc_consistent(lp->pdev, ALLOC_DESC_SIZE, &lp->desc_dma);
+	if (!lp->desc_pool)
+		return -ENOMEM;
+
+	r6040_up(dev);
+
+	napi_enable(&lp->napi);
+	netif_start_queue(dev);
+
+	if (lp->switch_sig != ICPLUS_PHY_ID) {
+		/* set and active a timer process */
+		init_timer(&lp->timer);
+		lp->timer.expires = TIMER_WUT;
+		lp->timer.data = (unsigned long)dev;
+		lp->timer.function = &r6040_timer;
+		add_timer(&lp->timer);
+	}
+	return 0;
+}
+
+static void
+r6040_tx_timeout(struct net_device *dev)
+{
+	struct r6040_private *priv = netdev_priv(dev);
+	spin_lock(&priv->lock);
+	dev->stats.tx_errors++;
+	spin_unlock(&priv->lock);
+
+	netif_stop_queue(dev);
+}
+
+
+static int
+r6040_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct r6040_private *lp = netdev_priv(dev);
+	struct r6040_descriptor *descptr;
+	int ioaddr = dev->base_addr;
+	unsigned long flags;
+
+	if (!skb)	/* NULL skb directly return */
+		return 0;
+	if (skb->len >= MAX_BUF_SIZE) {	/* Packet too long, drop it */
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	/* Critical Section */
+	spin_lock_irqsave(&lp->lock, flags);
+
+	/* TX resource check */
+	if (!lp->tx_free_desc) {
+		spin_unlock_irqrestore(&lp->lock, flags);
+		printk(KERN_ERR DRV_NAME ": NO TX DESC ");
+		return 1;
+	}
+
+	/* Statistic Counter */
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+	/* Set TX descriptor & Transmit it */
+	lp->tx_free_desc--;
+	descptr = lp->tx_insert_ptr;
+	if (skb->len < 0x3c)
+		descptr->len = 0x3c;
+	else
+		descptr->len = skb->len;
+
+	descptr->skb_ptr = skb;
+	descptr->buf = cpu_to_le32(pci_map_single(lp->pdev, skb->data, skb->len, PCI_DMA_TODEVICE));
+	descptr->status = 0x8000;
+	outw(0x01, ioaddr + 0x14);
+	lp->tx_insert_ptr = descptr->vndescp;
+
+	/* If no tx resource, stop */
+	if (!lp->tx_free_desc)
+		netif_stop_queue(dev);
+
+	dev->trans_start = jiffies;
+	spin_unlock_irqrestore(&lp->lock, flags);
+	return 0;
+}
+
+/* The RDC interrupt handler. */
+static irqreturn_t
+r6040_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct r6040_private *lp = netdev_priv(dev);
+	int ioaddr, status;
+	unsigned long flags;
+#ifdef CONFIG_R6040_NAPI
+	int handled = 1;
+#else
+	int handled = 0;
+#endif
+
+	if (!dev) {
+		printk(KERN_ERR DRV_NAME ": INT() unknown device.\n");
+		return IRQ_RETVAL(handled);
+	}
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	/* Check MAC Interrupt status */
+	ioaddr = dev->base_addr;
+	outw(0x0, ioaddr + 0x40);	/* Mask Off RDC MAC interrupt */
+	status = inw(ioaddr + 0x3c);	/* Read INTR status and clear */
+
+#ifdef CONFIG_R6040_NAPI
+	if (netif_rx_schedule_prep(dev, &lp->napi)) {
+		NAPI_status = status;
+		__netif_rx_schedule(dev, &lp->napi);
+	}
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+	return IRQ_RETVAL(handled);
+#else
+	/* TX interrupt request */
+	if (status & 0x10) {
+		handled = 1;
+		descptr = lp->tx_remove_ptr;
+		while (lp->tx_free_desc < TX_DCNT) {
+			if (descptr->status & 0x8000)
+				break; /* Not complte */
+			skb_ptr = descptr->skb_ptr;
+			pci_unmap_single(lp->pdev, descptr->buf, skb_ptr->len, PCI_DMA_TODEVICE);
+			dev_kfree_skb_irq(skb_ptr); /* Free buffer */
+			descptr->skb_ptr = 0;
+			descptr = descptr->vndescp; /* To next descriptor */
+			lp->tx_free_desc++;
+		}
+		lp->tx_remove_ptr = descptr;
+		if (lp->tx_free_desc)
+			netif_wake_queue(dev);
+	}
+
+	/* RX interrupt request */
+	if (status & 0x01) {
+		handled = 1;
+		descptr = lp->rx_remove_ptr;
+		while (lp->rx_free_desc) {
+			if (descptr->status & 0x8000)
+				break; /* No Rx packet */
+			skb_ptr = descptr->skb_ptr;
+			descptr->skb_ptr = 0;
+			skb_ptr->dev = dev;
+			skb_put(skb_ptr, descptr->len - 4);
+			pci_unmap_single(lp->pdev, descptr->buf, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			skb_ptr->protocol = eth_type_trans(skb_ptr, dev);
+			netif_rx(skb_ptr);  /* Send to upper layer */
+			lp->dev->stats.rx_packets++;
+			lp->dev->stats.rx_bytes += descptr->len;
+			descptr = descptr->vndescp; /* To next descriptor */
+			lp->rx_free_desc--;
+		}
+		lp->rx_remove_ptr = descptr;
+	}
+
+	/* Allocate new RX buffer */
+	if (lp->rx_free_desc < RX_DCNT)
+		rx_buf_alloc(lp, dev);
+
+	outw(R6040_INT_MASK, ioaddr + 0x40);	/* TX/RX interrupt enable */
+	spin_unlock_irqrestore(&lp->lock, flags);
+#endif
+	return IRQ_RETVAL(handled);
+}
+
+
+/*
+ *     Set or clear the multicast filter for this adaptor.
+ */
+static void
+set_multicast_list(struct net_device *dev)
+{
+	struct r6040_private *lp = netdev_priv(dev);
+	struct dev_mc_list *mcptr;
+	int ioaddr = dev->base_addr;
+	u16 *adrp, i;
+	unsigned long flags;
+
+	/* MAC Address */
+	adrp = (u16 *) dev->dev_addr;
+	outw(adrp[0], ioaddr + 0x68);
+	outw(adrp[1], ioaddr + 0x6A);
+	outw(adrp[2], ioaddr + 0x6C);
+
+
+	/* Promiscous Mode */
+	spin_lock_irqsave(&lp->lock, flags);
+	i = inw(ioaddr) & ~0x0120;		/* Clear AMCP & PROM */
+	if (dev->flags & IFF_PROMISC) {
+		i |= 0x0020;
+		lp->mcr0 |= 0x0020;
+	}
+	if (dev->mc_count > 4)
+		i |= 0x0020;	/* Too many multicast address */
+	outw(i, ioaddr);
+	spin_unlock_irqrestore(&lp->lock, flags);
+	/* Multicast Address */
+	if (dev->mc_count > 4)	/* Wait to do: Hash Table for multicast */
+		return;
+	/* Multicast Address 1~4 case */
+	for (i = 0, mcptr = dev->mc_list; (i < dev->mc_count) && (i < 4); i++) {
+		adrp = (u16 *)mcptr->dmi_addr;
+		outw(adrp[0], ioaddr + 0x70 + 8*i);
+		outw(adrp[1], ioaddr + 0x72 + 8*i);
+		outw(adrp[2], ioaddr + 0x74 + 8*i);
+		mcptr = mcptr->next;
+	}
+	for (i = dev->mc_count; i < 4; i++) {
+		outw(0xffff, ioaddr + 0x68 + 8*i);
+		outw(0xffff, ioaddr + 0x6A + 8*i);
+		outw(0xffff, ioaddr + 0x6C + 8*i);
+	}
+}
+
+static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct r6040_private *rp = netdev_priv(dev);
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, pci_name(rp->pdev));
+}
+
+static struct ethtool_ops netdev_ethtool_ops = {
+	.get_drvinfo		= netdev_get_drvinfo,
+};
+
+static int
+r6040_close(struct net_device *dev)
+{
+	struct r6040_private *lp = netdev_priv(dev);
+
+	/* deleted timer */
+	del_timer_sync(&lp->timer);
+
+	spin_lock_irq(&lp->lock);
+
+	netif_stop_queue(dev);
+	napi_disable(&lp->napi);
+
+	r6040_down(dev);
+
+	spin_unlock_irq(&lp->lock);
+
+	return 0;
+}
+
+static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct r6040_private *lp = netdev_priv(dev);
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *) &rq->ifr_data;
+	int rc;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+	spin_lock_irq(&lp->lock);
+	rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL);
+	spin_unlock_irq(&lp->lock);
+	return rc;
+}
+
+/* Stop RDC MAC and Free the allocated resource */
+static void r6040_down(struct net_device *dev)
+{
+	struct r6040_private *lp = netdev_priv(dev);
+	int i;
+	int ioaddr = dev->base_addr;
+	u16 *adrp;
+
+	/* Stop MAC */
+	outw(0x0000, ioaddr + 0x40);	/* Mask Off Interrupt */
+	outw(0x0001, ioaddr + 0x04);	/* Reset RDC MAC */
+	i = 0;
+	do {} while ((i++ < 2048) && (inw(ioaddr + 0x04) & 0x1));
+
+	/* Restore MAC Address to MIDx */
+	adrp = (u16 *) dev->dev_addr;
+	outw(adrp[0], ioaddr + 0x68);
+	outw(adrp[1], ioaddr + 0x6A);
+	outw(adrp[2], ioaddr + 0x6C);
+	free_irq(dev->irq, dev);
+	/* Free RX buffer */
+	for (i = 0; i < RX_DCNT; i++) {
+		if (lp->rx_insert_ptr->skb_ptr) {
+			pci_unmap_single(lp->pdev, lp->rx_insert_ptr->buf, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(lp->rx_insert_ptr->skb_ptr);
+			lp->rx_insert_ptr->skb_ptr = 0;
+		}
+		lp->rx_insert_ptr = lp->rx_insert_ptr->vndescp;
+	}
+
+	/* Free TX buffer */
+	for (i = 0; i < TX_DCNT; i++) {
+		if (lp->tx_insert_ptr->skb_ptr) {
+			pci_unmap_single(lp->pdev, lp->tx_insert_ptr->buf, MAX_BUF_SIZE, PCI_DMA_TODEVICE);
+			dev_kfree_skb(lp->tx_insert_ptr->skb_ptr);
+			lp->rx_insert_ptr->skb_ptr = 0;
+		}
+		lp->tx_insert_ptr = lp->tx_insert_ptr->vndescp;
+	}
+
+	/* Free Descriptor memory */
+	pci_free_consistent(lp->pdev, ALLOC_DESC_SIZE, lp->desc_pool, lp->desc_dma);
+}
+
+
+
+#ifdef CONFIG_R6040_NAPI
+static int r6040_poll(struct napi_struct *napi, int budget)
+{
+	struct r6040_private *priv = container_of(napi, struct r6040_private, napi);
+	struct r6040_descriptor *descptr;
+	struct sk_buff *skb_ptr;
+	int ioaddr = priv->dev->base_addr;
+	/* TX interrupt request */
+	if (NAPI_status & 0x10) {
+		descptr = priv->tx_remove_ptr;
+		while (priv->tx_free_desc < TX_DCNT) {
+			if (descptr->status & 0x8000)
+				break; /* Not complte */
+			skb_ptr = descptr->skb_ptr;
+			pci_unmap_single(priv->pdev, descptr->buf, skb_ptr->len, PCI_DMA_TODEVICE);
+			dev_kfree_skb_irq(skb_ptr); /* Free buffer */
+			descptr->skb_ptr = 0;
+			descptr = descptr->vndescp; /* To next descriptor */
+			priv->tx_free_desc++;
+		}
+		priv->tx_remove_ptr = descptr;
+		if (priv->tx_free_desc)
+			netif_wake_queue(priv->dev);
+	}
+	/* RX interrupt request */
+	if (NAPI_status & 0x01) {
+		descptr = priv->rx_remove_ptr;
+		while (priv->rx_free_desc) {
+			if (descptr->status & 0x8000)
+				break; /* No Rx packet */
+			skb_ptr = descptr->skb_ptr;
+			descptr->skb_ptr = 0;
+			skb_ptr->dev = priv->dev;
+			skb_put(skb_ptr, descptr->len - 4);
+			pci_unmap_single(priv->pdev, descptr->buf, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev);
+			netif_receive_skb(skb_ptr); /* Send to upper layer */
+			priv->dev->stats.rx_packets++;
+			priv->dev->stats.rx_bytes += descptr->len;
+			descptr = descptr->vndescp; /* To next descriptor */
+			priv->rx_free_desc--;
+		}
+		priv->rx_remove_ptr = descptr;
+	}
+	/* Allocate new RX buffer */
+	if (priv->rx_free_desc < RX_DCNT)
+		rx_buf_alloc(priv, priv->dev);
+	local_irq_disable();
+	netif_rx_complete(priv->dev, napi);
+	outw(R6040_INT_MASK, ioaddr + 0x40);
+	local_irq_enable();
+	return 0;
+}
+#endif
+
+/* Init RDC MAC */
+static void r6040_up(struct net_device *dev)
+{
+	struct r6040_private *lp = netdev_priv(dev);
+	struct r6040_descriptor *descptr;
+	int i;
+	int ioaddr = dev->base_addr;
+	u32 tmp_addr;
+	dma_addr_t desc_dma, start_dma;
+	/* Initialize */
+	lp->tx_free_desc = TX_DCNT;
+	lp->rx_free_desc = 0;
+	/* Init descriptor */
+	memset(lp->desc_pool, 0, ALLOC_DESC_SIZE); /* Let all descriptor = 0 */
+	lp->tx_insert_ptr = (struct r6040_descriptor *)lp->desc_pool;
+	lp->tx_remove_ptr = lp->tx_insert_ptr;
+	lp->rx_insert_ptr = (struct r6040_descriptor *)lp->tx_insert_ptr+TX_DCNT;
+	lp->rx_remove_ptr = lp->rx_insert_ptr;
+	/* Init TX descriptor */
+	descptr = lp->tx_insert_ptr;
+	desc_dma = lp->desc_dma;
+	start_dma = desc_dma;
+	for (i = 0; i < TX_DCNT; i++) {
+		descptr->ndesc = cpu_to_le32(desc_dma + sizeof(struct r6040_descriptor));
+		descptr->vndescp = (descptr + 1);
+		descptr = (descptr + 1);
+		desc_dma += sizeof(struct r6040_descriptor);
+	}
+	(descptr - 1)->ndesc = cpu_to_le32(start_dma);
+	(descptr - 1)->vndescp = lp->tx_insert_ptr;
+
+	/* Init RX descriptor */
+	start_dma = desc_dma;
+	descptr = lp->rx_insert_ptr;
+	for (i = 0; i < RX_DCNT; i++) {
+		descptr->ndesc = cpu_to_le32(desc_dma + sizeof(struct r6040_descriptor));
+		descptr->vndescp = (descptr + 1);
+		descptr = (descptr + 1);
+		desc_dma += sizeof(struct r6040_descriptor);
+	}
+	(descptr - 1)->ndesc = cpu_to_le32(start_dma);
+	(descptr - 1)->vndescp = lp->rx_insert_ptr;
+
+	/* Allocate buffer for RX descriptor */
+	rx_buf_alloc(lp, dev);
+
+	/* TX and RX descriptor start Register */
+	tmp_addr = cpu_to_le32((u32)lp->tx_insert_ptr);
+	tmp_addr = virt_to_bus((volatile void *)tmp_addr);
+	outw((u16) tmp_addr, ioaddr+0x2c);
+	outw(tmp_addr >> 16, ioaddr+0x30);
+	tmp_addr = cpu_to_le32((u32)lp->rx_insert_ptr);
+	tmp_addr = virt_to_bus((volatile void *)tmp_addr);
+	outw((u16) tmp_addr, ioaddr+0x34);
+	outw(tmp_addr >> 16, ioaddr+0x38);
+
+	/* Buffer Size Register */
+	outw(MAX_BUF_SIZE, ioaddr+0x18);
+	lp->switch_sig = phy_read(ioaddr, 0, 2);
+
+	if (lp->switch_sig  == ICPLUS_PHY_ID) {
+		phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */
+		lp->phy_mode = 0x8000;
+	} else {
+		/* PHY Mode Check */
+		phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP);
+		phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE);
+
+		if (PHY_MODE == 0x3100)
+			lp->phy_mode = phy_mode_chk(dev);
+		else
+			lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
+	}
+	/* MAC Bus Control Register */
+	outw(MBCR_DEFAULT, ioaddr+0x8);
+
+	/* MAC TX/RX Enable */
+	lp->mcr0 |= lp->phy_mode;
+	outw(lp->mcr0, ioaddr);
+
+	/* set interrupt waiting time and packet numbers */
+	outw(0x0802, ioaddr + 0x0C);
+	outw(0x0802, ioaddr + 0x10);
+
+	/* upgrade performance (by RDC guys) */
+	phy_write(ioaddr, 30, 17, (phy_read(ioaddr, 30, 17) | 0x4000));        /* bit 14=1 */
+	phy_write(ioaddr, 30, 17, ~((~phy_read(ioaddr, 30, 17)) | 0x2000));    /* bit 13=0 */
+	phy_write(ioaddr, 0, 19, 0x0000);
+	phy_write(ioaddr, 0, 30, 0x01F0);
+
+	/* Interrupt Mask Register */
+	outw(R6040_INT_MASK, ioaddr + 0x40);
+}
+
+/*
+  A periodic timer routine
+	Polling PHY Chip Link Status
+*/
+static void r6040_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct r6040_private *lp = netdev_priv(dev->priv);
+	u16 ioaddr = dev->base_addr, phy_mode;
+
+	/* Polling PHY Chip Status */
+	if (PHY_MODE == 0x3100)
+		phy_mode = phy_mode_chk(dev);
+	else
+		phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
+
+	if (phy_mode != lp->phy_mode) {
+		lp->phy_mode = phy_mode;
+		lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode;
+		outw(lp->mcr0, ioaddr);
+		printk(KERN_INFO "Link Change %x \n", inw(ioaddr));
+	}
+
+	/* Timer active again */
+	lp->timer.expires = TIMER_WUT;
+	add_timer(&lp->timer);
+}
+
+/* Allocate skb buffer for rx descriptor */
+static void rx_buf_alloc(struct r6040_private *lp, struct net_device *dev)
+{
+	struct r6040_descriptor *descptr;
+	int ioaddr = dev->base_addr ;
+
+	descptr = lp->rx_insert_ptr;
+	while (lp->rx_free_desc < RX_DCNT) {
+		descptr->skb_ptr = dev_alloc_skb(MAX_BUF_SIZE);
+
+		if (!descptr->skb_ptr)
+			break;
+		descptr->buf = cpu_to_le32(pci_map_single(lp->pdev, descptr->skb_ptr->tail, MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+		descptr->status = 0x8000;
+		descptr = descptr->vndescp;
+		lp->rx_free_desc++;
+		outw(lp->mcr0 | 0x0002, ioaddr); /* Trigger Rx DMA */
+	}
+	lp->rx_insert_ptr = descptr;
+}
+
+/* Status of PHY CHIP */
+static int phy_mode_chk(struct net_device *dev)
+{
+	struct r6040_private *lp = netdev_priv(dev);
+	int ioaddr = dev->base_addr, phy_dat;
+
+	/* PHY Link Status Check */
+	phy_dat = phy_read(ioaddr, lp->phy_addr, 1);
+	if (!(phy_dat & 0x4))
+		return 0x8000;	/* Link Failed, full duplex */
+
+	/* PHY Chip Auto-Negotiation Status */
+	phy_dat = phy_read(ioaddr, lp->phy_addr, 1);
+	if (phy_dat & 0x0020) {
+		/* Auto Negotiation Mode */
+		phy_dat = phy_read(ioaddr, lp->phy_addr, 5);
+		phy_dat &= phy_read(ioaddr, lp->phy_addr, 4);
+		if (phy_dat & 0x140)
+			phy_dat = 0x8000;
+		else
+			phy_dat = 0;
+	} else {
+		/* Force Mode */
+		phy_dat = phy_read(ioaddr, lp->phy_addr, 0);
+		if (phy_dat & 0x100)
+			phy_dat = 0x8000;
+		else
+			phy_dat = 0x0000;
+	}
+
+	return phy_dat;
+};
+
+/* Read a word data from PHY Chip */
+static int phy_read(int ioaddr, int phy_addr, int reg_idx)
+{
+	int i = 0;
+
+	outw(0x2000 + reg_idx + (phy_addr << 8), ioaddr + 0x20);
+	do {} while ((i++ < 2048) && (inw(ioaddr + 0x20) & 0x2000));
+
+	return inw(ioaddr + 0x24);
+}
+
+/* Write a word data from PHY Chip */
+static void phy_write(int ioaddr, int phy_addr, int reg_idx, int dat)
+{
+	int i = 0;
+
+	outw(dat, ioaddr + 0x28);
+	outw(0x4000 + reg_idx + (phy_addr << 8), ioaddr + 0x20);
+	do {} while ((i++ < 2048) && (inw(ioaddr + 0x20) & 0x4000));
+}
+
+/* Read/set MAC address routines */
+static void r6040_mac_address(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr ;
+       u16 *adrp ;
+
+       /* MAC operation register */
+       outw(0x01, ioaddr + 0x04); /* Reset MAC */
+       outw(2, ioaddr + 0xAC); /* Reset internal state machine */
+       outw(0, ioaddr + 0xAC);
+       udelay(5000);
+
+       /* Restore MAC Address */
+       adrp = (u16 *) dev->dev_addr;
+       outw(adrp[0], ioaddr + 0x68);
+       outw(adrp[1], ioaddr + 0x6A);
+       outw(adrp[2], ioaddr + 0x6C);
+}
+
+static struct pci_device_id r6040_pci_tbl[] = {
+	{PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+MODULE_DEVICE_TABLE(pci, r6040_pci_tbl);
+
+static struct pci_driver r6040_driver = {
+	.name		= "r6040",
+	.id_table	= r6040_pci_tbl,
+	.probe		= r6040_init_one,
+	.remove		= __devexit_p(r6040_remove_one),
+};
+
+
+static int __init r6040_init (void)
+{
+	return pci_register_driver (&r6040_driver);
+}
+
+
+static void __exit r6040_cleanup (void)
+{
+	pci_unregister_driver (&r6040_driver);
+}
+
+module_init(r6040_init);
+module_exit(r6040_cleanup);

^ permalink raw reply related

* Re: drivers/net/sunhme.c patch
From: David Miller @ 2007-10-29 22:10 UTC (permalink / raw)
  To: jengelh; +Cc: toms, linux-kernel, netdev
In-Reply-To: <Pine.LNX.4.64.0710291606260.26070@fbirervta.pbzchgretzou.qr>

From: Jan Engelhardt <jengelh@computergmbh.de>
Date: Mon, 29 Oct 2007 16:11:18 +0100 (CET)

> 
> On Oct 29 2007 08:54, Tom Southerland wrote:
> >
> > This patch provides a unique mac address for all interfaces
> > for the Sun QFE card (non-sparc).  It takes the base mac from
> > the first interface and increments the mac address for the
> > other interfaces.
> 
> Where is the difference to a SPARC QFE? PCI is PCI after all, is not it?

This is exactly why I wish this patch had been posted to
netdev@vger.kernel.org, now we have a dialogue going and even if I add
netdev to the CC: now, you can't follow it completely as a netdev
subscriber without going to the lkml archives.

To answer the question, yes it is just a normal PCI device, they put 4
HME chips behind a PCI bridge.  However, the OpenFirmware on the cards
usually creates device node properties for these PCI devices for the
local ethernet addresses.  That's what he's trying to duplicate here.

^ permalink raw reply

* Re: drivers/net/sunhme.c patch
From: Jan Engelhardt @ 2007-10-29 22:12 UTC (permalink / raw)
  To: David Miller; +Cc: toms, linux-kernel, netdev
In-Reply-To: <20071029.151025.87460351.davem@davemloft.net>


On Oct 29 2007 15:10, David Miller wrote:
>> On Oct 29 2007 08:54, Tom Southerland wrote:
>> >
>> > This patch provides a unique mac address for all interfaces
>> > for the Sun QFE card (non-sparc).  It takes the base mac from
>> > the first interface and increments the mac address for the
>> > other interfaces.
>> 
>> Where is the difference to a SPARC QFE? PCI is PCI after all, is not it?
>
>To answer the question, yes it is just a normal PCI device, they put 4
>HME chips behind a PCI bridge.  However, the OpenFirmware on the cards
>usually creates device node properties for these PCI devices for the
>local ethernet addresses.  That's what he's trying to duplicate here.
>
The question was more like: if I put in a QFE (that was acquired together
with a SUN E250) into x86, would I get duplicate MACs? (Would be strange -
I would have supposed the OF on the card is independent.)


^ permalink raw reply

* Re: Configuring the same IP on multiple addresses
From: David Miller @ 2007-10-29 22:25 UTC (permalink / raw)
  To: vladislav.yasevich; +Cc: netdev
In-Reply-To: <47262079.90507@hp.com>

From: Vlad Yasevich <vladislav.yasevich@hp.com>
Date: Mon, 29 Oct 2007 14:03:37 -0400

> So, I am looking for technical reasons why this is permitted.

I am looking for a technical reason why you find a need
to discover this feature and want the remove it :-)

Can you guys please just state upfront what virtualization
issue is made more difficult by features you want to remove?

That will make things go a lot more smoothly, thanks.

^ permalink raw reply

* Re: [bug, 2.6.24-rc1] sysfs: duplicate filename 'eth0' can not be created
From: David Miller @ 2007-10-29 22:36 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel, netdev, jgarzik
In-Reply-To: <20071029211746.GA19876@elte.hu>

From: Ingo Molnar <mingo@elte.hu>
Date: Mon, 29 Oct 2007 22:17:46 +0100

> 
> hm, this seems to have popped up in the last few days, never had it 
> before:
> 
>   sysfs: duplicate filename 'eth0' can not be created
>   WARNING: at fs/sysfs/dir.c:424 sysfs_add_one()

I checked in a change from Stephen Hemminger last week which
should keep this case from emitting warning messages.

commit c8d90dca3211966ba5189e0f3d4bccd558d9ae08
Author: Stephen Hemminger <shemminger@linux-foundation.org>
Date:   Fri Oct 26 03:53:42 2007 -0700

    [NET] dev_change_name: ignore changes to same name
    
    Prevent error/backtrace from dev_rename() when changing
    name of network device to the same name. This is a common
    situation with udev and other scripts that bind addr to device.
    
    Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
    Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/net/core/dev.c b/net/core/dev.c
index f1647d7..ddfef3b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -883,6 +883,9 @@ int dev_change_name(struct net_device *dev, char *newname)
 	if (!dev_valid_name(newname))
 		return -EINVAL;
 
+	if (strncmp(newname, dev->name, IFNAMSIZ) == 0)
+		return 0;
+
 	memcpy(oldname, dev->name, IFNAMSIZ);
 
 	if (strchr(newname, '%')) {

^ permalink raw reply related

* Re: [PATCH] inet: race in wait for connect.
From: David Miller @ 2007-10-29 22:38 UTC (permalink / raw)
  To: shemminger; +Cc: acme, netdev
In-Reply-To: <20071029143714.152e0431@freepuppy.rosehill>

From: Stephen Hemminger <shemminger@linux-foundation.org>
Date: Mon, 29 Oct 2007 14:37:14 -0700

> On Mon, 29 Oct 2007 19:29:06 -0200
> "Arnaldo Carvalho de Melo" <acme@redhat.com> wrote:
> 
> > Em Mon, Oct 29, 2007 at 01:52:22PM -0700, Stephen Hemminger escreveu:
> > > Fix possible race while waiting for connections in accept. I don't
> > > know of a test case that could reproduce this directly.
> > > 
> > > The state of the socket should be checked before checking the queue.
> > > If the socket has left the TCP_LISTEN state, then the accept queue
> > > is no longer valid.
> > 
> > Well if it left from LISTEN to CLOSED inet_csk_listen_stop must have
> > been called, and that calls reqsk_queue_yank_acceptq, that sets it to
> > NULL, reqsk_queue_empty(&icsk->icsk_accept_queue) returns true and we
> > get to if (sk->sk_state != TCP_LISTEN), returning -EINVAL as with your
> > patch.  So I can't see a race, just one branch less in one case :-)
> > 
> > - Arnaldo
> 
> Yeah, your right. The listen queue is garbage at this point but the
> accept queue is always empty.

Is there some failing test case you are aware of which led
you to this piece of code or did you happen to notice it
while scanning around?

^ permalink raw reply

* Re: [PATCH] pegasos_eth.c: Fix compile error over MV643XX_ defines
From: Dale Farnsworth @ 2007-10-29 22:39 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: netdev, linuxppc-dev, Jeff Garzik, Lennert Buytenhek,
	Tzachi Perelstein, Dale Farnsworth
In-Reply-To: <20071029212729.GA4074@pogo>

On Mon, Oct 29, 2007 at 05:27:29PM -0400, Luis R. Rodriguez wrote:
> This commit made an incorrect assumption:
> --
> Author: Lennert Buytenhek <buytenh@wantstofly.org>
>  Date:   Fri Oct 19 04:10:10 2007 +0200
> 
>     mv643xx_eth: Move ethernet register definitions into private header
>     
>     Move the mv643xx's ethernet-related register definitions from
>     include/linux/mv643xx.h into drivers/net/mv643xx_eth.h, since
>     they aren't of any use outside the ethernet driver.
>     
>     Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
>     Acked-by: Tzachi Perelstein <tzachi@marvell.com>
>     Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
> --
> 
> arch/powerpc/platforms/chrp/pegasos_eth.c made use of a 3 defines there.
> 
> mcgrof@pogo:~/devel/wireless-2.6$ git-describe 
> 
> v2.6.24-rc1-138-g0119130
> 
> This patch fixes this by internalizing 3 defines onto pegasos which are
> simply no longer available elsewhere. Without this your compile will fail

That compile failure was fixed in commit
30e69bf4cce16d4c2dcfd629a60fcd8e1aba9fee by Al Viro.

However, as I examine that commit, I see that it defines offsets from
the eth block in the chip, rather than the full chip registeri block
as the Pegasos 2 code expects.  So, I think it fixes the compile
failure, but leaves the Pegasos 2 broken.

Luis, do you have Pegasos 2 hardware?  Can you (or anyone) verify that
the following patch is needed for the Pegasos 2?

Thanks,
-Dale

---------------------------------

mv643xx_eth: Fix MV643XX_ETH offsets used by Pegasos 2

In the mv643xx_eth driver, we now use offsets from the ethernet
register block within the chip, but the pegasos 2 platform still
needs offsets from the full chip's register base address.

Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
---
 include/linux/mv643xx_eth.h |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h
index 8df230a..30e11aa 100644
--- a/include/linux/mv643xx_eth.h
+++ b/include/linux/mv643xx_eth.h
@@ -8,9 +8,9 @@
 #define MV643XX_ETH_NAME		"mv643xx_eth"
 #define MV643XX_ETH_SHARED_REGS		0x2000
 #define MV643XX_ETH_SHARED_REGS_SIZE	0x2000
-#define MV643XX_ETH_BAR_4	0x220
-#define MV643XX_ETH_SIZE_REG_4	0x224
-#define MV643XX_ETH_BASE_ADDR_ENABLE_REG	0x0290
+#define MV643XX_ETH_BAR_4		0x2220
+#define MV643XX_ETH_SIZE_REG_4		0x2224
+#define MV643XX_ETH_BASE_ADDR_ENABLE_REG	0x2290
 
 struct mv643xx_eth_platform_data {
 	int		port_number;

^ permalink raw reply related

* Re: drivers/net/sunhme.c patch
From: David Miller @ 2007-10-29 22:41 UTC (permalink / raw)
  To: jengelh; +Cc: toms, linux-kernel, netdev
In-Reply-To: <Pine.LNX.4.64.0710292311070.32301@fbirervta.pbzchgretzou.qr>

From: Jan Engelhardt <jengelh@computergmbh.de>
Date: Mon, 29 Oct 2007 23:12:25 +0100 (CET)

> The question was more like: if I put in a QFE (that was acquired together
> with a SUN E250) into x86, would I get duplicate MACs? (Would be strange -
> I would have supposed the OF on the card is independent.)

You are not supposed to.  Each HME instance should get a unique
MAC.

Normally OF would propagate this information around to the independant
device nodes, and we should try to preserve this behavior for non-OF
systems.

^ permalink raw reply

* Re: Configuring the same IP on multiple addresses
From: David Miller @ 2007-10-29 22:42 UTC (permalink / raw)
  To: vladislav.yasevich; +Cc: netdev
In-Reply-To: <20071029.152559.174870963.davem@davemloft.net>

From: David Miller <davem@davemloft.net>
Date: Mon, 29 Oct 2007 15:25:59 -0700 (PDT)

> Can you guys please just state upfront what virtualization
> issue is made more difficult by features you want to remove?

Sorry, I mentioned "virtualization" because that's been the
largest majority of the cases being presented lately.

I suspect in your case it's some multicast or SCTP thing :-)

^ permalink raw reply

* Re: [PATCH] pegasos_eth.c: Fix compile error over MV643XX_ defines
From: Lennert Buytenhek @ 2007-10-29 22:47 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: netdev, linuxppc-dev, Jeff Garzik, Tzachi Perelstein,
	Dale Farnsworth
In-Reply-To: <20071029212729.GA4074@pogo>

On Mon, Oct 29, 2007 at 05:27:29PM -0400, Luis R. Rodriguez wrote:

> This commit made an incorrect assumption:
> --
> Author: Lennert Buytenhek <buytenh@wantstofly.org>
>  Date:   Fri Oct 19 04:10:10 2007 +0200
> 
>     mv643xx_eth: Move ethernet register definitions into private header
>     
>     Move the mv643xx's ethernet-related register definitions from
>     include/linux/mv643xx.h into drivers/net/mv643xx_eth.h, since
>     they aren't of any use outside the ethernet driver.
>     
>     Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
>     Acked-by: Tzachi Perelstein <tzachi@marvell.com>
>     Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
> --
> 
> arch/powerpc/platforms/chrp/pegasos_eth.c made use of a 3 defines there.
> 
> mcgrof@pogo:~/devel/wireless-2.6$ git-describe 
> 
> v2.6.24-rc1-138-g0119130
> 
> This patch fixes this by internalizing 3 defines onto pegasos which are
> simply no longer available elsewhere. Without this your compile will fail
> whenever you enable 'Common Hardware Reference Platform (CHRP) based machines',
>
> [...]
> 
> diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c
> index 5bcc58d..1fc9e8c 100644
> --- a/arch/powerpc/platforms/chrp/pegasos_eth.c
> +++ b/arch/powerpc/platforms/chrp/pegasos_eth.c
> @@ -24,6 +24,9 @@
>  #define PEGASOS2_SRAM_BASE_ETH0			(PEGASOS2_SRAM_BASE)
>  #define PEGASOS2_SRAM_BASE_ETH1			(PEGASOS2_SRAM_BASE_ETH0 + (PEGASOS2_SRAM_SIZE / 2) )
>  
> +#define PEGASOS2_ETH_BAR_4			0x2220
> +#define PEGASOS2_ETH_SIZE_REG_4			0x2224
> +#define PEGASOS2_ETH_BASE_ADDR_ENABLE_REG	0x2290
>  
>  #define PEGASOS2_SRAM_RXRING_SIZE		(PEGASOS2_SRAM_SIZE/4)
>  #define PEGASOS2_SRAM_TXRING_SIZE		(PEGASOS2_SRAM_SIZE/4)
> @@ -147,13 +150,13 @@ static int Enable_SRAM(void)
>  
>  	ALong = 0x02;
>  	ALong |= PEGASOS2_SRAM_BASE & 0xffff0000;
> -	MV_WRITE(MV643XX_ETH_BAR_4, ALong);
> +	MV_WRITE(PEGASOS2_ETH_BAR_4, ALong);
>  
> -	MV_WRITE(MV643XX_ETH_SIZE_REG_4, (PEGASOS2_SRAM_SIZE-1) & 0xffff0000);
> +	MV_WRITE(PEGASOS2_ETH_SIZE_REG_4, (PEGASOS2_SRAM_SIZE-1) & 0xffff0000);
>  
> -	MV_READ(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
> +	MV_READ(PEGASOS2_ETH_BASE_ADDR_ENABLE_REG, ALong);
>  	ALong &= ~(1 << 4);
> -	MV_WRITE(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
> +	MV_WRITE(PEGASOS2_ETH_BASE_ADDR_ENABLE_REG, ALong);
>  
>  #ifdef BE_VERBOSE
>  	printk("Pegasos II/Marvell MV64361: register unmapped\n");

Al Viro sent a patch for this breakage a couple of days ago:

	http://marc.info/?l=linux-kernel&m=119351541706811&w=2

(FWIW, I think that code outside of mv643xx_eth.c should not be poking
into the mv643xx's registers directly.  Ideally, this info should just
be passed by pegasos_eth into mv643xx_eth via platform data, and then
mv643xx_eth can write the relevant hardware registers.)

^ permalink raw reply

* Re: [PATCH] inet: race in wait for connect.
From: Stephen Hemminger @ 2007-10-29 23:16 UTC (permalink / raw)
  To: David Miller; +Cc: acme, netdev
In-Reply-To: <20071029.153842.226361489.davem@davemloft.net>

On Mon, 29 Oct 2007 15:38:42 -0700 (PDT)
David Miller <davem@davemloft.net> wrote:

> From: Stephen Hemminger <shemminger@linux-foundation.org>
> Date: Mon, 29 Oct 2007 14:37:14 -0700
> 
> > On Mon, 29 Oct 2007 19:29:06 -0200
> > "Arnaldo Carvalho de Melo" <acme@redhat.com> wrote:
> > 
> > > Em Mon, Oct 29, 2007 at 01:52:22PM -0700, Stephen Hemminger escreveu:
> > > > Fix possible race while waiting for connections in accept. I don't
> > > > know of a test case that could reproduce this directly.
> > > > 
> > > > The state of the socket should be checked before checking the queue.
> > > > If the socket has left the TCP_LISTEN state, then the accept queue
> > > > is no longer valid.
> > > 
> > > Well if it left from LISTEN to CLOSED inet_csk_listen_stop must have
> > > been called, and that calls reqsk_queue_yank_acceptq, that sets it to
> > > NULL, reqsk_queue_empty(&icsk->icsk_accept_queue) returns true and we
> > > get to if (sk->sk_state != TCP_LISTEN), returning -EINVAL as with your
> > > patch.  So I can't see a race, just one branch less in one case :-)
> > > 
> > > - Arnaldo
> > 
> > Yeah, your right. The listen queue is garbage at this point but the
> > accept queue is always empty.
> 
> Is there some failing test case you are aware of which led
> you to this piece of code or did you happen to notice it
> while scanning around?

While instrumenting the snot out of accept logic for looking at alternatives
to the MT-accept vs. close issue.

-- 
Stephen Hemminger <shemminger@linux-foundation.org>

^ permalink raw reply

* Re: [PATCH 1/2] [CRYPTO] tcrypt: Move sg_init_table out of timing loops
From: Herbert Xu @ 2007-10-30  0:08 UTC (permalink / raw)
  To: Jens Axboe
  Cc: David S. Miller, Linux Kernel Mailing List,
	Linux Crypto Mailing List, netdev
In-Reply-To: <20071029201627.GD7499@kernel.dk>

On Mon, Oct 29, 2007 at 09:16:27PM +0100, Jens Axboe wrote:
> On Fri, Oct 26 2007, Herbert Xu wrote:
> > [CRYPTO] tcrypt: Move sg_init_table out of timing loops
> > 
> > This patch moves the sg_init_table out of the timing loops for hash
> > algorithms so that it doesn't impact on the speed test results.
> 
> Wouldn't it be better to just make sg_init_one() call sg_init_table?

This looks fine to me although I think it's orthogonal to the
patch you were quoting :)

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Fwd: Bug with tun0 and VLAN
From: Bruno Clermont @ 2007-10-30  1:11 UTC (permalink / raw)
  To: netdev
In-Reply-To: <47267AEB.90506@qualcomm.com>

Hi,

I previously contacted tun driver maintainer about a bug I found and
he suggested me to forward this to you.
so, look like there is a bug in the kernel when the VLAN code is
dealing with an interface like the tun interface.

see forwarded my original mail and Max reply.

thanks!

---------- Forwarded message ----------
From: Max Krasnyansky <maxk@qualcomm.com>
Date: Oct 29, 2007 8:29 PM
Subject: Re: Bug with tun0 and VLAN
To: Bruno Clermont <bruno.clermont@gmail.com>

Hi Bruno,

> Hi,
>
> I'm writing to you, because you seem to be the maintainer of the tun driver.
>
> I hit a bug lately. I was testing this scenario:
>
> [Server1][eth0]-------(Internet)----------[eth0][Server2]
>
> I want to be able to route traffic for many VLAN into a single tunnel
> instead of invoking 1 openvpn process per VLAN. so, I tried to add VLAN
> to tun interface.
>
> I create an OpenVPN tunnel between Server1 and 2, this part work. the
> tun0 is going up. I use heavily openvpn and I'm sure of me on this part.
> I made sure openvpn did not set any IP on the tunnel.
>
> So, I added the vlan to the tun interface on both server:
>
> ifconfig tun0 up
> vconfig add tun0 1
> vconfig add tun1 2
>
> on server1:
> ifconfig tun0.1 10.0.0.1 <http://10.0.0.1> netmask 255.255.255.0
> <http://255.255.255.0> up
> ifconfig tun0.1 10.0.1.1 <http://10.0.1.1> netmask 255.255.255.0
> <http://255.255.255.0> up
>
> on server2:
> ifconfig tun0.1 10.0.0.2 <http://10.0.0.2> netmask 255.255.255.0
> <http://255.255.255.0> up
> ifconfig tun0.1 10.0.1.2 <http://10.0.1.2> netmask 255.255.255.0
> <http://255.255.255.0> up
>
> Trying to ping the other end of the tun/vlan make the kernel panic on
> the host that try to ping.
> I tried on Ubuntu Feisty and Gutsy (2.6.22) and they both crash.
>
> I tried it severals times on different host and it seem that combining
> VLAN and tun interface crash the kernel.
> it's easy to reproduce.
>
> Is it a tun driver issue? VLAN code issue? some other part of the
> kernel? I don't know.
>
> your my first attempt of communication for this issue... If it's not
> supported, at least the kernel should not panic!

Actually TUN is a point to point device, it does not have Ethernet MAC
headers. In other words VLANs would never work over TUN.
I agree though that it should not crash. So it's better to report this to
netdev mailing list. Basically VLAN code should outright refuse to attach
to TUN devices.

Max

^ permalink raw reply

* drivers/net/sunhme.c patch
From: Tom Southerland @ 2007-10-30  1:53 UTC (permalink / raw)
  To: netdev

This patch provides a unique mac address for all interfaces
for the Sun QFE card (non-sparc).  It takes the base mac from
the first interface and increments the mac address for the
other interfaces.

It still preserves the 'macaddr' parameter so if desired, it
can still be used.

Before patching:

eth0      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BB
eth1      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BB
eth2      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BB
eth3      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BB

After patching:

eth0      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BB
eth1      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BC
eth2      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BD
eth3      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BE

Cheers,

Tom



--- linux-2.6.23.1/drivers/net/sunhme.c.orig    2007-10-29 07:58:25.000000000 -0600
+++ linux-2.6.23.1/drivers/net/sunhme.c 2007-10-29 08:53:03.000000000 -0600
@@ -3083,6 +3083,11 @@ static int __devinit happy_meal_pci_prob
                 }
  #else
                 get_hme_mac_nonsparc(pdev, &dev->dev_addr[0]);
+                if(macaddr[5] == 0){
+                 for (i = 0; i < 6; i++)
+                       macaddr[i] = dev->dev_addr[i];
+                 macaddr[5]++;
+                }
  #endif
         }



^ permalink raw reply

* Re: drivers/net/sunhme.c patch
From: David Miller @ 2007-10-30  3:12 UTC (permalink / raw)
  To: toms; +Cc: netdev
In-Reply-To: <47268EB0.5030703@wonderland.us.com>

From: Tom Southerland <toms@wonderland.us.com>
Date: Mon, 29 Oct 2007 19:53:52 -0600

> This patch provides a unique mac address for all interfaces
> for the Sun QFE card (non-sparc).  It takes the base mac from
> the first interface and increments the mac address for the
> other interfaces.
> 
> It still preserves the 'macaddr' parameter so if desired, it
> can still be used.
> 
> Before patching:
> 
> eth0      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BB
> eth1      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BB
> eth2      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BB
> eth3      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BB
> 
> After patching:
> 
> eth0      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BB
> eth1      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BC
> eth2      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BD
> eth3      Link encap:Ethernet  HWaddr 00:03:BA:17:4C:BE

Unfortunately, although I understand what you're trying to do,
this change is not correct.

We obtain properly the local-mac-address property stored in
the PCI ROM of each interface, and if you look at the code
we look the MACs up by interface index.

So we are (or should be) obtaining the per-interface MAC
address programmed into the onboard firmware.

Perhaps in get_hme_mac_nonsparc(), is_quattro_p() is evaluating
false and therefore we mistakedly always use index 0?

Could you please check this?  That's probably what the problem
is.

^ permalink raw reply

* Re: Configuring the same IP on multiple addresses
From: Brian Haley @ 2007-10-30  4:23 UTC (permalink / raw)
  To: David Miller; +Cc: vladislav.yasevich, netdev
In-Reply-To: <20071029.154258.39630263.davem@davemloft.net>

David Miller wrote:
> From: David Miller <davem@davemloft.net>
> Date: Mon, 29 Oct 2007 15:25:59 -0700 (PDT)
> 
>> Can you guys please just state upfront what virtualization
>> issue is made more difficult by features you want to remove?
> 
> Sorry, I mentioned "virtualization" because that's been the
> largest majority of the cases being presented lately.
> 
> I suspect in your case it's some multicast or SCTP thing :-)

It's actually neither in this case :)

We have customers migrating from BSD stacks to Linux.  They notice all 
the differences in the sockets API, sometimes even find bugs, and we fix 
them and send patches upstream.  They also do stupid things like 
duplicate address configurations on two interfaces in different subnets.

IPv6 was the curious one for us here since it falls into an RFC gray 
area - addresses are assigned to interfaces, not hosts (RFC 4291), but 
they should be tested for uniqueness before being assigned (RFC 4862). 
This address didn't pass the uniqueness test, although it did pass DAD 
because the links were different.  We couldn't find another OS for a 
host or router (including IOS) that allows this, hence the question.

Thanks, and sorry if it's just another waste of your time to explain it.

-Brian

^ permalink raw reply

* Re: [patch] net: avoid race between netpoll and network fast path
From: David Miller @ 2007-10-30  4:26 UTC (permalink / raw)
  To: tina.yang; +Cc: mpm, netdev
In-Reply-To: <4715A1B6.5020300@oracle.com>

From: Tina Yang <tina.yang@oracle.com>
Date: Tue, 16 Oct 2007 22:46:30 -0700

> 	The precise race is
> 	1) net_rx_action get the dev from poll_list
> 	2) at the same time, netpoll poll_napi() get a hold of the poll lock
> 	   and calls ->poll(), remove dev from the poll list
> 	3) after it finishes, net_rx_action get the poll lock, and calls
> 	   ->poll() the second time, and panic when trying to remove (again)
> 	   the dev from the poll list.

This is trivial to fix.

I'll check the following into 2.6.14 and backport it to
the -stable trees.

[NET]: Fix race between poll_napi() and net_rx_action()

netpoll_poll_lock() synchronizes the ->poll() invocation
code paths, but once we have the lock we have to make
sure that NAPI_STATE_SCHED is still set.  Otherwise we
get:

	cpu 0			cpu 1

	net_rx_action()		poll_napi()
	netpoll_poll_lock()	... spin on ->poll_lock
	->poll()
	  netif_rx_complete
	netpoll_poll_unlock()	acquire ->poll_lock()
				->poll()
				 netif_rx_complete()
				 CRASH

Based upon a bug report from Tina Yang.

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

diff --git a/net/core/dev.c b/net/core/dev.c
index 853c8b5..02e7d83 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2172,7 +2172,15 @@ static void net_rx_action(struct softirq_action *h)
 
 		weight = n->weight;
 
-		work = n->poll(n, weight);
+		/* This NAPI_STATE_SCHED test is for avoiding a race
+		 * with netpoll's poll_napi().  Only the entity which
+		 * obtains the lock and sees NAPI_STATE_SCHED set will
+		 * actually make the ->poll() call.  Therefore we avoid
+		 * accidently calling ->poll() when NAPI is not scheduled.
+		 */
+		work = 0;
+		if (test_bit(NAPI_STATE_SCHED, &n->state))
+			work = n->poll(n, weight);
 
 		WARN_ON_ONCE(work > weight);
 
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index bf8d18f..c499b5c 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -116,6 +116,29 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh,
  * network adapter, forcing superfluous retries and possibly timeouts.
  * Thus, we set our budget to greater than 1.
  */
+static int poll_one_napi(struct netpoll_info *npinfo,
+			 struct napi_struct *napi, int budget)
+{
+	int work;
+
+	/* net_rx_action's ->poll() invocations and our's are
+	 * synchronized by this test which is only made while
+	 * holding the napi->poll_lock.
+	 */
+	if (!test_bit(NAPI_STATE_SCHED, &napi->state))
+		return budget;
+
+	npinfo->rx_flags |= NETPOLL_RX_DROP;
+	atomic_inc(&trapped);
+
+	work = napi->poll(napi, budget);
+
+	atomic_dec(&trapped);
+	npinfo->rx_flags &= ~NETPOLL_RX_DROP;
+
+	return budget - work;
+}
+
 static void poll_napi(struct netpoll *np)
 {
 	struct netpoll_info *npinfo = np->dev->npinfo;
@@ -123,17 +146,13 @@ static void poll_napi(struct netpoll *np)
 	int budget = 16;
 
 	list_for_each_entry(napi, &np->dev->napi_list, dev_list) {
-		if (test_bit(NAPI_STATE_SCHED, &napi->state) &&
-		    napi->poll_owner != smp_processor_id() &&
+		if (napi->poll_owner != smp_processor_id() &&
 		    spin_trylock(&napi->poll_lock)) {
-			npinfo->rx_flags |= NETPOLL_RX_DROP;
-			atomic_inc(&trapped);
-
-			napi->poll(napi, budget);
-
-			atomic_dec(&trapped);
-			npinfo->rx_flags &= ~NETPOLL_RX_DROP;
+			budget = poll_one_napi(npinfo, napi, budget);
 			spin_unlock(&napi->poll_lock);
+
+			if (!budget)
+				break;
 		}
 	}
 }


^ permalink raw reply related

* Re: [PATCH 2/2] NFS: handle IPv6 addresses in nfs ctl
From: Neil Brown @ 2007-10-30  4:35 UTC (permalink / raw)
  To: Aurélien Charbon; +Cc: Mailing list NFSv4, netdev ML
In-Reply-To: <471C893F.6000306@ext.bull.net>

On Monday October 22, aurelien.charbon@ext.bull.net wrote:
> Here is a second missing part of the IPv6 support in NFS server code 
> concerning knfd syscall interface.
> It updates write_getfd and write_getfd to accept IPv6 addresses.

Sorry for not replying to this earlier - I saw the Oct 12 post and
thought about it but didn't actually reply before getting distracted
:-(

I think this patch is unnecessary and hence not wanted.
The getfs / getfs calls should be considered legacy calls.
Adding functionality to them is not appropriate.

IPv6 addresses should be handled only via the
   /proc/net/rpc/auth.unix.ip 
interface.

Thanks,
NeilBrown

^ permalink raw reply

* Re: [PATCH 5/5] introduce udp_rmem and udp_wmem
From: Bill Fink @ 2007-10-30  4:52 UTC (permalink / raw)
  To: Hideo AOKI
  Cc: David Miller, netdev, Satoshi Oshima, Herbert Xu, Andi Kleen,
	Stephen Hemminger, Evgeniy Polyakov, yoshfuji, Yumiko Sugita
In-Reply-To: <47264F5F.6040905@redhat.com>

On Mon, 29 Oct 2007, Hideo AOKI wrote:

> This patch added /proc/sys/net/udp_rmem and /proc/sys/net/udp_rmem.
> Each UDP packet is drooped when the number of pages for socket buffer
> is beyond the limit and the socket already consumes minimum buffer.

I think you meant /proc/sys/net/ipv4/udp_{r,w}mem above.

Patch not in-lined making replying more difficult.

Cutting and pasting:

> diff -pruN linux-2.6.24-rc1-mem003-ipv4-dev-p4/Documentation/networking/ip-sysctl.txt linux-2.6.24-rc1-mem003-ipv4-dev-p5/Documentation/networking/ip-sysctl.txt
> --- linux-2.6.24-rc1-mem003-ipv4-dev-p4/Documentation/networking/ip-sysctl.txt	2007-10-26 20:35:52.000000000 -0400
> +++ linux-2.6.24-rc1-mem003-ipv4-dev-p5/Documentation/networking/ip-sysctl.txt	2007-10-29 09:44:05.000000000 -0400
> @@ -452,6 +452,18 @@ udp_mem - INTEGER
>  	Number of pages allowed for queueing by all UDP sockets.
>  	Default is calculated at boot time from amount of available memory.
>  
> +udp_rmem - INTEGER
> +	Minimal size of receive buffer used by UDP sockets. Each UDP socket
> +	is able to use the size for receiving data, even if total pages of UDP
> +	sockets exceed udp_mem. The unit is byte.
> +	Default: 4096
> +
> +udp_wmem - INTEGER
> +	Minimal size of send buffer used by UDP sockets. Each UDP socket is
> +	able to use the size for sending data, even if total pages of UDP
> +	sockets exceed udp_mem. The unit is byte.
> +	Default: 4096
> +
>  CIPSOv4 Variables:
>  
>  cipso_cache_enable - BOOLEAN

I think either the above should be renamed to udp_{r,w}mem_min, or
they should be changed to a 3-tuple like tcp_{r,w}mem, and the code
refactored accordingly (but then what to do about
/proc/sys/net/core/{r,w}mem_max).

						-Bill

^ permalink raw reply

* Re: BUG in sys_socketpair
From: David Miller @ 2007-10-30  4:55 UTC (permalink / raw)
  To: cebbert; +Cc: socketpair_bug, netdev, linux-kernel, viro
In-Reply-To: <4720E424.7060509@redhat.com>

From: Chuck Ebbert <cebbert@redhat.com>
Date: Thu, 25 Oct 2007 14:44:52 -0400

> On 10/25/2007 10:11 AM, Rich Paul wrote:
> > In 2.6.23, there seems to be a minor bug in sys_socketpair.  When the
> > calls to sock_alloc_fd fail, it aborts the routine, but it returns the
> > variable err, which is not set in this case.
> > 
> > The result is a silent failure if you have too many files open and call
> > socketpair.
> > 
> > Here is a simple UNTESTED patch (not even compiled) which should resolve the
> > issue.
> > 
> > 
> > --- net/socket.c.orig   2007-10-25 10:03:56.000000000 -0400
> > +++ net/socket.c        2007-10-25 10:04:00.000000000 -0400
> Should be "err = fd1" (spaces), otherwise looks good.
> 
> Original did:
> 
> 	err = sock_map_fd(sock1);
> 	if (err < 0)
> 		goto out_release_both;
> 	fd1 = err;

Thanks everyone, I'll commit the following both to 2.6.x GIT
and -stable.

>From 42f3fc7e989554e9952bdf28af137e4e4570f067 Mon Sep 17 00:00:00 2001
From: David S. Miller <davem@sunset.davemloft.net>
Date: Mon, 29 Oct 2007 21:54:02 -0700
Subject: [PATCH] [NET]: Fix error reporting in sys_socketpair().

If either of the two sock_alloc_fd() calls fail, we
forget to update 'err' and thus we'll erroneously
return zero in these cases.

Based upon a report and patch from Rich Paul, and
commentary from Chuck Ebbert.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/socket.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 540013e..5d879fd 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1250,11 +1250,14 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
 		goto out_release_both;
 
 	fd1 = sock_alloc_fd(&newfile1);
-	if (unlikely(fd1 < 0))
+	if (unlikely(fd1 < 0)) {
+		err = fd1;
 		goto out_release_both;
+	}
 
 	fd2 = sock_alloc_fd(&newfile2);
 	if (unlikely(fd2 < 0)) {
+		err = fd2;
 		put_filp(newfile1);
 		put_unused_fd(fd1);
 		goto out_release_both;
-- 
1.5.2.5


^ permalink raw reply related

* Re: MD5 signature pool race bug?
From: David Miller @ 2007-10-30  5:01 UTC (permalink / raw)
  To: shemminger; +Cc: yoshfuji, netdev
In-Reply-To: <20071025113612.2ea69262@freepuppy.rosehill>

From: Stephen Hemminger <shemminger@linux-foundation.org>
Date: Thu, 25 Oct 2007 11:36:12 -0700

> Looking at this bug report:
> 	http://bugzilla.kernel.org/show_bug.cgi?id=9173
 ...
> It looks like there may be a race between the tricky allocate per-cpu pool
> and free-per-cpu pool logic.  IMHO the pool management code is more complex
> than it needs to be and may be the source of the bug. Couldn't the signature
> just use normal kmalloc/kfree and slab cache?

This bug was fixed by the patch below, please close this
bug.

Thanks!

commit 2c4f6219aca5939b57596278ea8b014275d4917b
Author: David S. Miller <davem@sunset.davemloft.net>
Date:   Tue Feb 20 23:51:47 2007 -0800

    [TCP]: Fix MD5 signature pool locking.
    
    The locking calls assumed that these code paths were only
    invoked in software interrupt context, but that isn't true.
    
    Therefore we need to use spin_{lock,unlock}_bh() throughout.
    
    Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index ac6516c..74c4d10 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2266,12 +2266,12 @@ void tcp_free_md5sig_pool(void)
 {
 	struct tcp_md5sig_pool **pool = NULL;
 
-	spin_lock(&tcp_md5sig_pool_lock);
+	spin_lock_bh(&tcp_md5sig_pool_lock);
 	if (--tcp_md5sig_users == 0) {
 		pool = tcp_md5sig_pool;
 		tcp_md5sig_pool = NULL;
 	}
-	spin_unlock(&tcp_md5sig_pool_lock);
+	spin_unlock_bh(&tcp_md5sig_pool_lock);
 	if (pool)
 		__tcp_free_md5sig_pool(pool);
 }
@@ -2314,36 +2314,36 @@ struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void)
 	int alloc = 0;
 
 retry:
-	spin_lock(&tcp_md5sig_pool_lock);
+	spin_lock_bh(&tcp_md5sig_pool_lock);
 	pool = tcp_md5sig_pool;
 	if (tcp_md5sig_users++ == 0) {
 		alloc = 1;
-		spin_unlock(&tcp_md5sig_pool_lock);
+		spin_unlock_bh(&tcp_md5sig_pool_lock);
 	} else if (!pool) {
 		tcp_md5sig_users--;
-		spin_unlock(&tcp_md5sig_pool_lock);
+		spin_unlock_bh(&tcp_md5sig_pool_lock);
 		cpu_relax();
 		goto retry;
 	} else
-		spin_unlock(&tcp_md5sig_pool_lock);
+		spin_unlock_bh(&tcp_md5sig_pool_lock);
 
 	if (alloc) {
 		/* we cannot hold spinlock here because this may sleep. */
 		struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool();
-		spin_lock(&tcp_md5sig_pool_lock);
+		spin_lock_bh(&tcp_md5sig_pool_lock);
 		if (!p) {
 			tcp_md5sig_users--;
-			spin_unlock(&tcp_md5sig_pool_lock);
+			spin_unlock_bh(&tcp_md5sig_pool_lock);
 			return NULL;
 		}
 		pool = tcp_md5sig_pool;
 		if (pool) {
 			/* oops, it has already been assigned. */
-			spin_unlock(&tcp_md5sig_pool_lock);
+			spin_unlock_bh(&tcp_md5sig_pool_lock);
 			__tcp_free_md5sig_pool(p);
 		} else {
 			tcp_md5sig_pool = pool = p;
-			spin_unlock(&tcp_md5sig_pool_lock);
+			spin_unlock_bh(&tcp_md5sig_pool_lock);
 		}
 	}
 	return pool;
@@ -2354,11 +2354,11 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
 struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu)
 {
 	struct tcp_md5sig_pool **p;
-	spin_lock(&tcp_md5sig_pool_lock);
+	spin_lock_bh(&tcp_md5sig_pool_lock);
 	p = tcp_md5sig_pool;
 	if (p)
 		tcp_md5sig_users++;
-	spin_unlock(&tcp_md5sig_pool_lock);
+	spin_unlock_bh(&tcp_md5sig_pool_lock);
 	return (p ? *per_cpu_ptr(p, cpu) : NULL);
 }
 

^ permalink raw reply related

* Re: [PATCH] [IPv4] SNMP: Refer correct memory location to display ICMP out-going statistics
From: David Miller @ 2007-10-30  5:03 UTC (permalink / raw)
  To: mitch; +Cc: netdev, dlstevens
In-Reply-To: <20071026105928.d56cd244.mitch@linux.vnet.ibm.com>

From: Mitsuru Chinen <mitch@linux.vnet.ibm.com>
Date: Fri, 26 Oct 2007 10:59:28 +0900

> While displaying ICMP out-going statistics as Out<name> counters in
> /proc/net/snmp, the memory location for ICMP in-coming statistics
> was referred by mistake.
> 
> Acked-by: David L Stevens <dlstevens@us.ibm.com> 
> Signed-off-by: Mitsuru Chinen <mitch@linux.vnet.ibm.com>

Patch applied, thank you!

^ 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