bk://gkernel.bkbits.net/netdev-2.6
jgarzik@pobox.com|ChangeSet|20041007034556|54749 jgarzik

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/10/08 11:54:04-07:00 akpm@bix.(none) 
#   Merge bk://gkernel.bkbits.net/netdev-2.6
#   into bix.(none):/usr/src/bk-netdev
# 
# drivers/usb/net/rtl8150.c
#   2004/10/08 11:53:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/net/pegasus.c
#   2004/10/08 11:53:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/net/kaweth.c
#   2004/10/08 11:53:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/net/catc.c
#   2004/10/08 11:53:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/wireless/prism54/islpci_dev.h
#   2004/10/08 11:53:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/10/08 11:53:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/wireless/prism54/isl_38xx.h
#   2004/10/08 11:53:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/wireless/prism54/isl_38xx.c
#   2004/10/08 11:53:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/defxx.c
#   2004/10/08 11:53:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/08 11:52:06-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev
# 
# drivers/media/dvb/dvb-core/dvb_net.c
#   2004/10/08 11:52:02-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/ieee1394/eth1394.c
#   2004/10/08 11:52:02-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# net/core/dev.c
#   2004/09/16 20:15:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# net/core/dev.c
#   2004/09/05 15:34:34-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# net/core/dev.c
#   2004/08/06 11:19:59-04:00 akpm@osdl.org +1 -1
#   wireless-extension-v17-for-linus.patch
# 
# ChangeSet
#   2004/10/06 23:45:56-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/acenic
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/usb/net/rtl8150.c
#   2004/10/06 23:45:52-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/usb/net/pegasus.c
#   2004/10/06 23:45:52-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/usb/net/kaweth.c
#   2004/10/06 23:45:52-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/usb/net/catc.c
#   2004/10/06 23:45:52-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/wireless/prism54/islpci_dev.h
#   2004/10/06 23:45:52-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/10/06 23:45:52-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/wireless/prism54/isl_38xx.h
#   2004/10/06 23:45:52-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/wireless/prism54/isl_38xx.c
#   2004/10/06 23:45:52-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/defxx.c
#   2004/10/06 23:45:52-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/06 23:44:56-04:00 akpm@osdl.org 
#   [PATCH] fix acenic hotplug
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   Now that the acenic has been converted to the hotplug API a number of uses
#   of __init and __initdata have to be changed to __devinit and __devinitdata.
#   
#   Acked-by: Jes Sorensen <jes@trained-monkey.org>
#   Signed-off-by: Anton Blanchard <anton@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/acenic_firmware.h
#   2004/10/05 02:28:48-04:00 akpm@osdl.org +1 -1
#   fix acenic hotplug
# 
# drivers/net/acenic.c
#   2004/10/05 02:30:43-04:00 akpm@osdl.org +10 -10
#   fix acenic hotplug
# 
# ChangeSet
#   2004/10/06 13:52:11-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev
# 
# drivers/usb/net/rtl8150.c
#   2004/10/06 13:52:08-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/net/pegasus.c
#   2004/10/06 13:52:08-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/net/kaweth.c
#   2004/10/06 13:52:08-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/usb/net/catc.c
#   2004/10/06 13:52:07-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/05 22:15:08-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev
# 
# drivers/net/wireless/prism54/islpci_dev.h
#   2004/10/05 22:15:04-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/10/05 22:15:04-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/wireless/prism54/isl_38xx.h
#   2004/10/05 22:15:04-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/wireless/prism54/isl_38xx.c
#   2004/10/05 22:15:04-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/net/defxx.c
#   2004/10/05 22:15:04-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/04 22:19:12-07:00 akpm@bix.(none) 
#   Merge bk://gkernel.bkbits.net/netdev-2.6
#   into bix.(none):/usr/src/bk-netdev
# 
# drivers/net/natsemi.c
#   2004/10/04 22:19:08-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/04 17:19:30-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/misc
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/ns83820.c
#   2004/10/04 17:19:26-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/04 17:17:08-04:00 nhorman@redhat.com 
#   [PATCH] ns83820: add vlan tag hardware acceleration support
#   
#   	I was poking about in the National Semi 83820 driver, and I happened to notice that the chip supports vlan tag add/strip assist in hardware, but the driver wasn't making use of it.  This patch adds in the driver support to use the vlan tag add/remove hardware, and enables the drivers use of the kernel vlan hwaccel interface.
#   
#   Signed-off-by: Neil Horman <nhorman@redhat.com>
# 
# drivers/net/ns83820.c
#   2004/10/01 09:29:04-04:00 nhorman@redhat.com +106 -6
#   ns83820: add vlan tag hardware acceleration support
# 
# ChangeSet
#   2004/10/04 16:56:49-04:00 margitsw@t-online.de 
#   [PATCH] prism54 bug initialization/mgt_commit
#   
#   *  Change mgt_commit from void to int
#   *  (and pass a return code)
#   *  We call this from device initialization,
#   *  therefore we need to know that it has succeeded
#   *  If it hasn't, we do not have a working device and
#   *  should pass a non-zero value upwards
# 
# drivers/net/wireless/prism54/oid_mgt.h
#   2004/10/02 09:01:41-04:00 margitsw@t-online.de +1 -1
#   prism54 bug initialization/mgt_commit
# 
# drivers/net/wireless/prism54/oid_mgt.c
#   2004/10/02 09:01:21-04:00 margitsw@t-online.de +3 -2
#   prism54 bug initialization/mgt_commit
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/10/02 09:04:56-04:00 margitsw@t-online.de +6 -1
#   prism54 bug initialization/mgt_commit
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/10/02 09:09:25-04:00 margitsw@t-online.de +8 -2
#   prism54 bug initialization/mgt_commit
# 
# ChangeSet
#   2004/10/04 16:56:36-04:00 margitsw@t-online.de 
#   [PATCH] prism54 print firmware version
#   
#   *  Print firmware version
#   *
#   *  As per convention, make errno return negative
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/09/25 06:03:58-04:00 margitsw@t-online.de +5 -1
#   prism54 print firmware version
# 
# ChangeSet
#   2004/10/04 16:56:21-04:00 margitsw@t-online.de 
#   [PATCH] prism54 Bug in timeout scheduling
#   
#   *  Bug in loop around schedule_timeout
#   *  We must rearm the task
#   *
#   *  Make timeout message meaningful
# 
# drivers/net/wireless/prism54/islpci_mgt.c
#   2004/10/02 06:27:10-04:00 margitsw@t-online.de +1 -0
#   prism54 Bug in timeout scheduling
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/10/02 06:26:51-04:00 margitsw@t-online.de +3 -2
#   prism54 Bug in timeout scheduling
# 
# ChangeSet
#   2004/10/04 16:56:09-04:00 margitsw@t-online.de 
#   [PATCH] prism54 remove TRACE
#   
#   *  Remove TRACE to please the janitors
# 
# drivers/net/wireless/prism54/islpci_mgt.h
#   2004/09/25 05:15:54-04:00 margitsw@t-online.de +0 -2
#   prism54 remove TRACE
# 
# drivers/net/wireless/prism54/islpci_hotplug.c
#   2004/09/25 05:15:41-04:00 margitsw@t-online.de +0 -3
#   prism54 remove TRACE
# 
# ChangeSet
#   2004/10/04 16:54:09-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/r8169
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/r8169.c
#   2004/10/04 16:54:06-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/04 16:51:57-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/janitor
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/tulip/tulip_core.c
#   2004/10/04 16:51:54-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/sis900.c
#   2004/10/04 16:51:54-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/natsemi.c
#   2004/10/04 16:51:54-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/04 16:51:14-04:00 sfeldma@pobox.com 
#   [PATCH] janitor: net/tulip: pci_find_device to pci_dev_present
#   
#   Replace pci_find_device with pci_dev_present.  Compile tested.
#   
#   Signed-off-by: Scott Feldman <sfeldma@pobox.com>
# 
# drivers/net/tulip/tulip_core.c
#   2004/10/03 01:01:22-04:00 sfeldma@pobox.com +12 -9
#   janitor: net/tulip: pci_find_device to pci_dev_present
# 
# ChangeSet
#   2004/10/04 16:51:01-04:00 sfeldma@pobox.com 
#   [PATCH] janitor: net/sis900: pci_find_device to pci_get_device
#   
#   Replace pci_find_device with pci_get_device/pci_dev_put to plug
#   race with pci_find_device.  Compile tested.
#   
#   Signed-off-by: Scott Feldman <sfeldma@pobox.com>
# 
# drivers/net/sis900.c
#   2004/10/03 00:29:07-04:00 sfeldma@pobox.com +10 -8
#   janitor: net/sis900: pci_find_device to pci_get_device
# 
# ChangeSet
#   2004/10/04 16:46:51-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: cleanup
#   
#   Cleanup
#   - timeout message is redundant with net/sched/sch_generic::dev_watchdog;
#   - anti-bloat in rtl8169_get_rx_csum;
#   - format fix.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
#   Signed-off-by: Jon Mason <jdmason@us.ibm.com>
# 
# drivers/net/r8169.c
#   2004/10/04 15:27:47-04:00 romieu@fr.zoreil.com +3 -5
#   r8169: cleanup
# 
# ChangeSet
#   2004/10/04 16:46:37-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: rtl8169_close() races
#   
#   - close the race with rtl8169_interrupt() which appears when rtl8169_close()
#     uses synchronize_irq()/free_irq();
#   - netif_poll_disable() allows rtl8169_close() to wait for any pending
#     rtl8169_poll() to complete so it can safely clear the rings.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/10/04 15:26:01-04:00 romieu@fr.zoreil.com +6 -0
#   r8169: rtl8169_close() races
# 
# ChangeSet
#   2004/10/04 16:46:24-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: automatic pci dac step down
#   
#   Automatic adjustement of highmem dma feature.
#   
#   The first interruption encountered on systems where the 8169 does not
#   perform PCI DAC correctly seems to always be a PCI error one.
#   When DAC is enabled, the driver tries to issue a complete down/up
#   sequence as an addition to the usual halt of the device.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/10/04 15:25:07-04:00 romieu@fr.zoreil.com +70 -7
#   r8169: automatic pci dac step down
# 
# ChangeSet
#   2004/10/04 16:46:10-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: wrong advertisement of VLAN features
#   
#   Removal of an advertisement for VLAN features which is redundant with
#   rtl8169_init_one().
#   
#   Signed-off-by: Jon Mason <jdmason@us.ibm.com>
# 
# drivers/net/r8169.c
#   2004/10/04 15:17:44-04:00 romieu@fr.zoreil.com +0 -2
#   r8169: wrong advertisement of VLAN features
# 
# ChangeSet
#   2004/10/04 16:45:56-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: Tx timeout rework
#   
#   Tx timeout rework:
#   - the ring descriptors of the chipset and the ring index of the driver
#     are synced during a reset of the device;
#   - rtl8169_interrupt: rtl8169_hw_reset() replaces the previous stop code.
#     An implicit reset of the device is added but it makes no noticeable
#     difference with the former behavior (i.e.: stop the chipset).
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/10/04 15:15:41-04:00 romieu@fr.zoreil.com +65 -24
#   r8169: Tx timeout rework
# 
# ChangeSet
#   2004/10/01 00:25:59-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/misc
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/ixgb/ixgb_main.c
#   2004/10/01 00:25:55-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/01 00:22:45-04:00 jesse.brandeburg@intel.com 
#   [PATCH] e100: whitespace and DPRINTKS
#   
#   This is a short patch to add a couple of new DPRINTKS and fix some
#   whitespace issues.
#   
#   Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
# 
# drivers/net/e100.c
#   2004/09/22 14:55:01-04:00 jesse.brandeburg@intel.com +6 -3
#   e100: whitespace and DPRINTKS
# 
# ChangeSet
#   2004/10/01 00:22:32-04:00 jesse.brandeburg@intel.com 
#   [PATCH] e100: fix NAPI race with watchdog
#   
#   While polling in NAPI mode, we were occassionally getting interrupts
#   re-enabled by the watchdog trying to generate a software interrupt.  Fix
#   is to add a spinlock around that shared hardware register to allow a
#   read-modify-write operation.  This was nasty nasty.  I don't like the
#   spinlock in the hot path but i see no other way.  Comments are welcome.
#   Updates the driver version as well.
#   
#   Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
# 
# drivers/net/e100.c
#   2004/09/22 14:49:05-04:00 jesse.brandeburg@intel.com +16 -3
#   e100: fix NAPI race with watchdog
# 
# ChangeSet
#   2004/10/01 00:20:57-04:00 jesse.brandeburg@intel.com 
#   [PATCH] ixgb: fix endianness issue for tx cleanup
#   
#   This patch fixes tx cleanup so that it works correctly on big endian
#   machines.
#   This time I remembered to update the version string.
#   
#   Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
# 
# drivers/net/ixgb/ixgb_main.c
#   2004/09/22 15:01:42-04:00 jesse.brandeburg@intel.com +2 -2
#   RESEND ixgb: fix endianness issue for tx cleanup
# 
# ChangeSet
#   2004/10/01 00:19:51-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/misc
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/ixgb/ixgb_main.c
#   2004/10/01 00:19:47-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/10/01 00:19:47-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/01 00:18:59-04:00 nacc@us.ibm.com 
#   [PATCH] net/de2104x: replace schedule_timeout() with msleep()
#   
#   Any comments would be appreciated.
#   
#   Description: Use msleep() instead of schedule_timeout()
#   to guarantee the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
# 
# drivers/net/tulip/de2104x.c
#   2004/09/15 12:38:42-04:00 nacc@us.ibm.com +1 -2
#   net/de2104x: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2004/10/01 00:16:39-04:00 felipewd@terra.com.br 
#   [PATCH] 8139cp net driver: add MODULE_VERSION
# 
# drivers/net/8139cp.c
#   2004/09/23 00:02:58-04:00 felipewd@terra.com.br +1 -0
#   8139cp net driver: add MODULE_VERSION
# 
# ChangeSet
#   2004/10/01 00:14:33-04:00 akpm@osdl.org 
#   [PATCH] e1000 sparc64 dma_mapping build fix
#   
#   drivers/net/e1000/e1000_main.c: In function `e1000_probe':
#   drivers/net/e1000/e1000_main.c:389: error: `DMA_64BIT_MASK' undeclared (first use in this function)
#   drivers/net/e1000/e1000_main.c:389: error: (Each undeclared identifier is reported only once
#   drivers/net/e1000/e1000_main.c:389: error: for each function it appears in.)
#   drivers/net/e1000/e1000_main.c:392: error: `DMA_32BIT_MASK' undeclared (first use in this function)
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/e1000/e1000.h
#   2004/09/21 02:38:09-04:00 akpm@osdl.org +1 -0
#   e1000 sparc64 dma_mapping build fix
# 
# ChangeSet
#   2004/10/01 00:13:59-04:00 akpm@osdl.org 
#   [PATCH] igxb speedup
#   
#   The interrupt routine will call both those functions even if the first doesn't
#   have any work to do.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/ixgb/ixgb_main.c
#   2004/08/30 03:50:40-04:00 akpm@osdl.org +5 -1
#   igxb speedup
# 
# ChangeSet
#   2004/09/30 23:34:42-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/forcedeth
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/forcedeth.c
#   2004/09/30 23:34:38-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/30 23:34:00-04:00 manfred@colorfullife.com 
#   [PATCH] rx checksum support for gige nForce ethernet
# 
# drivers/net/forcedeth.c
#   2004/09/25 15:31:16-04:00 manfred@colorfullife.com +28 -3
#   rx checksum support for gige nForce ethernet]
# 
# ChangeSet
#   2004/09/30 23:29:15-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 update -- fix MODULE_PARM, module_param, module_param_array
# 
# drivers/net/e1000/e1000_param.c
#   2004/09/21 00:54:34-04:00 ganesh.venkatesan@intel.com +104 -63
#   e1000 update -- fix MODULE_PARM, module_param,
# 
# drivers/net/e1000/e1000.h
#   2004/09/21 00:54:33-04:00 ganesh.venkatesan@intel.com +0 -1
#   e1000 update -- fix MODULE_PARM, module_param,
# 
# ChangeSet
#   2004/09/30 23:24:55-04:00 klassert@mathematik.tu-chemnitz.de 
#   [PATCH] 8139cp - add netpoll support
#   
#   Patch adds netpoll support to the 8139cp driver.
#   The patch needs some tests because I have no NIC of this type for testing.
#   
#   Applies against linux-2.6.9-rc2-mm3
#   
#   Signed-off-by: Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
# 
# drivers/net/8139cp.c
#   2004/09/27 07:55:04-04:00 klassert@mathematik.tu-chemnitz.de +19 -0
#   8139cp - add netpoll support
# 
# ChangeSet
#   2004/09/30 23:11:53-04:00 jt@bougret.hpl.hp.com 
#   [PATCH] WE-17 typo fix
#   
#   	Felix R. found a typo in the WE-17 patch I sent you and is
#   pending in your tree (more correctly, an overzealous
#   search&replace). The patch below fix this mistake.
#   	I would appreciate you adding this patch to your tree ;-)
# 
# net/core/wireless.c
#   2004/09/28 07:34:33-04:00 jt@bougret.hpl.hp.com +1 -1
#   WE-17 typo fix
# 
# ChangeSet
#   2004/09/30 19:38:25-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/misc
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/Kconfig
#   2004/09/30 19:38:21-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/09/17 11:39:00-04:00 akpm@osdl.org +12 -12
#   via-velocity Kconfig fix
# 
# ChangeSet
#   2004/09/30 19:33:53-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/linux-2.6
#   into pobox.com:/spare/repo/netdev-2.6/misc
# 
# drivers/net/Kconfig
#   2004/09/30 19:33:49-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/30 13:10:36-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev
# 
# drivers/net/natsemi.c
#   2004/09/30 13:10:30-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/20 18:47:14-04:00 jgarzik@pobox.com 
#   Hand-merge typhoon conflicts.
# 
# drivers/net/typhoon.c
#   2004/09/20 18:47:07-04:00 jgarzik@pobox.com +2 -23
#   Hand-merge typhoon conflicts.
# 
# ChangeSet
#   2004/09/20 18:40:34-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/r8169
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/wireless/airo.c
#   2004/09/20 18:40:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/r8169.c
#   2004/09/20 18:40:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/09/20 18:40:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/ieee1394/eth1394.c
#   2004/09/20 18:40:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/20 18:37:18-04:00 jgarzik@pobox.com 
#   Hand-merge upstream r8169 DAC changes.
# 
# drivers/net/r8169.c
#   2004/09/20 18:37:11-04:00 jgarzik@pobox.com +0 -14
#   Hand-merge upstream r8169 DAC changes.
# 
# drivers/net/Kconfig
#   2004/09/20 18:35:32-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/20 15:30:51-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/misc
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/Kconfig
#   2004/09/20 15:30:47-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/20 15:29:26-04:00 jgarzik@pobox.com 
#   Merge
# 
# drivers/net/smc91x.h
#   2004/09/20 15:29:25-04:00 jgarzik@pobox.com +0 -0
#   SCCS merged
# 
# drivers/net/Kconfig
#   2004/09/20 15:28:07-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/20 15:25:11-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/mc-filter
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/tulip/tulip_core.c
#   2004/09/20 15:25:07-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/20 15:17:45-04:00 ralf@linux-mips.org 
#   [PATCH] Stop queue on close in hdlcdrv
#   
#   The stop method of a driver should ensure queueing is stopped ...
# 
# drivers/net/hamradio/hdlcdrv.c
#   2004/05/04 07:47:17-04:00 ralf@linux-mips.org +2 -0
#   Stop queue on close in hdlcdrv
# 
# ChangeSet
#   2004/09/20 15:08:23-04:00 rl@hellgate.ch 
#   [PATCH] mc_filter on big-endian arch
#   
#   On Sat, 19 Jun 2004 17:37:37 -0400, Jeff Garzik wrote:
#   > you would be kind enough to resend the non-via-rhine patches WRT mc_filter?
#   
#   Sure. Patch is for 2.6 (not rediffed, yell if it doesn't apply
#   anymore). Btw, did you pick up the mc_filter patch for 2.4 via-rhine?
#   
#   This untested patch fixes hardware mc filters for tulip_core, winbond,
#   and atp. Hopefully :-).
#   
#   Please review and test.
#   
#   Signed-off-by: Roger Luethi <rl@hellgate.ch>
# 
# drivers/net/tulip/winbond-840.c
#   2004/06/06 12:04:19-04:00 rl@hellgate.ch +1 -1
#   mc_filter on big-endian arch
# 
# drivers/net/tulip/tulip_core.c
#   2004/06/06 12:04:36-04:00 rl@hellgate.ch +1 -1
#   mc_filter on big-endian arch
# 
# drivers/net/atp.c
#   2004/06/06 12:04:55-04:00 rl@hellgate.ch +1 -1
#   mc_filter on big-endian arch
# 
# ChangeSet
#   2004/09/20 14:48:28-04:00 shemminger@osdl.org 
#   [PATCH] 8139cp - module_param
#   
#   Not sure if I sent this already...
#   Convert 8139cp to use new module_param() not old MODULE_PARM
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/8139cp.c
#   2004/07/23 16:54:25-04:00 shemminger@osdl.org +3 -2
#   8139cp - module_param
# 
# ChangeSet
#   2004/09/20 14:44:20-04:00 romieu@fr.zoreil.com 
#   [PATCH] via-velocity: wrong module name in Kconfig documentation
#   
#   Copy/paste abuse.
# 
# drivers/net/Kconfig
#   2004/08/14 06:11:16-04:00 romieu@fr.zoreil.com +1 -1
#   via-velocity: wrong module name in Kconfig documentation
# 
# ChangeSet
#   2004/09/20 14:41:40-04:00 webvenza@libero.it 
#   [netdrvr sis900] whitespace and codingstyle updates
#   
#   Big patch, but only contains whitespace and CodingStyle fixes to make
#   the whole sis900.c file uniform. Some >80 lines where too difficult to
#   split, so I let them alone, readability would be just as bad as is now.
#   
#   This patch depends on the previous one liner that adds the new PHY ID
#   and is made against kernel 2.6.8 (as the previous).
#   
#   This patch is also available at: http://teg.homeunix.org/sis900.html
# 
# drivers/net/sis900.c
#   2004/09/20 14:41:32-04:00 webvenza@libero.it +142 -116
#   [netdrvr sis900] whitespace and codingstyle updates
#   
#   Big patch, but only contains whitespace and CodingStyle fixes to make
#   the whole sis900.c file uniform. Some >80 lines where too difficult to
#   split, so I let them alone, readability would be just as bad as is now.
#   
#   This patch depends on the previous one liner that adds the new PHY ID
#   and is made against kernel 2.6.8 (as the previous).
#   
#   This patch is also available at: http://teg.homeunix.org/sis900.html
# 
# ChangeSet
#   2004/09/20 14:36:10-04:00 elf@buici.com 
#   [PATCH] adding smc91x ethernet to lpd7a40x
#   
#   Small patch that adds support for the Logic Product Development variant
#   of the smc91x implementation.  The SMC_IOBARRIER is necessary to work-around a
#   peculiarity of the memory controller that interfaces the network controller to
#   the bus.
# 
# drivers/net/smc91x.h
#   2004/08/15 16:58:47-04:00 elf@buici.com +43 -0
#   adding smc91x ethernet to lpd7a40x
# 
# ChangeSet
#   2004/09/20 14:34:45-04:00 pavel@ucw.cz 
#   [PATCH] swsuspend for ne2k-pci cards
#   
#   Author: Éric Brunet <Eric.Brunet@lps.ens.fr>
# 
# drivers/net/ne2k-pci.c
#   2004/08/21 06:24:27-04:00 pavel@ucw.cz +31 -0
#   PATCH: swsuspend for ne2k-pci cards
# 
# ChangeSet
#   2004/09/20 14:08:38-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/r8169
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/r8169.c
#   2004/09/20 14:08:34-04:00 jgarzik@pobox.com +0 -1
#   Auto merged
# 
# ChangeSet
#   2004/09/20 14:06:35-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: default on disabling PCIDAC
#   
#   Default to disabling PCI DAC as this option appears unsafe on amd64
#   (original suggestion by Hans-Frieder Vogt <hfvogt@arcor.de>).
#   
#   The driver will typically report PCI System error when something goes
#   wrong. The relevant interrupt is not masked any more and the driver
#   can thus be disabled.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/09/19 18:16:02-04:00 romieu@fr.zoreil.com +15 -2
#   r8169: default on disabling PCIDAC
# 
# ChangeSet
#   2004/09/20 14:04:30-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/acenic
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/typhoon.c
#   2004/09/20 14:04:26-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/b44.h
#   2004/09/20 14:04:26-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/b44.c
#   2004/09/20 14:04:26-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/09/20 14:04:26-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/20 14:03:45-04:00 shemminger@osdl.org 
#   [PATCH] (4/4) acenic - don't spin forever in hard_start_xmit
#   
#   If driver is stuck due to ring full and hardware or link error, don't spin
#   forever in the hard_start_xmit routine.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/acenic.c
#   2004/09/20 13:47:22-04:00 shemminger@osdl.org +11 -3
#   (4/4) acenic - don't spin forever in hard_start_xmit
# 
# ChangeSet
#   2004/09/20 14:03:34-04:00 shemminger@osdl.org 
#   [PATCH] (3/4) acenic - __iomem warnings cleanup
#   
#   This cleans all the compile warnings and most of the sparse warnings
#   for the acenic driver relating to io memory space.
#   Remaining warnings are because tx_ring can be either in i/o or not
#   depending on the version of the card.
#   Not tested on old TIGON card.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/acenic.h
#   2004/09/20 13:47:00-04:00 shemminger@osdl.org +4 -4
#   (3/4) acenic - __iomem warnings cleanup
# 
# drivers/net/acenic.c
#   2004/09/20 13:47:00-04:00 shemminger@osdl.org +57 -80
#   (3/4) acenic - __iomem warnings cleanup
# 
# ChangeSet
#   2004/09/20 14:03:22-04:00 shemminger@osdl.org 
#   [PATCH] (2/4) acenic - eliminate MAX_SKB_FRAGS #if
#   
#   Since MAX_SKB_FRAGS is defined in both 2.4 and 2.6, it makes sense
#   to eliminate this old #if code.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/acenic.h
#   2004/09/20 13:46:46-04:00 shemminger@osdl.org +0 -11
#   (2/4) acenic - eliminate MAX_SKB_FRAGS #if
# 
# drivers/net/acenic.c
#   2004/09/20 13:46:46-04:00 shemminger@osdl.org +2 -8
#   (2/4) acenic - eliminate MAX_SKB_FRAGS #if
# 
# ChangeSet
#   2004/09/20 14:03:11-04:00 shemminger@osdl.org 
#   [PATCH] (1/4) acenic - use netdev_priv
#   
#   Trivial, use netdev_priv
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/acenic.h
#   2004/09/20 13:46:22-04:00 shemminger@osdl.org +2 -2
#   (1/4) acenic - use netdev_priv
# 
# drivers/net/acenic.c
#   2004/09/20 13:46:22-04:00 shemminger@osdl.org +1 -1
#   (1/4) acenic - use netdev_priv
# 
# ChangeSet
#   2004/09/17 12:19:28-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/iomap
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/eepro100.c
#   2004/09/17 12:19:24-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/17 12:17:15-04:00 jgarzik@pobox.com 
#   [netdrvr eepro100] fix pci_iomap() args and info msg that follows
# 
# drivers/net/eepro100.c
#   2004/09/17 12:17:09-04:00 jgarzik@pobox.com +6 -6
#   [netdrvr eepro100] fix pci_iomap() args and info msg that follows
# 
# ChangeSet
#   2004/09/17 11:59:08-04:00 pp@ee.oulu.fi 
#   [PATCH] b44: use bounce buffers to workaround chip DMA bug/limitations
#   
#   Signed-off-by: Pekka Pietikainen <pp@ee.oulu.fi>
# 
# drivers/net/b44.h
#   2004/08/08 03:54:18-04:00 pp@ee.oulu.fi +2 -1
#   b44: use bounce buffers to workaround chip DMA bug/limitations
# 
# drivers/net/b44.c
#   2004/08/08 03:54:18-04:00 pp@ee.oulu.fi +50 -4
#   b44: use bounce buffers to workaround chip DMA bug/limitations
# 
# ChangeSet
#   2004/09/17 11:57:59-04:00 jgarzik@pobox.com 
#   [netdrvr b44] update MODULE_AUTHORS
#   
#   As prodded by David Miller.
# 
# drivers/net/b44.c
#   2004/09/17 11:57:53-04:00 jgarzik@pobox.com +1 -1
#   [netdrvr b44] update MODULE_AUTHORS
#   
#   As prodded by David Miller.
# 
# ChangeSet
#   2004/09/17 11:53:57-04:00 jolt@tuxbox.org 
#   [netdrvr b44] clean up SiliconBackplane definitions/functions
#   
#   there is a good amount of code to support SiliconBackplane functions which are unneeded or simply plain wrong. Lets get rid of it.
#   
#   Signed-off-by: Florian Schirmer <jolt@tuxbox.org>
# 
# drivers/net/b44.h
#   2004/09/17 11:53:50-04:00 jolt@tuxbox.org +3 -107
#   [netdrvr b44] clean up SiliconBackplane definitions/functions
#   
#   there is a good amount of code to support SiliconBackplane functions which are unneeded or simply plain wrong. Lets get rid of it.
#   
#   Signed-off-by: Florian Schirmer <jolt@tuxbox.org>
# 
# drivers/net/b44.c
#   2004/09/17 11:53:50-04:00 jolt@tuxbox.org +4 -39
#   [netdrvr b44] clean up SiliconBackplane definitions/functions
#   
#   there is a good amount of code to support SiliconBackplane functions which are unneeded or simply plain wrong. Lets get rid of it.
#   
#   Signed-off-by: Florian Schirmer <jolt@tuxbox.org>
# 
# ChangeSet
#   2004/09/17 11:53:11-04:00 jolt@tuxbox.org 
#   [netdrvr b44] ignore carrier lost errors
#   
#   some (?) hardware seems to be buggy and is reporting bogus carrier lost 
#   values. Both reference implementations from Broadcom indicate that this 
#   counter is not reliable and therefore ignore it. We should do the same. 
#   "Fixes" the carrier lost problem i've seen.
#   
#   Signed-off-by: Florian Schirmer <jolt@tuxbox.org>
# 
# drivers/net/b44.c
#   2004/09/17 11:53:03-04:00 jolt@tuxbox.org +3 -0
#   [netdrvr b44] ignore carrier lost errors
#   
#   some (?) hardware seems to be buggy and is reporting bogus carrier lost 
#   values. Both reference implementations from Broadcom indicate that this 
#   counter is not reliable and therefore ignore it. We should do the same. 
#   "Fixes" the carrier lost problem i've seen.
#   
#   Signed-off-by: Florian Schirmer <jolt@tuxbox.org>
# 
# ChangeSet
#   2004/09/17 11:28:46-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/e1000
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/e1000/e1000_main.c
#   2004/09/17 11:28:41-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/17 10:37:55-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 - Ethtool -- 82545 do not support WoL
# 
# drivers/net/e1000/e1000_ethtool.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +2 -0
#   e1000 - Ethtool -- 82545 do not support WoL
# 
# ChangeSet
#   2004/09/17 10:37:43-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 - Polarity reversal workaround for 10F/10H links
# 
# drivers/net/e1000/e1000_osdep.h
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +6 -0
#   e1000 - Polarity reversal workaround for 10F/10H links
# 
# drivers/net/e1000/e1000_hw.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +115 -0
#   e1000 - Polarity reversal workaround for 10F/10H links
# 
# ChangeSet
#   2004/09/17 10:37:32-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 - Fix VLAN filter setup errors (while running on PPC)
# 
# drivers/net/e1000/e1000_main.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +4 -4
#   e1000 - Fix VLAN filter setup errors (while running on PPC)
# 
# ChangeSet
#   2004/09/17 10:37:20-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 Check value returned by from pci_enable_device
# 
# drivers/net/e1000/e1000_main.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +2 -2
#   e1000 Check value returned by from pci_enable_device
# 
# drivers/net/e1000/e1000_ethtool.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +2 -2
#   e1000 Check value returned by from pci_enable_device
# 
# ChangeSet
#   2004/09/17 10:37:08-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 - Removed support for advanced TCO features
# 
# drivers/net/e1000/e1000_main.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +2 -9
#   e1000 - Removed support for advanced TCO features
# 
# ChangeSet
#   2004/09/17 10:36:56-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 - use pci_device_name for syslog messages till
#   registering netdevice.
# 
# drivers/net/e1000/e1000_main.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +5 -11
#   e1000 - use pci_device_name for syslog messages till
#   registering netdevice.
# 
# drivers/net/e1000/e1000.h
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +0 -2
#   e1000 - use pci_device_name for syslog messages till
#   registering netdevice.
# 
# ChangeSet
#   2004/09/17 10:26:28-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e100 driver version number update
# 
# drivers/net/e100.c
#   2004/09/09 17:51:32-04:00 ganesh.venkatesan@intel.com +2 -2
#   e100 driver version number update
# 
# ChangeSet
#   2004/09/17 10:26:17-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e100 - use NET_IP_ALIGN to set rx data buffer alignment
# 
# drivers/net/e100.c
#   2004/09/09 17:51:32-04:00 ganesh.venkatesan@intel.com +2 -4
#   e100 - use NET_IP_ALIGN to set rx data buffer alignment
# 
# ChangeSet
#   2004/09/17 10:26:04-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e100 - Use pci_device_name for syslog messages till registering netdevice
# 
# drivers/net/e100.c
#   2004/09/09 17:51:32-04:00 ganesh.venkatesan@intel.com +2 -0
#   e100 - Use pci_device_name for syslog messages till registering netdevice
# 
# ChangeSet
#   2004/09/17 01:32:51-04:00 jgarzik@pobox.com 
#   Hand-merge two competing ethtool_ops conversions for typhoon
# 
# drivers/net/typhoon.c
#   2004/09/17 01:32:45-04:00 jgarzik@pobox.com +7 -72
#   Hand-merge two competing ethtool_ops conversions for typhoon
# 
# ChangeSet
#   2004/09/17 01:26:17-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/r8169
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/r8169.c
#   2004/09/17 01:26:14-04:00 jgarzik@pobox.com +0 -1
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/09/17 01:26:13-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/16 20:34:40-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: Mac identifier extracted from Realtek's driver v2.2
#   
#   Mac identifier extracted from Realtek's driver v2.2.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/09/08 17:31:09-04:00 romieu@fr.zoreil.com +3 -1
#   r8169: Mac identifier extracted from Realtek's driver v2.2
# 
# ChangeSet
#   2004/09/16 20:34:28-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: TSO support.
#   
#   TSO support. Suggestion of Jeff Garzik.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/09/08 16:53:47-04:00 romieu@fr.zoreil.com +14 -3
#   r8169: TSO support.
# 
# ChangeSet
#   2004/09/16 20:34:16-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: hint for Tx flow control
#   
#   return 1 in start_xmit() when the required descriptors are not available
#   and wait for more room.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/09/08 16:04:04-04:00 romieu@fr.zoreil.com +7 -5
#   r8169: hint for Tx flow control
# 
# ChangeSet
#   2004/09/16 20:34:04-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: miscalculation of available Tx descriptors
#   
#   The count of available entries in the Tx descriptors ring is badly wrong.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/09/08 16:02:35-04:00 romieu@fr.zoreil.com +9 -5
#   r8169: miscalculation of available Tx descriptors
# 
# ChangeSet
#   2004/09/16 20:27:36-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/linux-2.6
#   into pobox.com:/spare/repo/netdev-2.6/r8169
# 
# drivers/net/Kconfig
#   2004/09/16 20:27:32-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/16 20:21:50-04:00 akpm@osdl.org 
#   [PATCH] pegasus.c fixes
#   
#   drivers/usb/net/pegasus.c: In function `pegasus_set_settings':
#   drivers/usb/net/pegasus.c:961: warning: passing arg 2 of `mii_ethtool_sset' from incompatible pointer type
#   drivers/usb/net/pegasus.c: In function `pegasus_get_msglevel':
#   drivers/usb/net/pegasus.c:978: warning: unused variable `pegasus'
#   drivers/usb/net/pegasus.c: In function `pegasus_set_msglevel':
#   drivers/usb/net/pegasus.c:985: warning: unused variable `pegasus'
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/usb/net/pegasus.c
#   2004/08/31 00:56:49-04:00 akpm@osdl.org +9 -5
#   pegasus.c fixes
# 
# ChangeSet
#   2004/09/16 20:21:15-04:00 akpm@osdl.org 
#   [PATCH] add missing pci_disable_device for e1000
#   
#   From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
#   
#   This patch adds pci_disable_device() into e1000_remove().
#   
#   If your driver decides to stop using the device, it should call
#   pci_disable_device() to deallocate any IRQ resources, disable PCI
#   bus-mastering, etc.
#   
#   Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/e1000/e1000_main.c
#   2004/09/13 02:03:20-04:00 akpm@osdl.org +2 -0
#   add missing pci_disable_device for e1000
# 
# ChangeSet
#   2004/09/16 20:15:05-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/iomap
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# include/linux/netdevice.h
#   2004/09/16 20:15:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/eepro100.c
#   2004/09/16 20:15:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/09/16 20:15:01-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/16 20:13:40-04:00 davem@davemloft.net 
#   [PATCH] eepro100.c iomap conversion
# 
# drivers/net/eepro100.c
#   2004/09/16 19:48:12-04:00 davem@davemloft.net +129 -162
#   RFC eepro100.c conversion
# 
# drivers/net/Kconfig
#   2004/09/16 19:46:57-04:00 davem@davemloft.net +0 -10
#   RFC eepro100.c conversion
# 
# ChangeSet
#   2004/09/09 22:57:10-04:00 dave@thedillows.org 
#   PCI cleanups and convert to ethtool_ops
#   *) Reorder MWI initialization
#   *) Perform proper cleanup on probe failure
#   *) Remove cruft, and avoid locking up NIC on reset
#   
#   Signed-off-by: David A. Dillow <dave@thedillows.org>
# 
# drivers/net/typhoon.c
#   2004/09/09 22:49:47-04:00 dave@thedillows.org +12 -4
#   Update release date and version, add TODO list.
# 
# drivers/net/typhoon.c
#   2004/09/09 00:55:56-04:00 dave@thedillows.org +0 -6
#   Remove cruft from when the typhoon driver left the NIC in D3 state.
#   Its remove could be a problem on a warm-boot from Windows if 3Com's
#   drivers left the card in D3, but they don't do that, and the code
#   is blocking progress elsewhere in the PCI system.
# 
# drivers/net/typhoon.c
#   2004/09/09 00:30:09-04:00 dave@thedillows.org +81 -84
#   Convert to using ethtool_ops, and add some extra abilities.
# 
# drivers/net/typhoon.c
#   2004/09/08 23:30:07-04:00 dave@thedillows.org +14 -14
#   Make use of netdev_priv()
# 
# drivers/net/typhoon.c
#   2004/09/08 01:28:47-04:00 dave@thedillows.org +9 -8
#   Still seeing hangs with 100us wait, so bump it to 5ms if we can
#   sleep, and 500us otherwise.
# 
# drivers/net/typhoon.c
#   2004/09/08 00:50:01-04:00 dave@thedillows.org +21 -8
#   PCI cleanups:
#   * move pci_set_mwi() earlier in setup
#   * call pci_clear_mwi() in ->remove() and ->probe() error path
#   * call pci_disable_device() on probe error
#   * make use of DMA_32BIT_MASK constant
# 
# ChangeSet
#   2004/09/05 15:34:39-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/prism54
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# include/linux/netdevice.h
#   2004/09/05 15:34:34-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/wireless/wavelan.c
#   2004/09/05 15:34:34-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/wireless/airo.c
#   2004/09/05 15:34:34-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/forcedeth.c
#   2004/09/05 15:34:34-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/09/05 15:34:34-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/05 15:19:38-04:00 margitsw@t-online.de 
#   [PATCH] prism54 fix wpa_supplicant frequency parsing
#   
#   * This work fixes wpa_supplicant frequency parsing. iwlist eth0
#   * scan will now show channel and frequency.
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/09/05 04:49:53-04:00 margitsw@t-online.de +2 -2
#   prism54 fix wpa_supplicant frequency parsing
# 
# ChangeSet
#   2004/09/05 15:19:27-04:00 margitsw@t-online.de 
#   [PATCH] prism54 initial WPA support
#   
#   * Work based on initial patches from Jouni Malinen <jkmaline@cc.hut.fi>
#   * Initial wpa_supplicant support work:
#   * isl_ioctl.c (prism54_process_trap_helper): Start to use mlmeex,
#   * start doing what's right for
#   * DOT11_OID_AUTHENTICATEEX,
#   * DOT11_OID_ASSOCIATEEX,
#   * DOT11_OID_ASSOCIATEEX, and
#   * DOT11_OID_REASSOCIATEEX
#   
#   * isl_ioctl.c: add temporary structure for wpa_supplicant requests,
#   
#   * isl_ioctl.c: add prism2_ioctl_set_encryption which can probably be removed
#   later
#   
#   * isl_ioctl.c: add prism2_ioctl_set_generic_element (well tested)
#   
#   * isl_ioctl.c: add prism2_ioctl_mlme which should be unnecessary since
#   * WE scan should be used by wpa_supplicant
#   
#   * isl_ioctl.c: add prism54_hostapd - this parses wpa_supplicant
#   * requests and does the right job for each
#   
#   * isl_ioctl.c (prism54_set_wpa): changed to not use mgt_set/mgt_commit
#   * as commit is unecessary. Added proper OID sets to enable/disable WPA.
#   * This is called by wpa_supplicant at startup. This should eventually
#   * be part of WE18.
#   
#   * isl_ioctl.c (prism54_ioctl): Links wpa_supplicant to prism54
#   
#   * isl_ioctl.h: defined prism54_set_wpa to allow prism54_hostapd to use
#   
#   * isl_oid.h: add struct obj_attachment for OID OID_TYPE_ATTACH
#   
#   * oid_mgt.c: map OID DOT11_OID_ATTACHMENT to struct obj_attachment
#   
#   * oid_mgt.c (mgt_le_to_cpu, mgt_cpu_to_le): handle endianness for
#   * obj_attachment
#   
#   * oid_mgt.c: add mgt_set_varlen, needed for mlmeex as it has a
#   * variable size field.
#   
#   * oid_mgt.c: add mgt_unlatch_all, this can be used to force a commit
#   * on OIDs:
#   * MEDIUMLIMIT, BEACONPERIOD, DTIMPERIOD, ATIMWINDOW,
#   * LISTENINTERVAL, FREQUENCY, EXTENDEDRATES
#   * These OIDs are "latched". TODO: config mode handling.
#   * oid_mgt.c (mgt_response_to_str): learn to parse OID_TYPE_ATTACH
#   * oid_mgt.h: add mgt_set_varlen, and mgt_unlatch_all
# 
# drivers/net/wireless/prism54/oid_mgt.h
#   2004/09/05 04:49:05-04:00 margitsw@t-online.de +3 -0
#   prism54 initial WPA support
# 
# drivers/net/wireless/prism54/oid_mgt.c
#   2004/09/05 04:49:05-04:00 margitsw@t-online.de +92 -1
#   prism54 initial WPA support
# 
# drivers/net/wireless/prism54/isl_oid.h
#   2004/09/05 04:49:05-04:00 margitsw@t-online.de +9 -0
#   prism54 initial WPA support
# 
# drivers/net/wireless/prism54/isl_ioctl.h
#   2004/09/05 04:49:05-04:00 margitsw@t-online.de +2 -0
#   prism54 initial WPA support
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/09/05 04:49:05-04:00 margitsw@t-online.de +490 -18
#   prism54 initial WPA support
# 
# ChangeSet
#   2004/09/05 15:19:15-04:00 margitsw@t-online.de 
#   [PATCH] prism54 add WE17 support
#   
#   * Add support for WE17 from Jean Tourrilhes
# 
# drivers/net/wireless/prism54/islpci_dev.h
#   2004/09/05 04:47:13-04:00 margitsw@t-online.de +4 -0
#   prism54 add WE17 support
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/09/05 04:47:13-04:00 margitsw@t-online.de +6 -0
#   prism54 add WE17 support
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/09/05 04:47:13-04:00 margitsw@t-online.de +31 -6
#   prism54 add WE17 support
# 
# ChangeSet
#   2004/09/05 15:19:04-04:00 margitsw@t-online.de 
#   [PATCH] prism54 remove module params
#   
#   * Remove unneeded module params.
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/09/05 04:45:27-04:00 margitsw@t-online.de +21 -55
#   prism54 remove module params
# 
# ChangeSet
#   2004/09/05 15:18:53-04:00 margitsw@t-online.de 
#   [PATCH] prism54 Code cleanup
#   
#   (Patches submitted by Denis Vlasenko)
#   There are neither functionality changes nor bug fixes.
#   
#   * 2004-08-14 Denis Vlasenko <vda@port.imtp.ilyichevsk.odessa.ua>
#   * Move assignment out of if()
#   * Remove trailing space from printk
#   * Eliminate not needed local 'u32 reg'
#   * Add a comment about undoc bits
#   * Add #define VEC_SIZE, use it as appropriate
#   * Add some printks to reset error code path (our
#   * current area of trouble)
#   * Make printk text less confusing
#   * Some not needed NULL assignments removed
#   * mgt_commit_list(): tell which oid has failed
# 
# drivers/net/wireless/prism54/oid_mgt.c
#   2004/09/05 04:41:07-04:00 margitsw@t-online.de +15 -13
#   prism54 Code cleanup
# 
# drivers/net/wireless/prism54/islpci_eth.c
#   2004/09/05 04:41:07-04:00 margitsw@t-online.de +3 -2
#   prism54 Code cleanup
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/09/05 04:41:07-04:00 margitsw@t-online.de +14 -15
#   prism54 Code cleanup
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/09/05 04:41:07-04:00 margitsw@t-online.de +2 -2
#   prism54 Code cleanup
# 
# drivers/net/wireless/prism54/isl_38xx.h
#   2004/09/05 04:41:07-04:00 margitsw@t-online.de +4 -0
#   prism54 Code cleanup
# 
# drivers/net/wireless/prism54/isl_38xx.c
#   2004/09/05 04:41:07-04:00 margitsw@t-online.de +5 -10
#   prism54 Code cleanup
# 
# ChangeSet
#   2004/08/31 17:47:20-04:00 jgarzik@pobox.com 
#   Hand-merge upstream r8169 changes.
# 
# drivers/net/r8169.c
#   2004/08/31 17:47:12-04:00 jgarzik@pobox.com +1 -2
#   Hand-merge upstream r8169 changes.
# 
# ChangeSet
#   2004/08/31 03:20:31-04:00 romieu@fr.zoreil.com 
#   [PATCH] 8139cp: SG support fixes
#   
#   - suspicious length in pci_unmap_single;
#   - wait for the last frag before freeing the relevant skb;
#   - no need to crash when facing some unexpected csum combination.
# 
# drivers/net/8139cp.c
#   2004/08/30 15:21:23-04:00 romieu@fr.zoreil.com +13 -12
#   8139cp: SG support fixes
# 
# ChangeSet
#   2004/08/31 03:18:42-04:00 jgarzik@pobox.com 
#   Hand-merge upstream r8169 change.
# 
# drivers/net/r8169.c
#   2004/08/31 03:18:36-04:00 jgarzik@pobox.com +1 -2
#   Hand-merge upstream r8169 change.
# 
# ChangeSet
#   2004/08/31 03:16:23-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/net-drivers-2.6
#   into pobox.com:/spare/repo/netdev-2.6/8139cp
# 
# drivers/net/8139cp.c
#   2004/08/31 03:16:19-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/29 23:54:55-04:00 jgarzik@pobox.com 
#   Hand-merge viro conflicts with wavelan.
# 
# drivers/net/wireless/wavelan_cs.c
#   2004/08/29 23:54:49-04:00 jgarzik@pobox.com +0 -1
#   Hand-merge viro conflicts with wavelan.
# 
# ChangeSet
#   2004/08/29 23:51:12-04:00 viro@www.linux.org.uk 
#   [PATCH] (27/27) catc ethtool conversion
# 
# drivers/usb/net/catc.c
#   2004/08/29 19:21:09-04:00 viro@www.linux.org.uk +27 -63
#   (27/27) catc ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:51:01-04:00 viro@www.linux.org.uk 
#   [PATCH] (26/27) kaweth ethtool conversion
# 
# drivers/usb/net/kaweth.c
#   2004/08/29 19:21:04-04:00 viro@www.linux.org.uk +6 -28
#   (26/27) kaweth ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:50:49-04:00 viro@www.linux.org.uk 
#   [PATCH] (25/27) pegasus ethtool conversion
# 
# drivers/usb/net/pegasus.c
#   2004/08/29 19:20:54-04:00 viro@www.linux.org.uk +94 -150
#   (25/27) pegasus ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:50:38-04:00 viro@www.linux.org.uk 
#   [PATCH] (24/27) rtl8150 ethtool conversion
# 
# drivers/usb/net/rtl8150.c
#   2004/08/29 19:20:50-04:00 viro@www.linux.org.uk +45 -71
#   (24/27) rtl8150 ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:50:26-04:00 viro@www.linux.org.uk 
#   [PATCH] (23/27) gadget ethtool conversion
# 
# drivers/usb/gadget/ether.c
#   2004/08/29 19:20:49-04:00 viro@www.linux.org.uk +14 -43
#   (23/27) gadget ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:50:15-04:00 viro@www.linux.org.uk 
#   [PATCH] (22/27) amd8111e ethtool conversion
# 
# drivers/net/amd8111e.c
#   2004/08/29 19:20:49-04:00 viro@www.linux.org.uk +105 -143
#   (22/27) amd8111e ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:50:04-04:00 viro@www.linux.org.uk 
#   [PATCH] (21/27) dl2k ethtool conversion
# 
# drivers/net/dl2k.c
#   2004/08/29 19:20:42-04:00 viro@www.linux.org.uk +100 -119
#   (21/27) dl2k ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:49:49-04:00 viro@www.linux.org.uk 
#   [PATCH] (20/27) eepro100 ethtool conversion
# 
# drivers/net/eepro100.c
#   2004/08/29 19:20:35-04:00 viro@www.linux.org.uk +59 -73
#   (20/27) eepro100 ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:48:52-04:00 viro@www.linux.org.uk 
#   [PATCH] (19/27) ewrk3 ethtool conversion
# 
# drivers/net/ewrk3.c
#   2004/08/29 19:20:35-04:00 viro@www.linux.org.uk +142 -162
#   (19/27) ewrk3 ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:48:40-04:00 viro@www.linux.org.uk 
#   [PATCH] (18/27) forcedeth ethtool conversion
# 
# drivers/net/forcedeth.c
#   2004/08/29 19:20:34-04:00 viro@www.linux.org.uk +35 -76
#   (18/27) forcedeth ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:48:27-04:00 viro@www.linux.org.uk 
#   [PATCH] (17/27) hamachi ethtool conversion
# 
# drivers/net/hamachi.c
#   2004/08/29 19:20:33-04:00 viro@www.linux.org.uk +62 -65
#   (17/27) hamachi ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:48:17-04:00 viro@www.linux.org.uk 
#   [PATCH] (16/27) veth ethtool conversion
# 
# drivers/net/iseries_veth.c
#   2004/08/29 19:20:23-04:00 viro@www.linux.org.uk +31 -50
#   (16/27) veth ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:48:06-04:00 viro@www.linux.org.uk 
#   [PATCH] (15/27) natsemi ethtool conversion
# 
# drivers/net/natsemi.c
#   2004/08/29 19:20:13-04:00 viro@www.linux.org.uk +116 -157
#   (15/27) natsemi ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:47:55-04:00 viro@www.linux.org.uk 
#   [PATCH] (14/27) ns83820 ethtool conversion
# 
# drivers/net/ns83820.c
#   2004/08/29 19:20:08-04:00 viro@www.linux.org.uk +14 -47
#   (14/27) ns83820 ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:47:45-04:00 viro@www.linux.org.uk 
#   [PATCH] (13/27) starfire ethtool conversion
# 
# drivers/net/starfire.c
#   2004/08/29 19:20:04-04:00 viro@www.linux.org.uk +66 -81
#   (13/27) starfire ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:47:35-04:00 viro@www.linux.org.uk 
#   [PATCH] (12/27) sundance ethtool conversion
# 
# drivers/net/sundance.c
#   2004/08/29 19:20:00-04:00 viro@www.linux.org.uk +64 -81
#   (12/27) sundance ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:47:19-04:00 viro@www.linux.org.uk 
#   [PATCH] (11/27) typhoon ethtool conversion
# 
# drivers/net/typhoon.c
#   2004/08/29 19:19:57-04:00 viro@www.linux.org.uk +40 -75
#   (11/27) typhoon ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:46:09-04:00 viro@www.linux.org.uk 
#   [PATCH] (10/27) yellowfin ethtool conversion
# 
# drivers/net/yellowfin.c
#   2004/08/29 19:19:54-04:00 viro@www.linux.org.uk +10 -22
#   (10/27) yellowfin ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:45:57-04:00 viro@www.linux.org.uk 
#   [PATCH] (9/27) wl3501_cs ethtool conversion
# 
# drivers/net/wireless/wl3501_cs.c
#   2004/08/29 19:19:53-04:00 viro@www.linux.org.uk +6 -47
#   (9/27) wl3501_cs ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:45:43-04:00 viro@www.linux.org.uk 
#   [PATCH] (8/27) wavelan ethtool conversion
# 
# drivers/net/wireless/wavelan_cs.c
#   2004/08/29 19:19:53-04:00 viro@www.linux.org.uk +7 -56
#   (8/27) wavelan ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:45:26-04:00 viro@www.linux.org.uk 
#   [PATCH] (7/27) xircom ethtool conversion
# 
# drivers/net/tulip/xircom_tulip_cb.c
#   2004/08/29 19:19:52-04:00 viro@www.linux.org.uk +73 -87
#   (7/27) xircom ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:45:12-04:00 viro@www.linux.org.uk 
#   [PATCH] (6/27) tulip ethtool conversion
# 
# drivers/net/tulip/tulip_core.c
#   2004/08/29 19:19:51-04:00 viro@www.linux.org.uk +9 -23
#   (6/27) tulip ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:44:57-04:00 viro@www.linux.org.uk 
#   [PATCH] (5/27) smc91c92_cs ethtool conversion
# 
# drivers/net/pcmcia/smc91c92_cs.c
#   2004/08/29 19:19:51-04:00 viro@www.linux.org.uk +91 -90
#   (5/27) smc91c92_cs ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:44:45-04:00 viro@www.linux.org.uk 
#   [PATCH] (4/27) 3c509 ethtool conversion
# 
# drivers/net/3c509.c
#   2004/08/29 19:19:51-04:00 viro@www.linux.org.uk +46 -105
#   (4/27) 3c509 ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:44:34-04:00 viro@www.linux.org.uk 
#   [PATCH] (3/27) ixgb ethtool conversion
# 
# drivers/net/ixgb/ixgb_main.c
#   2004/08/29 19:22:37-04:00 viro@www.linux.org.uk +2 -22
#   (3/27) ixgb ethtool conversion
# 
# drivers/net/ixgb/ixgb_ethtool.c
#   2004/08/29 19:19:50-04:00 viro@www.linux.org.uk +164 -330
#   (3/27) ixgb ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:44:23-04:00 viro@www.linux.org.uk 
#   [PATCH] (2/27) cris ethtool conversion
# 
# arch/cris/arch-v10/drivers/ethernet.c
#   2004/08/29 19:19:50-04:00 viro@www.linux.org.uk +61 -79
#   (2/27) cris ethtool conversion
# 
# ChangeSet
#   2004/08/29 23:44:10-04:00 viro@www.linux.org.uk 
#   [PATCH] (1/27) eth1394 ethtool conversion
# 
# drivers/ieee1394/eth1394.c
#   2004/08/29 19:19:50-04:00 viro@www.linux.org.uk +10 -47
#   (1/27) eth1394 ethtool conversion
# 
# ChangeSet
#   2004/08/29 17:56:26-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/netdev-2.6/viro-eth1
#   into pobox.com:/spare/repo/netdev-2.6/ALL
# 
# drivers/net/wireless/wavelan_cs.c
#   2004/08/29 17:56:22-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/29 17:55:28-04:00 viro@www.linux.org.uk 
#   [netdrvr starfire] use netdev_priv
# 
# drivers/net/starfire.c
#   2004/08/29 17:55:20-04:00 viro@www.linux.org.uk +22 -21
#   [netdrvr starfire] use netdev_priv
# 
# ChangeSet
#   2004/08/29 17:55:03-04:00 viro@www.linux.org.uk 
#   [netdrvr starfire] fix unregister_netdev call site
# 
# drivers/net/starfire.c
#   2004/08/29 17:54:57-04:00 viro@www.linux.org.uk +1 -2
#   [netdrvr starfire] fix unregister_netdev call site
# 
# ChangeSet
#   2004/08/29 17:54:02-04:00 viro@www.linux.org.uk 
#   [netdrvr] use netdev_priv in dl2k, hamachi
# 
# drivers/net/hamachi.c
#   2004/08/29 17:53:56-04:00 viro@www.linux.org.uk +15 -15
#   [netdrvr] use netdev_priv in dl2k, hamachi
# 
# drivers/net/dl2k.c
#   2004/08/29 17:53:56-04:00 viro@www.linux.org.uk +24 -24
#   [netdrvr] use netdev_priv in dl2k, hamachi
# 
# ChangeSet
#   2004/08/29 17:53:24-04:00 viro@www.linux.org.uk 
#   [netdrvr] netdev_priv for sundance, typhoon, yellowfin
# 
# drivers/net/yellowfin.c
#   2004/08/29 17:53:18-04:00 viro@www.linux.org.uk +15 -15
#   [netdrvr] netdev_priv for sundance, typhoon, yellowfin
# 
# drivers/net/typhoon.c
#   2004/08/29 17:53:18-04:00 viro@www.linux.org.uk +14 -14
#   [netdrvr] netdev_priv for sundance, typhoon, yellowfin
# 
# drivers/net/sundance.c
#   2004/08/29 17:53:18-04:00 viro@www.linux.org.uk +21 -21
#   [netdrvr] netdev_priv for sundance, typhoon, yellowfin
# 
# ChangeSet
#   2004/08/29 17:52:25-04:00 viro@www.linux.org.uk 
#   [netdrvr] netdev_priv for ewrk3, xircom_tulip_cb, wavelan_cs
# 
# drivers/net/wireless/wavelan_cs.c
#   2004/08/29 17:52:18-04:00 viro@www.linux.org.uk +48 -50
#   [netdrvr] netdev_priv for ewrk3, xircom_tulip_cb, wavelan_cs
# 
# drivers/net/tulip/xircom_tulip_cb.c
#   2004/08/29 17:52:18-04:00 viro@www.linux.org.uk +20 -20
#   [netdrvr] netdev_priv for ewrk3, xircom_tulip_cb, wavelan_cs
# 
# drivers/net/ewrk3.c
#   2004/08/29 17:52:18-04:00 viro@www.linux.org.uk +14 -14
#   [netdrvr] netdev_priv for ewrk3, xircom_tulip_cb, wavelan_cs
# 
# ChangeSet
#   2004/08/29 17:51:25-04:00 viro@www.linux.org.uk 
#   [netdrvr usb] use netdev_priv
#   
#   Update catc, pegasus, rtl8150, and gadget/ether to use netdev_priv()
# 
# drivers/usb/net/rtl8150.c
#   2004/08/29 17:51:19-04:00 viro@www.linux.org.uk +19 -47
#   [netdrvr usb] use netdev_priv
#   
#   Update catc, pegasus, rtl8150, and gadget/ether to use netdev_priv()
# 
# drivers/usb/net/pegasus.c
#   2004/08/29 17:51:19-04:00 viro@www.linux.org.uk +20 -31
#   [netdrvr usb] use netdev_priv
#   
#   Update catc, pegasus, rtl8150, and gadget/ether to use netdev_priv()
# 
# drivers/usb/net/catc.c
#   2004/08/29 17:51:19-04:00 viro@www.linux.org.uk +10 -20
#   [netdrvr usb] use netdev_priv
#   
#   Update catc, pegasus, rtl8150, and gadget/ether to use netdev_priv()
# 
# drivers/usb/gadget/ether.c
#   2004/08/29 17:51:19-04:00 viro@www.linux.org.uk +8 -8
#   [netdrvr usb] use netdev_priv
#   
#   Update catc, pegasus, rtl8150, and gadget/ether to use netdev_priv()
# 
# ChangeSet
#   2004/08/29 17:50:16-04:00 viro@www.linux.org.uk 
#   [netdrvr eth1394] use netdev_priv
# 
# drivers/ieee1394/eth1394.c
#   2004/08/29 17:50:10-04:00 viro@www.linux.org.uk +19 -19
#   [netdrvr eth1394] use netdev_priv
# 
# ChangeSet
#   2004/08/29 17:19:44-04:00 jgarzik@pobox.com 
#   [netdrvr 8139cp] TSO support
# 
# drivers/net/8139cp.c
#   2004/08/29 17:19:37-04:00 jgarzik@pobox.com +33 -17
#   [netdrvr 8139cp] TSO support
# 
# ChangeSet
#   2004/08/29 16:37:18-04:00 jgarzik@pobox.com 
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/net/wireless/netwave_cs.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -12
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/net/wan/lmc/lmc_main.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -9
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/net/sk_mca.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -9
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/net/meth.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -26
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/net/ibmlana.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -9
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/media/dvb/dvb-core/dvb_net.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -9
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# ChangeSet
#   2004/08/28 19:25:49-04:00 olh@suse.de 
#   [PATCH] remove old version check from mac8390
#   
#   This 'netdevice' define will end up in the 'tags' file.
#   Its not used, so just remove it.
# 
# drivers/net/mac8390.c
#   2004/08/21 11:45:12-04:00 olh@suse.de +0 -4
#   remove old version check from mac8390
# 
# ChangeSet
#   2004/08/28 19:20:27-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: vlan support
#   
#   802.1Q support.
#   Mostly stolen from the 8139cp.c driver. The relevant registers and
#   descriptors bits are identical for both chipsets.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/08/23 17:31:33-04:00 romieu@fr.zoreil.com +94 -2
#   r8169: vlan support
# 
# drivers/net/Kconfig
#   2004/08/23 17:31:33-04:00 romieu@fr.zoreil.com +9 -0
#   r8169: vlan support
# 
# ChangeSet
#   2004/08/28 19:20:17-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: Rx checksum support
#   
#   Rx IP checksumming support.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/08/23 17:30:08-04:00 romieu@fr.zoreil.com +58 -1
#   r8169: Rx checksum support
# 
# ChangeSet
#   2004/08/28 19:20:06-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: advertise DMA to high memory
#   
#   Advertise the ability to DMA to high memory.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/08/23 17:30:06-04:00 romieu@fr.zoreil.com +3 -4
#   r8169: advertise DMA to high memory
# 
# ChangeSet
#   2004/08/28 19:19:56-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: Tx checksum offload
#   
#   SG and IP checksumming support on output.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/08/23 17:30:04-04:00 romieu@fr.zoreil.com +153 -58
#   r8169: Tx checksum offload
# 
# ChangeSet
#   2004/08/28 19:19:45-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: comment a gcc 2.95.x bug
#   
#   gcc 2.95.3 bug has been experienced on gcc 2.95.4.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/08/23 17:30:03-04:00 romieu@fr.zoreil.com +1 -1
#   r8169: comment a gcc 2.95.x bug
# 
# ChangeSet
#   2004/08/28 19:19:34-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: sync the names of a few bits with the 8139cp driver
#   
#   Sync the names of the descriptor with these which are used in the 8139cp
#   driver. Though not exactly identical the descriptors are forward compatible.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/08/23 17:30:01-04:00 romieu@fr.zoreil.com +20 -20
#   r8169: sync the names of a few bits with the 8139cp driver
# 
# ChangeSet
#   2004/08/28 19:19:23-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: bump version number
#   
#   Help reviewers realize that the in-kernel driver has evolved lately.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/08/23 17:30:00-04:00 romieu@fr.zoreil.com +10 -1
#   r8169: bump version number
# 
# ChangeSet
#   2004/08/28 19:19:13-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: enable MWI
#   
#   - enable Memory Write and Invalidate (disabled after reset);
#   - fix wrong goto.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/08/23 17:30:00-04:00 romieu@fr.zoreil.com +11 -6
#   r8169: enable MWI
# 
# ChangeSet
#   2004/08/28 19:19:03-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: code cleanup
#   
#   Cleanup/code removal:
#   - MAX_ETH_FRAME_SIZE is not used;
#   - removal of assertion for impossible condition (if it happens, it will _not_
#     take long to notice anyway)
#   - introduce rtl8169_release_board() to factor out some code;
#   - rtl8169_init_board:
#     - some variables are not really needed nor do they help read the code;
#     - more explicit name for label;
#   - tp->{Rx/Tx}DescArray: no need to zeroize coherent DMA mapping.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/08/23 17:29:59-04:00 romieu@fr.zoreil.com +26 -38
#   r8169: code cleanup
# 
# ChangeSet
#   2004/08/28 19:18:52-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: per device receive buffer size
#   
#   Turn the Rx receive buffer size into a per device variable.
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/08/23 17:29:59-04:00 romieu@fr.zoreil.com +28 -23
#   r8169: per device receive buffer size
# 
# ChangeSet
#   2004/08/28 19:18:40-04:00 romieu@fr.zoreil.com 
#   [PATCH] r8169: add ethtool_ops.{get_regs_len/get_regs}
#   
#   - ethtool_ops.{get_regs_len/get_regs} for r8169;
#   - fix a dubious check: datasheet v1.21 claims on p.44 that io/memory space
#     is exactly 256 bytes wide;
#   - use SET_ETHTOOL_OPS().
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
# 
# drivers/net/r8169.c
#   2004/08/23 17:29:58-04:00 romieu@fr.zoreil.com +23 -3
#   r8169: add ethtool_ops.{get_regs_len/get_regs}
# 
# ChangeSet
#   2004/08/28 19:06:15-04:00 rene.herman@keyaccess.nl 
#   [PATCH] 8139too Interframe Gap Time
# 
# drivers/net/8139too.c
#   2004/04/30 10:29:08-04:00 rene.herman@keyaccess.nl +9 -5
#   8139too Interframe Gap Time
# 
# ChangeSet
#   2004/08/28 19:00:51-04:00 akpm@osdl.org 
#   [PATCH] de4x5 warning fix
#   
#   Ugh.
#   
#   drivers/net/tulip/de4x5.c: In function `mii_get_phy':
#   drivers/net/tulip/de4x5.c:5092: warning: operation on `i' may be undefined
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/tulip/de4x5.c
#   2004/08/26 03:24:25-04:00 akpm@osdl.org +1 -1
#   de4x5 warning fix
# 
# ChangeSet
#   2004/08/28 18:53:53-04:00 akpm@osdl.org 
#   [PATCH] sparse: fix warnings in net/irda/*
#   
#   From: "Mika Kukkonen" <mika@osdl.org>
#   
#     CHECK   net/irda/irlan/irlan_client.c
#   net/irda/irlan/irlan_client.c:237:14: warning: assignment expression in
#   conditional
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# net/irda/irlan/irlan_client.c
#   2004/08/27 02:30:32-04:00 akpm@osdl.org +1 -1
#   sparse: fix warnings in net/irda/*
# 
# ChangeSet
#   2004/08/28 18:52:23-04:00 akpm@osdl.org 
#   [PATCH] defxx device name fixes
#   
#   From: "Maciej W. Rozycki" <macro@linux-mips.org>
#   
#   This is a fix for the "fddi%d" device name reported literally due to the
#   switch from init_fddidev() to alloc_fddidev().  Plus related updates to
#   module information.  Applies on top of the 2.4.27-defxx-sync2681 or
#   2.6.8.1-defxx-misc patches, respectively.  Please apply.
#   
#   Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/defxx.c
#   2004/08/24 22:18:36-04:00 akpm@osdl.org +68 -68
#   defxx device name fixes
# 
# ChangeSet
#   2004/08/28 18:52:12-04:00 akpm@osdl.org 
#   [PATCH] defxx trivial updates
#   
#   From: "Maciej W. Rozycki" <macro@linux-mips.org>
#   
#   Here are a few obvious clean-ups I did to the driver.
#   
#   Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/defxx.h
#   2004/08/24 22:18:36-04:00 akpm@osdl.org +1 -1
#   defxx trivial updates
# 
# drivers/net/defxx.c
#   2004/08/24 22:18:36-04:00 akpm@osdl.org +5 -5
#   defxx trivial updates
# 
# ChangeSet
#   2004/08/28 18:48:36-04:00 akpm@osdl.org 
#   [PATCH] wireless-drivers-update-for-we-17.patch
#   
#   From: Jean Tourrilhes <jt@bougret.hpl.hp.com>
#   
#   	This patch complement the main WE-17 patch I just sent you. It
#   updates a few driver to take advantage of WE-17. You should queue it
#   along with the other patch.
#   
#   	o Aironet driver :
#   		o iwspy data can be shared between eth0 and wifi0 if needed
#   		o allow arbitrarily large scan results (no longer limited)
#   		o export wireless event capabilities
#   	o Wavelan drivers :
#   		o export wireless event capabilities
#   
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/wireless/wavelan_cs.p.h
#   2004/08/06 11:20:00-04:00 akpm@osdl.org +3 -0
#   wireless-drivers-update-for-we-17.patch
# 
# drivers/net/wireless/wavelan_cs.c
#   2004/08/06 11:20:00-04:00 akpm@osdl.org +14 -9
#   wireless-drivers-update-for-we-17.patch
# 
# drivers/net/wireless/wavelan.p.h
#   2004/08/06 11:20:00-04:00 akpm@osdl.org +3 -0
#   wireless-drivers-update-for-we-17.patch
# 
# drivers/net/wireless/wavelan.c
#   2004/08/06 11:20:00-04:00 akpm@osdl.org +12 -7
#   wireless-drivers-update-for-we-17.patch
# 
# drivers/net/wireless/airo.c
#   2004/08/06 11:20:00-04:00 akpm@osdl.org +30 -15
#   wireless-drivers-update-for-we-17.patch
# 
# ChangeSet
#   2004/08/28 18:48:26-04:00 akpm@osdl.org 
#   [PATCH] wireless-extension-v17-for-linus.patch
#   
#   From: Jean Tourrilhes <jt@bougret.hpl.hp.com>
#   
#   	This is the patch to migrate Wireless Extension from WE-16 to
#   WE-17 for kernel 2.6.X. I would like you to queue that patch and
#   submit it to Linus as soon as 2.6.8 is released (so it can be fully
#   tested during 2.6.9). If you want, I can resend that as soon as 2.6.8
#   is released.
#   
#   	The patch is basically unchanged compared to the version
#   posted to the netdev list and my web page one month ago, I just
#   re-diff to the latest kernel (2.6.8-rc2-bk12). The patch already
#   included feedback from various driver maintainers, and nobody else
#   complained, so I guess it's ready.
#   	The patch for some drivers inside the kernel will follow
#   (airo.c, wavelan.c, wavelan_cs). Patch for various other drivers
#   (orinoco, hostap, prism54) have been sent already to their maintainers
#   (one month ago) and basically waiting for this patch.
#   
#   	Changelog :
#    *	- Add flags to frequency -> auto/fixed
#    *	- Document (struct iw_quality *)->updated, add new flags (INVALID)
#    *	- Wireless Event capability in struct iw_range
#    *	- Add support for relative TxPower (yick !)
#    *	- Change the way we get to spy_data method for added safety and hostap
#    *	- Remove spy #ifdef, they are always on -> cleaner code
#    *	- Allow any size GET request if user specifies length > max
#    *	- Start migrating get_wireless_stats to struct iw_handler_def
#    * Based on patch from Pavel Roskin <proski@gnu.org> :
#    *	- Fix kernel data leak to user space in private handler handling
#   
#   	I also added on my page a version of Wireless Tools that use
#   RtNetlink instead of ioctls. This is not as clean as I would like, but
#   is fully functional (if you have WE-19). I know that you were
#   interested, so feel free to send feedback on that...
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# net/core/wireless.c
#   2004/08/06 11:19:59-04:00 akpm@osdl.org +146 -66
#   wireless-extension-v17-for-linus.patch
# 
# include/net/iw_handler.h
#   2004/08/06 11:19:59-04:00 akpm@osdl.org +42 -18
#   wireless-extension-v17-for-linus.patch
# 
# include/linux/wireless.h
#   2004/08/06 11:19:59-04:00 akpm@osdl.org +52 -12
#   wireless-extension-v17-for-linus.patch
# 
# include/linux/netdevice.h
#   2004/08/06 11:19:59-04:00 akpm@osdl.org +3 -1
#   wireless-extension-v17-for-linus.patch
# 
diff -Nru a/arch/cris/arch-v10/drivers/ethernet.c b/arch/cris/arch-v10/drivers/ethernet.c
--- a/arch/cris/arch-v10/drivers/ethernet.c	2004-10-10 22:15:16 -07:00
+++ b/arch/cris/arch-v10/drivers/ethernet.c	2004-10-10 22:15:16 -07:00
@@ -401,7 +401,6 @@
 static void e100_rx(struct net_device *dev);
 static int e100_close(struct net_device *dev);
 static int e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-static int e100_ethtool_ioctl(struct net_device* dev, struct ifreq *ifr);
 static int e100_set_config(struct net_device* dev, struct ifmap* map);
 static void e100_tx_timeout(struct net_device *dev);
 static struct net_device_stats *e100_get_stats(struct net_device *dev);
@@ -410,6 +409,7 @@
 static void update_rx_stats(struct net_device_stats *);
 static void update_tx_stats(struct net_device_stats *);
 static int e100_probe_transceiver(void);
+static struct ethtool_ops ethtool_ops;
 
 static void e100_check_speed(unsigned long dummy);
 static void e100_set_speed(unsigned long speed);
@@ -483,6 +483,7 @@
 	dev->do_ioctl           = e100_ioctl;
 	dev->set_config		= e100_set_config;
 	dev->tx_timeout         = e100_tx_timeout;
+	SET_ETHTOOL_OPS(dev, &ethtool_ops);
 
 	/* Initialise the list of Etrax DMA-descriptors */
 
@@ -1401,8 +1402,6 @@
 
 	spin_lock(&np->lock); /* Preempt protection */
 	switch (cmd) {
-		case SIOCETHTOOL:
-			return e100_ethtool_ioctl(dev,ifr);
 		case SIOCGMIIPHY: /* Get PHY address */
 			data->phy_id = mdio_phy_addr;
 			break;
@@ -1439,87 +1438,70 @@
 	return 0;
 }
 
-static int
-e100_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
+static int e100_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
-	struct ethtool_cmd ecmd;
-
-	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd)))
-		return -EFAULT;
+	ecmd->supported = 
+	  SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |
+	  SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | 
+	  SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
+	ecmd->port = PORT_TP;
+	ecmd->transceiver = XCVR_EXTERNAL;
+	ecmd->phy_address = mdio_phy_addr;
+	ecmd->speed = current_speed;
+	ecmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+	ecmd->advertising = ADVERTISED_TP;
+	if (current_duplex == autoneg && current_speed_selection == 0)
+		ecmd->advertising |= ADVERTISED_Autoneg;
+	else {
+		ecmd->advertising |= 
+		  ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+		  ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
+		if (current_speed_selection == 10)
+			ecmd->advertising &= ~(ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full);
+		else if (current_speed_selection == 100)
+			ecmd->advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full);
+		if (current_duplex == half)
+			ecmd->advertising &= ~(ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Full);
+		else if (current_duplex == full)
+			ecmd->advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_100baseT_Half);
+	}
+	ecmd->autoneg = AUTONEG_ENABLE;
+	return 0;
+}
 
-	switch (ecmd.cmd) {
-		case ETHTOOL_GSET:
-		{
-			memset((void *) &ecmd, 0, sizeof (ecmd));
-			ecmd.supported = 
-			  SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |
-			  SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | 
-			  SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
-			ecmd.port = PORT_TP;
-			ecmd.transceiver = XCVR_EXTERNAL;
-			ecmd.phy_address = mdio_phy_addr;
-			ecmd.speed = current_speed;
-			ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-			ecmd.advertising = ADVERTISED_TP;
-			if (current_duplex == autoneg && current_speed_selection == 0)
-				ecmd.advertising |= ADVERTISED_Autoneg;
-			else {
-				ecmd.advertising |= 
-				  ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
-				  ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
-				if (current_speed_selection == 10)
-					ecmd.advertising &= ~(ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full);
-				else if (current_speed_selection == 100)
-					ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full);
-				if (current_duplex == half)
-					ecmd.advertising &= ~(ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Full);
-				else if (current_duplex == full)
-					ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_100baseT_Half);
-			}
-			ecmd.autoneg = AUTONEG_ENABLE;
-			if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd)))
-				return -EFAULT;
-		}
-		break;
-		case ETHTOOL_SSET:
-		{
-			if (!capable(CAP_NET_ADMIN)) {
-				return -EPERM;
-			}
-			if (ecmd.autoneg == AUTONEG_ENABLE) {
-				e100_set_duplex(autoneg);
-				e100_set_speed(0);
-			} else {
-				e100_set_duplex(ecmd.duplex == DUPLEX_HALF ? half : full);
-				e100_set_speed(ecmd.speed == SPEED_10 ? 10: 100);
-			}
-		}
-		break;
-		case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info;
-			memset((void *) &info, 0, sizeof (info));
-			strncpy(info.driver, "ETRAX 100LX", sizeof(info.driver) - 1);
-			strncpy(info.version, "$Revision: 1.22 $", sizeof(info.version) - 1);
-			strncpy(info.fw_version, "N/A", sizeof(info.fw_version) - 1);
-			strncpy(info.bus_info, "N/A", sizeof(info.bus_info) - 1);
-			info.regdump_len = 0;
-			info.eedump_len = 0;
-			info.testinfo_len = 0;
-			if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
-				return -EFAULT;
-		}
-		break;
-		case ETHTOOL_NWAY_RST:
-			if (current_duplex == autoneg && current_speed_selection == 0)
-				e100_negotiate();
-		break;
-		default:
-			return -EOPNOTSUPP;
-		break;
+static int e100_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	if (ecmd->autoneg == AUTONEG_ENABLE) {
+		e100_set_duplex(autoneg);
+		e100_set_speed(0);
+	} else {
+		e100_set_duplex(ecmd->duplex == DUPLEX_HALF ? half : full);
+		e100_set_speed(ecmd->speed == SPEED_10 ? 10: 100);
 	}
 	return 0;
 }
+
+static void e100_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strncpy(info->driver, "ETRAX 100LX", sizeof(info->driver) - 1);
+	strncpy(info->version, "$Revision: 1.22 $", sizeof(info->version) - 1);
+	strncpy(info->fw_version, "N/A", sizeof(info->fw_version) - 1);
+	strncpy(info->bus_info, "N/A", sizeof(info->bus_info) - 1);
+}
+
+static int e100_nway_reset(struct net_device *dev)
+{
+	if (current_duplex == autoneg && current_speed_selection == 0)
+		e100_negotiate();
+	return 0;
+}
+
+static struct ethtool_ops ethtool_ops = {
+	.get_settings = e100_get_settings,
+	.set_settings = e100_set_settings,
+	.get_drvinfo = e100_get_drvinfo,
+	.nway_reset = e100_nway_reset,
+};
 
 static int
 e100_set_config(struct net_device *dev, struct ifmap *map)
diff -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
--- a/drivers/ieee1394/eth1394.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/ieee1394/eth1394.c	2004-10-10 22:15:16 -07:00
@@ -190,8 +190,7 @@
 static int ether1394_tx(struct sk_buff *skb, struct net_device *dev);
 static void ether1394_iso(struct hpsb_iso *iso);
 
-static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-static int ether1394_ethtool_ioctl(struct net_device *dev, void __user *useraddr);
+static struct ethtool_ops ethtool_ops;
 
 static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
 			   quadlet_t *data, u64 addr, size_t len, u16 flags);
@@ -216,7 +215,7 @@
 /* This is called after an "ifup" */
 static int ether1394_open (struct net_device *dev)
 {
-	struct eth1394_priv *priv = dev->priv;
+	struct eth1394_priv *priv = netdev_priv(dev);
 	int ret = 0;
 
 	/* Something bad happened, don't even try */
@@ -261,7 +260,7 @@
 /* Return statistics to the caller */
 static struct net_device_stats *ether1394_stats (struct net_device *dev)
 {
-	return &(((struct eth1394_priv *)dev->priv)->stats);
+	return &(((struct eth1394_priv *)netdev_priv(dev))->stats);
 }
 
 /* What to do if we timeout. I think a host reset is probably in order, so
@@ -269,16 +268,16 @@
 static void ether1394_tx_timeout (struct net_device *dev)
 {
 	ETH1394_PRINT (KERN_ERR, dev->name, "Timeout, resetting host %s\n",
-		       ((struct eth1394_priv *)(dev->priv))->host->driver->name);
+		       ((struct eth1394_priv *)netdev_priv(dev))->host->driver->name);
 
-	highlevel_host_reset (((struct eth1394_priv *)(dev->priv))->host);
+	highlevel_host_reset (((struct eth1394_priv *)netdev_priv(dev))->host);
 
 	netif_wake_queue (dev);
 }
 
 static int ether1394_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct eth1394_priv *priv = dev->priv;
+	struct eth1394_priv *priv = netdev_priv(dev);
 
 	if ((new_mtu < 68) ||
 	    (new_mtu > min(ETH1394_DATA_LEN,
@@ -379,7 +378,7 @@
 	ud->device.driver_data = node_info;
 	new_node->ud = ud;
 
-	priv = (struct eth1394_priv *)hi->dev->priv;
+	priv = netdev_priv(hi->dev);
 	list_add_tail(&new_node->list, &priv->ip_node_list);
 
 	return 0;
@@ -400,7 +399,7 @@
 	if (!hi)
 		return -ENOENT;
 
-	priv = (struct eth1394_priv *)hi->dev->priv;
+	priv = netdev_priv(hi->dev);
 
 	old_node = eth1394_find_node(&priv->ip_node_list, ud);
 
@@ -435,7 +434,7 @@
 	if (!hi)
 		return -ENOENT;
 
-	priv = (struct eth1394_priv *)hi->dev->priv;
+	priv = netdev_priv(hi->dev);
 
 	node = eth1394_find_node(&priv->ip_node_list, ud);
 
@@ -459,7 +458,7 @@
 		ud->device.driver_data = node_info;
 		node->ud = ud;
 
-		priv = (struct eth1394_priv *)hi->dev->priv;
+		priv = netdev_priv(hi->dev);
 		list_add_tail(&node->list, &priv->ip_node_list);
 	}
 
@@ -496,7 +495,7 @@
 {
 	unsigned long flags;
 	int i;
-	struct eth1394_priv *priv = dev->priv;
+	struct eth1394_priv *priv = netdev_priv(dev);
 	struct hpsb_host *host = priv->host;
 	u64 guid = *((u64*)&(host->csr.rom->bus_info_data[3]));
 	u16 maxpayload = 1 << (host->csr.max_rec + 1);
@@ -547,7 +546,7 @@
 	dev->header_cache_update= ether1394_header_cache_update;
 	dev->hard_header_parse	= ether1394_header_parse;
 	dev->set_mac_address	= ether1394_mac_addr;
-	dev->do_ioctl		= ether1394_do_ioctl;
+	SET_ETHTOOL_OPS(dev, &ethtool_ops);
 
 	/* Some constants */
 	dev->watchdog_timeo	= ETHER1394_TIMEOUT;
@@ -602,7 +601,7 @@
 
 	SET_MODULE_OWNER(dev);
 
-	priv = (struct eth1394_priv *)dev->priv;
+	priv = netdev_priv(dev);
 
 	INIT_LIST_HEAD(&priv->ip_node_list);
 
@@ -672,7 +671,7 @@
 
 	hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
 	if (hi != NULL) {
-		struct eth1394_priv *priv = (struct eth1394_priv *)hi->dev->priv;
+		struct eth1394_priv *priv = netdev_priv(hi->dev);
 
 		hpsb_unregister_addrspace(&eth1394_highlevel, host,
 					  priv->local_fifo);
@@ -707,7 +706,7 @@
 		return;
 
 	dev = hi->dev;
-	priv = (struct eth1394_priv *)dev->priv;
+	priv = netdev_priv(dev);
 
 	/* Reset our private host data, but not our mtu */
 	netif_stop_queue (dev);
@@ -882,7 +881,7 @@
 					nodeid_t srcid, nodeid_t destid,
 					u16 ether_type)
 {
-	struct eth1394_priv *priv = dev->priv;
+	struct eth1394_priv *priv = netdev_priv(dev);
 	u64 dest_hw;
 	unsigned short ret = 0;
 
@@ -1112,7 +1111,7 @@
 {
 	struct sk_buff *skb;
 	unsigned long flags;
-	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
+	struct eth1394_priv *priv = netdev_priv(dev);
 	union eth1394_hdr *hdr = (union eth1394_hdr *)buf;
 	u16 ether_type = 0;  /* initialized to clear warning */
 	int hdr_len;
@@ -1350,7 +1349,7 @@
 				((be32_to_cpu(data[1]) & 0xff000000) >> 24));
 		source_id = be32_to_cpu(data[0]) >> 16;
 
-		priv = (struct eth1394_priv *)dev->priv;
+		priv = netdev_priv(dev);
 
 		if (info->channel != (iso->host->csr.broadcast_channel & 0x3f) ||
 		   specifier_id != ETHER1394_GASP_SPECIFIER_ID) {
@@ -1384,7 +1383,7 @@
 static inline void ether1394_arp_to_1394arp(struct sk_buff *skb,
 					    struct net_device *dev)
 {
-	struct eth1394_priv *priv = (struct eth1394_priv *)(dev->priv);
+	struct eth1394_priv *priv = netdev_priv(dev);
 
 	struct arphdr *arp = (struct arphdr *)skb->data;
 	unsigned char *arp_ptr = (unsigned char *)(arp + 1);
@@ -1582,7 +1581,7 @@
 {
 	struct sk_buff *skb = ptask->skb;
 	struct net_device *dev = skb->dev;
-	struct eth1394_priv *priv = dev->priv;
+	struct eth1394_priv *priv = netdev_priv(dev);
         unsigned long flags;
 
 	/* Statistics */
@@ -1635,7 +1634,7 @@
 {
 	int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
 	struct eth1394hdr *eth;
-	struct eth1394_priv *priv = dev->priv;
+	struct eth1394_priv *priv = netdev_priv(dev);
 	int proto;
 	unsigned long flags;
 	nodeid_t dest_node;
@@ -1768,53 +1767,17 @@
 	return 0;  /* returning non-zero causes serious problems */
 }
 
-static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	switch(cmd) {
-		case SIOCETHTOOL:
-			return ether1394_ethtool_ioctl(dev, ifr->ifr_data);
-
-		case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-		case SIOCGMIIREG:		/* Read MII PHY register. */
-		case SIOCSMIIREG:		/* Write MII PHY register. */
-		default:
-			return -EOPNOTSUPP;
-	}
-
-	return 0;
-}
-
-static int ether1394_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
-{
-	u32 ethcmd;
-
-	if (get_user(ethcmd, (u32 __user *)useraddr))
-		return -EFAULT;
-
-	switch (ethcmd) {
-		case ETHTOOL_GDRVINFO: {
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy (info.driver, driver_name);
-			strcpy (info.version, "$Rev: 1224 $");
-			/* FIXME XXX provide sane businfo */
-			strcpy (info.bus_info, "ieee1394");
-			if (copy_to_user (useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			break;
-		}
-		case ETHTOOL_GSET:
-		case ETHTOOL_SSET:
-		case ETHTOOL_NWAY_RST:
-		case ETHTOOL_GLINK:
-		case ETHTOOL_GMSGLVL:
-		case ETHTOOL_SMSGLVL:
-		default:
-			return -EOPNOTSUPP;
-	}
-
-	return 0;
+	strcpy (info->driver, driver_name);
+	strcpy (info->version, "$Rev: 1224 $");
+	/* FIXME XXX provide sane businfo */
+	strcpy (info->bus_info, "ieee1394");
 }
 
+static struct ethtool_ops ethtool_ops = {
+	.get_drvinfo = ether1394_get_drvinfo
+};
 
 static int __init ether1394_init_module (void)
 {
diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
--- a/drivers/media/dvb/dvb-core/dvb_net.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/media/dvb/dvb-core/dvb_net.c	2004-10-10 22:15:16 -07:00
@@ -919,14 +919,6 @@
 }
 
 
-static int dvb_net_set_config(struct net_device *dev, struct ifmap *map)
-{
-	if (netif_running(dev))
-		return -EBUSY;
-	return 0;
-}
-
-
 static void wq_restart_net_feed (void *data)
 {
 	struct net_device *dev = data;
@@ -985,7 +977,6 @@
 	dev->hard_start_xmit	= dvb_net_tx;
 	dev->get_stats		= dvb_net_get_stats;
 	dev->set_multicast_list = dvb_net_set_multicast_list;
-	dev->set_config         = dvb_net_set_config;
 	dev->set_mac_address    = dvb_net_set_mac;
 	dev->mtu		= 4096;
 	dev->mc_count           = 0;
diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c
--- a/drivers/net/3c509.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/3c509.c	2004-10-10 22:15:16 -07:00
@@ -197,9 +197,9 @@
 static int el3_close(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static void el3_tx_timeout (struct net_device *dev);
-static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 static void el3_down(struct net_device *dev);
 static void el3_up(struct net_device *dev);
+static struct ethtool_ops ethtool_ops;
 #ifdef CONFIG_PM
 static int el3_suspend(struct pm_dev *pdev);
 static int el3_resume(struct pm_dev *pdev);
@@ -321,7 +321,7 @@
 	dev->set_multicast_list = &set_multicast_list;
 	dev->tx_timeout = el3_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->do_ioctl = netdev_ioctl;
+	SET_ETHTOOL_OPS(dev, &ethtool_ops);
 
 	err = register_netdev(dev);
 	if (err) {
@@ -1285,122 +1285,63 @@
 	return 0;
 }
 
-/**
- * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
- * @dev: network interface on which out-of-band action is to be performed
- * @useraddr: userspace address to which data is to be read and returned
- *
- * Process the various commands of the SIOCETHTOOL interface.
- */
+static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+}
 
-static int
-netdev_ethtool_ioctl (struct net_device *dev, void __user *useraddr)
+static int el3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
-	u32 ethcmd;
 	struct el3_private *lp = netdev_priv(dev);
+	int ret;
 
-	/* dev_ioctl() in ../../net/core/dev.c has already checked
-	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
-
-	if (get_user(ethcmd, (u32 __user *)useraddr))
-		return -EFAULT;
-
-	switch (ethcmd) {
-
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-		strcpy (info.driver, DRV_NAME);
-		strcpy (info.version, DRV_VERSION);
-		if (copy_to_user (useraddr, &info, sizeof (info)))
-			return -EFAULT;
-		return 0;
-	}
-
-	/* get settings */
-	case ETHTOOL_GSET: {
-		int ret;
-		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-		spin_lock_irq(&lp->lock);
-		ret = el3_netdev_get_ecmd(dev, &ecmd);
-		spin_unlock_irq(&lp->lock);
-		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return ret;
-	}
-
-	/* set settings */
-	case ETHTOOL_SSET: {
-		int ret;
-		struct ethtool_cmd ecmd;
-		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-			return -EFAULT;
-		spin_lock_irq(&lp->lock);
-		ret = el3_netdev_set_ecmd(dev, &ecmd);
-		spin_unlock_irq(&lp->lock);
-		return ret;
-	}
-
-	/* get link status */
-	case ETHTOOL_GLINK: {
-		struct ethtool_value edata = { ETHTOOL_GLINK };
-		spin_lock_irq(&lp->lock);
-		edata.data = el3_link_ok(dev);
-		spin_unlock_irq(&lp->lock);
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-
-	/* get message-level */
-	case ETHTOOL_GMSGLVL: {
-		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
-		edata.data = el3_debug;
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set message-level */
-	case ETHTOOL_SMSGLVL: {
-		struct ethtool_value edata;
-		if (copy_from_user(&edata, useraddr, sizeof(edata)))
-			return -EFAULT;
-		el3_debug = edata.data;
-		return 0;
-	}
+	spin_lock_irq(&lp->lock);
+	ret = el3_netdev_get_ecmd(dev, ecmd);
+	spin_unlock_irq(&lp->lock);
+	return ret;
+}
 
-	default:
-		break;
-	}
+static int el3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct el3_private *lp = netdev_priv(dev);
+	int ret;
 
-	return -EOPNOTSUPP;
+	spin_lock_irq(&lp->lock);
+	ret = el3_netdev_set_ecmd(dev, ecmd);
+	spin_unlock_irq(&lp->lock);
+	return ret;
 }
 
-/**
- * netdev_ioctl: Handle network interface ioctls
- * @dev: network interface on which out-of-band action is to be performed
- * @rq: user request data
- * @cmd: command issued by user
- *
- * Process the various out-of-band ioctls passed to this driver.
- */
-
-static int
-netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+static u32 el3_get_link(struct net_device *dev)
 {
-	int rc = 0;
+	struct el3_private *lp = netdev_priv(dev);
+	u32 ret;
 
-	switch (cmd) {
-	case SIOCETHTOOL:
-		rc = netdev_ethtool_ioctl(dev, rq->ifr_data);
-		break;
+	spin_lock_irq(&lp->lock);
+	ret = el3_link_ok(dev);
+	spin_unlock_irq(&lp->lock);
+	return ret;
+}
 
-	default:
-		rc = -EOPNOTSUPP;
-		break;
-	}
+static u32 el3_get_msglevel(struct net_device *dev)
+{
+	return el3_debug;
+}
 
-	return rc;
+static void el3_set_msglevel(struct net_device *dev, u32 v)
+{
+	el3_debug = v;
 }
+
+static struct ethtool_ops ethtool_ops = {
+	.get_drvinfo = el3_get_drvinfo,
+	.get_settings = el3_get_settings,
+	.set_settings = el3_set_settings,
+	.get_link = el3_get_link,
+	.get_msglevel = el3_get_msglevel,
+	.set_msglevel = el3_set_msglevel,
+};
 
 static void
 el3_down(struct net_device *dev)
diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c
--- a/drivers/net/8139cp.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/8139cp.c	2004-10-10 22:15:16 -07:00
@@ -54,6 +54,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/netdevice.h>
@@ -90,16 +91,17 @@
 
 MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
 MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");
+MODULE_VERSION(DRV_VERSION);
 MODULE_LICENSE("GPL");
 
 static int debug = -1;
-MODULE_PARM (debug, "i");
+module_param(debug, int, 0);
 MODULE_PARM_DESC (debug, "8139cp: bitmapped message enable number");
 
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
    The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
 static int multicast_filter_limit = 32;
-MODULE_PARM (multicast_filter_limit, "i");
+module_param(multicast_filter_limit, int, 0);
 MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered multicast addresses");
 
 #define PFX			DRV_NAME ": "
@@ -185,6 +187,9 @@
 	RingEnd		= (1 << 30), /* End of descriptor ring */
 	FirstFrag	= (1 << 29), /* First segment of a packet */
 	LastFrag	= (1 << 28), /* Final segment of a packet */
+	LargeSend	= (1 << 27), /* TCP Large Send Offload (TSO) */
+	MSSShift	= 16,	     /* MSS value position */
+	MSSMask		= 0xfff,     /* MSS value: 11 bits */
 	TxError		= (1 << 23), /* Tx error summary */
 	RxError		= (1 << 20), /* Rx error summary */
 	IPCS		= (1 << 18), /* Calculate IP checksum */
@@ -311,7 +316,7 @@
 struct ring_info {
 	struct sk_buff		*skb;
 	dma_addr_t		mapping;
-	unsigned		frag;
+	u32			len;
 };
 
 struct cp_dma_stats {
@@ -394,6 +399,9 @@
 static void __cp_set_rx_mode (struct net_device *dev);
 static void cp_tx (struct cp_private *cp);
 static void cp_clean_rings (struct cp_private *cp);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void cp_poll_controller(struct net_device *dev);
+#endif
 
 static struct pci_device_id cp_pci_tbl[] = {
 	{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
@@ -686,6 +694,19 @@
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void cp_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	cp_interrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 static void cp_tx (struct cp_private *cp)
 {
 	unsigned tx_head = cp->tx_head;
@@ -705,7 +726,7 @@
 			BUG();
 
 		pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
-					skb->len, PCI_DMA_TODEVICE);
+				 cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
 
 		if (status & LastFrag) {
 			if (status & (TxError | TxFIFOUnder)) {
@@ -747,10 +768,11 @@
 {
 	struct cp_private *cp = netdev_priv(dev);
 	unsigned entry;
-	u32 eor;
+	u32 eor, flags;
 #if CP_VLAN_TAG_USED
 	u32 vlan_tag = 0;
 #endif
+	int mss = 0;
 
 	spin_lock_irq(&cp->lock);
 
@@ -770,6 +792,9 @@
 
 	entry = cp->tx_head;
 	eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
+	if (dev->features & NETIF_F_TSO)
+		mss = skb_shinfo(skb)->tso_size;
+
 	if (skb_shinfo(skb)->nr_frags == 0) {
 		struct cp_desc *txd = &cp->tx_ring[entry];
 		u32 len;
@@ -781,26 +806,26 @@
 		txd->addr = cpu_to_le64(mapping);
 		wmb();
 
-		if (skb->ip_summed == CHECKSUM_HW) {
+		flags = eor | len | DescOwn | FirstFrag | LastFrag;
+
+		if (mss)
+			flags |= LargeSend | ((mss & MSSMask) << MSSShift);
+		else if (skb->ip_summed == CHECKSUM_HW) {
 			const struct iphdr *ip = skb->nh.iph;
 			if (ip->protocol == IPPROTO_TCP)
-				txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-							 FirstFrag | LastFrag |
-							 IPCS | TCPCS);
+				flags |= IPCS | TCPCS;
 			else if (ip->protocol == IPPROTO_UDP)
-				txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-							 FirstFrag | LastFrag |
-							 IPCS | UDPCS);
+				flags |= IPCS | UDPCS;
 			else
-				BUG();
-		} else
-			txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-						 FirstFrag | LastFrag);
+				WARN_ON(1);	/* we need a WARN() */
+		}
+
+		txd->opts1 = cpu_to_le32(flags);
 		wmb();
 
 		cp->tx_skb[entry].skb = skb;
 		cp->tx_skb[entry].mapping = mapping;
-		cp->tx_skb[entry].frag = 0;
+		cp->tx_skb[entry].len = len;
 		entry = NEXT_TX(entry);
 	} else {
 		struct cp_desc *txd;
@@ -818,7 +843,7 @@
 					       first_len, PCI_DMA_TODEVICE);
 		cp->tx_skb[entry].skb = skb;
 		cp->tx_skb[entry].mapping = first_mapping;
-		cp->tx_skb[entry].frag = 1;
+		cp->tx_skb[entry].len = first_len;
 		entry = NEXT_TX(entry);
 
 		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@@ -834,16 +859,19 @@
 						 len, PCI_DMA_TODEVICE);
 			eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
 
-			if (skb->ip_summed == CHECKSUM_HW) {
-				ctrl = eor | len | DescOwn | IPCS;
+			ctrl = eor | len | DescOwn;
+
+			if (mss)
+				ctrl |= LargeSend |
+					((mss & MSSMask) << MSSShift);
+			else if (skb->ip_summed == CHECKSUM_HW) {
 				if (ip->protocol == IPPROTO_TCP)
-					ctrl |= TCPCS;
+					ctrl |= IPCS | TCPCS;
 				else if (ip->protocol == IPPROTO_UDP)
-					ctrl |= UDPCS;
+					ctrl |= IPCS | UDPCS;
 				else
 					BUG();
-			} else
-				ctrl = eor | len | DescOwn;
+			}
 
 			if (frag == skb_shinfo(skb)->nr_frags - 1)
 				ctrl |= LastFrag;
@@ -858,7 +886,7 @@
 
 			cp->tx_skb[entry].skb = skb;
 			cp->tx_skb[entry].mapping = mapping;
-			cp->tx_skb[entry].frag = frag + 2;
+			cp->tx_skb[entry].len = len;
 			entry = NEXT_TX(entry);
 		}
 
@@ -1072,7 +1100,6 @@
 		cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
 			skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
 		cp->rx_skb[i].skb = skb;
-		cp->rx_skb[i].frag = 0;
 
 		cp->rx_ring[i].opts2 = 0;
 		cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping);
@@ -1124,9 +1151,6 @@
 {
 	unsigned i;
 
-	memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
-	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
-
 	for (i = 0; i < CP_RX_RING_SIZE; i++) {
 		if (cp->rx_skb[i].skb) {
 			pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping,
@@ -1138,13 +1162,18 @@
 	for (i = 0; i < CP_TX_RING_SIZE; i++) {
 		if (cp->tx_skb[i].skb) {
 			struct sk_buff *skb = cp->tx_skb[i].skb;
+
 			pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping,
-					 skb->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb(skb);
+				 	 cp->tx_skb[i].len, PCI_DMA_TODEVICE);
+			if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag)
+				dev_kfree_skb(skb);
 			cp->net_stats.tx_dropped++;
 		}
 	}
 
+	memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
+	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
+
 	memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
 	memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
 }
@@ -1536,6 +1565,8 @@
 	.set_tx_csum		= ethtool_op_set_tx_csum, /* local! */
 	.get_sg			= ethtool_op_get_sg,
 	.set_sg			= ethtool_op_set_sg,
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= ethtool_op_set_tso,
 	.get_regs		= cp_get_regs,
 	.get_wol		= cp_get_wol,
 	.set_wol		= cp_set_wol,
@@ -1747,6 +1778,9 @@
 	dev->get_stats = cp_get_stats;
 	dev->do_ioctl = cp_ioctl;
 	dev->poll = cp_rx_poll;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = cp_poll_controller;
+#endif
 	dev->weight = 16;	/* arbitrary? from NAPI_HOWTO.txt. */
 #ifdef BROKEN
 	dev->change_mtu = cp_change_mtu;
@@ -1765,6 +1799,10 @@
 
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
+
+#if 0 /* disabled by default until verified */
+	dev->features |= NETIF_F_TSO;
+#endif
 
 	dev->irq = pdev->irq;
 
diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	2004-10-10 22:15:15 -07:00
+++ b/drivers/net/8139too.c	2004-10-10 22:15:15 -07:00
@@ -390,8 +390,14 @@
 
 /* Bits in TxConfig. */
 enum tx_config_bits {
-	TxIFG1 = (1 << 25),	/* Interframe Gap Time */
-	TxIFG0 = (1 << 24),	/* Enabling these bits violates IEEE 802.3 */
+
+        /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */
+        TxIFGShift = 24,
+        TxIFG84 = (0 << TxIFGShift),    /* 8.4us / 840ns (10 / 100Mbps) */
+        TxIFG88 = (1 << TxIFGShift),    /* 8.8us / 880ns (10 / 100Mbps) */
+        TxIFG92 = (2 << TxIFGShift),    /* 9.2us / 920ns (10 / 100Mbps) */
+        TxIFG96 = (3 << TxIFGShift),    /* 9.6us / 960ns (10 / 100Mbps) */
+
 	TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
 	TxCRC = (1 << 16),	/* DISABLE appending CRC to end of Tx packets */
 	TxClearAbt = (1 << 0),	/* Clear abort (WO) */
@@ -724,7 +730,7 @@
 #endif
 
 static const unsigned int rtl8139_tx_config =
-	(TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift);
+	TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift);
 
 static void __rtl8139_cleanup_dev (struct net_device *dev)
 {
@@ -1400,8 +1406,6 @@
 
 	tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys;
 	RTL_W32 (RxConfig, tp->rx_config);
-
-	/* Check this value: the documentation for IFG contradicts ifself. */
 	RTL_W32 (TxConfig, rtl8139_tx_config);
 
 	tp->cur_rx = 0;
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/Kconfig	2004-10-10 22:15:16 -07:00
@@ -1398,16 +1398,6 @@
 	  will be called eepro100.
 
 
-config EEPRO100_PIO
-	bool "Use PIO instead of MMIO" if !X86_VISWS
-	depends on EEPRO100
-	default y if X86_VISWS
-	help
-	  This instructs the driver to use programmed I/O ports (PIO) instead
-	  of PCI shared memory (MMIO).  This can possibly solve some problems
-	  in case your mainboard has memory consistency issues.  If unsure,
-	  say N.
-
 config E100
 	tristate "Intel(R) PRO/100+ support"
 	depends on NET_PCI && PCI
@@ -1730,7 +1720,7 @@
 	  (e.g. VT8235).
 
 	  To compile this driver as a module, choose M here. The module
-	  will be called via-rhine.
+	  will be called via-velocity.
 
 config VIA_RHINE_MMIO
 	bool "Use MMIO instead of PIO"
@@ -1742,18 +1732,6 @@
 
 	  If unsure, say Y.
 
-config VIA_VELOCITY
-	tristate "VIA Velocity support"
-	depends on NET_PCI && PCI
-	select CRC32
-	select CRC_CCITT
-	select MII
-	help
-	  If you have a VIA "Velocity" based network card say Y here.
-
-	  To compile this driver as a module, choose M here. The module
-	  will be called via-velocity.
-
 config LAN_SAA9730
 	bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)"
 	depends on NET_PCI && EXPERIMENTAL && MIPS
@@ -2061,6 +2039,15 @@
 
 	  If in doubt, say N.
 
+config R8169_VLAN
+	bool "VLAN support"
+	depends on R8169 && VLAN_8021Q
+	---help---
+	  Say Y here for the r8169 driver to support the functions required
+	  by the kernel 802.1Q code.
+	  
+	  If in doubt, say Y.
+
 config SK98LIN
 	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
 	depends on PCI
@@ -2139,6 +2126,18 @@
 	  inserted in and removed from the running kernel whenever you want),
 	  say M here and read Documentation/kbuild/modules.txt. The module will
 	  be called sk98lin. This is recommended.
+
+config VIA_VELOCITY
+	tristate "VIA Velocity support"
+	depends on NET_PCI && PCI
+	select CRC32
+	select CRC_CCITT
+	select MII
+	help
+	  If you have a VIA "Velocity" based network card say Y here.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called via-velocity.
 
 config TIGON3
 	tristate "Broadcom Tigon3 support"
diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c
--- a/drivers/net/acenic.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/acenic.c	2004-10-10 22:15:16 -07:00
@@ -444,7 +444,7 @@
 MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
 
 
-static char version[] __initdata = 
+static char version[] __devinitdata = 
   "acenic.c: v0.92 08/05/2002  Jes Sorensen, linux-acenic@SunSITE.dk\n"
   "                            http://home.cern.ch/~jes/gige/acenic.html\n";
 
@@ -539,7 +539,7 @@
 	 * addresses but who gives a damn.
 	 */
 	dev->base_addr = pci_resource_start(pdev, 0);
-	ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000);
+	ap->regs = ioremap(dev->base_addr, 0x4000);
 	if (!ap->regs) {
 		printk(KERN_ERR "%s:  Unable to map I/O register, "
 		       "AceNIC %i will be disabled.\n",
@@ -632,7 +632,7 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	short i;
 
 	unregister_netdev(dev);
@@ -885,7 +885,7 @@
 /*
  * Commands are considered to be slow.
  */
-static inline void ace_issue_cmd(struct ace_regs *regs, struct cmd *cmd)
+static inline void ace_issue_cmd(struct ace_regs __iomem *regs, struct cmd *cmd)
 {
 	u32 idx;
 
@@ -898,10 +898,10 @@
 }
 
 
-static int __init ace_init(struct net_device *dev)
+static int __devinit ace_init(struct net_device *dev)
 {
 	struct ace_private *ap;
-	struct ace_regs *regs;
+	struct ace_regs __iomem *regs;
 	struct ace_info *info = NULL;
 	struct pci_dev *pdev;
 	unsigned long myjif;
@@ -1319,11 +1319,10 @@
 	writel(TX_RING_BASE, &regs->WinBase);
 
 	if (ACE_IS_TIGON_I(ap)) {
-		ap->tx_ring = (struct tx_desc *)regs->Window;
-		for (i = 0; i < (TIGON_I_TX_RING_ENTRIES * 
-				 sizeof(struct tx_desc) / 4); i++) {
-			writel(0, (unsigned long)ap->tx_ring + i * 4);
-		}
+		ap->tx_ring = (struct tx_desc *) regs->Window;
+		for (i = 0; i < (TIGON_I_TX_RING_ENTRIES 
+				 * sizeof(struct tx_desc)) / sizeof(u32); i++)
+			writel(0, (void __iomem *)ap->tx_ring  + i * 4);
 
 		set_aceaddr(&info->tx_ctrl.rngptr, TX_RING_BASE);
 	} else {
@@ -1550,14 +1549,9 @@
 
 static void ace_set_rxtx_parms(struct net_device *dev, int jumbo)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
-	int board_idx;
-
-	ap = netdev_priv(dev);
-	regs = ap->regs;
-
-	board_idx = ap->board_idx;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	int board_idx = ap->board_idx;
 
 	if (board_idx >= 0) {
 		if (!jumbo) {
@@ -1595,7 +1589,7 @@
 {
 	struct net_device *dev = data;
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 
 	/*
 	 * We haven't received a stats update event for more than 2.5
@@ -1618,7 +1612,7 @@
 
 static void ace_tasklet(unsigned long dev)
 {
-	struct ace_private *ap = ((struct net_device *)dev)->priv;
+	struct ace_private *ap = netdev_priv((struct net_device *)dev);
 	int cur_size;
 
 	cur_size = atomic_read(&ap->cur_rx_bufs);
@@ -1676,10 +1670,9 @@
  */
 static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs)
 {
-	struct ace_regs *regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	short i, idx;
-
-	regs = ap->regs;
+	
 
 	prefetchw(&ap->cur_rx_bufs);
 
@@ -1740,11 +1733,9 @@
 
 static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs)
 {
-	struct ace_regs *regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	short i, idx;
 
-	regs = ap->regs;
-
 	prefetchw(&ap->cur_mini_bufs);
 
 	idx = ap->rx_mini_skbprd;
@@ -1799,11 +1790,9 @@
  */
 static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs)
 {
-	struct ace_regs *regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	short i, idx;
 
-	regs = ap->regs;
-
 	idx = ap->rx_jumbo_skbprd;
 
 	for (i = 0; i < nr_bufs; i++) {
@@ -2083,8 +2072,7 @@
 	 * the 12.3.x Firmware - my Tigon I NICs seem to disagree!
 	 */
 	if (ACE_IS_TIGON_I(ap)) {
-		struct ace_regs *regs = ap->regs;
-		writel(idx, &regs->RxRetCsm);
+		writel(idx, &ap->regs->RxRetCsm);
 	}
 	ap->cur_rx = idx;
 
@@ -2164,16 +2152,13 @@
 
 static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
 	struct net_device *dev = (struct net_device *)dev_id;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 	u32 idx;
 	u32 txcsm, rxretcsm, rxretprd;
 	u32 evtcsm, evtprd;
 
-	ap = netdev_priv(dev);
-	regs = ap->regs;
-
 	/*
 	 * In case of PCI shared interrupts or spurious interrupts,
 	 * we want to make sure it is actually our interrupt before
@@ -2326,13 +2311,10 @@
 
 static int ace_open(struct net_device *dev)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 	struct cmd cmd;
 
-	ap = netdev_priv(dev);
-	regs = ap->regs;
-
 	if (!(ap->fw_running)) {
 		printk(KERN_WARNING "%s: Firmware not running!\n", dev->name);
 		return -EBUSY;
@@ -2384,8 +2366,8 @@
 
 static int ace_close(struct net_device *dev)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 	struct cmd cmd;
 	unsigned long flags;
 	short i;
@@ -2397,9 +2379,7 @@
 	 */
 	netif_stop_queue(dev);
 
-	ap = netdev_priv(dev);
-	regs = ap->regs;
-
+	
 	if (ap->promisc) {
 		cmd.evt = C_SET_PROMISC_MODE;
 		cmd.code = C_C_PROMISC_DISABLE;
@@ -2434,9 +2414,11 @@
 
 		if (mapping) {
 			if (ACE_IS_TIGON_I(ap)) {
-				writel(0, &ap->tx_ring[i].addr.addrhi);
-				writel(0, &ap->tx_ring[i].addr.addrlo);
-				writel(0, &ap->tx_ring[i].flagsize);
+				struct tx_desc __iomem *tx 
+					= (struct tx_desc __iomem *) &ap->tx_ring[i];
+				writel(0, &tx->addr.addrhi);
+				writel(0, &tx->addr.addrlo);
+				writel(0, &tx->flagsize);
 			} else
 				memset(ap->tx_ring + i, 0,
 				       sizeof(struct tx_desc));
@@ -2493,11 +2475,12 @@
 #endif
 
 	if (ACE_IS_TIGON_I(ap)) {
-		writel(addr >> 32, &desc->addr.addrhi);
-		writel(addr & 0xffffffff, &desc->addr.addrlo);
-		writel(flagsize, &desc->flagsize);
+		struct tx_desc __iomem *io = (struct tx_desc __iomem *) desc;
+		writel(addr >> 32, &io->addr.addrhi);
+		writel(addr & 0xffffffff, &io->addr.addrlo);
+		writel(flagsize, &io->flagsize);
 #if ACENIC_DO_VLAN
-		writel(vlan_tag, &desc->vlanres);
+		writel(vlan_tag, &io->vlanres);
 #endif
 	} else {
 		desc->addr.addrhi = addr >> 32;
@@ -2513,9 +2496,10 @@
 static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	struct tx_desc *desc;
 	u32 idx, flagsize;
+	unsigned long maxjiff = jiffies + 3*HZ;
 
 restart:
 	idx = ap->tx_prd;
@@ -2523,10 +2507,7 @@
 	if (tx_ring_full(ap, ap->tx_ret_csm, idx))
 		goto overflow;
 
-#if MAX_SKB_FRAGS
-	if (!skb_shinfo(skb)->nr_frags)
-#endif
-	{
+	if (!skb_shinfo(skb)->nr_frags)	{
 		dma_addr_t mapping;
 		u32 vlan_tag = 0;
 
@@ -2548,9 +2529,7 @@
 			flagsize |= BD_FLG_COAL_NOW;
 
 		ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag);
-	}
-#if MAX_SKB_FRAGS
-	else {
+	} else {
 		dma_addr_t mapping;
 		u32 vlan_tag = 0;
 		int i, len = 0;
@@ -2605,7 +2584,6 @@
 			ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag);
 		}
 	}
-#endif
 
  	wmb();
  	ap->tx_prd = idx;
@@ -2625,7 +2603,7 @@
 	}
 
 	dev->trans_start = jiffies;
-	return 0;
+	return NETDEV_TX_OK;
 
 overflow:
 	/*
@@ -2644,15 +2622,22 @@
 	 * Alternative is to return with 1 not throttling queue. In this
 	 * case loop becomes longer, no more useful effects.
 	 */
-	barrier();
-	goto restart;
+	if (time_before(jiffies, maxjiff)) {
+		barrier();
+		cpu_relax();
+		goto restart;
+	}
+	
+	/* The ring is stuck full. */
+	printk(KERN_WARNING "%s: Transmit ring stuck full\n", dev->name);
+	return NETDEV_TX_BUSY;
 }
 
 
 static int ace_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 
 	if (new_mtu > ACE_JUMBO_MTU)
 		return -EINVAL;
@@ -2689,7 +2674,7 @@
 static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	u32 link;
 
 	memset(ecmd, 0, sizeof(struct ethtool_cmd));
@@ -2742,7 +2727,7 @@
 static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	u32 link, speed;
 
 	link = readl(&regs->GigLnkState);
@@ -2822,8 +2807,9 @@
  */
 static int ace_set_mac_addr(struct net_device *dev, void *p)
 {
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 	struct sockaddr *addr=p;
-	struct ace_regs *regs;
 	u8 *da;
 	struct cmd cmd;
 
@@ -2834,7 +2820,6 @@
 
 	da = (u8 *)dev->dev_addr;
 
-	regs = ((struct ace_private *)netdev_priv(dev))->regs;
 	writel(da[0] << 8 | da[1], &regs->MacAddrHi);
 	writel((da[2] << 24) | (da[3] << 16) | (da[4] << 8) | da[5],
 	       &regs->MacAddrLo);
@@ -2851,7 +2836,7 @@
 static void ace_set_multicast_list(struct net_device *dev)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	struct cmd cmd;
 
 	if ((dev->flags & IFF_ALLMULTI) && !(ap->mcast_all)) {
@@ -2905,8 +2890,8 @@
 static struct net_device_stats *ace_get_stats(struct net_device *dev)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_mac_stats *mac_stats =
-		(struct ace_mac_stats *)ap->regs->Stats;
+	struct ace_mac_stats __iomem *mac_stats =
+		(struct ace_mac_stats __iomem *)ap->regs->Stats;
 
 	ap->stats.rx_missed_errors = readl(&mac_stats->drop_space);
 	ap->stats.multicast = readl(&mac_stats->kept_mc);
@@ -2916,10 +2901,10 @@
 }
 
 
-static void __init ace_copy(struct ace_regs *regs, void *src,
+static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src,
 			    u32 dest, int size)
 {
-	unsigned long tdest;
+	void __iomem *tdest;
 	u32 *wsrc;
 	short tsize, i;
 
@@ -2929,7 +2914,7 @@
 	while (size > 0) {
 		tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
 			    min_t(u32, size, ACE_WINDOW_SIZE));
-		tdest = (unsigned long)&regs->Window +
+		tdest = (void __iomem *) &regs->Window + 
 			(dest & (ACE_WINDOW_SIZE - 1));
 		writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
 		/*
@@ -2949,9 +2934,9 @@
 }
 
 
-static void __init ace_clear(struct ace_regs *regs, u32 dest, int size)
+static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int size)
 {
-	unsigned long tdest;
+	void __iomem *tdest;
 	short tsize = 0, i;
 
 	if (size <= 0)
@@ -2960,7 +2945,7 @@
 	while (size > 0) {
 		tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
 				min_t(u32, size, ACE_WINDOW_SIZE));
-		tdest = (unsigned long)&regs->Window +
+		tdest = (void __iomem *) &regs->Window + 
 			(dest & (ACE_WINDOW_SIZE - 1));
 		writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
 
@@ -2982,13 +2967,10 @@
  * This operation requires the NIC to be halted and is performed with
  * interrupts disabled and with the spinlock hold.
  */
-int __init ace_load_firmware(struct net_device *dev)
+int __devinit ace_load_firmware(struct net_device *dev)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
-
-	ap = netdev_priv(dev);
-	regs = ap->regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 
 	if (!(readl(&regs->CpuCtrl) & CPU_HALTED)) {
 		printk(KERN_ERR "%s: trying to download firmware while the "
@@ -3036,7 +3018,7 @@
  * Thanks to Stevarino Webinski for helping tracking down the bugs in the
  * code i2c readout code by beta testing all my hacks.
  */
-static void __init eeprom_start(struct ace_regs *regs)
+static void __devinit eeprom_start(struct ace_regs __iomem *regs)
 {
 	u32 local;
 
@@ -3065,7 +3047,7 @@
 }
 
 
-static void __init eeprom_prep(struct ace_regs *regs, u8 magic)
+static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
 {
 	short i;
 	u32 local;
@@ -3102,7 +3084,7 @@
 }
 
 
-static int __init eeprom_check_ack(struct ace_regs *regs)
+static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs)
 {
 	int state;
 	u32 local;
@@ -3130,7 +3112,7 @@
 }
 
 
-static void __init eeprom_stop(struct ace_regs *regs)
+static void __devinit eeprom_stop(struct ace_regs __iomem *regs)
 {
 	u32 local;
 
@@ -3165,11 +3147,11 @@
 /*
  * Read a whole byte from the EEPROM.
  */
-static int __init read_eeprom_byte(struct net_device *dev,
+static int __devinit read_eeprom_byte(struct net_device *dev,
 				   unsigned long offset)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 	unsigned long flags;
 	u32 local;
 	int result = 0;
@@ -3180,9 +3162,6 @@
 		result = -ENODEV;
 		goto out;
 	}
-
-	ap = netdev_priv(dev);
-	regs = ap->regs;
 
 	/*
 	 * Don't take interrupts on this CPU will bit banging
diff -Nru a/drivers/net/acenic.h b/drivers/net/acenic.h
--- a/drivers/net/acenic.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/acenic.h	2004-10-10 22:15:16 -07:00
@@ -10,11 +10,6 @@
  */
 #define USE_TX_COAL_NOW	 0
 
-#ifndef MAX_SKB_FRAGS
-#define MAX_SKB_FRAGS 0
-#endif
-
-
 /*
  * Addressing:
  *
@@ -638,7 +633,7 @@
 struct ace_private
 {
 	struct ace_info		*info;
-	struct ace_regs		*regs;		/* register base */
+	struct ace_regs	__iomem	*regs;		/* register base */
 	struct ace_skb		*skb;
 	dma_addr_t		info_dma;	/* 32/64 bit */
 
@@ -712,13 +707,7 @@
 }
 
 #define tx_free(ap) 		tx_space((ap)->tx_ret_csm, (ap)->tx_prd, ap)
-
-#if MAX_SKB_FRAGS
 #define tx_ring_full(ap, csm, prd)	(tx_space(ap, csm, prd) <= TX_RESERVED)
-#else
-#define tx_ring_full			0
-#endif
-
 
 static inline void set_aceaddr(aceaddr *aa, dma_addr_t addr)
 {
@@ -729,7 +718,7 @@
 }
 
 
-static inline void ace_set_txprd(struct ace_regs *regs,
+static inline void ace_set_txprd(struct ace_regs __iomem *regs,
 				 struct ace_private *ap, u32 value)
 {
 #ifdef INDEX_DEBUG
@@ -750,8 +739,8 @@
 
 static inline void ace_mask_irq(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
-	struct ace_regs *regs = ap->regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 
 	if (ACE_IS_TIGON_I(ap))
 		writel(1, &regs->MaskInt);
@@ -764,8 +753,8 @@
 
 static inline void ace_unmask_irq(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
-	struct ace_regs *regs = ap->regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
  
 	if (ACE_IS_TIGON_I(ap))
 		writel(0, &regs->MaskInt);
diff -Nru a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h
--- a/drivers/net/acenic_firmware.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/acenic_firmware.h	2004-10-10 22:15:16 -07:00
@@ -23,7 +23,7 @@
 #define tigonFwRodata NULL
 #else
 /* Generated by genfw.c */
-static u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
+static u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = {
 0x10000003, 
 0x0, 0xd, 0xd, 0x3c1d0001, 
 0x8fbd5c54, 0x3a0f021, 0x3c100000, 0x26104000, 
diff -Nru a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
--- a/drivers/net/amd8111e.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/amd8111e.c	2004-10-10 22:15:16 -07:00
@@ -1464,32 +1464,25 @@
 /*
 This function returns all the memory mapped registers of the device.
 */
-static char* amd8111e_read_regs(struct amd8111e_priv* lp)
+static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf)
 {    	
-	void * mmio = lp->mmio;
-        u32 * reg_buff;
-
-     	reg_buff = kmalloc( AMD8111E_REG_DUMP_LEN,GFP_KERNEL);
-	if(NULL == reg_buff)
-		return NULL;
-
+	void *mmio = lp->mmio;
 	/* Read only necessary registers */
-	reg_buff[0] = readl(mmio + XMT_RING_BASE_ADDR0);
-	reg_buff[1] = readl(mmio + XMT_RING_LEN0);
-	reg_buff[2] = readl(mmio + RCV_RING_BASE_ADDR0);
-	reg_buff[3] = readl(mmio + RCV_RING_LEN0);
-	reg_buff[4] = readl(mmio + CMD0);
-	reg_buff[5] = readl(mmio + CMD2);
-	reg_buff[6] = readl(mmio + CMD3);
-	reg_buff[7] = readl(mmio + CMD7);
-	reg_buff[8] = readl(mmio + INT0);
-	reg_buff[9] = readl(mmio + INTEN0);
-	reg_buff[10] = readl(mmio + LADRF);
-	reg_buff[11] = readl(mmio + LADRF+4);
-	reg_buff[12] = readl(mmio + STAT0);
-
-	return (char *)reg_buff;
+	buf[0] = readl(mmio + XMT_RING_BASE_ADDR0);
+	buf[1] = readl(mmio + XMT_RING_LEN0);
+	buf[2] = readl(mmio + RCV_RING_BASE_ADDR0);
+	buf[3] = readl(mmio + RCV_RING_LEN0);
+	buf[4] = readl(mmio + CMD0);
+	buf[5] = readl(mmio + CMD2);
+	buf[6] = readl(mmio + CMD3);
+	buf[7] = readl(mmio + CMD7);
+	buf[8] = readl(mmio + INT0);
+	buf[9] = readl(mmio + INTEN0);
+	buf[10] = readl(mmio + LADRF);
+	buf[11] = readl(mmio + LADRF+4);
+	buf[12] = readl(mmio + STAT0);
 }
+
 /*
 amd8111e crc generator implementation is different from the kernel
 ether_crc() function.
@@ -1567,131 +1560,101 @@
 
 }
 
-/*
-This function handles all the  ethtool ioctls. It gives driver info, gets/sets driver speed, gets memory mapped register values, forces auto negotiation, sets/gets WOL options for ethtool application. 
-*/
-	
-static int amd8111e_ethtool_ioctl(struct net_device* dev, void __user *useraddr)
+static void amd8111e_get_drvinfo(struct net_device* dev, struct ethtool_drvinfo *info)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
 	struct pci_dev *pci_dev = lp->pci_dev;
-	u32 ethcmd;
-	
-	if( useraddr == NULL) 
-		return -EINVAL;
-	if(copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
-		return -EFAULT;
-	
-	switch(ethcmd){
-	
-	case ETHTOOL_GDRVINFO:{
-		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-		strcpy (info.driver, MODULE_NAME);
-		strcpy (info.version, MODULE_VERS);
-		memset(&info.fw_version, 0, sizeof(info.fw_version));
-		sprintf(info.fw_version,"%u",chip_version);
-		strcpy (info.bus_info, pci_name(pci_dev));
-		info.eedump_len = 0;
-		info.regdump_len = AMD8111E_REG_DUMP_LEN;
-		if (copy_to_user (useraddr, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	/* get settings */
-	case ETHTOOL_GSET: {
-		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-		spin_lock_irq(&lp->lock);
-		mii_ethtool_gset(&lp->mii_if, &ecmd);
-		spin_unlock_irq(&lp->lock);
-		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set settings */
-	case ETHTOOL_SSET: {
-		int r;
-		struct ethtool_cmd ecmd;
-		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-			return -EFAULT;
+	strcpy (info->driver, MODULE_NAME);
+	strcpy (info->version, MODULE_VERS);
+	sprintf(info->fw_version,"%u",chip_version);
+	strcpy (info->bus_info, pci_name(pci_dev));
+}
 
-		spin_lock_irq(&lp->lock);
-		r = mii_ethtool_sset(&lp->mii_if, &ecmd);
-		spin_unlock_irq(&lp->lock);
-		return r;
-	}
-	case ETHTOOL_GREGS: {
-		struct ethtool_regs regs;
-		u8 *regbuf;
-		int ret;
-
-		if (copy_from_user(&regs, useraddr, sizeof(regs)))
-			return -EFAULT;
-		if (regs.len > AMD8111E_REG_DUMP_LEN)
-			regs.len = AMD8111E_REG_DUMP_LEN;
-		regs.version = 0;
-		if (copy_to_user(useraddr, &regs, sizeof(regs)))
-			return -EFAULT;
-
-		regbuf = amd8111e_read_regs(lp);
-		if (!regbuf)
-			return -ENOMEM;
-
-		useraddr += offsetof(struct ethtool_regs, data);
-		ret = 0;
-		if (copy_to_user(useraddr, regbuf, regs.len))
-			ret = -EFAULT;
-		kfree(regbuf);
-		return ret;
-	}
-	/* restart autonegotiation */
-	case ETHTOOL_NWAY_RST: {
-		return mii_nway_restart(&lp->mii_if);
-	}
-	/* get link status */
-	case ETHTOOL_GLINK: {
-		struct ethtool_value val = {ETHTOOL_GLINK};
-		val.data = mii_link_ok(&lp->mii_if);
-		if (copy_to_user(useraddr, &val, sizeof(val)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_GWOL: {
-		struct ethtool_wolinfo wol_info = { ETHTOOL_GWOL };
+static int amd8111e_get_regs_len(struct net_device *dev)
+{
+	return AMD8111E_REG_DUMP_LEN;
+}
 
-		wol_info.supported = WAKE_MAGIC|WAKE_PHY;
-		wol_info.wolopts = 0;
-		if (lp->options & OPTION_WOL_ENABLE)
-			wol_info.wolopts = WAKE_MAGIC;
-		memset(&wol_info.sopass, 0, sizeof(wol_info.sopass));
-		if (copy_to_user(useraddr, &wol_info, sizeof(wol_info)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_SWOL: {
-		struct ethtool_wolinfo wol_info;
+static void amd8111e_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	regs->version = 0;
+	amd8111e_read_regs(lp, buf);
+}
 
-		if (copy_from_user(&wol_info, useraddr, sizeof(wol_info)))
-			return -EFAULT;
-		if (wol_info.wolopts & ~(WAKE_MAGIC |WAKE_PHY))
-			return -EINVAL;
-		spin_lock_irq(&lp->lock);
-		if(wol_info.wolopts & WAKE_MAGIC)
-			lp->options |= 
-				(OPTION_WOL_ENABLE | OPTION_WAKE_MAGIC_ENABLE);
-		else if(wol_info.wolopts & WAKE_PHY)
-			lp->options |= 
-				(OPTION_WOL_ENABLE | OPTION_WAKE_PHY_ENABLE);
-		else
-			lp->options &= ~OPTION_WOL_ENABLE; 
-		spin_unlock_irq(&lp->lock);
-		return 0;
-	}
-	
-	default:
-		break;
-	}
-		return -EOPNOTSUPP;
+static int amd8111e_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	spin_lock_irq(&lp->lock);
+	mii_ethtool_gset(&lp->mii_if, ecmd);
+	spin_unlock_irq(&lp->lock);
+	return 0;
+}
+
+static int amd8111e_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	int res;
+	spin_lock_irq(&lp->lock);
+	res = mii_ethtool_sset(&lp->mii_if, ecmd);
+	spin_unlock_irq(&lp->lock);
+	return res;
+}
+
+static int amd8111e_nway_reset(struct net_device *dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	return mii_nway_restart(&lp->mii_if);
+}
+
+static u32 amd8111e_get_link(struct net_device *dev)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	return mii_link_ok(&lp->mii_if);
 }
+
+static void amd8111e_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	wol_info->supported = WAKE_MAGIC|WAKE_PHY;
+	if (lp->options & OPTION_WOL_ENABLE)
+		wol_info->wolopts = WAKE_MAGIC;
+}
+
+static int amd8111e_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info)
+{
+	struct amd8111e_priv *lp = netdev_priv(dev);
+	if (wol_info->wolopts & ~(WAKE_MAGIC|WAKE_PHY))
+		return -EINVAL;
+	spin_lock_irq(&lp->lock);
+	if (wol_info->wolopts & WAKE_MAGIC)
+		lp->options |= 
+			(OPTION_WOL_ENABLE | OPTION_WAKE_MAGIC_ENABLE);
+	else if(wol_info->wolopts & WAKE_PHY)
+		lp->options |= 
+			(OPTION_WOL_ENABLE | OPTION_WAKE_PHY_ENABLE);
+	else
+		lp->options &= ~OPTION_WOL_ENABLE; 
+	spin_unlock_irq(&lp->lock);
+	return 0;
+}
+
+static struct ethtool_ops ops = {
+	.get_drvinfo = amd8111e_get_drvinfo,
+	.get_regs_len = amd8111e_get_regs_len,
+	.get_regs = amd8111e_get_regs,
+	.get_settings = amd8111e_get_settings,
+	.set_settings = amd8111e_set_settings,
+	.nway_reset = amd8111e_nway_reset,
+	.get_link = amd8111e_get_link,
+	.get_wol = amd8111e_get_wol,
+	.set_wol = amd8111e_set_wol,
+};
+
+/*
+This function handles all the  ethtool ioctls. It gives driver info, gets/sets driver speed, gets memory mapped register values, forces auto negotiation, sets/gets WOL options for ethtool application. 
+*/
+	
 static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd)
 {
 	struct mii_ioctl_data *data = if_mii(ifr);
@@ -1703,8 +1666,6 @@
 		return -EPERM;
 
 	switch(cmd) {
-	case SIOCETHTOOL:
-		return amd8111e_ethtool_ioctl(dev, ifr->ifr_data);
 	case SIOCGMIIPHY:
 		data->phy_id = PHY_ID;
 
@@ -2085,6 +2046,7 @@
 	dev->set_mac_address = amd8111e_set_mac_address;
 	dev->do_ioctl = amd8111e_ioctl;
 	dev->change_mtu = amd8111e_change_mtu;
+	SET_ETHTOOL_OPS(dev, &ops);
 	dev->irq =pdev->irq;
 	dev->tx_timeout = amd8111e_tx_timeout; 
 	dev->watchdog_timeo = AMD8111E_TX_TIMEOUT; 
diff -Nru a/drivers/net/atp.c b/drivers/net/atp.c
--- a/drivers/net/atp.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/atp.c	2004-10-10 22:15:16 -07:00
@@ -909,7 +909,7 @@
 			 i++, mclist = mclist->next)
 		{
 			int filterbit = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f;
-			mc_filter[filterbit >> 5] |= cpu_to_le32(1 << (filterbit & 31));
+			mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
 		}
 		new_mode = CMR2h_Normal;
 	}
diff -Nru a/drivers/net/b44.c b/drivers/net/b44.c
--- a/drivers/net/b44.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/b44.c	2004-10-10 22:15:16 -07:00
@@ -27,8 +27,8 @@
 
 #define DRV_MODULE_NAME		"b44"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"0.94"
-#define DRV_MODULE_RELDATE	"May 4, 2004"
+#define DRV_MODULE_VERSION	"0.95"
+#define DRV_MODULE_RELDATE	"Aug 3, 2004"
 
 #define B44_DEF_MSG_ENABLE	  \
 	(NETIF_MSG_DRV		| \
@@ -57,6 +57,7 @@
 #define B44_DEF_TX_RING_PENDING		(B44_TX_RING_SIZE - 1)
 #define B44_TX_RING_BYTES	(sizeof(struct dma_desc) * \
 				 B44_TX_RING_SIZE)
+#define B44_DMA_MASK 0x3fffffff
 
 #define TX_RING_GAP(BP)	\
 	(B44_TX_RING_SIZE - (BP)->tx_pending)
@@ -67,6 +68,7 @@
 #define NEXT_TX(N)		(((N) + 1) & (B44_TX_RING_SIZE - 1))
 
 #define RX_PKT_BUF_SZ		(1536 + bp->rx_offset + 64)
+#define TX_PKT_BUF_SZ		(B44_MAX_MTU + ETH_HLEN + 8)
 
 /* minimum number of free TX descriptors required to wake up TX process */
 #define B44_TX_WAKEUP_THRESH		(B44_TX_RING_SIZE / 4)
@@ -74,7 +76,7 @@
 static char version[] __devinitdata =
 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
-MODULE_AUTHOR("David S. Miller (davem@redhat.com)");
+MODULE_AUTHOR("Florian Schirmer, Pekka Pietikainen, David S. Miller");
 MODULE_DESCRIPTION("Broadcom 4400 10/100 PCI ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_PARM(b44_debug, "i");
@@ -141,41 +143,8 @@
  * interrupts disabled.
  */
 
-#define SBID_SDRAM		0
-#define SBID_PCI_MEM		1
-#define SBID_PCI_CFG		2
-#define SBID_PCI_DMA		3
-#define	SBID_SDRAM_SWAPPED	4
-#define SBID_ENUM		5
-#define SBID_REG_SDRAM		6
-#define SBID_REG_ILINE20	7
-#define SBID_REG_EMAC		8
-#define SBID_REG_CODEC		9
-#define SBID_REG_USB		10
-#define SBID_REG_PCI		11
-#define SBID_REG_MIPS		12
-#define SBID_REG_EXTIF		13
-#define	SBID_EXTIF		14
-#define	SBID_EJTAG		15
-#define	SBID_MAX		16
-
-static u32 ssb_get_addr(struct b44 *bp, u32 id, u32 instance)
-{
-	switch (id) {
-	case SBID_PCI_DMA:
-		return 0x40000000;
-	case SBID_ENUM:
-		return 0x18000000;
-	case SBID_REG_EMAC:
-		return 0x18000000;
-	case SBID_REG_CODEC:
-		return 0x18001000;
-	case SBID_REG_PCI:
-		return 0x18002000;
-	default:
-		return 0;
-	};
-}
+#define SB_PCI_DMA             0x40000000      /* Client Mode PCI memory access space (1 GB) */
+#define BCM4400_PCI_CORE_ADDR  0x18002000      /* Address of PCI core on BCM4400 cards */
 
 static u32 ssb_get_core_rev(struct b44 *bp)
 {
@@ -187,8 +156,7 @@
 	u32 bar_orig, pci_rev, val;
 
 	pci_read_config_dword(bp->pdev, SSB_BAR0_WIN, &bar_orig);
-	pci_write_config_dword(bp->pdev, SSB_BAR0_WIN,
-			       ssb_get_addr(bp, SBID_REG_PCI, 0));
+	pci_write_config_dword(bp->pdev, SSB_BAR0_WIN, BCM4400_PCI_CORE_ADDR);
 	pci_rev = ssb_get_core_rev(bp);
 
 	val = br32(bp, B44_SBINTVEC);
@@ -649,10 +617,30 @@
 	if (skb == NULL)
 		return -ENOMEM;
 
-	skb->dev = bp->dev;
 	mapping = pci_map_single(bp->pdev, skb->data,
 				 RX_PKT_BUF_SZ,
 				 PCI_DMA_FROMDEVICE);
+
+	/* Hardware bug work-around, the chip is unable to do PCI DMA
+	   to/from anything above 1GB :-( */
+	if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) {
+		/* Sigh... */
+		pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
+		dev_kfree_skb_any(skb);
+		skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
+		if (skb == NULL)
+			return -ENOMEM;
+		mapping = pci_map_single(bp->pdev, skb->data,
+					 RX_PKT_BUF_SZ,
+					 PCI_DMA_FROMDEVICE);
+		if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) {
+			pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
+			dev_kfree_skb_any(skb);
+			return -ENOMEM;
+		}
+	}
+
+	skb->dev = bp->dev;
 	skb_reserve(skb, bp->rx_offset);
 
 	rh = (struct rx_header *)
@@ -930,6 +918,12 @@
 
 	entry = bp->tx_prod;
 	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+	if(mapping+len > B44_DMA_MASK) {
+		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
+		pci_unmap_single(bp->pdev, mapping, len,PCI_DMA_TODEVICE);
+		memcpy(bp->tx_bufs+entry*TX_PKT_BUF_SZ,skb->data,skb->len);
+		mapping = pci_map_single(bp->pdev, bp->tx_bufs+entry*TX_PKT_BUF_SZ, len, PCI_DMA_TODEVICE);
+	}
 
 	bp->tx_buffers[entry].skb = skb;
 	pci_unmap_addr_set(&bp->tx_buffers[entry], mapping, mapping);
@@ -1077,6 +1071,11 @@
 				    bp->tx_ring, bp->tx_ring_dma);
 		bp->tx_ring = NULL;
 	}
+	if (bp->tx_bufs) {
+		pci_free_consistent(bp->pdev, B44_TX_RING_SIZE * TX_PKT_BUF_SZ,
+				    bp->tx_bufs, bp->tx_bufs_dma);
+		bp->tx_bufs = NULL;
+	}
 }
 
 /*
@@ -1099,6 +1098,12 @@
 		goto out_err;
 	memset(bp->tx_buffers, 0, size);
 
+	size = B44_TX_RING_SIZE * TX_PKT_BUF_SZ;
+	bp->tx_bufs = pci_alloc_consistent(bp->pdev, size, &bp->tx_bufs_dma);
+	if (!bp->tx_bufs)
+		goto out_err;
+	memset(bp->tx_bufs, 0, size);
+
 	size = DMA_TABLE_BYTES;
 	bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
 	if (!bp->rx_ring)
@@ -1358,7 +1363,10 @@
 				   hwstat->rx_symbol_errs);
 
 	nstat->tx_aborted_errors = hwstat->tx_underruns;
+#if 0
+	/* Carrier lost counter seems to be broken for some devices */
 	nstat->tx_carrier_errors = hwstat->tx_carrier_lost;
+#endif
 
 	return nstat;
 }
@@ -1684,7 +1692,6 @@
 	bp->dev->dev_addr[5] = eeprom[82];
 
 	bp->phy_addr = eeprom[90] & 0x1f;
-	bp->mdc_port = (eeprom[90] >> 14) & 0x1;
 
 	/* With this, plus the rx_header prepended to the data by the
 	 * hardware, we'll land the ethernet header on a 2-byte boundary.
@@ -1694,7 +1701,7 @@
 	bp->imask = IMASK_DEF;
 
 	bp->core_unit = ssb_core_unit(bp);
-	bp->dma_offset = ssb_get_addr(bp, SBID_PCI_DMA, 0);
+	bp->dma_offset = SB_PCI_DMA;
 
 	/* XXX - really required? 
 	   bp->flags |= B44_FLAG_BUGGY_TXPTR;
@@ -1738,11 +1745,18 @@
 
 	pci_set_master(pdev);
 
-	err = pci_set_dma_mask(pdev, (u64) 0xffffffff);
+	err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK);
 	if (err) {
 		printk(KERN_ERR PFX "No usable DMA configuration, "
 		       "aborting.\n");
 		goto err_out_free_res;
+	}
+	
+	err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
+	if (err) {
+	  printk(KERN_ERR PFX "No usable DMA configuration, "
+		 "aborting.\n");
+	  goto err_out_free_res;
 	}
 
 	b44reg_base = pci_resource_start(pdev, 0);
diff -Nru a/drivers/net/b44.h b/drivers/net/b44.h
--- a/drivers/net/b44.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/b44.h	2004-10-10 22:15:16 -07:00
@@ -223,21 +223,8 @@
 #define B44_RX_SYM	0x05D0UL /* MIB RX Symbol Errors */
 #define B44_RX_PAUSE	0x05D4UL /* MIB RX Pause Packets */
 #define B44_RX_NPAUSE	0x05D8UL /* MIB RX Non-Pause Packets */
-#define B44_SBIPSFLAG	0x0F08UL /* SB Initiator Port OCP Slave Flag */
-#define  SBIPSFLAG_IMASK1	0x0000003f /* Which sbflags --> mips interrupt 1 */
-#define  SBIPSFLAG_ISHIFT1	0
-#define  SBIPSFLAG_IMASK2	0x00003f00 /* Which sbflags --> mips interrupt 2 */
-#define  SBIPSFLAG_ISHIFT2	8
-#define  SBIPSFLAG_IMASK3	0x003f0000 /* Which sbflags --> mips interrupt 3 */
-#define  SBIPSFLAG_ISHIFT3	16
-#define  SBIPSFLAG_IMASK4	0x3f000000 /* Which sbflags --> mips interrupt 4 */
-#define  SBIPSFLAG_ISHIFT4	24
-#define B44_SBTPSFLAG	0x0F18UL /* SB Target Port OCP Slave Flag */
-#define  SBTPS_NUM0_MASK	0x0000003f
-#define  SBTPS_F0EN0		0x00000040
-#define B44_SBADMATCH3	0x0F60UL /* SB Address Match 3 */
-#define B44_SBADMATCH2	0x0F68UL /* SB Address Match 2 */
-#define B44_SBADMATCH1	0x0F70UL /* SB Address Match 1 */
+
+/* Silicon backplane register definitions */
 #define B44_SBIMSTATE	0x0F90UL /* SB Initiator Agent State */
 #define  SBIMSTATE_PC		0x0000000f /* Pipe Count */
 #define  SBIMSTATE_AP_MASK	0x00000030 /* Arbitration Priority */
@@ -269,86 +256,6 @@
 #define  SBTMSHIGH_GCR		0x20000000 /* Gated Clock Request */
 #define  SBTMSHIGH_BISTF	0x40000000 /* BIST Failed */
 #define  SBTMSHIGH_BISTD	0x80000000 /* BIST Done */
-#define B44_SBBWA0	0x0FA0UL /* SB Bandwidth Allocation Table 0 */
-#define  SBBWA0_TAB0_MASK	0x0000ffff /* Lookup Table 0 */
-#define  SBBWA0_TAB0_SHIFT	0
-#define  SBBWA0_TAB1_MASK	0xffff0000 /* Lookup Table 0 */
-#define  SBBWA0_TAB1_SHIFT	16
-#define B44_SBIMCFGLOW	0x0FA8UL /* SB Initiator Configuration Low */
-#define  SBIMCFGLOW_STO_MASK	0x00000003 /* Service Timeout */
-#define  SBIMCFGLOW_RTO_MASK	0x00000030 /* Request Timeout */
-#define  SBIMCFGLOW_RTO_SHIFT	4
-#define  SBIMCFGLOW_CID_MASK	0x00ff0000 /* Connection ID */
-#define  SBIMCFGLOW_CID_SHIFT	16
-#define B44_SBIMCFGHIGH	0x0FACUL /* SB Initiator Configuration High */
-#define  SBIMCFGHIGH_IEM_MASK	0x0000000c /* Inband Error Mode */
-#define  SBIMCFGHIGH_TEM_MASK	0x00000030 /* Timeout Error Mode */
-#define  SBIMCFGHIGH_TEM_SHIFT	4
-#define  SBIMCFGHIGH_BEM_MASK	0x000000c0 /* Bus Error Mode */
-#define  SBIMCFGHIGH_BEM_SHIFT	6
-#define B44_SBADMATCH0	0x0FB0UL /* SB Address Match 0 */
-#define  SBADMATCH0_TYPE_MASK	0x00000003 /* Address Type */
-#define  SBADMATCH0_AD64	0x00000004 /* Reserved */
-#define  SBADMATCH0_AI0_MASK	0x000000f8 /* Type0 Size */
-#define  SBADMATCH0_AI0_SHIFT	3
-#define  SBADMATCH0_AI1_MASK	0x000001f8 /* Type1 Size */
-#define  SBADMATCH0_AI1_SHIFT	3
-#define  SBADMATCH0_AI2_MASK	0x000001f8 /* Type2 Size */
-#define  SBADMATCH0_AI2_SHIFT	3
-#define  SBADMATCH0_ADEN	0x00000400 /* Enable */
-#define  SBADMATCH0_ADNEG	0x00000800 /* Negative Decode */
-#define  SBADMATCH0_BS0_MASK	0xffffff00 /* Type0 Base Address */
-#define  SBADMATCH0_BS0_SHIFT	8
-#define  SBADMATCH0_BS1_MASK	0xfffff000 /* Type1 Base Address */
-#define  SBADMATCH0_BS1_SHIFT	12
-#define  SBADMATCH0_BS2_MASK	0xffff0000 /* Type2 Base Address */
-#define  SBADMATCH0_BS2_SHIFT	16
-#define B44_SBTMCFGLOW	0x0FB8UL /* SB Target Configuration Low */
-#define  SBTMCFGLOW_CD_MASK	0x000000ff /* Clock Divide Mask */
-#define  SBTMCFGLOW_CO_MASK	0x0000f800 /* Clock Offset Mask */
-#define  SBTMCFGLOW_CO_SHIFT	11
-#define  SBTMCFGLOW_IF_MASK	0x00fc0000 /* Interrupt Flags Mask */
-#define  SBTMCFGLOW_IF_SHIFT	18
-#define  SBTMCFGLOW_IM_MASK	0x03000000 /* Interrupt Mode Mask */
-#define  SBTMCFGLOW_IM_SHIFT	24
-#define B44_SBTMCFGHIGH	0x0FBCUL /* SB Target Configuration High */
-#define  SBTMCFGHIGH_BM_MASK	0x00000003 /* Busy Mode */
-#define  SBTMCFGHIGH_RM_MASK	0x0000000C /* Retry Mode */
-#define  SBTMCFGHIGH_RM_SHIFT	2
-#define  SBTMCFGHIGH_SM_MASK	0x00000030 /* Stop Mode */
-#define  SBTMCFGHIGH_SM_SHIFT	4
-#define  SBTMCFGHIGH_EM_MASK	0x00000300 /* Error Mode */
-#define  SBTMCFGHIGH_EM_SHIFT	8
-#define  SBTMCFGHIGH_IM_MASK	0x00000c00 /* Interrupt Mode */
-#define  SBTMCFGHIGH_IM_SHIFT	10
-#define B44_SBBCFG	0x0FC0UL /* SB Broadcast Configuration */
-#define  SBBCFG_LAT_MASK	0x00000003 /* SB Latency */
-#define  SBBCFG_MAX0_MASK	0x000f0000 /* MAX Counter 0 */
-#define  SBBCFG_MAX0_SHIFT	16
-#define  SBBCFG_MAX1_MASK	0x00f00000 /* MAX Counter 1 */
-#define  SBBCFG_MAX1_SHIFT	20
-#define B44_SBBSTATE	0x0FC8UL /* SB Broadcast State */
-#define  SBBSTATE_SRD		0x00000001 /* ST Reg Disable */
-#define  SBBSTATE_HRD		0x00000002 /* Hold Reg Disable */
-#define B44_SBACTCNFG	0x0FD8UL /* SB Activate Configuration */
-#define B44_SBFLAGST	0x0FE8UL /* SB Current SBFLAGS */
-#define B44_SBIDLOW	0x0FF8UL /* SB Identification Low */
-#define  SBIDLOW_CS_MASK	0x00000003 /* Config Space Mask */
-#define  SBIDLOW_AR_MASK	0x00000038 /* Num Address Ranges Supported */
-#define  SBIDLOW_AR_SHIFT	3
-#define  SBIDLOW_SYNCH		0x00000040 /* Sync */
-#define  SBIDLOW_INIT		0x00000080 /* Initiator */
-#define  SBIDLOW_MINLAT_MASK	0x00000f00 /* Minimum Backplane Latency */
-#define  SBIDLOW_MINLAT_SHIFT	8
-#define  SBIDLOW_MAXLAT_MASK	0x0000f000 /* Maximum Backplane Latency */
-#define  SBIDLOW_MAXLAT_SHIFT	12
-#define  SBIDLOW_FIRST		0x00010000 /* This Initiator is First */
-#define  SBIDLOW_CW_MASK	0x000c0000 /* Cycle Counter Width */
-#define  SBIDLOW_CW_SHIFT	18
-#define  SBIDLOW_TP_MASK	0x00f00000 /* Target Ports */
-#define  SBIDLOW_TP_SHIFT	20
-#define  SBIDLOW_IP_MASK	0x0f000000 /* Initiator Ports */
-#define  SBIDLOW_IP_SHIFT	24
 #define B44_SBIDHIGH	0x0FFCUL /* SB Identification High */
 #define  SBIDHIGH_RC_MASK	0x0000000f /* Revision Code */
 #define  SBIDHIGH_CC_MASK	0x0000fff0 /* Core Code */
@@ -356,23 +263,13 @@
 #define  SBIDHIGH_VC_MASK	0xffff0000 /* Vendor Code */
 #define  SBIDHIGH_VC_SHIFT	16
 
-#define  CORE_CODE_ILINE20	0x801
-#define  CORE_CODE_SDRAM	0x803
-#define  CORE_CODE_PCI		0x804
-#define  CORE_CODE_MIPS		0x805
-#define  CORE_CODE_ENET		0x806
-#define  CORE_CODE_CODEC	0x807
-#define  CORE_CODE_USB		0x808
-#define  CORE_CODE_ILINE100	0x80a
-#define  CORE_CODE_EXTIF	0x811
-
 /* SSB PCI config space registers.  */
 #define	SSB_BAR0_WIN		0x80
 #define	SSB_BAR1_WIN		0x84
 #define	SSB_SPROM_CONTROL	0x88
 #define	SSB_BAR1_CONTROL	0x8c
 
-/* SSB core and hsot control registers.  */
+/* SSB core and host control registers.  */
 #define SSB_CONTROL		0x0000UL
 #define SSB_ARBCONTROL		0x0010UL
 #define SSB_ISTAT		0x0020UL
@@ -500,6 +397,7 @@
 
 	struct ring_info	*rx_buffers;
 	struct ring_info	*tx_buffers;
+	unsigned char		*tx_bufs; 
 
 	u32			dma_offset;
 	u32			flags;
@@ -531,13 +429,12 @@
 	struct pci_dev		*pdev;
 	struct net_device	*dev;
 
-	dma_addr_t		rx_ring_dma, tx_ring_dma;
+	dma_addr_t		rx_ring_dma, tx_ring_dma,tx_bufs_dma;
 
 	u32			rx_pending;
 	u32			tx_pending;
 	u32			pci_cfg_state[64 / sizeof(u32)];
 	u8			phy_addr;
-	u8			mdc_port;
 	u8			core_unit;
 
 	struct mii_if_info	mii_if;
diff -Nru a/drivers/net/defxx.c b/drivers/net/defxx.c
--- a/drivers/net/defxx.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/defxx.c	2004-10-10 22:15:16 -07:00
@@ -19,7 +19,7 @@
  *   LVS	Lawrence V. Stefani <lstefani@yahoo.com>
  *
  * Maintainers:
- *   macro	Maciej W. Rozycki <macro@ds2.pg.gda.pl>
+ *   macro	Maciej W. Rozycki <macro@linux-mips.org>
  *
  * Credits:
  *   I'd like to thank Patricia Cross for helping me get started with
@@ -190,6 +190,7 @@
  *		Feb 2001			Skb allocation fixes
  *		Feb 2001	davej		PCI enable cleanups.
  *		04 Aug 2003	macro		Converted to the DMA API.
+ *		14 Aug 2004	macro		Fix device names reported.
  */
 
 /* Include files */
@@ -214,12 +215,14 @@
 
 #include "defxx.h"
 
-/* Version information string - should be updated prior to each new release!!! */
+/* Version information string should be updated prior to each new release!  */
+#define DRV_NAME "defxx"
+#define DRV_VERSION "v1.07"
+#define DRV_RELDATE "2004/08/14"
 
 static char version[] __devinitdata =
-	"defxx.c:v1.06 2003/08/04  Lawrence V. Stefani and others\n";
-
-#define DRV_NAME "defxx"
+	DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
+	"  Lawrence V. Stefani and others\n";
 
 #define DYNAMIC_BUFFERS 1
 
@@ -235,7 +238,7 @@
 static void		dfx_bus_init(struct net_device *dev);
 static void		dfx_bus_config_check(DFX_board_t *bp);
 
-static int		dfx_driver_init(struct net_device *dev);
+static int		dfx_driver_init(struct net_device *dev, const char *print_name);
 static int		dfx_adap_init(DFX_board_t *bp, int get_buffers);
 
 static int		dfx_open(struct net_device *dev);
@@ -404,24 +407,25 @@
  */
 static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr)
 {
+	static int version_disp;
+	char *print_name = DRV_NAME;
 	struct net_device *dev;
 	DFX_board_t	  *bp;			/* board pointer */
 	int alloc_size;				/* total buffer size used */
 	int err;
 
-#ifndef MODULE
-	static int version_disp;
-
-	if (!version_disp)	/* display version info if adapter is found */
-	{
+	if (!version_disp) {	/* display version info if adapter is found */
 		version_disp = 1;	/* set display flag to TRUE so that */
 		printk(version);	/* we only display this string ONCE */
 	}
-#endif
+
+	if (pdev != NULL)
+		print_name = pdev->slot_name;
 
 	dev = alloc_fddidev(sizeof(*bp));
 	if (!dev) {
-		printk (KERN_ERR "defxx: unable to allocate fddidev, aborting\n");
+		printk(KERN_ERR "%s: unable to allocate fddidev, aborting\n",
+		       print_name);
 		return -ENOMEM;
 	}
 
@@ -437,9 +441,12 @@
 
 	bp = dev->priv;
 
-	if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, DRV_NAME)) {
-		printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n",
-			DRV_NAME, PFI_K_CSR_IO_LEN, ioaddr);
+	if (!request_region(ioaddr,
+			    pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN,
+			    print_name)) {
+		printk(KERN_ERR "%s: Cannot reserve I/O resource "
+		       "0x%x @ 0x%lx, aborting\n", print_name,
+		       pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, ioaddr);
 		err = -EBUSY;
 		goto err_out;
 	}
@@ -468,7 +475,7 @@
 		pci_set_master (pdev);
 	}
 
-	if (dfx_driver_init(dev) != DFX_K_SUCCESS) {
+	if (dfx_driver_init(dev, print_name) != DFX_K_SUCCESS) {
 		err = -ENODEV;
 		goto err_out_region;
 	}
@@ -477,6 +484,7 @@
 	if (err)
 		goto err_out_kfree;
 
+	printk("%s: registered as %s\n", print_name, dev->name);
 	return 0;
 
 err_out_kfree:
@@ -770,6 +778,7 @@
  *       
  * Arguments:
  *   dev - pointer to device information
+ *   print_name - printable device name
  *
  * Functional Description:
  *   This function allocates additional resources such as the host memory
@@ -792,7 +801,8 @@
  *   returning from this routine.
  */
 
-static int __devinit dfx_driver_init(struct net_device *dev)
+static int __devinit dfx_driver_init(struct net_device *dev,
+				     const char *print_name)
 {
 	DFX_board_t *bp = dev->priv;
 	int			alloc_size;			/* total buffer size needed */
@@ -841,26 +851,20 @@
 
 	/*  Read the factory MAC address from the adapter then save it */
 
-	if (dfx_hw_port_ctrl_req(bp,
-							PI_PCTRL_M_MLA,
-							PI_PDATA_A_MLA_K_LO,
-							0,
-							&data) != DFX_K_SUCCESS)
-		{
-		printk("%s: Could not read adapter factory MAC address!\n", dev->name);
+	if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_LO, 0,
+				 &data) != DFX_K_SUCCESS) {
+		printk("%s: Could not read adapter factory MAC address!\n",
+		       print_name);
 		return(DFX_K_FAILURE);
-		}
+	}
 	memcpy(&bp->factory_mac_addr[0], &data, sizeof(u32));
 
-	if (dfx_hw_port_ctrl_req(bp,
-							PI_PCTRL_M_MLA,
-							PI_PDATA_A_MLA_K_HI,
-							0,
-							&data) != DFX_K_SUCCESS)
-		{
-		printk("%s: Could not read adapter factory MAC address!\n", dev->name);
+	if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0,
+				 &data) != DFX_K_SUCCESS) {
+		printk("%s: Could not read adapter factory MAC address!\n",
+		       print_name);
 		return(DFX_K_FAILURE);
-		}
+	}
 	memcpy(&bp->factory_mac_addr[4], &data, sizeof(u16));
 
 	/*
@@ -872,27 +876,19 @@
 
 	memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
 	if (bp->bus_type == DFX_BUS_TYPE_EISA)
-		printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
-				dev->name,
-				dev->base_addr,
-				dev->irq,
-				dev->dev_addr[0],
-				dev->dev_addr[1],
-				dev->dev_addr[2],
-				dev->dev_addr[3],
-				dev->dev_addr[4],
-				dev->dev_addr[5]);
+		printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, "
+		       "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
+		       print_name, dev->base_addr, dev->irq,
+		       dev->dev_addr[0], dev->dev_addr[1],
+		       dev->dev_addr[2], dev->dev_addr[3],
+		       dev->dev_addr[4], dev->dev_addr[5]);
 	else
-		printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
-				dev->name,
-				dev->base_addr,
-				dev->irq,
-				dev->dev_addr[0],
-				dev->dev_addr[1],
-				dev->dev_addr[2],
-				dev->dev_addr[3],
-				dev->dev_addr[4],
-				dev->dev_addr[5]);
+		printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, "
+		       "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
+		       print_name, dev->base_addr, dev->irq,
+		       dev->dev_addr[0], dev->dev_addr[1],
+		       dev->dev_addr[2], dev->dev_addr[3],
+		       dev->dev_addr[4], dev->dev_addr[5]);
 
 	/*
 	 * Get memory for descriptor block, consumer block, and other buffers
@@ -909,11 +905,11 @@
 					(PI_ALIGN_K_DESC_BLK - 1);
 	bp->kmalloced = top_v = pci_alloc_consistent(bp->pci_dev, alloc_size,
 						     &bp->kmalloced_dma);
-	if (top_v == NULL)
-		{
-		printk("%s: Could not allocate memory for host buffers and structures!\n", dev->name);
+	if (top_v == NULL) {
+		printk("%s: Could not allocate memory for host buffers "
+		       "and structures!\n", print_name);
 		return(DFX_K_FAILURE);
-		}
+	}
 	memset(top_v, 0, alloc_size);	/* zero out memory before continuing */
 	top_p = bp->kmalloced_dma;	/* get physical address of buffer */
 
@@ -970,14 +966,20 @@
 
 	/* Display virtual and physical addresses if debug driver */
 
-	DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n",				dev->name, (long)bp->descr_block_virt,	bp->descr_block_phys);
-	DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n",			dev->name, (long)bp->cmd_req_virt,		bp->cmd_req_phys);
-	DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n",			dev->name, (long)bp->cmd_rsp_virt,		bp->cmd_rsp_phys);
-	DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n",			dev->name, (long)bp->rcv_block_virt,	bp->rcv_block_phys);
-	DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",				dev->name, (long)bp->cons_block_virt,	bp->cons_block_phys);
+	DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n",
+		   print_name,
+		   (long)bp->descr_block_virt, bp->descr_block_phys);
+	DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n",
+		   print_name, (long)bp->cmd_req_virt, bp->cmd_req_phys);
+	DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n",
+		   print_name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys);
+	DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n",
+		   print_name, (long)bp->rcv_block_virt, bp->rcv_block_phys);
+	DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",
+		   print_name, (long)bp->cons_block_virt, bp->cons_block_phys);
 
 	return(DFX_K_SUCCESS);
-	}
+}
 
 
 /*
@@ -2668,12 +2670,12 @@
  
 static void my_skb_align(struct sk_buff *skb, int n)
 {
-	unsigned long x=(unsigned long)skb->data;	
+	unsigned long x = (unsigned long)skb->data;
 	unsigned long v;
 	
-	v=(x+n-1)&~(n-1);	/* Where we want to be */
+	v = ALIGN(x, n);	/* Where we want to be */
 	
-	skb_reserve(skb, v-x);
+	skb_reserve(skb, v - x);
 }
 
 
@@ -3428,11 +3430,6 @@
 {
 	int rc_pci, rc_eisa;
 
-/* when a module, this is printed whether or not devices are found in probe */
-#ifdef MODULE
-	printk(version);
-#endif
-
 	rc_pci = pci_module_init(&dfx_driver);
 	if (rc_pci >= 0) dfx_have_pci = 1;
 	
@@ -3453,6 +3450,9 @@
 
 module_init(dfx_init);
 module_exit(dfx_cleanup);
+MODULE_AUTHOR("Lawrence V. Stefani");
+MODULE_DESCRIPTION("DEC FDDIcontroller EISA/PCI (DEFEA/DEFPA) driver "
+		   DRV_VERSION " " DRV_RELDATE);
 MODULE_LICENSE("GPL");
 
 
diff -Nru a/drivers/net/defxx.h b/drivers/net/defxx.h
--- a/drivers/net/defxx.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/defxx.h	2004-10-10 22:15:16 -07:00
@@ -16,7 +16,7 @@
  *   LVS	Lawrence V. Stefani <lstefani@yahoo.com>
  *
  * Maintainers:
- *   macro	Maciej W. Rozycki <macro@ds2.pg.gda.pl>
+ *   macro	Maciej W. Rozycki <macro@linux-mips.org>
  *
  * Modification History:
  *		Date		Name	Description
diff -Nru a/drivers/net/dl2k.c b/drivers/net/dl2k.c
--- a/drivers/net/dl2k.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/dl2k.c	2004-10-10 22:15:16 -07:00
@@ -107,7 +107,6 @@
 static void set_multicast (struct net_device *dev);
 static struct net_device_stats *get_stats (struct net_device *dev);
 static int clear_stats (struct net_device *dev);
-static int rio_ethtool_ioctl (struct net_device *dev, void __user *useraddr);
 static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 static int rio_close (struct net_device *dev);
 static int find_miiphy (struct net_device *dev);
@@ -122,6 +121,8 @@
 static int mii_write (struct net_device *dev, int phy_addr, int reg_num,
 		      u16 data);
 
+static struct ethtool_ops ethtool_ops;
+
 static int __devinit
 rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -168,7 +169,7 @@
 #endif
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
-	np = dev->priv;
+	np = netdev_priv(dev);
 	np->chip_id = chip_idx;
 	np->pdev = pdev;
 	spin_lock_init (&np->tx_lock);
@@ -244,6 +245,7 @@
 	dev->tx_timeout = &rio_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->change_mtu = &change_mtu;
+	SET_ETHTOOL_OPS(dev, &ethtool_ops);
 #if 0
 	dev->features = NETIF_F_IP_CSUM;
 #endif
@@ -335,7 +337,7 @@
 	int i, phy_found = 0;
 	struct netdev_private *np;
 	long ioaddr;
-	np = dev->priv;
+	np = netdev_priv(dev);
 	ioaddr = dev->base_addr;
 	np->phy_addr = 1;
 
@@ -362,7 +364,7 @@
 	u8 *psib;
 	u32 crc;
 	PSROM_t psrom = (PSROM_t) sromdata;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 
 	int cid, next;
 
@@ -432,7 +434,7 @@
 static int
 rio_open (struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int i;
 	u16 macctrl;
@@ -516,7 +518,7 @@
 rio_timer (unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	unsigned int entry;
 	int next_tick = 1*HZ;
 	unsigned long flags;
@@ -574,7 +576,7 @@
 static void
 alloc_list (struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int i;
 
 	np->cur_rx = np->cur_tx = 0;
@@ -631,7 +633,7 @@
 static int
 start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	struct netdev_desc *txdesc;
 	unsigned entry;
 	u32 ioaddr;
@@ -711,7 +713,7 @@
 	int handled = 0;
 
 	ioaddr = dev->base_addr;
-	np = dev->priv;
+	np = netdev_priv(dev);
 	while (1) {
 		int_status = readw (ioaddr + IntStatus); 
 		writew (int_status, ioaddr + IntStatus);
@@ -745,7 +747,7 @@
 static void 
 rio_free_tx (struct net_device *dev, int irq) 
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int entry = np->old_tx % TX_RING_SIZE;
 	int tx_use = 0;
 	unsigned long flag = 0;
@@ -798,7 +800,7 @@
 	int frame_id;
 	int i;
 
-	np = dev->priv;
+	np = netdev_priv(dev);
 
 	frame_id = (tx_status & 0xffff0000);
 	printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n",
@@ -855,7 +857,7 @@
 static int
 receive_packet (struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int entry = np->cur_rx % RX_RING_SIZE;
 	int cnt = 30;
 
@@ -965,7 +967,7 @@
 rio_error (struct net_device *dev, int int_status)
 {
 	long ioaddr = dev->base_addr;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	u16 macctrl;
 
 	/* Link change event */
@@ -1016,7 +1018,7 @@
 get_stats (struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 #ifdef MEM_MAPPING
 	int i;
 #endif
@@ -1132,7 +1134,7 @@
 int
 change_mtu (struct net_device *dev, int new_mtu)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int max = (np->jumbo) ? MAX_JUMBO : 1536;
 
 	if ((new_mtu < 68) || (new_mtu > max)) {
@@ -1150,7 +1152,7 @@
 	long ioaddr = dev->base_addr;
 	u32 hash_table[2];
 	u16 rx_mode = 0;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	
 	hash_table[0] = hash_table[1] = 0;
 	/* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */
@@ -1194,137 +1196,118 @@
 	writew (rx_mode, ioaddr + ReceiveMode);
 }
 
-static int
-rio_ethtool_ioctl (struct net_device *dev, void __user *useraddr)
+static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	strcpy(info->driver, "DL2K");
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, pci_name(np->pdev));
+}	
+
+static int rio_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct netdev_private *np = dev->priv;
-       	u32 ethcmd;
+	struct netdev_private *np = netdev_priv(dev);
+	if (np->phy_media) {
+		/* fiber device */
+		cmd->supported = SUPPORTED_Autoneg | SUPPORTED_FIBRE;
+		cmd->advertising= ADVERTISED_Autoneg | ADVERTISED_FIBRE;
+		cmd->port = PORT_FIBRE;
+		cmd->transceiver = XCVR_INTERNAL;	
+	} else {
+		/* copper device */
+		cmd->supported = SUPPORTED_10baseT_Half | 
+			SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half
+			| SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full |
+			SUPPORTED_Autoneg | SUPPORTED_MII;
+		cmd->advertising = ADVERTISED_10baseT_Half |
+			ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half |
+			ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full|
+			ADVERTISED_Autoneg | ADVERTISED_MII;
+		cmd->port = PORT_MII;
+		cmd->transceiver = XCVR_INTERNAL;
+	}
+	if ( np->link_status ) { 
+		cmd->speed = np->speed;
+		cmd->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+	} else {
+		cmd->speed = -1;
+		cmd->duplex = -1;
+	}
+	if ( np->an_enable)
+		cmd->autoneg = AUTONEG_ENABLE;
+	else
+		cmd->autoneg = AUTONEG_DISABLE;
 	
-	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
-		return -EFAULT;
-	switch (ethcmd) {
-		case ETHTOOL_GDRVINFO: {
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy(info.driver, "DL2K");
-			strcpy(info.version, DRV_VERSION);
-			strcpy(info.bus_info, pci_name(np->pdev));
-			memset(&info.fw_version, 0, sizeof(info.fw_version));
-			if (copy_to_user(useraddr, &info, sizeof(info)))
-				return -EFAULT;
+	cmd->phy_address = np->phy_addr;
+	return 0;				   
+}
+
+static int rio_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	netif_carrier_off(dev);
+	if (cmd->autoneg == AUTONEG_ENABLE) {
+		if (np->an_enable)
 			return 0;
+		else {
+			np->an_enable = 1;
+			mii_set_media(dev);
+			return 0;	
 		}	
- 	
-		case ETHTOOL_GSET: {
-			struct ethtool_cmd cmd = { ETHTOOL_GSET };
-			if (np->phy_media) {
-				/* fiber device */
-				cmd.supported = SUPPORTED_Autoneg | 
-							SUPPORTED_FIBRE;
-				cmd.advertising= ADVERTISED_Autoneg |
-							ADVERTISED_FIBRE;
-				cmd.port = PORT_FIBRE;
-				cmd.transceiver = XCVR_INTERNAL;	
-			} else {
-				/* copper device */
-				cmd.supported = SUPPORTED_10baseT_Half | 
-					SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half
-					| SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full |
-					SUPPORTED_Autoneg | SUPPORTED_MII;
-				cmd.advertising = ADVERTISED_10baseT_Half |
-					ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half |
-					ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full|
-					ADVERTISED_Autoneg | ADVERTISED_MII;
-				cmd.port = PORT_MII;
-				cmd.transceiver = XCVR_INTERNAL;
-			}
-			if ( np->link_status ) { 
-				cmd.speed = np->speed;
-				cmd.duplex = np->full_duplex ? 
-						    DUPLEX_FULL : DUPLEX_HALF;
-			} else {
-				cmd.speed = -1;
-				cmd.duplex = -1;
-			}
-			if ( np->an_enable)
-				cmd.autoneg = AUTONEG_ENABLE;
-			else
-				cmd.autoneg = AUTONEG_DISABLE;
-			
-			cmd.phy_address = np->phy_addr;
-
-			if (copy_to_user(useraddr, &cmd,
-					sizeof(cmd)))
-				return -EFAULT;
-			return 0;				   
-		}
-		case ETHTOOL_SSET: {
-			struct ethtool_cmd cmd;
-			if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
-				return -EFAULT;
-			netif_carrier_off(dev);
-			if (cmd.autoneg == AUTONEG_ENABLE) {
-				if (np->an_enable)
-					return 0;
-				else {
-					np->an_enable = 1;
-					mii_set_media(dev);
-					return 0;	
-				}	
-			} else {
-				np->an_enable = 0;
-				if (np->speed == 1000){
-					cmd.speed = SPEED_100;			
-					cmd.duplex = DUPLEX_FULL;
-					printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manul 100Mbps, Full duplex.\n");
-					}
-				switch(cmd.speed + cmd.duplex){
-				
-				case SPEED_10 + DUPLEX_HALF:
-					np->speed = 10;
-					np->full_duplex = 0;
-					break;
-				
-				case SPEED_10 + DUPLEX_FULL:
-					np->speed = 10;
-					np->full_duplex = 1;
-					break;
-				case SPEED_100 + DUPLEX_HALF:
-					np->speed = 100;
-					np->full_duplex = 0;
-					break;
-				case SPEED_100 + DUPLEX_FULL:
-					np->speed = 100;
-					np->full_duplex = 1;
-					break;
-				case SPEED_1000 + DUPLEX_HALF:/* not supported */
-				case SPEED_1000 + DUPLEX_FULL:/* not supported */
-				default:
-					return -EINVAL;	
-				}
-				mii_set_media(dev);
-			}
-		return 0;		   
+	} else {
+		np->an_enable = 0;
+		if (np->speed == 1000) {
+			cmd->speed = SPEED_100;			
+			cmd->duplex = DUPLEX_FULL;
+			printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manual 100Mbps, Full duplex.\n");
 		}
-#ifdef ETHTOOL_GLINK		
-		case ETHTOOL_GLINK:{
-		struct ethtool_value link = { ETHTOOL_GLINK };
-		link.data = np->link_status;
-		if (copy_to_user(useraddr, &link, sizeof(link)))
-			return -EFAULT;
-		return 0;
-		}			   
-#endif
+		switch(cmd->speed + cmd->duplex) {
+		
+		case SPEED_10 + DUPLEX_HALF:
+			np->speed = 10;
+			np->full_duplex = 0;
+			break;
+		
+		case SPEED_10 + DUPLEX_FULL:
+			np->speed = 10;
+			np->full_duplex = 1;
+			break;
+		case SPEED_100 + DUPLEX_HALF:
+			np->speed = 100;
+			np->full_duplex = 0;
+			break;
+		case SPEED_100 + DUPLEX_FULL:
+			np->speed = 100;
+			np->full_duplex = 1;
+			break;
+		case SPEED_1000 + DUPLEX_HALF:/* not supported */
+		case SPEED_1000 + DUPLEX_FULL:/* not supported */
 		default:
-		return -EOPNOTSUPP;
-	}	
+			return -EINVAL;	
+		}
+		mii_set_media(dev);
+	}
+	return 0;
+}
+
+static u32 rio_get_link(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	return np->link_status;
 }
 
+static struct ethtool_ops ethtool_ops = {
+	.get_drvinfo = rio_get_drvinfo,
+	.get_settings = rio_get_settings,
+	.set_settings = rio_set_settings,
+	.get_link = rio_get_link,
+};
 
 static int
 rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	int phy_addr;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru;
 	
 	struct netdev_desc *desc;
@@ -1332,8 +1315,6 @@
 
 	phy_addr = np->phy_addr;
 	switch (cmd) {
-	case SIOCETHTOOL:
-		return rio_ethtool_ioctl(dev, rq->ifr_data);		
 	case SIOCDEVPRIVATE:
 		break;
 	
@@ -1490,7 +1471,7 @@
 	int phy_addr;
 	struct netdev_private *np;
 
-	np = dev->priv;
+	np = netdev_priv(dev);
 	phy_addr = np->phy_addr;
 
 	do {
@@ -1512,7 +1493,7 @@
 	int phy_addr;
 	struct netdev_private *np;
 
-	np = dev->priv;
+	np = netdev_priv(dev);
 	phy_addr = np->phy_addr;
 
 	bmsr.image = mii_read (dev, phy_addr, MII_BMSR);
@@ -1594,7 +1575,7 @@
 	ANAR_t anar;
 	int phy_addr;
 	struct netdev_private *np;
-	np = dev->priv;
+	np = netdev_priv(dev);
 	phy_addr = np->phy_addr;
 
 	/* Does user set speed? */
@@ -1684,7 +1665,7 @@
 	int phy_addr;
 	struct netdev_private *np;
 
-	np = dev->priv;
+	np = netdev_priv(dev);
 	phy_addr = np->phy_addr;
 
 	bmsr.image = mii_read (dev, phy_addr, PCS_BMSR);
@@ -1740,7 +1721,7 @@
 	ANAR_PCS_t anar;
 	int phy_addr;
 	struct netdev_private *np;
-	np = dev->priv;
+	np = netdev_priv(dev);
 	phy_addr = np->phy_addr;
 
 	/* Auto-Negotiation? */
@@ -1794,7 +1775,7 @@
 rio_close (struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	struct sk_buff *skb;
 	int i;
 
@@ -1840,7 +1821,7 @@
 	struct net_device *dev = pci_get_drvdata (pdev);
 
 	if (dev) {
-		struct netdev_private *np = dev->priv;
+		struct netdev_private *np = netdev_priv(dev);
 
 		unregister_netdev (dev);
 		pci_free_consistent (pdev, RX_TOTAL_SIZE, np->rx_ring,
diff -Nru a/drivers/net/e100.c b/drivers/net/e100.c
--- a/drivers/net/e100.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/e100.c	2004-10-10 22:15:16 -07:00
@@ -154,8 +154,8 @@
 
 
 #define DRV_NAME		"e100"
-#define DRV_EXT			"-NAPI"
-#define DRV_VERSION		"3.0.27-k2"DRV_EXT
+#define DRV_EXT		"-NAPI"
+#define DRV_VERSION		"3.1.4-k2"DRV_EXT
 #define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
 #define DRV_COPYRIGHT		"Copyright(c) 1999-2004 Intel Corporation"
 #define PFX			DRV_NAME ": "
@@ -575,13 +575,21 @@
 
 static inline void e100_enable_irq(struct nic *nic)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&nic->cmd_lock, flags);
 	writeb(irq_mask_none, &nic->csr->scb.cmd_hi);
+	spin_unlock_irqrestore(&nic->cmd_lock, flags);
 	e100_write_flush(nic);
 }
 
 static inline void e100_disable_irq(struct nic *nic)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&nic->cmd_lock, flags);
 	writeb(irq_mask_all, &nic->csr->scb.cmd_hi);
+	spin_unlock_irqrestore(&nic->cmd_lock, flags);
 	e100_write_flush(nic);
 }
 
@@ -1254,8 +1262,13 @@
 	mii_check_link(&nic->mii);
 
 	/* Software generated interrupt to recover from (rare) Rx
-	 * allocation failure */
-	writeb(irq_sw_gen, &nic->csr->scb.cmd_hi);
+	* allocation failure.
+	* Unfortunately have to use a spinlock to not re-enable interrupts
+	* accidentally, due to hardware that shares a register between the
+	* interrupt mask bit and the SW Interrupt generation bit */
+	spin_lock_irq(&nic->cmd_lock);
+	writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
+	spin_unlock_irq(&nic->cmd_lock);
 	e100_write_flush(nic);
 
 	e100_update_stats(nic);
@@ -1305,6 +1318,7 @@
 	switch(err) {
 	case -ENOSPC:
 		/* We queued the skb, but now we're out of space. */
+		DPRINTK(TX_ERR, DEBUG, "No space for CB\n");
 		netif_stop_queue(netdev);
 		break;
 	case -ENOMEM:
@@ -1425,14 +1439,12 @@
 #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
 static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
 {
-	unsigned int rx_offset = 2; /* u32 align protocol headers */
-
-	if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + rx_offset)))
+	if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN)))
 		return -ENOMEM;
 
 	/* Align, init, and map the RFD. */
 	rx->skb->dev = nic->netdev;
-	skb_reserve(rx->skb, rx_offset);
+	skb_reserve(rx->skb, NET_IP_ALIGN);
 	memcpy(rx->skb->data, &nic->blank_rfd, sizeof(struct rfd));
 	rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
 		RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
@@ -1471,7 +1483,7 @@
 
 	/* If data isn't ready, nothing to indicate */
 	if(unlikely(!(rfd_status & cb_complete)))
-       		return -EAGAIN;
+		return -EAGAIN;
 
 	/* Get actual data size */
 	actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
@@ -1763,7 +1775,7 @@
 
 	if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
 	   skb->data, ETH_DATA_LEN))
-       		err = -EAGAIN;
+		err = -EAGAIN;
 
 err_loopback_none:
 	mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0);
@@ -1962,6 +1974,8 @@
 	rfds->count = min(rfds->count, rfds->max);
 	cbs->count = max(ring->tx_pending, cbs->min);
 	cbs->count = min(cbs->count, cbs->max);
+	DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n",
+	        rfds->count, cbs->count);
 	if(netif_running(netdev))
 		e100_up(nic);
 
@@ -2173,6 +2187,7 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	netdev->poll_controller = e100_netpoll;
 #endif
+	strcpy(netdev->name, pci_name(pdev));
 
 	nic = netdev_priv(netdev);
 	nic->netdev = netdev;
@@ -2256,6 +2271,7 @@
 
 	pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
 
+	strcpy(netdev->name, "eth%d");
 	if((err = register_netdev(netdev))) {
 		DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n");
 		goto err_out_free;
@@ -2352,7 +2368,7 @@
 		printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
 		printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);
 	}
-        return pci_module_init(&e100_driver);
+	return pci_module_init(&e100_driver);
 }
 
 static void __exit e100_cleanup_module(void)
diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
--- a/drivers/net/e1000/e1000.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/e1000/e1000.h	2004-10-10 22:15:16 -07:00
@@ -64,7 +64,6 @@
 #include <linux/udp.h>
 #include <net/pkt_sched.h>
 #include <linux/list.h>
-#include <linux/rtnetlink.h>
 #include <linux/reboot.h>
 #ifdef NETIF_F_TSO
 #include <net/checksum.h>
@@ -73,7 +72,6 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
-#include <linux/moduleparam.h>
 
 #define BAR_0		0
 #define BAR_1		1
diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
--- a/drivers/net/e1000/e1000_ethtool.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/e1000/e1000_ethtool.c	2004-10-10 22:15:16 -07:00
@@ -1017,8 +1017,8 @@
 		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
 		struct sk_buff *skb;
 
-		if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
-				     GFP_KERNEL))) {
+		if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, 
+				GFP_KERNEL))) {
 			ret_val = 6;
 			goto err_nomem;
 		}
@@ -1442,6 +1442,8 @@
 	case E1000_DEV_ID_82543GC_COPPER:
 	case E1000_DEV_ID_82544EI_FIBER:
 	case E1000_DEV_ID_82546EB_QUAD_COPPER:
+	case E1000_DEV_ID_82545EM_FIBER:
+	case E1000_DEV_ID_82545EM_COPPER:
 		wol->supported = 0;
 		wol->wolopts   = 0;
 		return;
diff -Nru a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
--- a/drivers/net/e1000/e1000_hw.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/e1000/e1000_hw.c	2004-10-10 22:15:16 -07:00
@@ -65,6 +65,7 @@
 static void e1000_standby_eeprom(struct e1000_hw *hw);
 static int32_t e1000_id_led_init(struct e1000_hw * hw);
 static int32_t e1000_set_vco_speed(struct e1000_hw *hw);
+static int32_t e1000_polarity_reversal_workaround(struct e1000_hw *hw);
 static int32_t e1000_set_phy_mode(struct e1000_hw *hw);
 
 /* IGP cable length table */
@@ -1594,6 +1595,15 @@
         ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
         if(ret_val)
             return ret_val;
+
+        if((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) &&
+           (!hw->autoneg) &&
+           (hw->forced_speed_duplex == e1000_10_full ||
+            hw->forced_speed_duplex == e1000_10_half)) {
+            ret_val = e1000_polarity_reversal_workaround(hw);
+            if(ret_val)
+                return ret_val;
+        }
     }
     return E1000_SUCCESS;
 }
@@ -1983,6 +1993,7 @@
     uint32_t ctrl;
     uint32_t status;
     uint32_t rctl;
+    uint32_t icr;
     uint32_t signal = 0;
     int32_t ret_val;
     uint16_t phy_data;
@@ -2032,6 +2043,25 @@
              * link-up */
             e1000_check_downshift(hw);
 
+            /* If we are on 82544 or 82543 silicon and speed/duplex
+             * are forced to 10H or 10F, then we will implement the polarity
+             * reversal workaround.  We disable interrupts first, and upon
+             * returning, place the devices interrupt state to its previous
+             * value except for the link status change interrupt which will
+             * happen due to the execution of this workaround.
+             */
+
+            if((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) &&
+               (!hw->autoneg) &&
+               (hw->forced_speed_duplex == e1000_10_full ||
+                hw->forced_speed_duplex == e1000_10_half)) {
+                E1000_WRITE_REG(hw, IMC, 0xffffffff);
+                ret_val = e1000_polarity_reversal_workaround(hw);
+                icr = E1000_READ_REG(hw, ICR);
+                E1000_WRITE_REG(hw, ICS, (icr & ~E1000_ICS_LSC));
+                E1000_WRITE_REG(hw, IMS, IMS_ENABLE_MASK);
+            }
+
         } else {
             /* No link detected */
             e1000_config_dsp_after_link_change(hw, FALSE);
@@ -5214,5 +5244,90 @@
             return TRUE;
     }
     return FALSE;
+}
+
+static int32_t
+e1000_polarity_reversal_workaround(struct e1000_hw *hw)
+{
+    int32_t ret_val;
+    uint16_t mii_status_reg;
+    uint16_t i;
+
+    /* Polarity reversal workaround for forced 10F/10H links. */
+
+    /* Disable the transmitter on the PHY */
+
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+    if(ret_val)
+        return ret_val;
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
+    if(ret_val)
+        return ret_val;
+
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+    if(ret_val)
+        return ret_val;
+
+    /* This loop will early-out if the NO link condition has been met. */
+    for(i = PHY_FORCE_TIME; i > 0; i--) {
+        /* Read the MII Status Register and wait for Link Status bit
+         * to be clear.
+         */
+
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+        if(ret_val)
+            return ret_val;
+
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+        if(ret_val)
+            return ret_val;
+
+        if((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) break;
+        msec_delay_irq(100);
+    }
+
+    /* Recommended delay time after link has been lost */
+    msec_delay_irq(1000);
+
+    /* Now we will re-enable th transmitter on the PHY */
+
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+    if(ret_val)
+        return ret_val;
+    msec_delay_irq(50);
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
+    if(ret_val)
+        return ret_val;
+    msec_delay_irq(50);
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
+    if(ret_val)
+        return ret_val;
+    msec_delay_irq(50);
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
+    if(ret_val)
+        return ret_val;
+
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+    if(ret_val)
+        return ret_val;
+
+    /* This loop will early-out if the link condition has been met. */
+    for(i = PHY_FORCE_TIME; i > 0; i--) {
+        /* Read the MII Status Register and wait for Link Status bit
+         * to be set.
+         */
+
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+        if(ret_val)
+            return ret_val;
+
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+        if(ret_val)
+            return ret_val;
+
+        if(mii_status_reg & MII_SR_LINK_STATUS) break;
+        msec_delay_irq(100);
+    }
+    return E1000_SUCCESS;
 }
 
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/e1000/e1000_main.c	2004-10-10 22:15:16 -07:00
@@ -311,7 +311,8 @@
 void
 e1000_reset(struct e1000_adapter *adapter)
 {
-	uint32_t pba, manc;
+	uint32_t pba;
+
 	/* Repartition Pba for greater than 9k mtu
 	 * To take effect CTRL.RST is required.
 	 */
@@ -354,12 +355,6 @@
 
 	e1000_reset_adaptive(&adapter->hw);
 	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
-
-	if(adapter->en_mng_pt) {
-		manc = E1000_READ_REG(&adapter->hw, MANC);
-		manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST);
-		E1000_WRITE_REG(&adapter->hw, MANC, manc);
-	}
 }
 
 /**
@@ -422,11 +417,6 @@
 	adapter->hw.back = adapter;
 	adapter->msg_enable = (1 << debug) - 1;
 
-	rtnl_lock();
-	/* we need to set the name early for the DPRINTK macro */
-	if(dev_alloc_name(netdev, netdev->name) < 0)
-		goto err_free_unlock;
-
 	mmio_start = pci_resource_start(pdev, BAR_0);
 	mmio_len = pci_resource_len(pdev, BAR_0);
 
@@ -466,6 +456,7 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	netdev->poll_controller = e1000_netpoll;
 #endif
+	strcpy(netdev->name, pci_name(pdev));
 
 	netdev->mem_start = mmio_start;
 	netdev->mem_end = mmio_start + mmio_len;
@@ -502,8 +493,6 @@
  	/* hard_start_xmit is safe against parallel locking */
  	netdev->features |= NETIF_F_LLTX; 
  
-	adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
-
 	/* before reading the EEPROM, reset the controller to 
 	 * put the device in a known good starting state */
 	
@@ -553,7 +542,6 @@
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
 
-	DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
 	e1000_check_options(adapter);
 
 	/* Initial Wake on LAN setting
@@ -586,12 +574,13 @@
 	/* reset the hardware with the new settings */
 	e1000_reset(adapter);
 
-	/* We're already holding the rtnl lock; call the no-lock version */
-	if((err = register_netdevice(netdev)))
+	strcpy(netdev->name, "eth%d");
+	if((err = register_netdev(netdev)))
 		goto err_register;
 
+	DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
+
 	cards_found++;
-	rtnl_unlock();
 	return 0;
 
 err_register:
@@ -599,8 +588,6 @@
 err_eeprom:
 	iounmap(adapter->hw.hw_addr);
 err_ioremap:
-err_free_unlock:
-	rtnl_unlock();
 	free_netdev(netdev);
 err_alloc_etherdev:
 	pci_release_regions(pdev);
@@ -641,6 +628,8 @@
 	pci_release_regions(pdev);
 
 	free_netdev(netdev);
+
+	pci_disable_device(pdev);
 }
 
 /**
@@ -2335,8 +2324,8 @@
 		if(unlikely(adapter->vlgrp &&
 			    (rx_desc->status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-						 le16_to_cpu(rx_desc->special &
-						 E1000_RXD_SPC_VLAN_MASK));
+					le16_to_cpu(rx_desc->special) &
+					E1000_RXD_SPC_VLAN_MASK);
 		} else {
 			netif_receive_skb(skb);
 		}
@@ -2344,8 +2333,8 @@
 		if(unlikely(adapter->vlgrp &&
 			    (rx_desc->status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_rx(skb, adapter->vlgrp,
-					le16_to_cpu(rx_desc->special &
-					E1000_RXD_SPC_VLAN_MASK));
+					le16_to_cpu(rx_desc->special) &
+					E1000_RXD_SPC_VLAN_MASK);
 		} else {
 			netif_rx(skb);
 		}
@@ -2894,9 +2883,9 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev->priv;
-	uint32_t manc;
+	uint32_t manc, ret;
 
-	pci_enable_device(pdev);
+	ret = pci_enable_device(pdev);
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev, adapter->pci_state);
 
diff -Nru a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
--- a/drivers/net/e1000/e1000_osdep.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/e1000/e1000_osdep.h	2004-10-10 22:15:16 -07:00
@@ -49,6 +49,12 @@
 				set_current_state(TASK_UNINTERRUPTIBLE); \
 				schedule_timeout((x * HZ)/1000 + 2); \
 			} } while(0)
+/* Some workarounds require millisecond delays and are run during interrupt
+ * context.  Most notably, when establishing link, the phy may need tweaking
+ * but cannot process phy register reads/writes faster than millisecond
+ * intervals...and we establish link due to a "link status change" interrupt.
+ */
+#define msec_delay_irq(x) mdelay(x)
 #endif
 
 #define PCI_COMMAND_REGISTER   PCI_COMMAND
diff -Nru a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
--- a/drivers/net/e1000/e1000_param.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/e1000/e1000_param.c	2004-10-10 22:15:16 -07:00
@@ -34,31 +34,21 @@
 
 #define E1000_MAX_NIC 32
 
-#define OPTION_UNSET    -1
+#define OPTION_UNSET   -1
 #define OPTION_DISABLED 0
 #define OPTION_ENABLED  1
 
-/* Module Parameters are always initialized to -1, so that the driver
- * can tell the difference between no user specified value or the
- * user asking for the default value.
- * The true default values are loaded in when e1000_check_options is called.
- *
- * This is a GCC extension to ANSI C.
- * See the item "Labeled Elements in Initializers" in the section
- * "Extensions to the C Language Family" of the GCC documentation.
- */
-
-#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
-
 /* All parameters are treated the same, as an integer array of values.
  * This macro just reduces the need to repeat the same declaration code
  * over and over (plus this helps to avoid typo bugs).
  */
 
-#define E1000_PARAM(X, S) \
-static const int __devinitdata X[E1000_MAX_NIC + 1] = E1000_PARAM_INIT; \
-MODULE_PARM(X, "1-" __MODULE_STRING(E1000_MAX_NIC) "i"); \
-MODULE_PARM_DESC(X, S);
+#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
+#define E1000_PARAM(X, desc) \
+	static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
+	static int num_##X = 0; \
+	module_param_array(X, int, num_##X, 0); \
+	MODULE_PARM_DESC(X, desc);
 
 /* Transmit Descriptor Count
  *
@@ -305,7 +295,6 @@
 		DPRINTK(PROBE, NOTICE,
 		       "Warning: no configuration for board #%i\n", bd);
 		DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
-		bd = E1000_MAX_NIC;
 	}
 
 	{ /* Transmit Descriptor Count */
@@ -322,9 +311,14 @@
 		opt.arg.r.max = mac_type < e1000_82544 ?
 			E1000_MAX_TXD : E1000_MAX_82544_TXD;
 
-		tx_ring->count = TxDescriptors[bd];
-		e1000_validate_option(&tx_ring->count, &opt, adapter);
-		E1000_ROUNDUP(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+		if (num_TxDescriptors > bd) {
+			tx_ring->count = TxDescriptors[bd];
+			e1000_validate_option(&tx_ring->count, &opt, adapter);
+			E1000_ROUNDUP(tx_ring->count, 
+						REQ_TX_DESCRIPTOR_MULTIPLE);
+		} else {
+			tx_ring->count = opt.def;
+		}
 	}
 	{ /* Receive Descriptor Count */
 		struct e1000_option opt = {
@@ -340,9 +334,14 @@
 		opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
 			E1000_MAX_82544_RXD;
 
-		rx_ring->count = RxDescriptors[bd];
-		e1000_validate_option(&rx_ring->count, &opt, adapter);
-		E1000_ROUNDUP(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE);
+		if (num_RxDescriptors > bd) {
+			rx_ring->count = RxDescriptors[bd];
+			e1000_validate_option(&rx_ring->count, &opt, adapter);
+			E1000_ROUNDUP(rx_ring->count, 
+						REQ_RX_DESCRIPTOR_MULTIPLE);
+		} else {
+			rx_ring->count = opt.def;
+		}
 	}
 	{ /* Checksum Offload Enable/Disable */
 		struct e1000_option opt = {
@@ -352,9 +351,13 @@
 			.def  = OPTION_ENABLED
 		};
 
-		int rx_csum = XsumRX[bd];
-		e1000_validate_option(&rx_csum, &opt, adapter);
-		adapter->rx_csum = rx_csum;
+		if (num_XsumRX > bd) {
+			int rx_csum = XsumRX[bd];
+			e1000_validate_option(&rx_csum, &opt, adapter);
+			adapter->rx_csum = rx_csum;
+		} else {
+			adapter->rx_csum = opt.def;
+		}
 	}
 	{ /* Flow Control */
 
@@ -374,9 +377,13 @@
 					 .p = fc_list }}
 		};
 
-		int fc = FlowControl[bd];
-		e1000_validate_option(&fc, &opt, adapter);
-		adapter->hw.fc = adapter->hw.original_fc = fc;
+		if (num_FlowControl > bd) {
+			int fc = FlowControl[bd];
+			e1000_validate_option(&fc, &opt, adapter);
+			adapter->hw.fc = adapter->hw.original_fc = fc;
+		} else {
+			adapter->hw.fc = opt.def;
+		}
 	}
 	{ /* Transmit Interrupt Delay */
 		struct e1000_option opt = {
@@ -388,8 +395,13 @@
 					 .max = MAX_TXDELAY }}
 		};
 
-		adapter->tx_int_delay = TxIntDelay[bd];
-		e1000_validate_option(&adapter->tx_int_delay, &opt, adapter);
+		if (num_TxIntDelay > bd) {
+			adapter->tx_int_delay = TxIntDelay[bd];
+			e1000_validate_option(&adapter->tx_int_delay, &opt, 
+								adapter);
+		} else {
+			adapter->tx_int_delay = opt.def;
+		}
 	}
 	{ /* Transmit Absolute Interrupt Delay */
 		struct e1000_option opt = {
@@ -401,8 +413,13 @@
 					 .max = MAX_TXABSDELAY }}
 		};
 
-		adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
-		e1000_validate_option(&adapter->tx_abs_int_delay, &opt, adapter);
+		if (num_TxAbsIntDelay > bd) {
+			adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
+			e1000_validate_option(&adapter->tx_abs_int_delay, &opt, 
+								adapter);
+		} else {
+			adapter->tx_abs_int_delay = opt.def;
+		}
 	}
 	{ /* Receive Interrupt Delay */
 		struct e1000_option opt = {
@@ -414,8 +431,13 @@
 					 .max = MAX_RXDELAY }}
 		};
 
-		adapter->rx_int_delay = RxIntDelay[bd];
-		e1000_validate_option(&adapter->rx_int_delay, &opt, adapter);
+		if (num_RxIntDelay > bd) {
+			adapter->rx_int_delay = RxIntDelay[bd];
+			e1000_validate_option(&adapter->rx_int_delay, &opt, 
+								adapter);
+		} else {
+			adapter->rx_int_delay = opt.def;
+		}
 	}
 	{ /* Receive Absolute Interrupt Delay */
 		struct e1000_option opt = {
@@ -427,8 +449,13 @@
 					 .max = MAX_RXABSDELAY }}
 		};
 
-		adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
-		e1000_validate_option(&adapter->rx_abs_int_delay, &opt, adapter);
+		if (num_RxAbsIntDelay > bd) {
+			adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
+			e1000_validate_option(&adapter->rx_abs_int_delay, &opt, 
+								adapter);
+		} else {
+			adapter->rx_abs_int_delay = opt.def;
+		}
 	}
 	{ /* Interrupt Throttling Rate */
 		struct e1000_option opt = {
@@ -440,20 +467,27 @@
 					 .max = MAX_ITR }}
 		};
 
-		adapter->itr = InterruptThrottleRate[bd];
-		switch(adapter->itr) {
-		case -1:
+		if (num_InterruptThrottleRate > bd) {
+			adapter->itr = InterruptThrottleRate[bd];
+			switch(adapter->itr) {
+			case -1:
+				adapter->itr = 1;
+				break;
+			case 0:
+				DPRINTK(PROBE, INFO, "%s turned off\n", 
+					opt.name);
+				break;
+			case 1:
+				DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", 
+					opt.name);
+				break;
+			default:
+				e1000_validate_option(&adapter->itr, &opt, 
+					adapter);
+				break;
+			}
+		} else {
 			adapter->itr = 1;
-			break;
-		case 0:
-			DPRINTK(PROBE, INFO, "%s turned off\n", opt.name);
-			break;
-		case 1:
-			DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", opt.name);
-			break;
-		default:
-			e1000_validate_option(&adapter->itr, &opt, adapter);
-			break;
 		}
 	}
 
@@ -481,17 +515,17 @@
 e1000_check_fiber_options(struct e1000_adapter *adapter)
 {
 	int bd = adapter->bd_number;
-	bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd;
-
-	if((Speed[bd] != OPTION_UNSET)) {
+	if(num_Speed > bd) {
 		DPRINTK(PROBE, INFO, "Speed not valid for fiber adapters, "
 		       "parameter ignored\n");
 	}
-	if((Duplex[bd] != OPTION_UNSET)) {
+
+	if(num_Duplex > bd) {
 		DPRINTK(PROBE, INFO, "Duplex not valid for fiber adapters, "
 		       "parameter ignored\n");
 	}
-	if((AutoNeg[bd] != OPTION_UNSET) && (AutoNeg[bd] != 0x20)) {
+
+	if((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
 		DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is "
 				 "not valid for fiber adapters, "
 				 "parameter ignored\n");
@@ -510,7 +544,6 @@
 {
 	int speed, dplx;
 	int bd = adapter->bd_number;
-	bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd;
 
 	{ /* Speed */
 		struct e1000_opt_list speed_list[] = {{          0, "" },
@@ -527,8 +560,12 @@
 					 .p = speed_list }}
 		};
 
-		speed = Speed[bd];
-		e1000_validate_option(&speed, &opt, adapter);
+		if (num_Speed > bd) {
+			speed = Speed[bd];
+			e1000_validate_option(&speed, &opt, adapter);
+		} else {
+			speed = opt.def;
+		}
 	}
 	{ /* Duplex */
 		struct e1000_opt_list dplx_list[] = {{           0, "" },
@@ -544,11 +581,15 @@
 					 .p = dplx_list }}
 		};
 
-		dplx = Duplex[bd];
-		e1000_validate_option(&dplx, &opt, adapter);
+		if (num_Duplex > bd) {
+			dplx = Duplex[bd];
+			e1000_validate_option(&dplx, &opt, adapter);
+		} else {
+			dplx = opt.def;
+		}
 	}
 
-	if(AutoNeg[bd] != OPTION_UNSET && (speed != 0 || dplx != 0)) {
+	if((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
 		DPRINTK(PROBE, INFO,
 		       "AutoNeg specified along with Speed or Duplex, "
 		       "parameter ignored\n");
@@ -605,7 +646,7 @@
 	switch (speed + dplx) {
 	case 0:
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
-		if(Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET)
+		if((num_Speed > bd) && (speed != 0 || dplx != 0))
 			DPRINTK(PROBE, INFO,
 			       "Speed and duplex autonegotiation enabled\n");
 		break;
diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/eepro100.c	2004-10-10 22:15:16 -07:00
@@ -114,11 +114,7 @@
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
 
-/* enable PIO instead of MMIO, if CONFIG_EEPRO100_PIO is selected */
-#ifdef CONFIG_EEPRO100_PIO
-#define USE_IO 1
-#endif
-
+static int use_io;
 static int debug = -1;
 #define DEBUG_DEFAULT		(NETIF_MSG_DRV		| \
 				 NETIF_MSG_HW		| \
@@ -130,6 +126,7 @@
 MODULE_AUTHOR("Maintainer: Andrey V. Savochkin <saw@saw.sw.com.sg>");
 MODULE_DESCRIPTION("Intel i82557/i82558/i82559 PCI EtherExpressPro driver");
 MODULE_LICENSE("GPL");
+MODULE_PARM(use_io, "i");
 MODULE_PARM(debug, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
@@ -289,39 +286,13 @@
 
 */
 
-static int speedo_found1(struct pci_dev *pdev, long ioaddr, int fnd_cnt, int acpi_idle_state);
+static int speedo_found1(struct pci_dev *pdev, void __iomem *ioaddr, int fnd_cnt, int acpi_idle_state);
 
 enum pci_flags_bit {
 	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
 	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
 };
 
-static inline unsigned int io_inw(unsigned long port)
-{
-	return inw(port);
-}
-static inline void io_outw(unsigned int val, unsigned long port)
-{
-	outw(val, port);
-}
-
-#ifndef USE_IO
-/* Currently alpha headers define in/out macros.
-   Undefine them.  2000/03/30  SAW */
-#undef inb
-#undef inw
-#undef inl
-#undef outb
-#undef outw
-#undef outl
-#define inb readb
-#define inw readw
-#define inl readl
-#define outb writeb
-#define outw writew
-#define outl writel
-#endif
-
 /* Offsets to the various registers.
    All accesses need not be longword aligned. */
 enum speedo_offsets {
@@ -453,6 +424,7 @@
    Unfortunately, all the positions have been shifted since there.
    A new re-alignment is required.  2000/03/06  SAW */
 struct speedo_private {
+    void __iomem *regs;
 	struct TxFD	*tx_ring;		/* Commands (usually CmdTxPacket). */
 	struct RxFD *rx_ringp[RX_RING_SIZE];	/* Rx descriptor, used as ring. */
 	/* The addresses of a Tx/Rx-in-place packets/buffers. */
@@ -523,7 +495,7 @@
 static int eepro100_init_one(struct pci_dev *pdev,
 		const struct pci_device_id *ent);
 
-static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
+static int do_eeprom_cmd(void __iomem *ioaddr, int cmd, int cmd_len);
 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 speedo_open(struct net_device *dev);
@@ -541,6 +513,7 @@
 static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void set_rx_mode(struct net_device *dev);
 static void speedo_show_state(struct net_device *dev);
+static struct ethtool_ops ethtool_ops;
 
 
 
@@ -553,15 +526,16 @@
 
 /* How to wait for the command unit to accept a command.
    Typically this takes 0 ticks. */
-static inline unsigned char wait_for_cmd_done(struct net_device *dev)
+static inline unsigned char wait_for_cmd_done(struct net_device *dev,
+											  	struct speedo_private *sp)
 {
 	int wait = 1000;
-	long cmd_ioaddr = dev->base_addr + SCBCmd;
+	void __iomem *cmd_ioaddr = sp->regs + SCBCmd;
 	unsigned char r;
 
 	do  {
 		udelay(1);
-		r = inb(cmd_ioaddr);
+		r = ioread8(cmd_ioaddr);
 	} while(r && --wait >= 0);
 
 	if (wait < 0)
@@ -572,10 +546,11 @@
 static int __devinit eepro100_init_one (struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
-	unsigned long ioaddr;
-	int irq;
+	void __iomem *ioaddr;
+	int irq, pci_bar;
 	int acpi_idle_state = 0, pm;
 	static int cards_found /* = 0 */;
+	unsigned long pci_base;
 
 #ifndef MODULE
 	/* when built-in, we only print version if device is found */
@@ -609,24 +584,17 @@
 	}
 
 	irq = pdev->irq;
-#ifdef USE_IO
-	ioaddr = pci_resource_start(pdev, 1);
+	pci_bar = use_io ? 1 : 0;
+	pci_base = pci_resource_start(pdev, pci_bar);
 	if (DEBUG & NETIF_MSG_PROBE)
-		printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",
-			   ioaddr, irq);
-#else
-	ioaddr = (unsigned long)ioremap(pci_resource_start(pdev, 0),
-									pci_resource_len(pdev, 0));
+		printk("Found Intel i82557 PCI Speedo at %#lx, IRQ %d.\n",
+		       pci_base, irq);
+
+	ioaddr = pci_iomap(pdev, pci_bar, 0);
 	if (!ioaddr) {
-		printk (KERN_ERR "eepro100: cannot remap MMIO region %lx @ %lx\n",
-				pci_resource_len(pdev, 0), pci_resource_start(pdev, 0));
+		printk (KERN_ERR "eepro100: cannot remap IO\n");
 		goto err_out_free_mmio_region;
 	}
-	if (DEBUG & NETIF_MSG_PROBE)
-		printk("Found Intel i82557 PCI Speedo, MMIO at %#lx, IRQ %d.\n",
-			   pci_resource_start(pdev, 0), irq);
-#endif
-
 
 	if (speedo_found1(pdev, ioaddr, cards_found, acpi_idle_state) == 0)
 		cards_found++;
@@ -636,9 +604,7 @@
 	return 0;
 
 err_out_iounmap: ;
-#ifndef USE_IO
-	iounmap ((void *)ioaddr);
-#endif
+	pci_iounmap(pdev, ioaddr);
 err_out_free_mmio_region:
 	release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
 err_out_free_pio_region:
@@ -665,7 +631,7 @@
 #endif
 
 static int __devinit speedo_found1(struct pci_dev *pdev,
-		long ioaddr, int card_idx, int acpi_idle_state)
+		void __iomem *ioaddr, int card_idx, int acpi_idle_state)
 {
 	struct net_device *dev;
 	struct speedo_private *sp;
@@ -708,14 +674,16 @@
 	   The size test is for 6 bit vs. 8 bit address serial EEPROMs.
 	*/
 	{
-		unsigned long iobase;
+		void __iomem *iobase;
 		int read_cmd, ee_size;
 		u16 sum;
 		int j;
 
 		/* Use IO only to avoid postponed writes and satisfy EEPROM timing
 		   requirements. */
-		iobase = pci_resource_start(pdev, 1);
+		iobase = pci_iomap(pdev, 1, pci_resource_len(pdev, 1));
+		if (!iobase)
+			goto err_free_unlock;
 		if ((do_eeprom_cmd(iobase, EE_READ_CMD << 24, 27) & 0xffe0000)
 			== 0xffe0000) {
 			ee_size = 0x100;
@@ -741,13 +709,15 @@
 		/* Don't  unregister_netdev(dev);  as the EEPro may actually be
 		   usable, especially if the MAC address is set later.
 		   On the other hand, it may be unusable if MDI data is corrupted. */
+
+		pci_iounmap(pdev, iobase);
 	}
 
 	/* Reset the chip: stop Tx and Rx processes and clear counters.
 	   This takes less than 10usec and will easily finish before the next
 	   action. */
-	outl(PortReset, ioaddr + SCBPort);
-	inl(ioaddr + SCBPort);
+	iowrite32(PortReset, ioaddr + SCBPort);
+	ioread32(ioaddr + SCBPort);
 	udelay(10);
 
 	if (eeprom[3] & 0x0100)
@@ -760,13 +730,12 @@
 	for (i = 0; i < 5; i++)
 		printk("%2.2X:", dev->dev_addr[i]);
 	printk("%2.2X, ", dev->dev_addr[i]);
-#ifdef USE_IO
-	printk("I/O at %#3lx, ", ioaddr);
-#endif
 	printk("IRQ %d.\n", pdev->irq);
 
-	/* we must initialize base_addr early, for mdio_{read,write} */
-	dev->base_addr = ioaddr;
+	sp = netdev_priv(dev);
+
+	/* we must initialize this early, for mdio_{read,write} */
+	sp->regs = ioaddr;
 
 #if 1 || defined(kernel_bloat)
 	/* OK, this is pure kernel bloat.  I don't like it when other drivers
@@ -813,7 +782,7 @@
 		self_test_results = (s32*) ((((long) tx_ring_space) + 15) & ~0xf);
 		self_test_results[0] = 0;
 		self_test_results[1] = -1;
-		outl(tx_ring_dma | PortSelfTest, ioaddr + SCBPort);
+		iowrite32(tx_ring_dma | PortSelfTest, ioaddr + SCBPort);
 		do {
 			udelay(10);
 		} while (self_test_results[1] == -1  &&  --boguscnt >= 0);
@@ -837,8 +806,8 @@
 	}
 #endif  /* kernel_bloat */
 
-	outl(PortReset, ioaddr + SCBPort);
-	inl(ioaddr + SCBPort);
+	iowrite32(PortReset, ioaddr + SCBPort);
+	ioread32(ioaddr + SCBPort);
 	udelay(10);
 
 	/* Return the chip to its original power state. */
@@ -849,7 +818,6 @@
 
 	dev->irq = pdev->irq;
 
-	sp = netdev_priv(dev);
 	sp->pdev = pdev;
 	sp->msg_enable = DEBUG;
 	sp->acpi_pwr = acpi_idle_state;
@@ -895,6 +863,7 @@
 	dev->get_stats = &speedo_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &speedo_ioctl;
+	SET_ETHTOOL_OPS(dev, &ethtool_ops);
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	dev->poll_controller = &poll_speedo;
 #endif
@@ -911,27 +880,27 @@
 	return -1;
 }
 
-static void do_slow_command(struct net_device *dev, int cmd)
+static void do_slow_command(struct net_device *dev, struct speedo_private *sp, int cmd)
 {
-	long cmd_ioaddr = dev->base_addr + SCBCmd;
+	void __iomem *cmd_ioaddr = sp->regs + SCBCmd;
 	int wait = 0;
 	do
-		if (inb(cmd_ioaddr) == 0) break;
+		if (ioread8(cmd_ioaddr) == 0) break;
 	while(++wait <= 200);
 	if (wait > 100)
 		printk(KERN_ERR "Command %4.4x never accepted (%d polls)!\n",
-		       inb(cmd_ioaddr), wait);
+		       ioread8(cmd_ioaddr), wait);
 
-	outb(cmd, cmd_ioaddr);
+	iowrite8(cmd, cmd_ioaddr);
 
 	for (wait = 0; wait <= 100; wait++)
-		if (inb(cmd_ioaddr) == 0) return;
+		if (ioread8(cmd_ioaddr) == 0) return;
 	for (; wait <= 20000; wait++)
-		if (inb(cmd_ioaddr) == 0) return;
+		if (ioread8(cmd_ioaddr) == 0) return;
 		else udelay(1);
 	printk(KERN_ERR "Command %4.4x was not accepted after %d polls!"
 	       "  Current status %8.8x.\n",
-	       cmd, wait, inl(dev->base_addr + SCBStatus));
+	       cmd, wait, ioread32(sp->regs + SCBStatus));
 }
 
 /* Serial EEPROM section.
@@ -953,35 +922,36 @@
    interval for serial EEPROM.  However, it looks like that there is an
    additional requirement dictating larger udelay's in the code below.
    2000/05/24  SAW */
-static int __devinit do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
+static int __devinit do_eeprom_cmd(void __iomem *ioaddr, int cmd, int cmd_len)
 {
 	unsigned retval = 0;
-	long ee_addr = ioaddr + SCBeeprom;
+	void __iomem *ee_addr = ioaddr + SCBeeprom;
 
-	io_outw(EE_ENB, ee_addr); udelay(2);
-	io_outw(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2);
+	iowrite16(EE_ENB, ee_addr); udelay(2);
+	iowrite16(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2);
 
 	/* Shift the command bits out. */
 	do {
 		short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
-		io_outw(dataval, ee_addr); udelay(2);
-		io_outw(dataval | EE_SHIFT_CLK, ee_addr); udelay(2);
-		retval = (retval << 1) | ((io_inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
+		iowrite16(dataval, ee_addr); udelay(2);
+		iowrite16(dataval | EE_SHIFT_CLK, ee_addr); udelay(2);
+		retval = (retval << 1) | ((ioread16(ee_addr) & EE_DATA_READ) ? 1 : 0);
 	} while (--cmd_len >= 0);
-	io_outw(EE_ENB, ee_addr); udelay(2);
+	iowrite16(EE_ENB, ee_addr); udelay(2);
 
 	/* Terminate the EEPROM access. */
-	io_outw(EE_ENB & ~EE_CS, ee_addr);
+	iowrite16(EE_ENB & ~EE_CS, ee_addr);
 	return retval;
 }
 
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
-	long ioaddr = dev->base_addr;
+	struct speedo_private *sp = netdev_priv(dev);
+	void __iomem *ioaddr = sp->regs;
 	int val, boguscnt = 64*10;		/* <64 usec. to complete, typ 27 ticks */
-	outl(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);
+	iowrite32(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);
 	do {
-		val = inl(ioaddr + SCBCtrlMDI);
+		val = ioread32(ioaddr + SCBCtrlMDI);
 		if (--boguscnt < 0) {
 			printk(KERN_ERR " mdio_read() timed out with val = %8.8x.\n", val);
 			break;
@@ -992,12 +962,13 @@
 
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
 {
-	long ioaddr = dev->base_addr;
+	struct speedo_private *sp = netdev_priv(dev);
+	void __iomem *ioaddr = sp->regs;
 	int val, boguscnt = 64*10;		/* <64 usec. to complete, typ 27 ticks */
-	outl(0x04000000 | (location<<16) | (phy_id<<21) | value,
+	iowrite32(0x04000000 | (location<<16) | (phy_id<<21) | value,
 		 ioaddr + SCBCtrlMDI);
 	do {
-		val = inl(ioaddr + SCBCtrlMDI);
+		val = ioread32(ioaddr + SCBCtrlMDI);
 		if (--boguscnt < 0) {
 			printk(KERN_ERR" mdio_write() timed out with val = %8.8x.\n", val);
 			break;
@@ -1009,7 +980,7 @@
 speedo_open(struct net_device *dev)
 {
 	struct speedo_private *sp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = sp->regs;
 	int retval;
 
 	if (netif_msg_ifup(sp))
@@ -1053,7 +1024,7 @@
 	speedo_init_rx_ring(dev);
 
 	/* Fire up the hardware. */
-	outw(SCBMaskAll, ioaddr + SCBCmd);
+	iowrite16(SCBMaskAll, ioaddr + SCBCmd);
 	speedo_resume(dev);
 
 	netdevice_start(dev);
@@ -1072,7 +1043,7 @@
 
 	if (netif_msg_ifup(sp)) {
 		printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n",
-			   dev->name, inw(ioaddr + SCBStatus));
+			   dev->name, ioread16(ioaddr + SCBStatus));
 	}
 
 	/* Set the timer.  The timer serves a dual purpose:
@@ -1096,46 +1067,46 @@
 static void speedo_resume(struct net_device *dev)
 {
 	struct speedo_private *sp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = sp->regs;
 
 	/* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */
 	sp->tx_threshold = 0x01208000;
 
 	/* Set the segment registers to '0'. */
-	if (wait_for_cmd_done(dev) != 0) {
-		outl(PortPartialReset, ioaddr + SCBPort);
+	if (wait_for_cmd_done(dev, sp) != 0) {
+		iowrite32(PortPartialReset, ioaddr + SCBPort);
 		udelay(10);
 	}
 
-        outl(0, ioaddr + SCBPointer);
-        inl(ioaddr + SCBPointer);			/* Flush to PCI. */
+        iowrite32(0, ioaddr + SCBPointer);
+        ioread32(ioaddr + SCBPointer);			/* Flush to PCI. */
         udelay(10);			/* Bogus, but it avoids the bug. */
 
         /* Note: these next two operations can take a while. */
-        do_slow_command(dev, RxAddrLoad);
-        do_slow_command(dev, CUCmdBase);
+        do_slow_command(dev, sp, RxAddrLoad);
+        do_slow_command(dev, sp, CUCmdBase);
 
 	/* Load the statistics block and rx ring addresses. */
-	outl(sp->lstats_dma, ioaddr + SCBPointer);
-	inl(ioaddr + SCBPointer);			/* Flush to PCI */
+	iowrite32(sp->lstats_dma, ioaddr + SCBPointer);
+	ioread32(ioaddr + SCBPointer);			/* Flush to PCI */
 
-	outb(CUStatsAddr, ioaddr + SCBCmd);
+	iowrite8(CUStatsAddr, ioaddr + SCBCmd);
 	sp->lstats->done_marker = 0;
-	wait_for_cmd_done(dev);
+	wait_for_cmd_done(dev, sp);
 
 	if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) {
 		if (netif_msg_rx_err(sp))
 			printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n",
 					dev->name);
 	} else {
-		outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
+		iowrite32(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
 			 ioaddr + SCBPointer);
-		inl(ioaddr + SCBPointer);		/* Flush to PCI */
+		ioread32(ioaddr + SCBPointer);		/* Flush to PCI */
 	}
 
 	/* Note: RxStart should complete instantly. */
-	do_slow_command(dev, RxStart);
-	do_slow_command(dev, CUDumpStats);
+	do_slow_command(dev, sp, RxStart);
+	do_slow_command(dev, sp, CUDumpStats);
 
 	/* Fill the first command with our physical address. */
 	{
@@ -1154,11 +1125,11 @@
 	}
 
 	/* Start the chip's Tx process and unmask interrupts. */
-	outl(TX_RING_ELEM_DMA(sp, sp->dirty_tx % TX_RING_SIZE),
+	iowrite32(TX_RING_ELEM_DMA(sp, sp->dirty_tx % TX_RING_SIZE),
 		 ioaddr + SCBPointer);
 	/* We are not ACK-ing FCP and ER in the interrupt handler yet so they should
 	   remain masked --Dragan */
-	outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd);
+	iowrite16(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd);
 }
 
 /*
@@ -1177,29 +1148,29 @@
 {
 	struct speedo_private *sp = netdev_priv(dev);
 	struct RxFD *rfd;
-	long ioaddr;
+	void __iomem *ioaddr;
 
-	ioaddr = dev->base_addr;
-	if (wait_for_cmd_done(dev) != 0) {
+	ioaddr = sp->regs;
+	if (wait_for_cmd_done(dev, sp) != 0) {
 		printk("%s: previous command stalled\n", dev->name);
 		return;
 	}
 	/*
 	* Put the hardware into a known state.
 	*/
-	outb(RxAbort, ioaddr + SCBCmd);
+	iowrite8(RxAbort, ioaddr + SCBCmd);
 
 	rfd = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
 
 	rfd->rx_buf_addr = 0xffffffff;
 
-	if (wait_for_cmd_done(dev) != 0) {
+	if (wait_for_cmd_done(dev, sp) != 0) {
 		printk("%s: RxAbort command stalled\n", dev->name);
 		return;
 	}
-	outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
+	iowrite32(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
 		ioaddr + SCBPointer);
-	outb(RxStart, ioaddr + SCBCmd);
+	iowrite8(RxStart, ioaddr + SCBCmd);
 }
 
 
@@ -1208,7 +1179,7 @@
 {
 	struct net_device *dev = (struct net_device *)data;
 	struct speedo_private *sp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = sp->regs;
 	int phy_num = sp->phy[0] & 0x1f;
 
 	/* We have MII and lost link beat. */
@@ -1231,7 +1202,7 @@
 	mii_check_link(&sp->mii_if);
 	if (netif_msg_timer(sp)) {
 		printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n",
-			   dev->name, inw(ioaddr + SCBStatus));
+			   dev->name, ioread16(ioaddr + SCBStatus));
 	}
 	if (sp->rx_mode < 0  ||
 		(sp->rx_bug  && jiffies - sp->last_rx_time > 2*HZ)) {
@@ -1278,7 +1249,7 @@
 
 #if 0
 	{
-		long ioaddr = dev->base_addr;
+		void __iomem *ioaddr = sp->regs;
 		int phy_num = sp->phy[0] & 0x1f;
 		for (i = 0; i < 16; i++) {
 			/* FIXME: what does it mean?  --SAW */
@@ -1399,14 +1370,14 @@
 static void speedo_tx_timeout(struct net_device *dev)
 {
 	struct speedo_private *sp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int status = inw(ioaddr + SCBStatus);
+	void __iomem *ioaddr = sp->regs;
+	int status = ioread16(ioaddr + SCBStatus);
 	unsigned long flags;
 
 	if (netif_msg_tx_err(sp)) {
 		printk(KERN_WARNING "%s: Transmit timed out: status %4.4x "
 		   " %4.4x at %d/%d command %8.8x.\n",
-		   dev->name, status, inw(ioaddr + SCBCmd),
+		   dev->name, status, ioread16(ioaddr + SCBCmd),
 		   sp->dirty_tx, sp->cur_tx,
 		   sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status);
 
@@ -1418,9 +1389,9 @@
 		/* Only the command unit has stopped. */
 		printk(KERN_WARNING "%s: Trying to restart the transmitter...\n",
 			   dev->name);
-		outl(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]),
+		iowrite32(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]),
 			 ioaddr + SCBPointer);
-		outw(CUStart, ioaddr + SCBCmd);
+		iowrite16(CUStart, ioaddr + SCBCmd);
 		reset_mii(dev);
 	} else {
 #else
@@ -1428,12 +1399,12 @@
 #endif
 		del_timer_sync(&sp->timer);
 		/* Reset the Tx and Rx units. */
-		outl(PortReset, ioaddr + SCBPort);
+		iowrite32(PortReset, ioaddr + SCBPort);
 		/* We may get spurious interrupts here.  But I don't think that they
 		   may do much harm.  1999/12/09 SAW */
 		udelay(10);
 		/* Disable interrupts. */
-		outw(SCBMaskAll, ioaddr + SCBCmd);
+		iowrite16(SCBMaskAll, ioaddr + SCBCmd);
 		synchronize_irq(dev->irq);
 		speedo_tx_buffer_gc(dev);
 		/* Free as much as possible.
@@ -1461,7 +1432,7 @@
 speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct speedo_private *sp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = sp->regs;
 	int entry;
 
 	/* Prevent interrupts from changing the Tx ring from underneath us. */
@@ -1500,18 +1471,18 @@
 	/* workaround for hardware bug on 10 mbit half duplex */
 
 	if ((sp->partner == 0) && (sp->chip_id == 1)) {
-		wait_for_cmd_done(dev);
-		outb(0 , ioaddr + SCBCmd);
+		wait_for_cmd_done(dev, sp);
+		iowrite8(0 , ioaddr + SCBCmd);
 		udelay(1);
 	}
 
 	/* Trigger the command unit resume. */
-	wait_for_cmd_done(dev);
+	wait_for_cmd_done(dev, sp);
 	clear_suspend(sp->last_cmd);
 	/* We want the time window between clearing suspend flag on the previous
 	   command and resuming CU to be as small as possible.
 	   Interrupts in between are very undesired.  --SAW */
-	outb(CUResume, ioaddr + SCBCmd);
+	iowrite8(CUResume, ioaddr + SCBCmd);
 	sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
 
 	/* Leave room for set_rx_mode(). If there is no more space than reserved
@@ -1593,12 +1564,13 @@
 {
 	struct net_device *dev = (struct net_device *)dev_instance;
 	struct speedo_private *sp;
-	long ioaddr, boguscnt = max_interrupt_work;
+	void __iomem *ioaddr;
+	long boguscnt = max_interrupt_work;
 	unsigned short status;
 	unsigned int handled = 0;
 
-	ioaddr = dev->base_addr;
 	sp = netdev_priv(dev);
+	ioaddr = sp->regs;
 
 #ifndef final_version
 	/* A lock to prevent simultaneous entry on SMP machines. */
@@ -1611,11 +1583,11 @@
 #endif
 
 	do {
-		status = inw(ioaddr + SCBStatus);
+		status = ioread16(ioaddr + SCBStatus);
 		/* Acknowledge all of the current interrupt sources ASAP. */
 		/* Will change from 0xfc00 to 0xff00 when we start handling
 		   FCP and ER interrupts --Dragan */
-		outw(status & 0xfc00, ioaddr + SCBStatus);
+		iowrite16(status & 0xfc00, ioaddr + SCBStatus);
 
 		if (netif_msg_intr(sp))
 			printk(KERN_DEBUG "%s: interrupt  status=%#4.4x.\n",
@@ -1675,14 +1647,14 @@
 			/* Clear all interrupt sources. */
 			/* Will change from 0xfc00 to 0xff00 when we start handling
 			   FCP and ER interrupts --Dragan */
-			outw(0xfc00, ioaddr + SCBStatus);
+			iowrite16(0xfc00, ioaddr + SCBStatus);
 			break;
 		}
 	} while (1);
 
 	if (netif_msg_intr(sp))
 		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
-			   dev->name, inw(ioaddr + SCBStatus));
+			   dev->name, ioread16(ioaddr + SCBStatus));
 
 	clear_bit(0, (void*)&sp->in_interrupt);
 	return IRQ_RETVAL(handled);
@@ -1901,8 +1873,8 @@
 static int
 speedo_close(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
 	struct speedo_private *sp = netdev_priv(dev);
+	void __iomem *ioaddr = sp->regs;
 	int i;
 
 	netdevice_stop(dev);
@@ -1910,16 +1882,16 @@
 
 	if (netif_msg_ifdown(sp))
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
-			   dev->name, inw(ioaddr + SCBStatus));
+			   dev->name, ioread16(ioaddr + SCBStatus));
 
 	/* Shut off the media monitoring timer. */
 	del_timer_sync(&sp->timer);
 
-	outw(SCBMaskAll, ioaddr + SCBCmd);
+	iowrite16(SCBMaskAll, ioaddr + SCBCmd);
 
 	/* Shutting down the chip nicely fails to disable flow control. So.. */
-	outl(PortPartialReset, ioaddr + SCBPort);
-	inl(ioaddr + SCBPort); /* flush posted write */
+	iowrite32(PortPartialReset, ioaddr + SCBPort);
+	ioread32(ioaddr + SCBPort); /* flush posted write */
 	/*
 	 * The chip requires a 10 microsecond quiet period.  Wait here!
 	 */
@@ -1981,7 +1953,7 @@
 speedo_get_stats(struct net_device *dev)
 {
 	struct speedo_private *sp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = sp->regs;
 
 	/* Update only if the previous dump finished. */
 	if (sp->lstats->done_marker == le32_to_cpu(0xA007)) {
@@ -2002,90 +1974,76 @@
 			/* Take a spinlock to make wait_for_cmd_done and sending the
 			   command atomic.  --SAW */
 			spin_lock_irqsave(&sp->lock, flags);
-			wait_for_cmd_done(dev);
-			outb(CUDumpStats, ioaddr + SCBCmd);
+			wait_for_cmd_done(dev, sp);
+			iowrite8(CUDumpStats, ioaddr + SCBCmd);
 			spin_unlock_irqrestore(&sp->lock, flags);
 		}
 	}
 	return &sp->stats;
 }
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void speedo_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	u32 ethcmd;
 	struct speedo_private *sp = netdev_priv(dev);
-		
-	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
-		return -EFAULT;
-	
-        switch (ethcmd) {
-	/* get driver-specific version/etc. info */
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-		strncpy(info.driver, "eepro100", sizeof(info.driver)-1);
-		strncpy(info.version, version, sizeof(info.version)-1);
-		if (sp && sp->pdev)
-			strcpy(info.bus_info, pci_name(sp->pdev));
-		if (copy_to_user(useraddr, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	
-	/* get settings */
-	case ETHTOOL_GSET: {
-		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-		spin_lock_irq(&sp->lock);
-		mii_ethtool_gset(&sp->mii_if, &ecmd);
-		spin_unlock_irq(&sp->lock);
-		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set settings */
-	case ETHTOOL_SSET: {
-		int r;
-		struct ethtool_cmd ecmd;
-		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-			return -EFAULT;
-		spin_lock_irq(&sp->lock);
-		r = mii_ethtool_sset(&sp->mii_if, &ecmd);
-		spin_unlock_irq(&sp->lock);
-		return r;
-	}
-	/* restart autonegotiation */
-	case ETHTOOL_NWAY_RST: {
-		return mii_nway_restart(&sp->mii_if);
-	}
-	/* get link status */
-	case ETHTOOL_GLINK: {
-		struct ethtool_value edata = {ETHTOOL_GLINK};
-		edata.data = mii_link_ok(&sp->mii_if);
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	/* get message-level */
-	case ETHTOOL_GMSGLVL: {
-		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
-		edata.data = sp->msg_enable;
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set message-level */
-	case ETHTOOL_SMSGLVL: {
-		struct ethtool_value edata;
-		if (copy_from_user(&edata, useraddr, sizeof(edata)))
-			return -EFAULT;
-		sp->msg_enable = edata.data;
-		return 0;
-	}
+	strncpy(info->driver, "eepro100", sizeof(info->driver)-1);
+	strncpy(info->version, version, sizeof(info->version)-1);
+	if (sp->pdev)
+		strcpy(info->bus_info, pci_name(sp->pdev));
+}
 
-        }
-	
-	return -EOPNOTSUPP;
+static int speedo_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct speedo_private *sp = netdev_priv(dev);
+	spin_lock_irq(&sp->lock);
+	mii_ethtool_gset(&sp->mii_if, ecmd);
+	spin_unlock_irq(&sp->lock);
+	return 0;
+}
+
+static int speedo_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct speedo_private *sp = netdev_priv(dev);
+	int res;
+	spin_lock_irq(&sp->lock);
+	res = mii_ethtool_sset(&sp->mii_if, ecmd);
+	spin_unlock_irq(&sp->lock);
+	return res;
+}
+
+static int speedo_nway_reset(struct net_device *dev)
+{
+	struct speedo_private *sp = netdev_priv(dev);
+	return mii_nway_restart(&sp->mii_if);
 }
 
+static u32 speedo_get_link(struct net_device *dev)
+{
+	struct speedo_private *sp = netdev_priv(dev);
+	return mii_link_ok(&sp->mii_if);
+}
+
+static u32 speedo_get_msglevel(struct net_device *dev)
+{
+	struct speedo_private *sp = netdev_priv(dev);
+	return sp->msg_enable;
+}
+
+static void speedo_set_msglevel(struct net_device *dev, u32 v)
+{
+	struct speedo_private *sp = netdev_priv(dev);
+	sp->msg_enable = v;
+}
+
+static struct ethtool_ops ethtool_ops = {
+	.get_drvinfo = speedo_get_drvinfo,
+	.get_settings = speedo_get_settings,
+	.set_settings = speedo_set_settings,
+	.nway_reset = speedo_nway_reset,
+	.get_link = speedo_get_link,
+	.get_msglevel = speedo_get_msglevel,
+	.set_msglevel = speedo_set_msglevel,
+};
+
 static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct speedo_private *sp = netdev_priv(dev);
@@ -2121,8 +2079,6 @@
 			add_timer(&sp->timer); /* may be set to the past  --SAW */
 		pci_set_power_state(sp->pdev, saved_acpi);
 		return 0;
-	case SIOCETHTOOL:
-		return netdev_ethtool_ioctl(dev, rq->ifr_data);
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -2140,7 +2096,7 @@
 static void set_rx_mode(struct net_device *dev)
 {
 	struct speedo_private *sp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = sp->regs;
 	struct descriptor *last_cmd;
 	char new_rx_mode;
 	unsigned long flags;
@@ -2195,9 +2151,9 @@
 			config_cmd_data[8] = 0;
 		}
 		/* Trigger the command unit resume. */
-		wait_for_cmd_done(dev);
+		wait_for_cmd_done(dev, sp);
 		clear_suspend(last_cmd);
-		outb(CUResume, ioaddr + SCBCmd);
+		iowrite8(CUResume, ioaddr + SCBCmd);
 		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
 			netif_stop_queue(dev);
 			sp->tx_full = 1;
@@ -2232,10 +2188,10 @@
 			*setup_params++ = *eaddrs++;
 		}
 
-		wait_for_cmd_done(dev);
+		wait_for_cmd_done(dev, sp);
 		clear_suspend(last_cmd);
 		/* Immediately trigger the command unit resume. */
-		outb(CUResume, ioaddr + SCBCmd);
+		iowrite8(CUResume, ioaddr + SCBCmd);
 
 		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
 			netif_stop_queue(dev);
@@ -2308,10 +2264,10 @@
 		pci_dma_sync_single_for_device(sp->pdev, mc_blk->frame_dma,
 									   mc_blk->len, PCI_DMA_TODEVICE);
 
-		wait_for_cmd_done(dev);
+		wait_for_cmd_done(dev, sp);
 		clear_suspend(last_cmd);
 		/* Immediately trigger the command unit resume. */
-		outb(CUResume, ioaddr + SCBCmd);
+		iowrite8(CUResume, ioaddr + SCBCmd);
 
 		if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
 			netif_stop_queue(dev);
@@ -2332,7 +2288,7 @@
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
 	struct speedo_private *sp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = sp->regs;
 
 	pci_save_state(pdev, sp->pm_state);
 
@@ -2342,7 +2298,7 @@
 	del_timer_sync(&sp->timer);
 
 	netif_device_detach(dev);
-	outl(PortPartialReset, ioaddr + SCBPort);
+	iowrite32(PortPartialReset, ioaddr + SCBPort);
 	
 	/* XXX call pci_set_power_state ()? */
 	return 0;
@@ -2352,7 +2308,7 @@
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
 	struct speedo_private *sp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = sp->regs;
 
 	pci_restore_state(pdev, sp->pm_state);
 
@@ -2366,7 +2322,7 @@
 		  reinitialization;
 		- serialization with other driver calls.
 	   2000/03/08  SAW */
-	outw(SCBMaskAll, ioaddr + SCBCmd);
+	iowrite16(SCBMaskAll, ioaddr + SCBCmd);
 	speedo_resume(dev);
 	netif_device_attach(dev);
 	sp->rx_mode = -1;
@@ -2388,10 +2344,7 @@
 	release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
 	release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
 
-#ifndef USE_IO
-	iounmap((char *)dev->base_addr);
-#endif
-
+	pci_iounmap(pdev, sp->regs);
 	pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
 								+ sizeof(struct speedo_stats),
 						sp->tx_ring, sp->tx_ring_dma);
diff -Nru a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
--- a/drivers/net/ewrk3.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/ewrk3.c	2004-10-10 22:15:16 -07:00
@@ -305,6 +305,8 @@
 static struct net_device_stats *ewrk3_get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct ethtool_ops ethtool_ops_203;
+static struct ethtool_ops ethtool_ops;
 
 /*
    ** Private functions
@@ -532,7 +534,7 @@
 		printk("      is in I/O only mode");
 	}
 
-	lp = (struct ewrk3_private *) dev->priv;
+	lp = netdev_priv(dev);
 	lp->shmem_base = mem_start;
 	lp->shmem_length = shmem_length;
 	lp->lemac = lemac;
@@ -610,6 +612,10 @@
 	dev->get_stats = ewrk3_get_stats;
 	dev->set_multicast_list = set_multicast_list;
 	dev->do_ioctl = ewrk3_ioctl;
+	if (lp->adapter_name[4] == '3')
+		SET_ETHTOOL_OPS(dev, &ethtool_ops_203);
+	else
+		SET_ETHTOOL_OPS(dev, &ethtool_ops);
 	dev->tx_timeout = ewrk3_timeout;
 	dev->watchdog_timeo = QUEUE_PKT_TIMEOUT;
 	
@@ -621,7 +627,7 @@
 
 static int ewrk3_open(struct net_device *dev)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+	struct ewrk3_private *lp = netdev_priv(dev);
 	u_long iobase = dev->base_addr;
 	int i, status = 0;
 	u_char icr, csr;
@@ -684,7 +690,7 @@
  */
 static void ewrk3_init(struct net_device *dev)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+	struct ewrk3_private *lp = netdev_priv(dev);
 	u_char csr, page;
 	u_long iobase = dev->base_addr;
 	int i;
@@ -725,7 +731,7 @@
  
 static void ewrk3_timeout(struct net_device *dev)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+	struct ewrk3_private *lp = netdev_priv(dev);
 	u_char icr, csr;
 	u_long iobase = dev->base_addr;
 	
@@ -761,7 +767,7 @@
  */
 static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+	struct ewrk3_private *lp = netdev_priv(dev);
 	u_long iobase = dev->base_addr;
 	u_long buf = 0;
 	u_char icr;
@@ -883,7 +889,7 @@
 	u_long iobase;
 	u_char icr, cr, csr;
 
-	lp = (struct ewrk3_private *) dev->priv;
+	lp = netdev_priv(dev);
 	iobase = dev->base_addr;
 
 	/* get the interrupt information */
@@ -931,7 +937,7 @@
 /* Called with lp->hw_lock held */
 static int ewrk3_rx(struct net_device *dev)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+	struct ewrk3_private *lp = netdev_priv(dev);
 	u_long iobase = dev->base_addr;
 	int i, status = 0;
 	u_char page;
@@ -1059,7 +1065,7 @@
 */
 static int ewrk3_tx(struct net_device *dev)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+	struct ewrk3_private *lp = netdev_priv(dev);
 	u_long iobase = dev->base_addr;
 	u_char tx_status;
 
@@ -1095,7 +1101,7 @@
 
 static int ewrk3_close(struct net_device *dev)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+	struct ewrk3_private *lp = netdev_priv(dev);
 	u_long iobase = dev->base_addr;
 	u_char icr, csr;
 
@@ -1130,7 +1136,7 @@
 
 static struct net_device_stats *ewrk3_get_stats(struct net_device *dev)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+	struct ewrk3_private *lp = netdev_priv(dev);
 
 	/* Null body since there is no framing error counter */
 	return &lp->stats;
@@ -1141,7 +1147,7 @@
  */
 static void set_multicast_list(struct net_device *dev)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+	struct ewrk3_private *lp = netdev_priv(dev);
 	u_long iobase = dev->base_addr;
 	u_char csr;
 
@@ -1174,7 +1180,7 @@
  */
 static void SetMulticastFilter(struct net_device *dev)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+	struct ewrk3_private *lp = netdev_priv(dev);
 	struct dev_mc_list *dmi = dev->mc_list;
 	u_long iobase = dev->base_addr;
 	int i;
@@ -1520,187 +1526,165 @@
 	return status;		/* return the device name string */
 }
 
-static int ewrk3_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void ewrk3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
-	u_long iobase = dev->base_addr;
-	u32 ethcmd;
-
-	if (get_user(ethcmd, (u32 __user *)useraddr))
-		return -EFAULT;
+	int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL);
 
-	switch (ethcmd) {
-
-	/* Get driver info */
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-		int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL);
-
-		strcpy(info.driver, DRV_NAME);
-		strcpy(info.version, DRV_VERSION);
-		sprintf(info.fw_version, "%d", fwrev);
-		strcpy(info.bus_info, "N/A");
-		info.eedump_len = EEPROM_MAX;
-		if (copy_to_user(useraddr, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-
-	/* Get settings */
-	case ETHTOOL_GSET: {
-		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-		u_char cr = inb(EWRK3_CR);
-
-		switch (lp->adapter_name[4]) {
-		case '3': /* DE203 */
-			ecmd.supported = SUPPORTED_BNC;
-			ecmd.port = PORT_BNC;
-			break;
-
-		case '4': /* DE204 */
-			ecmd.supported = SUPPORTED_TP;
-			ecmd.port = PORT_TP;
-			break;
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	sprintf(info->fw_version, "%d", fwrev);
+	strcpy(info->bus_info, "N/A");
+	info->eedump_len = EEPROM_MAX;
+}
 
-		case '5': /* DE205 */
-			ecmd.supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI;
-			ecmd.autoneg = !(cr & CR_APD);
-			/*
-			** Port is only valid if autoneg is disabled
-			** and even then we don't know if AUI is jumpered.
-			*/
-			if (!ecmd.autoneg)
-				ecmd.port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP;
-			break;
-		}
+static int ewrk3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct ewrk3_private *lp = netdev_priv(dev);
+	unsigned long iobase = dev->base_addr;
+	u8 cr = inb(EWRK3_CR);
 
-		ecmd.supported |= SUPPORTED_10baseT_Half;
-		ecmd.speed = SPEED_10;
-		ecmd.duplex = DUPLEX_HALF;
-
-		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-	}
-
-	/* Set settings */
-	case ETHTOOL_SSET: {
-		struct ethtool_cmd ecmd;
-		u_char cr;
-		u_long flags;
-
-		/* DE205 is the only card with anything to set */
-		if (lp->adapter_name[4] != '5')
-			return -EOPNOTSUPP;
-
-		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-			return -EFAULT;
-
-		/* Sanity-check parameters */
-		if (ecmd.speed != SPEED_10)
-			return -EINVAL;
-		if (ecmd.port != PORT_TP && ecmd.port != PORT_BNC)
-			return -EINVAL; /* AUI is not software-selectable */
-		if (ecmd.transceiver != XCVR_INTERNAL)
-			return -EINVAL;
-		if (ecmd.duplex != DUPLEX_HALF)
-			return -EINVAL;
-		if (ecmd.phy_address != 0)
-			return -EINVAL;
+	switch (lp->adapter_name[4]) {
+	case '3': /* DE203 */
+		ecmd->supported = SUPPORTED_BNC;
+		ecmd->port = PORT_BNC;
+		break;
 
-		spin_lock_irqsave(&lp->hw_lock, flags);
-		cr = inb(EWRK3_CR);
+	case '4': /* DE204 */
+		ecmd->supported = SUPPORTED_TP;
+		ecmd->port = PORT_TP;
+		break;
 
-		/* If Autoneg is set, change to Auto Port mode */
-		/* Otherwise, disable Auto Port and set port explicitly */
-		if (ecmd.autoneg) {
-			cr &= ~CR_APD;
-		} else {
-			cr |= CR_APD;
-			if (ecmd.port == PORT_TP)
-				cr &= ~CR_PSEL;		/* Force TP */
-			else
-				cr |= CR_PSEL;		/* Force BNC */
-		}
+	case '5': /* DE205 */
+		ecmd->supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI;
+		ecmd->autoneg = !(cr & CR_APD);
+		/*
+		** Port is only valid if autoneg is disabled
+		** and even then we don't know if AUI is jumpered.
+		*/
+		if (!ecmd->autoneg)
+			ecmd->port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP;
+		break;
+	}
 
-		/* Commit the changes */
-		outb(cr, EWRK3_CR);
+	ecmd->supported |= SUPPORTED_10baseT_Half;
+	ecmd->speed = SPEED_10;
+	ecmd->duplex = DUPLEX_HALF;
+	return 0;
+}
 
-		spin_unlock_irqrestore(&lp->hw_lock, flags);
-		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-	}
+static int ewrk3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct ewrk3_private *lp = netdev_priv(dev);
+	unsigned long iobase = dev->base_addr;
+	unsigned long flags;
+	u8 cr;
 
-	/* Get link status */
-	case ETHTOOL_GLINK: {
-		struct ethtool_value edata = { ETHTOOL_GLINK };
-		u_char cmr = inb(EWRK3_CMR);
+	/* DE205 is the only card with anything to set */
+	if (lp->adapter_name[4] != '5')
+		return -EOPNOTSUPP;
 
-		/* DE203 has BNC only and link status does not apply */
-		if (lp->adapter_name[4] == '3')
-			return -EOPNOTSUPP;
+	/* Sanity-check parameters */
+	if (ecmd->speed != SPEED_10)
+		return -EINVAL;
+	if (ecmd->port != PORT_TP && ecmd->port != PORT_BNC)
+		return -EINVAL; /* AUI is not software-selectable */
+	if (ecmd->transceiver != XCVR_INTERNAL)
+		return -EINVAL;
+	if (ecmd->duplex != DUPLEX_HALF)
+		return -EINVAL;
+	if (ecmd->phy_address != 0)
+		return -EINVAL;
 
-		/* On DE204 this is always valid since TP is the only port. */
-		/* On DE205 this reflects TP status even if BNC or AUI is selected. */
-		edata.data = !(cmr & CMR_LINK);
+	spin_lock_irqsave(&lp->hw_lock, flags);
+	cr = inb(EWRK3_CR);
 
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
+	/* If Autoneg is set, change to Auto Port mode */
+	/* Otherwise, disable Auto Port and set port explicitly */
+	if (ecmd->autoneg) {
+		cr &= ~CR_APD;
+	} else {
+		cr |= CR_APD;
+		if (ecmd->port == PORT_TP)
+			cr &= ~CR_PSEL;		/* Force TP */
+		else
+			cr |= CR_PSEL;		/* Force BNC */
 	}
 
-	/* Blink LED for identification */
-	case ETHTOOL_PHYS_ID: {
-		struct ethtool_value edata;
-		u_long flags;
-		u_char cr;
-		int count;
+	/* Commit the changes */
+	outb(cr, EWRK3_CR);
+	spin_unlock_irqrestore(&lp->hw_lock, flags);
+	return 0;
+}
 
-		if (copy_from_user(&edata, useraddr, sizeof(edata)))
-			return -EFAULT;
+static u32 ewrk3_get_link(struct net_device *dev)
+{
+	unsigned long iobase = dev->base_addr;
+	u8 cmr = inb(EWRK3_CMR);
+	/* DE203 has BNC only and link status does not apply */
+	/* On DE204 this is always valid since TP is the only port. */
+	/* On DE205 this reflects TP status even if BNC or AUI is selected. */
+	return !(cmr & CMR_LINK);
+}
 
-		/* Toggle LED 4x per second */
-		count = edata.data << 2;
+static int ewrk3_phys_id(struct net_device *dev, u32 data)
+{
+	struct ewrk3_private *lp = netdev_priv(dev);
+	unsigned long iobase = dev->base_addr;
+	unsigned long flags;
+	u8 cr;
+	int count;
 
-		spin_lock_irqsave(&lp->hw_lock, flags);
+	/* Toggle LED 4x per second */
+	count = data << 2;
 
-		/* Bail if a PHYS_ID is already in progress */
-		if (lp->led_mask == 0) {
-			spin_unlock_irqrestore(&lp->hw_lock, flags);
-			return -EBUSY;
-		}
+	spin_lock_irqsave(&lp->hw_lock, flags);
 
-		/* Prevent ISR from twiddling the LED */
-		lp->led_mask = 0;
+	/* Bail if a PHYS_ID is already in progress */
+	if (lp->led_mask == 0) {
+		spin_unlock_irqrestore(&lp->hw_lock, flags);
+		return -EBUSY;
+	}
 
-		while (count--) {
-			/* Toggle the LED */
-			cr = inb(EWRK3_CR);
-			outb(cr ^ CR_LED, EWRK3_CR);
-
-			/* Wait a little while */
-			spin_unlock_irqrestore(&lp->hw_lock, flags);
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ>>2);
-			spin_lock_irqsave(&lp->hw_lock, flags);
-
-			/* Exit if we got a signal */
-			if (signal_pending(current))
-				break;
-		}
+	/* Prevent ISR from twiddling the LED */
+	lp->led_mask = 0;
 
-		lp->led_mask = CR_LED;
+	while (count--) {
+		/* Toggle the LED */
 		cr = inb(EWRK3_CR);
-		outb(cr & ~CR_LED, EWRK3_CR);
+		outb(cr ^ CR_LED, EWRK3_CR);
+
+		/* Wait a little while */
 		spin_unlock_irqrestore(&lp->hw_lock, flags);
-		return signal_pending(current) ? -ERESTARTSYS : 0;
-	}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ>>2);
+		spin_lock_irqsave(&lp->hw_lock, flags);
 
+		/* Exit if we got a signal */
+		if (signal_pending(current))
+			break;
 	}
 
-	return -EOPNOTSUPP;
-}
+	lp->led_mask = CR_LED;
+	cr = inb(EWRK3_CR);
+	outb(cr & ~CR_LED, EWRK3_CR);
+	spin_unlock_irqrestore(&lp->hw_lock, flags);
+	return signal_pending(current) ? -ERESTARTSYS : 0;
+}
+
+static struct ethtool_ops ethtool_ops_203 = {
+	.get_drvinfo = ewrk3_get_drvinfo,
+	.get_settings = ewrk3_get_settings,
+	.set_settings = ewrk3_set_settings,
+	.phys_id = ewrk3_phys_id,
+};
+
+static struct ethtool_ops ethtool_ops = {
+	.get_drvinfo = ewrk3_get_drvinfo,
+	.get_settings = ewrk3_get_settings,
+	.set_settings = ewrk3_set_settings,
+	.get_link = ewrk3_get_link,
+	.phys_id = ewrk3_phys_id,
+};
 
 /*
    ** Perform IOCTL call functions here. Some are privileged operations and the
@@ -1708,7 +1692,7 @@
  */
 static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+	struct ewrk3_private *lp = netdev_priv(dev);
 	struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_ifru;
 	u_long iobase = dev->base_addr;
 	int i, j, status = 0;
@@ -1721,11 +1705,7 @@
 	
 	union ewrk3_addr *tmp;
 
-	/* ethtool IOCTLs are handled elsewhere */
-	if (cmd == SIOCETHTOOL)
-		return ewrk3_ethtool_ioctl(dev, rq->ifr_data);
-
-	/* Other than ethtool, all we handle are private IOCTLs */
+	/* All we handle are private IOCTLs */
 	if (cmd != EWRK3IOCTL)
 		return -EOPNOTSUPP;
 
diff -Nru a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
--- a/drivers/net/forcedeth.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/forcedeth.c	2004-10-10 22:15:16 -07:00
@@ -76,6 +76,9 @@
  *			   for registers, link status and other minor fixes.
  *	0.28: 21 Jun 2004: Big cleanup, making driver mostly endian safe
  *	0.29: 31 Aug 2004: Add backup timer for link change notification.
+ *	0.30: 25 Sep 2004: rx checksum support for nf 250 Gb. Add rx reset
+ *			   into nv_close, otherwise reenabling for wol can
+ *			   cause DMA to kfree'd memory.
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
@@ -87,7 +90,7 @@
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION		"0.29"
+#define FORCEDETH_VERSION		"0.30"
 #define DRV_NAME			"forcedeth"
 
 #include <linux/module.h>
@@ -217,6 +220,7 @@
 #define NVREG_TXRXCTL_BIT2	0x0004
 #define NVREG_TXRXCTL_IDLE	0x0008
 #define NVREG_TXRXCTL_RESET	0x0010
+#define NVREG_TXRXCTL_RXCHECK	0x0400
 	NvRegMIIStatus = 0x180,
 #define NVREG_MIISTAT_ERROR		0x0001
 #define NVREG_MIISTAT_LINKCHANGE	0x0008
@@ -313,6 +317,10 @@
 #define NV_RX_ERROR		(1<<30)
 #define NV_RX_AVAIL		(1<<31)
 
+#define NV_RX2_CHECKSUMMASK	(0x1C000000)
+#define NV_RX2_CHECKSUMOK1	(0x10000000)
+#define NV_RX2_CHECKSUMOK2	(0x14000000)
+#define NV_RX2_CHECKSUMOK3	(0x18000000)
 #define NV_RX2_DESCRIPTORVALID	(1<<29)
 #define NV_RX2_SUBSTRACT1	(1<<25)
 #define NV_RX2_ERROR1		(1<<18)
@@ -371,8 +379,15 @@
 #define POLL_WAIT	(1+HZ/100)
 #define LINK_TIMEOUT	(3*HZ)
 
+/* 
+ * desc_ver values:
+ * This field has two purposes:
+ * - Newer nics uses a different ring layout. The layout is selected by
+ *   comparing np->desc_ver with DESC_VER_xy.
+ * - It contains bits that are forced on when writing to NvRegTxRxControl.
+ */
 #define DESC_VER_1	0x0
-#define DESC_VER_2	0x02100
+#define DESC_VER_2	(0x02100|NVREG_TXRXCTL_RXCHECK)
 
 /* PHY defines */
 #define PHY_OUI_MARVELL	0x5043
@@ -748,91 +763,50 @@
 	return &np->stats;
 }
 
-static int nv_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 	struct fe_priv *np = get_nvpriv(dev);
-	u8 *base = get_hwbase(dev);
-	u32 ethcmd;
-
-	if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
-		return -EFAULT;
-
-	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO:
-	{
-		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-		strcpy(info.driver, "forcedeth");
-		strcpy(info.version, FORCEDETH_VERSION);
-		strcpy(info.bus_info, pci_name(np->pci_dev));
-		if (copy_to_user(useraddr, &info, sizeof (info)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_GLINK:
-	{
-		struct ethtool_value edata = { ETHTOOL_GLINK };
-
-		edata.data = !!netif_carrier_ok(dev);
-
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_GWOL:
-	{
-		struct ethtool_wolinfo wolinfo;
-		memset(&wolinfo, 0, sizeof(wolinfo));
-		wolinfo.supported = WAKE_MAGIC;
-
-		spin_lock_irq(&np->lock);
-		if (np->wolenabled)
-			wolinfo.wolopts = WAKE_MAGIC;
-		spin_unlock_irq(&np->lock);
-
-		if (copy_to_user(useraddr, &wolinfo, sizeof(wolinfo)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_SWOL:
-	{
-		struct ethtool_wolinfo wolinfo;
-		if (copy_from_user(&wolinfo, useraddr, sizeof(wolinfo)))
-			return -EFAULT;
-
-		spin_lock_irq(&np->lock);
-		if (wolinfo.wolopts == 0) {
-			writel(0, base + NvRegWakeUpFlags);
-			np->wolenabled = 0;
-		}
-		if (wolinfo.wolopts & WAKE_MAGIC) {
-			writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags);
-			np->wolenabled = 1;
-		}
-		spin_unlock_irq(&np->lock);
-		return 0;
-	}
+	strcpy(info->driver, "forcedeth");
+	strcpy(info->version, FORCEDETH_VERSION);
+	strcpy(info->bus_info, pci_name(np->pci_dev));
+}
 
-	default:
-		break;
-	}
+static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	wolinfo->supported = WAKE_MAGIC;
 
-	return -EOPNOTSUPP;
+	spin_lock_irq(&np->lock);
+	if (np->wolenabled)
+		wolinfo->wolopts = WAKE_MAGIC;
+	spin_unlock_irq(&np->lock);
 }
-/*
- * nv_ioctl: dev->do_ioctl function
- * Called with rtnl_lock held.
- */
-static int nv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+
+static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
 {
-	switch(cmd) {
-	case SIOCETHTOOL:
-		return nv_ethtool_ioctl(dev, rq->ifr_data);
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 *base = get_hwbase(dev);
 
-	default:
-		return -EOPNOTSUPP;
+	spin_lock_irq(&np->lock);
+	if (wolinfo->wolopts == 0) {
+		writel(0, base + NvRegWakeUpFlags);
+		np->wolenabled = 0;
+	}
+	if (wolinfo->wolopts & WAKE_MAGIC) {
+		writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags);
+		np->wolenabled = 1;
 	}
+	spin_unlock_irq(&np->lock);
+	return 0;
 }
 
+static struct ethtool_ops ops = {
+	.get_drvinfo = nv_get_drvinfo,
+	.get_link = ethtool_op_get_link,
+	.get_wol = nv_get_wol,
+	.set_wol = nv_set_wol,
+};
+
 /*
  * nv_alloc_rx: fill rx ring entries.
  * Return 1 if the allocations for the skbs failed and the
@@ -1181,6 +1155,15 @@
 					goto next_pkt;
 				}
 			}
+			Flags &= NV_RX2_CHECKSUMMASK;
+			if (Flags == NV_RX2_CHECKSUMOK1 ||
+					Flags == NV_RX2_CHECKSUMOK2 ||
+					Flags == NV_RX2_CHECKSUMOK3) {
+				dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name);
+				np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY;
+			} else {
+				dprintk(KERN_DEBUG "%s: hwchecksum miss!.\n", dev->name);
+			}
 		}
 		/* got a valid packet - forward it to the network core */
 		skb = np->rx_skbuff[i];
@@ -1673,9 +1656,10 @@
 	spin_lock_irq(&np->lock);
 	nv_stop_tx(dev);
 	nv_stop_rx(dev);
-	base = get_hwbase(dev);
+	nv_txrx_reset(dev);
 
 	/* disable interrupts on the nic or we will lock up */
+	base = get_hwbase(dev);
 	writel(0, base + NvRegIrqMask);
 	pci_push(base);
 	dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name);
@@ -1777,7 +1761,7 @@
 	dev->get_stats = nv_get_stats;
 	dev->change_mtu = nv_change_mtu;
 	dev->set_multicast_list = nv_set_multicast;
-	dev->do_ioctl = nv_ioctl;
+	SET_ETHTOOL_OPS(dev, &ops);
 	dev->tx_timeout = nv_tx_timeout;
 	dev->watchdog_timeo = NV_WATCHDOG_TIMEO;
 
diff -Nru a/drivers/net/hamachi.c b/drivers/net/hamachi.c
--- a/drivers/net/hamachi.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/hamachi.c	2004-10-10 22:15:16 -07:00
@@ -565,7 +565,8 @@
 static int hamachi_close(struct net_device *dev);
 static struct net_device_stats *hamachi_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
-
+static struct ethtool_ops ethtool_ops;
+static struct ethtool_ops ethtool_ops_no_mii;
 
 static int __devinit hamachi_init_one (struct pci_dev *pdev,
 				    const struct pci_device_id *ent)
@@ -631,7 +632,7 @@
 				   read_eeprom(ioaddr, i), i % 16 != 15 ? " " : "\n");
 #endif
 
-	hmp = dev->priv;
+	hmp = netdev_priv(dev);
 	spin_lock_init(&hmp->lock);
 
 	hmp->mii_if.dev = dev;
@@ -725,6 +726,10 @@
 	dev->get_stats = &hamachi_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &netdev_ioctl;
+	if (chip_tbl[hmp->chip_id].flags & CanHaveMII)
+		SET_ETHTOOL_OPS(dev, &ethtool_ops);
+	else
+		SET_ETHTOOL_OPS(dev, &ethtool_ops_no_mii);
 	dev->tx_timeout = &hamachi_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	if (mtu)
@@ -851,7 +856,7 @@
 
 static int hamachi_open(struct net_device *dev)
 {
-	struct hamachi_private *hmp = dev->priv;
+	struct hamachi_private *hmp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int i;
 	u32 rx_int_var, tx_int_var;
@@ -1000,7 +1005,7 @@
 
 static inline int hamachi_tx(struct net_device *dev)
 {
-	struct hamachi_private *hmp = dev->priv;
+	struct hamachi_private *hmp = netdev_priv(dev);
 
 	/* Update the dirty pointer until we find an entry that is
 		still owned by the card */
@@ -1032,7 +1037,7 @@
 static void hamachi_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
-	struct hamachi_private *hmp = dev->priv;
+	struct hamachi_private *hmp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int next_tick = 10*HZ;
 
@@ -1057,7 +1062,7 @@
 static void hamachi_tx_timeout(struct net_device *dev)
 {
 	int i;
-	struct hamachi_private *hmp = dev->priv;
+	struct hamachi_private *hmp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 
 	printk(KERN_WARNING "%s: Hamachi transmit timed out, status %8.8x,"
@@ -1163,7 +1168,7 @@
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void hamachi_init_ring(struct net_device *dev)
 {
-	struct hamachi_private *hmp = dev->priv;
+	struct hamachi_private *hmp = netdev_priv(dev);
 	int i;
 
 	hmp->tx_full = 0;
@@ -1255,7 +1260,7 @@
 
 static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct hamachi_private *hmp = dev->priv;
+	struct hamachi_private *hmp = netdev_priv(dev);
 	unsigned entry;
 	u16 status;
 
@@ -1383,7 +1388,7 @@
 #endif
 
 	ioaddr = dev->base_addr;
-	hmp = dev->priv;
+	hmp = netdev_priv(dev);
 	spin_lock(&hmp->lock);
 
 	do {
@@ -1477,7 +1482,7 @@
    for clarity and better register allocation. */
 static int hamachi_rx(struct net_device *dev)
 {
-	struct hamachi_private *hmp = dev->priv;
+	struct hamachi_private *hmp = netdev_priv(dev);
 	int entry = hmp->cur_rx % RX_RING_SIZE;
 	int boguscnt = (hmp->dirty_rx + RX_RING_SIZE) - hmp->cur_rx;
 
@@ -1693,7 +1698,7 @@
 static void hamachi_error(struct net_device *dev, int intr_status)
 {
 	long ioaddr = dev->base_addr;
-	struct hamachi_private *hmp = dev->priv;
+	struct hamachi_private *hmp = netdev_priv(dev);
 
 	if (intr_status & (LinkChange|NegotiationChange)) {
 		if (hamachi_debug > 1)
@@ -1727,7 +1732,7 @@
 static int hamachi_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct hamachi_private *hmp = dev->priv;
+	struct hamachi_private *hmp = netdev_priv(dev);
 	struct sk_buff *skb;
 	int i;
 
@@ -1813,7 +1818,7 @@
 static struct net_device_stats *hamachi_get_stats(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct hamachi_private *hmp = dev->priv;
+	struct hamachi_private *hmp = netdev_priv(dev);
 
 	/* We should lock this segment of code for SMP eventually, although
 	   the vulnerability window is very small and statistics are
@@ -1867,84 +1872,76 @@
 	}
 }
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static int check_if_running(struct net_device *dev)
 {
-	struct hamachi_private *np = dev->priv;
-	u32 ethcmd;
-		
-	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
-		return -EFAULT;
+	if (!netif_running(dev))
+		return -EINVAL;
+	return 0;
+}
 
-        switch (ethcmd) {
-        case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-		strcpy(info.driver, DRV_NAME);
-		strcpy(info.version, DRV_VERSION);
-		strcpy(info.bus_info, pci_name(np->pci_dev));
-		if (copy_to_user(useraddr, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-
-	/* get settings */
-	case ETHTOOL_GSET: {
-		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-		if (!(chip_tbl[np->chip_id].flags & CanHaveMII))
-			return -EINVAL;
-		spin_lock_irq(&np->lock);
-		mii_ethtool_gset(&np->mii_if, &ecmd);
-		spin_unlock_irq(&np->lock);
-		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set settings */
-	case ETHTOOL_SSET: {
-		int r;
-		struct ethtool_cmd ecmd;
-		if (!(chip_tbl[np->chip_id].flags & CanHaveMII))
-			return -EINVAL;
-		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-			return -EFAULT;
-		spin_lock_irq(&np->lock);
-		r = mii_ethtool_sset(&np->mii_if, &ecmd);
-		spin_unlock_irq(&np->lock);
-		return r;
-	}
-	/* restart autonegotiation */
-	case ETHTOOL_NWAY_RST: {
-		if (!(chip_tbl[np->chip_id].flags & CanHaveMII))
-			return -EINVAL;
-		return mii_nway_restart(&np->mii_if);
-	}
-	/* get link status */
-	case ETHTOOL_GLINK: {
-		struct ethtool_value edata = {ETHTOOL_GLINK};
-		if (!(chip_tbl[np->chip_id].flags & CanHaveMII))
-			return -EINVAL;
-		edata.data = mii_link_ok(&np->mii_if);
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-        }
-	
-	return -EOPNOTSUPP;
+static void hamachi_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct hamachi_private *np = netdev_priv(dev);
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, pci_name(np->pci_dev));
 }
 
+static int hamachi_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct hamachi_private *np = netdev_priv(dev);
+	spin_lock_irq(&np->lock);
+	mii_ethtool_gset(&np->mii_if, ecmd);
+	spin_unlock_irq(&np->lock);
+	return 0;
+}
+
+static int hamachi_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct hamachi_private *np = netdev_priv(dev);
+	int res;
+	spin_lock_irq(&np->lock);
+	res = mii_ethtool_sset(&np->mii_if, ecmd);
+	spin_unlock_irq(&np->lock);
+	return res;
+}
+
+static int hamachi_nway_reset(struct net_device *dev)
+{
+	struct hamachi_private *np = netdev_priv(dev);
+	return mii_nway_restart(&np->mii_if);
+}
+
+static u32 hamachi_get_link(struct net_device *dev)
+{
+	struct hamachi_private *np = netdev_priv(dev);
+	return mii_link_ok(&np->mii_if);
+}
+
+static struct ethtool_ops ethtool_ops = {
+	.begin = check_if_running,
+	.get_drvinfo = hamachi_get_drvinfo,
+	.get_settings = hamachi_get_settings,
+	.set_settings = hamachi_set_settings,
+	.nway_reset = hamachi_nway_reset,
+	.get_link = hamachi_get_link,
+};
+
+static struct ethtool_ops ethtool_ops_no_mii = {
+	.begin = check_if_running,
+	.get_drvinfo = hamachi_get_drvinfo,
+};
+
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct hamachi_private *np = dev->priv;
+	struct hamachi_private *np = netdev_priv(dev);
 	struct mii_ioctl_data *data = if_mii(rq);
 	int rc;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	if (cmd == SIOCETHTOOL)
-		rc = netdev_ethtool_ioctl(dev, rq->ifr_data);
-
-	else if (cmd == (SIOCDEVPRIVATE+3)) { /* set rx,tx intr params */
+	if (cmd == (SIOCDEVPRIVATE+3)) { /* set rx,tx intr params */
 		u32 *d = (u32 *)&rq->ifr_ifru;
 		/* Should add this check here or an ordinary user can do nasty
 		 * things. -KDU
@@ -1976,7 +1973,7 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 
 	if (dev) {
-		struct hamachi_private *hmp = dev->priv;
+		struct hamachi_private *hmp = netdev_priv(dev);
 
 		pci_free_consistent(pdev, RX_TOTAL_SIZE, hmp->rx_ring, 
 			hmp->rx_ring_dma);
diff -Nru a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
--- a/drivers/net/hamradio/hdlcdrv.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/hamradio/hdlcdrv.c	2004-10-10 22:15:16 -07:00
@@ -549,6 +549,8 @@
 
 	netif_stop_queue(dev);
 
+	netif_stop_queue(dev);
+
 	if (s->ops && s->ops->close)
 		i = s->ops->close(dev);
 	if (s->skb)
diff -Nru a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
--- a/drivers/net/ibmlana.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/ibmlana.c	2004-10-10 22:15:16 -07:00
@@ -885,14 +885,6 @@
 	return &priv->stat;
 }
 
-/* we don't support runtime reconfiguration, since am MCA card can
-   be unambigously identified by its POS registers. */
-
-static int ibmlana_config(struct net_device *dev, struct ifmap *map)
-{
-	return 0;
-}
-
 /* switch receiver mode. */
 
 static void ibmlana_set_multicast_list(struct net_device *dev)
@@ -984,7 +976,6 @@
 
 	dev->open = ibmlana_open;
 	dev->stop = ibmlana_close;
-	dev->set_config = ibmlana_config;
 	dev->hard_start_xmit = ibmlana_tx;
 	dev->do_ioctl = NULL;
 	dev->get_stats = ibmlana_stats;
diff -Nru a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
--- a/drivers/net/iseries_veth.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/iseries_veth.c	2004-10-10 22:15:16 -07:00
@@ -747,60 +747,41 @@
 	write_unlock_irqrestore(&port->mcast_gate, flags);
 }
 
-static int veth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-#ifdef SIOCETHTOOL
-	struct ethtool_cmd ecmd;
-
-	if (cmd != SIOCETHTOOL)
-		return -EOPNOTSUPP;
-	if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd)))
-		return -EFAULT;
-	switch (ecmd.cmd) {
-	case ETHTOOL_GSET:
-		ecmd.supported = (SUPPORTED_1000baseT_Full
-				  | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
-		ecmd.advertising = (SUPPORTED_1000baseT_Full
-				    | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
-
-		ecmd.port = PORT_FIBRE;
-		ecmd.transceiver = XCVR_INTERNAL;
-		ecmd.phy_address = 0;
-		ecmd.speed = SPEED_1000;
-		ecmd.duplex = DUPLEX_FULL;
-		ecmd.autoneg = AUTONEG_ENABLE;
-		ecmd.maxtxpkt = 120;
-		ecmd.maxrxpkt = 120;
-		if (copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-
-	case ETHTOOL_GDRVINFO:{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strncpy(info.driver, "veth", sizeof(info.driver) - 1);
-			info.driver[sizeof(info.driver) - 1] = '\0';
-			strncpy(info.version, "1.0", sizeof(info.version) - 1);
-			if (copy_to_user(ifr->ifr_data, &info, sizeof(info)))
-				return -EFAULT;
-			return 0;
-		}
-		/* get link status */
-	case ETHTOOL_GLINK:{
-			struct ethtool_value edata = { ETHTOOL_GLINK };
-			edata.data = 1;
-			if (copy_to_user(ifr->ifr_data, &edata, sizeof(edata)))
-				return -EFAULT;
-			return 0;
-		}
+	strncpy(info->driver, "veth", sizeof(info->driver) - 1);
+	info->driver[sizeof(info->driver) - 1] = '\0';
+	strncpy(info->version, "1.0", sizeof(info->version) - 1);
+}
 
-	default:
-		break;
-	}
+static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	ecmd->supported = (SUPPORTED_1000baseT_Full
+			  | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
+	ecmd->advertising = (SUPPORTED_1000baseT_Full
+			    | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
+	ecmd->port = PORT_FIBRE;
+	ecmd->transceiver = XCVR_INTERNAL;
+	ecmd->phy_address = 0;
+	ecmd->speed = SPEED_1000;
+	ecmd->duplex = DUPLEX_FULL;
+	ecmd->autoneg = AUTONEG_ENABLE;
+	ecmd->maxtxpkt = 120;
+	ecmd->maxrxpkt = 120;
+	return 0;
+}
 
-#endif
-	return -EOPNOTSUPP;
+static u32 veth_get_link(struct net_device *dev)
+{
+	return 1;
 }
 
+static struct ethtool_ops ops = {
+	.get_drvinfo = veth_get_drvinfo,
+	.get_settings = veth_get_settings,
+	.get_link = veth_get_link,
+};
+
 static void veth_tx_timeout(struct net_device *dev)
 {
 	struct veth_port *port = (struct veth_port *)dev->priv;
@@ -889,7 +870,7 @@
 	dev->change_mtu = veth_change_mtu;
 	dev->set_mac_address = NULL;
 	dev->set_multicast_list = veth_set_multicast_list;
-	dev->do_ioctl = veth_ioctl;
+	SET_ETHTOOL_OPS(dev, &ops);
 
 	dev->watchdog_timeo = 2 * (VETH_ACKTIMEOUT * HZ / 1000000);
 	dev->tx_timeout = veth_tx_timeout;
diff -Nru a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
--- a/drivers/net/ixgb/ixgb_ethtool.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/ixgb/ixgb_ethtool.c	2004-10-10 22:15:16 -07:00
@@ -38,12 +38,6 @@
 extern int ixgb_up(struct ixgb_adapter *adapter);
 extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
 
-static inline int ixgb_eeprom_size(struct ixgb_hw *hw)
-{
-	/* return size in bytes */
-	return (IXGB_EEPROM_SIZE << 1);
-}
-
 struct ixgb_stats {
 	char stat_string[ETH_GSTRING_LEN];
 	int sizeof_stat;
@@ -94,9 +88,10 @@
 #define IXGB_STATS_LEN	\
 	sizeof(ixgb_gstrings_stats) / sizeof(struct ixgb_stats)
 
-static void
-ixgb_ethtool_gset(struct ixgb_adapter *adapter, struct ethtool_cmd *ecmd)
+static int
+ixgb_ethtool_gset(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
+	struct ixgb_adapter *adapter = netdev->priv;
 	ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
 	ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
 	ecmd->port = PORT_FIBRE;
@@ -111,11 +106,13 @@
 	}
 
 	ecmd->autoneg = AUTONEG_DISABLE;
+	return 0;
 }
 
 static int
-ixgb_ethtool_sset(struct ixgb_adapter *adapter, struct ethtool_cmd *ecmd)
+ixgb_ethtool_sset(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
+	struct ixgb_adapter *adapter = netdev->priv;
 	if (ecmd->autoneg == AUTONEG_ENABLE ||
 	    ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
 		return -EINVAL;
@@ -123,14 +120,14 @@
 		ixgb_down(adapter, TRUE);
 		ixgb_up(adapter);
 	}
-
 	return 0;
 }
 
-static int
-ixgb_ethtool_gpause(struct ixgb_adapter *adapter,
+static void
+ixgb_ethtool_gpause(struct net_device *dev,
 		    struct ethtool_pauseparam *epause)
 {
+	struct ixgb_adapter *adapter = dev->priv;
 	struct ixgb_hw *hw = &adapter->hw;
 
 	epause->autoneg = AUTONEG_DISABLE;
@@ -143,14 +140,13 @@
 		epause->rx_pause = 1;
 		epause->tx_pause = 1;
 	}
-
-	return 0;
 }
 
 static int
-ixgb_ethtool_spause(struct ixgb_adapter *adapter,
+ixgb_ethtool_spause(struct net_device *dev,
 		    struct ethtool_pauseparam *epause)
 {
+	struct ixgb_adapter *adapter = dev->priv;
 	struct ixgb_hw *hw = &adapter->hw;
 
 	if (epause->autoneg == AUTONEG_ENABLE)
@@ -172,26 +168,23 @@
 }
 
 static void
-ixgb_ethtool_gdrvinfo(struct ixgb_adapter *adapter,
+ixgb_ethtool_gdrvinfo(struct net_device *netdev,
 		      struct ethtool_drvinfo *drvinfo)
 {
+	struct ixgb_adapter *adapter = netdev->priv;
 	strncpy(drvinfo->driver, ixgb_driver_name, 32);
 	strncpy(drvinfo->version, ixgb_driver_version, 32);
 	strncpy(drvinfo->fw_version, "N/A", 32);
 	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
-	drvinfo->n_stats = IXGB_STATS_LEN;
-#define IXGB_REG_DUMP_LEN  136*sizeof(uint32_t)
-	drvinfo->regdump_len = IXGB_REG_DUMP_LEN;
-	drvinfo->eedump_len = ixgb_eeprom_size(&adapter->hw);
 }
 
 #define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_
 static void
-ixgb_ethtool_gregs(struct ixgb_adapter *adapter,
-		   struct ethtool_regs *regs, uint32_t * regs_buff)
+ixgb_ethtool_gregs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
 {
+	struct ixgb_adapter *adapter = dev->priv;
 	struct ixgb_hw *hw = &adapter->hw;
-	uint32_t *reg = regs_buff;
+	uint32_t *reg = buf;
 	uint32_t *reg_start = reg;
 	uint8_t i;
 
@@ -323,69 +316,37 @@
 }
 
 static int
-ixgb_ethtool_geeprom(struct ixgb_adapter *adapter,
-		     struct ethtool_eeprom *eeprom, uint16_t * eeprom_buff)
+ixgb_ethtool_geeprom(struct net_device *dev,
+		     struct ethtool_eeprom *eeprom, u8 *data)
 {
+	struct ixgb_adapter *adapter = dev->priv;
 	struct ixgb_hw *hw = &adapter->hw;
-	int i, max_len, first_word, last_word;
-	int ret_val = 0;
-
-	if (eeprom->len == 0) {
-		ret_val = -EINVAL;
-		goto geeprom_error;
-	}
 
 	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
 
-	max_len = ixgb_eeprom_size(hw);
-
 	/* use our function to read the eeprom and update our cache */
 	ixgb_get_eeprom_data(hw);
-
-	if (eeprom->offset > eeprom->offset + eeprom->len) {
-		ret_val = -EINVAL;
-		goto geeprom_error;
-	}
-
-	if ((eeprom->offset + eeprom->len) > max_len)
-		eeprom->len = (max_len - eeprom->offset);
-
-	first_word = eeprom->offset >> 1;
-	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
-
-	for (i = 0; i <= (last_word - first_word); i++) {
-		eeprom_buff[i] = hw->eeprom[first_word + i];
-	}
-      geeprom_error:
-	return ret_val;
+	memcpy(data, (char *)hw->eeprom + eeprom->offset, eeprom->len);
+	return 0;
 }
 
 static int
-ixgb_ethtool_seeprom(struct ixgb_adapter *adapter,
-		     struct ethtool_eeprom *eeprom, void __user *user_data)
+ixgb_ethtool_seeprom(struct net_device *dev,
+		     struct ethtool_eeprom *eeprom, u8 *data)
 {
+	struct ixgb_adapter *adapter = dev->priv;
 	struct ixgb_hw *hw = &adapter->hw;
-	uint16_t eeprom_buff[256];
-	int i, max_len, first_word, last_word;
-	void *ptr;
+	/* We are under rtnl, so static is OK */
+	static uint16_t eeprom_buff[IXGB_EEPROM_SIZE];
+	int i, first_word, last_word;
+	char *ptr;
 
 	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
 		return -EFAULT;
 
-	if (eeprom->len == 0)
-		return -EINVAL;
-
-	max_len = ixgb_eeprom_size(hw);
-
-	if (eeprom->offset > eeprom->offset + eeprom->len)
-		return -EINVAL;
-
-	if ((eeprom->offset + eeprom->len) > max_len)
-		eeprom->len = (max_len - eeprom->offset);
-
 	first_word = eeprom->offset >> 1;
 	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
-	ptr = (void *)eeprom_buff;
+	ptr = (char *)eeprom_buff;
 
 	if (eeprom->offset & 1) {
 		/* need read/modify/write of first changed EEPROM word */
@@ -399,8 +360,7 @@
 		eeprom_buff[last_word - first_word]
 		    = ixgb_read_eeprom(hw, last_word);
 	}
-	if (copy_from_user(ptr, user_data, eeprom->len))
-		return -EFAULT;
+	memcpy(ptr, data, eeprom->len);
 
 	for (i = 0; i <= (last_word - first_word); i++)
 		ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]);
@@ -431,8 +391,9 @@
 }
 
 static int
-ixgb_ethtool_led_blink(struct ixgb_adapter *adapter, struct ethtool_value *id)
+ixgb_ethtool_led_blink(struct net_device *netdev, u32 data)
 {
+	struct ixgb_adapter *adapter = netdev->priv;
 	if (!adapter->blink_timer.function) {
 		init_timer(&adapter->blink_timer);
 		adapter->blink_timer.function = ixgb_led_blink_callback;
@@ -442,8 +403,8 @@
 	mod_timer(&adapter->blink_timer, jiffies);
 
 	set_current_state(TASK_INTERRUPTIBLE);
-	if (id->data)
-		schedule_timeout(id->data * HZ);
+	if (data)
+		schedule_timeout(data * HZ);
 	else
 		schedule_timeout(MAX_SCHEDULE_TIMEOUT);
 
@@ -454,268 +415,141 @@
 	return 0;
 }
 
-int ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
+static int ixgb_nway_reset(struct net_device *netdev)
 {
-	struct ixgb_adapter *adapter = netdev->priv;
-	void __user *addr = ifr->ifr_data;
-	uint32_t cmd;
+	if (netif_running(netdev)) {
+		struct ixgb_adapter *adapter = netdev->priv;
+		ixgb_down(adapter, TRUE);
+		ixgb_up(adapter);
+	}
+	return 0;
+}
 
-	if (get_user(cmd, (uint32_t __user *) addr))
-		return -EFAULT;
+static int ixgb_get_stats_count(struct net_device *dev)
+{
+	return IXGB_STATS_LEN;
+}
 
-	switch (cmd) {
-	case ETHTOOL_GSET:{
-			struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-			ixgb_ethtool_gset(adapter, &ecmd);
-			if (copy_to_user(addr, &ecmd, sizeof(ecmd)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_SSET:{
-			struct ethtool_cmd ecmd;
-			if (copy_from_user(&ecmd, addr, sizeof(ecmd)))
-				return -EFAULT;
-			return ixgb_ethtool_sset(adapter, &ecmd);
-		}
-	case ETHTOOL_GDRVINFO:{
-			struct ethtool_drvinfo drvinfo = { ETHTOOL_GDRVINFO };
-			ixgb_ethtool_gdrvinfo(adapter, &drvinfo);
-			if (copy_to_user(addr, &drvinfo, sizeof(drvinfo)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_GSTRINGS:{
-			struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS };
-			char *strings = NULL;
-			int err = 0;
-
-			if (copy_from_user(&gstrings, addr, sizeof(gstrings)))
-				return -EFAULT;
-			switch (gstrings.string_set) {
-			case ETH_SS_STATS:{
-					int i;
-					gstrings.len = IXGB_STATS_LEN;
-					strings =
-					    kmalloc(IXGB_STATS_LEN *
-						    ETH_GSTRING_LEN,
-						    GFP_KERNEL);
-					if (!strings)
-						return -ENOMEM;
-					for (i = 0; i < IXGB_STATS_LEN; i++) {
-						memcpy(&strings
-						       [i * ETH_GSTRING_LEN],
-						       ixgb_gstrings_stats[i].
-						       stat_string,
-						       ETH_GSTRING_LEN);
-					}
-					break;
-				}
-			default:
-				return -EOPNOTSUPP;
-			}
-			if (copy_to_user(addr, &gstrings, sizeof(gstrings)))
-				err = -EFAULT;
-			addr += offsetof(struct ethtool_gstrings, data);
-			if (!err && copy_to_user(addr, strings,
-						 gstrings.len *
-						 ETH_GSTRING_LEN))
-				err = -EFAULT;
-
-			kfree(strings);
-			return err;
-		}
-	case ETHTOOL_GREGS:{
-			struct ethtool_regs regs = { ETHTOOL_GREGS };
-			uint32_t regs_buff[IXGB_REG_DUMP_LEN];
-
-			if (copy_from_user(&regs, addr, sizeof(regs)))
-				return -EFAULT;
-			ixgb_ethtool_gregs(adapter, &regs, regs_buff);
-			if (copy_to_user(addr, &regs, sizeof(regs)))
-				return -EFAULT;
-
-			addr += offsetof(struct ethtool_regs, data);
-			if (copy_to_user(addr, regs_buff, regs.len))
-				return -EFAULT;
-
-			return 0;
-		}
-	case ETHTOOL_NWAY_RST:{
-			if (netif_running(netdev)) {
-				ixgb_down(adapter, TRUE);
-				ixgb_up(adapter);
-			}
-			return 0;
-		}
-	case ETHTOOL_PHYS_ID:{
-			struct ethtool_value id;
-			if (copy_from_user(&id, addr, sizeof(id)))
-				return -EFAULT;
-			return ixgb_ethtool_led_blink(adapter, &id);
-		}
-	case ETHTOOL_GLINK:{
-			struct ethtool_value link = { ETHTOOL_GLINK };
-			link.data = netif_carrier_ok(netdev);
-			if (copy_to_user(addr, &link, sizeof(link)))
-				return -EFAULT;
-			return 0;
-		}
-
-	case ETHTOOL_GEEPROM:{
-			struct ethtool_eeprom eeprom = { ETHTOOL_GEEPROM };
-			uint16_t eeprom_buff[IXGB_EEPROM_SIZE];
-			void *ptr;
-			int err = 0;
-
-			if (copy_from_user(&eeprom, addr, sizeof(eeprom)))
-				return -EFAULT;
-
-			if ((err =
-			     ixgb_ethtool_geeprom(adapter, &eeprom,
-						  eeprom_buff)) < 0)
-				return err;
-
-			if (copy_to_user(addr, &eeprom, sizeof(eeprom)))
-				return -EFAULT;
-
-			addr += offsetof(struct ethtool_eeprom, data);
-			ptr = ((void *)eeprom_buff) + (eeprom.offset & 1);
-
-			if (copy_to_user(addr, ptr, eeprom.len))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_SEEPROM:{
-			struct ethtool_eeprom eeprom;
-
-			if (copy_from_user(&eeprom, addr, sizeof(eeprom)))
-				return -EFAULT;
-
-			addr += offsetof(struct ethtool_eeprom, data);
-			return ixgb_ethtool_seeprom(adapter, &eeprom, addr);
-		}
-	case ETHTOOL_GPAUSEPARAM:{
-			struct ethtool_pauseparam epause =
-			    { ETHTOOL_GPAUSEPARAM };
-			ixgb_ethtool_gpause(adapter, &epause);
-			if (copy_to_user(addr, &epause, sizeof(epause)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_SPAUSEPARAM:{
-			struct ethtool_pauseparam epause;
-			if (copy_from_user(&epause, addr, sizeof(epause)))
-				return -EFAULT;
-			return ixgb_ethtool_spause(adapter, &epause);
-		}
-	case ETHTOOL_GSTATS:{
-			struct {
-				struct ethtool_stats eth_stats;
-				uint64_t data[IXGB_STATS_LEN];
-			} stats = { {
-			ETHTOOL_GSTATS, IXGB_STATS_LEN}};
-			int i;
-
-			for (i = 0; i < IXGB_STATS_LEN; i++)
-				stats.data[i] =
-				    (ixgb_gstrings_stats[i].sizeof_stat ==
-				     sizeof(uint64_t)) ? *(uint64_t *) ((char *)
-									adapter
-									+
-									ixgb_gstrings_stats
-									[i].
-									stat_offset)
-				    : *(uint32_t *) ((char *)adapter +
-						     ixgb_gstrings_stats[i].
-						     stat_offset);
-			if (copy_to_user(addr, &stats, sizeof(stats)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_GRXCSUM:{
-			struct ethtool_value edata = { ETHTOOL_GRXCSUM };
-
-			edata.data = adapter->rx_csum;
-			if (copy_to_user(addr, &edata, sizeof(edata)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_SRXCSUM:{
-			struct ethtool_value edata;
-
-			if (copy_from_user(&edata, addr, sizeof(edata)))
-				return -EFAULT;
-			adapter->rx_csum = edata.data;
-			ixgb_down(adapter, TRUE);
-			ixgb_up(adapter);
-			return 0;
-		}
-	case ETHTOOL_GTXCSUM:{
-			struct ethtool_value edata = { ETHTOOL_GTXCSUM };
-
-			edata.data = (netdev->features & NETIF_F_HW_CSUM) != 0;
-			if (copy_to_user(addr, &edata, sizeof(edata)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_STXCSUM:{
-			struct ethtool_value edata;
-
-			if (copy_from_user(&edata, addr, sizeof(edata)))
-				return -EFAULT;
-
-			if (edata.data)
-				netdev->features |= NETIF_F_HW_CSUM;
-			else
-				netdev->features &= ~NETIF_F_HW_CSUM;
-
-			return 0;
-		}
-	case ETHTOOL_GSG:{
-			struct ethtool_value edata = { ETHTOOL_GSG };
-
-			edata.data = (netdev->features & NETIF_F_SG) != 0;
-			if (copy_to_user(addr, &edata, sizeof(edata)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_SSG:{
-			struct ethtool_value edata;
-
-			if (copy_from_user(&edata, addr, sizeof(edata)))
-				return -EFAULT;
-
-			if (edata.data)
-				netdev->features |= NETIF_F_SG;
-			else
-				netdev->features &= ~NETIF_F_SG;
+static void ixgb_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+	int i;
+	for (i = 0; i < IXGB_STATS_LEN; i++) {
+		memcpy(data + i * ETH_GSTRING_LEN,
+		       ixgb_gstrings_stats[i].stat_string,
+		       ETH_GSTRING_LEN);
+	}
+}
 
-			return 0;
-		}
-#ifdef NETIF_F_TSO
-	case ETHTOOL_GTSO:{
-			struct ethtool_value edata = { ETHTOOL_GTSO };
+static int ixgb_get_regs_len(struct net_device *dev)
+{
+	return 136*sizeof(uint32_t);
+}
+
+static int ixgb_get_eeprom_len(struct net_device *dev)
+{
+	/* return size in bytes */
+	return (IXGB_EEPROM_SIZE << 1);
+}
 
-			edata.data = (netdev->features & NETIF_F_TSO) != 0;
-			if (copy_to_user(addr, &edata, sizeof(edata)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_STSO:{
-			struct ethtool_value edata;
-
-			if (copy_from_user(&edata, addr, sizeof(edata)))
-				return -EFAULT;
-
-			if (edata.data)
-				netdev->features |= NETIF_F_TSO;
-			else
-				netdev->features &= ~NETIF_F_TSO;
+static void get_ethtool_stats(struct net_device *dev,
+		struct ethtool_stats *stats, u64 *data)
+{
+	struct ixgb_adapter *adapter = dev->priv;
+	int i;
 
-			return 0;
-		}
-#endif
-	default:
-		return -EOPNOTSUPP;
+	for (i = 0; i < IXGB_STATS_LEN; i++) {
+		void *p = (char *)adapter + ixgb_gstrings_stats[i].stat_offset;
+		stats->data[i] =
+		    (ixgb_gstrings_stats[i].sizeof_stat == sizeof(uint64_t))
+		    ? *(uint64_t *) p
+		    : *(uint32_t *) p;
 	}
 }
+
+static u32 ixgb_get_rx_csum(struct net_device *dev)
+{
+	struct ixgb_adapter *adapter = dev->priv;
+	return adapter->rx_csum;
+}
+
+static int ixgb_set_rx_csum(struct net_device *dev, u32 sum)
+{
+	struct ixgb_adapter *adapter = dev->priv;
+	adapter->rx_csum = sum;
+	ixgb_down(adapter, TRUE);
+	ixgb_up(adapter);
+	return 0;
+}
+
+static u32 ixgb_get_tx_csum(struct net_device *dev)
+{
+	return (dev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static int ixgb_set_tx_csum(struct net_device *dev, u32 sum)
+{
+	if (sum)
+		dev->features |= NETIF_F_HW_CSUM;
+	else
+		dev->features &= ~NETIF_F_HW_CSUM;
+	return 0;
+}
+
+static u32 ixgb_get_sg(struct net_device *dev)
+{
+	return (dev->features & NETIF_F_SG) != 0;
+}
+
+static int ixgb_set_sg(struct net_device *dev, u32 sum)
+{
+	if (sum)
+		dev->features |= NETIF_F_SG;
+	else
+		dev->features &= ~NETIF_F_SG;
+	return 0;
+}
+
+#ifdef NETIF_F_TSO
+static u32 ixgb_get_tso(struct net_device *dev)
+{
+	return (dev->features & NETIF_F_TSO) != 0;
+}
+
+static int ixgb_set_tso(struct net_device *dev, u32 sum)
+{
+	if (sum)
+		dev->features |= NETIF_F_TSO;
+	else
+		dev->features &= ~NETIF_F_TSO;
+	return 0;
+}
+#endif
+
+struct ethtool_ops ixgb_ethtool_ops = {
+	.get_settings = ixgb_ethtool_gset,
+	.set_settings = ixgb_ethtool_sset,
+	.get_drvinfo = ixgb_ethtool_gdrvinfo,
+	.nway_reset = ixgb_nway_reset,
+	.get_link = ethtool_op_get_link,
+	.phys_id = ixgb_ethtool_led_blink,
+	.get_strings = ixgb_get_strings,
+	.get_stats_count = ixgb_get_stats_count,
+	.get_regs = ixgb_ethtool_gregs,
+	.get_regs_len = ixgb_get_regs_len,
+	.get_eeprom_len = ixgb_get_eeprom_len,
+	.get_eeprom = ixgb_ethtool_geeprom,
+	.set_eeprom = ixgb_ethtool_seeprom,
+	.get_pauseparam = ixgb_ethtool_gpause,
+	.set_pauseparam = ixgb_ethtool_spause,
+	.get_ethtool_stats = get_ethtool_stats,
+	.get_rx_csum = ixgb_get_rx_csum,
+	.set_rx_csum = ixgb_set_rx_csum,
+	.get_tx_csum = ixgb_get_tx_csum,
+	.set_tx_csum = ixgb_set_tx_csum,
+	.get_sg = ixgb_get_sg,
+	.set_sg = ixgb_set_sg,
+#ifdef NETIF_F_TSO
+	.get_tso = ixgb_get_tso,
+	.set_tso = ixgb_set_tso,
+#endif
+};
diff -Nru a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
--- a/drivers/net/ixgb/ixgb_main.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/ixgb/ixgb_main.c	2004-10-10 22:15:16 -07:00
@@ -30,7 +30,7 @@
 
 char ixgb_driver_name[] = "ixgb";
 char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
-char ixgb_driver_version[] = "1.0.66";
+char ixgb_driver_version[] = "1.0.66-k2";
 char ixgb_copyright[] = "Copyright (c) 2001-2004 Intel Corporation.";
 
 /* ixgb_pci_tbl - PCI Device ID Table
@@ -97,7 +97,6 @@
 static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
 #endif
 static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
-static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
 static void ixgb_tx_timeout(struct net_device *dev);
 static void ixgb_tx_timeout_task(struct net_device *dev);
 static void ixgb_vlan_rx_register(struct net_device *netdev,
@@ -124,7 +123,7 @@
 /* Exported from other modules */
 
 extern void ixgb_check_options(struct ixgb_adapter *adapter);
-extern int ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr);
+extern struct ethtool_ops ixgb_ethtool_ops;
 
 static struct pci_driver ixgb_driver = {
 	.name = ixgb_driver_name,
@@ -372,9 +371,9 @@
 	netdev->set_multicast_list = &ixgb_set_multi;
 	netdev->set_mac_address = &ixgb_set_mac;
 	netdev->change_mtu = &ixgb_change_mtu;
-	netdev->do_ioctl = &ixgb_ioctl;
 	netdev->tx_timeout = &ixgb_tx_timeout;
 	netdev->watchdog_timeo = HZ;
+	SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops);
 #ifdef CONFIG_IXGB_NAPI
 	netdev->poll = &ixgb_clean;
 	netdev->weight = 64;
@@ -1615,8 +1614,12 @@
 	}
 #else
 	for (i = 0; i < IXGB_MAX_INTR; i++)
-		if (!ixgb_clean_rx_irq(adapter) & !ixgb_clean_tx_irq(adapter))
+		if (ixgb_clean_rx_irq(adapter) == FALSE)
 			break;
+	for (i = 0; i < IXGB_MAX_INTR; i++)
+		if (ixgb_clean_tx_irq(adapter) == FALSE)
+			break;
+
 	/* if RAIDC:EN == 1 and ICR:RXDMT0 == 1, we need to
 	 * set IMS:RXDMT0 to 1 to restart the RBD timer (POLL)
 	 */
@@ -1677,7 +1680,7 @@
 	eop = tx_ring->buffer_info[i].next_to_watch;
 	eop_desc = IXGB_TX_DESC(*tx_ring, eop);
 
-	while (eop_desc->status & cpu_to_le32(IXGB_TX_DESC_STATUS_DD)) {
+	while (eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
 
 		for (cleaned = FALSE; !cleaned;) {
 			tx_desc = IXGB_TX_DESC(*tx_ring, i);
@@ -1967,25 +1970,6 @@
 	}
 
 	rx_ring->next_to_use = i;
-}
-
-/**
- * ixgb_ioctl - perform a command - e.g: ethtool:get_driver_info.
- * @param netdev network interface device structure
- * @param ifr data to be used/filled in by the ioctl command
- * @param cmd ioctl command to execute
- **/
-
-static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCETHTOOL:
-		return ixgb_ethtool_ioctl(netdev, ifr);
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return 0;
 }
 
 /**
diff -Nru a/drivers/net/mac8390.c b/drivers/net/mac8390.c
--- a/drivers/net/mac8390.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/mac8390.c	2004-10-10 22:15:16 -07:00
@@ -42,10 +42,6 @@
 
 #include "8390.h"
 
-#if (LINUX_VERSION_CODE < 0x02030e)
-#define net_device device
-#endif
-
 #define WD_START_PG			0x00	/* First page of TX buffer */
 #define CABLETRON_RX_START_PG		0x00    /* First page of RX buffer */
 #define CABLETRON_RX_STOP_PG		0x30    /* Last page +1 of RX ring */
diff -Nru a/drivers/net/meth.c b/drivers/net/meth.c
--- a/drivers/net/meth.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/meth.c	2004-10-10 22:15:16 -07:00
@@ -368,31 +368,6 @@
 }
 
 /*
- * Configuration changes (passed on by ifconfig)
- */
-static int meth_config(struct net_device *dev, struct ifmap *map)
-{
-	if (dev->flags & IFF_UP) /* can't act on a running interface */
-		return -EBUSY;
-
-	/* Don't allow changing the I/O address */
-	if (map->base_addr != dev->base_addr) {
-		printk(KERN_WARNING "meth: Can't change I/O address\n");
-		return -EOPNOTSUPP;
-	}
-
-	/* Don't allow changing the IRQ */
-	if (map->irq != dev->irq) {
-		printk(KERN_WARNING "meth: Can't change IRQ\n");
-		return -EOPNOTSUPP;
-	}
-	DPRINTK("Configured\n");
-
-	/* ignore other fields */
-	return 0;
-}
-
-/*
  * Receive a packet: retrieve, encapsulate and pass over to upper levels
  */
 static void meth_rx(struct net_device* dev, unsigned long int_status)
@@ -813,7 +788,6 @@
 
 	dev->open            = meth_open;
 	dev->stop            = meth_release;
-	dev->set_config      = meth_config;
 	dev->hard_start_xmit = meth_tx;
 	dev->do_ioctl        = meth_ioctl;
 	dev->get_stats       = meth_stats;
diff -Nru a/drivers/net/natsemi.c b/drivers/net/natsemi.c
--- a/drivers/net/natsemi.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/natsemi.c	2004-10-10 22:15:16 -07:00
@@ -768,6 +768,7 @@
 static int netdev_close(struct net_device *dev);
 static int netdev_get_regs(struct net_device *dev, u8 *buf);
 static int netdev_get_eeprom(struct net_device *dev, u8 *buf);
+static struct ethtool_ops ethtool_ops;
 
 static inline void __iomem *ns_ioaddr(struct net_device *dev)
 {
@@ -933,6 +934,7 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	dev->poll_controller = &natsemi_poll_controller;
 #endif
+	SET_ETHTOOL_OPS(dev, &ethtool_ops);
 
 	if (mtu)
 		dev->mtu = mtu;
@@ -2477,177 +2479,136 @@
 	spin_unlock_irq(&np->lock);
 }
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	u32 cmd;
-
-	if (get_user(cmd, (u32 __user *)useraddr))
-		return -EFAULT;
-
-	switch (cmd) {
-	/* get driver info */
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-		strncpy(info.driver, DRV_NAME, ETHTOOL_BUSINFO_LEN);
-		strncpy(info.version, DRV_VERSION, ETHTOOL_BUSINFO_LEN);
-		info.fw_version[0] = '\0';
-		strncpy(info.bus_info, pci_name(np->pci_dev),
-			ETHTOOL_BUSINFO_LEN);
-		info.eedump_len = NATSEMI_EEPROM_SIZE;
-		info.regdump_len = NATSEMI_REGS_SIZE;
-		if (copy_to_user(useraddr, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	/* get settings */
-	case ETHTOOL_GSET: {
-		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-		spin_lock_irq(&np->lock);
-		netdev_get_ecmd(dev, &ecmd);
-		spin_unlock_irq(&np->lock);
-		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set settings */
-	case ETHTOOL_SSET: {
-		struct ethtool_cmd ecmd;
-		int r;
-		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-			return -EFAULT;
-		spin_lock_irq(&np->lock);
-		r = netdev_set_ecmd(dev, &ecmd);
-		spin_unlock_irq(&np->lock);
-		return r;
-	}
-	/* get wake-on-lan */
-	case ETHTOOL_GWOL: {
-		struct ethtool_wolinfo wol = {ETHTOOL_GWOL};
-		spin_lock_irq(&np->lock);
-		netdev_get_wol(dev, &wol.supported, &wol.wolopts);
-		netdev_get_sopass(dev, wol.sopass);
-		spin_unlock_irq(&np->lock);
-		if (copy_to_user(useraddr, &wol, sizeof(wol)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set wake-on-lan */
-	case ETHTOOL_SWOL: {
-		struct ethtool_wolinfo wol;
-		int r;
-		if (copy_from_user(&wol, useraddr, sizeof(wol)))
-			return -EFAULT;
-		spin_lock_irq(&np->lock);
-		netdev_set_wol(dev, wol.wolopts);
-		r = netdev_set_sopass(dev, wol.sopass);
-		spin_unlock_irq(&np->lock);
-		return r;
-	}
-	/* get registers */
-	case ETHTOOL_GREGS: {
-		struct ethtool_regs regs;
-		u8 regbuf[NATSEMI_REGS_SIZE];
-		int r;
-
-		if (copy_from_user(&regs, useraddr, sizeof(regs)))
-			return -EFAULT;
-
-		if (regs.len > NATSEMI_REGS_SIZE) {
-			regs.len = NATSEMI_REGS_SIZE;
-		}
-		regs.version = NATSEMI_REGS_VER;
-		if (copy_to_user(useraddr, &regs, sizeof(regs)))
-			return -EFAULT;
+	strncpy(info->driver, DRV_NAME, ETHTOOL_BUSINFO_LEN);
+	strncpy(info->version, DRV_VERSION, ETHTOOL_BUSINFO_LEN);
+	strncpy(info->bus_info, pci_name(np->pci_dev), ETHTOOL_BUSINFO_LEN);
+}
 
-		useraddr += offsetof(struct ethtool_regs, data);
+static int get_regs_len(struct net_device *dev)
+{
+	return NATSEMI_REGS_SIZE;
+}
 
-		spin_lock_irq(&np->lock);
-		r = netdev_get_regs(dev, regbuf);
-		spin_unlock_irq(&np->lock);
+static int get_eeprom_len(struct net_device *dev)
+{
+	return NATSEMI_EEPROM_SIZE;
+}
 
-		if (r)
-			return r;
-		if (copy_to_user(useraddr, regbuf, regs.len))
-			return -EFAULT;
-		return 0;
-	}
-	/* get message-level */
-	case ETHTOOL_GMSGLVL: {
-		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
-		edata.data = np->msg_enable;
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set message-level */
-	case ETHTOOL_SMSGLVL: {
-		struct ethtool_value edata;
-		if (copy_from_user(&edata, useraddr, sizeof(edata)))
-			return -EFAULT;
-		np->msg_enable = edata.data;
-		return 0;
-	}
-	/* restart autonegotiation */
-	case ETHTOOL_NWAY_RST: {
-		int tmp;
-		int r = -EINVAL;
-		/* if autoneg is off, it's an error */
-		tmp = mdio_read(dev, MII_BMCR);
-		if (tmp & BMCR_ANENABLE) {
-			tmp |= (BMCR_ANRESTART);
-			mdio_write(dev, MII_BMCR, tmp);
-			r = 0;
-		}
-		return r;
-	}
-	/* get link status */
-	case ETHTOOL_GLINK: {
-		struct ethtool_value edata = {ETHTOOL_GLINK};
-		/* LSTATUS is latched low until a read - so read twice */
-		mdio_read(dev, MII_BMSR);
-		edata.data = (mdio_read(dev, MII_BMSR)&BMSR_LSTATUS) ? 1:0;
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	/* get EEPROM */
-	case ETHTOOL_GEEPROM: {
-		struct ethtool_eeprom eeprom;
-		u8 eebuf[NATSEMI_EEPROM_SIZE];
-		int r;
+static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	spin_lock_irq(&np->lock);
+	netdev_get_ecmd(dev, ecmd);
+	spin_unlock_irq(&np->lock);
+	return 0;
+}
 
-		if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
-			return -EFAULT;
+static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	int res;
+	spin_lock_irq(&np->lock);
+	res = netdev_set_ecmd(dev, ecmd);
+	spin_unlock_irq(&np->lock);
+	return res;
+}
 
-		if (eeprom.offset > eeprom.offset+eeprom.len)
-			return -EINVAL;
+static void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	spin_lock_irq(&np->lock);
+	netdev_get_wol(dev, &wol->supported, &wol->wolopts);
+	netdev_get_sopass(dev, wol->sopass);
+	spin_unlock_irq(&np->lock);
+}
 
-		if ((eeprom.offset+eeprom.len) > NATSEMI_EEPROM_SIZE) {
-			eeprom.len = NATSEMI_EEPROM_SIZE-eeprom.offset;
-		}
-		eeprom.magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16);
-		if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
-			return -EFAULT;
+static int set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	int res;
+	spin_lock_irq(&np->lock);
+	netdev_set_wol(dev, wol->wolopts);
+	res = netdev_set_sopass(dev, wol->sopass);
+	spin_unlock_irq(&np->lock);
+	return res;
+}
 
-		useraddr += offsetof(struct ethtool_eeprom, data);
+static void get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	regs->version = NATSEMI_REGS_VER;
+	spin_lock_irq(&np->lock);
+	netdev_get_regs(dev, buf);
+	spin_unlock_irq(&np->lock);
+}
 
-		spin_lock_irq(&np->lock);
-		r = netdev_get_eeprom(dev, eebuf);
-		spin_unlock_irq(&np->lock);
+static u32 get_msglevel(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	return np->msg_enable;
+}
 
-		if (r)
-			return r;
-		if (copy_to_user(useraddr, eebuf+eeprom.offset, eeprom.len))
-			return -EFAULT;
-		return 0;
-	}
+static void set_msglevel(struct net_device *dev, u32 val)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	np->msg_enable = val;
+}
 
+static int nway_reset(struct net_device *dev)
+{
+	int tmp;
+	int r = -EINVAL;
+	/* if autoneg is off, it's an error */
+	tmp = mdio_read(dev, MII_BMCR);
+	if (tmp & BMCR_ANENABLE) {
+		tmp |= (BMCR_ANRESTART);
+		mdio_write(dev, MII_BMCR, tmp);
+		r = 0;
 	}
+	return r;
+}
 
-	return -EOPNOTSUPP;
+static u32 get_link(struct net_device *dev)
+{
+	/* LSTATUS is latched low until a read - so read twice */
+	mdio_read(dev, MII_BMSR);
+	return (mdio_read(dev, MII_BMSR)&BMSR_LSTATUS) ? 1:0;
 }
 
+static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	u8 eebuf[NATSEMI_EEPROM_SIZE];
+	int res;
+
+	eeprom->magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16);
+	spin_lock_irq(&np->lock);
+	res = netdev_get_eeprom(dev, eebuf);
+	spin_unlock_irq(&np->lock);
+	if (!res)
+		memcpy(data, eebuf+eeprom->offset, eeprom->len);
+	return res;
+}
+
+static struct ethtool_ops ethtool_ops = {
+	.get_drvinfo = get_drvinfo,
+	.get_regs_len = get_regs_len,
+	.get_eeprom_len = get_eeprom_len,
+	.get_settings = get_settings,
+	.set_settings = set_settings,
+	.get_wol = get_wol,
+	.set_wol = set_wol,
+	.get_regs = get_regs,
+	.get_msglevel = get_msglevel,
+	.set_msglevel = set_msglevel,
+	.nway_reset = nway_reset,
+	.get_link = get_link,
+	.get_eeprom = get_eeprom,
+};
+
 static int netdev_set_wol(struct net_device *dev, u32 newval)
 {
 	struct netdev_private *np = netdev_priv(dev);
@@ -3002,8 +2963,6 @@
 	struct netdev_private *np = netdev_priv(dev);
 
 	switch(cmd) {
-	case SIOCETHTOOL:
-		return netdev_ethtool_ioctl(dev, rq->ifr_data);
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
 	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = np->phy_addr_external;
diff -Nru a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
--- a/drivers/net/ne2k-pci.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/ne2k-pci.c	2004-10-10 22:15:16 -07:00
@@ -653,12 +653,43 @@
 	pci_set_drvdata(pdev, NULL);
 }
 
+#ifdef CONFIG_PM
+static int ne2k_pci_suspend (struct pci_dev *pdev, u32 state)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+
+	netif_device_detach(dev);
+	pci_save_state(pdev, pdev->saved_config_space);
+	pci_set_power_state(pdev, state);
+
+	return 0;
+}
+
+static int ne2k_pci_resume (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+
+	pci_set_power_state(pdev, 0);
+	pci_restore_state(pdev, pdev->saved_config_space);
+	NS8390_init(dev, 1);
+	netif_device_attach(dev);
+
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
 
 static struct pci_driver ne2k_driver = {
 	.name		= DRV_NAME,
 	.probe		= ne2k_pci_init_one,
 	.remove		= __devexit_p(ne2k_pci_remove_one),
 	.id_table	= ne2k_pci_tbl,
+#ifdef CONFIG_PM
+	.suspend	= ne2k_pci_suspend,
+	.resume		= ne2k_pci_resume,
+#endif /* CONFIG_PM */
+
 };
 
 
diff -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c
--- a/drivers/net/ns83820.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/ns83820.c	2004-10-10 22:15:16 -07:00
@@ -64,6 +64,8 @@
  *				tuning
  *			0.20 -	fix stupid RFEN thinko.  i am such a smurf.
  *
+ *	20040828	0.21 -	add hardware vlan accleration
+ *				by Neil Horman <nhorman@redhat.com>
  * Driver Overview
  * ===============
  *
@@ -92,6 +94,7 @@
 //#define dprintk		printk
 #define dprintk(x...)		do { } while (0)
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -108,6 +111,7 @@
 #include <linux/prefetch.h>
 #include <linux/ethtool.h>
 #include <linux/timer.h>
+#include <linux/if_vlan.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -138,6 +142,9 @@
 
 /* tunables */
 #define RX_BUF_SIZE	1500	/* 8192 */
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define NS83820_VLAN_ACCEL_SUPPORT
+#endif
 
 /* Must not exceed ~65000. */
 #define NR_RX_DESC	64
@@ -262,6 +269,8 @@
 #define EXTSTS_UDPPKT	0x00200000
 #define EXTSTS_TCPPKT	0x00080000
 #define EXTSTS_IPPKT	0x00020000
+#define EXTSTS_VPKT	0x00010000
+#define EXTSTS_VTG_MASK	0x0000ffff
 
 #define SPDSTS_POLARITY	(CFG_SPDSTS1 | CFG_SPDSTS0 | CFG_DUPSTS | (lnksts ? CFG_LNKSTS : 0))
 
@@ -403,6 +412,7 @@
 #define CMDSTS_INTR	0x20000000
 #define CMDSTS_ERR	0x10000000
 #define CMDSTS_OK	0x08000000
+#define CMDSTS_RUNT	0x00200000
 #define CMDSTS_LEN_MASK	0x0000ffff
 
 #define CMDSTS_DEST_MASK	0x01800000
@@ -432,6 +442,10 @@
 
 	struct pci_dev		*pci_dev;
 
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+	struct vlan_group	*vlgrp;
+#endif
+
 	struct rx_info		rx_info;
 	struct tasklet_struct	rx_tasklet;
 
@@ -494,6 +508,33 @@
 	(((NR_TX_DESC-2 + dev->tx_done_idx - dev->tx_free_idx) % NR_TX_DESC) > MIN_TX_DESC_FREE)
 
 
+#ifdef NS83820_VLAN_ACCEL_SUPPORT 
+static void ns83820_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
+{
+	struct ns83820 *dev = PRIV(ndev);
+
+	spin_lock_irq(&dev->misc_lock);
+	spin_lock(&dev->tx_lock);
+
+	dev->vlgrp = grp;
+
+	spin_unlock(&dev->tx_lock);
+	spin_unlock_irq(&dev->misc_lock);
+}
+
+static void ns83820_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid)
+{
+	struct ns83820 *dev = PRIV(ndev);
+
+	spin_lock_irq(&dev->misc_lock);
+	spin_lock(&dev->tx_lock);
+	if (dev->vlgrp)
+		dev->vlgrp->vlan_devices[vid] = NULL;
+	spin_unlock(&dev->tx_lock);
+	spin_unlock_irq(&dev->misc_lock);
+}
+#endif
+
 /* Packet Receiver
  *
  * The hardware supports linked lists of receive descriptors for
@@ -836,6 +877,7 @@
 	struct ns83820 *dev = PRIV(ndev);
 	struct rx_info *info = &dev->rx_info;
 	unsigned next_rx;
+	int rx_rc, len;
 	u32 cmdsts, *desc;
 	unsigned long flags;
 	int nr = 0;
@@ -876,8 +918,24 @@
 
 		pci_unmap_single(dev->pci_dev, bufptr,
 				 RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+		len = cmdsts & CMDSTS_LEN_MASK;
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+		/* NH: As was mentioned below, this chip is kinda
+		 * brain dead about vlan tag stripping.  Frames
+		 * that are 64 bytes with a vlan header appended
+		 * like arp frames, or pings, are flagged as Runts
+		 * when the tag is stripped and hardware.  This
+		 * also means that the OK bit in the descriptor 
+		 * is cleared when the frame comes in so we have
+		 * to do a specific length check here to make sure
+		 * the frame would have been ok, had we not stripped
+		 * the tag.
+		 */ 
+		if (likely((CMDSTS_OK & cmdsts) ||
+			((cmdsts & CMDSTS_RUNT) && len >= 56))) {   
+#else
 		if (likely(CMDSTS_OK & cmdsts)) {
-			int len = cmdsts & 0xffff;
+#endif
 			skb_put(skb, len);
 			if (unlikely(!skb))
 				goto netdev_mangle_me_harder_failed;
@@ -891,7 +949,18 @@
 				skb->ip_summed = CHECKSUM_NONE;
 			}
 			skb->protocol = eth_type_trans(skb, ndev);
-			if (NET_RX_DROP == netif_rx(skb)) {
+#ifdef NS83820_VLAN_ACCEL_SUPPORT 
+			if(extsts & EXTSTS_VPKT) {
+				unsigned short tag;
+				tag = ntohs(extsts & EXTSTS_VTG_MASK);
+				rx_rc = vlan_hwaccel_rx(skb,dev->vlgrp,tag);
+			} else {
+				rx_rc = netif_rx(skb);
+			}
+#else
+			rx_rc = netif_rx(skb);
+#endif
+			if (NET_RX_DROP == rx_rc) {
 netdev_mangle_me_harder_failed:
 				dev->stats.rx_dropped ++;
 			}
@@ -1099,6 +1168,17 @@
 			extsts |= EXTSTS_UDPPKT;
 	}
 
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+	if(vlan_tx_tag_present(skb)) {
+		/* fetch the vlan tag info out of the
+		 * ancilliary data if the vlan code
+		 * is using hw vlan acceleration
+		 */
+		short tag = vlan_tx_tag_get(skb);
+		extsts |= (EXTSTS_VPKT | htons(tag));
+	}
+#endif
+
 	len = skb->len;
 	if (nr_frags)
 		len -= skb->data_len;
@@ -1192,59 +1272,26 @@
 	return &dev->stats;
 }
 
-static int ns83820_ethtool_ioctl (struct ns83820 *dev, void __user *useraddr)
+static void ns83820_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
 {
-	u32 ethcmd;
-
-	if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
-		return -EFAULT;
-
-	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy(info.driver, "ns83820");
-			strcpy(info.version, VERSION);
-			strcpy(info.bus_info, pci_name(dev->pci_dev));
-			if (copy_to_user(useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
-
-	/* get link status */
-	case ETHTOOL_GLINK: {
-		struct ethtool_value edata = { ETHTOOL_GLINK };
-		u32 cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY;
-
-		if (cfg & CFG_LNKSTS)
-			edata.data = 1;
-		else
-			edata.data = 0;
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-
-	default:
-		break;
-	}
-
-	return -EOPNOTSUPP;
+	struct ns83820 *dev = PRIV(ndev);
+	strcpy(info->driver, "ns83820");
+	strcpy(info->version, VERSION);
+	strcpy(info->bus_info, pci_name(dev->pci_dev));
 }
 
-static int ns83820_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
+static u32 ns83820_get_link(struct net_device *ndev)
 {
 	struct ns83820 *dev = PRIV(ndev);
-
-	switch(cmd) {
-	case SIOCETHTOOL:
-		return ns83820_ethtool_ioctl(dev, rq->ifr_data);
-
-	default:
-		return -EOPNOTSUPP;
-	}
+	u32 cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY;
+	return cfg & CFG_LNKSTS ? 1 : 0;
 }
 
+static struct ethtool_ops ops = {
+	.get_drvinfo = ns83820_get_drvinfo,
+	.get_link = ns83820_get_link
+};
+
 static void ns83820_mib_isr(struct ns83820 *dev)
 {
 	spin_lock(&dev->misc_lock);
@@ -1884,10 +1931,9 @@
 	ndev->get_stats = ns83820_get_stats;
 	ndev->change_mtu = ns83820_change_mtu;
 	ndev->set_multicast_list = ns83820_set_multicast;
-	ndev->do_ioctl = ns83820_ioctl;
+	SET_ETHTOOL_OPS(ndev, &ops);
 	ndev->tx_timeout = ns83820_tx_timeout;
 	ndev->watchdog_timeo = 5 * HZ;
-
 	pci_set_drvdata(pci_dev, ndev);
 
 	ns83820_do_reset(dev, CR_RST);
@@ -2013,11 +2059,25 @@
 	 * a ping with a VLAN header) then the card, strips the 4 byte VLAN
 	 * tag and then checks the packet size, so if RXCFG_ARP is not enabled,
 	 * it discrards it!.  These guys......
+	 * also turn on tag stripping if hardware acceleration is enabled
 	 */
-	writel(VRCR_IPEN | VRCR_VTDEN, dev->base + VRCR);
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+#define VRCR_INIT_VALUE (VRCR_IPEN|VRCR_VTDEN|VRCR_VTREN) 
+#else
+#define VRCR_INIT_VALUE (VRCR_IPEN|VRCR_VTDEN)
+#endif
+	writel(VRCR_INIT_VALUE, dev->base + VRCR);
 
-	/* Enable per-packet TCP/UDP/IP checksumming */
-	writel(VTCR_PPCHK, dev->base + VTCR);
+	/* Enable per-packet TCP/UDP/IP checksumming
+	 * and per packet vlan tag insertion if
+	 * vlan hardware acceleration is enabled
+	 */
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+#define VTCR_INIT_VALUE (VTCR_PPCHK|VTCR_VPPTI)
+#else
+#define VTCR_INIT_VALUE VTCR_PPCHK
+#endif
+	writel(VTCR_INIT_VALUE, dev->base + VTCR);
 
 	/* Ramit : Enable async and sync pause frames */
 	/* writel(0, dev->base + PCR); */
@@ -2033,6 +2093,13 @@
 	/* Yes, we support dumb IP checksum on transmit */
 	ndev->features |= NETIF_F_SG;
 	ndev->features |= NETIF_F_IP_CSUM;
+
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+	/* We also support hardware vlan acceleration */
+	ndev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	ndev->vlan_rx_register = ns83820_vlan_rx_register;
+	ndev->vlan_rx_kill_vid = ns83820_vlan_rx_kill_vid;
+#endif
 
 	if (using_dac) {
 		printk(KERN_INFO "%s: using 64 bit addressing.\n",
diff -Nru a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
--- a/drivers/net/pcmcia/smc91c92_cs.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/pcmcia/smc91c92_cs.c	2004-10-10 22:15:16 -07:00
@@ -304,6 +304,7 @@
 static int mdio_read(struct net_device *dev, int phy_id, int loc);
 static void mdio_write(struct net_device *dev, int phy_id, int loc, int value);
 static int smc_link_ok(struct net_device *dev);
+static struct ethtool_ops ethtool_ops;
 
 /*======================================================================
 
@@ -357,6 +358,7 @@
     dev->open = &smc_open;
     dev->stop = &smc_close;
     dev->do_ioctl = &smc_ioctl;
+    SET_ETHTOOL_OPS(dev, &ethtool_ops);
 #ifdef HAVE_TX_TIMEOUT
     dev->tx_timeout = smc_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
@@ -2118,131 +2120,130 @@
     return 0;
 }
 
-static int smc_ethtool_ioctl (struct net_device *dev, void __user *useraddr)
+static int check_if_running(struct net_device *dev)
 {
-    u32 ethcmd;
-    struct smc_private *smc = netdev_priv(dev);
-
-    if (get_user(ethcmd, (u32 __user *)useraddr))
-	return -EFAULT;
-
-    switch (ethcmd) {
-
-    case ETHTOOL_GDRVINFO: {
-	struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-	strcpy(info.driver, DRV_NAME);
-	strcpy(info.version, DRV_VERSION);
-	if (copy_to_user(useraddr, &info, sizeof(info)))
-	    return -EFAULT;
+	if (!netif_running(dev))
+		return -EINVAL;
 	return 0;
-    }
+}
+
+static void smc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+}
 
-    /* get settings */
-    case ETHTOOL_GSET: {
+static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct smc_private *smc = netdev_priv(dev);
+	ioaddr_t ioaddr = dev->base_addr;
+	u16 saved_bank = inw(ioaddr + BANK_SELECT);
 	int ret;
-	struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+
+	SMC_SELECT_BANK(3);
 	spin_lock_irq(&smc->lock);
 	if (smc->cfg & CFG_MII_SELECT)
-	    ret = mii_ethtool_gset(&smc->mii_if, &ecmd);
+		ret = mii_ethtool_gset(&smc->mii_if, ecmd);
 	else
-	    ret = smc_netdev_get_ecmd(dev, &ecmd);
+		ret = smc_netdev_get_ecmd(dev, ecmd);
 	spin_unlock_irq(&smc->lock);
-	if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-	    return -EFAULT;
+	SMC_SELECT_BANK(saved_bank);
 	return ret;
-    }
+}
 
-    /* set settings */
-    case ETHTOOL_SSET: {
+static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct smc_private *smc = netdev_priv(dev);
+	ioaddr_t ioaddr = dev->base_addr;
+	u16 saved_bank = inw(ioaddr + BANK_SELECT);
 	int ret;
-	struct ethtool_cmd ecmd;
-	if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-	    return -EFAULT;
+
+	SMC_SELECT_BANK(3);
 	spin_lock_irq(&smc->lock);
 	if (smc->cfg & CFG_MII_SELECT)
-	    ret = mii_ethtool_sset(&smc->mii_if, &ecmd);
+		ret = mii_ethtool_sset(&smc->mii_if, ecmd);
 	else
-	    ret = smc_netdev_set_ecmd(dev, &ecmd);
+		ret = smc_netdev_set_ecmd(dev, ecmd);
 	spin_unlock_irq(&smc->lock);
+	SMC_SELECT_BANK(saved_bank);
 	return ret;
-    }
+}
+
+static u32 smc_get_link(struct net_device *dev)
+{
+	struct smc_private *smc = netdev_priv(dev);
+	ioaddr_t ioaddr = dev->base_addr;
+	u16 saved_bank = inw(ioaddr + BANK_SELECT);
+	u32 ret;
 
-    /* get link status */
-    case ETHTOOL_GLINK: {
-	struct ethtool_value edata = { ETHTOOL_GLINK };
+	SMC_SELECT_BANK(3);
 	spin_lock_irq(&smc->lock);
-	edata.data = smc_link_ok(dev);
+	ret = smc_link_ok(dev);
 	spin_unlock_irq(&smc->lock);
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-	    return -EFAULT;
-	return 0;
-    }
+	SMC_SELECT_BANK(saved_bank);
+	return ret;
+}
 
 #ifdef PCMCIA_DEBUG
-    /* get message-level */
-    case ETHTOOL_GMSGLVL: {
-	struct ethtool_value edata = { ETHTOOL_GMSGLVL };
-	edata.data = pc_debug;
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-	    return -EFAULT;
-	return 0;
-    }
+static u32 smc_get_msglevel(struct net_device *dev)
+{
+	return pc_debug;
+}
 
-    /* set message-level */
-    case ETHTOOL_SMSGLVL: {
-	struct ethtool_value edata;
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-	    return -EFAULT;
-	pc_debug = edata.data;
-	return 0;
-    }
+static void smc_set_msglevel(struct net_device *dev, u32 val)
+{
+	pc_debug = val;
+}
 #endif
-    /* restart autonegotiation */
-    case ETHTOOL_NWAY_RST: {
-	if (smc->cfg & CFG_MII_SELECT)
-	    return mii_nway_restart(&smc->mii_if);
-	else
-	    return -EOPNOTSUPP;
-    }
-
-    default:
-	break;
-    }
 
-    return -EOPNOTSUPP;
-}
+static int smc_nway_reset(struct net_device *dev)
+{
+	struct smc_private *smc = netdev_priv(dev);
+	if (smc->cfg & CFG_MII_SELECT) {
+		ioaddr_t ioaddr = dev->base_addr;
+		u16 saved_bank = inw(ioaddr + BANK_SELECT);
+		int res;
+
+		SMC_SELECT_BANK(3);
+		res = mii_nway_restart(&smc->mii_if);
+		SMC_SELECT_BANK(saved_bank);
+
+		return res;
+	} else
+		return -EOPNOTSUPP;
+}
+
+static struct ethtool_ops ethtool_ops = {
+	.begin = check_if_running,
+	.get_drvinfo = smc_get_drvinfo,
+	.get_settings = smc_get_settings,
+	.set_settings = smc_set_settings,
+	.get_link = smc_get_link,
+#ifdef PCMCIA_DEBUG
+	.get_msglevel = smc_get_msglevel,
+	.set_msglevel = smc_set_msglevel,
+#endif
+	.nway_reset = smc_nway_reset,
+};
 
 static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
-    struct smc_private *smc = netdev_priv(dev);
-    struct mii_ioctl_data *mii;
-    int rc = 0;
-    u_short saved_bank;
-    ioaddr_t ioaddr = dev->base_addr;
-
-    mii = if_mii(rq);
-    if (!netif_running(dev))
-    	return -EINVAL;
+	struct smc_private *smc = netdev_priv(dev);
+	struct mii_ioctl_data *mii = if_mii(rq);
+	int rc = 0;
+	u16 saved_bank;
+	ioaddr_t ioaddr = dev->base_addr;
 
-    switch (cmd) {
-    case SIOCETHTOOL:
-	saved_bank = inw(ioaddr + BANK_SELECT);
-	SMC_SELECT_BANK(3);
-	rc = smc_ethtool_ioctl(dev, rq->ifr_data);
-	SMC_SELECT_BANK(saved_bank);
-	break;
+	if (!netif_running(dev))
+		return -EINVAL;
 
-    default:
 	spin_lock_irq(&smc->lock);
 	saved_bank = inw(ioaddr + BANK_SELECT);
 	SMC_SELECT_BANK(3);
 	rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL);
 	SMC_SELECT_BANK(saved_bank);
 	spin_unlock_irq(&smc->lock);
-	break;
-    }
-
-    return rc;
+	return rc;
 }
 
 static struct pcmcia_driver smc91c92_cs_driver = {
diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c
--- a/drivers/net/r8169.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/r8169.c	2004-10-10 22:15:16 -07:00
@@ -6,6 +6,7 @@
  History:
  Feb  4 2002	- created initially by ShuChen <shuchen@realtek.com.tw>.
  May 20 2002	- Add link status force-mode and TBI mode support.
+        2004	- Massive updates. See kernel SCM system for details.
 =========================================================================
   1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.
 	 Command: 'insmod r8169 media = SET_MEDIA'
@@ -33,6 +34,13 @@
 	- Copy mc_filter setup code from 8139cp
 	  (includes an optimization, and avoids set_bit use)
 
+VERSION 1.6LK	<2004/04/14>
+
+	- Merge of Realtek's version 1.6
+	- Conversion to DMA API
+	- Suspend/resume
+	- Endianness
+	- Misc Rx/Tx bugs
 */
 
 #include <linux/module.h>
@@ -42,13 +50,17 @@
 #include <linux/delay.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/if_vlan.h>
 #include <linux/crc32.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 
-#define RTL8169_VERSION "1.2"
+#define RTL8169_VERSION "1.6LK"
 #define MODULENAME "r8169"
 #define RTL8169_DRIVER_NAME   MODULENAME " Gigabit Ethernet driver " RTL8169_VERSION
 #define PFX MODULENAME ": "
@@ -65,11 +77,16 @@
 #define dprintk(fmt, args...)	do {} while (0)
 #endif /* RTL8169_DEBUG */
 
+#define TX_BUFFS_AVAIL(tp) \
+	(tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1)
+
 #ifdef CONFIG_R8169_NAPI
 #define rtl8169_rx_skb			netif_receive_skb
+#define rtl8169_rx_hwaccel_skb		vlan_hwaccel_rx
 #define rtl8169_rx_quota(count, quota)	min(count, quota)
 #else
 #define rtl8169_rx_skb			netif_rx
+#define rtl8169_rx_hwaccel_skb		vlan_hwaccel_receive_skb
 #define rtl8169_rx_quota(count, quota)	count
 #endif
 
@@ -87,9 +104,6 @@
 /* MAC address length*/
 #define MAC_ADDR_LEN	6
 
-/* max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4).*/
-#define MAX_ETH_FRAME_SIZE	1536
-
 #define TX_FIFO_THRESH 256	/* In bytes */
 
 #define RX_FIFO_THRESH	7	/* 7 means NO threshold, Rx buffer level before first PCI xfer.  */
@@ -99,6 +113,7 @@
 #define RxPacketMaxSize	0x0800	/* Maximum size supported is 16K-1 */
 #define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
 
+#define R8169_REGS_SIZE		256
 #define R8169_NAPI_WEIGHT	64
 #define NUM_TX_DESC	64	/* Number of Tx descriptor registers */
 #define NUM_RX_DESC	256	/* Number of Rx descriptor registers */
@@ -106,7 +121,6 @@
 #define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))
 #define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))
 
-#define RTL_MIN_IO_SIZE 0x80
 #define RTL8169_TX_TIMEOUT	(6*HZ)
 #define RTL8169_PHY_TIMEOUT	(10*HZ)
 
@@ -122,7 +136,8 @@
 	RTL_GIGA_MAC_VER_B = 0x00,
 	/* RTL_GIGA_MAC_VER_C = 0x03, */
 	RTL_GIGA_MAC_VER_D = 0x01,
-	RTL_GIGA_MAC_VER_E = 0x02
+	RTL_GIGA_MAC_VER_E = 0x02,
+	RTL_GIGA_MAC_VER_X = 0x04	/* Greater than RTL_GIGA_MAC_VER_E */
 };
 
 enum phy_version {
@@ -304,26 +319,55 @@
 };
 
 enum _DescStatusBit {
-	OWNbit = 0x80000000,
-	EORbit = 0x40000000,
-	FSbit = 0x20000000,
-	LSbit = 0x10000000,
+	DescOwn		= (1 << 31), /* Descriptor is owned by NIC */
+	RingEnd		= (1 << 30), /* End of descriptor ring */
+	FirstFrag	= (1 << 29), /* First segment of a packet */
+	LastFrag	= (1 << 28), /* Final segment of a packet */
+
+	/* Tx private */
+	LargeSend	= (1 << 27), /* TCP Large Send Offload (TSO) */
+	MSSShift	= 16,        /* MSS value position */
+	MSSMask		= 0xfff,     /* MSS value + LargeSend bit: 12 bits */
+	IPCS		= (1 << 18), /* Calculate IP checksum */
+	UDPCS		= (1 << 17), /* Calculate UDP/IP checksum */
+	TCPCS		= (1 << 16), /* Calculate TCP/IP checksum */
+	TxVlanTag	= (1 << 17), /* Add VLAN tag */
+
+	/* Rx private */
+	PID1		= (1 << 18), /* Protocol ID bit 1/2 */
+	PID0		= (1 << 17), /* Protocol ID bit 2/2 */
+
+#define RxProtoUDP	(PID1)
+#define RxProtoTCP	(PID0)
+#define RxProtoIP	(PID1 | PID0)
+#define RxProtoMask	RxProtoIP
+
+	IPFail		= (1 << 16), /* IP checksum failed */
+	UDPFail		= (1 << 15), /* UDP/IP checksum failed */
+	TCPFail		= (1 << 14), /* TCP/IP checksum failed */
+	RxVlanTag	= (1 << 16), /* VLAN tag available */
 };
 
 #define RsvdMask	0x3fffc000
 
 struct TxDesc {
-	u32 status;
-	u32 vlan_tag;
+	u32 opts1;
+	u32 opts2;
 	u64 addr;
 };
 
 struct RxDesc {
-	u32 status;
-	u32 vlan_tag;
+	u32 opts1;
+	u32 opts2;
 	u64 addr;
 };
 
+struct ring_info {
+	struct sk_buff	*skb;
+	u32		len;
+	u8		__pad[sizeof(void *) - sizeof(u32)];
+};
+
 struct rtl8169_private {
 	void *mmio_addr;		/* memory map physical address */
 	struct pci_dev *pci_dev;	/* Index of PCI device  */
@@ -341,18 +385,22 @@
 	dma_addr_t TxPhyAddr;
 	dma_addr_t RxPhyAddr;
 	struct sk_buff *Rx_skbuff[NUM_RX_DESC];	/* Rx data buffers */
-	struct sk_buff *Tx_skbuff[NUM_TX_DESC];	/* Tx data buffers */
+	struct ring_info tx_skb[NUM_TX_DESC];	/* Tx data buffers */
+	unsigned rx_buf_sz;
 	struct timer_list timer;
 	u16 cp_cmd;
 	u16 intr_mask;
 	int phy_auto_nego_reg;
 	int phy_1000_ctrl_reg;
-
+#ifdef CONFIG_R8169_VLAN
+	struct vlan_group *vlgrp;
+#endif
 	int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
 	void (*get_settings)(struct net_device *, struct ethtool_cmd *);
 	void (*phy_reset_enable)(void *);
 	unsigned int (*phy_reset_pending)(void *);
 	unsigned int (*link_ok)(void *);
+	struct work_struct task;
 };
 
 MODULE_AUTHOR("Realtek");
@@ -373,6 +421,8 @@
 static void rtl8169_set_rx_mode(struct net_device *dev);
 static void rtl8169_tx_timeout(struct net_device *dev);
 static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);
+static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
+				void *);
 #ifdef CONFIG_R8169_NAPI
 static int rtl8169_poll(struct net_device *dev, int *budget);
 #endif
@@ -511,6 +561,11 @@
 	strcpy(info->bus_info, pci_name(tp->pci_dev));
 }
 
+static int rtl8169_get_regs_len(struct net_device *dev)
+{
+	return R8169_REGS_SIZE;
+}
+
 static int rtl8169_set_speed_tbi(struct net_device *dev,
 				 u8 autoneg, u16 speed, u8 duplex)
 {
@@ -601,6 +656,105 @@
 	return ret;
 }
 
+static u32 rtl8169_get_rx_csum(struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+
+	return tp->cp_cmd & RxChkSum;
+}
+
+static int rtl8169_set_rx_csum(struct net_device *dev, u32 data)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tp->lock, flags);
+
+	if (data)
+		tp->cp_cmd |= RxChkSum;
+	else
+		tp->cp_cmd &= ~RxChkSum;
+
+	RTL_W16(CPlusCmd, tp->cp_cmd);
+	RTL_R16(CPlusCmd);
+
+	spin_unlock_irqrestore(&tp->lock, flags);
+
+	return 0;
+}
+
+#ifdef CONFIG_R8169_VLAN
+
+static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
+				      struct sk_buff *skb)
+{
+	return (tp->vlgrp && vlan_tx_tag_present(skb)) ?
+		TxVlanTag | cpu_to_be16(vlan_tx_tag_get(skb)) : 0x00;
+}
+
+static void rtl8169_vlan_rx_register(struct net_device *dev,
+				     struct vlan_group *grp)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tp->lock, flags);
+	tp->vlgrp = grp;
+	tp->cp_cmd |= RxVlan;
+	RTL_W16(CPlusCmd, tp->cp_cmd);
+	RTL_R16(CPlusCmd);
+	spin_unlock_irqrestore(&tp->lock, flags);
+}
+
+static void rtl8169_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tp->lock, flags);
+	tp->cp_cmd &= ~RxVlan;
+	RTL_W16(CPlusCmd, tp->cp_cmd);
+	RTL_R16(CPlusCmd);
+	if (tp->vlgrp)
+		tp->vlgrp->vlan_devices[vid] = NULL;
+	spin_unlock_irqrestore(&tp->lock, flags);
+}
+
+static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
+			       struct sk_buff *skb)
+{
+	u32 opts2 = desc->opts2;
+	int ret;
+
+	if (tp->vlgrp && (opts2 & RxVlanTag)) {
+		rtl8169_rx_hwaccel_skb(skb, tp->vlgrp,
+				       be16_to_cpu(opts2 & 0xffff));
+		ret = 0;
+	} else
+		ret = -1;
+	desc->opts2 = 0;
+	return ret;
+}
+
+#else /* !CONFIG_R8169_VLAN */
+
+static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
+				      struct sk_buff *skb)
+{
+	return 0;
+}
+
+static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
+			       struct sk_buff *skb)
+{
+	return -1;
+}
+
+#endif
+
 static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -674,12 +828,35 @@
 	return 0;
 }
 
+static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+			     void *p)
+{
+        struct rtl8169_private *tp = netdev_priv(dev);
+        unsigned long flags;
+
+        if (regs->len > R8169_REGS_SIZE)
+        	regs->len = R8169_REGS_SIZE;
+
+        spin_lock_irqsave(&tp->lock, flags);
+        memcpy_fromio(p, tp->mmio_addr, regs->len);
+        spin_unlock_irqrestore(&tp->lock, flags);
+}
 
 static struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_drvinfo		= rtl8169_get_drvinfo,
+	.get_regs_len		= rtl8169_get_regs_len,
 	.get_link		= ethtool_op_get_link,
 	.get_settings		= rtl8169_get_settings,
 	.set_settings		= rtl8169_set_settings,
+	.get_rx_csum		= rtl8169_get_rx_csum,
+	.set_rx_csum		= rtl8169_set_rx_csum,
+	.get_tx_csum		= ethtool_op_get_tx_csum,
+	.set_tx_csum		= ethtool_op_set_tx_csum,
+	.get_sg			= ethtool_op_get_sg,
+	.set_sg			= ethtool_op_set_sg,
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= ethtool_op_set_tso,
+	.get_regs		= rtl8169_get_regs,
 };
 
 static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum,
@@ -699,6 +876,7 @@
 		u32 mask;
 		int mac_version;
 	} mac_info[] = {
+		{ 0x1 << 28,	RTL_GIGA_MAC_VER_X },
 		{ 0x1 << 26,	RTL_GIGA_MAC_VER_E },
 		{ 0x1 << 23,	RTL_GIGA_MAC_VER_D }, 
 		{ 0x00000000,	RTL_GIGA_MAC_VER_B } /* Catch-all */
@@ -910,28 +1088,31 @@
 	add_timer(timer);
 }
 
+static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
+				  void *ioaddr)
+{
+	iounmap(ioaddr);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	free_netdev(dev);
+}
+
 static int __devinit
 rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
 		   void **ioaddr_out)
 {
-	void *ioaddr = NULL;
+	void *ioaddr;
 	struct net_device *dev;
 	struct rtl8169_private *tp;
-	unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
-	int rc, i, acpi_idle_state = 0, pm_cap;
-
+	int rc = -ENOMEM, i, acpi_idle_state = 0, pm_cap;
 
-	assert(pdev != NULL);
 	assert(ioaddr_out != NULL);
 
-	*ioaddr_out = NULL;
-	*dev_out = NULL;
-
 	// dev zeroed in alloc_etherdev 
 	dev = alloc_etherdev(sizeof (*tp));
 	if (dev == NULL) {
 		printk(KERN_ERR PFX "unable to alloc new ethernet\n");
-		return -ENOMEM;
+		goto err_out;
 	}
 
 	SET_MODULE_OWNER(dev);
@@ -942,9 +1123,13 @@
 	rc = pci_enable_device(pdev);
 	if (rc) {
 		printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name);
-		goto err_out;
+		goto err_out_free_dev;
 	}
 
+	rc = pci_set_mwi(pdev);
+	if (rc < 0)
+		goto err_out_disable;
+
 	/* save power state before pci_enable_device overwrites it */
 	pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
 	if (pm_cap) {
@@ -955,41 +1140,37 @@
 	} else {
 		printk(KERN_ERR PFX
 		       "Cannot find PowerManagement capability, aborting.\n");
-		goto err_out_free_res;
+		goto err_out_mwi;
 	}
 
-	mmio_start = pci_resource_start(pdev, 1);
-	mmio_end = pci_resource_end(pdev, 1);
-	mmio_flags = pci_resource_flags(pdev, 1);
-	mmio_len = pci_resource_len(pdev, 1);
-
 	// make sure PCI base addr 1 is MMIO
-	if (!(mmio_flags & IORESOURCE_MEM)) {
+	if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
 		printk(KERN_ERR PFX
 		       "region #1 not an MMIO resource, aborting\n");
 		rc = -ENODEV;
-		goto err_out_disable;
+		goto err_out_mwi;
 	}
 	// check for weird/broken PCI region reporting
-	if (mmio_len < RTL_MIN_IO_SIZE) {
+	if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) {
 		printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n");
 		rc = -ENODEV;
-		goto err_out_disable;
+		goto err_out_mwi;
 	}
 
 	rc = pci_request_regions(pdev, MODULENAME);
 	if (rc) {
 		printk(KERN_ERR PFX "%s: could not request regions.\n",
 		       pdev->slot_name);
-		goto err_out_disable;
+		goto err_out_mwi;
 	}
 
 	tp->cp_cmd = PCIMulRW | RxChkSum;
 
 	if ((sizeof(dma_addr_t) > 4) &&
-	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac)
+	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac) {
 		tp->cp_cmd |= PCIDAC;
-	else {
+		dev->features |= NETIF_F_HIGHDMA;
+	} else {
 		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 		if (rc < 0) {
 			printk(KERN_ERR PFX "DMA configuration failed.\n");
@@ -997,12 +1178,10 @@
 		}
 	}
 
-
-	// enable PCI bus-mastering
 	pci_set_master(pdev);
 
 	// ioremap MMIO region 
-	ioaddr = ioremap(mmio_start, mmio_len);
+	ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE);
 	if (ioaddr == NULL) {
 		printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");
 		rc = -EIO;
@@ -1039,26 +1218,35 @@
 	}
 	tp->chipset = i;
 
+	tp->rx_buf_sz = RX_BUF_SIZE;
+
 	*ioaddr_out = ioaddr;
 	*dev_out = dev;
-	return 0;
+out:
+	return rc;
 
 err_out_free_res:
 	pci_release_regions(pdev);
 
+err_out_mwi:
+	pci_clear_mwi(pdev);
+
 err_out_disable:
 	pci_disable_device(pdev);
 
-err_out:
+err_out_free_dev:
 	free_netdev(dev);
-	return rc;
+err_out:
+	*ioaddr_out = NULL;
+	*dev_out = NULL;
+	goto out;
 }
 
 static int __devinit
 rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct net_device *dev = NULL;
-	struct rtl8169_private *tp = NULL;
+	struct rtl8169_private *tp;
 	void *ioaddr = NULL;
 	static int board_idx = -1;
 	static int printed_version = 0;
@@ -1082,8 +1270,6 @@
 
 	tp = dev->priv;
 	assert(ioaddr != NULL);
-	assert(dev != NULL);
-	assert(tp != NULL);
 
 	if (RTL_R8(PHYstatus) & TBI_Enable) {
 		tp->set_speed = rtl8169_set_speed_tbi;
@@ -1108,18 +1294,26 @@
 	dev->open = rtl8169_open;
 	dev->hard_start_xmit = rtl8169_start_xmit;
 	dev->get_stats = rtl8169_get_stats;
-	dev->ethtool_ops = &rtl8169_ethtool_ops;
+	SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
 	dev->stop = rtl8169_close;
 	dev->tx_timeout = rtl8169_tx_timeout;
 	dev->set_multicast_list = rtl8169_set_rx_mode;
 	dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
 	dev->irq = pdev->irq;
 	dev->base_addr = (unsigned long) ioaddr;
+
 #ifdef CONFIG_R8169_NAPI
 	dev->poll = rtl8169_poll;
 	dev->weight = R8169_NAPI_WEIGHT;
 	printk(KERN_INFO PFX "NAPI enabled\n");
 #endif
+
+#ifdef CONFIG_R8169_VLAN
+	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	dev->vlan_rx_register = rtl8169_vlan_rx_register;
+	dev->vlan_rx_kill_vid = rtl8169_vlan_rx_kill_vid;
+#endif
+
 	tp->intr_mask = 0xffff;
 	tp->pci_dev = pdev;
 	tp->mmio_addr = ioaddr;
@@ -1128,10 +1322,7 @@
 
 	rc = register_netdev(dev);
 	if (rc) {
-		iounmap(ioaddr);
-		pci_release_regions(pdev);
-		pci_disable_device(pdev);
-		free_netdev(dev);
+		rtl8169_release_board(pdev, dev, ioaddr);
 		return rc;
 	}
 
@@ -1187,11 +1378,7 @@
 	assert(tp != NULL);
 
 	unregister_netdev(dev);
-	iounmap(tp->mmio_addr);
-	pci_release_regions(pdev);
-
-	pci_disable_device(pdev);
-	free_netdev(dev);
+	rtl8169_release_board(pdev, dev, tp->mmio_addr);
 	pci_set_drvdata(pdev, NULL);
 }
 
@@ -1270,6 +1457,8 @@
 	if (retval < 0)
 		goto err_free_rx;
 
+	INIT_WORK(&tp->task, NULL, dev);
+
 	rtl8169_hw_start(dev);
 
 	rtl8169_request_timer(dev);
@@ -1289,6 +1478,18 @@
 	goto out;
 }
 
+static void rtl8169_hw_reset(void *ioaddr)
+{
+	/* Disable interrupts */
+	RTL_W16(IntrMask, 0x0000);
+
+	/* Reset the chipset */
+	RTL_W8(ChipCmd, CmdReset);
+
+	/* PCI commit */
+	RTL_R8(ChipCmd);
+}
+
 static void
 rtl8169_hw_start(struct net_device *dev)
 {
@@ -1332,8 +1533,6 @@
 		RTL_W16(CPlusCmd, tp->cp_cmd);
 	}
 
-	tp->cur_rx = 0;
-
 	RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
 	RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));
 	RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
@@ -1357,49 +1556,51 @@
 static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
 {
 	desc->addr = 0x0badbadbadbadbadull;
-	desc->status &= ~cpu_to_le32(OWNbit | RsvdMask);
+	desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
 }
 
-static void rtl8169_free_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
-				struct RxDesc *desc)
+static void rtl8169_free_rx_skb(struct rtl8169_private *tp,
+				struct sk_buff **sk_buff, struct RxDesc *desc)
 {
-	pci_unmap_single(pdev, le64_to_cpu(desc->addr), RX_BUF_SIZE,
+	struct pci_dev *pdev = tp->pci_dev;
+
+	pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz,
 			 PCI_DMA_FROMDEVICE);
 	dev_kfree_skb(*sk_buff);
 	*sk_buff = NULL;
 	rtl8169_make_unusable_by_asic(desc);
 }
 
-static inline void rtl8169_return_to_asic(struct RxDesc *desc)
+static inline void rtl8169_return_to_asic(struct RxDesc *desc, int rx_buf_sz)
 {
-	desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE);
+	desc->opts1 |= cpu_to_le32(DescOwn + rx_buf_sz);
 }
 
-static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping)
+static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping,
+					int rx_buf_sz)
 {
 	desc->addr = cpu_to_le64(mapping);
-	desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE);
+	desc->opts1 |= cpu_to_le32(DescOwn + rx_buf_sz);
 }
 
-static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev,
-				struct sk_buff **sk_buff, struct RxDesc *desc)
+static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
+				struct RxDesc *desc, int rx_buf_sz)
 {
 	struct sk_buff *skb;
 	dma_addr_t mapping;
 	int ret = 0;
 
-	skb = dev_alloc_skb(RX_BUF_SIZE);
+	skb = dev_alloc_skb(rx_buf_sz);
 	if (!skb)
 		goto err_out;
 
-	skb->dev = dev;
 	skb_reserve(skb, 2);
 	*sk_buff = skb;
 
-	mapping = pci_map_single(pdev, skb->tail, RX_BUF_SIZE,
+	mapping = pci_map_single(pdev, skb->tail, rx_buf_sz,
 				 PCI_DMA_FROMDEVICE);
 
-	rtl8169_give_to_asic(desc, mapping);
+	rtl8169_give_to_asic(desc, mapping, rx_buf_sz);
 
 out:
 	return ret;
@@ -1416,7 +1617,7 @@
 
 	for (i = 0; i < NUM_RX_DESC; i++) {
 		if (tp->Rx_skbuff[i]) {
-			rtl8169_free_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
+			rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i,
 					    tp->RxDescArray + i);
 		}
 	}
@@ -1433,8 +1634,8 @@
 		if (tp->Rx_skbuff[i])
 			continue;
 			
-		ret = rtl8169_alloc_rx_skb(tp->pci_dev, dev, tp->Rx_skbuff + i,
-					   tp->RxDescArray + i);
+		ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
+					   tp->RxDescArray + i, tp->rx_buf_sz);
 		if (ret < 0)
 			break;
 	}
@@ -1443,19 +1644,21 @@
 
 static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
 {
-	desc->status |= cpu_to_le32(EORbit);
+	desc->opts1 |= cpu_to_le32(RingEnd);
+}
+
+static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
+{
+	tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
 }
 
 static int rtl8169_init_ring(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 
-	tp->cur_rx = tp->dirty_rx = 0;
-	tp->cur_tx = tp->dirty_tx = 0;
-	memset(tp->TxDescArray, 0x0, NUM_TX_DESC * sizeof (struct TxDesc));
-	memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof (struct RxDesc));
+	rtl8169_init_ring_indexes(tp);
 
-	memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *));
+	memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
 	memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
 
 	if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
@@ -1470,120 +1673,289 @@
 	return -ENOMEM;
 }
 
-static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
+static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb,
 				 struct TxDesc *desc)
 {
-	u32 len = sk_buff[0]->len;
+	unsigned int len = tx_skb->len;
 
-	pci_unmap_single(pdev, le64_to_cpu(desc->addr),
-			 len < ETH_ZLEN ? ETH_ZLEN : len, PCI_DMA_TODEVICE);
+	pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE);
+	desc->opts2 = 0x00;
 	desc->addr = 0x00;
-	*sk_buff = NULL;
+	tx_skb->len = 0;
 }
 
-static void
-rtl8169_tx_clear(struct rtl8169_private *tp)
+static void rtl8169_tx_clear(struct rtl8169_private *tp)
 {
-	int i;
+	unsigned int i;
 
-	tp->cur_tx = 0;
-	for (i = 0; i < NUM_TX_DESC; i++) {
-		struct sk_buff *skb = tp->Tx_skbuff[i];
+	for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) {
+		unsigned int entry = i % NUM_TX_DESC;
+		struct ring_info *tx_skb = tp->tx_skb + entry;
+		unsigned int len = tx_skb->len;
 
-		if (skb) {
-			rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + i,
-					     tp->TxDescArray + i);
-			dev_kfree_skb(skb);
+		if (len) {
+			struct sk_buff *skb = tx_skb->skb;
+
+			rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb,
+					     tp->TxDescArray + entry);
+			if (skb) {
+				dev_kfree_skb(skb);
+				tx_skb->skb = NULL;
+			}
 			tp->stats.tx_dropped++;
 		}
 	}
+	tp->cur_tx = tp->dirty_tx = 0;
 }
 
-static void
-rtl8169_tx_timeout(struct net_device *dev)
+static void rtl8169_schedule_work(struct net_device *dev, void (*task)(void *))
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
-	void *ioaddr = tp->mmio_addr;
-	u8 tmp8;
 
-	printk(KERN_INFO "%s: TX Timeout\n", dev->name);
-	/* disable Tx, if not already */
-	tmp8 = RTL_R8(ChipCmd);
-	if (tmp8 & CmdTxEnb)
-		RTL_W8(ChipCmd, tmp8 & ~CmdTxEnb);
+	PREPARE_WORK(&tp->task, task, dev);
+	schedule_delayed_work(&tp->task, 4);
+}
 
-	/* Disable interrupts by clearing the interrupt mask. */
-	RTL_W16(IntrMask, 0x0000);
+static void rtl8169_wait_for_quiescence(struct net_device *dev)
+{
+	synchronize_irq(dev->irq);
 
-	/* Stop a shared interrupt from scavenging while we are. */
-	spin_lock_irq(&tp->lock);
-	rtl8169_tx_clear(tp);
-	spin_unlock_irq(&tp->lock);
+	/* Wait for any pending NAPI task to complete */
+	netif_poll_disable(dev);
+}
 
-	/* ...and finally, reset everything */
-	rtl8169_hw_start(dev);
+static void rtl8169_reinit_task(void *_data)
+{
+	struct net_device *dev = _data;
+	int ret;
 
-	netif_wake_queue(dev);
+	if (netif_running(dev)) {
+		rtl8169_wait_for_quiescence(dev);
+		rtl8169_close(dev);
+	}
+
+	ret = rtl8169_open(dev);
+	if (unlikely(ret < 0)) {
+		if (net_ratelimit()) {
+			printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
+			       " Rescheduling.\n", dev->name, ret);
+		}
+		rtl8169_schedule_work(dev, rtl8169_reinit_task);
+	}
 }
 
-static int
-rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void rtl8169_reset_task(void *_data)
 {
+	struct net_device *dev = _data;
 	struct rtl8169_private *tp = netdev_priv(dev);
-	void *ioaddr = tp->mmio_addr;
-	unsigned int entry = tp->cur_tx % NUM_TX_DESC;
-	u32 len = skb->len;
 
-	if (unlikely(skb->len < ETH_ZLEN)) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (!skb)
-			goto err_update_stats;
-		len = ETH_ZLEN;
+	if (!netif_running(dev))
+		return;
+
+	rtl8169_wait_for_quiescence(dev);
+
+	rtl8169_rx_interrupt(dev, tp, tp->mmio_addr);
+	rtl8169_tx_clear(tp);
+
+	if (tp->dirty_rx == tp->cur_rx) {
+		rtl8169_init_ring_indexes(tp);
+		rtl8169_hw_start(dev);
+		netif_wake_queue(dev);
+	} else {
+		if (net_ratelimit()) {
+			printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
+			       dev->name);
+		}
+		rtl8169_schedule_work(dev, rtl8169_reset_task);
 	}
-	
-	if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) {
+}
+
+static void rtl8169_tx_timeout(struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+
+	rtl8169_hw_reset(tp->mmio_addr);
+
+	/* Let's wait a bit while any (async) irq lands on */
+	rtl8169_schedule_work(dev, rtl8169_reset_task);
+}
+
+static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
+			      u32 opts1)
+{
+	struct skb_shared_info *info = skb_shinfo(skb);
+	unsigned int cur_frag, entry;
+	struct TxDesc *txd;
+
+	entry = tp->cur_tx;
+	for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
+		skb_frag_t *frag = info->frags + cur_frag;
 		dma_addr_t mapping;
-		u32 status;
+		u32 status, len;
+		void *addr;
 
-		mapping = pci_map_single(tp->pci_dev, skb->data, len,
-					 PCI_DMA_TODEVICE);
+		entry = (entry + 1) % NUM_TX_DESC;
 
-		tp->Tx_skbuff[entry] = skb;
-		tp->TxDescArray[entry].addr = cpu_to_le64(mapping);
+		txd = tp->TxDescArray + entry;
+		len = frag->size;
+		addr = ((void *) page_address(frag->page)) + frag->page_offset;
+		mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE);
 
-		/* anti gcc 2.95.3 bugware */
-		status = OWNbit | FSbit | LSbit | len |
-			 (EORbit * !((entry + 1) % NUM_TX_DESC));
-		tp->TxDescArray[entry].status = cpu_to_le32(status);
-			
-		RTL_W8(TxPoll, 0x40);	//set polling bit
+		/* anti gcc 2.95.3 bugware (sic) */
+		status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
 
-		dev->trans_start = jiffies;
+		txd->opts1 = cpu_to_le32(status);
+		txd->addr = cpu_to_le64(mapping);
 
-		tp->cur_tx++;
-		smp_wmb();
-	} else
-		goto err_drop;
+		tp->tx_skb[entry].len = len;
+	}
+
+	if (cur_frag) {
+		tp->tx_skb[entry].skb = skb;
+		txd->opts1 |= cpu_to_le32(LastFrag);
+	}
+
+	return cur_frag;
+}
+
+static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
+{
+	if (dev->features & NETIF_F_TSO) {
+		u32 mss = skb_shinfo(skb)->tso_size;
 
-	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) {
-		u32 dirty = tp->dirty_tx;
+		if (mss)
+			return LargeSend | ((mss & MSSMask) << MSSShift);
+	}
+	if (skb->ip_summed == CHECKSUM_HW) {
+		const struct iphdr *ip = skb->nh.iph;
+
+		if (ip->protocol == IPPROTO_TCP)
+			return IPCS | TCPCS;
+		else if (ip->protocol == IPPROTO_UDP)
+			return IPCS | UDPCS;
+		WARN_ON(1);	/* we need a WARN() */
+	}
+	return 0;
+}
+
+static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC;
+	struct TxDesc *txd = tp->TxDescArray + entry;
+	void *ioaddr = tp->mmio_addr;
+	dma_addr_t mapping;
+	u32 status, len;
+	u32 opts1;
+	int ret = 0;
 	
+	if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
+		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
+		       dev->name);
+		goto err_stop;
+	}
+
+	if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
+		goto err_stop;
+
+	opts1 = DescOwn | rtl8169_tso_csum(skb, dev);
+
+	frags = rtl8169_xmit_frags(tp, skb, opts1);
+	if (frags) {
+		len = skb_headlen(skb);
+		opts1 |= FirstFrag;
+	} else {
+		len = skb->len;
+
+		if (unlikely(len < ETH_ZLEN)) {
+			skb = skb_padto(skb, ETH_ZLEN);
+			if (!skb)
+				goto err_update_stats;
+			len = ETH_ZLEN;
+		}
+
+		opts1 |= FirstFrag | LastFrag;
+		tp->tx_skb[entry].skb = skb;
+	}
+
+	mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE);
+
+	tp->tx_skb[entry].len = len;
+	txd->addr = cpu_to_le64(mapping);
+	txd->opts2 = rtl8169_tx_vlan_tag(tp, skb);
+
+	wmb();
+
+	/* anti gcc 2.95.3 bugware (sic) */
+	status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
+	txd->opts1 = cpu_to_le32(status);
+
+	dev->trans_start = jiffies;
+
+	tp->cur_tx += frags + 1;
+
+	smp_wmb();
+
+	RTL_W8(TxPoll, 0x40);	//set polling bit
+
+	if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) {
 		netif_stop_queue(dev);
 		smp_rmb();
-		if (dirty != tp->dirty_tx)
+		if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)
 			netif_wake_queue(dev);
 	}
 
 out:
-	return 0;
+	return ret;
 
-err_drop:
-	dev_kfree_skb(skb);
+err_stop:
+	netif_stop_queue(dev);
+	ret = 1;
 err_update_stats:
 	tp->stats.tx_dropped++;
 	goto out;
 }
 
+static void rtl8169_pcierr_interrupt(struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	struct pci_dev *pdev = tp->pci_dev;
+	void *ioaddr = tp->mmio_addr;
+	u16 pci_status, pci_cmd;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
+	pci_read_config_word(pdev, PCI_STATUS, &pci_status);
+
+	printk(KERN_ERR PFX "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n",
+	       dev->name, pci_cmd, pci_status);
+
+	/*
+	 * The recovery sequence below admits a very elaborated explanation:
+	 * - it seems to work;
+	 * - I did not see what else could be done.
+	 *
+	 * Feel free to adjust to your needs.
+	 */
+	pci_write_config_word(pdev, PCI_COMMAND,
+			      pci_cmd | PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+
+	pci_write_config_word(pdev, PCI_STATUS,
+		pci_status & (PCI_STATUS_DETECTED_PARITY |
+		PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT |
+		PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
+
+	/* The infamous DAC f*ckup only happens at boot time */
+	if ((tp->cp_cmd & PCIDAC) && (tp->dirty_rx == tp->cur_rx == 0)) {
+		printk(KERN_INFO PFX "%s: disabling PCI DAC.\n", dev->name);
+		tp->cp_cmd &= ~PCIDAC;
+		RTL_W16(CPlusCmd, tp->cp_cmd);
+		dev->features &= ~NETIF_F_HIGHDMA;
+		rtl8169_schedule_work(dev, rtl8169_reinit_task);
+	}
+
+	rtl8169_hw_reset(ioaddr);
+}
+
 static void
 rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
@@ -1600,22 +1972,24 @@
 
 	while (tx_left > 0) {
 		unsigned int entry = dirty_tx % NUM_TX_DESC;
-		struct sk_buff *skb = tp->Tx_skbuff[entry];
+		struct ring_info *tx_skb = tp->tx_skb + entry;
+		u32 len = tx_skb->len;
 		u32 status;
 
 		rmb();
-		status = le32_to_cpu(tp->TxDescArray[entry].status);
-		if (status & OWNbit)
+		status = le32_to_cpu(tp->TxDescArray[entry].opts1);
+		if (status & DescOwn)
 			break;
 
-		/* FIXME: is it really accurate for TxErr ? */
-		tp->stats.tx_bytes += skb->len >= ETH_ZLEN ?
-				      skb->len : ETH_ZLEN;
+		tp->stats.tx_bytes += len;
 		tp->stats.tx_packets++;
-		rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + entry,
-				     tp->TxDescArray + entry);
-		dev_kfree_skb_irq(skb);
-		tp->Tx_skbuff[entry] = NULL;
+
+		rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry);
+
+		if (status & LastFrag) {
+			dev_kfree_skb_irq(tx_skb->skb);
+			tx_skb->skb = NULL;
+		}
 		dirty_tx++;
 		tx_left--;
 	}
@@ -1623,14 +1997,28 @@
 	if (tp->dirty_tx != dirty_tx) {
 		tp->dirty_tx = dirty_tx;
 		smp_wmb();
-		if (netif_queue_stopped(dev))
+		if (netif_queue_stopped(dev) &&
+		    (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) {
 			netif_wake_queue(dev);
+		}
 	}
 }
 
+static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
+{
+	u32 opts1 = desc->opts1;
+	u32 status = opts1 & RxProtoMask;
+
+	if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
+	    ((status == RxProtoUDP) && !(opts1 & UDPFail)) ||
+	    ((status == RxProtoIP) && !(opts1 & IPFail)))
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	else
+		skb->ip_summed = CHECKSUM_NONE;
+}
+
 static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
-				      struct RxDesc *desc,
-				      struct net_device *dev)
+				      struct RxDesc *desc, int rx_buf_sz)
 {
 	int ret = -1;
 
@@ -1639,11 +2027,10 @@
 
 		skb = dev_alloc_skb(pkt_size + 2);
 		if (skb) {
-			skb->dev = dev;
 			skb_reserve(skb, 2);
 			eth_copy_and_sum(skb, sk_buff[0]->tail, pkt_size, 0);
 			*sk_buff = skb;
-			rtl8169_return_to_asic(desc);
+			rtl8169_return_to_asic(desc, rx_buf_sz);
 			ret = 0;
 		}
 	}
@@ -1670,9 +2057,9 @@
 		u32 status;
 
 		rmb();
-		status = le32_to_cpu(tp->RxDescArray[entry].status);
+		status = le32_to_cpu(tp->RxDescArray[entry].opts1);
 
-		if (status & OWNbit)
+		if (status & DescOwn)
 			break;
 		if (status & RxRES) {
 			printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name);
@@ -1688,22 +2075,27 @@
 			void (*pci_action)(struct pci_dev *, dma_addr_t,
 				size_t, int) = pci_dma_sync_single_for_device;
 
-
+			rtl8169_rx_csum(skb, desc);
+			
 			pci_dma_sync_single_for_cpu(tp->pci_dev,
-				le64_to_cpu(desc->addr), RX_BUF_SIZE,
+				le64_to_cpu(desc->addr), tp->rx_buf_sz,
 				PCI_DMA_FROMDEVICE);
 
-			if (rtl8169_try_rx_copy(&skb, pkt_size, desc, dev)) {
+			if (rtl8169_try_rx_copy(&skb, pkt_size, desc,
+						tp->rx_buf_sz)) {
 				pci_action = pci_unmap_single;
 				tp->Rx_skbuff[entry] = NULL;
 			}
 
 			pci_action(tp->pci_dev, le64_to_cpu(desc->addr),
-				   RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+				   tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
 
+			skb->dev = dev;
 			skb_put(skb, pkt_size);
 			skb->protocol = eth_type_trans(skb, dev);
-			rtl8169_rx_skb(skb);
+
+			if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0)
+				rtl8169_rx_skb(skb);
 
 			dev->last_rx = jiffies;
 			tp->stats.rx_bytes += pkt_size;
@@ -1748,6 +2140,9 @@
 	int status = 0;
 	int handled = 0;
 
+	if (unlikely(!netif_running(dev)))
+		goto out;
+
 	do {
 		status = RTL_R16(IntrStatus);
 
@@ -1765,11 +2160,7 @@
 			break;
 
 		if (unlikely(status & SYSErr)) {
-			printk(KERN_ERR PFX "%s: PCI error (status: 0x%04x)."
-			       " Device disabled.\n", dev->name, status);
-			RTL_W8(ChipCmd, 0x00);
-			RTL_W16(IntrMask, 0x0000);
-			RTL_R16(IntrMask);
+			rtl8169_pcierr_interrupt(dev);
 			break;
 		}
 
@@ -1783,7 +2174,7 @@
 		if (likely(netif_rx_schedule_prep(dev)))
 			__netif_rx_schedule(dev);
 		else {
-			printk(KERN_INFO "%s: interrupt %x taken in poll\n",
+			printk(KERN_INFO "%s: interrupt %04x taken in poll\n",
 			       dev->name, status);	
 		}
 		break;
@@ -1806,6 +2197,7 @@
 		/* Clear all interrupt sources. */
 		RTL_W16(IntrStatus, 0xffff);
 	}
+out:
 	return IRQ_RETVAL(handled);
 }
 
@@ -1848,6 +2240,8 @@
 
 	netif_stop_queue(dev);
 
+	flush_scheduled_work();
+
 	rtl8169_delete_timer(dev);
 
 	spin_lock_irq(&tp->lock);
@@ -1866,6 +2260,8 @@
 
 	synchronize_irq(dev->irq);
 	free_irq(dev->irq, dev);
+
+	netif_poll_disable(dev);
 
 	rtl8169_tx_clear(tp);
 
diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c
--- a/drivers/net/sis900.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/sis900.c	2004-10-10 22:15:16 -07:00
@@ -140,9 +140,9 @@
 };
 
 typedef struct _BufferDesc {
-	u32	link;
-	u32	cmdsts;
-	u32	bufptr;
+	u32 link;
+	u32 cmdsts;
+	u32 bufptr;
 } BufferDesc;
 
 struct sis900_private {
@@ -156,7 +156,7 @@
 	unsigned int cur_phy;
 
 	struct timer_list timer; /* Link status detection timer. */
-	u8     autong_complete; /* 1: auto-negotiate complete  */
+	u8 autong_complete; /* 1: auto-negotiate complete  */
 
 	unsigned int cur_rx, dirty_rx; /* producer/comsumer pointers for Tx/Rx ring */
 	unsigned int cur_tx, dirty_tx;
@@ -170,7 +170,7 @@
 	dma_addr_t tx_ring_dma;
 	dma_addr_t rx_ring_dma;
 
-	unsigned int tx_full;			/* The Tx queue is full.    */
+	unsigned int tx_full; /* The Tx queue is full. */
 	u8 host_bridge_rev;
 	u32 pci_state[16];
 };
@@ -256,19 +256,19 @@
  *	MAC address is read into @net_dev->dev_addr.
  */
 
-static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
+static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
+					struct net_device *net_dev)
 {
 	struct pci_dev *isa_bridge = NULL;
 	u8 reg;
 	int i;
 
-	isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, 0x0008, isa_bridge);
+	isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, isa_bridge);
+	if (!isa_bridge)
+		isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge);
 	if (!isa_bridge) {
-		isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge);
-		if (!isa_bridge) {
-			printk("%s: Can not find ISA bridge\n", net_dev->name);
-			return 0;
-		}
+		printk("%s: Can not find ISA bridge\n", net_dev->name);
+		return 0;
 	}
 	pci_read_config_byte(isa_bridge, 0x48, &reg);
 	pci_write_config_byte(isa_bridge, 0x48, reg | 0x40);
@@ -278,6 +278,7 @@
 		((u8 *)(net_dev->dev_addr))[i] = inb(0x71); 
 	}
 	pci_write_config_byte(isa_bridge, 0x48, reg & ~0x40);
+	pci_dev_put(isa_bridge);
 
 	return 1;
 }
@@ -293,7 +294,8 @@
  *	@net_dev->dev_addr.
  */
 
-static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
+static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
+					struct net_device *net_dev)
 {
 	long ioaddr = net_dev->base_addr;
 	u32 rfcrSave;
@@ -335,7 +337,8 @@
  *	MAC address is read into @net_dev->dev_addr.
  */
 
-static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
+static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
+					struct net_device *net_dev)
 {
 	long ioaddr = net_dev->base_addr;
 	long ee_addr = ioaddr + mear;
@@ -372,7 +375,8 @@
  *	ie: sis900_open(), sis900_start_xmit(), sis900_close(), etc.
  */
 
-static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
+static int __devinit sis900_probe(struct pci_dev *pci_dev,
+				const struct pci_device_id *pci_id)
 {
 	struct sis900_private *sis_priv;
 	struct net_device *net_dev;
@@ -485,9 +489,11 @@
 	}
 
 	/* save our host bridge revision */
-	dev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, NULL);
-	if (dev)
+	dev = pci_get_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, NULL);
+	if (dev) {
 		pci_read_config_byte(dev, PCI_CLASS_REVISION, &sis_priv->host_bridge_rev);
+		pci_dev_put(dev);
+	}
 
 	/* print some information about our NIC */
 	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", net_dev->name,
@@ -523,7 +529,7 @@
  *	return error if it failed to found.
  */
 
-static int __init sis900_mii_probe (struct net_device * net_dev)
+static int __init sis900_mii_probe(struct net_device * net_dev)
 {
 	struct sis900_private * sis_priv = net_dev->priv;
 	u16 poll_bit = MII_STAT_LINK, status = 0;
@@ -573,9 +579,10 @@
 				mii_phy->phy_types = mii_chip_table[i].phy_types;
 				if (mii_chip_table[i].phy_types == MIX)
 					mii_phy->phy_types =
-						(mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME;
+					    (mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME;
 				printk(KERN_INFO "%s: %s transceiver found at address %d.\n",
-				       net_dev->name, mii_chip_table[i].name, phy_addr);
+				       net_dev->name, mii_chip_table[i].name,
+				       phy_addr);
 				break;
 			}
 			
@@ -588,7 +595,7 @@
 	
 	if (sis_priv->mii == NULL) {
 		printk(KERN_INFO "%s: No MII transceivers found!\n",
-		       net_dev->name);
+			net_dev->name);
 		return 0;
 	}
 
@@ -612,7 +619,8 @@
 
 			poll_bit ^= (mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS) & poll_bit);
 			if (time_after_eq(jiffies, timeout)) {
-				printk(KERN_WARNING "%s: reset phy and link down now\n", net_dev->name);
+				printk(KERN_WARNING "%s: reset phy and link down now\n",
+					net_dev->name);
 				return -ETIME;
 			}
 		}
@@ -648,38 +656,41 @@
 static u16 sis900_default_phy(struct net_device * net_dev)
 {
 	struct sis900_private * sis_priv = net_dev->priv;
- 	struct mii_phy *phy = NULL, *phy_home = NULL, *default_phy = NULL, *phy_lan = NULL;
+ 	struct mii_phy *phy = NULL, *phy_home = NULL, 
+		*default_phy = NULL, *phy_lan = NULL;
 	u16 status;
 
-        for( phy=sis_priv->first_mii; phy; phy=phy->next ){
+        for (phy=sis_priv->first_mii; phy; phy=phy->next) {
 		status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);
 		status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);
 
 		/* Link ON & Not select default PHY & not ghost PHY */
-		 if ( (status & MII_STAT_LINK) && !default_phy && (phy->phy_types != UNKNOWN) )
+		 if ((status & MII_STAT_LINK) && !default_phy &&
+					(phy->phy_types != UNKNOWN))
 		 	default_phy = phy;
-		 else{
+		 else {
 			status = mdio_read(net_dev, phy->phy_addr, MII_CONTROL);
 			mdio_write(net_dev, phy->phy_addr, MII_CONTROL,
 				status | MII_CNTL_AUTO | MII_CNTL_ISOLATE);
-			if( phy->phy_types == HOME )
+			if (phy->phy_types == HOME)
 				phy_home = phy;
-			else if (phy->phy_types == LAN)
+			else if(phy->phy_types == LAN)
 				phy_lan = phy;
 		 }
 	}
 
-	if( !default_phy && phy_home )
+	if (!default_phy && phy_home)
 		default_phy = phy_home;
-	else if( !default_phy && phy_lan )
+	else if (!default_phy && phy_lan)
 		default_phy = phy_lan;
-	else if ( !default_phy )
+	else if (!default_phy)
 		default_phy = sis_priv->first_mii;
 
-	if( sis_priv->mii != default_phy ){
+	if (sis_priv->mii != default_phy) {
 		sis_priv->mii = default_phy;
 		sis_priv->cur_phy = default_phy->phy_addr;
-		printk(KERN_INFO "%s: Using transceiver found at address %d as default\n", net_dev->name,sis_priv->cur_phy);
+		printk(KERN_INFO "%s: Using transceiver found at address %d as default\n",
+					net_dev->name,sis_priv->cur_phy);
 	}
 	
 	status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);
@@ -702,7 +713,7 @@
  *	mii status register. It's necessary before auto-negotiate.
  */
  
-static void sis900_set_capability( struct net_device *net_dev , struct mii_phy *phy )
+static void sis900_set_capability(struct net_device *net_dev, struct mii_phy *phy)
 {
 	u16 cap;
 	u16 status;
@@ -852,7 +863,8 @@
  *	please see SiS7014 or ICS spec
  */
 
-static void mdio_write(struct net_device *net_dev, int phy_id, int location, int value)
+static void mdio_write(struct net_device *net_dev, int phy_id, int location,
+			int value)
 {
 	long mdio_addr = net_dev->base_addr + mear;
 	int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
@@ -940,7 +952,8 @@
 	pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
 	sis630_set_eq(net_dev, revision);
 
-	ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev);
+	ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ,
+						net_dev->name, net_dev);
 	if (ret)
 		return ret;
 
@@ -1137,48 +1150,55 @@
 		return;
 
 	if (netif_carrier_ok(net_dev)) {
-		reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
-		mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (0x2200 | reg14h) & 0xBFFF);
+		reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
+		mdio_write(net_dev, sis_priv->cur_phy, MII_RESV,
+					(0x2200 | reg14h) & 0xBFFF);
 		for (i=0; i < maxcount; i++) {
-			eq_value=(0x00F8 & mdio_read(net_dev, sis_priv->cur_phy, MII_RESV)) >> 3;
+			eq_value = (0x00F8 & mdio_read(net_dev,
+					sis_priv->cur_phy, MII_RESV)) >> 3;
 			if (i == 0)
 				max_value=min_value=eq_value;
-			max_value=(eq_value > max_value) ? eq_value : max_value;
-			min_value=(eq_value < min_value) ? eq_value : min_value;
+			max_value = (eq_value > max_value) ?
+						eq_value : max_value;
+			min_value = (eq_value < min_value) ?
+						eq_value : min_value;
 		}
 		/* 630E rule to determine the equalizer value */
 		if (revision == SIS630E_900_REV || revision == SIS630EA1_900_REV ||
 		    revision == SIS630ET_900_REV) {
 			if (max_value < 5)
-				eq_value=max_value;
+				eq_value = max_value;
 			else if (max_value >= 5 && max_value < 15)
-				eq_value=(max_value == min_value) ? max_value+2 : max_value+1;
+				eq_value = (max_value == min_value) ?
+						max_value+2 : max_value+1;
 			else if (max_value >= 15)
-				eq_value=(max_value == min_value) ? max_value+6 : max_value+5;
+				eq_value=(max_value == min_value) ?
+						max_value+6 : max_value+5;
 		}
 		/* 630B0&B1 rule to determine the equalizer value */
 		if (revision == SIS630A_900_REV && 
 		    (sis_priv->host_bridge_rev == SIS630B0 || 
 		     sis_priv->host_bridge_rev == SIS630B1)) {
 			if (max_value == 0)
-				eq_value=3;
+				eq_value = 3;
 			else
-				eq_value=(max_value+min_value+1)/2;
+				eq_value = (max_value + min_value + 1)/2;
 		}
 		/* write equalizer value and setting */
-		reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
-		reg14h=(reg14h & 0xFF07) | ((eq_value << 3) & 0x00F8);
-		reg14h=(reg14h | 0x6000) & 0xFDFF;
+		reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
+		reg14h = (reg14h & 0xFF07) | ((eq_value << 3) & 0x00F8);
+		reg14h = (reg14h | 0x6000) & 0xFDFF;
 		mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, reg14h);
-	}
-	else {
-		reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
+	} else {
+		reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
 		if (revision == SIS630A_900_REV && 
 		    (sis_priv->host_bridge_rev == SIS630B0 || 
 		     sis_priv->host_bridge_rev == SIS630B1)) 
-			mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (reg14h | 0x2200) & 0xBFFF);
+			mdio_write(net_dev, sis_priv->cur_phy, MII_RESV,
+						(reg14h | 0x2200) & 0xBFFF);
 		else
-			mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (reg14h | 0x2000) & 0xBFFF);
+			mdio_write(net_dev, sis_priv->cur_phy, MII_RESV,
+						(reg14h | 0x2000) & 0xBFFF);
 	}
 	return;
 }
@@ -1206,7 +1226,8 @@
 		sis900_read_mode(net_dev, &speed, &duplex);
 		if (duplex){
 			sis900_set_mode(net_dev->base_addr, speed, duplex);
-			pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
+			pci_read_config_byte(sis_priv->pci_dev,
+						PCI_CLASS_REVISION, &revision);
 			sis630_set_eq(net_dev, revision);
 			netif_start_queue(net_dev);
 		}
@@ -1230,9 +1251,8 @@
 			sis900_check_mode(net_dev, mii_phy);
 			netif_carrier_on(net_dev);
 		}
-	}
+	} else {
 	/* Link ON -> OFF */
-	else {
                 if (!(status & MII_STAT_LINK)){
                 	netif_carrier_off(net_dev);
                 	printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
@@ -1242,7 +1262,8 @@
 			    ((mii_phy->phy_id1 & 0xFFF0) == 0x8000))
                			sis900_reset_phy(net_dev,  sis_priv->cur_phy);
   
-                	pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
+                	pci_read_config_byte(sis_priv->pci_dev,
+					PCI_CLASS_REVISION, &revision);
 			sis630_set_eq(net_dev, revision);
   
                 	goto LookForLink;
@@ -1265,18 +1286,18 @@
  *	and autong_complete should be set to 1.
  */
 
-static void sis900_check_mode (struct net_device *net_dev, struct mii_phy *mii_phy)
+static void sis900_check_mode(struct net_device *net_dev, struct mii_phy *mii_phy)
 {
 	struct sis900_private *sis_priv = net_dev->priv;
 	long ioaddr = net_dev->base_addr;
 	int speed, duplex;
 
-	if( mii_phy->phy_types == LAN  ){
-		outl( ~EXD & inl( ioaddr + cfg ), ioaddr + cfg);
+	if (mii_phy->phy_types == LAN) {
+		outl(~EXD & inl(ioaddr + cfg), ioaddr + cfg);
 		sis900_set_capability(net_dev , mii_phy);
 		sis900_auto_negotiate(net_dev, sis_priv->cur_phy);
-	}else{
-		outl(EXD | inl( ioaddr + cfg ), ioaddr + cfg);
+	} else {
+		outl(EXD | inl(ioaddr + cfg), ioaddr + cfg);
 		speed = HW_SPEED_HOME;
 		duplex = FDX_CAPABLE_HALF_SELECTED;
 		sis900_set_mode(ioaddr, speed, duplex);
@@ -1301,20 +1322,20 @@
 {
 	u32 tx_flags = 0, rx_flags = 0;
 
-	if( inl(ioaddr + cfg) & EDB_MASTER_EN ){
-		tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
+	if (inl(ioaddr + cfg) & EDB_MASTER_EN) {
+		tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) |
+					(TX_FILL_THRESH << TxFILLT_shift);
 		rx_flags = DMA_BURST_64 << RxMXDMA_shift;
-	}
-	else{
-		tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
+	} else {
+		tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) |
+					(TX_FILL_THRESH << TxFILLT_shift);
 		rx_flags = DMA_BURST_512 << RxMXDMA_shift;
 	}
 
-	if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS ) {
+	if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
 		rx_flags |= (RxDRNT_10 << RxDRNT_shift);
 		tx_flags |= (TxDRNT_10 << TxDRNT_shift);
-	}
-	else {
+	} else {
 		rx_flags |= (RxDRNT_100 << RxDRNT_shift);
 		tx_flags |= (TxDRNT_100 << TxDRNT_shift);
 	}
@@ -1404,19 +1425,19 @@
 	sis_priv->autong_complete = 1;
 
 	/* Workaround for Realtek RTL8201 PHY issue */
-	if((phy->phy_id0 == 0x0000) && ((phy->phy_id1 & 0xFFF0) == 0x8200)){
-		if(mdio_read(net_dev, phy_addr, MII_CONTROL) & MII_CNTL_FDX)
+	if ((phy->phy_id0 == 0x0000) && ((phy->phy_id1 & 0xFFF0) == 0x8200)) {
+		if (mdio_read(net_dev, phy_addr, MII_CONTROL) & MII_CNTL_FDX)
 			*duplex = FDX_CAPABLE_FULL_SELECTED;
-		if(mdio_read(net_dev, phy_addr, 0x0019) & 0x01)
+		if (mdio_read(net_dev, phy_addr, 0x0019) & 0x01)
 			*speed = HW_SPEED_100_MBPS;
 	}
 
 	printk(KERN_INFO "%s: Media Link On %s %s-duplex \n",
-	       net_dev->name,
-	       *speed == HW_SPEED_100_MBPS ?
-	       "100mbps" : "10mbps",
-	       *duplex == FDX_CAPABLE_FULL_SELECTED ?
-	       "full" : "half");
+	       				net_dev->name,
+	       				*speed == HW_SPEED_100_MBPS ?
+	       					"100mbps" : "10mbps",
+	       				*duplex == FDX_CAPABLE_FULL_SELECTED ?
+	       					"full" : "half");
 }
 
 /**
@@ -1678,13 +1699,13 @@
 			sis_priv->stats.rx_bytes += rx_size;
 			sis_priv->stats.rx_packets++;
 
-			/* refill the Rx buffer, what if there is not enought memory for
-			   new socket buffer ?? */
+			/* refill the Rx buffer, what if there is not enought
+			 * memory for new socket buffer ?? */
 			if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
-				/* not enough memory for skbuff, this makes a "hole"
-				   on the buffer ring, it is not clear how the
-				   hardware will react to this kind of degenerated
-				   buffer */
+				/* not enough memory for skbuff, this makes a
+				 * "hole" on the buffer ring, it is not clear
+				 * how the hardware will react to this kind
+				 * of degenerated buffer */
 				printk(KERN_INFO "%s: Memory squeeze,"
 				       "deferring packet.\n",
 				       net_dev->name);
@@ -1708,8 +1729,8 @@
 		rx_status = sis_priv->rx_ring[entry].cmdsts;
 	} // while
 
-	/* refill the Rx buffer, what if the rate of refilling is slower than 
-	   consuming ?? */
+	/* refill the Rx buffer, what if the rate of refilling is slower
+	 * than consuming ?? */
 	for (;sis_priv->cur_rx - sis_priv->dirty_rx > 0; sis_priv->dirty_rx++) {
 		struct sk_buff *skb;
 
@@ -1717,10 +1738,10 @@
 
 		if (sis_priv->rx_skbuff[entry] == NULL) {
 			if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
-				/* not enough memory for skbuff, this makes a "hole"
-				   on the buffer ring, it is not clear how the 
-				   hardware will react to this kind of degenerated 
-				   buffer */
+				/* not enough memory for skbuff, this makes a
+				 * "hole" on the buffer ring, it is not clear
+				 * how the hardware will react to this kind
+				 * of degenerated buffer */
 				printk(KERN_INFO "%s: Memory squeeze,"
 				       "deferring packet.\n",
 				       net_dev->name);
@@ -1765,8 +1786,8 @@
 
 		if (tx_status & OWN) {
 			/* The packet is not transmitted yet (owned by hardware) !
-			   Note: the interrupt is generated only when Tx Machine
-			   is idle, so this is an almost impossible case */
+			 * Note: the interrupt is generated only when Tx Machine
+			 * is idle, so this is an almost impossible case */
 			break;
 		}
 
@@ -1804,8 +1825,8 @@
 
 	if (sis_priv->tx_full && netif_queue_stopped(net_dev) &&
 	    sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) {
-		/* The ring is no longer full, clear tx_full and schedule more transmission
-		   by netif_wake_queue(net_dev) */
+		/* The ring is no longer full, clear tx_full and schedule
+		 * more transmission by netif_wake_queue(net_dev) */
 		sis_priv->tx_full = 0;
 		netif_wake_queue (net_dev);
 	}
@@ -1819,8 +1840,7 @@
  *	free Tx and RX socket buffer
  */
 
-static int
-sis900_close(struct net_device *net_dev)
+static int sis900_close(struct net_device *net_dev)
 {
 	long ioaddr = net_dev->base_addr;
 	struct sis900_private *sis_priv = net_dev->priv;
@@ -1956,27 +1976,28 @@
 
 	if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
 		/* we switch on the ifmap->port field. I couldn't find anything
-		   like a definition or standard for the values of that field.
-		   I think the meaning of those values is device specific. But
-		   since I would like to change the media type via the ifconfig
-		   command I use the definition from linux/netdevice.h 
-		   (which seems to be different from the ifport(pcmcia) definition) 
-		*/
+		 * like a definition or standard for the values of that field.
+		 * I think the meaning of those values is device specific. But
+		 * since I would like to change the media type via the ifconfig
+		 * command I use the definition from linux/netdevice.h 
+		 * (which seems to be different from the ifport(pcmcia) definition) */
 		switch(map->port){
 		case IF_PORT_UNKNOWN: /* use auto here */   
 			dev->if_port = map->port;
-			/* we are going to change the media type, so the Link will
-			   be temporary down and we need to reflect that here. When
-			   the Link comes up again, it will be sensed by the sis_timer
-			   procedure, which also does all the rest for us */
+			/* we are going to change the media type, so the Link
+			 * will be temporary down and we need to reflect that
+			 * here. When the Link comes up again, it will be
+			 * sensed by the sis_timer procedure, which also does
+			 * all the rest for us */
 			netif_carrier_off(dev);
                 
 			/* read current state */
 			status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL);
                 
 			/* enable auto negotiation and reset the negotioation
-			   (I don't really know what the auto negatiotiation reset
-			   really means, but it sounds for me right to do one here)*/
+			 * (I don't really know what the auto negatiotiation
+			 * reset really means, but it sounds for me right to
+			 * do one here) */
 			mdio_write(dev, mii_phy->phy_addr,
 				   MII_CONTROL, status | MII_CNTL_AUTO | MII_CNTL_RST_AUTO);
 
@@ -1985,10 +2006,11 @@
 		case IF_PORT_10BASET: /* 10BaseT */         
 			dev->if_port = map->port;
                 
-			/* we are going to change the media type, so the Link will
-			   be temporary down and we need to reflect that here. When
-			   the Link comes up again, it will be sensed by the sis_timer
-			   procedure, which also does all the rest for us */
+			/* we are going to change the media type, so the Link
+			 * will be temporary down and we need to reflect that
+			 * here. When the Link comes up again, it will be
+			 * sensed by the sis_timer procedure, which also does
+			 * all the rest for us */
 			netif_carrier_off(dev);
         
 			/* set Speed to 10Mbps */
@@ -1997,24 +2019,27 @@
                 
 			/* disable auto negotiation and force 10MBit mode*/
 			mdio_write(dev, mii_phy->phy_addr,
-				   MII_CONTROL, status & ~(MII_CNTL_SPEED | MII_CNTL_AUTO));
+				   MII_CONTROL, status & ~(MII_CNTL_SPEED |
+					MII_CNTL_AUTO));
 			break;
             
 		case IF_PORT_100BASET: /* 100BaseT */
 		case IF_PORT_100BASETX: /* 100BaseTx */ 
 			dev->if_port = map->port;
                 
-			/* we are going to change the media type, so the Link will
-			   be temporary down and we need to reflect that here. When
-			   the Link comes up again, it will be sensed by the sis_timer
-			   procedure, which also does all the rest for us */
+			/* we are going to change the media type, so the Link
+			 * will be temporary down and we need to reflect that
+			 * here. When the Link comes up again, it will be
+			 * sensed by the sis_timer procedure, which also does
+			 * all the rest for us */
 			netif_carrier_off(dev);
                 
 			/* set Speed to 100Mbps */
 			/* disable auto negotiation and enable 100MBit Mode */
 			status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL);
 			mdio_write(dev, mii_phy->phy_addr,
-				   MII_CONTROL, (status & ~MII_CNTL_SPEED) | MII_CNTL_SPEED);
+				   MII_CONTROL, (status & ~MII_CNTL_SPEED) |
+				   MII_CNTL_SPEED);
                 
 			break;
             
@@ -2094,12 +2119,14 @@
 		for (i = 0; i < table_entries; i++)
 			mc_filter[i] = 0xffff;
 	} else {
-		/* Accept Broadcast packet, destination address matchs our MAC address,
-		   use Receive Filter to reject unwanted MCAST packet */
+		/* Accept Broadcast packet, destination address matchs our
+		 * MAC address, use Receive Filter to reject unwanted MCAST
+		 * packets */
 		struct dev_mc_list *mclist;
 		rx_mode = RFAAB;
-		for (i = 0, mclist = net_dev->mc_list; mclist && i < net_dev->mc_count;
-		     i++, mclist = mclist->next) {
+		for (i = 0, mclist = net_dev->mc_list;
+			mclist && i < net_dev->mc_count;
+			i++, mclist = mclist->next) {
 			unsigned int bit_nr =
 				sis900_mcast_bitnr(mclist->dmi_addr, revision);
 			mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf));
@@ -2115,7 +2142,8 @@
 
 	outl(RFEN | rx_mode, ioaddr + rfcr);
 
-	/* sis900 is capatable of looping back packet at MAC level for debugging purpose */
+	/* sis900 is capable of looping back packets at MAC level for
+	 * debugging purpose */
 	if (net_dev->flags & IFF_LOOPBACK) {
 		u32 cr_saved;
 		/* We must disable Tx/Rx before setting loopback mode */
diff -Nru a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
--- a/drivers/net/sk_mca.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/sk_mca.c	2004-10-10 22:15:16 -07:00
@@ -972,14 +972,6 @@
 	return &(priv->stat);
 }
 
-/* we don't support runtime reconfiguration, since an MCA card can
-   be unambigously identified by its POS registers. */
-
-static int skmca_config(struct net_device *dev, struct ifmap *map)
-{
-	return 0;
-}
-
 /* switch receiver mode.  We use the LANCE's multicast filter to prefilter
    multicast addresses. */
 
@@ -1147,7 +1139,6 @@
 	/* set methods */
 	dev->open = skmca_open;
 	dev->stop = skmca_close;
-	dev->set_config = skmca_config;
 	dev->hard_start_xmit = skmca_tx;
 	dev->do_ioctl = NULL;
 	dev->get_stats = skmca_stats;
diff -Nru a/drivers/net/smc91x.h b/drivers/net/smc91x.h
--- a/drivers/net/smc91x.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/smc91x.h	2004-10-10 22:15:16 -07:00
@@ -160,6 +160,49 @@
 #define SMC_insw(a, r, p, l)	insw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)	outsw((a) + (r), p, l)
 
+#elif	defined(CONFIG_MACH_LPD7A400) || defined(CONFIG_MACH_LPD7A404)
+
+#include <asm/arch/constants.h>	/* IOBARRIER_VIRT */
+
+#define SMC_CAN_USE_8BIT	0
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	0
+#define SMC_NOWAIT		0
+#define SMC_IOBARRIER		({ barrier (); readl (IOBARRIER_VIRT); })
+
+static inline unsigned short SMC_inw (unsigned long a, int r)
+{
+	unsigned short v;
+	v = readw (a + r);
+	SMC_IOBARRIER;
+	return v;
+}
+
+static inline void SMC_outw (unsigned short v, unsigned long a, int r)
+{
+	writew (v, a + r);
+	SMC_IOBARRIER;
+}
+
+static inline void SMC_insw (unsigned long a, int r, unsigned char* p, int l)
+{
+	while (l-- > 0) {
+		*((unsigned short*)p)++ = readw (a + r);
+		SMC_IOBARRIER;
+	}
+}
+
+static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
+{
+	while (l-- > 0) {
+		writew (*((unsigned short*)p)++, a + r);
+		SMC_IOBARRIER;
+	}
+}
+
+#define RPC_LSA_DEFAULT		RPC_LED_TX_RX
+#define RPC_LSB_DEFAULT		RPC_LED_100_10
+
 #elif   defined(CONFIG_M32R)
 
 #define SMC_CAN_USE_8BIT	0
diff -Nru a/drivers/net/starfire.c b/drivers/net/starfire.c
--- a/drivers/net/starfire.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/starfire.c	2004-10-10 22:15:16 -07:00
@@ -799,12 +799,13 @@
 static int	netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int	netdev_close(struct net_device *dev);
 static void	netdev_media_change(struct net_device *dev);
+static struct ethtool_ops ethtool_ops;
 
 
 #ifdef VLAN_SUPPORT
 static void netdev_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 {
-        struct netdev_private *np = dev->priv;
+        struct netdev_private *np = netdev_priv(dev);
 
         spin_lock(&np->lock);
 	if (debug > 2)
@@ -816,7 +817,7 @@
 
 static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 
 	spin_lock(&np->lock);
 	if (debug > 1)
@@ -827,7 +828,7 @@
 
 static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 
 	spin_lock(&np->lock);
 	if (debug > 1)
@@ -951,7 +952,7 @@
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
 
-	np = dev->priv;
+	np = netdev_priv(dev);
 	spin_lock_init(&np->lock);
 	pci_set_drvdata(pdev, dev);
 
@@ -1015,6 +1016,7 @@
 	dev->get_stats = &get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &netdev_ioctl;
+	SET_ETHTOOL_OPS(dev, &ethtool_ops);
 
 	if (mtu)
 		dev->mtu = mtu;
@@ -1102,7 +1104,7 @@
 
 static int netdev_open(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int i, retval;
 	size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
@@ -1267,7 +1269,7 @@
 
 static void check_duplex(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	u16 reg0;
 	int silly_count = 1000;
 
@@ -1302,7 +1304,7 @@
 
 static void tx_timeout(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int old_debug;
 
@@ -1332,7 +1334,7 @@
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void init_ring(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int i;
 
 	np->cur_rx = np->cur_tx = np->reap_tx = 0;
@@ -1378,7 +1380,7 @@
 
 static int start_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	unsigned int entry;
 	u32 status;
 	int i;
@@ -1497,7 +1499,7 @@
 	int handled = 0;
 
 	ioaddr = dev->base_addr;
-	np = dev->priv;
+	np = netdev_priv(dev);
 
 	do {
 		u32 intr_status = readl(ioaddr + IntrClear);
@@ -1597,7 +1599,7 @@
    for clarity, code sharing between NAPI/non-NAPI, and better register allocation. */
 static int __netdev_rx(struct net_device *dev, int *quota)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	u32 desc_status;
 	int retcode = 0;
 
@@ -1752,7 +1754,7 @@
 
 static void refill_rx_ring(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	struct sk_buff *skb;
 	int entry = -1;
 
@@ -1780,7 +1782,7 @@
 
 static void netdev_media_change(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	u16 reg0, reg1, reg4, reg5;
 	u32 new_tx_mode;
@@ -1855,7 +1857,7 @@
 
 static void netdev_error(struct net_device *dev, int intr_status)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 
 	/* Came close to underrunning the Tx FIFO, increase threshold. */
 	if (intr_status & IntrTxDataLow) {
@@ -1883,7 +1885,7 @@
 static struct net_device_stats *get_stats(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 
 	/* This adapter architecture needs no SMP locks. */
 	np->stats.tx_bytes = readl(ioaddr + 0x57010);
@@ -1917,7 +1919,7 @@
 	struct dev_mc_list *mclist;
 	int i;
 #ifdef VLAN_SUPPORT
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 
 	rx_mode |= VlanMode;
 	if (np->vlgrp) {
@@ -1996,106 +1998,89 @@
 	writel(rx_mode, ioaddr + RxFilterMode);
 }
 
+static int check_if_running(struct net_device *dev)
+{
+	if (!netif_running(dev))
+		return -EINVAL;
+	return 0;
+}
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	struct ethtool_cmd ecmd;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, PCI_SLOT_NAME(np->pci_dev));
+}
 
-	if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-		return -EFAULT;
+static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	spin_lock_irq(&np->lock);
+	mii_ethtool_gset(&np->mii_if, ecmd);
+	spin_unlock_irq(&np->lock);
+	return 0;
+}
 
-	switch (ecmd.cmd) {
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info;
-		memset(&info, 0, sizeof(info));
-		info.cmd = ecmd.cmd;
-		strcpy(info.driver, DRV_NAME);
-		strcpy(info.version, DRV_VERSION);
-		*info.fw_version = 0;
-		strcpy(info.bus_info, PCI_SLOT_NAME(np->pci_dev));
-		if (copy_to_user(useraddr, &info, sizeof(info)))
-		       return -EFAULT;
-		return 0;
-	}
+static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	int res;
+	spin_lock_irq(&np->lock);
+	res = mii_ethtool_sset(&np->mii_if, ecmd);
+	spin_unlock_irq(&np->lock);
+	check_duplex(dev);
+	return res;
+}
 
-	/* get settings */
-	case ETHTOOL_GSET: {
-		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-		spin_lock_irq(&np->lock);
-		mii_ethtool_gset(&np->mii_if, &ecmd);
-		spin_unlock_irq(&np->lock);
-		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set settings */
-	case ETHTOOL_SSET: {
-		int r;
-		struct ethtool_cmd ecmd;
-		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-			return -EFAULT;
-		spin_lock_irq(&np->lock);
-		r = mii_ethtool_sset(&np->mii_if, &ecmd);
-		spin_unlock_irq(&np->lock);
-		check_duplex(dev);
-		return r;
-	}
-	/* restart autonegotiation */
-	case ETHTOOL_NWAY_RST: {
-		return mii_nway_restart(&np->mii_if);
-	}
-	/* get link status */
-	case ETHTOOL_GLINK: {
-		struct ethtool_value edata = {ETHTOOL_GLINK};
-		edata.data = mii_link_ok(&np->mii_if);
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
+static int nway_reset(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	return mii_nway_restart(&np->mii_if);
+}
 
-	/* get message-level */
-	case ETHTOOL_GMSGLVL: {
-		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
-		edata.data = debug;
-		if (copy_to_user(useraddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	/* set message-level */
-	case ETHTOOL_SMSGLVL: {
-		struct ethtool_value edata;
-		if (copy_from_user(&edata, useraddr, sizeof(edata)))
-			return -EFAULT;
-		debug = edata.data;
-		return 0;
-	}
-	default:
-		return -EOPNOTSUPP;
-	}
+static u32 get_link(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	return mii_link_ok(&np->mii_if);
+}
+
+static u32 get_msglevel(struct net_device *dev)
+{
+	return debug;
 }
 
+static void set_msglevel(struct net_device *dev, u32 val)
+{
+	debug = val;
+}
+
+static struct ethtool_ops ethtool_ops = {
+	.begin = check_if_running,
+	.get_drvinfo = get_drvinfo,
+	.get_settings = get_settings,
+	.set_settings = set_settings,
+	.nway_reset = nway_reset,
+	.get_link = get_link,
+	.get_msglevel = get_msglevel,
+	.set_msglevel = set_msglevel,
+};
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
+	struct mii_ioctl_data *data = if_mii(rq);
 	int rc;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	if (cmd == SIOCETHTOOL)
-		rc = netdev_ethtool_ioctl(dev, rq->ifr_data);
+	spin_lock_irq(&np->lock);
+	rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL);
+	spin_unlock_irq(&np->lock);
 
-	else {
-		struct mii_ioctl_data *data = if_mii(rq);
-		spin_lock_irq(&np->lock);
-		rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL);
-		spin_unlock_irq(&np->lock);
-
-		if ((cmd == SIOCSMIIREG) && (data->phy_id == np->phys[0]))
-			check_duplex(dev);
-	}
+	if ((cmd == SIOCSMIIREG) && (data->phy_id == np->phys[0]))
+		check_duplex(dev);
 
 	return rc;
 }
@@ -2103,7 +2088,7 @@
 static int netdev_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int i;
 
 	netif_stop_queue(dev);
@@ -2174,16 +2159,16 @@
 static void __devexit starfire_remove_one (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct netdev_private *np;
+	struct netdev_private *np = netdev_priv(dev);
 
 	if (!dev)
 		BUG();
 
-	np = dev->priv;
+	unregister_netdev(dev);
+
 	if (np->queue_mem)
 		pci_free_consistent(pdev, np->queue_mem_size, np->queue_mem, np->queue_mem_dma);
 
-	unregister_netdev(dev);
 
 	/* XXX: add wakeup code -- requires firmware for MagicPacket */
 	pci_set_power_state(pdev, 3);	/* go to sleep in D3 mode */
diff -Nru a/drivers/net/sundance.c b/drivers/net/sundance.c
--- a/drivers/net/sundance.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/sundance.c	2004-10-10 22:15:16 -07:00
@@ -511,8 +511,7 @@
 static struct net_device_stats *get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int  netdev_close(struct net_device *dev);
-
-
+static struct ethtool_ops ethtool_ops;
 
 static int __devinit sundance_probe1 (struct pci_dev *pdev,
 				      const struct pci_device_id *ent)
@@ -567,7 +566,7 @@
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
 
-	np = dev->priv;
+	np = netdev_priv(dev);
 	np->pci_dev = pdev;
 	np->chip_id = chip_idx;
 	np->msg_enable = (1 << debug) - 1;
@@ -600,6 +599,7 @@
 	dev->get_stats = &get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &netdev_ioctl;
+	SET_ETHTOOL_OPS(dev, &ethtool_ops);
 	dev->tx_timeout = &tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->change_mtu = &change_mtu;
@@ -787,7 +787,7 @@
 
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long mdio_addr = dev->base_addr + MIICtrl;
 	int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
 	int i, retval = 0;
@@ -817,7 +817,7 @@
 
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long mdio_addr = dev->base_addr + MIICtrl;
 	int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
 	int i;
@@ -846,7 +846,7 @@
 
 static int netdev_open(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int i;
 
@@ -916,7 +916,7 @@
 
 static void check_duplex(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
 	int negotiated = mii_lpa & np->mii_if.advertising;
@@ -945,7 +945,7 @@
 static void netdev_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int next_tick = 10*HZ;
 
@@ -962,7 +962,7 @@
 
 static void tx_timeout(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	unsigned long flag;
 	
@@ -1015,7 +1015,7 @@
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void init_ring(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int i;
 
 	np->cur_rx = np->cur_tx = 0;
@@ -1058,7 +1058,7 @@
 static void tx_poll (unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	unsigned head = np->cur_task % TX_RING_SIZE;
 	struct netdev_desc *txdesc = 
 		&np->tx_ring[(np->cur_tx - 1) % TX_RING_SIZE];
@@ -1085,7 +1085,7 @@
 static int
 start_tx (struct sk_buff *skb, struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	struct netdev_desc *txdesc;
 	unsigned entry;
 
@@ -1127,7 +1127,7 @@
 static int
 reset_tx (struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	struct sk_buff *skb;
 	int i;
@@ -1176,7 +1176,7 @@
 	int handled = 0;
 
 	ioaddr = dev->base_addr;
-	np = dev->priv;
+	np = netdev_priv(dev);
 
 	do {
 		int intr_status = readw(ioaddr + IntrStatus);
@@ -1301,7 +1301,7 @@
 static void rx_poll(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int entry = np->cur_rx % RX_RING_SIZE;
 	int boguscnt = np->budget;
 	long ioaddr = dev->base_addr;
@@ -1398,7 +1398,7 @@
 
 static void refill_rx (struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int entry;
 	int cnt = 0;
 
@@ -1429,7 +1429,7 @@
 static void netdev_error(struct net_device *dev, int intr_status)
 {
 	long ioaddr = dev->base_addr;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	u16 mii_ctl, mii_advertise, mii_lpa;
 	int speed;
 
@@ -1483,7 +1483,7 @@
 
 static struct net_device_stats *get_stats(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int i;
 
@@ -1512,7 +1512,7 @@
 static void set_rx_mode(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	u16 mc_filter[4];			/* Multicast hash filter */
 	u32 rx_mode;
 	int i;
@@ -1565,91 +1565,79 @@
 	writew(addr16, dev->base_addr + StationAddr+4);
 	return 0;
 }
-	
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static int check_if_running(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
-	u32 ethcmd;
+	if (!netif_running(dev))
+		return -EINVAL;
+	return 0;
+}
 
-	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
-		return -EFAULT;
+static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, pci_name(np->pci_dev));
+}
 
-        switch (ethcmd) {
-		/* get constant driver settings/info */
-        	case ETHTOOL_GDRVINFO: {
-			struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-			strcpy(info.driver, DRV_NAME);
-			strcpy(info.version, DRV_VERSION);
-			strcpy(info.bus_info, pci_name(np->pci_dev));
-			memset(&info.fw_version, 0, sizeof(info.fw_version));
-			if (copy_to_user(useraddr, &info, sizeof(info)))
-				return -EFAULT;
-			return 0;
-		}
+static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	spin_lock_irq(&np->lock);
+	mii_ethtool_gset(&np->mii_if, ecmd);
+	spin_unlock_irq(&np->lock);
+	return 0;
+}
 
-		/* get media settings */
-		case ETHTOOL_GSET: {
-			struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-			spin_lock_irq(&np->lock);
-			mii_ethtool_gset(&np->mii_if, &ecmd);
-			spin_unlock_irq(&np->lock);
-			if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-				return -EFAULT;
-			return 0;
-		}
-		/* set media settings */
-		case ETHTOOL_SSET: {
-			int r;
-			struct ethtool_cmd ecmd;
-			if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-				return -EFAULT;
-			spin_lock_irq(&np->lock);
-			r = mii_ethtool_sset(&np->mii_if, &ecmd);
-			spin_unlock_irq(&np->lock);
-			return r;
-		}
-
-		/* restart autonegotiation */
-		case ETHTOOL_NWAY_RST: {
-			return mii_nway_restart(&np->mii_if);
-		}
-
-		/* get link status */
-		case ETHTOOL_GLINK: {
-			struct ethtool_value edata = {ETHTOOL_GLINK};
-			edata.data = mii_link_ok(&np->mii_if);
-			if (copy_to_user(useraddr, &edata, sizeof(edata)))
-				return -EFAULT;
-			return 0;
-		}
+static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	int res;
+	spin_lock_irq(&np->lock);
+	res = mii_ethtool_sset(&np->mii_if, ecmd);
+	spin_unlock_irq(&np->lock);
+	return res;
+}
 
-		/* get message-level */
-		case ETHTOOL_GMSGLVL: {
-			struct ethtool_value edata = {ETHTOOL_GMSGLVL};
-			edata.data = np->msg_enable;
-			if (copy_to_user(useraddr, &edata, sizeof(edata)))
-				return -EFAULT;
-			return 0;
-		}
-		/* set message-level */
-		case ETHTOOL_SMSGLVL: {
-			struct ethtool_value edata;
-			if (copy_from_user(&edata, useraddr, sizeof(edata)))
-				return -EFAULT;
-			np->msg_enable = edata.data;
-			return 0;
-		}
+static int nway_reset(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	return mii_nway_restart(&np->mii_if);
+}
+
+static u32 get_link(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	return mii_link_ok(&np->mii_if);
+}
 
-		default:
-		return -EOPNOTSUPP;
+static u32 get_msglevel(struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	return np->msg_enable;
+}
 
-        }
+static void set_msglevel(struct net_device *dev, u32 val)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	np->msg_enable = val;
 }
 
+static struct ethtool_ops ethtool_ops = {
+	.begin = check_if_running,
+	.get_drvinfo = get_drvinfo,
+	.get_settings = get_settings,
+	.set_settings = set_settings,
+	.nway_reset = nway_reset,
+	.get_link = get_link,
+	.get_msglevel = get_msglevel,
+	.set_msglevel = set_msglevel,
+};
+
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int rc;
 	int i;
 	long ioaddr = dev->base_addr;
@@ -1657,14 +1645,9 @@
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	if (cmd == SIOCETHTOOL)
-		rc = netdev_ethtool_ioctl(dev, rq->ifr_data);
-
-	else {
-		spin_lock_irq(&np->lock);
-		rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL);
-		spin_unlock_irq(&np->lock);
-	}
+	spin_lock_irq(&np->lock);
+	rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL);
+	spin_unlock_irq(&np->lock);
 	switch (cmd) {
 		case SIOCDEVPRIVATE:
 		for (i=0; i<TX_RING_SIZE; i++) {
@@ -1696,7 +1679,7 @@
 static int netdev_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	struct sk_buff *skb;
 	int i;
 
@@ -1775,7 +1758,7 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 
 	if (dev) {
-		struct netdev_private *np = dev->priv;
+		struct netdev_private *np = netdev_priv(dev);
 
 		unregister_netdev(dev);
         	pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring,
diff -Nru a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
--- a/drivers/net/tulip/de2104x.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/tulip/de2104x.c	2004-10-10 22:15:16 -07:00
@@ -1208,8 +1208,7 @@
 		pci_write_config_dword(de->pdev, PCIPM, pmctl);
 
 		/* de4x5.c delays, so we do too */
-		current->state = TASK_UNINTERRUPTIBLE;
-		schedule_timeout(msecs_to_jiffies(10));
+		msleep(10);
 	}
 }
 
diff -Nru a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
--- a/drivers/net/tulip/de4x5.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/tulip/de4x5.c	2004-10-10 22:15:16 -07:00
@@ -5089,7 +5089,7 @@
     lp->useMII = TRUE;
 
     /* Search the MII address space for possible PHY devices */
-    for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(++i)%DE4X5_MAX_MII) {
+    for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) {
 	lp->phy[lp->active].addr = i;
 	if (i==0) n++;                             /* Count cycles */
 	while (de4x5_reset_phy(dev)<0) udelay(100);/* Wait for reset */
diff -Nru a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
--- a/drivers/net/tulip/tulip_core.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/tulip/tulip_core.c	2004-10-10 22:15:16 -07:00
@@ -830,30 +830,18 @@
 }
 
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void tulip_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 	struct tulip_private *np = netdev_priv(dev);
-	u32 ethcmd;
-
-	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
-		return -EFAULT;
-
-        switch (ethcmd) {
-        case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-		strcpy(info.driver, DRV_NAME);
-		strcpy(info.version, DRV_VERSION);
-		strcpy(info.bus_info, pci_name(np->pdev));
-		if (copy_to_user(useraddr, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-
-        }
-
-	return -EOPNOTSUPP;
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, pci_name(np->pdev));
 }
 
+static struct ethtool_ops ops = {
+	.get_drvinfo = tulip_get_drvinfo
+};
+
 /* Provide ioctl() calls to examine the MII xcvr state. */
 static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
@@ -865,9 +853,6 @@
 	unsigned int regnum = data->reg_num;
 
 	switch (cmd) {
-	case SIOCETHTOOL:
-		return netdev_ethtool_ioctl(dev, rq->ifr_data);
-
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
 		if (tp->mii_cnt)
 			data->phy_id = phy;
@@ -1059,7 +1044,7 @@
 				else
 					filterbit = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
 				filterbit &= 0x3f;
-				mc_filter[filterbit >> 5] |= cpu_to_le32(1 << (filterbit & 31));
+				mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
 				if (tulip_debug > 2) {
 					printk(KERN_INFO "%s: Added filter for %2.2x:%2.2x:%2.2x:"
 						   "%2.2x:%2.2x:%2.2x  %8.8x bit %d.\n", dev->name,
@@ -1236,6 +1221,11 @@
 	struct tulip_private *tp;
 	/* See note below on the multiport cards. */
 	static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
+	static struct pci_device_id early_486_chipsets[] = {
+		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424) },
+		{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496) },
+		{ },
+	};
 	static int last_irq;
 	static int multiport_cnt;	/* For four-port boards w/one EEPROM */
 	u8 chip_rev;
@@ -1289,17 +1279,15 @@
 	 *	without the workarounds being on.
 	 */
 
-	/* Intel Saturn. Switch to 8 long words burst, 8 long word cache aligned
-	   Aries might need this too. The Saturn errata are not pretty reading but
-	   thankfully it's an old 486 chipset.
+	/* 1. Intel Saturn. Switch to 8 long words burst, 8 long word cache
+	      aligned.  Aries might need this too. The Saturn errata are not 
+	      pretty reading but thankfully it's an old 486 chipset.
+
+	   2. The dreaded SiS496 486 chipset. Same workaround as Intel
+	      Saturn.
 	*/
 
-	if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, NULL)) {
-		csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift);
-		force_csr0 = 1;
-	}
-	/* The dreaded SiS496 486 chipset. Same workaround as above. */
-	if (pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, NULL)) {
+	if (pci_dev_present(early_486_chipsets)) {
 		csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift);
 		force_csr0 = 1;
 	}
@@ -1644,6 +1632,7 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	dev->poll_controller = &poll_tulip;
 #endif
+	SET_ETHTOOL_OPS(dev, &ops);
 
 	if (register_netdev(dev))
 		goto err_out_free_ring;
diff -Nru a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
--- a/drivers/net/tulip/winbond-840.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/tulip/winbond-840.c	2004-10-10 22:15:16 -07:00
@@ -1424,7 +1424,7 @@
 			 i++, mclist = mclist->next) {
 			int filterbit = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F;
 			filterbit &= 0x3f;
-			mc_filter[filterbit >> 5] |= cpu_to_le32(1 << (filterbit & 31));
+			mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
 		}
 		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
 	}
diff -Nru a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
--- a/drivers/net/tulip/xircom_tulip_cb.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/tulip/xircom_tulip_cb.c	2004-10-10 22:15:16 -07:00
@@ -350,6 +350,7 @@
 static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void set_rx_mode(struct net_device *dev);
 static void check_duplex(struct net_device *dev);
+static struct ethtool_ops ops;
 
 
 /* The Xircom cards are picky about when certain bits in CSR6 can be
@@ -450,7 +451,7 @@
  */
 static void find_mii_transceivers(struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	int phy, phy_idx;
 
 	if (media_cap[tp->default_port] & MediaIsMII) {
@@ -505,7 +506,7 @@
  */
 static void transceiver_voodoo(struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 
 	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
@@ -584,7 +585,7 @@
 	/* Clear the missed-packet counter. */
 	(volatile int)inl(ioaddr + CSR8);
 
-	tp = dev->priv;
+	tp = netdev_priv(dev);
 
 	tp->lock = SPIN_LOCK_UNLOCKED;
 	tp->pdev = pdev;
@@ -626,6 +627,7 @@
 #endif
 	dev->tx_timeout = xircom_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+	SET_ETHTOOL_OPS(dev, &ops);
 
 	transceiver_voodoo(dev);
 
@@ -749,7 +751,7 @@
 static void
 xircom_up(struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int i;
 
@@ -804,7 +806,7 @@
 static int
 xircom_open(struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 
 	if (request_irq(dev->irq, &xircom_interrupt, SA_SHIRQ, dev->name, dev))
 		return -EAGAIN;
@@ -818,7 +820,7 @@
 
 static void xircom_tx_timeout(struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 
 	if (media_cap[dev->if_port] & MediaIsMII) {
@@ -870,7 +872,7 @@
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void xircom_init_ring(struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	int i;
 
 	tp->tx_full = 0;
@@ -919,7 +921,7 @@
 static int
 xircom_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	int entry;
 	u32 flag;
 
@@ -971,7 +973,7 @@
 
 static void xircom_media_change(struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	u16 reg0, reg1, reg4, reg5;
 	u32 csr6 = inl(ioaddr + CSR6), newcsr6;
@@ -1032,7 +1034,7 @@
 
 static void check_duplex(struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	u16 reg0;
 
 	mdio_write(dev, tp->phys[0], MII_BMCR, BMCR_RESET);
@@ -1065,7 +1067,7 @@
 static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_instance;
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int csr5, work_budget = max_interrupt_work;
 	int handled = 0;
@@ -1203,7 +1205,7 @@
 static int
 xircom_rx(struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	int entry = tp->cur_rx % RX_RING_SIZE;
 	int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
 	int work_done = 0;
@@ -1303,7 +1305,7 @@
 xircom_down(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 
 	/* Disable interrupts by clearing the interrupt mask. */
 	outl(0, ioaddr + CSR7);
@@ -1321,7 +1323,7 @@
 xircom_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	int i;
 
 	if (xircom_debug > 1)
@@ -1359,7 +1361,7 @@
 
 static struct net_device_stats *xircom_get_stats(struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 
 	if (netif_device_present(dev))
@@ -1368,18 +1370,10 @@
 	return &tp->stats;
 }
 
-
-static int xircom_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static int xircom_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
-	struct ethtool_cmd ecmd;
-	struct xircom_private *tp = dev->priv;
-
-	if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-		return -EFAULT;
-
-	switch (ecmd.cmd) {
-	case ETHTOOL_GSET:
-		ecmd.supported =
+	struct xircom_private *tp = netdev_priv(dev);
+	ecmd->supported =
 			SUPPORTED_10baseT_Half |
 			SUPPORTED_10baseT_Full |
 			SUPPORTED_100baseT_Half |
@@ -1387,98 +1381,90 @@
 			SUPPORTED_Autoneg |
 			SUPPORTED_MII;
 
-		ecmd.advertising = ADVERTISED_MII;
-		if (tp->advertising[0] & ADVERTISE_10HALF)
-			ecmd.advertising |= ADVERTISED_10baseT_Half;
-		if (tp->advertising[0] & ADVERTISE_10FULL)
-			ecmd.advertising |= ADVERTISED_10baseT_Full;
-		if (tp->advertising[0] & ADVERTISE_100HALF)
-			ecmd.advertising |= ADVERTISED_100baseT_Half;
-		if (tp->advertising[0] & ADVERTISE_100FULL)
-			ecmd.advertising |= ADVERTISED_100baseT_Full;
-		if (tp->autoneg) {
-			ecmd.advertising |= ADVERTISED_Autoneg;
-			ecmd.autoneg = AUTONEG_ENABLE;
-		} else
-			ecmd.autoneg = AUTONEG_DISABLE;
-
-		ecmd.port = PORT_MII;
-		ecmd.transceiver = XCVR_INTERNAL;
-		ecmd.phy_address = tp->phys[0];
-		ecmd.speed = tp->speed100 ? SPEED_100 : SPEED_10;
-		ecmd.duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-		ecmd.maxtxpkt = TX_RING_SIZE / 2;
-		ecmd.maxrxpkt = 0;
+	ecmd->advertising = ADVERTISED_MII;
+	if (tp->advertising[0] & ADVERTISE_10HALF)
+		ecmd->advertising |= ADVERTISED_10baseT_Half;
+	if (tp->advertising[0] & ADVERTISE_10FULL)
+		ecmd->advertising |= ADVERTISED_10baseT_Full;
+	if (tp->advertising[0] & ADVERTISE_100HALF)
+		ecmd->advertising |= ADVERTISED_100baseT_Half;
+	if (tp->advertising[0] & ADVERTISE_100FULL)
+		ecmd->advertising |= ADVERTISED_100baseT_Full;
+	if (tp->autoneg) {
+		ecmd->advertising |= ADVERTISED_Autoneg;
+		ecmd->autoneg = AUTONEG_ENABLE;
+	} else
+		ecmd->autoneg = AUTONEG_DISABLE;
 
-		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
+	ecmd->port = PORT_MII;
+	ecmd->transceiver = XCVR_INTERNAL;
+	ecmd->phy_address = tp->phys[0];
+	ecmd->speed = tp->speed100 ? SPEED_100 : SPEED_10;
+	ecmd->duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+	ecmd->maxtxpkt = TX_RING_SIZE / 2;
+	ecmd->maxrxpkt = 0;
+	return 0;
+}
 
-	case ETHTOOL_SSET: {
-		u16 autoneg, speed100, full_duplex;
+static int xircom_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct xircom_private *tp = netdev_priv(dev);
+	u16 autoneg, speed100, full_duplex;
 
-		autoneg = (ecmd.autoneg == AUTONEG_ENABLE);
-		speed100 = (ecmd.speed == SPEED_100);
-		full_duplex = (ecmd.duplex == DUPLEX_FULL);
-
-		tp->autoneg = autoneg;
-		if (speed100 != tp->speed100 ||
-		    full_duplex != tp->full_duplex) {
-			tp->speed100 = speed100;
-			tp->full_duplex = full_duplex;
-			/* change advertising bits */
-			tp->advertising[0] &= ~(ADVERTISE_10HALF |
-					     ADVERTISE_10FULL |
-					     ADVERTISE_100HALF |
-					     ADVERTISE_100FULL |
-					     ADVERTISE_100BASE4);
-			if (speed100) {
-				if (full_duplex)
-					tp->advertising[0] |= ADVERTISE_100FULL;
-				else
-					tp->advertising[0] |= ADVERTISE_100HALF;
-			} else {
-				if (full_duplex)
-					tp->advertising[0] |= ADVERTISE_10FULL;
-				else
-					tp->advertising[0] |= ADVERTISE_10HALF;
-			}
+	autoneg = (ecmd->autoneg == AUTONEG_ENABLE);
+	speed100 = (ecmd->speed == SPEED_100);
+	full_duplex = (ecmd->duplex == DUPLEX_FULL);
+
+	tp->autoneg = autoneg;
+	if (speed100 != tp->speed100 ||
+	    full_duplex != tp->full_duplex) {
+		tp->speed100 = speed100;
+		tp->full_duplex = full_duplex;
+		/* change advertising bits */
+		tp->advertising[0] &= ~(ADVERTISE_10HALF |
+				     ADVERTISE_10FULL |
+				     ADVERTISE_100HALF |
+				     ADVERTISE_100FULL |
+				     ADVERTISE_100BASE4);
+		if (speed100) {
+			if (full_duplex)
+				tp->advertising[0] |= ADVERTISE_100FULL;
+			else
+				tp->advertising[0] |= ADVERTISE_100HALF;
+		} else {
+			if (full_duplex)
+				tp->advertising[0] |= ADVERTISE_10FULL;
+			else
+				tp->advertising[0] |= ADVERTISE_10HALF;
 		}
-		check_duplex(dev);
-		return 0;
-	}
-
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info;
-		memset(&info, 0, sizeof(info));
-		info.cmd = ecmd.cmd;
-		strcpy(info.driver, DRV_NAME);
-		strcpy(info.version, DRV_VERSION);
-		*info.fw_version = 0;
-		strcpy(info.bus_info, pci_name(tp->pdev));
-		if (copy_to_user(useraddr, &info, sizeof(info)))
-		       return -EFAULT;
-		return 0;
 	}
+	check_duplex(dev);
+	return 0;
+}
 
-	default:
-		return -EOPNOTSUPP;
-	}
+static void xircom_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct xircom_private *tp = netdev_priv(dev);
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, pci_name(tp->pdev));
 }
 
+static struct ethtool_ops ops = {
+	.get_settings = xircom_get_settings,
+	.set_settings = xircom_set_settings,
+	.get_drvinfo = xircom_get_drvinfo,
+};
 
 /* Provide ioctl() calls to examine the MII xcvr state. */
 static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	u16 *data = (u16 *)&rq->ifr_ifru;
 	int phy = tp->phys[0] & 0x1f;
 	unsigned long flags;
 
 	switch(cmd) {
-	case SIOCETHTOOL:
-		return xircom_ethtool_ioctl(dev, rq->ifr_data);
-
 	/* Legacy mii-diag interface */
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
 		if (tp->mii_cnt)
@@ -1531,7 +1517,7 @@
    when re-entered but still correct. */
 static void set_rx_mode(struct net_device *dev)
 {
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	struct dev_mc_list *mclist;
 	long ioaddr = dev->base_addr;
 	int csr6 = inl(ioaddr + CSR6);
@@ -1672,7 +1658,7 @@
 static int xircom_suspend(struct pci_dev *pdev, u32 state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	printk(KERN_INFO "xircom_suspend(%s)\n", dev->name);
 	if (tp->open)
 		xircom_down(dev);
@@ -1688,7 +1674,7 @@
 static int xircom_resume(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct xircom_private *tp = dev->priv;
+	struct xircom_private *tp = netdev_priv(dev);
 	printk(KERN_INFO "xircom_resume(%s)\n", dev->name);
 
 	pci_set_power_state(pdev,0);
diff -Nru a/drivers/net/typhoon.c b/drivers/net/typhoon.c
--- a/drivers/net/typhoon.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/typhoon.c	2004-10-10 22:15:16 -07:00
@@ -1,6 +1,6 @@
 /* typhoon.c: A Linux Ethernet device driver for 3Com 3CR990 family of NICs */
 /*
-	Written 2002-2003 by David Dillow <dave@thedillows.org>
+	Written 2002-2004 by David Dillow <dave@thedillows.org>
 	Based on code written 1998-2000 by Donald Becker <becker@scyld.com> and
 	Linux 2.2.x driver by David P. McLean <davidpmclean@yahoo.com>.
 
@@ -33,8 +33,16 @@
 	*) Waiting for a command response takes 8ms due to non-preemptable
 		polling. Only significant for getting stats and creating
 		SAs, but an ugly wart never the less.
-	*) I've not tested multicast. I think it works, but reports welcome.
+
+	TODO:
 	*) Doesn't do IPSEC offloading. Yet. Keep yer pants on, it's coming.
+	*) Add more support for ethtool (especially for NIC stats)
+	*) Allow disabling of RX checksum offloading
+	*) Fix MAC changing to work while the interface is up
+		(Need to put commands on the TX ring, which changes
+		the locking)
+	*) Add in FCS to {rx,tx}_bytes, since the hardware doesn't. See
+		http://oss.sgi.com/cgi-bin/mesg.cgi?a=netdev&i=20031215152211.7003fe8e.rddunlap%40osdl.org
 */
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
@@ -85,8 +93,8 @@
 #define PKT_BUF_SZ		1536
 
 #define DRV_MODULE_NAME		"typhoon"
-#define DRV_MODULE_VERSION 	"1.5.3"
-#define DRV_MODULE_RELDATE	"03/12/15"
+#define DRV_MODULE_VERSION 	"1.5.4"
+#define DRV_MODULE_RELDATE	"04/09/09"
 #define PFX			DRV_MODULE_NAME ": "
 #define ERR_PFX			KERN_ERR PFX
 
@@ -410,21 +418,22 @@
 out:
 	writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
 	writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
-	udelay(100);
-	return err;
 
 	/* The 3XP seems to need a little extra time to complete the load
 	 * of the sleep image before we can reliably boot it. Failure to
 	 * do this occasionally results in a hung adapter after boot in
 	 * typhoon_init_one() while trying to read the MAC address or
 	 * putting the card to sleep. 3Com's driver waits 5ms, but
-	 * that seems to be overkill -- with a 50usec delay, it survives
-	 * 35000 typhoon_init_one() calls, where it only make it 25-100
-	 * without it.
-	 *
-	 * As it turns out, still occasionally getting a hung adapter,
-	 * so I'm bumping it to 100us.
+	 * that seems to be overkill. However, if we can sleep, we might
+	 * as well give it that much time. Otherwise, we'll give it 500us,
+	 * which should be enough (I've see it work well at 100us, but still
+	 * saw occasional problems.)
 	 */
+	if(wait_type == WaitSleep)
+		msleep(5);
+	else
+		udelay(500);
+	return err;
 }
 
 static int
@@ -688,7 +697,7 @@
 static void
 typhoon_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 {
-	struct typhoon *tp = (struct typhoon *) dev->priv;
+	struct typhoon *tp = netdev_priv(dev);
 	struct cmd_desc xp_cmd;
 	int err;
 
@@ -726,7 +735,7 @@
 static void
 typhoon_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
-	struct typhoon *tp = (struct typhoon *) dev->priv;
+	struct typhoon *tp = netdev_priv(dev);
 	spin_lock_bh(&tp->state_lock);
 	if(tp->vlgrp)
 		tp->vlgrp->vlan_devices[vid] = NULL;
@@ -757,7 +766,7 @@
 static int
 typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	struct typhoon *tp = (struct typhoon *) dev->priv;
+	struct typhoon *tp = netdev_priv(dev);
 	struct transmit_ring *txRing;
 	struct tx_desc *txd, *first_txd;
 	dma_addr_t skb_dma;
@@ -908,7 +917,7 @@
 static void
 typhoon_set_rx_mode(struct net_device *dev)
 {
-	struct typhoon *tp = (struct typhoon *) dev->priv;
+	struct typhoon *tp = netdev_priv(dev);
 	struct cmd_desc xp_cmd;
 	u32 mc_filter[2];
 	u16 filter;
@@ -965,6 +974,9 @@
 
 	/* 3Com's Linux driver uses txMultipleCollisions as it's
 	 * collisions value, but there is some other collision info as well...
+	 *
+	 * The extra status reported would be a good candidate for
+	 * ethtool_ops->get_{strings,stats}()
 	 */
 	stats->tx_packets = le32_to_cpu(s->txPackets);
 	stats->tx_bytes = le32_to_cpu(s->txBytes);
@@ -1002,7 +1014,7 @@
 static struct net_device_stats *
 typhoon_get_stats(struct net_device *dev)
 {
-	struct typhoon *tp = (struct typhoon *) dev->priv;
+	struct typhoon *tp = netdev_priv(dev);
 	struct net_device_stats *stats = &tp->stats;
 	struct net_device_stats *saved = &tp->stats_saved;
 
@@ -1030,9 +1042,10 @@
 	return 0;
 }
 
-static inline void
-typhoon_ethtool_gdrvinfo(struct typhoon *tp, struct ethtool_drvinfo *info)
+static void
+typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
+	struct typhoon *tp = netdev_priv(dev);
 	struct pci_dev *pci_dev = tp->pdev;
 	struct cmd_desc xp_cmd;
 	struct resp_desc xp_resp[3];
@@ -1055,9 +1068,11 @@
 	strcpy(info->bus_info, pci_name(pci_dev));
 }
 
-static inline void
-typhoon_ethtool_gset(struct typhoon *tp, struct ethtool_cmd *cmd)
+static int
+typhoon_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
+	struct typhoon *tp = netdev_priv(dev);
+
 	cmd->supported = SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
 				SUPPORTED_Autoneg;
 
@@ -1107,15 +1122,19 @@
 		cmd->autoneg = AUTONEG_DISABLE;
 	cmd->maxtxpkt = 1;
 	cmd->maxrxpkt = 1;
+
+	return 0;
 }
 
-static inline int
-typhoon_ethtool_sset(struct typhoon *tp, struct ethtool_cmd *cmd)
+static int
+typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
+	struct typhoon *tp = netdev_priv(dev);
 	struct cmd_desc xp_cmd;
 	int xcvr;
 	int err;
 
+	err = -EINVAL;
 	if(cmd->autoneg == AUTONEG_ENABLE) {
 		xcvr = TYPHOON_XCVR_AUTONEG;
 	} else {
@@ -1125,23 +1144,23 @@
 			else if(cmd->speed == SPEED_100)
 				xcvr = TYPHOON_XCVR_100HALF;
 			else
-				return -EINVAL;
+				goto out;
 		} else if(cmd->duplex == DUPLEX_FULL) {
 			if(cmd->speed == SPEED_10)
 				xcvr = TYPHOON_XCVR_10FULL;
 			else if(cmd->speed == SPEED_100)
 				xcvr = TYPHOON_XCVR_100FULL;
 			else
-				return -EINVAL;
+				goto out;
 		} else
-			return -EINVAL;
+			goto out;
 	}
 
 	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_XCVR_SELECT);
 	xp_cmd.parm1 = cpu_to_le16(xcvr);
 	err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
 	if(err < 0)
-		return err;
+		goto out;
 
 	tp->xcvr_select = xcvr;
 	if(cmd->autoneg == AUTONEG_ENABLE) {
@@ -1152,92 +1171,38 @@
 		tp->duplex = cmd->duplex;
 	}
 
-	return 0;
+out:
+	return err;
 }
 
-static inline int
-typhoon_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void typhoon_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-	struct typhoon *tp = (struct typhoon *) dev->priv;
-	u32 ethcmd;
-
-	if(copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
-		return -EFAULT;
-
-	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO: {
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-
-			typhoon_ethtool_gdrvinfo(tp, &info);
-			if(copy_to_user(useraddr, &info, sizeof(info)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_GSET: {
-			struct ethtool_cmd cmd = { ETHTOOL_GSET };
-
-			typhoon_ethtool_gset(tp, &cmd);
-			if(copy_to_user(useraddr, &cmd, sizeof(cmd)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_SSET: {
-			struct ethtool_cmd cmd;
-			if(copy_from_user(&cmd, useraddr, sizeof(cmd)))
-				return -EFAULT;
-
-			return typhoon_ethtool_sset(tp, &cmd);
-		}
-	case ETHTOOL_GLINK:{
-			struct ethtool_value edata = { ETHTOOL_GLINK };
-
-			edata.data = netif_carrier_ok(dev) ? 1 : 0;
-			if(copy_to_user(useraddr, &edata, sizeof(edata)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_GWOL: {
-			struct ethtool_wolinfo wol = { ETHTOOL_GWOL };
-
-			if(tp->wol_events & TYPHOON_WAKE_LINK_EVENT)
-				wol.wolopts |= WAKE_PHY;
-			if(tp->wol_events & TYPHOON_WAKE_MAGIC_PKT)
-				wol.wolopts |= WAKE_MAGIC;
-			if(copy_to_user(useraddr, &wol, sizeof(wol)))
-				return -EFAULT;
-			return 0;
-	}
-	case ETHTOOL_SWOL: {
-			struct ethtool_wolinfo wol;
-
-			if(copy_from_user(&wol, useraddr, sizeof(wol)))
-				return -EFAULT;
-			tp->wol_events = 0;
-			if(wol.wolopts & WAKE_PHY)
-				tp->wol_events |= TYPHOON_WAKE_LINK_EVENT;
-			if(wol.wolopts & WAKE_MAGIC)
-				tp->wol_events |= TYPHOON_WAKE_MAGIC_PKT;
-			return 0;
-	}
-	default:
-		break;
-	}
-
-	return -EOPNOTSUPP;
+	struct typhoon *tp = netdev_priv(dev);
+	if (tp->wol_events & TYPHOON_WAKE_LINK_EVENT)
+		wol->wolopts |= WAKE_PHY;
+	if (tp->wol_events & TYPHOON_WAKE_MAGIC_PKT)
+		wol->wolopts |= WAKE_MAGIC;
+}
+
+static int typhoon_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct typhoon *tp = netdev_priv(dev);
+	tp->wol_events = 0;
+	if (wol->wolopts & WAKE_PHY)
+		tp->wol_events |= TYPHOON_WAKE_LINK_EVENT;
+	if (wol->wolopts & WAKE_MAGIC)
+		tp->wol_events |= TYPHOON_WAKE_MAGIC_PKT;
+	return 0;
 }
 
-static int
-typhoon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	switch (cmd) {
-	case SIOCETHTOOL:
-		return typhoon_ethtool_ioctl(dev, ifr->ifr_data);
-	default:
-		break;
-	}
-
-	return -EOPNOTSUPP;
-}
+static struct ethtool_ops typhoon_ethtool_ops = {
+	.get_drvinfo = typhoon_get_drvinfo,
+	.get_settings = typhoon_get_settings,
+	.set_settings = typhoon_set_settings,
+	.get_link = ethtool_op_get_link,
+	.get_wol = typhoon_get_wol,
+	.set_wol = typhoon_set_wol,
+};
 
 static int
 typhoon_wait_interrupt(void __iomem *ioaddr)
@@ -1756,7 +1721,7 @@
 static int
 typhoon_poll(struct net_device *dev, int *total_budget)
 {
-	struct typhoon *tp = (struct typhoon *) dev->priv;
+	struct typhoon *tp = netdev_priv(dev);
 	struct typhoon_indexes *indexes = tp->indexes;
 	int orig_budget = *total_budget;
 	int budget, work_done, done;
@@ -2069,7 +2034,7 @@
 static void
 typhoon_tx_timeout(struct net_device *dev)
 {
-	struct typhoon *tp = (struct typhoon *) dev->priv;
+	struct typhoon *tp = netdev_priv(dev);
 
 	if(typhoon_reset(tp->ioaddr, WaitNoSleep) < 0) {
 		printk(KERN_WARNING "%s: could not reset in tx timeout\n",
@@ -2099,7 +2064,7 @@
 static int
 typhoon_open(struct net_device *dev)
 {
-	struct typhoon *tp = (struct typhoon *) dev->priv;
+	struct typhoon *tp = netdev_priv(dev);
 	int err;
 
 	err = typhoon_wakeup(tp, WaitSleep);
@@ -2141,7 +2106,7 @@
 static int
 typhoon_close(struct net_device *dev)
 {
-	struct typhoon *tp = (struct typhoon *) dev->priv;
+	struct typhoon *tp = netdev_priv(dev);
 
 	netif_stop_queue(dev);
 
@@ -2169,7 +2134,7 @@
 typhoon_resume(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct typhoon *tp = (struct typhoon *) dev->priv;
+	struct typhoon *tp = netdev_priv(dev);
 
 	/* If we're down, resume when we are upped.
 	 */
@@ -2201,7 +2166,7 @@
 typhoon_suspend(struct pci_dev *pdev, u32 state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct typhoon *tp = (struct typhoon *) dev->priv;
+	struct typhoon *tp = netdev_priv(dev);
 	struct cmd_desc xp_cmd;
 
 	/* If we're down, we're already suspended.
@@ -2305,17 +2270,17 @@
 		goto error_out_dev;
 	}
 
-	/* If we transitioned from D3->D0 in pci_enable_device(),
-	 * we lost our configuration and need to restore it to the
-	 * conditions at boot.
-	 */
-	pci_restore_state(pdev, NULL);
+	err = pci_set_mwi(pdev);
+	if(err < 0) {
+		printk(ERR_PFX "%s: unable to set MWI\n", pci_name(pdev));
+		goto error_out_disable;
+	}
 
-	err = pci_set_dma_mask(pdev, 0xffffffffULL);
+	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 	if(err < 0) {
 		printk(ERR_PFX "%s: No usable DMA configuration\n",
 		       pci_name(pdev));
-		goto error_out_dev;
+		goto error_out_mwi;
 	}
 
 	/* sanity checks, resource #1 is our mmio area
@@ -2325,25 +2290,22 @@
 		       "%s: region #1 not a PCI MMIO resource, aborting\n",
 		       pci_name(pdev));
 		err = -ENODEV;
-		goto error_out_dev;
+		goto error_out_mwi;
 	}
 	if(pci_resource_len(pdev, 1) < 128) {
 		printk(ERR_PFX "%s: Invalid PCI MMIO region size, aborting\n",
 		       pci_name(pdev));
 		err = -ENODEV;
-		goto error_out_dev;
+		goto error_out_mwi;
 	}
 
 	err = pci_request_regions(pdev, "typhoon");
 	if(err < 0) {
 		printk(ERR_PFX "%s: could not request regions\n",
 		       pci_name(pdev));
-		goto error_out_dev;
+		goto error_out_mwi;
 	}
 
-	pci_set_master(pdev);
-	pci_set_mwi(pdev);
-
 	/* map our MMIO region
 	 */
 	ioaddr = pci_resource_start(pdev, 1);
@@ -2367,7 +2329,7 @@
 	}
 
 	dev->irq = pdev->irq;
-	tp = dev->priv;
+	tp = netdev_priv(dev);
 	tp->shared = (struct typhoon_shared *) shared;
 	tp->shared_dma = shared_dma;
 	tp->pdev = pdev;
@@ -2392,6 +2354,11 @@
 		goto error_out_dma;
 	}
 
+	/* Now that we've reset the 3XP and are sure it's not going to
+	 * write all over memory, enable bus mastering.
+	 */
+	pci_set_master(pdev);
+
 	/* dev->name is not valid until we register, but we need to
 	 * use some common routines to initialize the card. So that those
 	 * routines print the right name, we keep our oun pointer to the name
@@ -2465,9 +2432,9 @@
 	dev->watchdog_timeo	= TX_TIMEOUT;
 	dev->get_stats		= typhoon_get_stats;
 	dev->set_mac_address	= typhoon_set_mac_address;
-	dev->do_ioctl		= typhoon_ioctl;
 	dev->vlan_rx_register	= typhoon_vlan_rx_register;
 	dev->vlan_rx_kill_vid	= typhoon_vlan_rx_kill_vid;
+	SET_ETHTOOL_OPS(dev, &typhoon_ethtool_ops);
 
 	/* We can handle scatter gather, up to 16 entries, and
 	 * we can do IP checksumming (only version 4, doh...)
@@ -2528,6 +2495,10 @@
 	iounmap(ioaddr_mapped);
 error_out_regions:
 	pci_release_regions(pdev);
+error_out_mwi:
+	pci_clear_mwi(pdev);
+error_out_disable:
+	pci_disable_device(pdev);
 error_out_dev:
 	free_netdev(dev);
 error_out:
@@ -2538,7 +2509,7 @@
 typhoon_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct typhoon *tp = (struct typhoon *) (dev->priv);
+	struct typhoon *tp = netdev_priv(dev);
 
 	unregister_netdev(dev);
 	pci_set_power_state(pdev, 0);
@@ -2548,6 +2519,7 @@
 	pci_free_consistent(pdev, sizeof(struct typhoon_shared),
 			    tp->shared, tp->shared_dma);
 	pci_release_regions(pdev);
+	pci_clear_mwi(pdev);
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 	free_netdev(dev);
diff -Nru a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
--- a/drivers/net/wan/lmc/lmc_main.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wan/lmc/lmc_main.c	2004-10-10 22:15:16 -07:00
@@ -101,7 +101,6 @@
 static int lmc_close(struct net_device *dev);
 static struct net_device_stats *lmc_get_stats(struct net_device *dev);
 static irqreturn_t lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int lmc_set_config(struct net_device *dev, struct ifmap *map);
 static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size);
 static void lmc_softreset(lmc_softc_t * const);
 static void lmc_running_reset(struct net_device *dev);
@@ -814,7 +813,6 @@
     dev->stop = lmc_close;
     dev->get_stats = lmc_get_stats;
     dev->do_ioctl = lmc_ioctl;
-    dev->set_config = lmc_set_config;
     dev->tx_timeout = lmc_driver_timeout;
     dev->watchdog_timeo = (HZ); /* 1 second */
     
@@ -1973,13 +1971,6 @@
     LMC_CSR_WRITE (sc, csr_txlist, virt_to_bus (sc->lmc_txring));
 
     lmc_trace(sc->lmc_device, "lmc_softreset out");
-}
-
-static int lmc_set_config(struct net_device *dev, struct ifmap *map) /*fold00*/
-{
-    lmc_trace(dev, "lmc_set_config in");
-    lmc_trace(dev, "lmc_set_config out");
-    return -EOPNOTSUPP;
 }
 
 void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/
diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
--- a/drivers/net/wireless/airo.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/airo.c	2004-10-10 22:15:16 -07:00
@@ -1189,6 +1189,7 @@
 	struct iw_statistics	wstats;		// wireless stats
 	unsigned long		scan_timestamp;	/* Time started to scan */
 	struct iw_spy_data	spy_data;
+	struct iw_public_data	wireless_data;
 #endif /* WIRELESS_EXT */
 #ifdef MICSUPPORT
 	/* MIC stuff */
@@ -2640,8 +2641,7 @@
 	dev->set_mac_address = &airo_set_mac_address;
 	dev->do_ioctl = &airo_ioctl;
 #ifdef WIRELESS_EXT
-	dev->get_wireless_stats = airo_get_wireless_stats;
-	dev->wireless_handlers = (struct iw_handler_def *)&airo_handler_def;
+	dev->wireless_handlers = &airo_handler_def;
 #endif /* WIRELESS_EXT */
 	dev->change_mtu = &airo_change_mtu;
 	dev->open = &airo_open;
@@ -2668,6 +2668,9 @@
 	dev->priv = ethdev->priv;
 	dev->irq = ethdev->irq;
 	dev->base_addr = ethdev->base_addr;
+#ifdef WIRELESS_EXT
+	dev->wireless_data = ethdev->wireless_data;
+#endif /* WIRELESS_EXT */
 	memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
 	err = register_netdev(dev);
 	if (err<0) {
@@ -2747,8 +2750,9 @@
 	dev->set_mac_address = &airo_set_mac_address;
 	dev->do_ioctl = &airo_ioctl;
 #ifdef WIRELESS_EXT
-	dev->get_wireless_stats = airo_get_wireless_stats;
-	dev->wireless_handlers = (struct iw_handler_def *)&airo_handler_def;
+	dev->wireless_handlers = &airo_handler_def;
+	ai->wireless_data.spy_data = &ai->spy_data;
+	dev->wireless_data = &ai->wireless_data;
 #endif /* WIRELESS_EXT */
 	dev->change_mtu = &airo_change_mtu;
 	dev->open = &airo_open;
@@ -3231,7 +3235,7 @@
 					goto exitrx;
 				}
 			}
-#ifdef IW_WIRELESS_SPY		/* defined in iw_handler.h */
+#ifdef WIRELESS_SPY
 			if (apriv->spy_data.spy_number > 0) {
 				char *sa;
 				struct iw_quality wstats;
@@ -3251,7 +3255,7 @@
 				/* Update spy records */
 				wireless_spy_update(dev, sa, &wstats);
 			}
-#endif /* IW_WIRELESS_SPY */
+#endif /* WIRELESS_SPY */
 			OUT4500( apriv, EVACK, EV_RX);
 
 			if (test_bit(FLAG_802_11, &apriv->flags)) {
@@ -3476,7 +3480,7 @@
 #else
 		memcpy(buffer, ai->rxfids[0].virtual_host_addr, len);
 #endif
-#ifdef IW_WIRELESS_SPY		/* defined in iw_handler.h */
+#ifdef WIRELESS_SPY
 		if (ai->spy_data.spy_number > 0) {
 			char *sa;
 			struct iw_quality wstats;
@@ -3488,7 +3492,7 @@
 			/* Update spy records */
 			wireless_spy_update(ai->dev, sa, &wstats);
 		}
-#endif /* IW_WIRELESS_SPY */
+#endif /* WIRELESS_SPY */
 
 		skb->dev = ai->dev;
 		skb->ip_summed = CHECKSUM_NONE;
@@ -6520,6 +6524,13 @@
 		range->avg_qual.level = 176;	/* -80 dBm */
 	range->avg_qual.noise = 0;
 
+	/* Event capability (kernel + driver) */
+	range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
+				IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
+				IW_EVENT_CAPA_MASK(SIOCGIWAP) |
+				IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
+	range->event_capa[1] = IW_EVENT_CAPA_K_1;
+	range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVTXDROP);
 	return 0;
 }
 
@@ -6887,9 +6898,15 @@
 	while((!rc) && (BSSList.index != 0xffff)) {
 		/* Translate to WE format this entry */
 		current_ev = airo_translate_scan(dev, current_ev,
-						 extra + IW_SCAN_MAX_DATA,
+						 extra + dwrq->length,
 						 &BSSList);
 
+		/* Check if there is space for one more entry */
+		if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
+			/* Ask user space to try again with a bigger buffer */
+			return -E2BIG;
+		}
+
 		/* Read next entry */
 		rc = PC4500_readrid(ai, RID_BSSLISTNEXT,
 				    &BSSList, sizeof(BSSList), 1);
@@ -7025,12 +7042,10 @@
 	.num_standard	= sizeof(airo_handler)/sizeof(iw_handler),
 	.num_private	= sizeof(airo_private_handler)/sizeof(iw_handler),
 	.num_private_args = sizeof(airo_private_args)/sizeof(struct iw_priv_args),
-	.standard	= (iw_handler *) airo_handler,
-	.private	= (iw_handler *) airo_private_handler,
-	.private_args	= (struct iw_priv_args *) airo_private_args,
-	.spy_offset	= ((void *) (&((struct airo_info *) NULL)->spy_data) -
-			   (void *) NULL),
-
+	.standard	= airo_handler,
+	.private	= airo_private_handler,
+	.private_args	= airo_private_args,
+	.get_wireless_stats = airo_get_wireless_stats,
 };
 
 #endif /* WIRELESS_EXT */
diff -Nru a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
--- a/drivers/net/wireless/netwave_cs.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/netwave_cs.c	2004-10-10 22:15:16 -07:00
@@ -219,7 +219,6 @@
 /* Misc device stuff */
 static int netwave_open(struct net_device *dev);  /* Open the device */
 static int netwave_close(struct net_device *dev); /* Close the device */
-static int netwave_config(struct net_device *dev, struct ifmap *map);
 
 /* Packet transmission and Packet reception */
 static int netwave_start_xmit( struct sk_buff *skb, struct net_device *dev);
@@ -482,7 +481,6 @@
     /* Netwave specific entries in the device structure */
     SET_MODULE_OWNER(dev);
     dev->hard_start_xmit = &netwave_start_xmit;
-    dev->set_config = &netwave_config;
     dev->get_stats  = &netwave_get_stats;
     dev->set_multicast_list = &set_multicast_list;
     /* wireless extensions */
@@ -1286,16 +1284,6 @@
     /* Set the IENA bit in COR */
     wait_WOC(iobase);
     outb(corConfIENA + corConfLVLREQ, iobase + NETWAVE_REG_COR);
-}
-
-/*
- * Function netwave_config (dev, map)
- *
- *    Configure device, this work is done by netwave_pcmcia_config when a
- *    card is inserted
- */
-static int netwave_config(struct net_device *dev, struct ifmap *map) {
-    return 0; 
 }
 
 /*
diff -Nru a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c
--- a/drivers/net/wireless/prism54/isl_38xx.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/isl_38xx.c	2004-10-10 22:15:16 -07:00
@@ -133,8 +133,8 @@
 		      readl(device_base + ISL38XX_CTRL_STAT_REG));
 		udelay(ISL38XX_WRITEIO_DELAY);
 
-		if (reg = readl(device_base + ISL38XX_INT_IDENT_REG),
-		    reg == 0xabadface) {
+		reg = readl(device_base + ISL38XX_INT_IDENT_REG);
+		if (reg == 0xabadface) {
 #if VERBOSE > SHOW_ERROR_MESSAGES
 			do_gettimeofday(&current_time);
 			DEBUG(SHOW_TRACING,
@@ -192,10 +192,8 @@
 void
 isl38xx_interface_reset(void __iomem *device_base, dma_addr_t host_address)
 {
-	u32 reg;
-
 #if VERBOSE > SHOW_ERROR_MESSAGES
-	DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_interface_reset \n");
+	DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_interface_reset\n");
 #endif
 
 	/* load the address of the control block in the device */
@@ -203,8 +201,7 @@
 	udelay(ISL38XX_WRITEIO_DELAY);
 
 	/* set the reset bit in the Device Interrupt Register */
-	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_RESET,
-			  ISL38XX_DEV_INT_REG);
+	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_RESET, ISL38XX_DEV_INT_REG);
 	udelay(ISL38XX_WRITEIO_DELAY);
 
 	/* enable the interrupt for detecting initialization */
@@ -212,9 +209,7 @@
 	/* Note: Do not enable other interrupts here. We want the
 	 * device to have come up first 100% before allowing any other 
 	 * interrupts. */
-	reg = ISL38XX_INT_IDENT_INIT;
-
-	isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG);
+	isl38xx_w32_flush(device_base, ISL38XX_INT_IDENT_INIT, ISL38XX_INT_EN_REG);
 	udelay(ISL38XX_WRITEIO_DELAY);  /* allow complete full reset */
 }
 
diff -Nru a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h
--- a/drivers/net/wireless/prism54/isl_38xx.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/isl_38xx.h	2004-10-10 22:15:16 -07:00
@@ -95,6 +95,10 @@
 #define ISL38XX_INT_SOURCES                     0x001E
 
 /* Control/Status register bits */
+/* Looks like there are other meaningful bits
+    0x20004400 seen in normal operation,
+    0x200044db at 'timeout waiting for mgmt response'
+*/
 #define ISL38XX_CTRL_STAT_SLEEPMODE             0x00000200
 #define	ISL38XX_CTRL_STAT_CLKRUN		0x00800000
 #define ISL38XX_CTRL_STAT_RESET                 0x10000000
diff -Nru a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
--- a/drivers/net/wireless/prism54/isl_ioctl.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/isl_ioctl.c	2004-10-10 22:15:16 -07:00
@@ -36,38 +36,6 @@
 
 #include <net/iw_handler.h>	/* New driver API */
 
-static int init_mode = CARD_DEFAULT_IW_MODE;
-static int init_channel = CARD_DEFAULT_CHANNEL;
-static int init_wep = CARD_DEFAULT_WEP;
-static int init_filter = CARD_DEFAULT_FILTER;
-static int init_authen = CARD_DEFAULT_AUTHEN;
-static int init_dot1x = CARD_DEFAULT_DOT1X;
-static int init_conformance = CARD_DEFAULT_CONFORMANCE;
-static int init_mlme = CARD_DEFAULT_MLME_MODE;
-
-module_param(init_mode, int, 0);
-MODULE_PARM_DESC(init_mode,
-		 "Set card mode:\n0: Auto\n1: Ad-Hoc\n2: Managed Client (Default)\n3: Master / Access Point\n4: Repeater (Not supported yet)\n5: Secondary (Not supported yet)\n6: Monitor");
-
-module_param(init_channel, int, 0);
-MODULE_PARM_DESC(init_channel,
-		 "Check `iwpriv ethx channel` for available channels");
-
-module_param(init_wep, int, 0);
-module_param(init_filter, int, 0);
-
-module_param(init_authen, int, 0);
-MODULE_PARM_DESC(init_authen,
-		 "Authentication method. Can be of seven types:\n0 0x0000: None\n1 0x0001: DOT11_AUTH_OS (Default)\n2 0x0002: DOT11_AUTH_SK\n3 0x0003: DOT11_AUTH_BOTH");
-
-module_param(init_dot1x, int, 0);
-MODULE_PARM_DESC(init_dot1x,
-		 "\n0: None/not set	(Default)\n1: DOT11_DOT1X_AUTHENABLED\n2: DOT11_DOT1X_KEYTXENABLED");
-
-module_param(init_mlme, int, 0);
-MODULE_PARM_DESC(init_mlme,
-		 "Sets the MAC layer management entity (MLME) mode of operation,\n0: DOT11_MLME_AUTO (Default)\n1: DOT11_MLME_INTERMEDIATE\n2: DOT11_MLME_EXTENDED");
-
 /**
  * prism54_mib_mode_helper - MIB change mode helper function
  * @mib: the &struct islpci_mib object to modify
@@ -141,36 +109,34 @@
 void
 prism54_mib_init(islpci_private *priv)
 {
-	u32 t;
+	u32 channel, authen, wep, filter, dot1x, mlme, conformance, power, mode;
 	struct obj_buffer psm_buffer = {
 		.size = PSM_BUFFER_SIZE,
 		.addr = priv->device_psm_buffer
 	};
 
-	mgt_set(priv, DOT11_OID_CHANNEL, &init_channel);
-	mgt_set(priv, DOT11_OID_AUTHENABLE, &init_authen);
-	mgt_set(priv, DOT11_OID_PRIVACYINVOKED, &init_wep);
-
+	channel = CARD_DEFAULT_CHANNEL;
+	authen = CARD_DEFAULT_AUTHEN;
+	wep = CARD_DEFAULT_WEP;
+	filter = CARD_DEFAULT_FILTER; /* (0) Do not filter un-encrypted data */
+	dot1x = CARD_DEFAULT_DOT1X; 
+	mlme = CARD_DEFAULT_MLME_MODE;
+	conformance = CARD_DEFAULT_CONFORMANCE;
+	power = 127;
+	mode = CARD_DEFAULT_IW_MODE;
+
+	mgt_set(priv, DOT11_OID_CHANNEL, &channel);
+	mgt_set(priv, DOT11_OID_AUTHENABLE, &authen);
+	mgt_set(priv, DOT11_OID_PRIVACYINVOKED, &wep);
 	mgt_set(priv, DOT11_OID_PSMBUFFER, &psm_buffer);
-	mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &init_filter);
-	mgt_set(priv, DOT11_OID_DOT1XENABLE, &init_dot1x);
-	mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &init_mlme);
-	mgt_set(priv, OID_INL_DOT11D_CONFORMANCE, &init_conformance);
-
-	t = 127;
-	mgt_set(priv, OID_INL_OUTPUTPOWER, &t);
-
-	/* Important: we are setting a default wireless mode and we are 
-	 * forcing a valid one, so prism54_mib_mode_helper should just set
-	 * mib values depending on what the wireless mode given is. No need
-	 * for it save old values */
-	if (init_mode > IW_MODE_MONITOR || init_mode < IW_MODE_AUTO) {
-		printk(KERN_DEBUG "%s(): You passed a non-valid init_mode. "
-		       "Using default mode\n", __FUNCTION__);
-		init_mode = CARD_DEFAULT_IW_MODE;
-	}
+	mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &filter);
+	mgt_set(priv, DOT11_OID_DOT1XENABLE, &dot1x);
+	mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlme);
+	mgt_set(priv, OID_INL_DOT11D_CONFORMANCE, &conformance);
+	mgt_set(priv, OID_INL_OUTPUTPOWER, &power);
+
 	/* This sets all of the mode-dependent values */
-	prism54_mib_mode_helper(priv, init_mode);
+	prism54_mib_mode_helper(priv, mode);
 }
 
 /* this will be executed outside of atomic context thanks to
@@ -374,7 +340,10 @@
 
 	mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlmeautolevel);
 
-	mgt_commit(priv);
+	if (mgt_commit(priv)) {
+		up_write(&priv->mib_sem);
+		return -EIO;
+	}
 	priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR)
 	    ? priv->monitor_type : ARPHRD_ETHER;
 	up_write(&priv->mib_sem);
@@ -485,6 +454,15 @@
 	/* txpower is supported in dBm's */
 	range->txpower_capa = IW_TXPOW_DBM;
 
+#if WIRELESS_EXT > 16
+	/* Event capability (kernel + driver) */
+	range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
+	IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
+	IW_EVENT_CAPA_MASK(SIOCGIWAP));
+	range->event_capa[1] = IW_EVENT_CAPA_K_1;
+	range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM);
+#endif /* WIRELESS_EXT > 16 */
+
 	if (islpci_get_state(priv) < PRV_STATE_INIT)
 		return 0;
 
@@ -629,8 +607,8 @@
 	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL);
 
 	/* Add frequency. (short) bss->channel is the frequency in MHz */
-	iwe.u.freq.m = channel_of_freq(bss->channel);
-	iwe.u.freq.e = 0;
+	iwe.u.freq.m = bss->channel;
+	iwe.u.freq.e = 6;
 	iwe.cmd = SIOCGIWFREQ;
 	current_ev =
 	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
@@ -690,19 +668,33 @@
 	rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r);
 	noise = r.u;
 
-	/* Ask the device for a list of known bss. We can report at most
-	 * IW_MAX_AP=64 to the range struct. But the device won't repport anything
-	 * if you change the value of IWMAX_BSS=24.
-	 */
+	/* Ask the device for a list of known bss.
+	* The old API, using SIOCGIWAPLIST, had a hard limit of IW_MAX_AP=64.
+	* The new API, using SIOCGIWSCAN, is only limited by the buffer size.
+	* WE-14->WE-16, the buffer is limited to IW_SCAN_MAX_DATA bytes.
+	* Starting with WE-17, the buffer can be as big as needed.
+	* But the device won't repport anything if you change the value
+	* of IWMAX_BSS=24. */
+	
 	rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r);
 	bsslist = r.ptr;
 
 	/* ok now, scan the list and translate its info */
-	for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++)
+	for (i = 0; i < (int) bsslist->nr; i++) {
 		current_ev = prism54_translate_bss(ndev, current_ev,
-						   extra + IW_SCAN_MAX_DATA,
+						   extra + dwrq->length,
 						   &(bsslist->bsslist[i]),
 						   noise);
+#if WIRELESS_EXT > 16
+		/* Check if there is space for one more entry */
+		if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
+			/* Ask user space to try again with a bigger buffer */
+			rvalue = -E2BIG;
+			break;
+		}
+#endif /* WIRELESS_EXT > 16 */
+	}
+
 	kfree(bsslist);
 	dwrq->length = (current_ev - extra);
 	dwrq->flags = 0;	/* todo */
@@ -1412,7 +1404,10 @@
 		mlmeautolevel = DOT11_MLME_EXTENDED;
 	mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlmeautolevel);
 	/* restart the card with our new policy */
-	mgt_commit(priv);
+	if (mgt_commit(priv)) {
+		up_write(&priv->mib_sem);
+		return -EIO;
+	}
 	up_write(&priv->mib_sem);
 
 	return 0;
@@ -1746,11 +1741,13 @@
 			    char *data)
 {
 	struct obj_mlme *mlme = (struct obj_mlme *) data;
-	size_t len;
-	u8 *payload, *pos = (u8 *) (mlme + 1);
-
-	len = pos[0] | (pos[1] << 8);	/* little endian data length */
-	payload = pos + 2;
+	struct obj_mlmeex *mlmeex = (struct obj_mlmeex *) data;
+	struct obj_mlmeex *confirm;
+	u8 wpa_ie[MAX_WPA_IE_LEN];
+	int wpa_ie_len;
+	size_t len = 0; /* u16, better? */
+	u8 *payload = 0, *pos = 0;
+	int ret;
 
 	/* I think all trapable objects are listed here.
 	 * Some oids have a EX version. The difference is that they are emitted
@@ -1760,9 +1757,14 @@
 	 * suited. We use the more flexible custom event facility.
 	 */
 
+	if (oid >= DOT11_OID_BEACON) {
+		len = mlmeex->size;
+		payload = pos = mlmeex->data;
+	}
+
 	/* I fear prism54_process_bss_data won't work with big endian data */
 	if ((oid == DOT11_OID_BEACON) || (oid == DOT11_OID_PROBE))
-		prism54_process_bss_data(priv, oid, mlme->address,
+		prism54_process_bss_data(priv, oid, mlmeex->address,
 					 payload, len);
 
 	mgt_le_to_cpu(isl_oid[oid].flags & OID_FLAG_TYPE, (void *) mlme);
@@ -1822,21 +1824,134 @@
 
 	case DOT11_OID_AUTHENTICATEEX:
 		handle_request(priv, mlme, oid);
-		send_formatted_event(priv, "Authenticate request", mlme, 1);
+		send_formatted_event(priv, "Authenticate request (ex)", mlme, 1);
+
+		if (priv->iw_mode != IW_MODE_MASTER 
+				&& mlmeex->state != DOT11_STATE_AUTHING)
+			break;
+
+		confirm = kmalloc(sizeof(struct obj_mlmeex) + 6, GFP_ATOMIC);
+
+		if (!confirm) 
+			break;
+
+		memcpy(&confirm->address, mlmeex->address, ETH_ALEN);
+		printk(KERN_DEBUG "Authenticate from: address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", 
+				mlmeex->address[0],
+				mlmeex->address[1],
+				mlmeex->address[2],
+				mlmeex->address[3],
+				mlmeex->address[4],
+				mlmeex->address[5]
+				);
+		confirm->id = -1; /* or mlmeex->id ? */
+		confirm->state = 0; /* not used */
+		confirm->code = 0;
+		confirm->size = 6;
+		confirm->data[0] = 0x00;
+		confirm->data[1] = 0x00;
+		confirm->data[2] = 0x02;
+		confirm->data[3] = 0x00;
+		confirm->data[4] = 0x00;
+		confirm->data[5] = 0x00;
+
+		ret = mgt_set_varlen(priv, DOT11_OID_ASSOCIATEEX, confirm, 6);
+
+		kfree(confirm);
+		if (ret)
+			return ret;
 		break;
 
 	case DOT11_OID_DISASSOCIATEEX:
-		send_formatted_event(priv, "Disassociate request", mlme, 0);
+		send_formatted_event(priv, "Disassociate request (ex)", mlme, 0);
 		break;
 
 	case DOT11_OID_ASSOCIATEEX:
 		handle_request(priv, mlme, oid);
-		send_formatted_event(priv, "Associate request", mlme, 1);
+		send_formatted_event(priv, "Associate request (ex)", mlme, 1);
+
+		if (priv->iw_mode != IW_MODE_MASTER 
+				&& mlmeex->state != DOT11_STATE_AUTHING)
+			break;
+		
+		confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC);
+
+		if (!confirm)
+			break;
+
+		memcpy(&confirm->address, mlmeex->address, ETH_ALEN);
+
+		confirm->id = ((struct obj_mlmeex *)mlme)->id;
+		confirm->state = 0; /* not used */
+		confirm->code = 0;
+
+		wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie);
+
+		if (!wpa_ie_len) {
+			printk(KERN_DEBUG "No WPA IE found from "
+					"address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", 
+				mlmeex->address[0],
+				mlmeex->address[1],
+				mlmeex->address[2],
+				mlmeex->address[3],
+				mlmeex->address[4],
+				mlmeex->address[5]
+				);
+			kfree(confirm);
+			break;
+		}
+
+		confirm->size = wpa_ie_len;
+		memcpy(&confirm->data, wpa_ie, wpa_ie_len);
+
+		mgt_set_varlen(priv, oid, confirm, wpa_ie_len);
+
+		kfree(confirm);
+		
 		break;
 
 	case DOT11_OID_REASSOCIATEEX:
 		handle_request(priv, mlme, oid);
-		send_formatted_event(priv, "Reassociate request", mlme, 1);
+		send_formatted_event(priv, "Reassociate request (ex)", mlme, 1);
+
+		if (priv->iw_mode != IW_MODE_MASTER 
+				&& mlmeex->state != DOT11_STATE_ASSOCING)
+			break;
+
+		confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC);
+
+		if (!confirm)
+			break;
+
+		memcpy(&confirm->address, mlmeex->address, ETH_ALEN);
+
+		confirm->id = mlmeex->id;
+		confirm->state = 0; /* not used */
+		confirm->code = 0;
+
+		wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie);
+
+		if (!wpa_ie_len) {
+			printk(KERN_DEBUG "No WPA IE found from "
+					"address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", 
+				mlmeex->address[0],
+				mlmeex->address[1],
+				mlmeex->address[2],
+				mlmeex->address[3],
+				mlmeex->address[4],
+				mlmeex->address[5]
+				);
+			kfree(confirm);
+			break;
+		}
+
+		confirm->size = wpa_ie_len; 
+		memcpy(&confirm->data, wpa_ie, wpa_ie_len);
+
+		mgt_set_varlen(priv, oid, confirm, wpa_ie_len);
+
+		kfree(confirm);
+		
 		break;
 
 	default:
@@ -1879,23 +1994,367 @@
 	return ret;
 }
 
+/* Note: currently, use hostapd ioctl from the Host AP driver for WPA
+ * support. This is to be replaced with Linux wireless extensions once they
+ * get WPA support. */
+
+/* Note II: please leave all this together as it will be easier to remove later,
+ * once wireless extensions add WPA support -mcgrof */
+
+/* PRISM54_HOSTAPD ioctl() cmd: */
+enum {
+	PRISM2_SET_ENCRYPTION = 6,
+	PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12,
+	PRISM2_HOSTAPD_MLME = 13,
+	PRISM2_HOSTAPD_SCAN_REQ = 14,
+};
+
+#define PRISM54_SET_WPA			SIOCIWFIRSTPRIV+12
+#define PRISM54_HOSTAPD			SIOCIWFIRSTPRIV+25
+#define PRISM54_DROP_UNENCRYPTED	SIOCIWFIRSTPRIV+26
+
+#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
+#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
+((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
+
+/* Maximum length for algorithm names (-1 for nul termination) 
+ * used in ioctl() */
+#define HOSTAP_CRYPT_ALG_NAME_LEN 16
+	
+struct prism2_hostapd_param {
+	u32 cmd;
+	u8 sta_addr[ETH_ALEN];
+	union {
+	       struct {
+		       u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];
+		       u32 flags;
+		       u32 err;
+		       u8 idx;
+		       u8 seq[8]; /* sequence counter (set: RX, get: TX) */
+		       u16 key_len;
+		       u8 key[0];
+		       } crypt;
+               struct {
+                       u8 len;
+                       u8 data[0];
+               } generic_elem;
+               struct {
+#define MLME_STA_DEAUTH 0
+#define MLME_STA_DISASSOC 1
+                       u16 cmd;
+                       u16 reason_code;
+               } mlme;
+               struct {
+                       u8 ssid_len;
+                       u8 ssid[32];
+               } scan_req;
+       } u;
+};
+
+
+static int
+prism2_ioctl_set_encryption(struct net_device *dev,
+	struct prism2_hostapd_param *param,
+	int param_len)
+{
+	islpci_private *priv = netdev_priv(dev);
+	int rvalue = 0, force = 0;
+	int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0;
+	union oid_res_t r;
+
+	/* with the new API, it's impossible to get a NULL pointer.
+	 * New version of iwconfig set the IW_ENCODE_NOKEY flag
+	 * when no key is given, but older versions don't. */
+
+	if (param->u.crypt.key_len > 0) {
+		/* we have a key to set */
+		int index = param->u.crypt.idx;
+		int current_index;
+		struct obj_key key = { DOT11_PRIV_TKIP, 0, "" };
+
+		/* get the current key index */
+		rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
+		current_index = r.u;
+		/* Verify that the key is not marked as invalid */
+		if (!(param->u.crypt.flags & IW_ENCODE_NOKEY)) {
+			key.length = param->u.crypt.key_len > sizeof (param->u.crypt.key) ?
+			    sizeof (param->u.crypt.key) : param->u.crypt.key_len;
+			memcpy(key.key, param->u.crypt.key, key.length);
+			if (key.length == 32)
+				/* we want WPA-PSK */
+				key.type = DOT11_PRIV_TKIP;
+			if ((index < 0) || (index > 3))
+				/* no index provided use the current one */
+				index = current_index;
+
+			/* now send the key to the card  */
+			rvalue |=
+			    mgt_set_request(priv, DOT11_OID_DEFKEYX, index,
+					    &key);
+		}
+		/*
+		 * If a valid key is set, encryption should be enabled 
+		 * (user may turn it off later).
+		 * This is also how "iwconfig ethX key on" works
+		 */
+		if ((index == current_index) && (key.length > 0))
+			force = 1;
+	} else {
+		int index = (param->u.crypt.flags & IW_ENCODE_INDEX) - 1;
+		if ((index >= 0) && (index <= 3)) {
+			/* we want to set the key index */
+			rvalue |=
+			    mgt_set_request(priv, DOT11_OID_DEFKEYID, 0,
+					    &index);
+		} else {
+			if (!param->u.crypt.flags & IW_ENCODE_MODE) {
+				/* we cannot do anything. Complain. */
+				return -EINVAL;
+			}
+		}
+	}
+	/* now read the flags */
+	if (param->u.crypt.flags & IW_ENCODE_DISABLED) {
+		/* Encoding disabled, 
+		 * authen = DOT11_AUTH_OS;
+		 * invoke = 0;
+		 * exunencrypt = 0; */
+	}
+	if (param->u.crypt.flags & IW_ENCODE_OPEN)
+		/* Encode but accept non-encoded packets. No auth */
+		invoke = 1;
+	if ((param->u.crypt.flags & IW_ENCODE_RESTRICTED) || force) {
+		/* Refuse non-encoded packets. Auth */
+		authen = DOT11_AUTH_BOTH;
+		invoke = 1;
+		exunencrypt = 1;
+	}
+	/* do the change if requested  */
+	if ((param->u.crypt.flags & IW_ENCODE_MODE) || force) {
+		rvalue |=
+		    mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen);
+		rvalue |=
+		    mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke);
+		rvalue |=
+		    mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0,
+				    &exunencrypt);
+	}
+	return rvalue;
+}
+
+static int
+prism2_ioctl_set_generic_element(struct net_device *ndev,
+	struct prism2_hostapd_param *param,
+	int param_len)
+{
+       islpci_private *priv = netdev_priv(ndev);
+       int max_len, len, alen, ret=0;
+       struct obj_attachment *attach;
+
+       len = param->u.generic_elem.len;
+       max_len = param_len - PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN;
+       if (max_len < 0 || max_len < len)
+               return -EINVAL;
+
+       alen = sizeof(*attach) + len;
+       attach = kmalloc(alen, GFP_KERNEL);
+       if (attach == NULL)
+               return -ENOMEM;
+
+       memset(attach, 0, alen);
+#define WLAN_FC_TYPE_MGMT 0
+#define WLAN_FC_STYPE_ASSOC_REQ 0
+#define WLAN_FC_STYPE_REASSOC_REQ 2
+
+       /* Note: endianness is covered by mgt_set_varlen */
+
+       attach->type = (WLAN_FC_TYPE_MGMT << 2) |
+               (WLAN_FC_STYPE_ASSOC_REQ << 4);
+       attach->id = -1;
+       attach->size = len;
+       memcpy(attach->data, param->u.generic_elem.data, len);
+
+       ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len);
+
+       if (ret == 0) {
+               attach->type = (WLAN_FC_TYPE_MGMT << 2) |
+                       (WLAN_FC_STYPE_REASSOC_REQ << 4);
+
+	       ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len);
+
+	       if (ret == 0) 
+		       printk(KERN_DEBUG "%s: WPA IE Attachment was set\n",
+				       ndev->name);
+       }
+
+       kfree(attach);
+       return ret;
+
+}
+
+static int
+prism2_ioctl_mlme(struct net_device *dev, struct prism2_hostapd_param *param)
+{
+	return -EOPNOTSUPP;
+}
+
+static int
+prism2_ioctl_scan_req(struct net_device *ndev,
+                     struct prism2_hostapd_param *param)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	int i, rvalue;
+	struct obj_bsslist *bsslist;
+	u32 noise = 0;
+	char *extra = "";
+	char *current_ev = "foo";
+	union oid_res_t r;
+
+	if (islpci_get_state(priv) < PRV_STATE_INIT) {
+		/* device is not ready, fail gently */
+		return 0;
+	}
+
+	/* first get the noise value. We will use it to report the link quality */
+	rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r);
+	noise = r.u;
+
+	/* Ask the device for a list of known bss. We can report at most
+	 * IW_MAX_AP=64 to the range struct. But the device won't repport anything
+	 * if you change the value of IWMAX_BSS=24.
+	 */
+	rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r);
+	bsslist = r.ptr;
+
+	/* ok now, scan the list and translate its info */
+	for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++)
+		current_ev = prism54_translate_bss(ndev, current_ev,
+						   extra + IW_SCAN_MAX_DATA,
+						   &(bsslist->bsslist[i]),
+						   noise);
+	kfree(bsslist);
+
+	return rvalue;
+}
+
+static int
+prism54_hostapd(struct net_device *ndev, struct iw_point *p)
+{
+       struct prism2_hostapd_param *param;
+       int ret = 0;
+       u32 uwrq;
+
+       printk(KERN_DEBUG "prism54_hostapd - len=%d\n", p->length);
+       if (p->length < sizeof(struct prism2_hostapd_param) ||
+           p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
+               return -EINVAL;
+
+       param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL);
+       if (param == NULL)
+               return -ENOMEM;
+
+       if (copy_from_user(param, p->pointer, p->length)) {
+               kfree(param);
+               return -EFAULT;
+       }
+
+       switch (param->cmd) {
+       case PRISM2_SET_ENCRYPTION:
+	       printk(KERN_DEBUG "%s: Caught WPA supplicant set encryption request\n",
+			       ndev->name);
+               ret = prism2_ioctl_set_encryption(ndev, param, p->length);
+               break;
+       case PRISM2_HOSTAPD_SET_GENERIC_ELEMENT:
+	       printk(KERN_DEBUG "%s: Caught WPA supplicant set WPA IE request\n",
+			       ndev->name);
+               ret = prism2_ioctl_set_generic_element(ndev, param,
+                                                      p->length);
+               break;
+       case PRISM2_HOSTAPD_MLME:
+	       printk(KERN_DEBUG "%s: Caught WPA supplicant MLME request\n",
+			       ndev->name);
+               ret = prism2_ioctl_mlme(ndev, param);
+               break;
+       case PRISM2_HOSTAPD_SCAN_REQ:
+	       printk(KERN_DEBUG "%s: Caught WPA supplicant scan request\n",
+			       ndev->name);
+               ret = prism2_ioctl_scan_req(ndev, param);
+               break;
+	case PRISM54_SET_WPA:
+	       printk(KERN_DEBUG "%s: Caught WPA supplicant wpa init request\n",
+			       ndev->name);
+	       uwrq = 1;
+	       ret = prism54_set_wpa(ndev, NULL, &uwrq, NULL);
+	       break;
+	case PRISM54_DROP_UNENCRYPTED:
+	       printk(KERN_DEBUG "%s: Caught WPA drop unencrypted request\n",
+			       ndev->name);
+#if 0
+	       uwrq = 0x01;
+	       mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &uwrq);
+	       down_write(&priv->mib_sem);
+	       mgt_commit(priv);
+	       up_write(&priv->mib_sem);
+#endif
+	       /* Not necessary, as set_wpa does it, should we just do it here though? */
+	       ret = 0;
+	       break;
+       default:
+	       printk(KERN_DEBUG "%s: Caught a WPA supplicant request that is not supported\n",
+			       ndev->name);
+               ret = -EOPNOTSUPP;
+               break;
+       }
+
+       if (ret == 0 && copy_to_user(p->pointer, param, p->length))
+               ret = -EFAULT;
+
+       kfree(param);
+
+       return ret;
+}
+
 int
 prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info,
 		__u32 * uwrq, char *extra)
 {
 	islpci_private *priv = netdev_priv(ndev);
+	u32 mlme, authen, dot1x, filter, wep;
 
-	down_write(&priv->mib_sem);
+	if (islpci_get_state(priv) < PRV_STATE_INIT)
+		return 0;
+
+	wep = 1; /* For privacy invoked */
+	filter = 1; /* Filter out all unencrypted frames */
+	dot1x = 0x01; /* To enable eap filter */
+	mlme = DOT11_MLME_EXTENDED;
+	authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
 
+	down_write(&priv->mib_sem);
 	priv->wpa = *uwrq;
-	if (priv->wpa) {
-		u32 l = DOT11_MLME_EXTENDED;
-		mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &l);
+
+	switch (priv->wpa) {
+		default:
+		case 0: /* Clears/disables WPA and friends */
+			wep = 0;
+			filter = 0; /* Do not filter un-encrypted data */
+			dot1x = 0;
+			mlme = DOT11_MLME_AUTO;
+			printk("%s: Disabling WPA\n", ndev->name);
+			break;
+		case 2: 
+		case 1: /* WPA */
+			printk("%s: Enabling WPA\n", ndev->name);
+			break;
 	}
-	/* restart the card with new level. Needed ? */
-	mgt_commit(priv);
 	up_write(&priv->mib_sem);
 
+	mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen);
+	mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &wep);
+	mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &filter);
+	mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x);
+	mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlme);
+
 	return 0;
 }
 
@@ -1947,7 +2406,7 @@
 		      struct iw_point *data, char *extra)
 {
 	islpci_private *priv = netdev_priv(ndev);
-	struct islpci_mgmtframe *response = NULL;
+	struct islpci_mgmtframe *response;
 	int ret = -EIO;
 
 	printk("%s: get_oid 0x%08X\n", ndev->name, priv->priv_oid);
@@ -1983,7 +2442,7 @@
 		      struct iw_point *data, char *extra)
 {
 	islpci_private *priv = netdev_priv(ndev);
-	struct islpci_mgmtframe *response = NULL;
+	struct islpci_mgmtframe *response;
 	int ret = 0, response_op = PIMFOR_OP_ERROR;
 
 	printk("%s: set_oid 0x%08X\tlen: %d\n", ndev->name, priv->priv_oid,
@@ -2256,14 +2715,24 @@
 	.standard = (iw_handler *) prism54_handler,
 	.private = (iw_handler *) prism54_private_handler,
 	.private_args = (struct iw_priv_args *) prism54_private_args,
+#if WIRELESS_EXT == 16
 	.spy_offset = offsetof(islpci_private, spy_data),
+#endif /* WIRELESS_EXT == 16 */
 };
 
-/* For ioctls that don't work with the new API */
+/* For wpa_supplicant */
 
 int
 prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 {
-
+	struct iwreq *wrq = (struct iwreq *) rq;
+	int ret = -1;
+	switch (cmd) {
+		case PRISM54_HOSTAPD:
+		if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+		ret = prism54_hostapd(ndev, &wrq->u.data);
+		return ret;
+	}
 	return -EOPNOTSUPP;
 }
diff -Nru a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h
--- a/drivers/net/wireless/prism54/isl_ioctl.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/isl_ioctl.h	2004-10-10 22:15:16 -07:00
@@ -48,6 +48,8 @@
 int prism54_set_mac_address(struct net_device *, void *);
 
 int prism54_ioctl(struct net_device *, struct ifreq *, int);
+int prism54_set_wpa(struct net_device *, struct iw_request_info *, 
+			__u32 *, char *);
 
 extern const struct iw_handler_def prism54_handler_def;
 
diff -Nru a/drivers/net/wireless/prism54/isl_oid.h b/drivers/net/wireless/prism54/isl_oid.h
--- a/drivers/net/wireless/prism54/isl_oid.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/isl_oid.h	2004-10-10 22:15:16 -07:00
@@ -91,6 +91,14 @@
 	u16 mhz[0];
 } __attribute__ ((packed));
 
+struct obj_attachment {
+	char type;
+	char reserved;
+	short id;
+	short size;
+	char data[0];
+} __attribute__((packed));
+
 /* 
  * in case everything's ok, the inlined function below will be
  * optimized away by the compiler...
@@ -472,6 +480,7 @@
 #define OID_TYPE_MLMEEX		0x09
 #define OID_TYPE_ADDR		0x0A
 #define OID_TYPE_RAW		0x0B
+#define OID_TYPE_ATTACH		0x0C
 
 /* OID_TYPE_MLMEEX is special because of a variable size field when sending.
  * Not yet implemented (not used in driver anyway).
diff -Nru a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
--- a/drivers/net/wireless/prism54/islpci_dev.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/islpci_dev.c	2004-10-10 22:15:16 -07:00
@@ -105,7 +105,7 @@
 			       "%s: firmware '%s' size is not multiple of 32bit, aborting!\n",
 			       "prism54", priv->firmware);
 			release_firmware(fw_entry);
-			return EILSEQ; /* Illegal byte sequence  */;
+			return -EILSEQ; /* Illegal byte sequence  */;
 		}
 
 		while (fw_len > 0) {
@@ -142,6 +142,10 @@
 
 		BUG_ON(fw_len != 0);
 
+		/* Firmware version is at offset 40 (also for "newmac") */
+		printk(KERN_DEBUG "%s: firmware version: %.8s\n",
+		       priv->ndev->name, fw_entry->data + 40);
+
 		release_firmware(fw_entry);
 	}
 
@@ -375,8 +379,6 @@
 	u32 rc;
 	islpci_private *priv = netdev_priv(ndev);
 
-	printk(KERN_DEBUG "%s: islpci_open()\n", ndev->name);
-
 	/* reset data structures, upload firmware and reset device */
 	rc = islpci_reset(priv,1);
 	if (rc) {
@@ -462,8 +464,7 @@
 		return rc;
 	}
 
-	printk(KERN_DEBUG
-	       "%s: firmware uploaded done, now triggering reset...\n",
+	printk(KERN_DEBUG "%s: firmware upload complete\n",
 	       priv->ndev->name);
 
 	islpci_set_state(priv, PRV_STATE_POSTBOOT);
@@ -489,6 +490,7 @@
 		/* The software reset acknowledge needs about 220 msec here.
 		 * Be conservative and wait for up to one second. */
 	
+		set_current_state(TASK_UNINTERRUPTIBLE);
 		remaining = schedule_timeout(HZ);
 
 		if(remaining > 0) {
@@ -499,15 +501,16 @@
 		/* If we're here it's because our IRQ hasn't yet gone through. 
 		 * Retry a bit more...
 		 */
-		 printk(KERN_ERR "%s: device soft reset timed out\n",
-		       priv->ndev->name);
-
+		printk(KERN_ERR "%s: no 'reset complete' IRQ seen - retrying\n",
+			priv->ndev->name);
 	}
 
 	finish_wait(&priv->reset_done, &wait);
 
-	if(result)
+	if (result) {
+		printk(KERN_ERR "%s: interface reset failure\n", priv->ndev->name);
 		return result;
+	}
 
 	islpci_set_state(priv, PRV_STATE_INIT);
 
@@ -519,11 +522,17 @@
 	isl38xx_enable_common_interrupts(priv->device_base);
 
 	down_write(&priv->mib_sem);
-	mgt_commit(priv);
+	result = mgt_commit(priv);
+	if (result) {
+		printk(KERN_ERR "%s: interface reset failure\n", priv->ndev->name);
+		up_write(&priv->mib_sem);
+		return result;
+	}
 	up_write(&priv->mib_sem);
 
 	islpci_set_state(priv, PRV_STATE_READY);
 
+	printk(KERN_DEBUG "%s: interface reset complete\n", priv->ndev->name);
 	return 0;
 }
 
@@ -584,18 +593,18 @@
 	/* now that the data structures are cleaned up, upload
 	 * firmware and reset interface */
 		rc = islpci_upload_fw(priv);
-		if (rc) 
+		if (rc) {
+			printk(KERN_ERR "%s: islpci_reset: failure\n",
+				priv->ndev->name);
 			return rc;
+		}
 	}
 
 	/* finally reset interface */
 	rc = islpci_reset_if(priv);
-	if (!rc) /* If successful */
-		return rc;
-	
-	printk(KERN_DEBUG  "prism54: Your card/socket may be faulty, or IRQ line too busy :(\n");
+	if (rc)
+		printk(KERN_ERR "prism54: Your card/socket may be faulty, or IRQ line too busy :(\n");
 	return rc;
-
 }
 
 struct net_device_stats *
@@ -604,7 +613,7 @@
 	islpci_private *priv = netdev_priv(ndev);
 
 #if VERBOSE > SHOW_ERROR_MESSAGES
-	DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics \n");
+	DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics\n");
 #endif
 
 	return &priv->statistics;
@@ -829,6 +838,12 @@
 	priv->monitor_type = ARPHRD_IEEE80211;
 	priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ?
 		priv->monitor_type : ARPHRD_ETHER;
+
+#if WIRELESS_EXT > 16
+	/* Add pointers to enable iwspy support. */
+	priv->wireless_data.spy_data = &priv->spy_data;
+	ndev->wireless_data = &priv->wireless_data;
+#endif /* WIRELESS_EXT > 16 */
 
 	/* save the start and end address of the PCI memory area */
 	ndev->mem_start = (unsigned long) priv->device_base;
diff -Nru a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
--- a/drivers/net/wireless/prism54/islpci_dev.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/islpci_dev.h	2004-10-10 22:15:16 -07:00
@@ -100,6 +100,10 @@
 
 	struct iw_spy_data spy_data; /* iwspy support */
 
+#if WIRELESS_EXT > 16
+	struct iw_public_data wireless_data;
+#endif /* WIRELESS_EXT > 16 */
+
 	int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
 
 	struct islpci_acl acl;
diff -Nru a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
--- a/drivers/net/wireless/prism54/islpci_eth.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/islpci_eth.c	2004-10-10 22:15:16 -07:00
@@ -508,11 +508,12 @@
 	/* increment the transmit error counter */
 	statistics->tx_errors++;
 
+	printk(KERN_WARNING "%s: tx_timeout", ndev->name);
 	if (!priv->reset_task_pending) {
 		priv->reset_task_pending = 1;
+		printk(", scheduling a reset");
 		netif_stop_queue(ndev);
 		schedule_work(&priv->reset_task);
 	}
-
-	return;
+	printk("\n");
 }
diff -Nru a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
--- a/drivers/net/wireless/prism54/islpci_hotplug.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c	2004-10-10 22:15:16 -07:00
@@ -107,9 +107,6 @@
 	islpci_private *priv;
 	int rvalue;
 
-	/* TRACE(DRV_NAME); */
-	
-	
 	/* Enable the pci device */
 	if (pci_enable_device(pdev)) {
 		printk(KERN_ERR "%s: pci_enable_device() failed.\n", DRV_NAME);
diff -Nru a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c
--- a/drivers/net/wireless/prism54/islpci_mgt.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/islpci_mgt.c	2004-10-10 22:15:16 -07:00
@@ -473,6 +473,7 @@
 		int timeleft;
 		struct islpci_mgmtframe *frame;
 
+		set_current_state(TASK_UNINTERRUPTIBLE);
 		timeleft = schedule_timeout(wait_cycle_jiffies);
 		frame = xchg(&priv->mgmt_received, NULL);
 		if (frame) {
diff -Nru a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h
--- a/drivers/net/wireless/prism54/islpci_mgt.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/islpci_mgt.h	2004-10-10 22:15:16 -07:00
@@ -31,8 +31,6 @@
 #define K_DEBUG(f, m, args...) do { if(f & m) printk(KERN_DEBUG args); } while(0)
 #define DEBUG(f, args...) K_DEBUG(f, pc_debug, args)
 
-#define TRACE(devname)   K_DEBUG(SHOW_TRACING, VERBOSE, "%s:  -> " __FUNCTION__ "()\n", devname)
-
 extern int pc_debug;
 #define init_wds 0	/* help compiler optimize away dead code */
 
diff -Nru a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
--- a/drivers/net/wireless/prism54/oid_mgt.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/oid_mgt.c	2004-10-10 22:15:16 -07:00
@@ -201,7 +201,8 @@
 	OID_U32(DOT11_OID_STATIMEOUT, 0x19000000),
 	OID_U32_C(DOT11_OID_MLMEAUTOLEVEL, 0x19000001),
 	OID_U32(DOT11_OID_BSSTIMEOUT, 0x19000002),
-	OID_UNKNOWN(DOT11_OID_ATTACHMENT, 0x19000003),
+	[DOT11_OID_ATTACHMENT] = {0x19000003, 0,
+		sizeof(struct obj_attachment), OID_TYPE_ATTACH},
 	OID_STRUCT_C(DOT11_OID_PSMBUFFER, 0x19000004, struct obj_buffer,
 		     OID_TYPE_BUFFER),
 
@@ -329,6 +330,12 @@
 			mlme->size = le16_to_cpu(mlme->size);
 			break;
 		}
+	case OID_TYPE_ATTACH:{
+			struct obj_attachment *attach = data;
+			attach->id = le16_to_cpu(attach->id);
+			attach->size = le16_to_cpu(attach->size);; 
+			break;
+	}
 	case OID_TYPE_SSID:
 	case OID_TYPE_KEY:
 	case OID_TYPE_ADDR:
@@ -392,6 +399,12 @@
 			mlme->size = cpu_to_le16(mlme->size);
 			break;
 		}
+	case OID_TYPE_ATTACH:{
+			struct obj_attachment *attach = data;
+			attach->id = cpu_to_le16(attach->id);
+			attach->size = cpu_to_le16(attach->size);; 
+			break;
+	}
 	case OID_TYPE_SSID:
 	case OID_TYPE_KEY:
 	case OID_TYPE_ADDR:
@@ -465,6 +478,42 @@
 	return ret;
 }
 
+/* None of these are cached */
+int
+mgt_set_varlen(islpci_private *priv, enum oid_num_t n, void *data, int extra_len)
+{
+	int ret = 0;
+	struct islpci_mgmtframe *response;
+	int response_op = PIMFOR_OP_ERROR;
+	int dlen;
+	u32 oid;
+
+	BUG_ON(OID_NUM_LAST <= n);
+
+	dlen = isl_oid[n].size;
+	oid = isl_oid[n].oid;
+
+	mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, data);
+
+	if (islpci_get_state(priv) >= PRV_STATE_READY) {
+		ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid,
+					     data, dlen + extra_len, &response);
+		if (!ret) {
+			response_op = response->header->operation;
+			islpci_mgt_release(response);
+		}
+		if (ret || response_op == PIMFOR_OP_ERROR)
+			ret = -EIO;
+	} else 
+		ret = -EIO;
+
+	/* re-set given data to what it was */
+	if (data)
+		mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, data);
+
+	return ret;
+}
+
 int
 mgt_get_request(islpci_private *priv, enum oid_num_t n, int extra, void *data,
 		union oid_res_t *res)
@@ -555,15 +604,18 @@
 		u32 oid = t->oid;
 		BUG_ON(data == NULL);
 		while (j <= t->range) {
-			response = NULL;
-			ret |= islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET,
+			int r = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET,
 						      oid, data, t->size,
 						      &response);
 			if (response) {
-				ret |= (response->header->operation ==
-					PIMFOR_OP_ERROR);
+				r |= (response->header->operation == PIMFOR_OP_ERROR);
 				islpci_mgt_release(response);
 			}
+			if (r)
+				printk(KERN_ERR "%s: mgt_commit_list: failure. "
+					"oid=%08x err=%d\n",
+					priv->ndev->name, oid, r);
+			ret |= r;
 			j++;
 			oid++;
 			data += t->size;
@@ -624,7 +676,7 @@
 static int
 mgt_update_addr(islpci_private *priv)
 {
-	struct islpci_mgmtframe *res = NULL;
+	struct islpci_mgmtframe *res;
 	int ret;
 
 	ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET,
@@ -638,26 +690,26 @@
 	if (res)
 		islpci_mgt_release(res);
 
+	if (ret)
+		printk(KERN_ERR "%s: mgt_update_addr: failure\n", priv->ndev->name);
 	return ret;
 }
 
-void
+#define VEC_SIZE(a) (sizeof(a)/sizeof(a[0]))
+
+int
 mgt_commit(islpci_private *priv)
 {
 	int rvalue;
 	u32 u;
 
 	if (islpci_get_state(priv) < PRV_STATE_INIT)
-		return;
+		return 0;
 
-	rvalue = mgt_commit_list(priv, commit_part1,
-				 sizeof (commit_part1) /
-				 sizeof (commit_part1[0]));
+	rvalue = mgt_commit_list(priv, commit_part1, VEC_SIZE(commit_part1));
 
 	if (priv->iw_mode != IW_MODE_MONITOR)
-		rvalue |= mgt_commit_list(priv, commit_part2,
-					  sizeof (commit_part2) /
-					  sizeof (commit_part2[0]));
+		rvalue |= mgt_commit_list(priv, commit_part2, VEC_SIZE(commit_part2));
 
 	u = OID_INL_MODE;
 	rvalue |= mgt_commit_list(priv, &u, 1);
@@ -666,9 +718,43 @@
 	if (rvalue) {
 		/* some request have failed. The device might be in an
 		   incoherent state. We should reset it ! */
-		printk(KERN_DEBUG "%s: mgt_commit has failed. Restart the "
-		       "device \n", priv->ndev->name);
+		printk(KERN_DEBUG "%s: mgt_commit: failure\n", priv->ndev->name);
 	}
+	return rvalue;
+}
+
+/* The following OIDs need to be "unlatched":
+ *
+ * MEDIUMLIMIT,BEACONPERIOD,DTIMPERIOD,ATIMWINDOW,LISTENINTERVAL
+ * FREQUENCY,EXTENDEDRATES.
+ *
+ * The way to do this is to set ESSID. Note though that they may get 
+ * unlatch before though by setting another OID. */
+void
+mgt_unlatch_all(islpci_private *priv)
+{
+	u32 u;
+	int rvalue = 0;
+
+	if (islpci_get_state(priv) < PRV_STATE_INIT)
+		return;
+
+	u = DOT11_OID_SSID;
+	rvalue = mgt_commit_list(priv, &u, 1);
+	/* Necessary if in MANUAL RUN mode? */
+#if 0
+	u = OID_INL_MODE;
+	rvalue |= mgt_commit_list(priv, &u, 1);
+
+	u = DOT11_OID_MLMEAUTOLEVEL;
+	rvalue |= mgt_commit_list(priv, &u, 1);
+
+	u = OID_INL_MODE;
+	rvalue |= mgt_commit_list(priv, &u, 1);
+#endif
+
+	if (rvalue)
+		printk(KERN_DEBUG "%s: Unlatching OIDs failed\n", priv->ndev->name);
 }
 
 /* This will tell you if you are allowed to answer a mlme(ex) request .*/
@@ -769,6 +855,14 @@
 					"id=0x%X\nstate=0x%X\n"
 					"code=0x%X\nsize=0x%X\n", mlme->id,
 					mlme->state, mlme->code, mlme->size);
+		}
+		break;
+	case OID_TYPE_ATTACH:{
+			struct obj_attachment *attach = r->ptr;
+			return snprintf(str, PRIV_STR_SIZE,
+					"id=%d\nsize=%d\n",
+					attach->id,
+					attach->size);
 		}
 		break;
 	case OID_TYPE_SSID:{
diff -Nru a/drivers/net/wireless/prism54/oid_mgt.h b/drivers/net/wireless/prism54/oid_mgt.h
--- a/drivers/net/wireless/prism54/oid_mgt.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/prism54/oid_mgt.h	2004-10-10 22:15:16 -07:00
@@ -36,6 +36,8 @@
 void mgt_le_to_cpu(int, void *);
 
 int mgt_set_request(islpci_private *, enum oid_num_t, int, void *);
+int mgt_set_varlen(islpci_private *, enum oid_num_t, void *, int);
+
 
 int mgt_get_request(islpci_private *, enum oid_num_t, int, void *,
 		    union oid_res_t *);
@@ -46,7 +48,8 @@
 
 void mgt_get(islpci_private *, enum oid_num_t, void *);
 
-void mgt_commit(islpci_private *);
+int mgt_commit(islpci_private *);
+void mgt_unlatch_all(islpci_private *);
 
 int mgt_mlme_answer(islpci_private *);
 
diff -Nru a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
--- a/drivers/net/wireless/wavelan.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/wavelan.c	2004-10-10 22:15:16 -07:00
@@ -2172,6 +2172,11 @@
 	range->num_bitrates = 1;
 	range->bitrate[0] = 2000000;	/* 2 Mb/s */
 
+	/* Event capability (kernel + driver) */
+	range->event_capa[0] = (IW_EVENT_CAPA_MASK(0x8B02) |
+				IW_EVENT_CAPA_MASK(0x8B04));
+	range->event_capa[1] = IW_EVENT_CAPA_K_1;
+
 	/* Disable interrupts and save flags. */
 	spin_lock_irqsave(&lp->spinlock, flags);
 	
@@ -2403,11 +2408,10 @@
 	.num_standard	= sizeof(wavelan_handler)/sizeof(iw_handler),
 	.num_private	= sizeof(wavelan_private_handler)/sizeof(iw_handler),
 	.num_private_args = sizeof(wavelan_private_args)/sizeof(struct iw_priv_args),
-	.standard	= (iw_handler *) wavelan_handler,
-	.private	= (iw_handler *) wavelan_private_handler,
-	.private_args	= (struct iw_priv_args *) wavelan_private_args,
-	.spy_offset	= ((void *) (&((net_local *) NULL)->spy_data) -
-			   (void *) NULL),
+	.standard	= wavelan_handler,
+	.private	= wavelan_private_handler,
+	.private_args	= wavelan_private_args,
+	.get_wireless_stats = wavelan_get_wireless_stats,
 };
 
 /*------------------------------------------------------------------*/
@@ -4191,8 +4195,9 @@
 #endif				/* SET_MAC_ADDRESS */
 
 #ifdef WIRELESS_EXT		/* if wireless extension exists in the kernel */
-	dev->get_wireless_stats = wavelan_get_wireless_stats;
-	dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def;
+	dev->wireless_handlers = &wavelan_handler_def;
+	lp->wireless_data.spy_data = &lp->spy_data;
+	dev->wireless_data = &lp->wireless_data;
 #endif
 
 	dev->mtu = WAVELAN_MTU;
diff -Nru a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
--- a/drivers/net/wireless/wavelan.p.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/wavelan.p.h	2004-10-10 22:15:16 -07:00
@@ -510,6 +510,7 @@
   iw_stats	wstats;		/* Wireless-specific statistics */
 
   struct iw_spy_data	spy_data;
+  struct iw_public_data	wireless_data;
 #endif
 
 #ifdef HISTOGRAM
@@ -614,6 +615,8 @@
 /* ------------------- IOCTL, STATS & RECONFIG ------------------- */
 static en_stats	*
 	wavelan_get_stats(struct net_device *);	/* Give stats /proc/net/dev */
+static iw_stats *
+	wavelan_get_wireless_stats(struct net_device *);
 static void
 	wavelan_set_multicast_list(struct net_device *);
 /* ----------------------- PACKET RECEPTION ----------------------- */
diff -Nru a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
--- a/drivers/net/wireless/wavelan_cs.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/wavelan_cs.c	2004-10-10 22:15:16 -07:00
@@ -502,7 +502,7 @@
   
 void wv_roam_init(struct net_device *dev)
 {
-  net_local  *lp= (net_local *)dev->priv;
+  net_local  *lp= netdev_priv(dev);
 
   /* Do not remove this unless you have a good reason */
   printk(KERN_NOTICE "%s: Warning, you have enabled roaming on"
@@ -532,7 +532,7 @@
 void wv_roam_cleanup(struct net_device *dev)
 {
   wavepoint_history *ptr,*old_ptr;
-  net_local *lp= (net_local *)dev->priv;
+  net_local *lp= netdev_priv(dev);
   
   printk(KERN_DEBUG "WaveLAN: Roaming Disabled on device %s\n",dev->name);
   
@@ -762,7 +762,7 @@
   unsigned short nwid=ntohs(beacon->nwid);  
   unsigned short sigqual=stats[2] & MMR_SGNL_QUAL;   /* SNR of beacon */
   wavepoint_history *wavepoint=NULL;                /* WavePoint table entry */
-  net_local *lp=(net_local *)dev->priv;              /* Device info */
+  net_local *lp = netdev_priv(dev);              /* Device info */
 
 #ifdef I_NEED_THIS_FEATURE
   /* Some people don't need this, some other may need it */
@@ -1006,7 +1006,7 @@
 static inline void
 wv_82593_reconfig(struct net_device *	dev)
 {
-  net_local *		lp = (net_local *)dev->priv;
+  net_local *		lp = netdev_priv(dev);
   dev_link_t *		link = lp->link;
   unsigned long		flags;
 
@@ -1135,7 +1135,7 @@
 wv_mmc_show(struct net_device *	dev)
 {
   ioaddr_t	base = dev->base_addr;
-  net_local *	lp = (net_local *)dev->priv;
+  net_local *	lp = netdev_priv(dev);
   mmr_t		m;
 
   /* Basic check */
@@ -1224,7 +1224,7 @@
 static void
 wv_ru_show(struct net_device *	dev)
 {
-  net_local *lp = (net_local *) dev->priv;
+  net_local *lp = netdev_priv(dev);
 
   printk(KERN_DEBUG "##### wavelan i82593 receiver status: #####\n");
   printk(KERN_DEBUG "ru: rfp %d stop %d", lp->rfp, lp->stop);
@@ -1258,9 +1258,7 @@
 static void
 wv_local_show(struct net_device *	dev)
 {
-  net_local *lp;
-
-  lp = (net_local *)dev->priv;
+  net_local *lp = netdev_priv(dev);
 
   printk(KERN_DEBUG "local:");
   /*
@@ -1418,7 +1416,7 @@
   printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name);
 #endif
 
-  return(&((net_local *) dev->priv)->stats);
+  return(&((net_local *)netdev_priv(dev))->stats);
 }
 
 /*------------------------------------------------------------------*/
@@ -1433,7 +1431,7 @@
 static void
 wavelan_set_multicast_list(struct net_device *	dev)
 {
-  net_local *	lp = (net_local *) dev->priv;
+  net_local *	lp = netdev_priv(dev);
 
 #ifdef DEBUG_IOCTL_TRACE
   printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n", dev->name);
@@ -1550,7 +1548,6 @@
 /*
  * Frequency setting (for hardware able of it)
  * It's a bit complicated and you don't really want to look into it...
- * (called in wavelan_ioctl)
  */
 static inline int
 wv_set_frequency(u_long		base,	/* i/o port of the card */
@@ -1826,7 +1823,7 @@
 wl_his_gather(struct net_device *	dev,
 	      u_char *	stats)		/* Statistics to gather */
 {
-  net_local *	lp = (net_local *) dev->priv;
+  net_local *	lp = netdev_priv(dev);
   u_char	level = stats[0] & MMR_SIGNAL_LVL;
   int		i;
 
@@ -1840,28 +1837,15 @@
 }
 #endif	/* HISTOGRAM */
 
-static inline int
-wl_netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void wl_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	u32 ethcmd;
-
-	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
-		return -EFAULT;
-
-	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-
-		strncpy(info.driver, "wavelan_cs", sizeof(info.driver)-1);
-		if (copy_to_user(useraddr, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	}
-
-	return -EOPNOTSUPP;
+	strncpy(info->driver, "wavelan_cs", sizeof(info->driver)-1);
 }
 
+static struct ethtool_ops ops = {
+	.get_drvinfo = wl_get_drvinfo
+};
+
 /*------------------------------------------------------------------*/
 /*
  * Wireless Handler : get protocol name
@@ -1885,7 +1869,7 @@
 			    char *extra)
 {
 	ioaddr_t base = dev->base_addr;
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	psa_t psa;
 	mm_t m;
 	unsigned long flags;
@@ -1943,7 +1927,7 @@
 			    union iwreq_data *wrqu,
 			    char *extra)
 {
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	psa_t psa;
 	unsigned long flags;
 	int ret = 0;
@@ -1975,7 +1959,7 @@
 			    char *extra)
 {
 	ioaddr_t base = dev->base_addr;
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	unsigned long flags;
 	int ret;
 
@@ -2005,7 +1989,7 @@
 			    char *extra)
 {
 	ioaddr_t base = dev->base_addr;
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	psa_t psa;
 	unsigned long flags;
 	int ret = 0;
@@ -2051,7 +2035,7 @@
 			    char *extra)
 {
 	ioaddr_t base = dev->base_addr;
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	psa_t psa;
 	unsigned long flags;
 	int ret = 0;
@@ -2086,7 +2070,7 @@
 			    union iwreq_data *wrqu,
 			    char *extra)
 {
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	psa_t psa;
 	unsigned long flags;
 	int ret = 0;
@@ -2117,7 +2101,7 @@
 			      char *extra)
 {
 	ioaddr_t base = dev->base_addr;
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	unsigned long flags;
 	psa_t psa;
 	int ret = 0;
@@ -2187,7 +2171,7 @@
 			      char *extra)
 {
 	ioaddr_t base = dev->base_addr;
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	psa_t psa;
 	unsigned long flags;
 	int ret = 0;
@@ -2234,7 +2218,7 @@
 			     union iwreq_data *wrqu,
 			     char *extra)
 {
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	unsigned long flags;
 	int ret = 0;
 
@@ -2282,7 +2266,7 @@
 			     union iwreq_data *wrqu,
 			     char *extra)
 {
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 
 	/* Is the domain ID active ? */
 	wrqu->data.flags = lp->filter_domains;
@@ -2347,7 +2331,7 @@
 			    union iwreq_data *wrqu,
 			    char *extra)
 {
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	unsigned long flags;
 	int ret = 0;
 
@@ -2406,7 +2390,7 @@
 			     char *extra)
 {
 	ioaddr_t base = dev->base_addr;
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	struct iw_range *range = (struct iw_range *) extra;
 	unsigned long flags;
 	int ret = 0;
@@ -2438,6 +2422,12 @@
 	range->num_bitrates = 1;
 	range->bitrate[0] = 2000000;	/* 2 Mb/s */
 
+	/* Event capability (kernel + driver) */
+	range->event_capa[0] = (IW_EVENT_CAPA_MASK(0x8B02) |
+				IW_EVENT_CAPA_MASK(0x8B04) |
+				IW_EVENT_CAPA_MASK(0x8B06));
+	range->event_capa[1] = IW_EVENT_CAPA_K_1;
+
 	/* Disable interrupts and save flags. */
 	spin_lock_irqsave(&lp->spinlock, flags);
 	
@@ -2476,7 +2466,7 @@
 			    char *extra)
 {
 	ioaddr_t base = dev->base_addr;
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	psa_t psa;
 	unsigned long flags;
 
@@ -2507,7 +2497,7 @@
 			    union iwreq_data *wrqu,
 			    char *extra)
 {
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	psa_t psa;
 	unsigned long flags;
 
@@ -2535,7 +2525,7 @@
 			    union iwreq_data *wrqu,
 			    char *extra)
 {
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 	unsigned long flags;
 
 	/* Disable interrupts and save flags. */
@@ -2580,7 +2570,7 @@
 			     union iwreq_data *wrqu,
 			     char *extra)
 {
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 
 	/* Check the number of intervals. */
 	if (wrqu->data.length > 16) {
@@ -2623,7 +2613,7 @@
 			     union iwreq_data *wrqu,
 			     char *extra)
 {
-	net_local *lp = (net_local *) dev->priv;	/* lp is not unused */
+	net_local *lp = netdev_priv(dev);
 
 	/* Set the number of intervals. */
 	wrqu->data.length = lp->his_number;
@@ -2737,50 +2727,14 @@
 	.num_standard	= sizeof(wavelan_handler)/sizeof(iw_handler),
 	.num_private	= sizeof(wavelan_private_handler)/sizeof(iw_handler),
 	.num_private_args = sizeof(wavelan_private_args)/sizeof(struct iw_priv_args),
-	.standard	= (iw_handler *) wavelan_handler,
-	.private	= (iw_handler *) wavelan_private_handler,
-	.private_args	= (struct iw_priv_args *) wavelan_private_args,
-	.spy_offset	= ((void *) (&((net_local *) NULL)->spy_data) -
-			   (void *) NULL),
+	.standard	= wavelan_handler,
+	.private	= wavelan_private_handler,
+	.private_args	= wavelan_private_args,
+	.get_wireless_stats = wavelan_get_wireless_stats,
 };
 
 /*------------------------------------------------------------------*/
 /*
- * Perform ioctl : config & info stuff
- * This is here that are treated the wireless extensions (iwconfig)
- */
-static int
-wavelan_ioctl(struct net_device *	dev,	/* Device on wich the ioctl apply */
-	      struct ifreq *	rq,	/* Data passed */
-	      int		cmd)	/* Ioctl number */
-{
-  int			ret = 0;
-
-#ifdef DEBUG_IOCTL_TRACE
-  printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, cmd);
-#endif
-
-  /* Look what is the request */
-  switch(cmd)
-    {
-    case SIOCETHTOOL:
-      ret = wl_netdev_ethtool_ioctl(dev, rq->ifr_data);
-      break;
-
-      /* ------------------- OTHER IOCTL ------------------- */
-
-    default:
-      ret = -EOPNOTSUPP;
-    }
-
-#ifdef DEBUG_IOCTL_TRACE
-  printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
-#endif
-  return ret;
-}
-
-/*------------------------------------------------------------------*/
-/*
  * Get wireless statistics
  * Called by /proc/net/wireless...
  */
@@ -2788,7 +2742,7 @@
 wavelan_get_wireless_stats(struct net_device *	dev)
 {
   ioaddr_t		base = dev->base_addr;
-  net_local *		lp = (net_local *) dev->priv;
+  net_local *		lp = netdev_priv(dev);
   mmr_t			m;
   iw_stats *		wstats;
   unsigned long		flags;
@@ -2913,7 +2867,7 @@
 	       int		fd_p,
 	       int		sksize)
 {
-  net_local *		lp = (net_local *) dev->priv;
+  net_local *		lp = netdev_priv(dev);
   struct sk_buff *	skb;
 
 #ifdef DEBUG_RX_TRACE
@@ -3015,7 +2969,7 @@
 wv_packet_rcv(struct net_device *	dev)
 {
   ioaddr_t	base = dev->base_addr;
-  net_local *	lp = (net_local *) dev->priv;
+  net_local *	lp = netdev_priv(dev);
   int		newrfp;
   int		rp;
   int		len;
@@ -3150,7 +3104,7 @@
 		void *		buf,
 		short		length)
 {
-  net_local *		lp = (net_local *) dev->priv;
+  net_local *		lp = netdev_priv(dev);
   ioaddr_t		base = dev->base_addr;
   unsigned long		flags;
   int			clen = length;
@@ -3211,7 +3165,7 @@
 wavelan_packet_xmit(struct sk_buff *	skb,
 		    struct net_device *		dev)
 {
-  net_local *		lp = (net_local *)dev->priv;
+  net_local *		lp = netdev_priv(dev);
   unsigned long		flags;
 
 #ifdef DEBUG_TX_TRACE
@@ -3470,7 +3424,7 @@
 wv_ru_stop(struct net_device *	dev)
 {
   ioaddr_t	base = dev->base_addr;
-  net_local *	lp = (net_local *) dev->priv;
+  net_local *	lp = netdev_priv(dev);
   unsigned long	flags;
   int		status;
   int		spin;
@@ -3533,7 +3487,7 @@
 wv_ru_start(struct net_device *	dev)
 {
   ioaddr_t	base = dev->base_addr;
-  net_local *	lp = (net_local *) dev->priv;
+  net_local *	lp = netdev_priv(dev);
   unsigned long	flags;
 
 #ifdef DEBUG_CONFIG_TRACE
@@ -3621,7 +3575,7 @@
 wv_82593_config(struct net_device *	dev)
 {
   ioaddr_t			base = dev->base_addr;
-  net_local *			lp = (net_local *) dev->priv;
+  net_local *			lp = netdev_priv(dev);
   struct i82593_conf_block	cfblk;
   int				ret = TRUE;
 
@@ -3796,7 +3750,7 @@
 {
   int		i;
   conf_reg_t	reg = { 0, CS_READ, CISREG_COR, 0 };
-  dev_link_t *	link = ((net_local *) dev->priv)->link;
+  dev_link_t *	link = ((net_local *)netdev_priv(dev))->link;
 
 #ifdef DEBUG_CONFIG_TRACE
   printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name);
@@ -3856,7 +3810,7 @@
 static int
 wv_hw_config(struct net_device *	dev)
 {
-  net_local *		lp = (net_local *) dev->priv;
+  net_local *		lp = netdev_priv(dev);
   ioaddr_t		base = dev->base_addr;
   unsigned long		flags;
   int			ret = FALSE;
@@ -3963,7 +3917,7 @@
 static inline void
 wv_hw_reset(struct net_device *	dev)
 {
-  net_local *	lp = (net_local *) dev->priv;
+  net_local *	lp = netdev_priv(dev);
 
 #ifdef DEBUG_CONFIG_TRACE
   printk(KERN_DEBUG "%s: ->wv_hw_reset()\n", dev->name);
@@ -4131,8 +4085,8 @@
       return FALSE;
     }
 
-  strcpy(((net_local *) dev->priv)->node.dev_name, dev->name);
-  link->dev = &((net_local *) dev->priv)->node;
+  strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name);
+  link->dev = &((net_local *) netdev_priv(dev))->node;
 
 #ifdef DEBUG_CONFIG_TRACE
   printk(KERN_DEBUG "<-wv_pcmcia_config()\n");
@@ -4203,7 +4157,7 @@
   printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name);
 #endif
 
-  lp = (net_local *) dev->priv;
+  lp = netdev_priv(dev);
   base = dev->base_addr;
 
 #ifdef DEBUG_INTERRUPT_INFO
@@ -4453,7 +4407,7 @@
 static void
 wavelan_watchdog(struct net_device *	dev)
 {
-  net_local *		lp = (net_local *) dev->priv;
+  net_local *		lp = netdev_priv(dev);
   ioaddr_t		base = dev->base_addr;
   unsigned long		flags;
   int			aborted = FALSE;
@@ -4528,8 +4482,8 @@
 static int
 wavelan_open(struct net_device *	dev)
 {
-  dev_link_t *	link = ((net_local *) dev->priv)->link;
-  net_local *	lp = (net_local *)dev->priv;
+  net_local *	lp = netdev_priv(dev);
+  dev_link_t *	link = lp->link;
   ioaddr_t	base = dev->base_addr;
 
 #ifdef DEBUG_CALLBACK_TRACE
@@ -4583,7 +4537,7 @@
 static int
 wavelan_close(struct net_device *	dev)
 {
-  dev_link_t *	link = ((net_local *) dev->priv)->link;
+  dev_link_t *	link = ((net_local *)netdev_priv(dev))->link;
   ioaddr_t	base = dev->base_addr;
 
 #ifdef DEBUG_CALLBACK_TRACE
@@ -4686,7 +4640,7 @@
   }
   link->priv = link->irq.Instance = dev;
 
-  lp = dev->priv;
+  lp = netdev_priv(dev);
 
   /* Init specific data */
   lp->configured = 0;
@@ -4718,11 +4672,12 @@
   /* Set the watchdog timer */
   dev->tx_timeout	= &wavelan_watchdog;
   dev->watchdog_timeo	= WATCHDOG_JIFFIES;
+  SET_ETHTOOL_OPS(dev, &ops);
 
 #ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
-  dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def;
-  dev->do_ioctl = wavelan_ioctl;	/* old wireless extensions */
-  dev->get_wireless_stats = wavelan_get_wireless_stats;
+  dev->wireless_handlers = &wavelan_handler_def;
+  lp->wireless_data.spy_data = &lp->spy_data;
+  dev->wireless_data = &lp->wireless_data;
 #endif
 
   /* Other specific data */
@@ -4820,8 +4775,8 @@
       if (link->dev)
 	unregister_netdev(dev);
       link->dev = NULL;
-      ((net_local *) dev->priv)->link = NULL;
-      ((net_local *) dev->priv)->dev = NULL;
+      ((net_local *)netdev_priv(dev))->link = NULL;
+      ((net_local *)netdev_priv(dev))->dev = NULL;
       free_netdev(dev);
     }
   kfree(link);
diff -Nru a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
--- a/drivers/net/wireless/wavelan_cs.p.h	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/wireless/wavelan_cs.p.h	2004-10-10 22:15:16 -07:00
@@ -629,6 +629,7 @@
   iw_stats	wstats;		/* Wireless specific stats */
 
   struct iw_spy_data	spy_data;
+  struct iw_public_data	wireless_data;
 #endif
 
 #ifdef HISTOGRAM
@@ -725,6 +726,8 @@
 /* ------------------- IOCTL, STATS & RECONFIG ------------------- */
 static en_stats	*
 	wavelan_get_stats(struct net_device *);	/* Give stats /proc/net/dev */
+static iw_stats *
+	wavelan_get_wireless_stats(struct net_device *);
 /* ----------------------- PACKET RECEPTION ----------------------- */
 static inline int
 	wv_start_of_frame(struct net_device *,	/* Seek beggining of current frame */
diff -Nru a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
--- a/drivers/net/wireless/wl3501_cs.c	2004-10-10 22:15:15 -07:00
+++ b/drivers/net/wireless/wl3501_cs.c	2004-10-10 22:15:16 -07:00
@@ -1487,55 +1487,14 @@
 	return wstats;
 }
 
-static inline int wl3501_ethtool_ioctl(struct net_device *dev, void __user *uaddr)
+static void wl3501_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	u32 ethcmd;
-	int rc = -EFAULT;
-
-	if (copy_from_user(&ethcmd, uaddr, sizeof(ethcmd)))
-		goto out;
-
-	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = { .cmd = ETHTOOL_GDRVINFO, };
-
-		strlcpy(info.driver, wl3501_dev_info, sizeof(info.driver));
-		rc = copy_to_user(uaddr, &info, sizeof(info)) ? -EFAULT : 1;
-	}
-	default:
-		rc = -EOPNOTSUPP;
-		break;
-	}
-out:
-	return rc;
+	strlcpy(info->driver, wl3501_dev_info, sizeof(info->driver));
 }
 
-/**
- * wl3501_ioctl - Perform IOCTL call functions
- * @dev - network device
- * @ifreq - request
- * @cmd - command
- *
- * Perform IOCTL call functions here. Some are privileged operations and the
- * effective uid is checked in those cases.
- *
- * This part is optional. Needed only if you want to run wlu (unix version).
- *
- * CAUTION: To prevent interrupted by wl3501_interrupt() and timer-based
- * wl3501_hard_start_xmit() from other interrupts, this should be run
- * single-threaded.
- */
-static int wl3501_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	int rc = -ENODEV;
-
-	if (netif_device_present(dev)) {
-		rc = -EOPNOTSUPP;
-		if (cmd == SIOCETHTOOL)
-			rc = wl3501_ethtool_ioctl(dev, rq->ifr_data);
-	}
-	return rc;
-}
+static struct ethtool_ops ops = {
+	.get_drvinfo = wl3501_get_drvinfo
+};
 
 /**
  * wl3501_detach - deletes a driver "instance"
@@ -2047,8 +2006,8 @@
 	dev->watchdog_timeo	= 5 * HZ;
 	dev->get_stats		= wl3501_get_stats;
 	dev->get_wireless_stats = wl3501_get_wireless_stats;
-	dev->do_ioctl		= wl3501_ioctl;
 	dev->wireless_handlers	= (struct iw_handler_def *)&wl3501_handler_def;
+	SET_ETHTOOL_OPS(dev, &ops);
 	netif_stop_queue(dev);
 	link->priv = link->irq.Instance = dev;
 
diff -Nru a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
--- a/drivers/net/yellowfin.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/net/yellowfin.c	2004-10-10 22:15:16 -07:00
@@ -406,6 +406,7 @@
 static int yellowfin_close(struct net_device *dev);
 static struct net_device_stats *yellowfin_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
+static struct ethtool_ops ethtool_ops;
 
 
 static int __devinit yellowfin_init_one(struct pci_dev *pdev,
@@ -440,7 +441,7 @@
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	np = dev->priv;
+	np = netdev_priv(dev);
 
 	if (pci_request_regions(pdev, DRV_NAME))
 		goto err_out_free_netdev;
@@ -521,6 +522,7 @@
 	dev->get_stats = &yellowfin_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &netdev_ioctl;
+	SET_ETHTOOL_OPS(dev, &ethtool_ops);
 	dev->tx_timeout = yellowfin_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
@@ -619,7 +621,7 @@
 
 static int yellowfin_open(struct net_device *dev)
 {
-	struct yellowfin_private *yp = dev->priv;
+	struct yellowfin_private *yp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int i;
 
@@ -701,7 +703,7 @@
 static void yellowfin_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
-	struct yellowfin_private *yp = dev->priv;
+	struct yellowfin_private *yp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	int next_tick = 60*HZ;
 
@@ -735,7 +737,7 @@
 
 static void yellowfin_tx_timeout(struct net_device *dev)
 {
-	struct yellowfin_private *yp = dev->priv;
+	struct yellowfin_private *yp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 
 	printk(KERN_WARNING "%s: Yellowfin transmit timed out at %d/%d Tx "
@@ -772,7 +774,7 @@
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void yellowfin_init_ring(struct net_device *dev)
 {
-	struct yellowfin_private *yp = dev->priv;
+	struct yellowfin_private *yp = netdev_priv(dev);
 	int i;
 
 	yp->tx_full = 0;
@@ -855,7 +857,7 @@
 
 static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct yellowfin_private *yp = dev->priv;
+	struct yellowfin_private *yp = netdev_priv(dev);
 	unsigned entry;
 	int len = skb->len;
 
@@ -953,7 +955,7 @@
 #endif
 
 	ioaddr = dev->base_addr;
-	yp = dev->priv;
+	yp = netdev_priv(dev);
 	
 	spin_lock (&yp->lock);
 
@@ -1095,7 +1097,7 @@
    for clarity and better register allocation. */
 static int yellowfin_rx(struct net_device *dev)
 {
-	struct yellowfin_private *yp = dev->priv;
+	struct yellowfin_private *yp = netdev_priv(dev);
 	int entry = yp->cur_rx % RX_RING_SIZE;
 	int boguscnt = yp->dirty_rx + RX_RING_SIZE - yp->cur_rx;
 
@@ -1239,7 +1241,7 @@
 
 static void yellowfin_error(struct net_device *dev, int intr_status)
 {
-	struct yellowfin_private *yp = dev->priv;
+	struct yellowfin_private *yp = netdev_priv(dev);
 
 	printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
 		   dev->name, intr_status);
@@ -1253,7 +1255,7 @@
 static int yellowfin_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	struct yellowfin_private *yp = dev->priv;
+	struct yellowfin_private *yp = netdev_priv(dev);
 	int i;
 
 	netif_stop_queue (dev);
@@ -1340,7 +1342,7 @@
 
 static struct net_device_stats *yellowfin_get_stats(struct net_device *dev)
 {
-	struct yellowfin_private *yp = dev->priv;
+	struct yellowfin_private *yp = netdev_priv(dev);
 	return &yp->stats;
 }
 
@@ -1348,7 +1350,7 @@
 
 static void set_rx_mode(struct net_device *dev)
 {
-	struct yellowfin_private *yp = dev->priv;
+	struct yellowfin_private *yp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	u16 cfg_value = inw(ioaddr + Cnfg);
 
@@ -1394,39 +1396,25 @@
 	outw(cfg_value | 0x1000, ioaddr + Cnfg);
 }
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void yellowfin_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	struct yellowfin_private *np = dev->priv;
-	u32 ethcmd;
-		
-	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
-		return -EFAULT;
-
-        switch (ethcmd) {
-        case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-		strcpy(info.driver, DRV_NAME);
-		strcpy(info.version, DRV_VERSION);
-		strcpy(info.bus_info, pci_name(np->pci_dev));
-		if (copy_to_user(useraddr, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-
-        }
-	
-	return -EOPNOTSUPP;
+	struct yellowfin_private *np = netdev_priv(dev);
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, pci_name(np->pci_dev));
 }
 
+static struct ethtool_ops ethtool_ops = {
+	.get_drvinfo = yellowfin_get_drvinfo
+};
+
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct yellowfin_private *np = dev->priv;
+	struct yellowfin_private *np = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
 	struct mii_ioctl_data *data = if_mii(rq);
 
 	switch(cmd) {
-	case SIOCETHTOOL:
-		return netdev_ethtool_ioctl(dev, rq->ifr_data);
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
 		data->phy_id = np->phys[0] & 0x1f;
 		/* Fall Through */
@@ -1466,7 +1454,7 @@
 
 	if (!dev)
 		BUG();
-	np = dev->priv;
+	np = netdev_priv(dev);
 
         pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, 
 		np->tx_status_dma);
diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
--- a/drivers/usb/gadget/ether.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/usb/gadget/ether.c	2004-10-10 22:15:16 -07:00
@@ -1670,7 +1670,7 @@
 
 static int eth_change_mtu (struct net_device *net, int new_mtu)
 {
-	struct eth_dev	*dev = (struct eth_dev *) net->priv;
+	struct eth_dev	*dev = netdev_priv(net);
 
 	// FIXME if rndis, don't change while link's live
 
@@ -1685,58 +1685,29 @@
 
 static struct net_device_stats *eth_get_stats (struct net_device *net)
 {
-	return &((struct eth_dev *) net->priv)->stats;
+	return &((struct eth_dev *)netdev_priv(net))->stats;
 }
 
-static int eth_ethtool_ioctl (struct net_device *net, void __user *useraddr)
+static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
 {
-	struct eth_dev	*dev = (struct eth_dev *) net->priv;
-	u32		cmd;
-
-	if (get_user (cmd, (u32 __user *)useraddr))
-		return -EFAULT;
-	switch (cmd) {
-
-	case ETHTOOL_GDRVINFO: {	/* get driver info */
-		struct ethtool_drvinfo		info;
-
-		memset (&info, 0, sizeof info);
-		info.cmd = ETHTOOL_GDRVINFO;
-		strlcpy (info.driver, shortname, sizeof info.driver);
-		strlcpy (info.version, DRIVER_VERSION, sizeof info.version);
-		strlcpy (info.fw_version, dev->gadget->name,
-			sizeof info.fw_version);
-		strlcpy (info.bus_info, dev->gadget->dev.bus_id,
-			sizeof info.bus_info);
-		if (copy_to_user (useraddr, &info, sizeof (info)))
-			return -EFAULT;
-		return 0;
-		}
-
-	case ETHTOOL_GLINK: {		/* get link status */
-		struct ethtool_value	edata = { ETHTOOL_GLINK };
-
-		edata.data = (dev->gadget->speed != USB_SPEED_UNKNOWN);
-		if (copy_to_user (useraddr, &edata, sizeof (edata)))
-			return -EFAULT;
-		return 0;
-		}
-
-	}
-	/* Note that the ethtool user space code requires EOPNOTSUPP */
-	return -EOPNOTSUPP;
+	struct eth_dev	*dev = netdev_priv(net);
+	strlcpy(p->driver, shortname, sizeof p->driver);
+	strlcpy(p->version, DRIVER_VERSION, sizeof p->version);
+	strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version);
+	strlcpy (p->bus_info, dev->gadget->dev.bus_id, sizeof p->bus_info);
 }
 
-static int eth_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+static u32 eth_get_link(struct net_device *net)
 {
-	switch (cmd) {
-	case SIOCETHTOOL:
-		return eth_ethtool_ioctl(net, rq->ifr_data);
-	default:
-		return -EOPNOTSUPP;
-	}
+	struct eth_dev	*dev = netdev_priv(net);
+	return dev->gadget->speed != USB_SPEED_UNKNOWN;
 }
 
+static struct ethtool_ops ops = {
+	.get_drvinfo = eth_get_drvinfo,
+	.get_link = eth_get_link
+};
+
 static void defer_kevent (struct eth_dev *dev, int flag)
 {
 	if (test_and_set_bit (flag, &dev->todo))
@@ -1997,7 +1968,7 @@
 
 static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
 {
-	struct eth_dev		*dev = (struct eth_dev *) net->priv;
+	struct eth_dev		*dev = netdev_priv(net);
 	int			length = skb->len;
 	int			retval;
 	struct usb_request	*req = NULL;
@@ -2110,7 +2081,7 @@
 
 static int rndis_control_ack (struct net_device *net)
 {
-	struct eth_dev          *dev = (struct eth_dev *) net->priv;
+	struct eth_dev          *dev = netdev_priv(net);
 	u32                     length;
 	struct usb_request      *resp;
 	
@@ -2177,7 +2148,7 @@
 
 static int eth_open (struct net_device *net)
 {
-	struct eth_dev		*dev = (struct eth_dev *) net->priv;
+	struct eth_dev		*dev = netdev_priv(net);
 
 	DEBUG (dev, "%s\n", __FUNCTION__);
 	if (netif_carrier_ok (dev->net))
@@ -2187,7 +2158,7 @@
 
 static int eth_stop (struct net_device *net)
 {
-	struct eth_dev		*dev = (struct eth_dev *) net->priv;
+	struct eth_dev		*dev = netdev_priv(net);
 
 	VDEBUG (dev, "%s\n", __FUNCTION__);
 	netif_stop_queue (net);
@@ -2474,7 +2445,7 @@
  	net = alloc_etherdev (sizeof *dev);
  	if (!net)
 		return status;
-	dev = net->priv;
+	dev = netdev_priv(net);
 	spin_lock_init (&dev->lock);
 	INIT_WORK (&dev->work, eth_work, dev);
 	INIT_LIST_HEAD (&dev->tx_reqs);
@@ -2518,7 +2489,7 @@
 	net->stop = eth_stop;
 	// watchdog_timeo, tx_timeout ...
 	// set_multicast_list
-	net->do_ioctl = eth_ioctl;
+	SET_ETHTOOL_OPS(net, &ops);
 
 	/* preallocate control response and buffer */
 	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
diff -Nru a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
--- a/drivers/usb/net/catc.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/usb/net/catc.c	2004-10-10 22:15:16 -07:00
@@ -411,7 +411,7 @@
 
 static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
-	struct catc *catc = netdev->priv;
+	struct catc *catc = netdev_priv(netdev);
 	unsigned long flags;
 	char *tx_buf;
 
@@ -442,7 +442,7 @@
 
 static void catc_tx_timeout(struct net_device *netdev)
 {
-	struct catc *catc = netdev->priv;
+	struct catc *catc = netdev_priv(netdev);
 
 	warn("Transmit timed out.");
 	catc->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
@@ -604,7 +604,7 @@
 
 static struct net_device_stats *catc_get_stats(struct net_device *netdev)
 {
-	struct catc *catc = netdev->priv;
+	struct catc *catc = netdev_priv(netdev);
 	return &catc->stats;
 }
 
@@ -622,7 +622,7 @@
 
 static void catc_set_multicast_list(struct net_device *netdev)
 {
-	struct catc *catc = netdev->priv;
+	struct catc *catc = netdev_priv(netdev);
 	struct dev_mc_list *mc;
 	u8 broadcast[6];
 	u8 rx = RxEnable | RxPolarity | RxMultiCast;
@@ -664,74 +664,38 @@
 	}
 }
 
-/*
- * ioctl's
- */
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+void catc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-        struct catc *catc = dev->priv;
-        u32 cmd;
-        
-        if (get_user(cmd, (u32 __user *)useraddr))
-                return -EFAULT;
-
-        switch (cmd) {
-        /* get driver info */
-        case ETHTOOL_GDRVINFO: {
-                struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-                strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN);
-                strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
-		usb_make_path (catc->usbdev, info.bus_info, sizeof info.bus_info);
-                if (copy_to_user(useraddr, &info, sizeof(info)))
-                        return -EFAULT;
-                return 0;
-        }
-
-	/* get settings */
-	case ETHTOOL_GSET:
-		if (catc->is_f5u011) {
-			struct ethtool_cmd ecmd = { ETHTOOL_GSET, 
-						    SUPPORTED_10baseT_Half | SUPPORTED_TP, 
-						    ADVERTISED_10baseT_Half | ADVERTISED_TP, 
-						    SPEED_10, 
-						    DUPLEX_HALF, 
-						    PORT_TP, 
-						    0, 
-						    XCVR_INTERNAL, 
-						    AUTONEG_DISABLE, 
-						    1, 
-						    1 
-			};
-			if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-				return -EFAULT;
-			return 0;
-		} else {
-			return -EOPNOTSUPP;
-		}
+	struct catc *catc = netdev_priv(dev);
+	strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN);
+	strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
+	usb_make_path (catc->usbdev, info->bus_info, sizeof info->bus_info);
+}
 
-        /* get link status */
-        case ETHTOOL_GLINK: {
-                struct ethtool_value edata = {ETHTOOL_GLINK};
-                edata.data = netif_carrier_ok(dev);
-                if (copy_to_user(useraddr, &edata, sizeof(edata)))
-                        return -EFAULT;
-                return 0;
-        }
-	}
-        
-        return -EOPNOTSUPP;
-}
-
-static int catc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-        switch(cmd) {
-        case SIOCETHTOOL:
-                return netdev_ethtool_ioctl(dev, rq->ifr_data);
-        default:
-                return -EOPNOTSUPP;
-        }
+static int catc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct catc *catc = netdev_priv(dev);
+	if (!catc->is_f5u011)
+		return -EOPNOTSUPP;
+
+	cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_TP;
+	cmd->advertising = ADVERTISED_10baseT_Half | ADVERTISED_TP;
+	cmd->speed = SPEED_10;
+	cmd->duplex = DUPLEX_HALF;
+	cmd->port = PORT_TP; 
+	cmd->phy_address = 0;
+	cmd->transceiver = XCVR_INTERNAL;
+	cmd->autoneg = AUTONEG_DISABLE;
+	cmd->maxtxpkt = 1;
+	cmd->maxrxpkt = 1;
+	return 0;
 }
 
+static struct ethtool_ops ops = {
+	.get_drvinfo = catc_get_drvinfo,
+	.get_settings = catc_get_settings,
+	.get_link = ethtool_op_get_link
+};
 
 /*
  * Open, close.
@@ -739,7 +703,7 @@
 
 static int catc_open(struct net_device *netdev)
 {
-	struct catc *catc = netdev->priv;
+	struct catc *catc = netdev_priv(netdev);
 	int status;
 
 	catc->irq_urb->dev = catc->usbdev;
@@ -758,7 +722,7 @@
 
 static int catc_stop(struct net_device *netdev)
 {
-	struct catc *catc = netdev->priv;
+	struct catc *catc = netdev_priv(netdev);
 
 	netif_stop_queue(netdev);
 
@@ -791,17 +755,11 @@
 		return -EIO;
 	}
 
-	catc = kmalloc(sizeof(struct catc), GFP_KERNEL);
-	if (!catc)
+	netdev = alloc_etherdev(sizeof(struct catc));
+	if (!netdev)
 		return -ENOMEM;
 
-	memset(catc, 0, sizeof(struct catc));
-
-	netdev = alloc_etherdev(0);
-	if (!netdev) {
-		kfree(catc);
-		return -EIO;
-	}
+	catc = netdev_priv(netdev);
 
 	netdev->open = catc_open;
 	netdev->hard_start_xmit = catc_hard_start_xmit;
@@ -810,8 +768,7 @@
 	netdev->tx_timeout = catc_tx_timeout;
 	netdev->watchdog_timeo = TX_TIMEOUT;
 	netdev->set_multicast_list = catc_set_multicast_list;
-	netdev->do_ioctl = catc_ioctl;
-	netdev->priv = catc;
+	SET_ETHTOOL_OPS(netdev, &ops);
 
 	catc->usbdev = usbdev;
 	catc->netdev = netdev;
@@ -839,7 +796,6 @@
 		if (catc->irq_urb)
 			usb_free_urb(catc->irq_urb);
 		free_netdev(netdev);
-		kfree(catc);
 		return -ENOMEM;
 	}
 
@@ -944,7 +900,6 @@
 		usb_free_urb(catc->rx_urb);
 		usb_free_urb(catc->irq_urb);
 		free_netdev(netdev);
-		kfree(catc);
 		return -EIO;
 	}
 	return 0;
@@ -962,7 +917,6 @@
 		usb_free_urb(catc->rx_urb);
 		usb_free_urb(catc->irq_urb);
 		free_netdev(catc->netdev);
-		kfree(catc);
 	}
 }
 
diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
--- a/drivers/usb/net/kaweth.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/usb/net/kaweth.c	2004-10-10 22:15:16 -07:00
@@ -710,37 +710,15 @@
 	return 0;
 }
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void kaweth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	u32 ethcmd;
 
-	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
-		return -EFAULT;
-
-	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-		strlcpy(info.driver, driver_name, sizeof(info.driver));
-		if (copy_to_user(useraddr, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	}
-
-	return -EOPNOTSUPP;
+	strlcpy(info->driver, driver_name, sizeof(info->driver));
 }
 
-/****************************************************************
- *     kaweth_ioctl
- ****************************************************************/
-static int kaweth_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
-{
-	switch (cmd) {
-	case SIOCETHTOOL:
-		return netdev_ethtool_ioctl(net, rq->ifr_data);
-	}
-	return -EOPNOTSUPP;
-}
+static struct ethtool_ops ops = {
+	.get_drvinfo = kaweth_get_drvinfo
+};
 
 /****************************************************************
  *     kaweth_usb_transmit_complete
@@ -1107,11 +1085,11 @@
 	kaweth->net->watchdog_timeo = KAWETH_TX_TIMEOUT;
 	kaweth->net->tx_timeout = kaweth_tx_timeout;
 
-	kaweth->net->do_ioctl = kaweth_ioctl;
 	kaweth->net->hard_start_xmit = kaweth_start_xmit;
 	kaweth->net->set_multicast_list = kaweth_set_rx_mode;
 	kaweth->net->get_stats = kaweth_netdev_stats;
 	kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size);
+	SET_ETHTOOL_OPS(kaweth->net, &ops);
 
 	memset(&kaweth->stats, 0, sizeof(kaweth->stats));
 
diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
--- a/drivers/usb/net/pegasus.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/usb/net/pegasus.c	2004-10-10 22:15:16 -07:00
@@ -308,7 +308,7 @@
 
 static int mdio_read(struct net_device *dev, int phy_id, int loc)
 {
-	pegasus_t *pegasus = (pegasus_t *) dev->priv;
+	pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev);
 	int res;
 
 	read_mii_word(pegasus, phy_id, loc, (u16 *) & res);
@@ -338,7 +338,7 @@
 
 static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
 {
-	pegasus_t *pegasus = (pegasus_t *) dev->priv;
+	pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev);
 
 	write_mii_word(pegasus, phy_id, loc, val);
 }
@@ -471,7 +471,7 @@
 {
 	__u16 linkpart;
 	__u8 data[4];
-	pegasus_t *pegasus = dev->priv;
+	pegasus_t *pegasus = netdev_priv(dev);
 
 	read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart);
 	data[0] = 0xc9;
@@ -754,11 +754,7 @@
 
 static void pegasus_tx_timeout(struct net_device *net)
 {
-	pegasus_t *pegasus = net->priv;
-
-	if (!pegasus)
-		return;
-
+	pegasus_t *pegasus = netdev_priv(net);
 	warn("%s: Tx timed out.", net->name);
 	pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
 	usb_unlink_urb(pegasus->tx_urb);
@@ -767,7 +763,7 @@
 
 static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
 {
-	pegasus_t *pegasus = net->priv;
+	pegasus_t *pegasus = netdev_priv(net);
 	int count = ((skb->len + 2) & 0x3f) ? skb->len + 2 : skb->len + 3;
 	int res;
 	__u16 l16 = skb->len;
@@ -804,7 +800,7 @@
 
 static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
 {
-	return &((pegasus_t *) dev->priv)->stats;
+	return &((pegasus_t *) netdev_priv(dev))->stats;
 }
 
 static inline void disable_net_traffic(pegasus_t * pegasus)
@@ -832,10 +828,9 @@
 
 static void set_carrier(struct net_device *net)
 {
-	pegasus_t *pegasus;
+	pegasus_t *pegasus = netdev_priv(net);
 	short tmp;
 
-	pegasus = net->priv;
 	read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp);
 	if (tmp & BMSR_LSTATUS)
 		netif_carrier_on(net);
@@ -890,7 +885,7 @@
 
 static int pegasus_open(struct net_device *net)
 {
-	pegasus_t *pegasus = (pegasus_t *) net->priv;
+	pegasus_t *pegasus = netdev_priv(net);
 	int res;
 
 	if (pegasus->rx_skb == NULL)
@@ -933,7 +928,7 @@
 
 static int pegasus_close(struct net_device *net)
 {
-	pegasus_t *pegasus = net->priv;
+	pegasus_t *pegasus = netdev_priv(net);
 
 	pegasus->flags &= ~PEGASUS_RUNNING;
 	netif_stop_queue(net);
@@ -944,177 +939,124 @@
 
 	return 0;
 }
-#ifdef	CONFIG_MII
-static int pegasus_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
-{
 
-	u32 ethcmd;
-	pegasus_t *pegasus = dev->priv;
+void pegasus_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	pegasus_t *pegasus = netdev_priv(dev);
+	strncpy(info->driver, driver_name, sizeof (info->driver) - 1);
+	strncpy(info->version, DRIVER_VERSION, sizeof (info->version) - 1);
+	usb_make_path(pegasus->usb, info->bus_info, sizeof (info->bus_info));
+}
 
-	if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
-		return -EFAULT;
+#ifdef	CONFIG_MII
+static int pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	pegasus_t *pegasus = netdev_priv(dev);
+	mii_ethtool_gset(&pegasus->mii, ecmd);
+	return 0;
+}
+static int pegasus_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	pegasus_t *pegasus = netdev_priv(dev);
+	return mii_ethtool_sset(&pegasus->mii, ecmd);
+}
 
-	switch (ethcmd) {
-	/* get driver-specific version/etc. info */
-	case ETHTOOL_GDRVINFO:{
-			struct ethtool_drvinfo info;
-			memset (&info, 0, sizeof (info));
-			info.cmd = ETHTOOL_GDRVINFO;
-			strncpy(info.driver, driver_name,
-				sizeof (info.driver) - 1);
-			strncpy(info.version, DRIVER_VERSION,
-				sizeof (info.version) - 1);
-			usb_make_path(pegasus->usb, info.bus_info,
-				      sizeof (info.bus_info));
-			if (copy_to_user(useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
+static int pegasus_nway_reset(struct net_device *dev)
+{
+	pegasus_t *pegasus = netdev_priv(dev);
+	return mii_nway_restart(&pegasus->mii);
+}
 
-	/* get settings */
-	case ETHTOOL_GSET:{
-			struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-			mii_ethtool_gset(&pegasus->mii, &ecmd);
-			if (copy_to_user(useraddr, &ecmd, sizeof (ecmd)))
-				return -EFAULT;
-			return 0;
-		}
-	/* set settings */
-	case ETHTOOL_SSET:{
-			int r;
-			struct ethtool_cmd ecmd;
-			if (copy_from_user(&ecmd, useraddr, sizeof (ecmd)))
-				return -EFAULT;
-			r = mii_ethtool_sset(&pegasus->mii, &ecmd);
-			return r;
-		}
-	/* restart autonegotiation */
-	case ETHTOOL_NWAY_RST:{
-			return mii_nway_restart(&pegasus->mii);
-		}
+static u32 pegasus_get_link(struct net_device *dev)
+{
+	pegasus_t *pegasus = netdev_priv(dev);
+	return mii_link_ok(&pegasus->mii);
+}
 
-	/* get link status */
-	case ETHTOOL_GLINK:{
-			struct ethtool_value edata = { ETHTOOL_GLINK };
-			edata.data = mii_link_ok(&pegasus->mii);
-			if (copy_to_user(useraddr, &edata, sizeof (edata)))
-				return -EFAULT;
-			return 0;
-		}
-	/* get message-level */
-	case ETHTOOL_GMSGLVL:{
-			struct ethtool_value edata = { ETHTOOL_GMSGLVL };
-			/* edata.data = pegasus->msg_enable; FIXME */
-			if (copy_to_user(useraddr, &edata, sizeof (edata)))
-				return -EFAULT;
-			return 0;
-		}
-	/* set message-level */
-	case ETHTOOL_SMSGLVL:{
-			struct ethtool_value edata;
-			if (copy_from_user(&edata, useraddr, sizeof (edata)))
-				return -EFAULT;
-			/* sp->msg_enable = edata.data; FIXME */
-			return 0;
-		}
+static u32 pegasus_get_msglevel(struct net_device *dev)
+{
+	/*
+	 * pegasus_t *pegasus = netdev_priv(dev);
+	 * return pegasus->msg_enable; FIXME
+	 */
+	return 0;
+}
 
-	}
+static void pegasus_set_msglevel(struct net_device *dev, u32 v)
+{
+	/*
+	 * pegasus_t *pegasus = netdev_priv(dev);
+	 * pegasus->msg_enable = edata.data; FIXME
+	 */
+}
 
-	return -EOPNOTSUPP;
+static struct ethtool_ops ops = {
+	.get_drvinfo = pegasus_get_drvinfo,
+	.get_settings = pegasus_get_settings,
+	.set_settings = pegasus_set_settings,
+	.nway_reset = pegasus_nway_reset,
+	.get_link = pegasus_get_link,
+	.get_msglevel = pegasus_get_msglevel,
+	.set_msglevel = pegasus_set_msglevel,
+};
 
-}
 #else
-static int pegasus_ethtool_ioctl(struct net_device *net, void __user *uaddr)
-{
-	pegasus_t *pegasus;
-	int cmd;
-
-	pegasus = net->priv;
-	if (get_user(cmd, (int __user *) uaddr))
-		return -EFAULT;
-	switch (cmd) {
-	case ETHTOOL_GDRVINFO:{
-			struct ethtool_drvinfo info;
-			memset (&info, 0, sizeof (info));
-			info.cmd = ETHTOOL_GDRVINFO;
-			strncpy(info.driver, driver_name,
-				sizeof (info.driver) - 1);
-			strncpy(info.version, DRIVER_VERSION,
-				sizeof (info.version) - 1);
-			usb_make_path(pegasus->usb, info.bus_info,
-				      sizeof (info.bus_info));
-			if (copy_to_user(uaddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
-	case ETHTOOL_GSET:{
-			struct ethtool_cmd ecmd;
-			short lpa, bmcr;
-			u8 port;
-
-			memset(&ecmd, 0, sizeof (ecmd));
-			ecmd.supported = (SUPPORTED_10baseT_Half |
-					  SUPPORTED_10baseT_Full |
-					  SUPPORTED_100baseT_Half |
-					  SUPPORTED_100baseT_Full |
-					  SUPPORTED_Autoneg |
-					  SUPPORTED_TP | SUPPORTED_MII);
-			get_registers(pegasus, Reg7b, 1, &port);
-			if (port == 0)
-				ecmd.port = PORT_MII;
-			else
-				ecmd.port = PORT_TP;
-			ecmd.transceiver = XCVR_INTERNAL;
-			ecmd.phy_address = pegasus->phy;
-			read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr);
-			read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa);
-			if (bmcr & BMCR_ANENABLE) {
-				ecmd.autoneg = AUTONEG_ENABLE;
-				ecmd.speed = lpa & (LPA_100HALF | LPA_100FULL) ?
-				    SPEED_100 : SPEED_10;
-				if (ecmd.speed == SPEED_100)
-					ecmd.duplex = lpa & LPA_100FULL ?
-					    DUPLEX_FULL : DUPLEX_HALF;
-				else
-					ecmd.duplex = lpa & LPA_10FULL ?
-					    DUPLEX_FULL : DUPLEX_HALF;
-			} else {
-				ecmd.autoneg = AUTONEG_DISABLE;
-				ecmd.speed = bmcr & BMCR_SPEED100 ?
-				    SPEED_100 : SPEED_10;
-				ecmd.duplex = bmcr & BMCR_FULLDPLX ?
-				    DUPLEX_FULL : DUPLEX_HALF;
-			}
-			if (copy_to_user(uaddr, &ecmd, sizeof (ecmd)))
-				return -EFAULT;
 
-			return 0;
-		}
-	case ETHTOOL_SSET:{
-			return -EOPNOTSUPP;
-		}
-	case ETHTOOL_GLINK:{
-			struct ethtool_value edata = { ETHTOOL_GLINK };
-			edata.data = netif_carrier_ok(net);
-			if (copy_to_user(uaddr, &edata, sizeof (edata)))
-				return -EFAULT;
-			return 0;
-		}
-	default:
-		return -EOPNOTSUPP;
+static int pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	pegasus_t *pegasus = netdev_priv(dev);
+	short lpa, bmcr;
+	u8 port;
+
+	ecmd->supported = (SUPPORTED_10baseT_Half |
+			  SUPPORTED_10baseT_Full |
+			  SUPPORTED_100baseT_Half |
+			  SUPPORTED_100baseT_Full |
+			  SUPPORTED_Autoneg |
+			  SUPPORTED_TP | SUPPORTED_MII);
+	get_registers(pegasus, Reg7b, 1, &port);
+	if (port == 0)
+		ecmd->port = PORT_MII;
+	else
+		ecmd->port = PORT_TP;
+	ecmd->transceiver = XCVR_INTERNAL;
+	ecmd->phy_address = pegasus->phy;
+	read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr);
+	read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa);
+	if (bmcr & BMCR_ANENABLE) {
+		ecmd->autoneg = AUTONEG_ENABLE;
+		ecmd->speed = lpa & (LPA_100HALF | LPA_100FULL) ?
+		    SPEED_100 : SPEED_10;
+		if (ecmd->speed == SPEED_100)
+			ecmd->duplex = lpa & LPA_100FULL ?
+			    DUPLEX_FULL : DUPLEX_HALF;
+		else
+			ecmd->duplex = lpa & LPA_10FULL ?
+			    DUPLEX_FULL : DUPLEX_HALF;
+	} else {
+		ecmd->autoneg = AUTONEG_DISABLE;
+		ecmd->speed = bmcr & BMCR_SPEED100 ?
+		    SPEED_100 : SPEED_10;
+		ecmd->duplex = bmcr & BMCR_FULLDPLX ?
+		    DUPLEX_FULL : DUPLEX_HALF;
 	}
+	return 0;
 }
+
+static struct ethtool_ops ops = {
+	.get_drvinfo = pegasus_get_drvinfo,
+	.get_settings = pegasus_get_settings,
+	.get_link = ethtool_op_get_link,
+};
 #endif
+
 static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
 {
 	__u16 *data = (__u16 *) & rq->ifr_ifru;
-	pegasus_t *pegasus = net->priv;
+	pegasus_t *pegasus = netdev_priv(net);
 	int res;
 
 	switch (cmd) {
-	case SIOCETHTOOL:
-		res = pegasus_ethtool_ioctl(net, rq->ifr_data);
-		break;
 	case SIOCDEVPRIVATE:
 		data[0] = pegasus->phy;
 	case SIOCDEVPRIVATE + 1:
@@ -1135,7 +1077,7 @@
 
 static void pegasus_set_multicast(struct net_device *net)
 {
-	pegasus_t *pegasus = net->priv;
+	pegasus_t *pegasus = netdev_priv(net);
 
 	if (net->flags & IFF_PROMISC) {
 		pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
@@ -1211,11 +1153,13 @@
 	int res = -ENOMEM;
 
 	usb_get_dev(dev);
-	if (!(pegasus = kmalloc(sizeof (struct pegasus), GFP_KERNEL))) {
+	net = alloc_etherdev(sizeof(struct pegasus));
+	if (!net) {
 		err("out of memory allocating device structure");
 		goto out;
 	}
 
+	pegasus = netdev_priv(net);
 	memset(pegasus, 0, sizeof (struct pegasus));
 	pegasus->dev_index = dev_index;
 	init_waitqueue_head(&pegasus->ctrl_wait);
@@ -1223,16 +1167,11 @@
 	if (!alloc_urbs(pegasus))
 		goto out1;
 
-	net = alloc_etherdev(0);
-	if (!net)
-		goto out2;
-
 	tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
 
 	pegasus->usb = dev;
 	pegasus->net = net;
 	SET_MODULE_OWNER(net);
-	net->priv = pegasus;
 	net->open = pegasus_open;
 	net->stop = pegasus_close;
 	net->watchdog_timeo = PEGASUS_TX_TIMEOUT;
@@ -1242,6 +1181,7 @@
 	net->set_multicast_list = pegasus_set_multicast;
 	net->get_stats = pegasus_netdev_stats;
 	net->mtu = PEGASUS_MTU;
+	SET_ETHTOOL_OPS(net, &ops);
 	pegasus->mii.dev = net;
 	pegasus->mii.mdio_read = mdio_read;
 	pegasus->mii.mdio_write = mdio_write;
@@ -1254,7 +1194,7 @@
 	if (reset_mac(pegasus)) {
 		err("can't reset MAC");
 		res = -EIO;
-		goto out3;
+		goto out2;
 	}
 	set_ethernet_addr(pegasus);
 	fill_skb_pool(pegasus);
@@ -1271,19 +1211,17 @@
 	SET_NETDEV_DEV(net, &intf->dev);
 	res = register_netdev(net);
 	if (res)
-		goto out4;
+		goto out3;
 	printk("%s: %s\n", net->name, usb_dev_id[dev_index].name);
 	return 0;
 
-out4:
+out3:
 	usb_set_intfdata(intf, NULL);
 	free_skb_pool(pegasus);
-out3:
-	free_netdev(net);
 out2:
 	free_all_urbs(pegasus);
 out1:
-	kfree(pegasus);
+	free_netdev(net);
 out:
 	usb_put_dev(dev);
 	return res;
@@ -1307,7 +1245,6 @@
 	if (pegasus->rx_skb)
 		dev_kfree_skb(pegasus->rx_skb);
 	free_netdev(pegasus->net);
-	kfree(pegasus);
 }
 
 static struct usb_driver pegasus_driver = {
diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
--- a/drivers/usb/net/rtl8150.c	2004-10-10 22:15:16 -07:00
+++ b/drivers/usb/net/rtl8150.c	2004-10-10 22:15:16 -07:00
@@ -304,15 +304,12 @@
 static int rtl8150_set_mac_address(struct net_device *netdev, void *p)
 {
 	struct sockaddr *addr = p;
-	rtl8150_t *dev;
+	rtl8150_t *dev = netdev_priv(netdev);
 	int i;
 
 	if (netif_running(netdev))
 		return -EBUSY;
-	dev = netdev->priv;
-	if (dev == NULL) {
-		return -ENODEV;
-	}
+
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 	dbg("%s: Setting MAC address to ", netdev->name);
 	for (i = 0; i < 5; i++)
@@ -651,16 +648,12 @@
 
 static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev)
 {
-	return &((rtl8150_t *) dev->priv)->stats;
+	return &((rtl8150_t *)netdev_priv(dev))->stats;
 }
 
 static void rtl8150_tx_timeout(struct net_device *netdev)
 {
-	rtl8150_t *dev;
-
-	dev = netdev->priv;
-	if (!dev)
-		return;
+	rtl8150_t *dev = netdev_priv(netdev);
 	warn("%s: Tx timeout.", netdev->name);
 	dev->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
 	usb_unlink_urb(dev->tx_urb);
@@ -669,9 +662,7 @@
 
 static void rtl8150_set_multicast(struct net_device *netdev)
 {
-	rtl8150_t *dev;
-
-	dev = netdev->priv;
+	rtl8150_t *dev = netdev_priv(netdev);
 	netif_stop_queue(netdev);
 	if (netdev->flags & IFF_PROMISC) {
 		dev->rx_creg |= cpu_to_le16(0x0001);
@@ -691,11 +682,10 @@
 
 static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
-	rtl8150_t *dev;
+	rtl8150_t *dev = netdev_priv(netdev);
 	int count, res;
 
 	netif_stop_queue(netdev);
-	dev = netdev->priv;
 	count = (skb->len < 60) ? 60 : skb->len;
 	count = (count & 0x3f) ? count : count + 1;
 	dev->tx_skb = skb;
@@ -717,7 +707,7 @@
 
 static void set_carrier(struct net_device *netdev)
 {
-	rtl8150_t *dev = netdev->priv;
+	rtl8150_t *dev = netdev_priv(netdev);
 	short tmp;
 
 	get_registers(dev, CSCR, 2, &tmp);
@@ -729,13 +719,9 @@
 
 static int rtl8150_open(struct net_device *netdev)
 {
-	rtl8150_t *dev;
+	rtl8150_t *dev = netdev_priv(netdev);
 	int res;
 
-	dev = netdev->priv;
-	if (dev == NULL) {
-		return -ENODEV;
-	}
 	if (dev->rx_skb == NULL)
 		dev->rx_skb = pull_skb(dev);
 	if (!dev->rx_skb)
@@ -761,13 +747,9 @@
 
 static int rtl8150_close(struct net_device *netdev)
 {
-	rtl8150_t *dev;
+	rtl8150_t *dev = netdev_priv(netdev);
 	int res = 0;
 
-	dev = netdev->priv;
-	if (!dev)
-		return -ENODEV;
-
 	netif_stop_queue(netdev);
 	if (!test_bit(RTL8150_UNPLUG, &dev->flags))
 		disable_net_traffic(dev);
@@ -776,93 +758,64 @@
 	return res;
 }
 
-static int rtl8150_ethtool_ioctl(struct net_device *netdev, void __user *uaddr)
+static void rtl8150_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
 {
-	rtl8150_t *dev;
-	int cmd;
-
-	dev = netdev->priv;
-	if (get_user(cmd, (int __user *) uaddr))
-		return -EFAULT;
+	rtl8150_t *dev = netdev_priv(netdev);
 
-	switch (cmd) {
-	case ETHTOOL_GDRVINFO:{
-		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-
-		strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN);
-		strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
-		usb_make_path(dev->udev, info.bus_info, sizeof info.bus_info);
-		if (copy_to_user(uaddr, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-		}
-	case ETHTOOL_GSET:{
-		struct ethtool_cmd ecmd;
-		short lpa, bmcr;
-
-		if (copy_from_user(&ecmd, uaddr, sizeof(ecmd)))
-			return -EFAULT;
-		ecmd.supported = (SUPPORTED_10baseT_Half |
-				  SUPPORTED_10baseT_Full |
-				  SUPPORTED_100baseT_Half |
-				  SUPPORTED_100baseT_Full |
-				  SUPPORTED_Autoneg |
-				  SUPPORTED_TP | SUPPORTED_MII);
-		ecmd.port = PORT_TP;
-		ecmd.transceiver = XCVR_INTERNAL;
-		ecmd.phy_address = dev->phy;
-		get_registers(dev, BMCR, 2, &bmcr);
-		get_registers(dev, ANLP, 2, &lpa);
-		if (bmcr & BMCR_ANENABLE) {
-			ecmd.autoneg = AUTONEG_ENABLE;
-			ecmd.speed = (lpa & (LPA_100HALF | LPA_100FULL)) ?
-			             SPEED_100 : SPEED_10;
-			if (ecmd.speed == SPEED_100)
-				ecmd.duplex = (lpa & LPA_100FULL) ?
-				    DUPLEX_FULL : DUPLEX_HALF;
-			else
-				ecmd.duplex = (lpa & LPA_10FULL) ?
-				    DUPLEX_FULL : DUPLEX_HALF;
-		} else {
-			ecmd.autoneg = AUTONEG_DISABLE;
-			ecmd.speed = (bmcr & BMCR_SPEED100) ?
-			    SPEED_100 : SPEED_10;
-			ecmd.duplex = (bmcr & BMCR_FULLDPLX) ?
+	strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN);
+	strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
+	usb_make_path(dev->udev, info->bus_info, sizeof info->bus_info);
+}
+
+static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+{
+	rtl8150_t *dev = netdev_priv(netdev);
+	short lpa, bmcr;
+
+	ecmd->supported = (SUPPORTED_10baseT_Half |
+			  SUPPORTED_10baseT_Full |
+			  SUPPORTED_100baseT_Half |
+			  SUPPORTED_100baseT_Full |
+			  SUPPORTED_Autoneg |
+			  SUPPORTED_TP | SUPPORTED_MII);
+	ecmd->port = PORT_TP;
+	ecmd->transceiver = XCVR_INTERNAL;
+	ecmd->phy_address = dev->phy;
+	get_registers(dev, BMCR, 2, &bmcr);
+	get_registers(dev, ANLP, 2, &lpa);
+	if (bmcr & BMCR_ANENABLE) {
+		ecmd->autoneg = AUTONEG_ENABLE;
+		ecmd->speed = (lpa & (LPA_100HALF | LPA_100FULL)) ?
+			     SPEED_100 : SPEED_10;
+		if (ecmd->speed == SPEED_100)
+			ecmd->duplex = (lpa & LPA_100FULL) ?
 			    DUPLEX_FULL : DUPLEX_HALF;
-		}
-		if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-		}
-	case ETHTOOL_SSET:
-		return -ENOTSUPP;
-	case ETHTOOL_GLINK:{
-		struct ethtool_value edata = { ETHTOOL_GLINK };
-
-		edata.data = netif_carrier_ok(netdev);
-		if (copy_to_user(uaddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-		}
-	default:
-		return -EOPNOTSUPP;
+		else
+			ecmd->duplex = (lpa & LPA_10FULL) ?
+			    DUPLEX_FULL : DUPLEX_HALF;
+	} else {
+		ecmd->autoneg = AUTONEG_DISABLE;
+		ecmd->speed = (bmcr & BMCR_SPEED100) ?
+		    SPEED_100 : SPEED_10;
+		ecmd->duplex = (bmcr & BMCR_FULLDPLX) ?
+		    DUPLEX_FULL : DUPLEX_HALF;
 	}
+	return 0;
 }
 
+static struct ethtool_ops ops = {
+	.get_drvinfo = rtl8150_get_drvinfo,
+	.get_settings = rtl8150_get_settings,
+	.get_link = ethtool_op_get_link
+};
+
 static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 {
-	rtl8150_t *dev;
-	u16 *data;
-	int res;
-
-	dev = netdev->priv;
-	data = (u16 *) & rq->ifr_ifru;
-	res = 0;
+	rtl8150_t *dev = netdev_priv(netdev);
+	u16 *data = (u16 *) & rq->ifr_ifru;
+	int res = 0;
 
 	switch (cmd) {
-	case SIOCETHTOOL:
-		res = rtl8150_ethtool_ioctl(netdev, rq->ifr_data);
-		break;
 	case SIOCDEVPRIVATE:
 		data[0] = dev->phy;
 	case SIOCDEVPRIVATE + 1:
@@ -887,23 +840,18 @@
 	rtl8150_t *dev;
 	struct net_device *netdev;
 
-	dev = kmalloc(sizeof(rtl8150_t), GFP_KERNEL);
-	if (!dev) {
+	netdev = alloc_etherdev(sizeof(rtl8150_t));
+	if (!netdev) {
 		err("Out of memory");
 		return -ENOMEM;
-	} else
-		memset(dev, 0, sizeof(rtl8150_t));
+	}
+
+	dev = netdev_priv(netdev);
+	memset(dev, 0, sizeof(rtl8150_t));
 
 	dev->intr_buff = kmalloc(INTBUFSIZE, GFP_KERNEL);
 	if (!dev->intr_buff) {
-		kfree(dev);
-		return -ENOMEM;
-	}
-	netdev = alloc_etherdev(0);
-	if (!netdev) {
-		kfree(dev->intr_buff);
-		kfree(dev);
-		err("Oh boy, out of memory again?!?");
+		free_netdev(netdev);
 		return -ENOMEM;
 	}
 
@@ -913,7 +861,6 @@
 	dev->udev = udev;
 	dev->netdev = netdev;
 	SET_MODULE_OWNER(netdev);
-	netdev->priv = dev;
 	netdev->open = rtl8150_open;
 	netdev->stop = rtl8150_close;
 	netdev->do_ioctl = rtl8150_ioctl;
@@ -924,6 +871,7 @@
 	netdev->set_mac_address = rtl8150_set_mac_address;
 	netdev->get_stats = rtl8150_netdev_stats;
 	netdev->mtu = RTL8150_MTU;
+	SET_ETHTOOL_OPS(netdev, &ops);
 	dev->intr_interval = 100;	/* 100ms */
 
 	if (!alloc_all_urbs(dev)) {
@@ -954,7 +902,6 @@
 out:
 	kfree(dev->intr_buff);
 	free_netdev(netdev);
-	kfree(dev);
 	return -EIO;
 }
 
@@ -971,9 +918,8 @@
 		free_skb_pool(dev);
 		if (dev->rx_skb)
 			dev_kfree_skb(dev->rx_skb);
-		free_netdev(dev->netdev);
 		kfree(dev->intr_buff);
-		kfree(dev);
+		free_netdev(dev->netdev);
 	}
 }
 
diff -Nru a/include/linux/netdevice.h b/include/linux/netdevice.h
--- a/include/linux/netdevice.h	2004-10-10 22:15:16 -07:00
+++ b/include/linux/netdevice.h	2004-10-10 22:15:16 -07:00
@@ -309,7 +309,9 @@
 
 	/* List of functions to handle Wireless Extensions (instead of ioctl).
 	 * See <net/iw_handler.h> for details. Jean II */
-	struct iw_handler_def *	wireless_handlers;
+	const struct iw_handler_def *	wireless_handlers;
+	/* Instance data managed by the core of Wireless Extensions. */
+	struct iw_public_data *	wireless_data;
 
 	struct ethtool_ops *ethtool_ops;
 
diff -Nru a/include/linux/wireless.h b/include/linux/wireless.h
--- a/include/linux/wireless.h	2004-10-10 22:15:16 -07:00
+++ b/include/linux/wireless.h	2004-10-10 22:15:16 -07:00
@@ -1,10 +1,10 @@
 /*
  * This file define a set of standard wireless extensions
  *
- * Version :	16	2.4.03
+ * Version :	17	21.6.04
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
  */
 
 #ifndef _LINUX_WIRELESS_H
@@ -47,12 +47,12 @@
  *	# include/net/iw_handler.h
  *
  * Note as well that /proc/net/wireless implementation has now moved in :
- *	# include/linux/wireless.c
+ *	# net/core/wireless.c
  *
  * Wireless Events (2002 -> onward) :
  * --------------------------------
  * Events are defined at the end of this file, and implemented in :
- *	# include/linux/wireless.c
+ *	# net/core/wireless.c
  *
  * Other comments :
  * --------------
@@ -82,7 +82,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT	16
+#define WIRELESS_EXT	17
 
 /*
  * Changes :
@@ -175,6 +175,13 @@
  *	- Remove IW_MAX_GET_SPY because conflict with enhanced spy support
  *	- Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
  *	- Add IW_ENCODE_TEMP and iw_range->encoding_login_index
+ *
+ * V16 to V17
+ * ----------
+ *	- Add flags to frequency -> auto/fixed
+ *	- Document (struct iw_quality *)->updated, add new flags (INVALID)
+ *	- Wireless Event capability in struct iw_range
+ *	- Add support for relative TxPower (yick !)
  */
 
 /**************************** CONSTANTS ****************************/
@@ -251,7 +258,7 @@
 
 /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
 
-/* These 16 ioctl are wireless device private.
+/* These 32 ioctl are wireless device private, for 16 commands.
  * Each driver is free to use them for whatever purpose it chooses,
  * however the driver *must* export the description of those ioctls
  * with SIOCGIWPRIV and *must* use arguments as defined below.
@@ -266,8 +273,8 @@
  * We now have 32 commands, so a bit more space ;-).
  * Also, all 'odd' commands are only usable by root and don't return the
  * content of ifr/iwr to user (but you are not obliged to use the set/get
- * convention, just use every other two command).
- * And I repeat : you are not obliged to use them with iwspy, but you
+ * convention, just use every other two command). More details in iwpriv.c.
+ * And I repeat : you are not forced to use them with iwpriv, but you
  * must be compliant with it.
  */
 
@@ -352,6 +359,18 @@
 #define IW_MODE_SECOND	5	/* Secondary master/repeater (backup) */
 #define IW_MODE_MONITOR	6	/* Passive monitor (listen only) */
 
+/* Statistics flags (bitmask in updated) */
+#define IW_QUAL_QUAL_UPDATED	0x1	/* Value was updated since last read */
+#define IW_QUAL_LEVEL_UPDATED	0x2
+#define IW_QUAL_NOISE_UPDATED	0x4
+#define IW_QUAL_QUAL_INVALID	0x10	/* Driver doesn't provide value */
+#define IW_QUAL_LEVEL_INVALID	0x20
+#define IW_QUAL_NOISE_INVALID	0x40
+
+/* Frequency flags */
+#define IW_FREQ_AUTO		0x00	/* Let the driver decides */
+#define IW_FREQ_FIXED		0x01	/* Force a specific value */
+
 /* Maximum number of size of encoding token available
  * they are listed in the range structure */
 #define IW_MAX_ENCODING_SIZES	8
@@ -390,6 +409,7 @@
 #define IW_TXPOW_TYPE		0x00FF	/* Type of value */
 #define IW_TXPOW_DBM		0x0000	/* Value is in dBm */
 #define IW_TXPOW_MWATT		0x0001	/* Value is in mW */
+#define IW_TXPOW_RELATIVE	0x0002	/* Value is in arbitrary units */
 #define IW_TXPOW_RANGE		0x1000	/* Range of value between min/max */
 
 /* Retry limits and lifetime flags available */
@@ -418,6 +438,25 @@
 /* Max number of char in custom event - use multiple of them if needed */
 #define IW_CUSTOM_MAX		256	/* In bytes */
 
+/* Event capability macros - in (struct iw_range *)->event_capa
+ * Because we have more than 32 possible events, we use an array of
+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
+#define IW_EVENT_CAPA_BASE(cmd)		((cmd >= SIOCIWFIRSTPRIV) ? \
+					 (cmd - SIOCIWFIRSTPRIV + 0x60) : \
+					 (cmd - SIOCSIWCOMMIT))
+#define IW_EVENT_CAPA_INDEX(cmd)	(IW_EVENT_CAPA_BASE(cmd) >> 5)
+#define IW_EVENT_CAPA_MASK(cmd)		(1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
+/* Event capability constants - event autogenerated by the kernel
+ * This list is valid for most 802.11 devices, customise as needed... */
+#define IW_EVENT_CAPA_K_0	(IW_EVENT_CAPA_MASK(0x8B04) | \
+				 IW_EVENT_CAPA_MASK(0x8B06) | \
+				 IW_EVENT_CAPA_MASK(0x8B1A))
+#define IW_EVENT_CAPA_K_1	(IW_EVENT_CAPA_MASK(0x8B2A))
+/* "Easy" macro to set events in iw_range (less efficient) */
+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
+
+
 /****************************** TYPES ******************************/
 
 /* --------------------------- SUBTYPES --------------------------- */
@@ -456,7 +495,7 @@
 	__s32		m;		/* Mantissa */
 	__s16		e;		/* Exponent */
 	__u8		i;		/* List index (when in range struct) */
-	__u8		pad;		/* Unused - just for alignement */
+	__u8		flags;		/* Flags (fixed/auto) */
 };
 
 /*
@@ -610,11 +649,12 @@
 	/* Old Frequency (backward compat - moved lower ) */
 	__u16		old_num_channels;
 	__u8		old_num_frequency;
-	/* Filler to keep "version" at the same offset */
-	__s32		old_freq[6];
+
+	/* Wireless event capability bitmasks */
+	__u32		event_capa[6];
 
 	/* signal level threshold range */
-	__s32	sensitivity;
+	__s32		sensitivity;
 
 	/* Quality of link & SNR stuff */
 	/* Quality range (link, level, noise)
diff -Nru a/include/net/iw_handler.h b/include/net/iw_handler.h
--- a/include/net/iw_handler.h	2004-10-10 22:15:16 -07:00
+++ b/include/net/iw_handler.h	2004-10-10 22:15:16 -07:00
@@ -1,10 +1,10 @@
 /*
  * This file define the new driver API for Wireless Extensions
  *
- * Version :	5	4.12.02
+ * Version :	6	21.6.04
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 2001-2004 Jean Tourrilhes, All Rights Reserved.
  */
 
 #ifndef _IW_HANDLER_H
@@ -206,7 +206,7 @@
  * will be needed...
  * I just plan to increment with each new version.
  */
-#define IW_HANDLER_VERSION	5
+#define IW_HANDLER_VERSION	6
 
 /*
  * Changes :
@@ -224,11 +224,18 @@
  * V4 to V5
  * --------
  *	- Add new spy support : struct iw_spy_data & prototypes
+ *
+ * V5 to V6
+ * --------
+ *	- Change the way we get to spy_data method for added safety
+ *	- Remove spy #ifdef, they are always on -> cleaner code
+ *	- Add IW_DESCR_FLAG_NOMAX flag for very large requests
+ *	- Start migrating get_wireless_stats to struct iw_handler_def
  */
 
 /**************************** CONSTANTS ****************************/
 
-/* Enable enhanced spy support. Disable to reduce footprint */
+/* Enhanced spy support available */
 #define IW_WIRELESS_SPY
 #define IW_WIRELESS_THRSPY
 
@@ -258,6 +265,7 @@
 #define IW_DESCR_FLAG_EVENT	0x0002	/* Generate an event on SET */
 #define IW_DESCR_FLAG_RESTRICT	0x0004	/* GET : request is ROOT only */
 				/* SET : Omit payload from generated iwevent */
+#define IW_DESCR_FLAG_NOMAX	0x0008	/* GET : no limit on request size */
 /* Driver level flags */
 #define IW_DESCR_FLAG_WAIT	0x0100	/* Wait for driver event */
 
@@ -303,31 +311,33 @@
 {
 	/* Number of handlers defined (more precisely, index of the
 	 * last defined handler + 1) */
-	__u16			num_standard;
-	__u16			num_private;
+	const __u16		num_standard;
+	const __u16		num_private;
 	/* Number of private arg description */
-	__u16			num_private_args;
+	const __u16		num_private_args;
 
 	/* Array of handlers for standard ioctls
 	 * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME]
 	 */
-	iw_handler *		standard;
+	const iw_handler *	standard;
 
 	/* Array of handlers for private ioctls
 	 * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
 	 */
-	iw_handler *		private;
+	const iw_handler *	private;
 
 	/* Arguments of private handler. This one is just a list, so you
 	 * can put it in any order you want and should not leave holes...
 	 * We will automatically export that to user space... */
-	struct iw_priv_args *	private_args;
+	const struct iw_priv_args *	private_args;
 
-	/* Driver enhanced spy support */
-	long			spy_offset;	/* Spy data offset */
+	/* This field will be *removed* in the next version of WE */
+	const long		spy_offset;	/* DO NOT USE */
 
-	/* In the long term, get_wireless_stats will move from
-	 * 'struct net_device' to here, to minimise bloat. */
+	/* New location of get_wireless_stats, to de-bloat struct net_device.
+	 * The old pointer in struct net_device will be gradually phased
+	 * out, and drivers are encouraged to use this one... */
+	struct iw_statistics*	(*get_wireless_stats)(struct net_device *dev);
 };
 
 /* ---------------------- IOCTL DESCRIPTION ---------------------- */
@@ -374,18 +384,29 @@
  */
 struct iw_spy_data
 {
-#ifdef IW_WIRELESS_SPY
 	/* --- Standard spy support --- */
 	int			spy_number;
 	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
 	struct iw_quality	spy_stat[IW_MAX_SPY];
-#ifdef IW_WIRELESS_THRSPY
 	/* --- Enhanced spy support (event) */
 	struct iw_quality	spy_thr_low;	/* Low threshold */
 	struct iw_quality	spy_thr_high;	/* High threshold */
 	u_char			spy_thr_under[IW_MAX_SPY];
-#endif /* IW_WIRELESS_THRSPY */
-#endif /* IW_WIRELESS_SPY */
+};
+
+/* --------------------- DEVICE WIRELESS DATA --------------------- */
+/*
+ * This is all the wireless data specific to a device instance that
+ * is managed by the core of Wireless Extensions.
+ * We only keep pointer to those structures, so that a driver is free
+ * to share them between instances.
+ * This structure should be initialised before registering the device.
+ * Access to this data follow the same rules as any other struct net_device
+ * data (i.e. valid as long as struct net_device exist, same locking rules).
+ */
+struct iw_public_data {
+	/* Driver enhanced spy support */
+	struct iw_spy_data *	spy_data;
 };
 
 /**************************** PROTOTYPES ****************************/
@@ -393,6 +414,9 @@
  * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
  * Those may be called only within the kernel.
  */
+
+/* Data needed by fs/compat_ioctl.c for 32->64 bit conversion */
+extern const char iw_priv_type_size[];
 
 /* First : function strictly used inside the kernel */
 
diff -Nru a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c	2004-10-10 22:15:16 -07:00
+++ b/net/core/dev.c	2004-10-10 22:15:16 -07:00
@@ -2745,7 +2745,7 @@
 				/* Follow me in net/core/wireless.c */
 				ret = wireless_process_ioctl(&ifr, cmd);
 				rtnl_unlock();
-				if (!ret && IW_IS_GET(cmd) &&
+				if (IW_IS_GET(cmd) &&
 				    copy_to_user(arg, &ifr,
 					    	 sizeof(struct ifreq)))
 					ret = -EFAULT;
diff -Nru a/net/core/wireless.c b/net/core/wireless.c
--- a/net/core/wireless.c	2004-10-10 22:15:16 -07:00
+++ b/net/core/wireless.c	2004-10-10 22:15:16 -07:00
@@ -2,7 +2,7 @@
  * This file implement the Wireless Extensions APIs.
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
  *
  * (As all part of the Linux kernel, this file is GPL)
  */
@@ -48,6 +48,15 @@
  *	o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
  *	o Add enhanced spy support : iw_handler_set_thrspy() and event.
  *	o Add WIRELESS_EXT version display in /proc/net/wireless
+ *
+ * v6 - 18.06.04 - Jean II
+ *	o Change get_spydata() method for added safety
+ *	o Remove spy #ifdef, they are always on -> cleaner code
+ *	o Allow any size GET request is user specifies length > max
+ *	o Start migrating get_wireless_stats to struct iw_handler_def
+ *	o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus
+ * Based on patch from Pavel Roskin <proski@gnu.org> :
+ *	o Fix kernel data leak to user space in private handler handling
  */
 
 /***************************** INCLUDES *****************************/
@@ -69,10 +78,6 @@
 
 /**************************** CONSTANTS ****************************/
 
-/* Enough lenience, let's make sure things are proper... */
-#define WE_STRICT_WRITE		/* Check write buffer size */
-/* I'll probably drop both the define and kernel message in the next version */
-
 /* Debugging stuff */
 #undef WE_IOCTL_DEBUG		/* Debug IOCTL API */
 #undef WE_EVENT_DEBUG		/* Debug Event dispatcher */
@@ -186,6 +191,7 @@
 		.token_size	= sizeof(struct sockaddr) +
 				  sizeof(struct iw_quality),
 		.max_tokens	= IW_MAX_AP,
+		.flags		= IW_DESCR_FLAG_NOMAX,
 	},
 	[SIOCSIWSCAN	- SIOCIWFIRST] = {
 		.header_type	= IW_HEADER_TYPE_PARAM,
@@ -194,6 +200,7 @@
 		.header_type	= IW_HEADER_TYPE_POINT,
 		.token_size	= 1,
 		.max_tokens	= IW_SCAN_MAX_DATA,
+		.flags		= IW_DESCR_FLAG_NOMAX,
 	},
 	[SIOCSIWESSID	- SIOCIWFIRST] = {
 		.header_type	= IW_HEADER_TYPE_POINT,
@@ -296,7 +303,7 @@
 				       sizeof(struct iw_ioctl_description));
 
 /* Size (in bytes) of the various private data types */
-static const char priv_type_size[] = {
+const char iw_priv_type_size[] = {
 	0,				/* IW_PRIV_TYPE_NONE */
 	1,				/* IW_PRIV_TYPE_BYTE */
 	1,				/* IW_PRIV_TYPE_CHAR */
@@ -363,12 +370,15 @@
  */
 static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
 {
+	/* New location */
+	if((dev->wireless_handlers != NULL) &&
+	   (dev->wireless_handlers->get_wireless_stats != NULL))
+		return dev->wireless_handlers->get_wireless_stats(dev);
+
+	/* Old location, will be phased out in next WE */
 	return (dev->get_wireless_stats ?
 		dev->get_wireless_stats(dev) :
 		(struct iw_statistics *) NULL);
-	/* In the future, get_wireless_stats may move from 'struct net_device'
-	 * to 'struct iw_handler_def', to de-bloat struct net_device.
-	 * Definitely worse a thought... */
 }
 
 /* ---------------------------------------------------------------- */
@@ -403,14 +413,32 @@
 
 /* ---------------------------------------------------------------- */
 /*
- * Number of private arguments
+ * Calculate size of private arguments
  */
 static inline int get_priv_size(__u16	args)
 {
 	int	num = args & IW_PRIV_SIZE_MASK;
 	int	type = (args & IW_PRIV_TYPE_MASK) >> 12;
 
-	return num * priv_type_size[type];
+	return num * iw_priv_type_size[type];
+}
+
+/* ---------------------------------------------------------------- */
+/*
+ * Re-calculate the size of private arguments
+ */
+static inline int adjust_priv_size(__u16		args,
+				   union iwreq_data *	wrqu)
+{
+	int	num = wrqu->data.length;
+	int	max = args & IW_PRIV_SIZE_MASK;
+	int	type = (args & IW_PRIV_TYPE_MASK) >> 12;
+
+	/* Make sure the driver doesn't goof up */
+	if (max < num)
+		num = max;
+
+	return num * iw_priv_type_size[type];
 }
 
 
@@ -440,11 +468,14 @@
 		seq_printf(seq, "%6s: %04x  %3d%c  %3d%c  %3d%c  %6d %6d %6d "
 				"%6d %6d   %6d\n",
 			   dev->name, stats->status, stats->qual.qual,
-			   stats->qual.updated & 1 ? '.' : ' ',
+			   stats->qual.updated & IW_QUAL_QUAL_UPDATED
+			   ? '.' : ' ',
 			   ((__u8) stats->qual.level),
-			   stats->qual.updated & 2 ? '.' : ' ',
+			   stats->qual.updated & IW_QUAL_LEVEL_UPDATED
+			   ? '.' : ' ',
 			   ((__u8) stats->qual.noise),
-			   stats->qual.updated & 4 ? '.' : ' ',
+			   stats->qual.updated & IW_QUAL_NOISE_UPDATED
+			   ? '.' : ' ',
 			   stats->discard.nwid, stats->discard.code,
 			   stats->discard.fragment, stats->discard.retries,
 			   stats->discard.misc, stats->miss.beacon);
@@ -555,13 +586,15 @@
 	/* Check NULL pointer */
 	if(iwr->u.data.pointer == NULL)
 		return -EFAULT;
-#ifdef WE_STRICT_WRITE
+
 	/* Check if there is enough buffer up there */
 	if(iwr->u.data.length < dev->wireless_handlers->num_private_args) {
-		printk(KERN_ERR "%s (WE) : Buffer for request SIOCGIWPRIV too small (%d<%d)\n", dev->name, iwr->u.data.length, dev->wireless_handlers->num_private_args);
+		/* User space can't know in advance how large the buffer
+		 * needs to be. Give it a hint, so that we can support
+		 * any size buffer we want somewhat efficiently... */
+		iwr->u.data.length = dev->wireless_handlers->num_private_args;
 		return -E2BIG;
 	}
-#endif	/* WE_STRICT_WRITE */
 
 	/* Set the number of available ioctls. */
 	iwr->u.data.length = dev->wireless_handlers->num_private_args;
@@ -590,7 +623,6 @@
 	const struct iw_ioctl_description *	descr;
 	struct iw_request_info			info;
 	int					ret = -EINVAL;
-	int					user_size = 0;
 
 	/* Get the description of the IOCTL */
 	if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
@@ -621,8 +653,14 @@
 #endif	/* WE_SET_EVENT */
 	} else {
 		char *	extra;
+		int	extra_size;
+		int	user_length = 0;
 		int	err;
 
+		/* Calculate space needed by arguments. Always allocate
+		 * for max space. Easier, and won't last long... */
+		extra_size = descr->max_tokens * descr->token_size;
+
 		/* Check what user space is giving us */
 		if(IW_IS_SET(cmd)) {
 			/* Check NULL pointer */
@@ -639,18 +677,29 @@
 			if(iwr->u.data.pointer == NULL)
 				return -EFAULT;
 			/* Save user space buffer size for checking */
-			user_size = iwr->u.data.length;
+			user_length = iwr->u.data.length;
+
+			/* Don't check if user_length > max to allow forward
+			 * compatibility. The test user_length < min is
+			 * implied by the test at the end. */
+
+			/* Support for very large requests */
+			if((descr->flags & IW_DESCR_FLAG_NOMAX) &&
+			   (user_length > descr->max_tokens)) {
+				/* Allow userspace to GET more than max so
+				 * we can support any size GET requests.
+				 * There is still a limit : -ENOMEM. */
+				extra_size = user_length * descr->token_size;
+			}
 		}
 
 #ifdef WE_IOCTL_DEBUG
 		printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
-		       dev->name, descr->max_tokens * descr->token_size);
+		       dev->name, extra_size);
 #endif	/* WE_IOCTL_DEBUG */
 
-		/* Always allocate for max space. Easier, and won't last
-		 * long... */
-		extra = kmalloc(descr->max_tokens * descr->token_size,
-				GFP_KERNEL);
+		/* Create the kernel buffer */
+		extra = kmalloc(extra_size, GFP_KERNEL);
 		if (extra == NULL) {
 			return -ENOMEM;
 		}
@@ -676,14 +725,11 @@
 
 		/* If we have something to return to the user */
 		if (!ret && IW_IS_GET(cmd)) {
-#ifdef WE_STRICT_WRITE
 			/* Check if there is enough buffer up there */
-			if(user_size < iwr->u.data.length) {
-				printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length);
+			if(user_length < iwr->u.data.length) {
 				kfree(extra);
 				return -E2BIG;
 			}
-#endif	/* WE_STRICT_WRITE */
 
 			err = copy_to_user(iwr->u.data.pointer, extra,
 					   iwr->u.data.length *
@@ -746,7 +792,7 @@
 				     iw_handler		handler)
 {
 	struct iwreq *			iwr = (struct iwreq *) ifr;
-	struct iw_priv_args *		descr = NULL;
+	const struct iw_priv_args *	descr = NULL;
 	struct iw_request_info		info;
 	int				extra_size = 0;
 	int				i;
@@ -786,7 +832,7 @@
 			   ((extra_size + offset) <= IFNAMSIZ))
 				extra_size = 0;
 		} else {
-			/* Size of set arguments */
+			/* Size of get arguments */
 			extra_size = get_priv_size(descr->get_args);
 
 			/* Does it fits in iwr ? */
@@ -856,6 +902,14 @@
 
 		/* If we have something to return to the user */
 		if (!ret && IW_IS_GET(cmd)) {
+
+			/* Adjust for the actual length if it's variable,
+			 * avoid leaking kernel bits outside. */
+			if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) {
+				extra_size = adjust_priv_size(descr->get_args,
+							      &(iwr->u));
+			}
+
 			err = copy_to_user(iwr->u.data.pointer, extra,
 					   extra_size);
 			if (err)
@@ -1127,9 +1181,25 @@
  * One of the main advantage of centralising spy support here is that
  * it becomes much easier to improve and extend it without having to touch
  * the drivers. One example is the addition of the Spy-Threshold events.
- * Note : IW_WIRELESS_SPY is defined in iw_handler.h
  */
 
+/* ---------------------------------------------------------------- */
+/*
+ * Return the pointer to the spy data in the driver.
+ * Because this is called on the Rx path via wireless_spy_update(),
+ * we want it to be efficient...
+ */
+static inline struct iw_spy_data * get_spydata(struct net_device *dev)
+{
+	/* This is the new way */
+	if(dev->wireless_data)
+		return(dev->wireless_data->spy_data);
+
+	/* This is the old way. Doesn't work for multi-headed drivers.
+	 * It will be removed in the next version of WE. */
+	return (dev->priv + dev->wireless_handlers->spy_offset);
+}
+
 /*------------------------------------------------------------------*/
 /*
  * Standard Wireless Handler : set Spy List
@@ -1139,16 +1209,30 @@
 		       union iwreq_data *	wrqu,
 		       char *			extra)
 {
-#ifdef IW_WIRELESS_SPY
-	struct iw_spy_data *	spydata = (dev->priv +
-					   dev->wireless_handlers->spy_offset);
+	struct iw_spy_data *	spydata = get_spydata(dev);
 	struct sockaddr *	address = (struct sockaddr *) extra;
 
+	if(!dev->wireless_data)
+		/* Help user know that driver needs updating */
+		printk(KERN_DEBUG "%s (WE) : Driver using old/buggy spy support, please fix driver !\n",
+		       dev->name);
+	/* Make sure driver is not buggy or using the old API */
+	if(!spydata)
+		return -EOPNOTSUPP;
+
 	/* Disable spy collection while we copy the addresses.
-	 * As we don't disable interrupts, we need to do this to avoid races.
-	 * As we are the only writer, this is good enough. */
+	 * While we copy addresses, any call to wireless_spy_update()
+	 * will NOP. This is OK, as anyway the addresses are changing. */
 	spydata->spy_number = 0;
 
+	/* We want to operate without locking, because wireless_spy_update()
+	 * most likely will happen in the interrupt handler, and therefore
+	 * have it own locking constraints and needs performance.
+	 * The rtnl_lock() make sure we don't race with the other iw_handlers.
+	 * This make sure wireless_spy_update() "see" that the spy list
+	 * is temporarily disabled. */
+	wmb();
+
 	/* Are there are addresses to copy? */
 	if(wrqu->data.length > 0) {
 		int i;
@@ -1174,13 +1258,14 @@
 			       spydata->spy_address[i][5]);
 #endif	/* WE_SPY_DEBUG */
 	}
+
+	/* Make sure above is updated before re-enabling */
+	wmb();
+
 	/* Enable addresses */
 	spydata->spy_number = wrqu->data.length;
 
 	return 0;
-#else /* IW_WIRELESS_SPY */
-	return -EOPNOTSUPP;
-#endif /* IW_WIRELESS_SPY */
 }
 
 /*------------------------------------------------------------------*/
@@ -1192,12 +1277,14 @@
 		       union iwreq_data *	wrqu,
 		       char *			extra)
 {
-#ifdef IW_WIRELESS_SPY
-	struct iw_spy_data *	spydata = (dev->priv +
-					   dev->wireless_handlers->spy_offset);
+	struct iw_spy_data *	spydata = get_spydata(dev);
 	struct sockaddr *	address = (struct sockaddr *) extra;
 	int			i;
 
+	/* Make sure driver is not buggy or using the old API */
+	if(!spydata)
+		return -EOPNOTSUPP;
+
 	wrqu->data.length = spydata->spy_number;
 
 	/* Copy addresses. */
@@ -1214,9 +1301,6 @@
 	for(i = 0; i < spydata->spy_number; i++)
 		spydata->spy_stat[i].updated = 0;
 	return 0;
-#else /* IW_WIRELESS_SPY */
-	return -EOPNOTSUPP;
-#endif /* IW_WIRELESS_SPY */
 }
 
 /*------------------------------------------------------------------*/
@@ -1228,11 +1312,13 @@
 			  union iwreq_data *	wrqu,
 			  char *		extra)
 {
-#ifdef IW_WIRELESS_THRSPY
-	struct iw_spy_data *	spydata = (dev->priv +
-					   dev->wireless_handlers->spy_offset);
+	struct iw_spy_data *	spydata = get_spydata(dev);
 	struct iw_thrspy *	threshold = (struct iw_thrspy *) extra;
 
+	/* Make sure driver is not buggy or using the old API */
+	if(!spydata)
+		return -EOPNOTSUPP;
+
 	/* Just do it */
 	memcpy(&(spydata->spy_thr_low), &(threshold->low),
 	       2 * sizeof(struct iw_quality));
@@ -1245,9 +1331,6 @@
 #endif	/* WE_SPY_DEBUG */
 
 	return 0;
-#else /* IW_WIRELESS_THRSPY */
-	return -EOPNOTSUPP;
-#endif /* IW_WIRELESS_THRSPY */
 }
 
 /*------------------------------------------------------------------*/
@@ -1259,22 +1342,20 @@
 			  union iwreq_data *	wrqu,
 			  char *		extra)
 {
-#ifdef IW_WIRELESS_THRSPY
-	struct iw_spy_data *	spydata = (dev->priv +
-					   dev->wireless_handlers->spy_offset);
+	struct iw_spy_data *	spydata = get_spydata(dev);
 	struct iw_thrspy *	threshold = (struct iw_thrspy *) extra;
 
+	/* Make sure driver is not buggy or using the old API */
+	if(!spydata)
+		return -EOPNOTSUPP;
+
 	/* Just do it */
 	memcpy(&(threshold->low), &(spydata->spy_thr_low),
 	       2 * sizeof(struct iw_quality));
 
 	return 0;
-#else /* IW_WIRELESS_THRSPY */
-	return -EOPNOTSUPP;
-#endif /* IW_WIRELESS_THRSPY */
 }
 
-#ifdef IW_WIRELESS_THRSPY
 /*------------------------------------------------------------------*/
 /*
  * Prepare and send a Spy Threshold event
@@ -1312,7 +1393,6 @@
 	/* Send event to user space */
 	wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
 }
-#endif /* IW_WIRELESS_THRSPY */
 
 /* ---------------------------------------------------------------- */
 /*
@@ -1325,12 +1405,14 @@
 			 unsigned char *	address,
 			 struct iw_quality *	wstats)
 {
-#ifdef IW_WIRELESS_SPY
-	struct iw_spy_data *	spydata = (dev->priv +
-					   dev->wireless_handlers->spy_offset);
+	struct iw_spy_data *	spydata = get_spydata(dev);
 	int			i;
 	int			match = -1;
 
+	/* Make sure driver is not buggy or using the old API */
+	if(!spydata)
+		return;
+
 #ifdef WE_SPY_DEBUG
 	printk(KERN_DEBUG "wireless_spy_update() :  offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
 #endif	/* WE_SPY_DEBUG */
@@ -1342,7 +1424,7 @@
 			       sizeof(struct iw_quality));
 			match = i;
 		}
-#ifdef IW_WIRELESS_THRSPY
+
 	/* Generate an event if we cross the spy threshold.
 	 * To avoid event storms, we have a simple hysteresis : we generate
 	 * event only when we go under the low threshold or above the
@@ -1362,8 +1444,6 @@
 			}
 		}
 	}
-#endif /* IW_WIRELESS_THRSPY */
-#endif /* IW_WIRELESS_SPY */
 }
 
 EXPORT_SYMBOL(iw_handler_get_spy);
diff -Nru a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
--- a/net/irda/irlan/irlan_client.c	2004-10-10 22:15:16 -07:00
+++ b/net/irda/irlan/irlan_client.c	2004-10-10 22:15:16 -07:00
@@ -234,7 +234,7 @@
 	ASSERT(tsap == self->client.tsap_ctrl, return;);
 
        	/* Remove frames queued on the control channel */
-	while ((skb = skb_dequeue(&self->client.txq))) {
+	while ((skb = skb_dequeue(&self->client.txq)) != NULL) {
 		dev_kfree_skb(skb);
 	}
 	self->client.tx_busy = FALSE;