]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.99pre6-3 2.3.99pre6-3
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:34:00 +0000 (15:34 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:34:00 +0000 (15:34 -0500)
189 files changed:
CREDITS
Documentation/Changes
Documentation/Configure.help
Documentation/networking/fore200e.txt
Documentation/networking/tulip.txt
MAINTAINERS
Makefile
arch/alpha/kernel/irq.c
arch/arm/defconfig
arch/i386/config.in
arch/i386/defconfig
arch/ia64/defconfig
arch/ppc/defconfig
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc/kernel/sys_sunos.c
arch/sparc/kernel/systbls.S
arch/sparc/kernel/time.c
arch/sparc/lib/atomic.S
arch/sparc/lib/bitops.S
arch/sparc/lib/copy_user.S
arch/sparc64/defconfig
arch/sparc64/kernel/ioctl32.c
arch/sparc64/kernel/power.c
arch/sparc64/kernel/sbus.c
arch/sparc64/kernel/signal32.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/kernel/sys_sparc.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/sys_sunos32.c
arch/sparc64/kernel/systbls.S
arch/sparc64/kernel/time.c
arch/sparc64/lib/blockops.S
arch/sparc64/mm/fault.c
arch/sparc64/mm/init.c
arch/sparc64/solaris/misc.c
drivers/atm/Config.in
drivers/atm/Makefile
drivers/atm/ambassador.c
drivers/atm/ambassador.h
drivers/atm/atmdev_init.c
drivers/atm/eni.c
drivers/atm/eni.h
drivers/atm/fore200e.c
drivers/atm/fore200e.h
drivers/atm/horizon.c
drivers/atm/uPD98402.c
drivers/cdrom/cdrom.c
drivers/char/sx.c
drivers/ide/Config.in
drivers/ide/Makefile
drivers/ide/aec6210.c [deleted file]
drivers/ide/aec62xx.c [new file with mode: 0644]
drivers/ide/ali14xx.c
drivers/ide/alim15x3.c
drivers/ide/amd7409.c
drivers/ide/buddha.c
drivers/ide/cmd640.c
drivers/ide/cmd64x.c
drivers/ide/cy82c693.c
drivers/ide/dtc2278.c
drivers/ide/falconide.c
drivers/ide/gayle.c
drivers/ide/ht6560b.c
drivers/ide/icside.c
drivers/ide/ide-cd.c
drivers/ide/ide-cd.h
drivers/ide/ide-disk.c
drivers/ide/ide-dma.c
drivers/ide/ide-floppy.c
drivers/ide/ide-pci.c
drivers/ide/ide-pnp.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/ide/ide-tape.c
drivers/ide/ide.c
drivers/ide/macide.c
drivers/ide/ns87415.c
drivers/ide/opti621.c
drivers/ide/pdc4030.c
drivers/ide/piix.c
drivers/ide/qd6580.c
drivers/ide/rapide.c
drivers/ide/rz1000.c
drivers/ide/umc8672.c
drivers/ide/via82cxxx.c
drivers/isdn/avmb1/b1pcmcia.c
drivers/isdn/avmb1/capi.c
drivers/isdn/avmb1/capifs.c
drivers/net/8139too.c
drivers/net/Space.c
drivers/net/cs89x0.c
drivers/net/ppp_generic.c
drivers/net/tulip/21142.c
drivers/net/tulip/timer.c
drivers/net/tulip/tulip_core.c
drivers/pci/pci.ids
drivers/sbus/char/sab82532.c
drivers/scsi/ide-scsi.c
drivers/scsi/sd.c
drivers/sound/Makefile
drivers/sound/sb_card.c
drivers/video/aty128fb.c
drivers/video/fbcon-iplan2p2.c
drivers/video/fbcon-iplan2p4.c
drivers/video/fbcon-iplan2p8.c
drivers/video/tdfxfb.c
fs/Config.in
fs/affs/Changes
fs/affs/file.c
fs/devfs/base.c
fs/partitions/acorn.c
fs/partitions/msdos.c
fs/stat.c
include/asm-sparc/elf.h
include/asm-sparc/io.h
include/asm-sparc/namei.h
include/asm-sparc64/delay.h
include/asm-sparc64/elf.h
include/asm-sparc64/io.h
include/asm-sparc64/namei.h
include/asm-sparc64/page.h
include/asm-sparc64/pgalloc.h
include/asm-sparc64/pgtable.h
include/asm-sparc64/sab82532.h
include/asm-sparc64/vga.h
include/linux/atmdev.h
include/linux/hdreg.h
include/linux/hdsmart.h
include/linux/ide.h
include/linux/kernel.h
include/linux/mm.h
include/linux/netfilter_ipv4/ip_conntrack_protocol.h
include/linux/netfilter_ipv4/ipt_state.h
include/linux/pci_ids.h
include/linux/timer.h
include/linux/x25.h
include/net/sock.h
include/net/x25.h
ipc/shm.c
kernel/fork.c
kernel/sys.c
kernel/sysctl.c
net/802/tr.c
net/atm/clip.c
net/atm/common.c
net/atm/common.h
net/atm/lane_mpoa_init.c
net/atm/lec.c
net/atm/lec.h
net/atm/mpc.c
net/atm/mpoa_caches.c
net/atm/mpoa_caches.h
net/atm/raw.c
net/bridge/br.c
net/core/netfilter.c
net/core/skbuff.c
net/core/sock.c
net/econet/af_econet.c
net/ipv4/arp.c
net/ipv4/fib_rules.c
net/ipv4/icmp.c
net/ipv4/ip_fragment.c
net/ipv4/ip_input.c
net/ipv4/ipconfig.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_conntrack_proto_generic.c
net/ipv4/netfilter/ip_conntrack_proto_icmp.c
net/ipv4/netfilter/ip_conntrack_proto_tcp.c
net/ipv4/netfilter/ip_conntrack_proto_udp.c
net/ipv4/netfilter/ip_conntrack_standalone.c
net/ipv4/netfilter/ip_nat_standalone.c
net/ipv4/netfilter/ip_queue.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ipchains_core.c
net/ipv4/netfilter/ipfwadm_core.c
net/ipv4/netfilter/ipt_LOG.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/sched/sch_gred.c
net/sunrpc/pmap_clnt.c
net/sunrpc/svcsock.c
net/x25/af_x25.c
net/x25/x25_facilities.c
net/x25/x25_in.c
net/x25/x25_link.c
net/x25/x25_subr.c

diff --git a/CREDITS b/CREDITS
index d7b04cbde9dbb4c5605f584d129c3514b6661ce2..6fde4afc1d2d78942349956a52706febea8c7a07 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -941,17 +941,13 @@ E: ajh@primag.co.uk
 D: Selection mechanism
 
 N: Andre Hedrick
+E: andre@linux-ide.org
 E: andre@suse.com
 D: Random SMP kernel hacker...
 D: Uniform Multi-Platform E-IDE driver
-D: AEC6210UF Ultra33
-D: Aladdin 1533/1543(C) chipset
-D: Active-Chipset maddness..........
-D: HighPoint HPT343/5 Ultra/33 & HPT366 Ultra/66 chipsets
-D: Intel PIIX chipset
-D: Promise PDC20246/20247 & PDC20262 chipsets
-D: SiS5513 Ultra/66/33 chipsets
-D: VIA 82C586/596/686 chipsets
+D: Active-ATA-Chipset maddness..........
+D: Ultra DMA 66/33
+D: ATA-Smart Kernel Daemon
 S: 580 Second Street, Suite 2
 S: Oakland, CA
 S: USA
@@ -1173,6 +1169,7 @@ E: djones2@glam.ac.uk
 W: http://linux.powertweak.com
 D: Moved PCI bridge tuning to userspace (Powertweak).
 D: Centaur/IDT Winchip/Winchip 2 tweaks.
+D: AFFS fixes for 2.3.x
 D: Misc clean ups and other random hacking.
 S: 28, Laura Street,
 S: Treforest, Pontypridd,
index ce2c77a9be093d25d397129e9fe351346c63a1c2..f5c4d516f4101e125117bbea550e32560d6ec552 100644 (file)
@@ -62,7 +62,7 @@ running, the suggested command should tell you.
 - Bash                   1.14.7                  ; bash -version
 - Ncpfs                  2.2.0                   ; ncpmount -v
 - Pcmcia-cs              3.1.2                   ; cardmgr -V
-- PPP                    2.3.11                  ; pppd --version
+- PPP                    2.4.0b1                 ; pppd --version
 - Util-linux             2.9i                    ; chsh -v
 - isdn4k-utils           v3.1beta7               ; isdnctrl 2>&1|grep version
 
@@ -391,22 +391,33 @@ support utils to the latest release of pcmcia-cs.
 PPP
 ===
 
-   Due to changes in the PPP driver and routing code, those of you
+   The PPP driver has been restructured to support multilink and
+to enable it to operate over diverse kinds of media.  Those of you
 using PPP networking will need to upgrade your pppd to at least
-version 2.3.11. See ftp://cs.anu.edu.au/pub/software/ppp/ for newest
-versions.
+version 2.4.0b1.  See ftp://linuxcare.com.au/pub/ppp/ for the latest
+version.
 
-   You must make sure that the special device file /dev/ppp exists.
-It can be made by executing this command as root:
+   If you are not using devfs, you must make sure that the special
+device file /dev/ppp exists.  It can be made by executing this command
+as root:
 
        mknod /dev/ppp c 108 0
 
    If you have built ppp support as modules, you should put the lines
-below in your /etc/modules.conf file. I assume you want asynchronous
-ppp; replace ppp_async by ppp_synctty if you want synchronous ppp.
+below in your /etc/modules.conf file.
 
-       alias char-major-108 ppp_generic
-       alias tty-ldisc-3 ppp_async
+       alias char-major-108    ppp_generic
+       alias /dev/ppp          ppp_generic
+       alias tty-ldisc-3       ppp_async
+       alias tty-ldisc-14      ppp_synctty
+       alias ppp-compress-21   bsd_comp
+       alias ppp-compress-24   ppp_deflate
+       alias ppp-compress-26   ppp_deflate
+
+If you are using devfsd and you have ppp_generic as a module, put the
+following line in your /etc/devfsd.conf:
+
+       LOOKUP          ppp             MODLOAD
 
 iBCS
 ====
@@ -723,8 +734,8 @@ ftp://metalab.unc.edu/pub/Linux/system/serial/setserial-2.15.tar.gz
 PPP
 ===
 
-The 2.3.11 release:
-ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.11.tar.gz
+The 2.4.0b1 release:
+ftp://linuxcare.com.au/pub/ppp/ppp-2.4.0b1.tar.gz
 
 IP Chains
 =========
index fd656f58bcf7caf464ce8bbe851beac802199d22..4d2034c7672a09fb3072b73b2d240a4114be2b68 100644 (file)
@@ -718,21 +718,25 @@ CONFIG_BLK_DEV_3W_XXXX_RAID
 
   Please read the comments at the top of drivers/scsi/3w-xxxx.c  
 
-AEC6210 chipset support
-CONFIG_BLK_DEV_AEC6210
+AEC62XX chipset support
+CONFIG_BLK_DEV_AEC62XX
   This driver adds up to 4 more EIDE devices sharing a single
   interrupt. This add-on card is a bootable PCI UDMA controller. In
   order to get this card to initialize correctly in some cases, you
   should say Y here, and preferably also to "Use DMA by default when
   available".
 
-  Please read the comments at the top of drivers/ide/aec6210.c If
-  you say Y here, then say Y to "Use DMA by default when available" as
+  The ATP850U/UF is an UltraDMA 33 chipset base.
+  The ATP860 is an UltraDMA 66 chipset base.
+  The ATP860M(acintosh) version is an UltraDMA 66 chipset base.
+
+  Please read the comments at the top of drivers/ide/aec62xx.c
+  If you say Y here, then say Y to "Use DMA by default when available" as
   well.
 
-AEC6210 Tuning support (WIP)
-CONFIG_AEC6210_TUNING
-  Please read the comments at the top of drivers/ide/aec6210.c  
+AEC62XX Tuning support (WIP)
+CONFIG_AEC62XX_TUNING
+  Please read the comments at the top of drivers/ide/aec62xx.c  
   If unsure, say N.
 
 ALI M15x3 chipset support
@@ -972,6 +976,12 @@ CONFIG_BLK_DEV_VIA82CXXX
 
   If unsure, say N.
 
+VIA82CXXX Tuning support (WIP)
+CONFIG_VIA82CXXX_TUNING
+  Please read the comments at the top of drivers/ide/via82cxxx.c
+
+  If unsure, say N.
+
 Other IDE chipset support
 CONFIG_IDE_CHIPSETS
   Say Y here if you want to include enhanced support for various IDE
@@ -4844,12 +4854,16 @@ CONFIG_PHONE_IXJ
   say N here.
 
 FORE Systems 200E-series
-CONFIG_ATM_FORE200E
+CONFIG_ATM_FORE200E_MAYBE
   This is a driver for the FORE Systems 200E-series ATM adapter
   cards. It simultaneously supports PCA-200E and SBA-200E models
   on PCI and SBUS hosts. Say Y (or M to compile as a module
   named fore_200e.o) here if you have one of these ATM adapters.
  
+  Note that the driver will actually be compiled only if you
+  additionally enable the support for PCA-200E and/or SBA-200E
+  cards.
+
   See the file Documentation/networking/fore200e.txt for further
   details.
  
index 13ee5327eca623689d6e3211ec5b44f34c14f42c..b1f337f0f4ca0a7234f506cdc0cd85ea6b5e2ff9 100644 (file)
@@ -1,6 +1,26 @@
 
-Fore PCA-200E/SBA-200E ATM NIC Firmware Copyright Notice
---------------------------------------------------------
+FORE Systems PCA-200E/SBA-200E ATM NIC driver
+---------------------------------------------
+
+This driver adds support for the FORE Systems 200E-series ATM adapters
+to the Linux operating system. It is based on the earlier PCA-200E driver
+written by Uwe Dannowski.
+
+The driver simultaneously supports PCA-200E and SBA-200E adapters on
+i386, alpha (untested), powerpc, sparc and sparc64 archs.
+
+The intent is to enable the use of different models of FORE adapters at the
+same time, by hosts that have several bus interfaces (such as PCI+SBUS,
+PCI+MCA or PCI+EISA).
+
+Only PCI and SBUS devices are currently supported by the driver, but support
+for other bus interfaces such as EISA should not be too hard to add (this may
+be more tricky for the MCA bus, though, as FORE made some MCA-specific
+modifications to the adapter's AALI interface).
+
+
+Firmware Copyright Notice
+-------------------------
 
 Please read the fore200e_firmware_copyright file present
 in the linux/drivers/atm directory for details and restrictions.
@@ -13,26 +33,22 @@ The FORE Systems 200E-series driver is shipped with firmware data being
 uploaded to the ATM adapters at system boot time or at module loading time. 
 The supplied firmware images should work with all adapters.
 
-However, if you encounter problems (firmware doesn't start or the driver
-is unable to read PROM data), you may consider trying another firmware
+However, if you encounter problems (the firmware doesn't start or the driver
+is unable to read the PROM data), you may consider trying another firmware
 version. Alternative binary firmware images can be found somewhere on the
-ForeThough CD-ROM supplied with your adapter by FORE Systems.
+ForeThought CD-ROM supplied with your adapter by FORE Systems.
 
 You can also get the latest firmware images from FORE Systems at
 http://www.fore.com. Register TACTics Online and go to
 the 'software updates' pages. The firmware binaries are part of
-the various ForeThough software distributions.
+the various ForeThought software distributions.
 
 Notice that different versions of the PCA-200E firmware exist, depending
 on the endianess of the host architecture. The driver is shipped with
 both little and big endian PCA firmware images.
 
 Name and location of the new firmware images can be set at kernel
-configuration time.
-
-
-Driver Rebuilding
------------------
+configuration time:
 
 1. Copy the new firmware binary files (with .bin, .bin1 or .bin2 suffix)
    to some directory, such as linux/drivers/atm.
@@ -40,11 +56,7 @@ Driver Rebuilding
 2. Reconfigure your kernel to set the new firmware name and location.
    Expected pathnames are absolute or relative to the drivers/atm directory.
 
-3. Delete the files drivers/atm/fore200e_pca_fw.[co] and/or fore200e_sba_fw.[co]
-   to ensure that the new firmware will be used when rebuilding the kernel or
-   the module.
-
-4. Rebuild and re-install your kernel or your module.
+3. Rebuild and re-install your kernel or your module.
 
 
 Feedback
@@ -52,4 +64,3 @@ Feedback
 
 Feedback is welcome. Please send success stories/bug reports/
 patches/improvement/comments/flames to <lizzi@cnam.fr>.
-
index f4b553705f0faed3f504f62d377fceb4ddb79df9..be41c4031198a7671abb3d0751b4355d985ec878 100644 (file)
@@ -142,6 +142,10 @@ tulip_core.c       - Driver core (a.k.a. where "everything else" goes)
 
 Version history
 ===============
+0.9.4.3 (April 14, 2000):
+* mod_timer fix (Hal Murray)
+* PNIC2 resusitation (Chris Smith)
+
 0.9.4.2 (March 21, 2000):
 * Fix 21041 CSR7, CSR13/14/15 handling
 * Merge some PCI ids from tulip 0.91x
index ed1b09e33b80e23ce58c754fbe3174d7dcb92dd6..43e375cf781f548c350a8ddf5c7b2ff4e368eeba 100644 (file)
@@ -474,9 +474,11 @@ S:      Supported
 
 IDE DRIVER [GENERAL]
 P:     Andre Hedrick
+M:     andre@linux-ide.org
 M:     andre@suse.com
 L:     linux-kernel@vger.rutgers.edu
-W:     http://linux.kernel.org/pub/linux/kernel/people/hedrick/
+W:     http://www.kernel.org/pub/linux/kernel/people/hedrick/
+W:     http://www.linux-ide.org/
 S:     Supported
 
 IDE/ATAPI CDROM DRIVER
@@ -611,9 +613,8 @@ S:  Maintained
 
 MAESTRO PCI SOUND DRIVER
 P:     Zach Brown
-M:     zab@redhat.com
-W:     http://people.redhat.com/zab/maestro/
-S:     Supported
+M:     zab@zabbo.net
+S:     Odd Fixes
 
 M68K
 P:     Jes Sorensen
index 790887c5a5ee72304fc10dd7a740c67cf8bb4f28..0fcc720279e4c988002ad52458f8ccaa502559d2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -370,6 +370,7 @@ clean:      archclean
        rm -f drivers/char/conmakehash
        rm -f drivers/pci/devlist.h drivers/pci/classlist.h drivers/pci/gen-devlist
        rm -f drivers/sound/bin2hex drivers/sound/hex2hex
+       rm -f drivers/atm/fore200e_mkfirm drivers/atm/{pca,sba}*{.bin,.bin1,.bin2}
        rm -f net/khttpd/make_times_h
        rm -f net/khttpd/times.h
        rm -f submenu*
@@ -388,6 +389,7 @@ mrproper: clean archmrproper
        rm -f drivers/sound/msndperm.c
        rm -f drivers/sound/pndsperm.c
        rm -f drivers/sound/pndspini.c
+       rm -f drivers/atm/fore200e_*_fw.c drivers/atm/.fore200e_*.fw
        rm -f .version .config* config.in config.old
        rm -f scripts/tkparse scripts/kconfig.tk scripts/kconfig.tmp
        rm -f scripts/lxdialog/*.o scripts/lxdialog/lxdialog
index 1f454cf48cf6e340e0d0f147be9f6079cca96b0f..e47fcd3caa7eb7a2eb7e41dd5aebde3e5424a87d 100644 (file)
@@ -373,7 +373,7 @@ register_irq_proc (unsigned int irq)
 
 #ifdef CONFIG_SMP
        /* create /proc/irq/1234/smp_affinity */
-       entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]);
+       entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
 
        entry->nlink = 1;
        entry->data = (void *)(long)irq;
@@ -397,7 +397,7 @@ init_irq_proc (void)
 
 #ifdef CONFIG_SMP
        /* create /proc/irq/prof_cpu_mask */
-       entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir);
+       entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
 
        entry->nlink = 1;
        entry->data = (void *)&prof_cpu_mask;
index c5b38947644ebd30ed4eeac30ac4aa14ee62bfa8..077eef8b3f5dbecfa326d12fb857e862c40b5406 100644 (file)
@@ -536,8 +536,8 @@ CONFIG_BLK_DEV_IDEDMA=y
 CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 # CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD7409 is not set
index f652df3331df04aa5bdfe0c3526373b5f498d522..fbf8dc50073f1a95cf8b2564f720278621bcb375 100644 (file)
@@ -28,45 +28,51 @@ choice 'Processor family' \
 #
 # Define implied options from the CPU selection here
 #
-if [ "$CONFIG_M386" != "y" ]; then
+if [ "$CONFIG_M386" = "y" ]; then
+   define_int  CONFIG_X86_L1_CACHE_BYTES 16
+else
    define_bool CONFIG_X86_WP_WORKS_OK y
    define_bool CONFIG_X86_INVLPG y
    define_bool CONFIG_X86_CMPXCHG y
    define_bool CONFIG_X86_BSWAP y
    define_bool CONFIG_X86_POPAD_OK y
 fi
-if [ "$CONFIG_M386" = "y" -o "$CONFIG_M486" = "y" ]; then
-   define_int CONFIG_X86_L1_CACHE_BYTES 16
-else
-   define_int CONFIG_X86_L1_CACHE_BYTES 32
-fi
-if [ "$CONFIG_M486" = "y" -o "$CONFIG_M586" = "y" ]; then
+if [ "$CONFIG_M486" = "y" ]; then
+   define_int  CONFIG_X86_L1_CACHE_BYTES 16
    define_bool CONFIG_X86_USE_STRING_486 y
    define_bool CONFIG_X86_ALIGNMENT_16 y
 fi
-if [ "$CONFIG_M586TSC" = "y" ]; then
+if [ "$CONFIG_M586" = "y" ]; then
+   define_int  CONFIG_X86_L1_CACHE_BYTES 32
    define_bool CONFIG_X86_USE_STRING_486 y
    define_bool CONFIG_X86_ALIGNMENT_16 y
-   define_bool CONFIG_X86_TSC y
 fi
-if [ "$CONFIG_MK6" = "y" ]; then
+if [ "$CONFIG_M586TSC" = "y" ]; then
+   define_int  CONFIG_X86_L1_CACHE_BYTES 32
+   define_bool CONFIG_X86_USE_STRING_486 y
    define_bool CONFIG_X86_ALIGNMENT_16 y
    define_bool CONFIG_X86_TSC y
-   define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
 fi
 if [ "$CONFIG_M686" = "y" ]; then
+   define_int  CONFIG_X86_L1_CACHE_BYTES 32
    define_bool CONFIG_X86_TSC y
    define_bool CONFIG_X86_GOOD_APIC y
    define_bool CONFIG_X86_PGE y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
 fi
+if [ "$CONFIG_MK6" = "y" ]; then
+   define_int  CONFIG_X86_L1_CACHE_BYTES 32
+   define_bool CONFIG_X86_ALIGNMENT_16 y
+   define_bool CONFIG_X86_TSC y
+   define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
+fi
 if [ "$CONFIG_MK7" = "y" ]; then
+   define_int  CONFIG_X86_L1_CACHE_BYTES 64
    define_bool CONFIG_X86_TSC y
    define_bool CONFIG_X86_GOOD_APIC y
    define_bool CONFIG_X86_USE_3DNOW y
    define_bool CONFIG_X86_PGE y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
-   define_int CONFIG_X86_L1_CACHE_BYTES 64
 fi
 
 tristate '/dev/cpu/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE
index 9fa79dff9934cab71cc5e12ed5911c987b9448e2..26f859887dabe06e83b17edddd60fbdc4650eaf6 100644 (file)
@@ -190,8 +190,8 @@ CONFIG_IDEPCI_SHARE_IRQ=y
 # CONFIG_IDEDMA_PCI_EXPERIMENTAL is not set
 # CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD7409 is not set
index 12854f121721f52bda38641cc9d100202308d256..00a0e05b7c039f0007df698da864311a3c470c96 100644 (file)
@@ -115,8 +115,8 @@ CONFIG_BLK_DEV_IDEDMA=y
 CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 # CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD7409 is not set
index 8717bc055f8f9c6b5d5a5354207b2045db4e00bb..229768b9bdc0ac0da08e809810ff54a609326081 100644 (file)
@@ -184,8 +184,8 @@ CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 # CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD7409 is not set
index b589712aaee14bc3a5a51e91a1e2915a01537bb7..5cd8f723598357bd42eb99c25c9604cb42f5065f 100644 (file)
@@ -443,38 +443,14 @@ void smp4d_message_pass(int target, int msg, unsigned long data, int wait)
        panic("Bogon SMP message pass.");
 }
 
-/* Protects counters touched during level14 ticker */
-static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
-
-#ifdef CONFIG_PROFILE
-
-/* 32-bit Sparc specific profiling function. */
-static inline void sparc_do_profile(unsigned long pc)
-{
-       if(prof_buffer && current->pid) {
-               extern int _stext;
-
-               pc -= (unsigned long) &_stext;
-               pc >>= prof_shift;
-
-               spin_lock(&ticker_lock);
-               if(pc < prof_len)
-                       prof_buffer[pc]++;
-               else
-                       prof_buffer[prof_len - 1]++;
-               spin_unlock(&ticker_lock);
-       }
-}
-
-#endif
-
 extern unsigned int prof_multiplier[NR_CPUS];
 extern unsigned int prof_counter[NR_CPUS];
 
 extern void update_one_process(struct task_struct *p, unsigned long ticks,
                               unsigned long user, unsigned long system,
                               int cpu);
-                              
+
+extern void sparc_do_profile(unsigned long pc, unsigned long o7);
 
 void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
 {
@@ -493,12 +469,13 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
                show_leds(cpu);
        }
 
-#ifdef CONFIG_PROFILE
        if(!user_mode(regs))
-               sparc_do_profile(regs->pc);
-#endif
+               sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+
        if(!--prof_counter[cpu]) {
                int user = user_mode(regs);
+
+               irq_enter(cpu, 0);
                if(current->pid) {
                        update_one_process(current, 1, user, !user, cpu);
 
@@ -507,7 +484,6 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
                                current->need_resched = 1;
                        }
 
-                       spin_lock(&ticker_lock);
                        if(user) {
                                if(current->priority < DEF_PRIORITY) {
                                        kstat.cpu_nice++;
@@ -520,9 +496,9 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
                                kstat.cpu_system++;
                                kstat.per_cpu_system[cpu]++;
                        }
-                       spin_unlock(&ticker_lock);
                }
                prof_counter[cpu] = prof_multiplier[cpu];
+               irq_exit(cpu, 0);
        }
 }
 
index 36c3d3c259d993dc5bf12be44c19a57b70b9500f..f0e046db367ce1d9adbb3d2c4f9d97626d752cbc 100644 (file)
@@ -440,27 +440,6 @@ void smp4m_cross_call_irq(void)
        ccall_info.processors_out[i] = 1;
 }
 
-/* Protects counters touched during level14 ticker */
-static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
-
-/* 32-bit Sparc specific profiling function. */
-static inline void sparc_do_profile(unsigned long pc)
-{
-       if(prof_buffer && current->pid) {
-               extern int _stext;
-
-               pc -= (unsigned long) &_stext;
-               pc >>= prof_shift;
-
-               spin_lock(&ticker_lock);
-               if(pc < prof_len)
-                       prof_buffer[pc]++;
-               else
-                       prof_buffer[prof_len - 1]++;
-               spin_unlock(&ticker_lock);
-       }
-}
-
 extern unsigned int prof_multiplier[NR_CPUS];
 extern unsigned int prof_counter[NR_CPUS];
 
@@ -468,6 +447,8 @@ extern void update_one_process(struct task_struct *p, unsigned long ticks,
                               unsigned long user, unsigned long system,
                               int cpu);
 
+extern void sparc_do_profile(unsigned long pc, unsigned long o7);
+
 void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
 {
        int cpu = smp_processor_id();
@@ -475,7 +456,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
        clear_profile_irq(mid_xlate[cpu]);
 
        if(!user_mode(regs))
-               sparc_do_profile(regs->pc);
+               sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
 
        if(!--prof_counter[cpu]) {
                int user = user_mode(regs);
index 675ac5890d4e51f334f25c82f13a57e38e5c0470..dfb28aab1c90b4477364c802c39cee2519c647c4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.120 2000/04/08 08:32:14 davem Exp $
+/* $Id: sys_sunos.c,v 1.121 2000/04/13 00:55:48 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
index de3e68560612251bed6dd673977541ba08dcc203..5bb551a46ba2410d6c4a453a0fe548ba25127287 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.96 2000/03/15 02:43:32 davem Exp $
+/* $Id: systbls.S,v 1.97 2000/04/13 00:55:49 davem Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
index 5a03e646b0321b4e4329695e3b5347344fe8aaa1..68105c4216a05d5b2eab6920a15ebe558611c66b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.53 2000/02/09 21:11:04 davem Exp $
+/* $Id: time.c,v 1.54 2000/04/13 08:14:30 anton Exp $
  * linux/arch/sparc/kernel/time.c
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -70,6 +70,37 @@ struct intersil *intersil_clock;
 
 #endif
 
+static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
+
+/* 32-bit Sparc specific profiling function. */
+void sparc_do_profile(unsigned long pc, unsigned long o7)
+{
+       if(prof_buffer && current->pid) {
+               extern int _stext;
+               extern int __copy_user_begin, __copy_user_end;
+               extern int __atomic_begin, __atomic_end;
+               extern int __bitops_begin, __bitops_end;
+
+               if ((pc >= (unsigned long) &__copy_user_begin &&
+                    pc < (unsigned long) &__copy_user_end) ||
+                   (pc >= (unsigned long) &__atomic_begin &&
+                    pc < (unsigned long) &__atomic_end) ||
+                   (pc >= (unsigned long) &__bitops_begin &&
+                    pc < (unsigned long) &__bitops_end))
+                       pc = o7;
+
+               pc -= (unsigned long) &_stext;
+               pc >>= prof_shift;
+
+               spin_lock(&ticker_lock);
+               if(pc < prof_len)
+                       prof_buffer[pc]++;
+               else
+                       prof_buffer[prof_len - 1]++;
+               spin_unlock(&ticker_lock);
+       }
+}
+
 __volatile__ unsigned int *master_l10_counter;
 __volatile__ unsigned int *master_l10_limit;
 
@@ -82,6 +113,11 @@ void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        /* last time the cmos clock got updated */
        static long last_rtc_update=0;
 
+#ifndef __SMP__
+       if(!user_mode(regs))
+               sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+#endif
+
 #ifdef CONFIG_SUN4
        if((idprom->id_machtype == (SM_SUN4 | SM_4_260)) ||
           (idprom->id_machtype == (SM_SUN4 | SM_4_110))) {
index c57e61574c770a74d1323586ff998a2ecb8d9160..76c4d8164cfe1ab03068bb03138107c7bb674b05 100644 (file)
@@ -10,6 +10,9 @@
        .text
        .align  4
 
+       .globl  __atomic_begin
+__atomic_begin:
+
 #ifndef __SMP__
        .globl  ___xchg32_sun4c
 ___xchg32_sun4c:
@@ -92,3 +95,6 @@ ___atomic_sub:
        nop; nop; nop;                  ! Let the bits set
        jmpl    %o7, %g0                ! NOTE: not + 8, see callers in atomic.h
         mov    %g4, %o7                ! Restore %o7
+
+       .globl  __atomic_end
+__atomic_end:
index ea9ed5a6cf8c1542d272363bc2916adf4a636fe1..10fc427389ab13830d7db0234a2c1dfc92f70550 100644 (file)
@@ -10,6 +10,9 @@
        .text
        .align  4
 
+       .globl  __bitops_begin
+__bitops_begin:
+
        /* Take bits in %g2 and set them in word at %g1,
         * return whether bits were set in original value
         * in %g2.  %g4 holds value to restore into %o7
@@ -159,3 +162,6 @@ ___clear_le_bit:
        nop; nop; nop
        jmpl    %o7, %g0
         mov    %g4, %o7
+
+       .globl  __bitops_end
+__bitops_end:
index 97c55f02d73333befca945d24b901692bfaa8301..239ec762ddfc8f3425259a6c6cdce2da8d6c0c29 100644 (file)
        .text
        .align  4
 
+       .globl  __copy_user_begin
+__copy_user_begin:
+
        .globl  C_LABEL(__copy_user)
 dword_align:
        andcc   %o1, 1, %g0
@@ -482,3 +485,6 @@ fixupretl:
        sub     %o0, %g3, %o0
        ba      fixupretl
         add    %g3, %o2, %g3
+
+       .globl  __copy_user_end
+__copy_user_end:
index 3ceeb634b25586f49ef6dd8cb2a6c3579d064b81..ace71569b7671585371a0d6007742fffba8f6168 100644 (file)
@@ -223,8 +223,8 @@ CONFIG_BLK_DEV_IDEDMA=y
 CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 # CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD7409 is not set
index ef07fca85ebca66a934a6c4c4161881a78ea4089..c7e2fecfbe70c87a0474689bacdaa985971eb851 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.87 2000/03/30 02:09:07 davem Exp $
+/* $Id: ioctl32.c,v 1.88 2000/04/14 10:10:34 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -1816,6 +1816,7 @@ struct atm_iobuf32 {
 #define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32)
 #define ATM_GETLOOP32    _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32)
 #define ATM_SETLOOP32    _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32)
+#define ATM_QUERYLOOP32          _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32)
 
 static struct {
         unsigned int cmd32;
@@ -1836,7 +1837,8 @@ static struct {
        { ATM_GETSTAT32,     ATM_GETSTAT },
        { ATM_GETSTATZ32,    ATM_GETSTATZ },
        { ATM_GETLOOP32,     ATM_GETLOOP },
-       { ATM_SETLOOP32,     ATM_SETLOOP }
+       { ATM_SETLOOP32,     ATM_SETLOOP },
+       { ATM_QUERYLOOP32,   ATM_QUERYLOOP }
 };
 
 #define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0]))
@@ -1996,6 +1998,7 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
        case ATM_GETSTATZ:
        case ATM_GETLOOP:
        case ATM_SETLOOP:
+       case ATM_QUERYLOOP:
                 return do_atmif_sioc(fd, cmd, arg);
         }
 
@@ -3110,6 +3113,7 @@ HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl)
 HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl)
 HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl)
 HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_QUERYLOOP32, do_atm_ioctl)
 HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl)
 HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl)
 HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl)
index e612d0200122d3a950d8b9518004228405b52ff6..ccf0c03bf35a06e042fcde37d0118a62c5b2a7cc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: power.c,v 1.5 1999/12/19 23:28:00 davem Exp $
+/* $Id: power.c,v 1.6 2000/04/13 00:59:59 davem Exp $
  * power.c: Power management driver.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -55,8 +55,7 @@ static int powerd(void *__unused)
        static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
        char *argv[] = { "/usr/bin/shutdown", "-h", "now", NULL };
 
-       current->session = 1;
-       current->pgrp = 1;
+       daemonize();
        sprintf(current->comm, "powerd");
 
 again:
index c9a0d4a59b61f83efdf66601e8a0d04cb295f73b..602ee9ca2b3ce7e8330449af527d93109e337162 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.10 2000/03/10 07:52:08 davem Exp $
+/* $Id: sbus.c,v 1.11 2000/04/14 09:13:04 davem Exp $
  * sbus.c: UltraSparc SBUS controller support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -315,7 +315,7 @@ void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_add
 dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int dir)
 {
        struct sbus_iommu *iommu = sdev->bus->iommu;
-       unsigned long npages, phys_base, flags;
+       unsigned long npages, pbase, flags;
        iopte_t *iopte;
        u32 dma_base, offset;
        unsigned long iopte_bits;
@@ -323,10 +323,10 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int di
        if (dir == SBUS_DMA_NONE)
                BUG();
 
-       phys_base = (unsigned long) ptr;
-       offset = (u32) (phys_base & ~PAGE_MASK);
-       size = (PAGE_ALIGN(phys_base + size) - (phys_base & PAGE_MASK));
-       phys_base = (unsigned long) __pa(phys_base & PAGE_MASK);
+       pbase = (unsigned long) ptr;
+       offset = (u32) (pbase & ~PAGE_MASK);
+       size = (PAGE_ALIGN(pbase + size) - (pbase & PAGE_MASK));
+       pbase = (unsigned long) __pa(pbase & PAGE_MASK);
 
        spin_lock_irqsave(&iommu->lock, flags);
        npages = size >> PAGE_SHIFT;
@@ -337,8 +337,8 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int di
        if (dir != SBUS_DMA_TODEVICE)
                iopte_bits |= IOPTE_WRITE;
        while (npages--) {
-               *iopte++ = __iopte(iopte_bits | (phys_base & IOPTE_PAGE));
-               phys_base += PAGE_SIZE;
+               *iopte++ = __iopte(iopte_bits | (pbase & IOPTE_PAGE));
+               pbase += PAGE_SIZE;
        }
        npages = size >> PAGE_SHIFT;
        spin_unlock_irqrestore(&iommu->lock, flags);
index 273643db6bf18a70186bf003930ad55bdc79ab61..1f5c03716102748fdd7e1c6c4a62cf8900ee22b5 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: signal32.c,v 1.61 2000/04/08 02:11:46 davem Exp $
+/*  $Id: signal32.c,v 1.62 2000/04/12 08:10:19 davem Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -750,8 +750,7 @@ static inline void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *reg
                        goto sigsegv;
 
                if(pte_present(*ptep)) {
-                       unsigned long page = (unsigned long)
-                               __va(pte_pagenr(*ptep) << PAGE_SHIFT);
+                       unsigned long page = page_address(pte_page(*ptep));
 
                        __asm__ __volatile__("
                        membar  #StoreStore
@@ -1176,8 +1175,7 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs
                        goto sigsegv;
 
                if(pte_present(*ptep)) {
-                       unsigned long page = (unsigned long)
-                               __va(pte_pagenr(*ptep) << PAGE_SHIFT);
+                       unsigned long page = page_address(pte_page(*ptep));
 
                        __asm__ __volatile__("
                        membar  #StoreStore
index e9a180d2a340d3b5fde560022a582aa5017e589d..9964a78268e2d6dd697f5ff8676697132596814f 100644 (file)
@@ -627,33 +627,7 @@ void smp_promstop_others(void)
                smp_cross_call(&xcall_promstop, 0, 0, 0);
 }
 
-static inline void sparc64_do_profile(unsigned long pc, unsigned long o7)
-{
-       if (prof_buffer && current->pid) {
-               extern int _stext;
-               extern int rwlock_impl_begin, rwlock_impl_end;
-               extern int atomic_impl_begin, atomic_impl_end;
-               extern int __memcpy_begin, __memcpy_end;
-               extern int __bitops_begin, __bitops_end;
-
-               if ((pc >= (unsigned long) &atomic_impl_begin &&
-                    pc < (unsigned long) &atomic_impl_end) ||
-                   (pc >= (unsigned long) &rwlock_impl_begin &&
-                    pc < (unsigned long) &rwlock_impl_end) ||
-                   (pc >= (unsigned long) &__memcpy_begin &&
-                    pc < (unsigned long) &__memcpy_end) ||
-                   (pc >= (unsigned long) &__bitops_begin &&
-                    pc < (unsigned long) &__bitops_end))
-                       pc = o7;
-
-               pc -= (unsigned long) &_stext;
-               pc >>= prof_shift;
-
-               if(pc >= prof_len)
-                       pc = prof_len - 1;
-               atomic_inc((atomic_t *)&prof_buffer[pc]);
-       }
-}
+extern void sparc64_do_profile(unsigned long pc, unsigned long o7);
 
 static unsigned long current_tick_offset;
 
@@ -862,7 +836,7 @@ cycles_t cacheflush_time;
 
 static void __init smp_tune_scheduling (void)
 {
-       unsigned long flush_base, flags, *p;
+       unsigned long orig_flush_base, flush_base, flags, *p;
        unsigned int ecache_size, order;
        cycles_t tick1, tick2, raw;
 
@@ -881,7 +855,8 @@ static void __init smp_tune_scheduling (void)
                                         "ecache-size", (512 * 1024));
        if (ecache_size > (4 * 1024 * 1024))
                ecache_size = (4 * 1024 * 1024);
-       flush_base = __get_free_pages(GFP_KERNEL, order = get_order(ecache_size));
+       orig_flush_base = flush_base =
+               __get_free_pages(GFP_KERNEL, order = get_order(ecache_size));
 
        if (flush_base != 0UL) {
                __save_and_cli(flags);
@@ -923,7 +898,7 @@ static void __init smp_tune_scheduling (void)
                 */
                cacheflush_time = (raw - (raw >> 2));
 
-               free_pages(flush_base, order);
+               free_pages(orig_flush_base, order);
        } else {
                cacheflush_time = ((ecache_size << 2) +
                                   (ecache_size << 1));
index fc7a8cfe57fd707c785c14a17eb59662edd3e294..9a1158fcdcc48da031857ee8d21f29bb70c5f309 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.80 2000/03/27 10:38:47 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.81 2000/04/13 04:45:58 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -297,8 +297,8 @@ EXPORT_SYMBOL(move_addr_to_user);
 /* Special internal versions of library functions. */
 EXPORT_SYMBOL(__memcpy);
 EXPORT_SYMBOL(__memset);
-EXPORT_SYMBOL(clear_page);
-EXPORT_SYMBOL(copy_page);
+EXPORT_SYMBOL(_clear_page);
+EXPORT_SYMBOL(_copy_page);
 EXPORT_SYMBOL(clear_user_page);
 EXPORT_SYMBOL(copy_user_page);
 EXPORT_SYMBOL(__bzero);
index 82aedbb08102016dd8bb03d2040572e181779b7a..067dac553fc031ada979271909d3b7c7c1ef9e25 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.37 2000/03/17 05:48:46 anton Exp $
+/* $Id: sys_sparc.c,v 1.38 2000/04/13 07:30:34 jj Exp $
  * linux/arch/sparc64/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -23,6 +23,7 @@
 #include <linux/smp_lock.h>
 #include <linux/malloc.h>
 #include <linux/ipc.h>
+#include <linux/personality.h>
 
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
@@ -182,6 +183,33 @@ out:
        return err;
 }
 
+extern asmlinkage int sys_newuname(struct new_utsname * name);
+
+asmlinkage int sparc64_newuname(struct new_utsname * name)
+{
+       int ret = sys_newuname(name);
+       
+       if (current->personality == PER_LINUX32 && !ret) {
+               ret = copy_to_user(name->machine, "sparc\0\0", 8);
+       }
+       return ret;
+}
+
+extern asmlinkage long sys_personality(unsigned long);
+
+asmlinkage int sparc64_personality(unsigned long personality)
+{
+       int ret;
+       lock_kernel();
+       if (current->personality == PER_LINUX32 && personality == PER_LINUX)
+               personality = PER_LINUX32;
+       ret = sys_personality(personality);
+       unlock_kernel();
+       if (ret == PER_LINUX32)
+               ret = PER_LINUX;
+       return ret;
+}
+
 /* Linux version of mmap */
 asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
        unsigned long prot, unsigned long flags, unsigned long fd,
index 06258d9b27b863a7e9fc16686b8edc77ea228a46..7bb75f4aedda0631f69f088a93ea5e55f16d9c36 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.144 2000/04/08 02:11:47 davem Exp $
+/* $Id: sys_sparc32.c,v 1.145 2000/04/13 07:30:34 jj Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -3980,18 +3980,6 @@ asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
 }
 
 
-extern asmlinkage int sys_newuname(struct new_utsname * name);
-
-asmlinkage int sys32_newuname(struct new_utsname * name)
-{
-       int ret = sys_newuname(name);
-       
-       if (current->personality == PER_LINUX32 && !ret) {
-               ret = copy_to_user(name->machine, "sparc\0\0", 8);
-       }
-       return ret;
-}
-
 extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
                                    size_t count, loff_t pos);
 
@@ -4013,21 +4001,6 @@ asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
 }
 
 
-extern asmlinkage long sys_personality(unsigned long);
-
-asmlinkage int sys32_personality(unsigned long personality)
-{
-       int ret;
-       lock_kernel();
-       if (current->personality == PER_LINUX32 && personality == PER_LINUX)
-               personality = PER_LINUX32;
-       ret = sys_personality(personality);
-       unlock_kernel();
-       if (ret == PER_LINUX32)
-               ret = PER_LINUX;
-       return ret;
-}
-
 extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
 
 asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
index 7b44226da1a8686d78d368473b82d890abcaa6b1..9c8b4fbe1d9b23ff1e03fd7ba49802b28388e91f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.44 2000/04/08 02:11:50 davem Exp $
+/* $Id: sys_sunos32.c,v 1.45 2000/04/13 00:55:49 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
index d86649bf76e83157ce97126e2113e5800e513967..eb02486f5a5268d5f7982b49a2bf2ed7a3709c54 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.71 2000/03/15 02:43:36 davem Exp $
+/* $Id: systbls.S,v 1.72 2000/04/13 07:30:34 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -56,8 +56,8 @@ sys_call_table32:
 /*170*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
        .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*180*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
-       .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname
-/*190*/        .word sys32_init_module, sys32_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+       .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
+/*190*/        .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
        .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
 /*200*/        .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
        .word sys_nis_syscall, sys32_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
@@ -115,8 +115,8 @@ sys_call_table:
 /*170*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
        .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*180*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
-       .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
-/*190*/        .word sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+       .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
+/*190*/        .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
        .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
 /*200*/        .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
        .word sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
index e599b48cbbd687b90d7f8d13c7c8074e033185de..a955e75df3bb98524724f5de29eaaa28522a8399 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.24 2000/03/02 02:00:25 davem Exp $
+/* $Id: time.c,v 1.25 2000/04/13 05:29:44 davem Exp $
  * time.c: UltraSparc timer and TOD clock support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -67,6 +67,34 @@ static __inline__ void timer_check_rtc(void)
        }
 }
 
+void sparc64_do_profile(unsigned long pc, unsigned long o7)
+{
+       if (prof_buffer && current->pid) {
+               extern int _stext;
+               extern int rwlock_impl_begin, rwlock_impl_end;
+               extern int atomic_impl_begin, atomic_impl_end;
+               extern int __memcpy_begin, __memcpy_end;
+               extern int __bitops_begin, __bitops_end;
+
+               if ((pc >= (unsigned long) &atomic_impl_begin &&
+                    pc < (unsigned long) &atomic_impl_end) ||
+                   (pc >= (unsigned long) &rwlock_impl_begin &&
+                    pc < (unsigned long) &rwlock_impl_end) ||
+                   (pc >= (unsigned long) &__memcpy_begin &&
+                    pc < (unsigned long) &__memcpy_end) ||
+                   (pc >= (unsigned long) &__bitops_begin &&
+                    pc < (unsigned long) &__bitops_end))
+                       pc = o7;
+
+               pc -= (unsigned long) &_stext;
+               pc >>= prof_shift;
+
+               if(pc >= prof_len)
+                       pc = prof_len - 1;
+               atomic_inc((atomic_t *)&prof_buffer[pc]);
+       }
+}
+
 static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
        unsigned long ticks, pstate;
@@ -74,6 +102,10 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        write_lock(&xtime_lock);
 
        do {
+#ifndef __SMP__
+               if ((regs->tstate & TSTATE_PRIV) != 0)
+                       sparc64_do_profile(regs->tpc, regs->u_regs[UREG_RETPC]);
+#endif
                do_timer(regs);
 
                /* Guarentee that the following sequences execute
index 9c6a8beba3fad0f6ad719c2e9701173124e213ee..9668f86d8bc5ab96279b2a48c929f7a44ecc7e3d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: blockops.S,v 1.24 2000/03/27 10:38:41 davem Exp $
+/* $Id: blockops.S,v 1.25 2000/04/13 04:45:58 davem Exp $
  * blockops.S: UltraSparc block zero optimized routines.
  *
  * Copyright (C) 1996, 1998, 1999, 2000 David S. Miller (davem@redhat.com)
@@ -26,9 +26,9 @@
        .text
 
        .align          32
-       .globl          copy_page
-       .type           copy_page,@function
-copy_page: /* %o0=dest, %o1=src */
+       .globl          _copy_page
+       .type           _copy_page,@function
+_copy_page: /* %o0=dest, %o1=src */
        VISEntry
        membar          #LoadStore | #StoreStore | #StoreLoad
        ldda            [%o1] ASI_BLK_P, %f0
@@ -205,9 +205,9 @@ copy_page_using_blkcommit:
         stda           %f16, [%o0] ASI_BLK_COMMIT_P
 
        .align          32
-       .globl          clear_page
-       .type           clear_page,@function
-clear_page:    /* %o0=dest */
+       .globl          _clear_page
+       .type           _clear_page,@function
+_clear_page:   /* %o0=dest */
        VISEntryHalf
        ba,pt           %xcc, clear_page_common
         clr            %o4
index 0d8152887dce2ec5ab0b3f59985374ccfc5b0353..a3d46e027722a3f1ae57038117e7b5b41d1ddc0e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.45 2000/03/27 10:38:51 davem Exp $
+/* $Id: fault.c,v 1.46 2000/04/12 08:10:23 davem Exp $
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -110,7 +110,8 @@ static unsigned int get_user_insn(unsigned long tpc)
        if(!pte_present(pte))
                goto out;
 
-       pa = (pte_pagenr(pte) << PAGE_SHIFT) + (tpc & ~PAGE_MASK);
+       pa  = phys_base + (pte_pagenr(pte) << PAGE_SHIFT);
+       pa += (tpc & ~PAGE_MASK);
 
        /* Use phys bypass so we don't pollute dtlb/dcache. */
        __asm__ __volatile__("lduwa [%1] %2, %0"
index 1d2049b5f9ffe8a5e6b30fcdee91569d3782a9e2..63818e309ccb9a68907d98f80e0d863876aa93c4 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.149 2000/03/15 14:42:58 jj Exp $
+/*  $Id: init.c,v 1.150 2000/04/12 08:10:22 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -738,22 +738,17 @@ pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset)
  */
 pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset, unsigned long color)
 {
-       unsigned long paddr = __get_free_pages(GFP_KERNEL, 1);
+       struct page *page = alloc_pages(GFP_KERNEL, 1);
 
-       if (paddr) {
-               struct page *page2 = mem_map + MAP_NR(paddr + PAGE_SIZE);
+       if (page) {
                unsigned long *to_free;
+               unsigned long paddr;
                pte_t *pte;
 
-               /* Set count of second page, so we can free it
-                * seperately later on.
-                */
-               atomic_set(&page2->count, 1);
-
-               /* Clear out both pages now. */
+               set_page_count((page + 1), 1);
+               paddr = page_address(page);
                memset((char *)paddr, 0, (PAGE_SIZE << 1));
 
-               /* Determine which page we give to this request. */
                if (!color) {
                        pte = (pte_t *) paddr;
                        to_free = (unsigned long *) (paddr + PAGE_SIZE);
@@ -804,50 +799,39 @@ void sparc_ultra_dump_dtlb(void)
         }
 }
 
-#undef DEBUG_BOOTMEM
-
 extern unsigned long cmdline_memory_size;
 
-unsigned long __init bootmem_init(void)
+unsigned long __init bootmem_init(unsigned long *pages_avail)
 {
        unsigned long bootmap_size, start_pfn, end_pfn;
        unsigned long end_of_phys_memory = 0UL;
-       unsigned long bootmap_pfn;
+       unsigned long bootmap_pfn, bytes_avail, size;
        int i;
 
-       /* XXX It is a bit ambiguous here, whether we should
-        * XXX treat the user specified mem=xxx as total wanted
-        * XXX physical memory, or as a limit to the upper
-        * XXX physical address we allow.  For now it is the
-        * XXX latter. -DaveM
-        */
-#ifdef DEBUG_BOOTMEM
-       prom_printf("bootmem_init: Scan sp_banks,  ");
-#endif
+
+       bytes_avail = 0UL;
        for (i = 0; sp_banks[i].num_bytes != 0; i++) {
                end_of_phys_memory = sp_banks[i].base_addr +
                        sp_banks[i].num_bytes;
+               bytes_avail += sp_banks[i].num_bytes;
                if (cmdline_memory_size) {
-                       if (end_of_phys_memory > cmdline_memory_size) {
-                               if (cmdline_memory_size < sp_banks[i].base_addr) {
-                                       end_of_phys_memory =
-                                               sp_banks[i-1].base_addr +
-                                               sp_banks[i-1].num_bytes;
+                       if (bytes_avail > cmdline_memory_size) {
+                               unsigned long slack = bytes_avail - cmdline_memory_size;
+
+                               bytes_avail -= slack;
+                               end_of_phys_memory -= slack;
+
+                               sp_banks[i].num_bytes -= slack;
+                               if (sp_banks[i].num_bytes == 0)
                                        sp_banks[i].base_addr = 0xdeadbeef;
-                                       sp_banks[i].num_bytes = 0;
-                               } else {
-                                       sp_banks[i].num_bytes -=
-                                               (end_of_phys_memory -
-                                                cmdline_memory_size);
-                                       end_of_phys_memory = cmdline_memory_size;
-                                       sp_banks[++i].base_addr = 0xdeadbeef;
-                                       sp_banks[i].num_bytes = 0;
-                               }
+
                                break;
                        }
                }
        }
 
+       *pages_avail = bytes_avail >> PAGE_SHIFT;
+
        /* Start with page aligned address of last symbol in kernel
         * image.  The kernel is hard mapped below PAGE_OFFSET in a
         * 4MB locked TLB translation.
@@ -886,50 +870,40 @@ unsigned long __init bootmem_init(void)
        }
 #endif 
        /* Initialize the boot-time allocator. */
-#ifdef DEBUG_BOOTMEM
-       prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],epfn[%lx])\n",
-                   start_pfn, bootmap_pfn, end_pfn);
-#endif
-       bootmap_size = init_bootmem(bootmap_pfn, end_pfn);
+       bootmap_size = init_bootmem_node(0, bootmap_pfn, phys_base>>PAGE_SHIFT, end_pfn);
 
        /* Now register the available physical memory with the
         * allocator.
         */
-       for (i = 0; sp_banks[i].num_bytes != 0; i++) {
-#ifdef DEBUG_BOOTMEM
-               prom_printf("free_bootmem: base[%lx] size[%lx]\n",
-                           sp_banks[i].base_addr,
-                           sp_banks[i].num_bytes);
-#endif
+       for (i = 0; sp_banks[i].num_bytes != 0; i++)
                free_bootmem(sp_banks[i].base_addr,
                             sp_banks[i].num_bytes);
-       }
 
-       /* Reserve the kernel text/data/bss, the bootmem bootmap and initrd. */
-#ifdef DEBUG_BOOTMEM
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (initrd_start)
-               prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
-                           initrd_start, initrd_end - initrd_start);
-#endif         
-       prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
-                   phys_base, (start_pfn << PAGE_SHIFT) - phys_base);
-       prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
-                   (bootmap_pfn << PAGE_SHIFT), bootmap_size);
-#endif
 #ifdef CONFIG_BLK_DEV_INITRD
        if (initrd_start) {
-               reserve_bootmem(initrd_start, initrd_end - initrd_start);
+               size = initrd_end - initrd_start;
+
+               /* Resert the initrd image area. */
+               reserve_bootmem(initrd_start, size);
+               *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
+
                initrd_start += PAGE_OFFSET;
                initrd_end += PAGE_OFFSET;
        }
 #endif
-       reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) - phys_base);
-       reserve_bootmem((bootmap_pfn << PAGE_SHIFT), bootmap_size);
+       /* Reserve the kernel text/data/bss. */
+       size = (start_pfn << PAGE_SHIFT) - phys_base;
+       reserve_bootmem(phys_base, size);
+       *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+       /* Reserve the bootmem map.   We do not account for it
+        * in pages_avail because we will release that memory
+        * in free_all_bootmem.
+        */
+       size = bootmap_size;
+       reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size);
+       *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
 
-#ifdef DEBUG_BOOTMEM
-       prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn);
-#endif
        return end_pfn;
 }
 
@@ -946,7 +920,7 @@ void __init paging_init(void)
        extern unsigned int sparc64_vpte_patchme2[1];
        unsigned long alias_base = phys_base + PAGE_OFFSET;
        unsigned long second_alias_page = 0;
-       unsigned long pt, flags, end_pfn;
+       unsigned long pt, flags, end_pfn, pages_avail;
        unsigned long shift = alias_base - ((unsigned long)&empty_zero_page);
 
        set_bit(0, mmu_context_bmap);
@@ -1001,7 +975,8 @@ void __init paging_init(void)
        flushi((long)&sparc64_vpte_patchme1[0]);
        
        /* Setup bootmem... */
-       last_valid_pfn = end_pfn = bootmem_init();
+       pages_avail = 0;
+       last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
 
 #ifdef CONFIG_SUN_SERIAL
        /* This does not logically belong here, but we need to
@@ -1039,10 +1014,20 @@ void __init paging_init(void)
        flush_tlb_all();
 
        {
-               unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0};
+               unsigned long zones_size[MAX_NR_ZONES];
+               unsigned long zholes_size[MAX_NR_ZONES];
+               unsigned long npages;
+               int znum;
+
+               for (znum = 0; znum < MAX_NR_ZONES; znum++)
+                       zones_size[znum] = zholes_size[znum] = 0;
+
+               npages = end_pfn - (phys_base >> PAGE_SHIFT);
+               zones_size[ZONE_DMA] = npages;
+               zholes_size[ZONE_DMA] = npages - pages_avail;
 
-               zones_size[ZONE_DMA] = end_pfn;
-               free_area_init(zones_size);
+               free_area_init_node(0, NULL, zones_size,
+                                   phys_base, zholes_size);
        }
 
        device_scan();
@@ -1139,9 +1124,6 @@ static void __init taint_real_pages(void)
        struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS];
        int i;
 
-#ifdef DEBUG_BOOTMEM
-       prom_printf("taint_real_pages: Rescan sp_banks[].\n");
-#endif
        for (i = 0; i < SPARC_PHYS_BANKS; i++) {
                saved_sp_banks[i].base_addr =
                        sp_banks[i].base_addr;
@@ -1176,10 +1158,6 @@ static void __init taint_real_pages(void)
                                        goto do_next_page;
                                }
                        }
-#ifdef DEBUG_BOOTMEM
-                       prom_printf("taint: Page went away, reserve page %lx.\n",
-                                   old_start);
-#endif
                        reserve_bootmem(old_start, PAGE_SIZE);
 
                do_next_page:
@@ -1188,70 +1166,6 @@ static void __init taint_real_pages(void)
        }
 }
 
-void __init free_mem_map_range(struct page *first, struct page *last)
-{
-       first = (struct page *) PAGE_ALIGN((unsigned long)first);
-       last  = (struct page *) ((unsigned long)last & PAGE_MASK);
-#ifdef DEBUG_BOOTMEM
-       prom_printf("[%p,%p] ", first, last);
-#endif
-       while (first < last) {
-               ClearPageReserved(mem_map + MAP_NR(first));
-               set_page_count(mem_map + MAP_NR(first), 1);
-               free_page((unsigned long)first);
-               num_physpages++;
-
-               first = (struct page *)((unsigned long)first + PAGE_SIZE);
-       }
-}
-
-/* Walk through holes in sp_banks regions, if the mem_map array
- * areas representing those holes consume a page or more, free
- * up such pages.  This helps a lot on machines where physical
- * ram is configured such that it begins at some hugh value.
- *
- * The sp_banks array is sorted by base address.
- */
-void __init free_unused_mem_map(void)
-{
-       int i;
-
-#ifdef DEBUG_BOOTMEM
-       prom_printf("free_unused_mem_map: ");
-#endif
-       for (i = 0; sp_banks[i].num_bytes; i++) {
-               if (i == 0) {
-                       struct page *first, *last;
-
-                       first = mem_map;
-                       last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT];
-                       free_mem_map_range(first, last);
-               } else {
-                       struct page *first, *last;
-                       unsigned long prev_end;
-
-                       prev_end = sp_banks[i-1].base_addr +
-                               sp_banks[i-1].num_bytes;
-                       prev_end = PAGE_ALIGN(prev_end);
-                       first = &mem_map[prev_end >> PAGE_SHIFT];
-                       last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT];
-
-                       free_mem_map_range(first, last);
-
-                       if (!sp_banks[i+1].num_bytes) {
-                               prev_end = sp_banks[i].base_addr +
-                                       sp_banks[i].num_bytes;
-                               first = &mem_map[prev_end >> PAGE_SHIFT];
-                               last = &mem_map[last_valid_pfn];
-                               free_mem_map_range(first, last);
-                       }
-               }
-       }
-#ifdef DEBUG_BOOTMEM
-       prom_printf("\n");
-#endif
-}
-
 void __init mem_init(void)
 {
        unsigned long codepages, datapages, initpages;
@@ -1279,16 +1193,10 @@ void __init mem_init(void)
 
        taint_real_pages();
 
-       max_mapnr = last_valid_pfn;
+       max_mapnr = last_valid_pfn - (phys_base >> PAGE_SHIFT);
        high_memory = __va(last_valid_pfn << PAGE_SHIFT);
 
-#ifdef DEBUG_BOOTMEM
-       prom_printf("mem_init: Calling free_all_bootmem().\n");
-#endif
        num_physpages = free_all_bootmem();
-#if 0
-       free_unused_mem_map();
-#endif
        codepages = (((unsigned long) &etext) - ((unsigned long)&_start));
        codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
        datapages = (((unsigned long) &edata) - ((unsigned long)&etext));
@@ -1317,19 +1225,6 @@ void __init mem_init(void)
               datapages << (PAGE_SHIFT-10), 
               initpages << (PAGE_SHIFT-10), 
               PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT));
-
-       /* NOTE NOTE NOTE NOTE
-        * Please keep track of things and make sure this
-        * always matches the code in mm/page_alloc.c -DaveM
-        */
-       i = nr_free_pages() >> 7;
-       if (i < 48)
-               i = 48;
-       if (i > 256)
-               i = 256;
-       freepages.min = i;
-       freepages.low = i << 1;
-       freepages.high = freepages.low + i;
 }
 
 void free_initmem (void)
index 2639d19776b5fe412339874b0492269b994d8efe..ef4c9aa013508f3e94d0edf45d876c8e6d82c088 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.24 2000/04/08 02:11:55 davem Exp $
+/* $Id: misc.c,v 1.26 2000/04/14 09:59:02 davem Exp $
  * misc.c: Miscelaneous syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
index 8fb55632a75533983b70699001fc8d42055001a5..c603f71affd71c42bb8409090125081ff2d03f1d 100644 (file)
@@ -52,8 +52,8 @@ if [ "$CONFIG_PCI" = "y" ]; then
     fi
 fi
 if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SBUS" = "y" ]; then
-  tristate 'FORE Systems 200E-series' CONFIG_ATM_FORE200E
-  if [ "$CONFIG_ATM_FORE200E" != "n" ]; then
+  tristate 'FORE Systems 200E-series' CONFIG_ATM_FORE200E_MAYBE
+  if [ "$CONFIG_ATM_FORE200E_MAYBE" != "n" ]; then
     if [ "$CONFIG_PCI" = "y" ]; then
       bool '  PCA-200E support' CONFIG_ATM_FORE200E_PCA y
       if [ "$CONFIG_ATM_FORE200E_PCA" = "y" ]; then
@@ -72,8 +72,16 @@ if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SBUS" = "y" ]; then
         fi
       fi
     fi
+  fi
+  if [ "$CONFIG_ATM_FORE200E_PCA" = "y" -o "$CONFIG_ATM_FORE200E_SBA" = "y" ]; \
+    then
     int  '  Maximum number of tx retries' CONFIG_ATM_FORE200E_TX_RETRY 16
     int  '  Debugging level (0-3)' CONFIG_ATM_FORE200E_DEBUG 0
+    if [ "$CONFIG_ATM_FORE200E_MAYBE" = "y" ]; then
+      define_tristate CONFIG_ATM_FORE200E y
+    else
+      define_tristate CONFIG_ATM_FORE200E m
+    fi
   fi
 fi
 endmenu
index 8dbf1364aa73ba85d05f88e3223a41326348cb48..330d5d1c37b28d712ae2b2987c5ffcd848c2bb8b 100644 (file)
@@ -30,10 +30,6 @@ else
   endif
 endif
 
-ifeq ($(CONFIG_ATM_TNETA1570),y)
-O_OBJS += tneta1570.o suni.o
-endif
-
 ifeq ($(CONFIG_ATM_NICSTAR),y)
 O_OBJS += nicstar.o
   ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y)
@@ -101,23 +97,29 @@ else
 endif
 
 ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
-FORE200E_FW_OBJS += fore200e_pca_fw.o
+  FORE200E_FW_OBJS += fore200e_pca_fw.o
+  ifeq ($(strip $(CONFIG_ATM_FORE200E_PCA_FW)),"")
+    CONFIG_ATM_FORE200E_PCA_DEFAULT_FW := y
+  endif
   ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y)
 #   guess the target endianess to choose the right PCA-200E firmware image
     CONFIG_ATM_FORE200E_PCA_FW := $(shell if test -n "`$(CC) -E -dM ../../include/asm/byteorder.h | grep ' __LITTLE_ENDIAN '`"; then echo pca200e.bin; else echo pca200e_ecd.bin2; fi)
   endif
 endif
 ifeq ($(CONFIG_ATM_FORE200E_SBA),y)
-FORE200E_FW_OBJS += fore200e_sba_fw.o
+  FORE200E_FW_OBJS += fore200e_sba_fw.o
+  ifeq ($(strip $(CONFIG_ATM_FORE200E_SBA_FW)),"")
+    CONFIG_ATM_FORE200E_SBA_DEFAULT_FW := y
+  endif
   ifeq ($(CONFIG_ATM_FORE200E_SBA_DEFAULT_FW),y)
     CONFIG_ATM_FORE200E_SBA_FW := sba200e_ecd.bin2
   endif
 endif
 ifeq ($(CONFIG_ATM_FORE200E),y)
-O_OBJS += fore200e.o $(FORE200E_FW_OBJS)
+  O_OBJS += fore200e.o $(FORE200E_FW_OBJS)
 else
   ifeq ($(CONFIG_ATM_FORE200E),m)
-  M_OBJS += fore_200e.o
+    M_OBJS += fore_200e.o
   endif
 endif
 
@@ -125,33 +127,51 @@ EXTRA_CFLAGS=-g
 
 include $(TOPDIR)/Rules.make
 
+
 # FORE Systems 200E-series firmware magic
 fore200e_pca_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_PCA_FW)) \
          fore200e_mkfirm
        ./fore200e_mkfirm -k -b _fore200e_pca_fw \
          -i $(CONFIG_ATM_FORE200E_PCA_FW) -o $@
+       @ ( \
+         echo 'ifeq ($(strip $(CONFIG_ATM_FORE200E_PCA_FW)), $$(CONFIG_ATM_FORE200E_PCA_FW))'; \
+         echo 'FORE200E_FW_UP_TO_DATE += $@'; \
+         echo 'endif' \
+       ) >.$@.fw
 
 fore200e_sba_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_SBA_FW)) \
          fore200e_mkfirm
        ./fore200e_mkfirm -k -b _fore200e_sba_fw \
          -i $(CONFIG_ATM_FORE200E_SBA_FW) -o $@
+       @ ( \
+         echo 'ifeq ($(strip $(CONFIG_ATM_FORE200E_SBA_FW)), $$(CONFIG_ATM_FORE200E_SBA_FW))'; \
+         echo 'FORE200E_FW_UP_TO_DATE += $@'; \
+         echo 'endif' \
+       ) >.$@.fw
 
 fore200e_mkfirm: fore200e_mkfirm.c
        $(HOSTCC) $(HOSTCFLAGS) $< -o $@
 
-# deal with the various suffixes of the firmware images
-%.bin:  %.data
-       objcopy -Iihex $< -Obinary $@.gz
-       gzip -df $@.gz
-
-%.bin1: %.data
-       objcopy -Iihex $< -Obinary $@.gz
-       gzip -df $@.gz
-
-%.bin2: %.data
+# deal with the various suffixes of the binary firmware images
+%.bin %.bin1 %.bin2: %.data
        objcopy -Iihex $< -Obinary $@.gz
        gzip -df $@.gz
 
 # module build
 fore_200e.o: fore200e.o $(FORE200E_FW_OBJS)
        $(LD) -r -o $@ $< $(FORE200E_FW_OBJS)
+
+# firmware dependency stuff taken from drivers/sound/Makefile
+FORE200E_FW_UP_TO_DATE :=
+
+FORE200E_FW_FILES := $(wildcard .fore200e_*.fw)
+ifneq ($(FORE200E_FW_FILES),)
+include $(FORE200E_FW_FILES)
+endif
+
+FORE200E_FW_CHANGED := $(filter-out $(FORE200E_FW_UP_TO_DATE), \
+                       fore200e_pca_fw.c fore200e_sba_fw.c)
+
+ifneq ($(FORE200E_FW_CHANGED),)
+$(FORE200E_FW_CHANGED): dummy
+endif
index a71884db7d8921b71af0078b62a437381af11831..151704c95f2075ddde4f3145636a87cf9b0387c2 100644 (file)
@@ -1251,10 +1251,15 @@ static int amb_open (struct atm_vcc * atm_vcc, short vpi, int vci) {
     }
   }
   
+  // prevent module unload while sleeping (kmalloc/down)
+  // doing this any earlier would complicate more error return paths
+  MOD_INC_USE_COUNT;
+  
   // get space for our vcc stuff
   vcc = kmalloc (sizeof(amb_vcc), GFP_KERNEL);
   if (!vcc) {
     PRINTK (KERN_ERR, "out of memory!");
+    MOD_DEC_USE_COUNT;
     return -ENOMEM;
   }
   atm_vcc->dev_data = (void *) vcc;
@@ -1340,7 +1345,6 @@ static int amb_open (struct atm_vcc * atm_vcc, short vpi, int vci) {
   // indicate readiness
   set_bit(ATM_VF_READY,&atm_vcc->flags);
   
-  MOD_INC_USE_COUNT;
   return 0;
 }
 
@@ -1420,7 +1424,9 @@ static void amb_close (struct atm_vcc * atm_vcc) {
   
   // say the VPI/VCI is free again
   clear_bit(ATM_VF_ADDR,&atm_vcc->flags);
+
   MOD_DEC_USE_COUNT;
+  return;
 }
 
 /********** Debug\17Ioctl **********/
index 11ce866dab48a0409cffd2e367f5b57f27689bbf..e8c3456e3927d4b1f545f5cc4c33afa69454fa2a 100644 (file)
@@ -631,7 +631,7 @@ struct amb_dev {
   u32              iobase;
   u32 *            membase;
 
-#if 0  
+#ifdef FILL_RX_POOLS_IN_BH
   struct tq_struct bh;
 #endif
   
index 443831a82b8aa100b6fd17e48d139f7e8ecda94b..73c785fe05faa0619a1117f55fdc918dbec34ff4 100644 (file)
@@ -1,21 +1,15 @@
 /* drivers/atm/atmdev_init.c - ATM device driver initialization */
  
-/* Written 1995-1997 by Werner Almesberger, EPFL LRC */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
  
 
 #include <linux/config.h>
 #include <linux/init.h>
 
 
-#ifdef CONFIG_ATM_ENI
-extern int eni_detect(void);
-#endif
 #ifdef CONFIG_ATM_ZATM
 extern int zatm_detect(void);
 #endif
-#ifdef CONFIG_ATM_TNETA1570
-extern int tneta1570_detect(void);
-#endif
 #ifdef CONFIG_ATM_NICSTAR
 extern int nicstar_detect(void);
 #endif
@@ -33,20 +27,20 @@ extern int fore200e_detect(void);
 #endif
 
 
+/*
+ * For historical reasons, atmdev_init returns the number of devices found.
+ * Note that some detections may not go via atmdev_init (e.g. eni.c), so this
+ * number is meaningless.
+ */
+
 int __init atmdev_init(void)
 {
        int devs;
 
        devs = 0;
-#ifdef CONFIG_ATM_ENI
-//     devs += eni_detect();
-#endif
 #ifdef CONFIG_ATM_ZATM
        devs += zatm_detect();
 #endif
-#ifdef CONFIG_ATM_TNETA1570
-       devs += tneta1570_detect();
-#endif
 #ifdef CONFIG_ATM_NICSTAR
        devs += nicstar_detect();
 #endif
index b3240d498957157d94de7b9f3aaad4cce6a9d521..df6ae2eda1858b5f180e49ecb3d81dbc1ac15e14 100644 (file)
@@ -879,14 +879,13 @@ static void close_rx(struct atm_vcc *vcc)
                        set_current_state(TASK_UNINTERRUPTIBLE);
                }
                for (;;) {
-                       unsigned long flags;
                        int at_end;
                        u32 tmp;
 
-                       spin_lock_irqsave(&eni_dev->lock,flags);
+                       tasklet_disable(&eni_dev->task);
                        tmp = readl(eni_dev->vci+vcc->vci*16+4) & MID_VCI_READ;
                        at_end = eni_vcc->rx_pos == tmp >> MID_VCI_READ_SHIFT;
-                       spin_unlock_irqrestore(&eni_dev->lock,flags);
+                       tasklet_enable(&eni_dev->task);
                        if (at_end) break;
                        EVENT("drain discard (host 0x%lx, nic 0x%lx)\n",
                            eni_vcc->rx_pos,tmp);
@@ -972,8 +971,8 @@ static inline void put_dma(int chan,u32 *dma,int *j,dma_addr_t paddr,
        }
 #ifdef CONFIG_ATM_ENI_BURST_TX_16W /* may work with some PCI chipsets ... */
        if (words & ~15) {
-               DPRINTK("put_dma: %lx DMA: %d*16/%d words\n",paddr,words >> 4,
-                   words);
+               DPRINTK("put_dma: %lx DMA: %d*16/%d words\n",
+                   (unsigned long) paddr,words >> 4,words);
                dma[(*j)++] = MID_DT_16W | ((words >> 4) << MID_DMA_COUNT_SHIFT)
                    | (chan << MID_DMA_CHAN_SHIFT);
                dma[(*j)++] = paddr;
@@ -994,8 +993,8 @@ static inline void put_dma(int chan,u32 *dma,int *j,dma_addr_t paddr,
 #endif
 #ifdef CONFIG_ATM_ENI_BURST_TX_4W /* probably useless if TX_8W or TX_16W */
        if (words & ~3) {
-               DPRINTK("put_dma: %lx DMA: %d*4/%d words\n",paddr,words >> 2,
-                   words);
+               DPRINTK("put_dma: %lx DMA: %d*4/%d words\n",
+                   (unsigned long) paddr,words >> 2,words);
                dma[(*j)++] = MID_DT_4W | ((words >> 2) << MID_DMA_COUNT_SHIFT)
                    | (chan << MID_DMA_CHAN_SHIFT);
                dma[(*j)++] = paddr;
@@ -1005,8 +1004,8 @@ static inline void put_dma(int chan,u32 *dma,int *j,dma_addr_t paddr,
 #endif
 #ifdef CONFIG_ATM_ENI_BURST_TX_2W /* probably useless if TX_4W, TX_8W, ... */
        if (words & ~1) {
-               DPRINTK("put_dma: %lx DMA: %d*2/%d words\n",paddr,words >> 1,
-                   words);
+               DPRINTK("put_dma: %lx DMA: %d*2/%d words\n",
+                   (unsigned long) paddr,words >> 1,words);
                dma[(*j)++] = MID_DT_2W | ((words >> 1) << MID_DMA_COUNT_SHIFT)
                    | (chan << MID_DMA_CHAN_SHIFT);
                dma[(*j)++] = paddr;
@@ -1188,7 +1187,7 @@ static void poll_tx(struct atm_dev *dev)
                if (tx->send)
                        while ((skb = skb_dequeue(&tx->backlog))) {
                                res = do_tx(skb);
-                               if (res == enq_ok) tx->backlog_len--;
+                               if (res == enq_ok) atomic_dec(&tx->backlog_len);
                                else {
                                        DPRINTK("re-queuing TX PDU\n");
                                        skb_queue_head(&tx->backlog,skb);
@@ -1327,7 +1326,7 @@ static int reserve_or_set_tx(struct atm_vcc *vcc,struct atm_trafprm *txtp,
                tx->send = mem;
                tx->words = size >> 2;
                skb_queue_head_init(&tx->backlog);
-               tx->backlog_len = 0;
+               atomic_set(&tx->backlog_len,0);
                for (order = 0; size > (1 << (order+10)); order++);
                eni_out((order << MID_SIZE_SHIFT) |
                    ((tx->send-eni_dev->ram) >> (MID_LOC_SKIP+2)),
@@ -1399,12 +1398,11 @@ static void close_tx(struct atm_vcc *vcc)
        add_wait_queue(&eni_dev->tx_wait,&wait);
        set_current_state(TASK_UNINTERRUPTIBLE);
        for (;;) {
-               unsigned long flags;
                int txing;
 
-               spin_lock_irqsave(&eni_dev->lock,flags);
+               tasklet_disable(&eni_dev->task);
                txing = skb_peek(&eni_vcc->tx->backlog) || eni_vcc->txing;
-               spin_unlock_irqrestore(&eni_dev->lock,flags);
+               tasklet_enable(&eni_dev->task);
                if (!txing) break;
                DPRINTK("%d TX left\n",eni_vcc->txing);
                schedule();
@@ -1468,44 +1466,24 @@ if (eni_boards) printk(KERN_INFO "loss: %ld\n",ENI_DEV(eni_boards)->lost);
 #endif
 
 
-static void misc_int(struct atm_dev *dev,unsigned long reason)
+static void bug_int(struct atm_dev *dev,unsigned long reason)
 {
        struct eni_dev *eni_dev;
 
-       DPRINTK(">misc_int\n");
+       DPRINTK(">bug_int\n");
        eni_dev = ENI_DEV(dev);
-       if (reason & MID_STAT_OVFL) {
-               EVENT("stat overflow\n",0,0);
-               eni_dev->lost += eni_in(MID_STAT) & MID_OVFL_TRASH;
-       }
-       if (reason & MID_SUNI_INT) {
-               EVENT("SUNI int\n",0,0);
-               dev->phy->interrupt(dev);
-#if 0
-               foo();
-#endif
-       }
-       if (reason & MID_DMA_ERR_ACK) {
+       if (reason & MID_DMA_ERR_ACK)
                printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "
                    "error\n",dev->number);
-               EVENT("---dump ends here---\n",0,0);
-               printk(KERN_NOTICE "---recent events---\n");
-               event_dump();
-       }
-       if (reason & MID_TX_IDENT_MISM) {
+       if (reason & MID_TX_IDENT_MISM)
                printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - ident "
                    "mismatch\n",dev->number);
-               EVENT("---dump ends here---\n",0,0);
-               printk(KERN_NOTICE "---recent events---\n");
-               event_dump();
-       }
-       if (reason & MID_TX_DMA_OVFL) {
+       if (reason & MID_TX_DMA_OVFL)
                printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "
                    "overflow\n",dev->number);
-               EVENT("---dump ends here---\n",0,0);
-               printk(KERN_NOTICE "---recent events---\n");
-               event_dump();
-       }
+       EVENT("---dump ends here---\n",0,0);
+       printk(KERN_NOTICE "---recent events---\n");
+       event_dump();
 }
 
 
@@ -1513,54 +1491,78 @@ static void eni_int(int irq,void *dev_id,struct pt_regs *regs)
 {
        struct atm_dev *dev;
        struct eni_dev *eni_dev;
-       unsigned long reason;
+       u32 reason;
 
        DPRINTK(">eni_int\n");
        dev = dev_id;
        eni_dev = ENI_DEV(dev);
-       while ((reason = eni_in(MID_ISA))) {
-               DPRINTK(DEV_LABEL ": int 0x%lx\n",reason);
-               if (reason & MID_RX_DMA_COMPLETE) {
-                       EVENT("INT: RX DMA complete, starting dequeue_rx\n",
-                           0,0);
-                       spin_lock(&eni_dev->lock);
-                       dequeue_rx(dev);
-                       EVENT("dequeue_rx done, starting poll_rx\n",0,0);
-                       poll_rx(dev);
-                       spin_unlock(&eni_dev->lock);
-                       EVENT("poll_rx done\n",0,0);
-                       /* poll_tx ? */
-               }
-               if (reason & MID_SERVICE) {
-                       EVENT("INT: service, starting get_service\n",0,0);
-                       spin_lock(&eni_dev->lock);
-                       get_service(dev);
-                       EVENT("get_service done, starting poll_rx\n",0,0);
-                       poll_rx(dev);
-                       spin_unlock(&eni_dev->lock);
-                       EVENT("poll_rx done\n",0,0);
-               }
-               if (reason & MID_TX_DMA_COMPLETE) {
-                       EVENT("INT: TX DMA COMPLETE\n",0,0);
-                       spin_lock(&eni_dev->lock);
-                       dequeue_tx(dev);
-                       spin_unlock(&eni_dev->lock);
-               }
-               if (reason & MID_TX_COMPLETE) {
-                       EVENT("INT: TX COMPLETE\n",0,0);
+       reason = eni_in(MID_ISA);
+       DPRINTK(DEV_LABEL ": int 0x%lx\n",(unsigned long) reason);
+       /*
+        * Must handle these two right now, because reading ISA doesn't clear
+        * them, so they re-occur and we never make it to the tasklet. Since
+        * they're rare, we don't mind the occasional invocation of eni_tasklet
+        * with eni_dev->events == 0.
+        */
+       if (reason & MID_STAT_OVFL) {
+               EVENT("stat overflow\n",0,0);
+               eni_dev->lost += eni_in(MID_STAT) & MID_OVFL_TRASH;
+       }
+       if (reason & MID_SUNI_INT) {
+               EVENT("SUNI int\n",0,0);
+               dev->phy->interrupt(dev);
+#if 0
+               foo();
+#endif
+       }
+       spin_lock(&eni_dev->lock);
+       eni_dev->events |= reason;
+       spin_unlock(&eni_dev->lock);
+       tasklet_schedule(&eni_dev->task);
+}
+
+
+static void eni_tasklet(unsigned long data)
+{
+       struct atm_dev *dev = (struct atm_dev *) data;
+       struct eni_dev *eni_dev = ENI_DEV(dev);
+       unsigned long flags;
+       u32 events;
+
+       DPRINTK("eni_tasklet (dev %p)\n",dev);
+       spin_lock_irqsave(&eni_dev->lock,flags);
+       events = xchg(&eni_dev->events,0);
+       spin_unlock_irqrestore(&eni_dev->lock,flags);
+       if (events & MID_RX_DMA_COMPLETE) {
+               EVENT("INT: RX DMA complete, starting dequeue_rx\n",0,0);
+               dequeue_rx(dev);
+               EVENT("dequeue_rx done, starting poll_rx\n",0,0);
+               poll_rx(dev);
+               EVENT("poll_rx done\n",0,0);
+               /* poll_tx ? */
+       }
+       if (events & MID_SERVICE) {
+               EVENT("INT: service, starting get_service\n",0,0);
+               get_service(dev);
+               EVENT("get_service done, starting poll_rx\n",0,0);
+               poll_rx(dev);
+               EVENT("poll_rx done\n",0,0);
+       }
+       if (events & MID_TX_DMA_COMPLETE) {
+               EVENT("INT: TX DMA COMPLETE\n",0,0);
+               dequeue_tx(dev);
+       }
+       if (events & MID_TX_COMPLETE) {
+               EVENT("INT: TX COMPLETE\n",0,0);
 tx_complete++;
-                       spin_lock(&eni_dev->lock);
-                       poll_tx(dev);
-                       spin_unlock(&eni_dev->lock);
-                       wake_up(&eni_dev->tx_wait);
-                       /* poll_rx ? */
-               }
-               if (reason & (MID_STAT_OVFL | MID_SUNI_INT | MID_DMA_ERR_ACK |
-                   MID_TX_IDENT_MISM | MID_TX_DMA_OVFL)) {
-                       EVENT("misc interrupt\n",0,0);
-                       misc_int(dev,reason);
-               }
+               wake_up(&eni_dev->tx_wait);
+               /* poll_rx ? */
+       }
+       if (events & (MID_DMA_ERR_ACK | MID_TX_IDENT_MISM | MID_TX_DMA_OVFL)) {
+               EVENT("bug interrupt\n",0,0);
+               bug_int(dev,events);
        }
+       poll_tx(dev);
 }
 
 
@@ -1824,6 +1826,8 @@ static int __devinit eni_start(struct atm_dev *dev)
             eni_dev->vci,eni_dev->rx_dma,eni_dev->tx_dma,
             eni_dev->service,buf);
        spin_lock_init(&eni_dev->lock);
+       tasklet_init(&eni_dev->task,eni_tasklet,(unsigned long) dev);
+       eni_dev->events = 0;
        /* initialize memory management */
        buffer_mem = eni_dev->mem-(buf-eni_dev->ram);
        eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
@@ -1969,7 +1973,6 @@ static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs)
        struct eni_dev *eni_dev = ENI_DEV(vcc->dev);
        struct eni_tx *tx = ENI_VCC(vcc)->tx;
        struct sk_buff *skb;
-       unsigned long flags;
        int error,rate,rsv,shp;
 
        if (qos->txtp.traffic_class == ATM_NONE) return 0;
@@ -1989,7 +1992,7 @@ static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs)
         * Walk through the send buffer and patch the rate information in all
         * segmentation buffer descriptors of this VCC.
         */
-       spin_lock_irqsave(&eni_dev->lock,flags);
+       tasklet_disable(&eni_dev->task);
        for (skb = eni_dev->tx_queue.next; skb !=
            (struct sk_buff *) &eni_dev->tx_queue; skb = skb->next) {
                unsigned long dsc;
@@ -2000,7 +2003,7 @@ static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs)
                    (tx->prescaler << MID_SEG_PR_SHIFT) |
                    (tx->resolution << MID_SEG_RATE_SHIFT), dsc);
        }
-       spin_unlock_irqrestore(&eni_dev->lock,flags);
+       tasklet_enable(&eni_dev->task);
        return 0;
 }
 
@@ -2061,8 +2064,6 @@ static int eni_setsockopt(struct atm_vcc *vcc,int level,int optname,
 
 static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb)
 {
-       unsigned long flags;
-
        DPRINTK(">eni_send\n");
        if (!ENI_VCC(vcc)->tx) {
                if (vcc->pop) vcc->pop(vcc,skb);
@@ -2084,13 +2085,10 @@ static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb)
        }
 submitted++;
        ATM_SKB(skb)->vcc = vcc;
-       spin_lock_irqsave(&ENI_DEV(vcc->dev)->lock,flags); /* brute force */
-       if (skb_peek(&ENI_VCC(vcc)->tx->backlog) || do_tx(skb)) {
-               skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb);
-               ENI_VCC(vcc)->tx->backlog_len++;
+       skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb);
+       atomic_inc(&ENI_VCC(vcc)->tx->backlog_len);
 backlogged++;
-       }
-       spin_unlock_irqrestore(&ENI_DEV(vcc->dev)->lock,flags);
+       tasklet_schedule(&ENI_DEV(vcc->dev)->task);
        return 0;
 }
 
@@ -2189,7 +2187,7 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
                }
                if (--left) continue;
                return sprintf(page,"%10sbacklog %d bytes\n","",
-                   tx->backlog_len);
+                   atomic_read(&tx->backlog_len));
        }
        for (vcc = dev->vccs; vcc; vcc = vcc->next) {
                struct eni_vcc *eni_vcc = ENI_VCC(vcc);
index 23ba60fb1e9e1bb8aeb8d0e26c72de6b88dd42a0..12a3e196c5f7520b41d2f34f4403eb71bb4a0cbc 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/time.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
+#include <asm/atomic.h>
 
 #include "midway.h"
 
@@ -46,7 +47,7 @@ struct eni_tx {
        int reserved;                   /* reserved peak cell rate */
        int shaping;                    /* shaped peak cell rate */
        struct sk_buff_head backlog;    /* queue of waiting TX buffers */
-       int backlog_len;                /* length of backlog in bytes */
+       atomic_t backlog_len;           /* length of backlog in bytes */
 };
 
 struct eni_vcc {
@@ -68,6 +69,8 @@ struct eni_vcc {
 struct eni_dev {
        /*-------------------------------- spinlock */
        spinlock_t lock;                /* sync with interrupt */
+       struct tasklet_struct task;     /* tasklet for interrupt work */
+       u32 events;                     /* pending events */
        /*-------------------------------- base pointers into Midway address
                                           space */
        unsigned long phy;              /* PHY interface chip registers */
index 1fec6e0062c74546ad0e27802093333e8addb8d1..d9d5a66c548b053f261cb529cee9e77408941a64 100644 (file)
@@ -1,8 +1,8 @@
 /*
-  $Id: fore200e.c,v 1.2 2000/03/21 21:19:24 davem Exp $
+  $Id: fore200e.c,v 1.5 2000/04/14 10:10:34 davem Exp $
 
   A FORE Systems 200E-series driver for ATM on Linux.
-  Christophe Lizzi (lizzi@cnam.fr), October 1999-February 2000.
+  Christophe Lizzi (lizzi@cnam.fr), October 1999-March 2000.
 
   Based on the PCA-200E driver from Uwe Dannowski (Uwe.Dannowski@inf.tu-dresden.de).
 
 #include <linux/init.h>
 #include <linux/capability.h>
 #include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
 #include <linux/atmdev.h>
 #include <linux/sonet.h>
 #include <linux/atm_suni.h>
-#include <linux/bitops.h>
 #include <asm/io.h>
 #include <asm/string.h>
 #include <asm/segment.h>
@@ -66,7 +67,7 @@
 #define FORE200E_52BYTE_AAL0_SDU
 #endif
 
-#define FORE200E_VERSION "0.2b"
+#define FORE200E_VERSION "0.2d"
 
 
 #define FORE200E         "fore200e: "
@@ -444,6 +445,7 @@ fore200e_shutdown(struct fore200e* fore200e)
 }
 
 
+
 #ifdef CONFIG_ATM_FORE200E_PCA
 
 static u32 fore200e_pca_read(volatile u32* addr)
@@ -477,7 +479,8 @@ fore200e_pca_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int d
 static void
 fore200e_pca_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction)
 {
-    DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction);
+    DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d\n",
+           dma_addr, size, direction);
 
     pci_unmap_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size, direction);
 }
@@ -496,7 +499,8 @@ fore200e_pca_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size, int dir
    (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */
 
 static int
-fore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int nbr, int alignment)
+fore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk,
+                            int size, int nbr, int alignment)
 {
 #if defined(__sparc_v9__)
     /* returned chunks are page-aligned */
@@ -659,6 +663,7 @@ fore200e_pca_detect(const struct fore200e_bus* bus, int index)
 
     sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);
 
+    pci_enable_device(pci_dev);
     pci_set_master(pci_dev);
 
     return fore200e;
@@ -756,7 +761,8 @@ fore200e_sba_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int d
 static void
 fore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction)
 {
-    DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", dma_addr, size, direction);
+    DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n",
+           dma_addr, size, direction);
 
     sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction);
 }
@@ -775,7 +781,8 @@ fore200e_sba_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size, int dir
    (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */
 
 static int
-fore200e_sba_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int nbr, int alignment)
+fore200e_sba_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk,
+                            int size, int nbr, int alignment)
 {
     chunk->alloc_size = chunk->align_size = size * nbr;
 
@@ -1234,15 +1241,25 @@ fore200e_interrupt(int irq, void* dev, struct pt_regs* regs)
     }
     DPRINTK(3, "valid interrupt on device %c\n", fore200e->name[9]);
 
-    fore200e_irq_rx(fore200e);
+    tasklet_schedule(&fore200e->tasklet);
+    
+    fore200e->bus->irq_ack(fore200e);
+}
+
+
+static void
+fore200e_tasklet(unsigned long data)
+{
+    struct fore200e* fore200e = (struct fore200e*) data;
 
+    fore200e_irq_rx(fore200e);
+    
     if (fore200e->host_txq.txing)
        fore200e_irq_tx(fore200e);
-    
-    fore200e->bus->irq_ack(fore200e);
 }
 
 
+
 static int
 fore200e_select_scheme(struct atm_vcc* vcc)
 {
@@ -1400,7 +1417,7 @@ fore200e_open(struct atm_vcc *vcc, short vpi, int vci)
     if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC)
        return 0;
 
-    set_bit(ATM_VF_ADDR,&vcc->flags);
+    set_bit(ATM_VF_ADDR, &vcc->flags);
     vcc->itf    = vcc->dev->number;
 
     DPRINTK(2, "opening %d.%d.%d:%d QoS = (tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "
@@ -1463,7 +1480,7 @@ fore200e_open(struct atm_vcc *vcc, short vpi, int vci)
     fore200e_vcc->tx_min_pdu = fore200e_vcc->rx_min_pdu = 65536;
     fore200e_vcc->tx_max_pdu = fore200e_vcc->rx_max_pdu = 0;
     
-    clear_bit(ATM_VF_READY,&vcc->flags);
+    set_bit(ATM_VF_READY, &vcc->flags);
     return 0;
 }
 
@@ -1489,6 +1506,8 @@ fore200e_close(struct atm_vcc* vcc)
        fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
        up(&fore200e->rate_sf);
     }
+
+    clear_bit(ATM_VF_READY, &vcc->flags);
 }
 
 
@@ -1506,7 +1525,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
     struct host_txq_entry* entry;
     struct tpd*            tpd;
     struct tpd_haddr       tpd_haddr;
-    unsigned long          flags;
+    //unsigned long          flags;
     int                    retry        = CONFIG_ATM_FORE200E_TX_RETRY;
     int                    tx_copy      = 0;
     int                    tx_len       = skb->len;
@@ -1531,7 +1550,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
     
   retry_here:
     
-    spin_lock_irqsave(&fore200e->tx_lock, flags);
+    tasklet_disable(&fore200e->tasklet);
 
     entry = &txq->host_entry[ txq->head ];
     
@@ -1542,7 +1561,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
        
        if (*entry->status != STATUS_FREE) {
            
-           spin_unlock_irqrestore(&fore200e->tx_lock, flags);
+           tasklet_enable(&fore200e->tasklet);
 
            /* retry once again? */
            if(--retry > 0)
@@ -1582,7 +1601,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
        entry->data = kmalloc(tx_len, GFP_ATOMIC | GFP_DMA);
        if (entry->data == NULL) {
            
-           spin_unlock_irqrestore(&fore200e->tx_lock, flags);
+           tasklet_enable(&fore200e->tasklet);
            if (vcc->pop)
                vcc->pop(vcc, skb);
            else
@@ -1606,10 +1625,10 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
     FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX);
     txq->txing++;
 
-    spin_unlock_irqrestore(&fore200e->tx_lock, flags);
-    
+    tasklet_enable(&fore200e->tasklet);
+
     /* ensure DMA synchronisation */
-       fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length, FORE200E_DMA_TODEVICE);
+    fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length, FORE200E_DMA_TODEVICE);
     
     DPRINTK(3, "tx on %d.%d.%d:%d, len = %u (%u)\n", 
            vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
@@ -1934,8 +1953,7 @@ fore200e_ioctl(struct atm_dev* dev, unsigned int cmd, void* arg)
        return put_user(fore200e->loop_mode, (int*)arg) ? -EFAULT : 0;
 
     case ATM_QUERYLOOP:
-       return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, (int*)arg) ?
-           -EFAULT : 0;
+       return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, (int*)arg) ? -EFAULT : 0;
     }
 
     return -ENOSYS; /* not implemented */
@@ -1976,7 +1994,7 @@ fore200e_change_qos(struct atm_vcc* vcc,struct atm_qos* qos, int flags)
        /* update rate control parameters */
        fore200e_rate_ctrl(qos, &fore200e_vcc->rate);
 
-       set_bit(ATM_VF_HASQOS,&vcc->flags);
+       set_bit(ATM_VF_HASQOS, &vcc->flags);
        return 0;
     }
     
@@ -1997,6 +2015,8 @@ fore200e_irq_request(struct fore200e* fore200e)
     printk(FORE200E "IRQ %s reserved for device %s\n",
           fore200e_irq_itoa(fore200e->irq), fore200e->name);
 
+    tasklet_init(&fore200e->tasklet, fore200e_tasklet, (unsigned long)fore200e);
+
     fore200e->state = FORE200E_STATE_IRQ;
     return 0;
 }
@@ -2338,7 +2358,6 @@ fore200e_initialize(struct fore200e* fore200e)
 
     DPRINTK(2, "device %s being initialized\n", fore200e->name);
 
-    spin_lock_init(&fore200e->tx_lock);
     init_MUTEX(&fore200e->rate_sf);
     
     cpq = fore200e->cp_queues = (struct cp_queues*) (fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET);
@@ -2714,7 +2733,7 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page)
        if (media_index < 0 || media_index > 4)
            media_index = 5;
        
-       switch(fore200e->loop_mode) {
+       switch (fore200e->loop_mode) {
            case ATM_LM_NONE:    oc3_index = 0;
                                 break;
            case ATM_LM_LOC_PHY: oc3_index = 1;
@@ -2900,21 +2919,24 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page)
 
 
 #ifdef MODULE
-unsigned int
-init_module(void)
+static unsigned int __init
+fore200e_module_init(void)
 {
     DPRINTK(1, "module loaded\n");
     return fore200e_detect() == 0;
 }
 
-void
-cleanup_module(void)
+static void __exit
+fore200e_module_cleanup(void)
 {
     while (fore200e_boards) {
        fore200e_cleanup(&fore200e_boards);
     }
     DPRINTK(1, "module being removed\n");
 }
+
+module_init(fore200e_module_init);
+module_exit(fore200e_module_cleanup);
 #endif
 
 
index f29fbde973447c58c85c72d2b9d6cfffccbc8f91..e56afd2b6462f180567761ef4fc5792a9e78daf9 100644 (file)
@@ -1,3 +1,4 @@
+/* $Id: fore200e.h,v 1.4 2000/04/14 10:10:34 davem Exp $ */
 #ifndef _FORE200E_H
 #define _FORE200E_H
 
@@ -827,14 +828,18 @@ typedef struct fore200e_bus {
 #    else
        /* in that case, we'll need to add an extra indirection, e.g.
          fore200e->bus->dma_direction[ fore200e_dma_direction ] */
-#      error PCI and SBUS DMA direction flags differ!
+#      error PCI and SBUS DMA direction flags have different values!
 #    endif
 #  else
-#    define FORE200E_DMA_BIDIRECTIONAL SBA_DMA_BIDIRECTIONAL
-#    define FORE200E_DMA_TODEVICE      SBA_DMA_TODEVICE
-#    define FORE200E_DMA_FROMDEVICE    SBA_DMA_FROMDEVICE
+#    define FORE200E_DMA_BIDIRECTIONAL SBUS_DMA_BIDIRECTIONAL
+#    define FORE200E_DMA_TODEVICE      SBUS_DMA_TODEVICE
+#    define FORE200E_DMA_FROMDEVICE    SBUS_DMA_FROMDEVICE
 #  endif
 #else
+#  ifndef CONFIG_ATM_FORE200E_PCA
+#    warning compiling the fore200e driver without any hardware support enabled!
+#    include <linux/pci.h>
+#  endif
 #  define FORE200E_DMA_BIDIRECTIONAL PCI_DMA_BIDIRECTIONAL
 #  define FORE200E_DMA_TODEVICE      PCI_DMA_TODEVICE
 #  define FORE200E_DMA_FROMDEVICE    PCI_DMA_FROMDEVICE
@@ -874,7 +879,7 @@ typedef struct fore200e {
     struct stats*              stats;                  /* last snapshot of the stats         */
     
     struct semaphore           rate_sf;                /* protects rate reservation ops      */
-    spinlock_t                 tx_lock;                /* protects tx ops                    */
+    struct tasklet_struct      tasklet;                /* performs interrupt work            */
 
 } fore200e_t;
 
index f0dff701117bfb72e1dc586c5b7a15a7f87d4778..f39845f853bfeb8141b70a1c1bf03b89103b7a09 100644 (file)
@@ -2490,10 +2490,15 @@ static int hrz_open (struct atm_vcc * atm_vcc, short vpi, int vci) {
     return -EINVAL;
   }
   
+  // prevent module unload while sleeping (kmalloc)
+  // doing this any earlier would complicate more error return paths
+  MOD_INC_USE_COUNT;
+  
   // get space for our vcc stuff and copy parameters into it
   vccp = kmalloc (sizeof(hrz_vcc), GFP_KERNEL);
   if (!vccp) {
     PRINTK (KERN_ERR, "out of memory!");
+    MOD_DEC_USE_COUNT;
     return -ENOMEM;
   }
   *vccp = vcc;
@@ -2525,6 +2530,7 @@ static int hrz_open (struct atm_vcc * atm_vcc, short vpi, int vci) {
   if (error) {
     PRINTD (DBG_QOS|DBG_VCC, "insufficient cell rate resources");
     kfree (vccp);
+    MOD_DEC_USE_COUNT;
     return error;
   }
   
@@ -2537,11 +2543,13 @@ static int hrz_open (struct atm_vcc * atm_vcc, short vpi, int vci) {
   if (rxtp->traffic_class != ATM_NONE) {
     if (dev->rxer[channel]) {
       PRINTD (DBG_ERR|DBG_VCC, "VC already open for RX");
-      return -EBUSY;
+      error = -EBUSY;
     }
-    error = hrz_open_rx (dev, channel);
+    if (!error)
+      error = hrz_open_rx (dev, channel);
     if (error) {
       kfree (vccp);
+      MOD_DEC_USE_COUNT;
       return error;
     }
     // this link allows RX frames through
@@ -2556,7 +2564,6 @@ static int hrz_open (struct atm_vcc * atm_vcc, short vpi, int vci) {
   // indicate readiness
   set_bit(ATM_VF_READY,&atm_vcc->flags);
   
-  MOD_INC_USE_COUNT;
   return 0;
 }
 
index 7c5f5757935dc0e7b92d7caa9825cdc0c1b16c24..8f06133342943c8b7adcdb57128c42f0782f76a7 100644 (file)
@@ -141,7 +141,7 @@ static int uPD98402_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
                        return fetch_stats(dev,(struct sonet_stats *) arg,
                            cmd == SONET_GETSTATZ);
                case SONET_SETFRAMING:
-                       return set_framing(dev,(int) arg);
+                       return set_framing(dev,(int) (long) arg);
                case SONET_GETFRAMING:
                        return put_user(PRIV(dev)->framing,(int *) arg) ?
                            -EFAULT : 0;
index c66efc8c7f96a093f3eeee0995ea5036e1a91e4b..3ad5841a3425246017d4d2f72384f3601b1daa35 100644 (file)
@@ -465,10 +465,8 @@ int cdrom_open(struct inode *ip, struct file *fp)
        if ((cdi = cdrom_find_device(dev)) == NULL)
                return -ENODEV;
 
-       /* just CD-RW for now. DVD-RW will come soon, CD-R and DVD-R
-        * need to be handled differently. */
-       if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_CD_RW))
-                       return -EROFS;
+       if (fp->f_mode & FMODE_WRITE)
+               return -EROFS;
 
        /* if this was a O_NONBLOCK open and we should honor the flags,
         * do a quick open without drive/disc integrity checks. */
@@ -1648,7 +1646,7 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
                if (tracks.data > 0) return CDS_DATA_1;
                /* Policy mode off */
 
-               cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognise!\n");
+               cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognize!\n");
                return CDS_NO_INFO;
                }
 
@@ -2529,33 +2527,31 @@ static void cdrom_sysctl_register(void)
 
        initialized = 1;
 }
-#endif /* endif CONFIG_SYSCTL */
 
-
-#ifdef MODULE
 static void cdrom_sysctl_unregister(void)
 {
-#ifdef CONFIG_SYSCTL
        unregister_sysctl_table(cdrom_sysctl_header);
-#endif
 }
 
-int init_module(void)
+#endif /* CONFIG_SYSCTL */
+
+static int cdrom_init(void)
 {
 #ifdef CONFIG_SYSCTL
        cdrom_sysctl_register();
 #endif
-       devfs_handle = devfs_mk_dir (NULL, "cdroms", 6, NULL);
+       devfs_handle = devfs_mk_dir(NULL, "cdroms", 6, NULL);
        return 0;
 }
 
-void cleanup_module(void)
+static void cdrom_exit(void)
 {
        printk(KERN_INFO "Uniform CD-ROM driver unloaded\n");
 #ifdef CONFIG_SYSCTL
        cdrom_sysctl_unregister();
-#endif /* CONFIG_SYSCTL */
-       devfs_unregister (devfs_handle);
+#endif
+       devfs_unregister(devfs_handle);
 }
-#endif /* endif MODULE */
 
+module_init(cdrom_init);
+module_exit(cdrom_exit);
index 1b85830345ee95a25c82fa4115e7ce759cbd0331..a5c94927a4ebef13a100665e1a99df0d77ba0f2a 100644 (file)
  *
  * Revision history:
  * $Log: sx.c,v $
- * Revision 1.32  2000/03/07 90:00:00  wolff,pvdl
+ * Revision 1.33  2000/03/09 10:00:00  pvdl,wolff
+ * - Fixed module and port counting
+ * - Fixed signal handling
+ * - Fixed an Ooops
+ * 
+ * Revision 1.32  2000/03/07 09:00:00  wolff,pvdl
  * - Fixed some sx_dprintk typos
  * - added detection for an invalid board/module configuration
  *
  * */
 
 
-#define RCS_ID "$Id: sx.c,v 1.32 2000/03/07 17:01:02 wolff, pvdl Exp $"
-#define RCS_REV "$Revision: 1.32 $"
+#define RCS_ID "$Id: sx.c,v 1.33 2000/03/08 10:01:02 wolff, pvdl Exp $"
+#define RCS_REV "$Revision: 1.33 $"
 
 
 #include <linux/module.h>
 
 #include "sxboards.h"
 #include "sxwindow.h"
-#include <linux/generic_serial.h>
+
 #include <linux/compatmac.h>
+#include <linux/generic_serial.h>
 #include "sx.h"
 
 
    if you want more than 4 boards.  */
 
 
-
 /* Why the hell am I defining these here? */
 #define SX_TYPE_NORMAL 1
 #define SX_TYPE_CALLOUT 2
 
+
 #ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
 #define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
 #endif
@@ -767,6 +773,7 @@ static void sx_setsignals (struct sx_port *port, int dtr, int rts)
        if (rts >= 0) t = rts? (t | OP_RTS): (t & ~OP_RTS);
        sx_write_channel_byte (port, hi_op, t);
        sx_dprintk (SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
+
        func_exit ();
 }
 
@@ -882,6 +889,9 @@ static int sx_set_real_termios (void *ptr)
 
        func_enter2();
 
+       if (!port->gs.tty)
+               return 0;
+
        /* What is this doing here? -- REW
           Ha! figured it out. It is to allow you to get DTR active again
           if you've dropped it with stty 0. Moved to set_baud, where it
@@ -1043,7 +1053,7 @@ void sx_transmit_chars (struct sx_port *port)
                sx_disable_tx_interrupts (port);
        }
 
-       if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
+       if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
                if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
                    port->gs.tty->ldisc.write_wakeup)
                        (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
@@ -1294,6 +1304,8 @@ static void sx_pollfunc (unsigned long data)
 
        sx_interrupt (0, board, NULL);
 
+       init_timer(&board->timer);
+
        board->timer.expires = jiffies + sx_poll;
        add_timer (&board->timer);
        func_exit ();
@@ -1389,7 +1401,7 @@ static void sx_shutdown_port (void * ptr)
        func_enter();
 
        port->gs.flags &= ~ GS_ACTIVE;
-       if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {
+       if (port->gs.tty && (port->gs.tty->termios->c_cflag & HUPCL)) {
                sx_setsignals (port, 0, 0);
                sx_reconfigure_port(port);
        }
@@ -1452,6 +1464,8 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
 
        tty->driver_data = port;
        port->gs.tty = tty;
+       if (!port->gs.count)
+               MOD_INC_USE_COUNT;
        port->gs.count++;
 
        sx_dprintk (SX_DEBUG_OPEN, "starting port\n");
@@ -1463,19 +1477,13 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
        sx_dprintk (SX_DEBUG_OPEN, "done gs_init\n");
        if (retval) {
                port->gs.count--;
+               if (port->gs.count) MOD_DEC_USE_COUNT;
                return retval;
        }
 
        port->gs.flags |= GS_ACTIVE;
        sx_setsignals (port, 1,1);
 
-       sx_dprintk (SX_DEBUG_OPEN, "before inc_use_count (count=%d.\n", 
-                   port->gs.count);
-       if (port->gs.count == 1) {
-               MOD_INC_USE_COUNT;
-       }
-       sx_dprintk (SX_DEBUG_OPEN, "after inc_use_count\n");
-
 #if 0
        if (sx_debug & SX_DEBUG_OPEN)
                my_hd ((unsigned char *)port, sizeof (*port));
@@ -1487,8 +1495,8 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
 
        if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
                printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
-               MOD_DEC_USE_COUNT;
                port->gs.count--;
+               if (!port->gs.count) MOD_DEC_USE_COUNT;
                return -EIO;
        }
 
@@ -1497,8 +1505,10 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
                    retval, port->gs.count);
 
        if (retval) {
-               MOD_DEC_USE_COUNT;
-               port->gs.count--;
+               /* 
+                * Don't lower gs.count here because sx_close() will be called later
+                */ 
+
                return retval;
        }
        /* tty->low_latency = 1; */
@@ -1530,7 +1540,21 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
    exit minicom.  I expect an "oops".  -- REW */
 static void sx_hungup (void *ptr)
 {
+       struct sx_port *port = ptr; 
        func_enter ();
+
+       sx_setsignals (port, 0, 0);
+       sx_reconfigure_port(port);      
+       sx_send_command (port, HS_CLOSE, 0, 0);
+
+       if (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED) {
+               if (sx_send_command (port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) != 1) {
+                       printk (KERN_ERR 
+                               "sx: sent the force_close command, but card didn't react\n");
+               } else
+                       sx_dprintk (SX_DEBUG_CLOSE, "sent the force_close command.\n");
+       }
+
        MOD_DEC_USE_COUNT;
        func_exit ();
 }
@@ -1543,6 +1567,9 @@ static void sx_close (void *ptr)
        int to = 5 * HZ; 
 
        func_enter ();
+
+       sx_setsignals (port, 0, 0);
+       sx_reconfigure_port(port);      
        sx_send_command (port, HS_CLOSE, 0, 0);
 
        while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED)) {
@@ -1563,6 +1590,11 @@ static void sx_close (void *ptr)
        sx_dprintk (SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n", 
                    5 * HZ - to - 1, port->gs.count);
 
+       if(port->gs.count) {
+               sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count);
+               port->gs.count = 0;
+       }
+
        MOD_DEC_USE_COUNT;
        func_exit ();
 }
index 15e1fd52b516649aaf7cbdf7e319b9e1b943cbc1..c1390b2f8267b87092ea82e827cbb005e1b8e23b 100644 (file)
@@ -35,8 +35,8 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
            define_bool CONFIG_IDEDMA_PCI_EXPERIMENTAL $CONFIG_EXPERIMENTAL
            dep_bool '      ATA Work(s) In Progress (EXPERIMENTAL)' CONFIG_IDEDMA_PCI_WIP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
            dep_bool '      Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP
-           dep_bool '    AEC6210 chipset support' CONFIG_BLK_DEV_AEC6210 $CONFIG_BLK_DEV_IDEDMA_PCI
-           dep_mbool '      AEC6210 Tuning support (WIP)' CONFIG_AEC6210_TUNING $CONFIG_BLK_DEV_AEC6210 $CONFIG_IDEDMA_PCI_WIP
+           dep_bool '    AEC62XX chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI
+           dep_mbool '      AEC62XX Tuning support (WIP)' CONFIG_AEC62XX_TUNING $CONFIG_BLK_DEV_AEC62XX $CONFIG_IDEDMA_PCI_WIP
            dep_bool '    ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI
            dep_mbool '      ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3
            dep_bool '    AMD Viper support' CONFIG_BLK_DEV_AMD7409 $CONFIG_BLK_DEV_IDEDMA_PCI
@@ -62,6 +62,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
            dep_bool '    SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
            dep_bool '    Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI
            dep_bool '    VIA82CXXX chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI
+           dep_mbool '      VIA82CXXX Tuning support (WIP)' CONFIG_VIA82CXXX_TUNING $CONFIG_BLK_DEV_VIA82CXXX $CONFIG_IDEDMA_PCI_WIP
          fi
         if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then
            bool '    Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
@@ -122,7 +123,7 @@ else
 fi
 
 if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \
-     "$CONFIG_BLK_DEV_AEC6210" = "y" -o \
+     "$CONFIG_BLK_DEV_AEC62XX" = "y" -o \
      "$CONFIG_BLK_DEV_ALI15X3" = "y" -o \
      "$CONFIG_BLK_DEV_AMD7409" = "y" -o \
      "$CONFIG_BLK_DEV_CMD640" = "y" -o \
@@ -136,7 +137,8 @@ if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \
      "$CONFIG_BLK_DEV_PDC202XX" = "y" -o \
      "$CONFIG_BLK_DEV_PIIX" = "y" -o \
      "$CONFIG_BLK_DEV_SIS5513" = "y" -o \
-     "$CONFIG_BLK_DEV_SL82C105" = "y" ]; then
+     "$CONFIG_BLK_DEV_SL82C105" = "y" -o \
+     "$CONFIG_BLK_DEV_VIA82CXXX" = "y" ]; then
    define_bool CONFIG_BLK_DEV_IDE_MODES y
 else
    define_bool CONFIG_BLK_DEV_IDE_MODES n
index 699c48b8240776b3014522e32f23333c5412015a..278ad7ab7038a9968ebca80317b19d07e0e9c840 100644 (file)
@@ -25,8 +25,8 @@ MOD_LIST_NAME := IDE_MODULES
 LX_OBJS :=
 MX_OBJS :=
 
-ifeq ($(CONFIG_BLK_DEV_AEC6210),y)
-IDE_OBJS += aec6210.o
+ifeq ($(CONFIG_BLK_DEV_AEC62XX),y)
+IDE_OBJS += aec62xx.o
 endif
 
 ifeq ($(CONFIG_BLK_DEV_ALI14XX),y)
diff --git a/drivers/ide/aec6210.c b/drivers/ide/aec6210.c
deleted file mode 100644 (file)
index cf41fa3..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * linux/drivers/ide/aec6210.c         Version 0.06    Mar. 18, 2000
- *
- * Copyright (C) 1998-2000     Andre Hedrick (andre@suse.com)
- * May be copied or modified under the terms of the GNU General Public License
- *
- *  pio 0 ::       40: 00 07 00 00 00 00 00 00 02 07 a6 04 00 02 00 02
- *  pio 1 ::       40: 0a 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02
- *  pio 2 ::       40: 08 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02
- *  pio 3 ::       40: 03 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- *  pio 4 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- *  dma 0 ::       40: 0a 07 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- *  dma 1 ::       40: 02 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- *  dma 2 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- *                 50: ff ff ff ff 00 06 04 00 00 00 00 00 00 00 00 00
- *
- * udma 0 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- *                 50: ff ff ff ff 01 06 04 00 00 00 00 00 00 00 00 00
- *
- * udma 1 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- *                 50: ff ff ff ff 01 06 04 00 00 00 00 00 00 00 00 00
- *
- * udma 2 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- *                 50: ff ff ff ff 02 06 04 00 00 00 00 00 00 00 00 00
- *
- * auto   ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- *                 50: ff ff ff ff 02 06 04 00 00 00 00 00 00 00 00 00
- *
- * auto   ::       40: 01 04 01 04 01 04 01 04 02 05 a6 cf 00 02 00 02
- *                 50: ff ff ff ff aa 06 04 00 00 00 00 00 00 00 00 00
- *
- *                 NO-Devices
- *                 40: 00 00 00 00 00 00 00 00 02 05 a6 00 00 02 00 02
- *                 50: ff ff ff ff 00 06 00 00 00 00 00 00 00 00 00 00
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include "ide_modes.h"
-
-#define ACARD_DEBUG_DRIVE_INFO         0
-
-#undef DISPLAY_AEC6210_TIMINGS
-
-#if defined(DISPLAY_AEC6210_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static int aec6210_get_info(char *, char **, off_t, int);
-extern int (*aec6210_display_info)(char *, char **, off_t, int); /* ide-proc.c */
-extern char *ide_media_verbose(ide_drive_t *);
-static struct pci_dev *bmide_dev;
-
-static int aec6210_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-       char *p = buffer;
-
-       u32 bibma = bmide_dev->resource[4].start;
-       u8 c0 = 0, c1 = 0;
-       
-       p += sprintf(p, "\n                                AEC6210 Chipset.\n");
-
-        /*
-         * at that point bibma+0x2 et bibma+0xa are byte registers
-         * to investigate:
-         */
-       c0 = inb_p((unsigned short)bibma + 0x02);
-       c1 = inb_p((unsigned short)bibma + 0x0a);
-
-       p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
-       p += sprintf(p, "                %sabled                         %sabled\n",
-                       (c0&0x80) ? "dis" : " en",
-                       (c1&0x80) ? "dis" : " en");
-       p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
-       p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
-                       (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",
-                       (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );
-
-       p += sprintf(p, "UDMA\n");
-       p += sprintf(p, "DMA\n");
-       p += sprintf(p, "PIO\n");
-       return p-buffer;/* => must be less than 4k! */
-}
-#endif /* defined(DISPLAY_AEC6210_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-byte aec6210_proc = 0;
-
-#ifdef CONFIG_AEC6210_TUNING
-
-struct chipset_bus_clock_list_entry {
-       byte            xfer_speed;
-       unsigned short  chipset_settings;
-       byte            ultra_settings;
-};
-
-struct chipset_bus_clock_list_entry aec6210_base [] = {
-       {       XFER_UDMA_2,    0x0401, 0x02    },
-       {       XFER_UDMA_1,    0x0401, 0x01    },
-       {       XFER_UDMA_0,    0x0401, 0x01    },
-
-       {       XFER_MW_DMA_2,  0x0401, 0x00    },
-       {       XFER_MW_DMA_1,  0x0402, 0x00    },
-       {       XFER_MW_DMA_0,  0x070a, 0x00    },
-
-       {       XFER_PIO_4,     0x0401, 0x00    },
-       {       XFER_PIO_3,     0x0403, 0x00    },
-       {       XFER_PIO_2,     0x0708, 0x00    },
-       {       XFER_PIO_1,     0x070a, 0x00    },
-       {       XFER_PIO_0,     0x0700, 0x00    },
-       {       0,              0x0000, 0x00    }
-};
-
-extern char *ide_xfer_verbose (byte xfer_rate);
-
-/*
- * TO DO: active tuning and correction of cards without a bios.
- */
-
-static unsigned short pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
-{
-       for ( ; chipset_table->xfer_speed ; chipset_table++)
-               if (chipset_table->xfer_speed == speed) {
-                       return chipset_table->chipset_settings;
-               }
-       return 0x0000;
-}
-
-static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
-{
-       for ( ; chipset_table->xfer_speed ; chipset_table++)
-               if (chipset_table->xfer_speed == speed) {
-                       return chipset_table->ultra_settings;
-               }
-       return 0x00;
-}
-
-static int aec6210_tune_chipset (ide_drive_t *drive, byte speed)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-
-       int                     err;
-       byte                    drive_pci;
-       unsigned short          drive_conf = 0x0000;
-       byte                    ultra = 0x00, ultra_conf = 0x00;
-       byte                    tmp1 = 0x00, tmp2 = 0x00;
-
-       int drive_number        = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
-
-       switch(drive_number) {
-               case 0:         drive_pci = 0x40; break;
-               case 1:         drive_pci = 0x42; break;
-               case 2:         drive_pci = 0x44; break;
-               case 3:         drive_pci = 0x46; break;
-               default:        return -1;
-       }
-
-       pci_read_config_word(HWIF(drive)->pci_dev, drive_pci, &drive_conf);
-       drive_conf = pci_bus_clock_list(speed, aec6210_base);
-       pci_write_config_word(HWIF(drive)->pci_dev, drive_pci, drive_conf);
-
-       pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, &ultra);
-       tmp1 = ((0x00 << (2*drive_number)) | (ultra & ~(3 << (2*drive_number))));
-       ultra_conf = pci_bus_clock_list_ultra(speed, aec6210_base);
-       tmp2 = ((ultra_conf << (2*drive_number)) | (tmp1 & ~(3 << (2*drive_number))));
-       pci_write_config_byte(HWIF(drive)->pci_dev, 0x54, tmp2);
-
-       err = ide_config_drive_speed(drive, speed);
-
-#if ACARD_DEBUG_DRIVE_INFO
-       printk("%s: %s drive%d 0x04%x 0x02%x 0x02%x 0x02%x 0x02%x\n",
-               drive->name, ide_xfer_verbose(speed), drive_number,
-               drive_conf, ultra, tmp1, ultra_conf, tmp2);
-#endif /* ACARD_DEBUG_DRIVE_INFO */
-
-       return(err);
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
-{
-       struct hd_driveid *id = drive->id;
-       byte speed = -1;
-
-       if (drive->media != ide_disk)
-               return ((int) ide_dma_off_quietly);
-
-       if (((id->dma_ultra & 0x0010) ||
-            (id->dma_ultra & 0x0008) ||
-            (id->dma_ultra & 0x0004)) && (ultra)) {
-               speed = XFER_UDMA_2;
-       } else if ((id->dma_ultra & 0x0002) && (ultra)) {
-               speed = XFER_UDMA_1;
-       } else if ((id->dma_ultra & 0x0001) && (ultra)) {
-               speed = XFER_UDMA_0;
-       } else if (id->dma_mword & 0x0004) {
-               speed = XFER_MW_DMA_2;
-       } else if (id->dma_mword & 0x0002) {
-               speed = XFER_MW_DMA_1;
-       } else if (id->dma_mword & 0x0001) {
-               speed = XFER_MW_DMA_0;
-       } else if (id->dma_1word & 0x0004) {
-               speed = XFER_SW_DMA_2;
-       } else if (id->dma_1word & 0x0002) {
-               speed = XFER_SW_DMA_1;
-       } else if (id->dma_1word & 0x0001) {
-               speed = XFER_SW_DMA_0;
-       } else {
-               return ((int) ide_dma_off_quietly);
-       }
-       (void) aec6210_tune_chipset(drive, speed);
-
-       return ((int)   ((id->dma_ultra >> 11) & 3) ? ide_dma_off :
-                       ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
-                       ((id->dma_mword >> 8) & 7) ? ide_dma_on :
-                       ((id->dma_1word >> 8) & 7) ? ide_dma_on :
-                                                    ide_dma_off_quietly);
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
-static void aec6210_tune_drive (ide_drive_t *drive, byte pio)
-{
-       byte speed;
-
-       switch(pio) {
-               case 5:
-                       speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
-               case 4:
-                       speed = XFER_PIO_4; break;
-               case 3:
-                       speed = XFER_PIO_3; break;
-               case 2:
-                       speed = XFER_PIO_2; break;
-               case 1:
-                       speed = XFER_PIO_1; break;
-               default:
-                       speed = XFER_PIO_0; break;
-       }
-       (void) aec6210_tune_chipset(drive, speed);
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-static int config_drive_xfer_rate (ide_drive_t *drive)
-{
-       struct hd_driveid *id = drive->id;
-       ide_dma_action_t dma_func = ide_dma_on;
-
-       if (id && (id->capability & 1) && HWIF(drive)->autodma) {
-               /* Consult the list of known "bad" drives */
-               if (ide_dmaproc(ide_dma_bad_drive, drive)) {
-                       dma_func = ide_dma_off;
-                       goto fast_ata_pio;
-               }
-               dma_func = ide_dma_off_quietly;
-               if (id->field_valid & 4) {
-                       if (id->dma_ultra & 0x001F) {
-                               /* Force if Capable UltraDMA */
-                               dma_func = config_chipset_for_dma(drive, 1);
-                               if ((id->field_valid & 2) &&
-                                   (dma_func != ide_dma_on))
-                                       goto try_dma_modes;
-                       }
-               } else if (id->field_valid & 2) {
-try_dma_modes:
-                       if ((id->dma_mword & 0x0007) ||
-                           (id->dma_1word & 0x0007)) {
-                               /* Force if Capable regular DMA modes */
-                               dma_func = config_chipset_for_dma(drive, 0);
-                               if (dma_func != ide_dma_on)
-                                       goto no_dma_set;
-                       }
-               } else if (ide_dmaproc(ide_dma_good_drive, drive)) {
-                       if (id->eide_dma_time > 150) {
-                               goto no_dma_set;
-                       }
-                       /* Consult the list of known "good" drives */
-                       dma_func = config_chipset_for_dma(drive, 0);
-                       if (dma_func != ide_dma_on)
-                               goto no_dma_set;
-               } else {
-                       goto fast_ata_pio;
-               }
-       } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-               dma_func = ide_dma_off_quietly;
-no_dma_set:
-               aec6210_tune_drive(drive, 5);
-       }
-       return HWIF(drive)->dmaproc(dma_func, drive);
-}
-
-/*
- * aec6210_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
- */
-int aec6210_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
-{
-       switch (func) {
-               case ide_dma_check:
-                       return config_drive_xfer_rate(drive);
-               default:
-                       break;
-       }
-       return ide_dmaproc(func, drive);        /* use standard DMA stuff */
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-#endif /* CONFIG_AEC6210_TUNING */
-
-unsigned int __init pci_init_aec6210 (struct pci_dev *dev, const char *name)
-{
-       if (dev->resource[PCI_ROM_RESOURCE].start) {
-               pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
-               printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
-       }
-
-#if defined(DISPLAY_AEC6210_TIMINGS) && defined(CONFIG_PROC_FS)
-       aec6210_proc = 1;
-       bmide_dev = dev;
-       aec6210_display_info = &aec6210_get_info;
-#endif /* DISPLAY_AEC6210_TIMINGS && CONFIG_PROC_FS */
-
-       return dev->irq;
-}
-
-void __init ide_init_aec6210 (ide_hwif_t *hwif)
-{
-#ifdef CONFIG_AEC6210_TUNING
-       hwif->tuneproc = &aec6210_tune_drive;
-       hwif->drives[0].autotune = 1;
-       hwif->drives[1].autotune = 1;
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-       if (hwif->dma_base)
-               hwif->dmaproc = &aec6210_dmaproc;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-#endif /* CONFIG_AEC6210_TUNING */
-}
-
-void __init ide_dmacapable_aec6210 (ide_hwif_t *hwif, unsigned long dmabase)
-{
-       byte dma_new    = 0;
-       byte dma_old    = inb(dmabase+2);
-       byte reg54h     = 0;
-       byte masterdma  = hwif->channel ? 0x30 : 0x03;
-       byte slavedma   = hwif->channel ? 0xc0 : 0x0c;
-       unsigned long flags;
-
-       __save_flags(flags);    /* local CPU only */
-       __cli();                /* local CPU only */
-
-       dma_new = dma_old;
-
-       pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
-
-       if (reg54h & masterdma) dma_new |= 0x20;
-       if (reg54h & slavedma)  dma_new |= 0x40;
-       if (dma_new != dma_old) outb(dma_new, dmabase+2);
-
-       __restore_flags(flags); /* local CPU only */
-
-       ide_setup_dma(hwif, dmabase, 8);
-}
diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c
new file mode 100644 (file)
index 0000000..0158b42
--- /dev/null
@@ -0,0 +1,553 @@
+/*
+ * linux/drivers/ide/aec62xx.c         Version 0.08    Mar. 28, 2000
+ *
+ * Copyright (C) 2000  Andre Hedrick (andre@suse.com)
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+#define DISPLAY_AEC62XX_TIMINGS
+
+#ifndef HIGH_4
+#define HIGH_4(H)              ((H)=(H>>4))
+#endif
+#ifndef LOW_4
+#define LOW_4(L)               ((L)=(L-((L>>4)<<4)))
+#endif
+#ifndef SPLIT_BYTE
+#define SPLIT_BYTE(B,H,L)      ((H)=(B>>4), (L)=(B-((B>>4)<<4)))
+#endif
+#ifndef MAKE_WORD
+#define MAKE_WORD(W,HB,LB)     ((W)=((HB<<8)+LB))
+#endif
+
+
+#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static int aec62xx_get_info(char *, char **, off_t, int);
+extern int (*aec62xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+extern char *ide_media_verbose(ide_drive_t *);
+static struct pci_dev *bmide_dev;
+
+static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count)
+{
+       char *p = buffer;
+
+       u32 bibma = bmide_dev->resource[4].start;
+       u8 c0 = 0, c1 = 0;
+       u8 art = 0, uart = 0;
+
+       switch(bmide_dev->device) {
+               case PCI_DEVICE_ID_ARTOP_ATP850UF:
+                       p += sprintf(p, "\n                                AEC6210 Chipset.\n");
+                       break;
+               case PCI_DEVICE_ID_ARTOP_ATP860:
+                       p += sprintf(p, "\n                                AEC6260 No Bios Chipset.\n");
+                       break;
+               case PCI_DEVICE_ID_ARTOP_ATP860R:
+                       p += sprintf(p, "\n                                AEC6260 Chipset.\n");
+                       break;
+               default:
+                       p += sprintf(p, "\n                                AEC62?? Chipset.\n");
+                       break;
+       }
+
+        /*
+         * at that point bibma+0x2 et bibma+0xa are byte registers
+         * to investigate:
+         */
+       c0 = inb_p((unsigned short)bibma + 0x02);
+       c1 = inb_p((unsigned short)bibma + 0x0a);
+
+       p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
+       (void) pci_read_config_byte(bmide_dev, 0x4a, &art);
+       p += sprintf(p, "                %sabled                         %sabled\n",
+               (art&0x02)?" en":"dis",(art&0x04)?" en":"dis");
+       p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+       p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
+               (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ",(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no ");
+
+       switch(bmide_dev->device) {
+               case PCI_DEVICE_ID_ARTOP_ATP850UF:
+                       (void) pci_read_config_byte(bmide_dev, 0x54, &art);
+                       p += sprintf(p, "DMA Mode:       %s(%s)          %s(%s)         %s(%s)           %s(%s)\n",
+                               (c0&0x20)?((art&0x03)?"UDMA":" DMA"):" PIO",
+                               (art&0x02)?"2":(art&0x01)?"1":"0",
+                               (c0&0x40)?((art&0x0c)?"UDMA":" DMA"):" PIO",
+                               (art&0x08)?"2":(art&0x04)?"1":"0",
+                               (c1&0x20)?((art&0x30)?"UDMA":" DMA"):" PIO",
+                               (art&0x20)?"2":(art&0x10)?"1":"0",
+                               (c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO",
+                               (art&0x80)?"2":(art&0x40)?"1":"0");
+                       (void) pci_read_config_byte(bmide_dev, 0x40, &art);
+                       p += sprintf(p, "Active:         0x%02x", art);
+                       (void) pci_read_config_byte(bmide_dev, 0x42, &art);
+                       p += sprintf(p, "             0x%02x", art);
+                       (void) pci_read_config_byte(bmide_dev, 0x44, &art);
+                       p += sprintf(p, "            0x%02x", art);
+                       (void) pci_read_config_byte(bmide_dev, 0x46, &art);
+                       p += sprintf(p, "              0x%02x\n", art);
+                       (void) pci_read_config_byte(bmide_dev, 0x41, &art);
+                       p += sprintf(p, "Recovery:       0x%02x", art);
+                       (void) pci_read_config_byte(bmide_dev, 0x43, &art);
+                       p += sprintf(p, "             0x%02x", art);
+                       (void) pci_read_config_byte(bmide_dev, 0x45, &art);
+                       p += sprintf(p, "            0x%02x", art);
+                       (void) pci_read_config_byte(bmide_dev, 0x47, &art);
+                       p += sprintf(p, "              0x%02x\n", art);
+                       break;
+               case PCI_DEVICE_ID_ARTOP_ATP860:
+               case PCI_DEVICE_ID_ARTOP_ATP860R:
+                       (void) pci_read_config_byte(bmide_dev, 0x44, &art);
+                       p += sprintf(p, "DMA Mode:       %s(%s)          %s(%s)",
+                               (c0&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO",
+                               ((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((art&0x01)==0x01)?"0":"?",
+                               (c0&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO",
+                               ((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((art&0x10)==0x10)?"0":"?");
+                       (void) pci_read_config_byte(bmide_dev, 0x45, &art);
+                       p += sprintf(p, "         %s(%s)           %s(%s)\n",
+                               (c1&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO",
+                               ((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((art&0x01)==0x01)?"0":"?",
+                               (c1&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO",
+                               ((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((art&0x10)==0x10)?"0":"?");
+                       (void) pci_read_config_byte(bmide_dev, 0x40, &art);
+                       p += sprintf(p, "Active:         0x%02x", HIGH_4(art));
+                       (void) pci_read_config_byte(bmide_dev, 0x41, &art);
+                       p += sprintf(p, "             0x%02x", HIGH_4(art));
+                       (void) pci_read_config_byte(bmide_dev, 0x42, &art);
+                       p += sprintf(p, "            0x%02x", HIGH_4(art));
+                       (void) pci_read_config_byte(bmide_dev, 0x43, &art);
+                       p += sprintf(p, "              0x%02x\n", HIGH_4(art));
+                       (void) pci_read_config_byte(bmide_dev, 0x40, &art);
+                       p += sprintf(p, "Recovery:       0x%02x", LOW_4(art));
+                       (void) pci_read_config_byte(bmide_dev, 0x41, &art);
+                       p += sprintf(p, "             0x%02x", LOW_4(art));
+                       (void) pci_read_config_byte(bmide_dev, 0x42, &art);
+                       p += sprintf(p, "            0x%02x", LOW_4(art));
+                       (void) pci_read_config_byte(bmide_dev, 0x43, &art);
+                       p += sprintf(p, "              0x%02x\n", LOW_4(art));
+                       (void) pci_read_config_byte(bmide_dev, 0x49, &uart);
+                       p += sprintf(p, "reg49h = 0x%02x ", uart);
+                       (void) pci_read_config_byte(bmide_dev, 0x4a, &uart);
+                       p += sprintf(p, "reg4ah = 0x%02x\n", uart);
+                       break;
+               default:
+                       break;
+       }
+
+       return p-buffer;/* => must be less than 4k! */
+}
+#endif /* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+byte aec62xx_proc = 0;
+
+#ifdef CONFIG_AEC62XX_TUNING
+
+struct chipset_bus_clock_list_entry {
+       byte            xfer_speed;
+
+       byte            chipset_settings_34;
+       byte            ultra_settings_34;
+
+       byte            chipset_settings_33;
+       byte            ultra_settings_33;
+};
+
+struct chipset_bus_clock_list_entry aec62xx_base [] = {
+       {       XFER_UDMA_4,    0x41,   0x04,   0x31,   0x05    },
+       {       XFER_UDMA_3,    0x41,   0x03,   0x31,   0x04    },
+       {       XFER_UDMA_2,    0x41,   0x02,   0x31,   0x03    },
+       {       XFER_UDMA_1,    0x41,   0x01,   0x31,   0x02    },
+       {       XFER_UDMA_0,    0x41,   0x01,   0x31,   0x01    },
+
+       {       XFER_MW_DMA_2,  0x41,   0x00,   0x31,   0x00    },
+       {       XFER_MW_DMA_1,  0x42,   0x00,   0x31,   0x00    },
+       {       XFER_MW_DMA_0,  0x7a,   0x00,   0x0a,   0x00    },
+
+       {       XFER_PIO_4,     0x41,   0x00,   0x31,   0x00    },
+       {       XFER_PIO_3,     0x43,   0x00,   0x33,   0x00    },
+       {       XFER_PIO_2,     0x78,   0x00,   0x08,   0x00    },
+       {       XFER_PIO_1,     0x7a,   0x00,   0x0a,   0x00    },
+       {       XFER_PIO_0,     0x70,   0x00,   0x00,   0x00    },
+       {       0,              0x00,   0x00,   0x00,   0x00    }
+};
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+/*
+ * TO DO: active tuning and correction of cards without a bios.
+ */
+
+static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+{
+       for ( ; chipset_table->xfer_speed ; chipset_table++)
+               if (chipset_table->xfer_speed == speed) {
+                       return ((byte) ((1) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34));
+               }
+       return 0x00;
+}
+
+static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+{
+       for ( ; chipset_table->xfer_speed ; chipset_table++)
+               if (chipset_table->xfer_speed == speed) {
+                       return ((byte) ((1) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34));
+               }
+       return 0x00;
+}
+
+static int aec6210_tune_chipset (ide_drive_t *drive, byte speed)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = hwif->pci_dev;
+       byte unit               = (drive->select.b.unit & 0x01);
+       int drive_number        = ((hwif->channel ? 2 : 0) + unit);
+       int err                 = 0;
+       unsigned short d_conf   = 0x0000;
+       byte ultra              = 0x00;
+       byte ultra_conf         = 0x00;
+       byte tmp0               = 0x00;
+       byte tmp1               = 0x00;
+       byte tmp2               = 0x00;
+       unsigned long flags;
+
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
+
+       pci_read_config_word(dev, 0x40|(2*drive_number), &d_conf);
+       tmp0 = pci_bus_clock_list(speed, aec62xx_base);
+       SPLIT_BYTE(tmp0,tmp1,tmp2);
+       MAKE_WORD(d_conf,tmp1,tmp2);
+       pci_write_config_word(dev, 0x40|(2*drive_number), d_conf);
+
+       tmp1 = 0x00;
+       tmp2 = 0x00;
+       pci_read_config_byte(dev, 0x54, &ultra);
+       tmp1 = ((0x00 << (2*drive_number)) | (ultra & ~(3 << (2*drive_number))));
+       ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base);
+       tmp2 = ((ultra_conf << (2*drive_number)) | (tmp1 & ~(3 << (2*drive_number))));
+       pci_write_config_byte(dev, 0x54, tmp2);
+
+       __restore_flags(flags); /* local CPU only */
+
+       err = ide_config_drive_speed(drive, speed);
+       return(err);
+}
+
+static int aec6260_tune_chipset (ide_drive_t *drive, byte speed)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = hwif->pci_dev;
+       byte unit               = (drive->select.b.unit & 0x01);
+       int drive_number        = ((hwif->channel ? 2 : 0) + unit);
+       byte ultra_pci          = hwif->channel ? 0x45 : 0x44;
+       int err                 = 0;
+       byte drive_conf         = 0x00;
+       byte ultra_conf         = 0x00;
+       byte ultra              = 0x00;
+       byte tmp1               = 0x00;
+       byte tmp2               = 0x00;
+
+       unsigned long flags;
+
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
+
+       pci_read_config_byte(dev, 0x40|drive_number, &drive_conf);
+       drive_conf = pci_bus_clock_list(speed, aec62xx_base);
+       pci_write_config_byte(dev, 0x40|drive_number, drive_conf);
+
+       pci_read_config_byte(dev, ultra_pci, &ultra);
+       tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
+       ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base);
+       tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit))));
+       pci_write_config_byte(dev, ultra_pci, tmp2);
+       __restore_flags(flags); /* local CPU only */
+
+       err = ide_config_drive_speed(drive, speed);
+       return(err);
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+static int config_aec6210_chipset_for_dma (ide_drive_t *drive, byte ultra)
+{
+       struct hd_driveid *id   = drive->id;
+       ide_hwif_t *hwif        = HWIF(drive);
+       byte unit               = (drive->select.b.unit & 0x01);
+       unsigned long dma_base  = hwif->dma_base;
+       byte speed              = -1;
+
+       if (drive->media != ide_disk)
+               return ((int) ide_dma_off_quietly);
+
+       if (((id->dma_ultra & 0x0010) ||
+            (id->dma_ultra & 0x0008) ||
+            (id->dma_ultra & 0x0004)) && (ultra)) {
+               speed = XFER_UDMA_2;
+       } else if ((id->dma_ultra & 0x0002) && (ultra)) {
+               speed = XFER_UDMA_1;
+       } else if ((id->dma_ultra & 0x0001) && (ultra)) {
+               speed = XFER_UDMA_0;
+       } else if (id->dma_mword & 0x0004) {
+               speed = XFER_MW_DMA_2;
+       } else if (id->dma_mword & 0x0002) {
+               speed = XFER_MW_DMA_1;
+       } else if (id->dma_mword & 0x0001) {
+               speed = XFER_MW_DMA_0;
+       } else if (id->dma_1word & 0x0004) {
+               speed = XFER_SW_DMA_2;
+       } else if (id->dma_1word & 0x0002) {
+               speed = XFER_SW_DMA_1;
+       } else if (id->dma_1word & 0x0001) {
+               speed = XFER_SW_DMA_0;
+       } else {
+               return ((int) ide_dma_off_quietly);
+       }
+
+       outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+       (void) aec6210_tune_chipset(drive, speed);
+
+       return ((int)   ((id->dma_ultra >> 11) & 3) ? ide_dma_off :
+                       ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+                       ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+                       ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+                                                    ide_dma_off_quietly);
+}
+
+static int config_aec6260_chipset_for_dma (ide_drive_t *drive, byte ultra)
+{
+       struct hd_driveid *id   = drive->id;
+       ide_hwif_t *hwif        = HWIF(drive);
+       byte unit               = (drive->select.b.unit & 0x01);
+       unsigned long dma_base  = hwif->dma_base;
+       byte speed              = -1;
+       byte ultra66            = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
+
+       if (drive->media != ide_disk)
+               return ((int) ide_dma_off_quietly);
+
+       if ((id->dma_ultra & 0x0010) && (ultra) && (ultra66)) {
+               speed = XFER_UDMA_4;
+       } else if ((id->dma_ultra & 0x0008) && (ultra) && (ultra66)) {
+               speed = XFER_UDMA_3;
+       } else if ((id->dma_ultra & 0x0004) && (ultra)) {
+               speed = XFER_UDMA_2;
+       } else if ((id->dma_ultra & 0x0002) && (ultra)) {
+               speed = XFER_UDMA_1;
+       } else if ((id->dma_ultra & 0x0001) && (ultra)) {
+               speed = XFER_UDMA_0;
+       } else if (id->dma_mword & 0x0004) {
+               speed = XFER_MW_DMA_2;
+       } else if (id->dma_mword & 0x0002) {
+               speed = XFER_MW_DMA_1;
+       } else if (id->dma_mword & 0x0001) {
+               speed = XFER_MW_DMA_0;
+       } else if (id->dma_1word & 0x0004) {
+               speed = XFER_SW_DMA_2;
+       } else if (id->dma_1word & 0x0002) {
+               speed = XFER_SW_DMA_1;
+       } else if (id->dma_1word & 0x0001) {
+               speed = XFER_SW_DMA_0;
+       } else {
+               return ((int) ide_dma_off_quietly);
+       }
+
+       outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+       (void) aec6260_tune_chipset(drive, speed);
+
+       return ((int)   ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
+                       ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+                       ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+                       ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+                                                    ide_dma_off_quietly);
+}
+
+static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
+{
+       switch(HWIF(drive)->pci_dev->device) {  
+               case PCI_DEVICE_ID_ARTOP_ATP850UF:
+                       return config_aec6210_chipset_for_dma(drive, ultra);
+               case PCI_DEVICE_ID_ARTOP_ATP860:
+               case PCI_DEVICE_ID_ARTOP_ATP860R:
+                       return config_aec6260_chipset_for_dma(drive, ultra);
+               default:
+                       return ((int) ide_dma_off_quietly);
+       }
+}
+
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+static void aec62xx_tune_drive (ide_drive_t *drive, byte pio)
+{
+       byte speed;
+       byte new_pio = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+       switch(pio) {
+               case 5:         speed = new_pio; break;
+               case 4:         speed = XFER_PIO_4; break;
+               case 3:         speed = XFER_PIO_3; break;
+               case 2:         speed = XFER_PIO_2; break;
+               case 1:         speed = XFER_PIO_1; break;
+               default:        speed = XFER_PIO_0; break;
+       }
+
+       switch(HWIF(drive)->pci_dev->device) {
+               case PCI_DEVICE_ID_ARTOP_ATP850UF:
+                       (void) aec6210_tune_chipset(drive, speed);
+               case PCI_DEVICE_ID_ARTOP_ATP860:
+               case PCI_DEVICE_ID_ARTOP_ATP860R:
+                       (void) aec6260_tune_chipset(drive, speed);
+               default:
+                       break;
+        }
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+       struct hd_driveid *id = drive->id;
+       ide_dma_action_t dma_func = ide_dma_on;
+
+       if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+               /* Consult the list of known "bad" drives */
+               if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+                       dma_func = ide_dma_off;
+                       goto fast_ata_pio;
+               }
+               dma_func = ide_dma_off_quietly;
+               if (id->field_valid & 4) {
+                       if (id->dma_ultra & 0x001F) {
+                               /* Force if Capable UltraDMA */
+                               dma_func = config_chipset_for_dma(drive, 1);
+                               if ((id->field_valid & 2) &&
+                                   (dma_func != ide_dma_on))
+                                       goto try_dma_modes;
+                       }
+               } else if (id->field_valid & 2) {
+try_dma_modes:
+                       if ((id->dma_mword & 0x0007) ||
+                           (id->dma_1word & 0x0007)) {
+                               /* Force if Capable regular DMA modes */
+                               dma_func = config_chipset_for_dma(drive, 0);
+                               if (dma_func != ide_dma_on)
+                                       goto no_dma_set;
+                       }
+               } else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+                       if (id->eide_dma_time > 150) {
+                               goto no_dma_set;
+                       }
+                       /* Consult the list of known "good" drives */
+                       dma_func = config_chipset_for_dma(drive, 0);
+                       if (dma_func != ide_dma_on)
+                               goto no_dma_set;
+               } else {
+                       goto fast_ata_pio;
+               }
+       } else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+               dma_func = ide_dma_off_quietly;
+no_dma_set:
+               aec62xx_tune_drive(drive, 5);
+       }
+       return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * aec62xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ */
+int aec62xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+       switch (func) {
+               case ide_dma_check:
+                       return config_drive_xfer_rate(drive);
+               default:
+                       break;
+       }
+       return ide_dmaproc(func, drive);        /* use standard DMA stuff */
+}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+#endif /* CONFIG_AEC62XX_TUNING */
+
+unsigned int __init pci_init_aec62xx (struct pci_dev *dev, const char *name)
+{
+       if (dev->resource[PCI_ROM_RESOURCE].start) {
+               pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+               printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
+       }
+
+#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS)
+       if (!aec62xx_proc) {
+               aec62xx_proc = 1;
+               bmide_dev = dev;
+               aec62xx_display_info = &aec62xx_get_info;
+       }
+#endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */
+
+       return dev->irq;
+}
+
+unsigned int __init ata66_aec62xx (ide_hwif_t *hwif)
+{
+       byte mask       = hwif->channel ? 0x02 : 0x01;
+       byte ata66      = 0;
+
+       pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
+#if 1
+       printk("AEC6260: reg49h=0x%02x ATA-%s Cable Port%d\n", ata66, (ata66 & mask) ? "33" : "66", hwif->channel);
+#endif
+       return ((ata66 & mask) ? 0 : 1);
+}
+
+void __init ide_init_aec62xx (ide_hwif_t *hwif)
+{
+#ifdef CONFIG_AEC62XX_TUNING
+       hwif->tuneproc = &aec62xx_tune_drive;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+       if (hwif->dma_base)
+               hwif->dmaproc = &aec62xx_dmaproc;
+#else /* !CONFIG_BLK_DEV_IDEDMA */
+       hwif->drives[0].autotune = 1;
+       hwif->drives[1].autotune = 1;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+#endif /* CONFIG_AEC62XX_TUNING */
+}
+
+void __init ide_dmacapable_aec62xx (ide_hwif_t *hwif, unsigned long dmabase)
+{
+#ifdef CONFIG_AEC62XX_TUNING
+       unsigned long flags;
+       byte reg54h = 0;
+
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
+
+       pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
+       pci_write_config_byte(hwif->pci_dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F));
+
+       __restore_flags(flags); /* local CPU only */
+#endif /* CONFIG_AEC62XX_TUNING */
+       ide_setup_dma(hwif, dmabase, 8);
+}
index ff87917c5c320d8190129dd56219a18b05bd150e..d3bf7b80119c1ec1f356ef4a394fd2af5ceeac2a 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 
@@ -118,7 +119,7 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
        byte param1, param2, param3, param4;
        unsigned long flags;
        ide_pio_data_t d;
-       int bus_speed = ide_system_bus_speed();
+       int bus_speed = system_bus_clock();
 
        pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d);
 
index b043d67743795dd83efa3a43f9cff5de04db3a11..c5f570674a10721f531fc8cf831f9d06d7040a45 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 
@@ -249,7 +250,7 @@ static void ali15x3_tune_drive (ide_drive_t *drive, byte pio)
        int s_time, a_time, c_time;
        byte s_clc, a_clc, r_clc;
        unsigned long flags;
-       int bus_speed = ide_system_bus_speed();
+       int bus_speed = system_bus_clock();
        int port = hwif->index ? 0x5c : 0x58;
        int portFIFO = hwif->channel ? 0x55 : 0x54;
        byte cd_dma_fifo = 0;
@@ -409,14 +410,14 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra33)
 
 static byte ali15x3_can_ultra (ide_drive_t *drive)
 {
-#ifdef CONFIG_WDC_ALI15X3
+#ifndef CONFIG_WDC_ALI15X3
        struct hd_driveid *id   = drive->id;
 #endif /* CONFIG_WDC_ALI15X3 */
 
        if (m5229_revision <= 0x20) {
                return 0;
        } else if ((m5229_revision < 0xC2) &&
-#ifdef CONFIG_WDC_ALI15X3
+#ifndef CONFIG_WDC_ALI15X3
                   ((chip_is_1543c_e && strstr(id->model, "WDC ")) ||
                    (drive->media!=ide_disk))) {
 #else /* CONFIG_WDC_ALI15X3 */
index 2d44044dddde6d06653fc9045c2ae8e579c09a49..14a8a83f15c789f2dc551546fdd6d3da00f6379d 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/hdreg.h>
 
 #include <linux/interrupt.h>
+#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
 
index da53155c1816b10dd2b58210422c5bd56b29797e..710b6654d97d76717c3f2a5f4294de5699ca59c9 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/hdreg.h>
 #include <linux/zorro.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
index 7a094d497660972c558598bf200b6fb490cdf137..3bf1299320aae4e8a54780bf5b26ac13a7cad16b 100644 (file)
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 
@@ -595,7 +596,7 @@ static void cmd640_set_mode (unsigned int index, byte pio_mode, unsigned int cyc
 {
        int setup_time, active_time, recovery_time, clock_time;
        byte setup_count, active_count, recovery_count, recovery_count2, cycle_count;
-       int bus_speed = ide_system_bus_speed();
+       int bus_speed = system_bus_clock();
 
        if (pio_mode > 5)
                pio_mode = 5;
index 2aaf83b2655be2460c048f5c71227d1398cc93ae..8e100de3c20a12fd73edafa44146aa9377eff0d7 100644 (file)
 #include <linux/delay.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
+
 #include "ide_modes.h"
 
 #ifndef SPLIT_BYTE
@@ -271,7 +273,7 @@ static void cmd64x_tuneproc (ide_drive_t *drive, byte mode_wanted)
        int setup_time, active_time, recovery_time, clock_time, pio_mode, cycle_time;
        byte recovery_count2, cycle_count;
        int setup_count, active_count, recovery_count;
-       int bus_speed = ide_system_bus_speed();
+       int bus_speed = system_bus_clock();
        /*byte b;*/
        ide_pio_data_t  d;
 
@@ -645,6 +647,9 @@ unsigned int __init pci_init_cmd64x (struct pci_dev *dev, const char *name)
 #endif
        (void) pci_write_config_byte(dev, DRWTIM23, 0x3f);
        (void) pci_write_config_byte(dev, DRWTIM3,  0x3f);
+#ifdef CONFIG_PPC
+       (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0);
+#endif /* CONFIG_PPC */
 
 #if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS)
        if (!cmd64x_proc) {
index 4498b754bc4eeaab3a4cf5bb9ee1c99bb7157c76..3ecaa31ece2c54bbbaf409b16cfd994913dcb60e 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 
@@ -140,9 +141,8 @@ static int calc_clk (int time, int bus_speed)
 static void compute_clocks (byte pio, pio_clocks_t *p_pclk)
 {
        int clk1, clk2;
-       int bus_speed;
+       int bus_speed = system_bus_clock();     /* get speed of PCI bus */
 
-       bus_speed = ide_system_bus_speed();     /* get speed of PCI bus */
        /* we don't check against CY82C693's min and max speed,
         * so you can play with the idebus=xx parameter
         */
index 28537d048826ff4a86b54c0bdc006ec42e7032b9..16fbceac264fbca22112af25dd8673845b2cc860 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 
index 096d75fc042d17a52206c5561631618f93725c10..fa2e4b2ac2c6627fa4e5226526c2eb8f5d67241f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/atarihw.h>
 #include <asm/atariints.h>
index 170bf16f7b600d9cbe3fe8227248368ff49631ac..74806824219b9b5bde86b7e7ebe97945c56def58 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
index 1c0b55dace0cb0a0bbe1cf8a0dac7a4381f9742a..3ba8e55eee712844941a5da7bf09c56d55e62bd6 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 
@@ -203,9 +204,10 @@ static int __init try_to_init_ht6560b(void)
 
 static byte ht_pio2timings(ide_drive_t *drive, byte pio)
 {
-       int bus_speed, active_time, recovery_time;
+       int active_time, recovery_time;
        int active_cycles, recovery_cycles;
        ide_pio_data_t d;
+       int bus_speed = system_bus_clock();
        
         if (pio) {
                pio = ide_get_best_pio_mode(drive, pio, 5, &d);
@@ -215,7 +217,6 @@ static byte ht_pio2timings(ide_drive_t *drive, byte pio)
                 *  actual cycle time for recovery and activity
                 *  according system bus speed.
                 */
-               bus_speed = ide_system_bus_speed();
                active_time = ide_pio_timings[pio].active_time;
                recovery_time = d.cycle_time 
                        - active_time
index 213ddbff0758b03b1881ccdef22bab1dda4d95a6..8ef0f9356e1b80acf2a864f9f72aa7af7a133ebf 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/errno.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/dma.h>
 #include <asm/ecard.h>
index 17cc3eb88d4afd53018dd10659320d9606edf91c..66397d93e71ac0c46efec50b86290ed9d989bc7b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1994, 1995, 1996  scott snyder  <snyder@fnald0.fnal.gov>
  * Copyright (C) 1996-1998  Erik Andersen <andersee@debian.org>
- * Copyright (C) 1998, 1999 Jens Axboe <axboe@image.dk>
+ * Copyright (C) 1998-2000  Jens Axboe <axboe@suse.de>
  *
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
@@ -16,8 +16,8 @@
  * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI 
  * (SFF-8020i rev 2.6) standards. These documents can be obtained by 
  * anonymous ftp from:
- * ftp://fission.dt.wdc.com/pub/standards/SFF/specs/INF-8020.PDF
- * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r01.pdf
+ * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
+ * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
  *
  * Drives that deviate from these standards will be accomodated as much
  * as possible via compile time or command-line options.  Since I only have
  *                     - Fixed a problem with WPI CDS-32X drive - it
  *                       failed the capabilities 
  *
+ * 4.57  Apr 7, 2000   - Fixed sense reporting.
+ *                     - Fixed possible oops in ide_cdrom_get_last_session()
+ *                     - Fix locking mania and make ide_cdrom_reset relock
+ *                     - Stop spewing errors to log when magicdev polls with
+ *                       TEST_UNIT_READY on some drives.
+ *                     - Various fixes from Tobias Ringstrom:
+ *                       tray if it was locked prior to the reset.
+ *                       - cdrom_read_capacity returns one frame too little.
+ *                       - Fix real capacity reporting.
  *
  *************************************************************************/
  
-#define IDECD_VERSION "4.56"
+#define IDECD_VERSION "4.57"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -314,11 +323,12 @@ static void cdrom_saw_media_change (ide_drive_t *drive)
 
 
 static
-void cdrom_analyze_sense_data (ide_drive_t *drive, struct request_sense *reqbuf,
-                              struct packet_command *failed_command)
+void cdrom_analyze_sense_data(ide_drive_t *drive,
+                             struct packet_command *failed_command,
+                             struct request_sense *sense)
 {
-       if (reqbuf->sense_key == NOT_READY ||
-           reqbuf->sense_key == UNIT_ATTENTION) {
+       if (sense->sense_key == NOT_READY ||
+           sense->sense_key == UNIT_ATTENTION) {
                /* Make good and sure we've seen this potential media change.
                   Some drives (i.e. Creative) fail to present the correct
                   sense key in the error register. */
@@ -330,13 +340,14 @@ void cdrom_analyze_sense_data (ide_drive_t *drive, struct request_sense *reqbuf,
                   uses this command to poll the drive, and we don't want
                   to fill the syslog with useless errors. */
                if (failed_command &&
-                   failed_command->c[0] == GPCMD_READ_SUBCHANNEL)
+                   (failed_command->c[0] == GPCMD_READ_SUBCHANNEL ||
+                    failed_command->c[0] == GPCMD_TEST_UNIT_READY))
                        return;
        }
 
-       if (reqbuf->error_code == 0x70 && reqbuf->sense_key  == 0x02
-        && ((reqbuf->asc      == 0x3a && reqbuf->ascq       == 0x00) ||
-            (reqbuf->asc      == 0x04 && reqbuf->ascq       == 0x01)))
+       if (sense->error_code == 0x70 && sense->sense_key  == 0x02
+        && ((sense->asc      == 0x3a && sense->ascq       == 0x00) ||
+            (sense->asc      == 0x04 && sense->ascq       == 0x01)))
        {
                /*
                 * Suppress the following errors:
@@ -353,30 +364,32 @@ void cdrom_analyze_sense_data (ide_drive_t *drive, struct request_sense *reqbuf,
                char buf[80];
 
                printk ("ATAPI device %s:\n", drive->name);
-               if (reqbuf->error_code==0x70)
+               if (sense->error_code==0x70)
                        printk("  Error: ");
-               else if (reqbuf->error_code==0x71)
+               else if (sense->error_code==0x71)
                        printk("  Deferred Error: ");
+               else if (sense->error_code == 0x7f)
+                       printk("  Vendor-specific Error: ");
                else
                        printk("  Unknown Error Type: ");
 
-               if ( reqbuf->sense_key < ARY_LEN (sense_key_texts))
-                       s = sense_key_texts[reqbuf->sense_key];
+               if (sense->sense_key < ARY_LEN(sense_key_texts))
+                       s = sense_key_texts[sense->sense_key];
                else
                        s = "bad sense key!";
 
-               printk ("%s -- (Sense key=0x%02x)\n", s, reqbuf->sense_key);
+               printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
 
-               if (reqbuf->asc == 0x40) {
-                       sprintf (buf, "Diagnostic failure on component 0x%02x",
-                                reqbuf->ascq);
+               if (sense->asc == 0x40) {
+                       sprintf(buf, "Diagnostic failure on component 0x%02x",
+                                sense->ascq);
                        s = buf;
                } else {
-                       int lo=0, mid, hi=ARY_LEN (sense_data_texts);
-                       unsigned long key = (reqbuf->sense_key << 16);
-                       key |= (reqbuf->asc << 8);
-                       if ( ! (reqbuf->ascq >= 0x80 && reqbuf->ascq <= 0xdd) )
-                               key |= reqbuf->ascq;
+                       int lo = 0, mid, hi = ARY_LEN(sense_data_texts);
+                       unsigned long key = (sense->sense_key << 16);
+                       key |= (sense->asc << 8);
+                       if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
+                               key |= sense->ascq;
                        s = NULL;
 
                        while (hi > lo) {
@@ -394,14 +407,14 @@ void cdrom_analyze_sense_data (ide_drive_t *drive, struct request_sense *reqbuf,
                }
 
                if (s == NULL) {
-                       if (reqbuf->asc > 0x80)
+                       if (sense->asc > 0x80)
                                s = "(vendor-specific error)";
                        else
                                s = "(reserved error code)";
                }
 
-               printk ("  %s -- (asc=0x%02x, ascq=0x%02x)\n",
-                       s, reqbuf->asc, reqbuf->ascq);
+               printk("  %s -- (asc=0x%02x, ascq=0x%02x)\n",
+                       s, sense->asc, sense->ascq);
 
                if (failed_command != NULL) {
 
@@ -431,21 +444,21 @@ void cdrom_analyze_sense_data (ide_drive_t *drive, struct request_sense *reqbuf,
                 * In the case of NOT_READY, if SKSV is set the drive can
                 * give us nice ETA readings.
                 */
-               if (reqbuf->sense_key == NOT_READY && (reqbuf->sks[0] & 0x80)) {
-                       int progress = (reqbuf->sks[1] << 8 | reqbuf->sks[2]) * 100;
+               if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
+                       int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
                        printk("  Command is %02d%% complete\n", progress / 0xffff);
 
                }
 
-               if (reqbuf->sense_key == ILLEGAL_REQUEST &&
-                   (reqbuf->sks[0] & 0x80) != 0) {
-                       printk ("  Error in %s byte %d",
-                               (reqbuf->sks[0] & 0x40) != 0 ?
+               if (sense->sense_key == ILLEGAL_REQUEST &&
+                   (sense->sks[0] & 0x80) != 0) {
+                       printk("  Error in %s byte %d",
+                               (sense->sks[0] & 0x40) != 0 ?
                                "command packet" : "command data",
-                               (reqbuf->sks[1] << 8) + reqbuf->sks[2]);
+                               (sense->sks[1] << 8) + sense->sks[2]);
 
-                       if ((reqbuf->sks[0] & 0x40) != 0)
-                               printk (" bit %d", reqbuf->sks[0] & 0x07);
+                       if ((sense->sks[0] & 0x40) != 0)
+                               printk (" bit %d", sense->sks[0] & 0x07);
 
                        printk ("\n");
                }
@@ -456,45 +469,43 @@ void cdrom_analyze_sense_data (ide_drive_t *drive, struct request_sense *reqbuf,
        /* Suppress printing unit attention and `in progress of becoming ready'
           errors when we're not being verbose. */
 
-       if (reqbuf->sense_key == UNIT_ATTENTION ||
-           (reqbuf->sense_key == NOT_READY && (reqbuf->asc == 4 ||
-                                               reqbuf->asc == 0x3a)))
+       if (sense->sense_key == UNIT_ATTENTION ||
+           (sense->sense_key == NOT_READY && (sense->asc == 4 ||
+                                               sense->asc == 0x3a)))
                return;
 
-       printk ("%s: error code: 0x%02x  sense_key: 0x%02x  asc: 0x%02x  ascq: 0x%02x\n",
+       printk("%s: error code: 0x%02x  sense_key: 0x%02x  asc: 0x%02x  ascq: 0x%02x\n",
                drive->name,
-               reqbuf->error_code, reqbuf->sense_key,
-               reqbuf->asc, reqbuf->ascq);
+               sense->error_code, sense->sense_key,
+               sense->asc, sense->ascq);
 #endif /* not VERBOSE_IDE_CD_ERRORS */
 }
 
-static void cdrom_queue_request_sense (ide_drive_t *drive, 
-                                      struct semaphore *sem,
-                                      struct packet_command *failed_command)
+static void cdrom_queue_request_sense(ide_drive_t *drive, 
+                                     struct semaphore *sem,
+                                     struct request_sense *sense,
+                                     struct packet_command *failed_command)
 {
        struct cdrom_info *info = drive->driver_data;
        struct request *rq;
-       struct packet_command *pc;
+       struct packet_command *pc = &info->request_sense_pc;
 
-       /* Make up a new request to retrieve sense information. */
-       pc = &info->request_sense_pc;
-       memset(pc, 0, sizeof (*pc));
+       if (sense == NULL)
+               sense = &info->sense_data;
 
+       memset(pc, 0, sizeof(struct packet_command));
        pc->c[0] = GPCMD_REQUEST_SENSE;
-
-       /* just get the first 18 bytes of the sense info, there might not
-        * be more available */
        pc->c[4] = pc->buflen = 18;
-       pc->buffer = (char *)&info->sense_data;
-       pc->sense_data = (struct request_sense *)failed_command;
+       pc->buffer = (char *) sense;
+       pc->sense = (struct request_sense *) failed_command;
 
        /* stuff the sense request in front of our current request */
        rq = &info->request_sense_request;
-       ide_init_drive_cmd (rq);
+       ide_init_drive_cmd(rq);
        rq->cmd = REQUEST_SENSE_COMMAND;
-       rq->buffer = (char *)pc;
+       rq->buffer = (char *) pc;
        rq->sem = sem;
-       (void) ide_do_drive_cmd (drive, rq, ide_preempt);
+       (void) ide_do_drive_cmd(drive, rq, ide_preempt);
 }
 
 
@@ -503,11 +514,10 @@ static void cdrom_end_request (int uptodate, ide_drive_t *drive)
        struct request *rq = HWGROUP(drive)->rq;
 
        if (rq->cmd == REQUEST_SENSE_COMMAND && uptodate) {
-               struct packet_command *pc = (struct packet_command *)
-                                             rq->buffer;
-               cdrom_analyze_sense_data (drive,
-                       (struct request_sense *) (pc->buffer - pc->c[4]),
-                       (struct packet_command *) pc->sense_data);
+               struct packet_command *pc = (struct packet_command *)rq->buffer;
+               cdrom_analyze_sense_data(drive,
+                       (struct packet_command *) pc->sense,
+                       (struct request_sense *) (pc->buffer - pc->c[4]));
        }
        if (rq->cmd == READ && !rq->current_nr_sectors)
                uptodate = 1;
@@ -523,7 +533,7 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
 {
        struct request *rq = HWGROUP(drive)->rq;
        int stat, cmd, err, sense_key;
-       struct packet_command *pc = (struct packet_command *) rq->buffer;
+       struct packet_command *pc;
        
        /* Check for errors. */
        stat = GET_STAT();
@@ -547,6 +557,7 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
                           from the drive (probably while trying
                           to recover from a former error).  Just give up. */
 
+                       pc = (struct packet_command *) rq->buffer;
                        pc->stat = 1;
                        cdrom_end_request (1, drive);
                        *startstop = ide_error (drive, "request sense failure", stat);
@@ -556,6 +567,7 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
                        /* All other functions, except for READ. */
 
                        struct semaphore *sem = NULL;
+                       pc = (struct packet_command *) rq->buffer;
 
                        /* Check for tray open. */
                        if (sense_key == NOT_READY) {
@@ -589,7 +601,8 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
                        cdrom_end_request (1, drive);
 
                        if ((stat & ERR_STAT) != 0)
-                               cdrom_queue_request_sense(drive, sem, pc);
+                               cdrom_queue_request_sense(drive, sem, pc->sense,
+                                                         pc);
                } else {
                        /* Handle errors from READ requests. */
 
@@ -628,7 +641,7 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
                        /* If we got a CHECK_CONDITION status,
                           queue a request sense command. */
                        if ((stat & ERR_STAT) != 0)
-                               cdrom_queue_request_sense(drive, NULL, NULL);
+                               cdrom_queue_request_sense(drive, NULL, NULL, NULL);
                }
        }
 
@@ -1062,11 +1075,11 @@ static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
        pc.c[0] = GPCMD_READ_10;
        pc.c[7] = (nframes >> 8);
        pc.c[8] = (nframes & 0xff);
-       put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]);
+       put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
 
        /* Send the command to the drive and return. */
-       return cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c),
-                                             &cdrom_read_intr);
+       return cdrom_transfer_packet_command(drive, pc.c, sizeof(pc.c),
+                                            &cdrom_read_intr);
 }
 
 
@@ -1178,7 +1191,8 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
  */
 
 /* Forward declarations. */
-static int cdrom_lockdoor(ide_drive_t *drive, int lockflag);
+static int cdrom_lockdoor(ide_drive_t *drive, int lockflag,
+                         struct request_sense *sense);
 
 /* Interrupt routine for packet command completion. */
 static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
@@ -1186,11 +1200,8 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
        int ireason, len, stat, thislen;
        struct request *rq = HWGROUP(drive)->rq;
        struct packet_command *pc = (struct packet_command *)rq->buffer;
-       struct cdrom_info *info = drive->driver_data;
        ide_startstop_t startstop;
 
-       pc->sense_data = &info->sense_data;
-
        /* Check for errors. */
        if (cdrom_decode_status (&startstop, drive, 0, &stat))
                return startstop;
@@ -1320,8 +1331,12 @@ void cdrom_sleep (int time)
 static
 int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc)
 {
-       int retries = 10;
+       struct request_sense sense;
        struct request req;
+       int retries = 10;
+
+       if (pc->sense == NULL)
+               pc->sense = &sense;
 
        /* Start of retry loop. */
        do {
@@ -1337,7 +1352,7 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc)
                        /* The request failed.  Retry if it was due to a unit
                           attention status
                           (usually means media was changed). */
-                       struct request_sense *reqbuf = pc->sense_data;
+                       struct request_sense *reqbuf = pc->sense;
 
                        if (reqbuf->sense_key == UNIT_ATTENTION)
                                cdrom_saw_media_change (drive);
@@ -1358,24 +1373,7 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc)
        } while (pc->stat != 0 && retries >= 0);
 
        /* Return an error if the command failed. */
-       if (pc->stat)
-               return -EIO;
-
-       /* The command succeeded.  If it was anything other than
-          a request sense, eject, or door lock command,
-          and we think that the door is presently unlocked, lock it
-          again. (The door was probably unlocked via an explicit
-          CDROMEJECT ioctl.) */
-       if (CDROM_STATE_FLAGS (drive)->door_locked == 0 &&
-           (pc->c[0] != GPCMD_TEST_UNIT_READY &&
-            pc->c[0] != GPCMD_REQUEST_SENSE &&
-            pc->c[0] != GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL &&
-            pc->c[0] != GPCMD_START_STOP_UNIT &&
-            pc->c[0] != GPCMD_MODE_SENSE_10 &&
-            pc->c[0] != GPCMD_MODE_SELECT_10)) {
-               (void) cdrom_lockdoor (drive, 1);
-       }
-       return 0;
+       return pc->stat ? -EIO : 0;
 }
 
 /****************************************************************************
@@ -1483,13 +1481,14 @@ int msf_to_lba (byte m, byte s, byte f)
        return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
 }
 
-static int cdrom_check_status (ide_drive_t  *drive)
+static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
 {
        struct packet_command pc;
        struct cdrom_info *info = drive->driver_data;
        struct cdrom_device_info *cdi = &info->devinfo;
 
        memset(&pc, 0, sizeof(pc));
+       pc.sense = sense;
 
        pc.c[0] = GPCMD_TEST_UNIT_READY;
 
@@ -1506,24 +1505,26 @@ static int cdrom_check_status (ide_drive_t  *drive)
 
 /* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
 static int
-cdrom_lockdoor(ide_drive_t *drive, int lockflag)
+cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
 {
-       struct request_sense *sense;
+       struct request_sense my_sense;
        struct packet_command pc;
        int stat;
 
+       if (sense == NULL)
+               sense = &my_sense;
+
        /* If the drive cannot lock the door, just pretend. */
-       if (CDROM_CONFIG_FLAGS (drive)->no_doorlock)
+       if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {
                stat = 0;
-       else {
+       else {
                memset(&pc, 0, sizeof(pc));
+               pc.sense = sense;
                pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
                pc.c[4] = (lockflag != 0);
                stat = cdrom_queue_packet_command (drive, &pc);
        }
 
-       sense = pc.sense_data;
-
        /* If we got an illegal field error, the drive
           probably cannot lock the door. */
        if (stat != 0 &&
@@ -1548,7 +1549,8 @@ cdrom_lockdoor(ide_drive_t *drive, int lockflag)
 
 /* Eject the disk if EJECTFLAG is 0.
    If EJECTFLAG is 1, try to reload the disk. */
-static int cdrom_eject(ide_drive_t *drive, int ejectflag)
+static int cdrom_eject(ide_drive_t *drive, int ejectflag,
+                      struct request_sense *sense)
 {
        struct packet_command pc;
 
@@ -1560,13 +1562,15 @@ static int cdrom_eject(ide_drive_t *drive, int ejectflag)
                return 0;
 
        memset(&pc, 0, sizeof (pc));
+       pc.sense = sense;
 
        pc.c[0] = GPCMD_START_STOP_UNIT;
        pc.c[4] = 0x02 + (ejectflag != 0);
        return cdrom_queue_packet_command (drive, &pc);
 }
 
-static int cdrom_read_capacity(ide_drive_t *drive, unsigned *capacity)
+static int cdrom_read_capacity(ide_drive_t *drive, unsigned *capacity,
+                              struct request_sense *sense)
 {
        struct {
                __u32 lba;
@@ -1576,7 +1580,8 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned *capacity)
        int stat;
        struct packet_command pc;
 
-       memset(&pc, 0, sizeof (pc));
+       memset(&pc, 0, sizeof(pc));
+       pc.sense = sense;
 
        pc.c[0] = GPCMD_READ_CDVD_CAPACITY;
        pc.buffer = (char *)&capbuf;
@@ -1584,17 +1589,19 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned *capacity)
 
        stat = cdrom_queue_packet_command(drive, &pc);
        if (stat == 0)
-               *capacity = be32_to_cpu(capbuf.lba);
+               *capacity = 1 + be32_to_cpu(capbuf.lba);
 
        return stat;
 }
 
 static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
-                               int format, char *buf, int buflen)
+                               int format, char *buf, int buflen,
+                               struct request_sense *sense)
 {
        struct packet_command pc;
 
        memset(&pc, 0, sizeof(pc));
+       pc.sense = sense;
 
        pc.buffer =  buf;
        pc.buflen = buflen;
@@ -1612,12 +1619,11 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
 
 
 /* Try to read the entire TOC for the disk into our internal buffer. */
-static int cdrom_read_toc (ide_drive_t *drive)
+static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
 {
        int stat, ntracks, i;
        struct cdrom_info *info = drive->driver_data;
        struct atapi_toc *toc = info->toc;
-       int minor = drive->select.b.unit << PARTN_BITS;
        struct {
                struct atapi_toc_header hdr;
                struct atapi_toc_entry  ent;
@@ -1637,13 +1643,13 @@ static int cdrom_read_toc (ide_drive_t *drive)
        /* Check to see if the existing data is still valid.
           If it is, just return. */
        if (CDROM_STATE_FLAGS (drive)->toc_valid)
-               (void) cdrom_check_status(drive);
+               (void) cdrom_check_status(drive, sense);
 
        if (CDROM_STATE_FLAGS (drive)->toc_valid) return 0;
 
        /* First read just the header, so we know how long the TOC is. */
-       stat = cdrom_read_tocentry (drive, 0, 1, 0, (char *)&toc->hdr,
-                                   sizeof (struct atapi_toc_header));
+       stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
+                                   sizeof(struct atapi_toc_header), sense);
        if (stat) return stat;
 
 #if ! STANDARD_ATAPI
@@ -1658,10 +1664,11 @@ static int cdrom_read_toc (ide_drive_t *drive)
        if (ntracks > MAX_TRACKS) ntracks = MAX_TRACKS;
 
        /* Now read the whole schmeer. */
-       stat = cdrom_read_tocentry (drive, toc->hdr.first_track, 1, 0, (char *)&toc->hdr,
-                                   sizeof (struct atapi_toc_header) +
-                                   (ntracks + 1) *
-                                   sizeof (struct atapi_toc_entry));
+       stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0,
+                                 (char *)&toc->hdr,
+                                  sizeof(struct atapi_toc_header) +
+                                  (ntracks + 1) *
+                                  sizeof(struct atapi_toc_entry), sense);
 
        if (stat && toc->hdr.first_track > 1) {
                /* Cds with CDI tracks only don't have any TOC entries,
@@ -1674,11 +1681,12 @@ static int cdrom_read_toc (ide_drive_t *drive)
                   the readable TOC is empty (CDI tracks are not included)
                   and only holds the Leadout entry. Heiko Eißfeldt */
                ntracks = 0;
-               stat = cdrom_read_tocentry (drive, CDROM_LEADOUT, 1,
-                                           0, (char *)&toc->hdr,
-                                           sizeof (struct atapi_toc_header) +
-                                          (ntracks+1) *
-                                           sizeof (struct atapi_toc_entry));
+               stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
+                                          (char *)&toc->hdr,
+                                          sizeof(struct atapi_toc_header) +
+                                          (ntracks + 1) *
+                                          sizeof(struct atapi_toc_entry),
+                                          sense);
                if (stat) {
                        return stat;
                }
@@ -1722,8 +1730,8 @@ static int cdrom_read_toc (ide_drive_t *drive)
        /* Read the multisession information. */
        if (toc->hdr.first_track != CDROM_LEADOUT) {
                /* Read the multisession information. */
-               stat = cdrom_read_tocentry (drive, 0, 1, 1,
-                                          (char *)&ms_tmp, sizeof (ms_tmp));
+               stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
+                                          sizeof(ms_tmp), sense);
                if (stat) return stat;
        } else {
                ms_tmp.ent.addr.msf.minute = 0;
@@ -1749,45 +1757,23 @@ static int cdrom_read_toc (ide_drive_t *drive)
                                     (long *)&toc->capacity);
        if (stat)
 #endif
-       stat = cdrom_read_capacity (drive, &toc->capacity);
+       stat = cdrom_read_capacity(drive, &toc->capacity, sense);
        if (stat) toc->capacity = 0x1fffff;
 
-       /* for general /dev/cdrom like mounting, one big disc */
-       drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
-       HWIF(drive)->gd->sizes[minor] = (toc->capacity * SECTORS_PER_FRAME) >>
-                                       (BLOCK_SIZE_BITS - 9);
-
        /* Remember that we've read this stuff. */
        CDROM_STATE_FLAGS (drive)->toc_valid = 1;
 
-       /* should be "if multisession", but it does no harm. */
-       if (ntracks == 1)
-               return 0;
-
-       /* setup each minor to respond to a session */
-       minor++;
-       i = toc->hdr.first_track;
-       while ((i <= ntracks) && ((minor & CD_PART_MASK) < CD_PART_MAX)) {
-               drive->part[minor & PARTN_MASK].start_sect = 0;
-               drive->part[minor & PARTN_MASK].nr_sects =
-                       (toc->ent[i].addr.lba *
-                       SECTORS_PER_FRAME) << (BLOCK_SIZE_BITS - 9);
-               HWIF(drive)->gd->sizes[minor] = (toc->ent[i].addr.lba *
-                       SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
-               i++;
-               minor++;
-       }
-
        return 0;
 }
 
 
 static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
-                                int buflen)
+                                int buflen, struct request_sense *sense)
 {
        struct packet_command pc;
 
        memset(&pc, 0, sizeof(pc));
+       pc.sense = sense;
 
        pc.buffer = buf;
        pc.buflen = buflen;
@@ -1802,10 +1788,12 @@ static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
 
 /* ATAPI cdrom drives are free to select the speed you request or any slower
    rate :-( Requesting too fast a speed will _not_ produce an error. */
-static int cdrom_select_speed (ide_drive_t *drive, int speed)
+static int cdrom_select_speed(ide_drive_t *drive, int speed,
+                             struct request_sense *sense)
 {
        struct packet_command pc;
        memset(&pc, 0, sizeof(pc));
+       pc.sense = sense;
 
        if (speed == 0)
                speed = 0xffff; /* set to max */
@@ -1825,7 +1813,7 @@ static int cdrom_select_speed (ide_drive_t *drive, int speed)
                pc.c[5] = speed & 0xff;
        }
 
-       return cdrom_queue_packet_command (drive, &pc);
+       return cdrom_queue_packet_command(drive, &pc);
 }
 
 
@@ -1869,10 +1857,7 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
        pc.buffer = cgc->buffer;
        pc.buflen = cgc->buflen;
        cgc->stat = cdrom_queue_packet_command(drive, &pc);
-
-       /* There was an error, assign sense. */
-       if (cgc->stat)
-               cgc->sense = pc.sense_data;
+       cgc->sense = pc.sense;
 
        return cgc->stat;
 }
@@ -1938,7 +1923,7 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
                struct atapi_toc *toc;
 
                /* Make sure our saved TOC is valid. */
-               stat = cdrom_read_toc(drive);
+               stat = cdrom_read_toc(drive, NULL);
                if (stat) return stat;
 
                toc = info->toc;
@@ -1978,11 +1963,22 @@ static
 int ide_cdrom_reset (struct cdrom_device_info *cdi)
 {
        ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+       struct request_sense sense;
        struct request req;
+       int ret;
 
        ide_init_drive_cmd (&req);
        req.cmd = RESET_DRIVE_COMMAND;
-       return ide_do_drive_cmd (drive, &req, ide_wait);
+       ret = ide_do_drive_cmd(drive, &req, ide_wait);
+
+       /*
+        * A reset will unlock the door. If it was previously locked,
+        * lock it again.
+        */
+       if (CDROM_STATE_FLAGS(drive)->door_locked)
+               (void) cdrom_lockdoor(drive, 1, &sense);
+
+       return ret;
 }
 
 
@@ -1990,20 +1986,21 @@ static
 int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
 {
        ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+       struct request_sense sense;
 
        if (position) {
-               int stat = cdrom_lockdoor (drive, 0);
+               int stat = cdrom_lockdoor(drive, 0, &sense);
                if (stat) return stat;
        }
 
-       return cdrom_eject(drive, !position);
+       return cdrom_eject(drive, !position, &sense);
 }
 
 static
 int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
 {
        ide_drive_t *drive = (ide_drive_t*) cdi->handle;
-       return cdrom_lockdoor (drive, lock);
+       return cdrom_lockdoor(drive, lock, NULL);
 }
 
 #undef __ACER50__
@@ -2060,21 +2057,20 @@ static
 int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
 {
 #ifndef __ACER50__
-        int stat, attempts = 3;
-       ide_drive_t *drive = (ide_drive_t*) cdi->handle;
-       struct cdrom_generic_command cgc;
+        int attempts = 3;
        struct {
                char pad[8];
                struct atapi_capabilities_page cap;
        } buf;
 #else
-       int stat;
-       ide_drive_t *drive = (ide_drive_t*) cdi->handle;
-       struct cdrom_generic_command cgc;
        struct get_capabilities_buf buf;
 #endif /* __ACER50__ */
+       ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+       struct cdrom_generic_command cgc;
+       struct request_sense sense;
+       int stat;
 
-       if ((stat = cdrom_select_speed (drive, speed)) < 0)
+       if ((stat = cdrom_select_speed (drive, speed, &sense)) < 0)
                return stat;
 
        init_cdrom_command(&cgc, &buf, sizeof(buf), CGC_DATA_UNKNOWN);
@@ -2112,19 +2108,18 @@ static
 int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
 {
        ide_drive_t *drive = (ide_drive_t*) cdi->handle;
-       struct cdrom_info *info = drive->driver_data;
 
        if (slot_nr == CDSL_CURRENT) {
-               struct request_sense *sense = &info->sense_data;
-               int stat = cdrom_check_status(drive);
-               if (stat == 0 || sense->sense_key == UNIT_ATTENTION)
+               struct request_sense sense;
+               int stat = cdrom_check_status(drive, &sense);
+               if (stat == 0 || sense.sense_key == UNIT_ATTENTION)
                        return CDS_DISC_OK;
 
-               if (sense->sense_key == NOT_READY && sense->asc == 0x04 &&
-                   sense->ascq == 0x04)
+               if (sense.sense_key == NOT_READY && sense.asc == 0x04 &&
+                   sense.ascq == 0x04)
                        return CDS_DISC_OK;
 
-               if (sense->sense_key == NOT_READY) {
+               if (sense.sense_key == NOT_READY) {
                        /* ATAPI doesn't have anything that can help
                           us decide whether the drive is really
                           emtpy or the tray is just open. irk. */
@@ -2132,9 +2127,8 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
                }
 
                return CDS_DRIVE_NOT_READY;
-       } else {
-               return -EINVAL;
        }
+       return -EINVAL;
 }
 
 static
@@ -2144,8 +2138,14 @@ int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
        struct atapi_toc *toc;
        ide_drive_t *drive = (ide_drive_t*) cdi->handle;
        struct cdrom_info *info = drive->driver_data;
+       struct request_sense sense;
+       int ret;
 
        toc = info->toc;
+       if (!CDROM_STATE_FLAGS(drive)->toc_valid || toc == NULL)
+               if ((ret = cdrom_read_toc(drive, &sense)))
+                       return ret;
+
        ms_info->addr.lba = toc->last_session_lba;
        ms_info->xa_flag = toc->xa_flag;
 
@@ -2161,7 +2161,7 @@ int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
        ide_drive_t *drive = (ide_drive_t*) cdi->handle;
 
 /* get MCN */
-       if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf))))
+       if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL)))
                return stat;
 
        memcpy (mcn_info->medium_catalog_number, mcnbuf+9,
@@ -2183,11 +2183,13 @@ int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
                                       int slot_nr)
 {
        ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+       int retval;
        
        if (slot_nr == CDSL_CURRENT) {
-               (void) cdrom_check_status(drive);
+               (void) cdrom_check_status(drive, NULL);
+               retval = CDROM_STATE_FLAGS (drive)->media_changed;
                CDROM_STATE_FLAGS (drive)->media_changed = 0;
-               return CDROM_STATE_FLAGS (drive)->media_changed;
+               return retval;
        } else {
                return -EINVAL;
        }
@@ -2600,6 +2602,37 @@ int ide_cdrom_check_media_change (ide_drive_t *drive)
                        (drive->select.b.unit)<<PARTN_BITS));
 }
 
+static
+void ide_cdrom_revalidate (ide_drive_t *drive)
+{
+       struct cdrom_info *info = drive->driver_data;
+       struct atapi_toc *toc;
+       int minor = drive->select.b.unit << PARTN_BITS;
+       struct request_sense sense;
+
+       cdrom_read_toc(drive, &sense);
+
+       if (!CDROM_STATE_FLAGS(drive)->toc_valid)
+               return;
+
+       toc = info->toc;
+
+       /* for general /dev/cdrom like mounting, one big disc */
+       drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
+       HWIF(drive)->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME;
+
+       blk_size[HWIF(drive)->major] = HWIF(drive)->gd->sizes;
+}
+
+static
+unsigned long ide_cdrom_capacity (ide_drive_t *drive)
+{
+       unsigned capacity;
+
+       capacity = cdrom_read_capacity(drive, &capacity, NULL);
+       return capacity ? 0 : capacity * SECTORS_PER_FRAME;
+}
+
 static
 int ide_cdrom_cleanup(ide_drive_t *drive)
 {
@@ -2635,13 +2668,14 @@ static ide_driver_t ide_cdrom_driver = {
        ide_cdrom_open,                 /* open */
        ide_cdrom_release,              /* release */
        ide_cdrom_check_media_change,   /* media_change */
+       ide_cdrom_revalidate,           /* revalidate */
        NULL,                           /* pre_reset */
-       NULL,                           /* capacity */
+       ide_cdrom_capacity,             /* capacity */
        NULL,                           /* special */
        NULL                            /* proc */
 };
 
-int ide_cdrom_init (void);
+int ide_cdrom_init(void);
 static ide_module_t ide_cdrom_module = {
        IDE_DRIVER_MODULE,
        ide_cdrom_init,
@@ -2670,7 +2704,7 @@ void __exit ide_cdrom_exit(void)
 }
 #endif /* MODULE */
  
-int ide_cdrom_init (void)
+int ide_cdrom_init(void)
 {
        ide_drive_t *drive;
        struct cdrom_info *info;
index 77937dd4b983c025a4d0c45d5820a2c422fc447e..3c685d5bfe576c382ae92ddf25dbc5d066e493fb 100644 (file)
@@ -43,6 +43,8 @@
 #define SECTOR_BUFFER_SIZE     (CD_FRAMESIZE * 32)
 #define SECTORS_BUFFER         (SECTOR_BUFFER_SIZE / SECTOR_SIZE)
 
+#define BLOCKS_PER_FRAME       (CD_FRAMESIZE / BLOCK_SIZE)
+
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 
 /* special command codes for strategy routine. */
@@ -103,7 +105,7 @@ struct packet_command {
        char *buffer;
        int buflen;
        int stat;
-       struct request_sense *sense_data;
+       struct request_sense *sense;
        unsigned char c[12];
 };
 
index e8cfa5c7a767f02e3f5c9a983b0dc1505b4260b7..66bf35a70c0d551ca2a3545cef8e5f95b076e1d6 100644 (file)
@@ -512,6 +512,13 @@ static int idedisk_media_change (ide_drive_t *drive)
        return drive->removable;        /* if removable, always assume it was changed */
 }
 
+static void idedisk_revalidate (ide_drive_t *drive)
+{
+       grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
+                       1<<PARTN_BITS,
+                       current_capacity(drive));
+}
+
 /*
  * Compute drive->capacity, the full capacity of the drive
  * Called with drive->id != NULL.
@@ -726,6 +733,7 @@ static ide_driver_t idedisk_driver = {
        idedisk_open,           /* open */
        idedisk_release,        /* release */
        idedisk_media_change,   /* media_change */
+       idedisk_revalidate,     /* revalidate */
        idedisk_pre_reset,      /* pre_reset */
        idedisk_capacity,       /* capacity */
        idedisk_special,        /* special */
index 9caffd2f1d88738eebc8451fe54315efdd1a5297..835fa91e34e465e7ca456397215b855d89a9338c 100644 (file)
@@ -368,7 +368,13 @@ int report_drive_dmaing (ide_drive_t *drive)
                }
        } else if ((id->field_valid & 4) &&
                   (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
-               printk(", UDMA(33)");   /* UDMA BIOS-enabled! */
+               if ((id->dma_ultra >> 10) & 1) {
+                       printk(", UDMA(33)");   /* UDMA BIOS-enabled! */
+               } else if ((id->dma_ultra >> 9) & 1) {
+                       printk(", UDMA(25)");   /* UDMA BIOS-enabled! */
+               } else {
+                       printk(", UDMA(16)");   /* UDMA BIOS-enabled! */
+               }
        } else if (id->field_valid & 4) {
                printk(", (U)DMA");     /* Can be BIOS-enabled! */
        } else {
index 55349e92aef5535848bfadbdc25122394e7c26eb..1130bd3d5dbf9db78c6309391d6ff1cfbb8f8a0a 100644 (file)
@@ -1375,6 +1375,16 @@ static int idefloppy_media_change (ide_drive_t *drive)
        return test_and_clear_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
 }
 
+/*
+ *     Revalidate the new media. Should set blk_size[]
+ */
+static void idefloppy_revalidate (ide_drive_t *drive)
+{
+       grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
+                       1<<PARTN_BITS,
+                       current_capacity(drive));
+}
+
 /*
  *     Return the current floppy capacity to ide.c.
  */
@@ -1604,6 +1614,7 @@ static ide_driver_t idefloppy_driver = {
        idefloppy_open,         /* open */
        idefloppy_release,      /* release */
        idefloppy_media_change, /* media_change */
+       idefloppy_revalidate,   /* media_change */
        NULL,                   /* pre_reset */
        idefloppy_capacity,     /* capacity */
        NULL,                   /* special */
index 35ba5cb5f753e5c27b9025a534d04e9dd75ed656..8d999d91c618f48f1029866616f4731d5e830b51 100644 (file)
@@ -52,6 +52,8 @@
 #define DEVID_NS87415  ((ide_pci_devid_t){PCI_VENDOR_ID_NS,      PCI_DEVICE_ID_NS_87415})
 #define DEVID_HT6565   ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK,  PCI_DEVICE_ID_HOLTEK_6565})
 #define DEVID_AEC6210  ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP,   PCI_DEVICE_ID_ARTOP_ATP850UF})
+#define DEVID_AEC6260  ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP,   PCI_DEVICE_ID_ARTOP_ATP860})
+#define DEVID_AEC6260R ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP,   PCI_DEVICE_ID_ARTOP_ATP860R})
 #define DEVID_W82C105  ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105})
 #define DEVID_UM8673F  ((ide_pci_devid_t){PCI_VENDOR_ID_UMC,     PCI_DEVICE_ID_UMC_UM8673F})
 #define DEVID_UM8886A  ((ide_pci_devid_t){PCI_VENDOR_ID_UMC,     PCI_DEVICE_ID_UMC_UM8886A})
 
 #define        IDE_IGNORE      ((void *)-1)
 
-#ifdef CONFIG_BLK_DEV_AEC6210
-extern unsigned int pci_init_aec6210(struct pci_dev *, const char *);
-extern void ide_init_aec6210(ide_hwif_t *);
-extern void ide_dmacapable_aec6210(ide_hwif_t *, unsigned long);
-#define PCI_AEC6210    &pci_init_aec6210
-#define INIT_AEC6210   &ide_init_aec6210
-#define DMA_AEC6210    &ide_dmacapable_aec6210
+#ifdef CONFIG_BLK_DEV_AEC62XX
+extern unsigned int pci_init_aec62xx(struct pci_dev *, const char *);
+extern unsigned int ata66_aec62xx(ide_hwif_t *);
+extern void ide_init_aec62xx(ide_hwif_t *);
+extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long);
+#define PCI_AEC62XX    &pci_init_aec62xx
+#define ATA66_AEC62XX  &ata66_aec62xx
+#define INIT_AEC62XX   &ide_init_aec62xx
+#define DMA_AEC62XX    &ide_dmacapable_aec62xx
 #else
-#define PCI_AEC6210    NULL
-#define INIT_AEC6210   NULL
-#define DMA_AEC6210    NULL
+#define PCI_AEC62XX    NULL
+#define ATA66_AEC62XX  NULL
+#define INIT_AEC62XX   NULL
+#define DMA_AEC62XX    NULL
 #endif
 
 #ifdef CONFIG_BLK_DEV_ALI15X3
@@ -318,7 +323,9 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = {
        {DEVID_OPTI621X,"OPTI621X",     NULL,           NULL,           INIT_OPTI621,   NULL,           {{0x45,0x80,0x00}, {0x40,0x08,0x00}},   ON_BOARD,       0 },
        {DEVID_TRM290,  "TRM290",       NULL,           NULL,           INIT_TRM290,    NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
        {DEVID_NS87415, "NS87415",      NULL,           NULL,           INIT_NS87415,   NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
-       {DEVID_AEC6210, "AEC6210",      PCI_AEC6210,    NULL,           INIT_AEC6210,   DMA_AEC6210,    {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   OFF_BOARD,      0 },
+       {DEVID_AEC6210, "AEC6210",      PCI_AEC62XX,    NULL,           INIT_AEC62XX,   DMA_AEC62XX,    {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},   OFF_BOARD,      0 },
+       {DEVID_AEC6260, "AEC6260",      PCI_AEC62XX,    ATA66_AEC62XX,  INIT_AEC62XX,   NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   NEVER_BOARD,    0 },
+       {DEVID_AEC6260R,"AEC6260R",     PCI_AEC62XX,    ATA66_AEC62XX,  INIT_AEC62XX,   NULL,           {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},   OFF_BOARD,      0 },
        {DEVID_W82C105, "W82C105",      NULL,           NULL,           INIT_W82C105,   DMA_W82C105,    {{0x40,0x01,0x01}, {0x40,0x10,0x10}},   ON_BOARD,       0 },
        {DEVID_UM8673F, "UM8673F",      NULL,           NULL,           NULL,           NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
        {DEVID_UM8886A, "UM8886A",      NULL,           NULL,           NULL,           NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}},   ON_BOARD,       0 },
@@ -344,6 +351,8 @@ static unsigned int __init ide_special_settings (struct pci_dev *dev, const char
                case PCI_DEVICE_ID_PROMISE_20246:
                case PCI_DEVICE_ID_PROMISE_20262:
                case PCI_DEVICE_ID_ARTOP_ATP850UF:
+               case PCI_DEVICE_ID_ARTOP_ATP860:
+               case PCI_DEVICE_ID_ARTOP_ATP860R:
                        return dev->irq;
                default:
                        break;
@@ -592,6 +601,7 @@ check_if_enabled:
                }
 #ifdef CONFIG_BLK_DEV_IDEDMA
                if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) ||
+                   IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X))
                        autodma = 0;
                if (autodma)
@@ -599,6 +609,8 @@ check_if_enabled:
                if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) ||
+                   IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
+                   IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) ||
                    IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) ||
index d8edb89c51073c6ff4279dad936ff408a3b79ceb..cf49e1a66c265c1eaf98422ff636efc2f9fcb31a 100644 (file)
@@ -17,6 +17,8 @@
  */
 
 #include <linux/ide.h>
+#include <linux/init.h>
+
 #include <linux/isapnp.h>
 
 #ifndef PREPARE_FUNC
index 200204ee60fa9e6c2db8198213672ed5d859ca9b..7c5130e77f5f67ff69b644a996b5a9b67478e47d 100644 (file)
@@ -204,6 +204,10 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
                hd_status = IDE_STATUS_REG;
        }
 
+       /* set features register for atapi identify command to be sure of reply */
+       if ((cmd == WIN_PIDENTIFY))
+               OUT_BYTE(0,IDE_FEATURE_REG);    /* disable dma & overlap */
+
 #if CONFIG_BLK_DEV_PDC4030
        if (HWIF(drive)->chipset == ide_pdc4030) {
                /* DC4030 hosted drives need their own identify... */
index fd33e4e42c72124bf4366e507199212826b926c7..efc0ea717274d706ea59f3cae439327858599c54 100644 (file)
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #endif
 
-#ifdef CONFIG_BLK_DEV_AEC6210
-extern byte aec6210_proc;
-int (*aec6210_display_info)(char *, char **, off_t, int) = NULL;
-#endif /* CONFIG_BLK_DEV_AEC6210 */
+#ifdef CONFIG_BLK_DEV_AEC62XX
+extern byte aec62xx_proc;
+int (*aec62xx_display_info)(char *, char **, off_t, int) = NULL;
+#endif /* CONFIG_BLK_DEV_AEC62XX */
 #ifdef CONFIG_BLK_DEV_ALI15X3
 extern byte ali_proc;
 int (*ali_display_info)(char *, char **, off_t, int) = NULL;
@@ -801,10 +801,10 @@ void proc_ide_create(void)
        create_proc_read_entry("drivers", 0, proc_ide_root,
                                proc_ide_read_drivers, NULL);
 
-#ifdef CONFIG_BLK_DEV_AEC6210
-       if ((aec6210_display_info) && (aec6210_proc))
-               create_proc_info_entry("aec6210", 0, proc_ide_root, aec6210_display_info);
-#endif /* CONFIG_BLK_DEV_AEC6210 */
+#ifdef CONFIG_BLK_DEV_AEC62XX
+       if ((aec62xx_display_info) && (aec62xx_proc))
+               create_proc_info_entry("aec62xx", 0, proc_ide_root, aec62xx_display_info);
+#endif /* CONFIG_BLK_DEV_AEC62XX */
 #ifdef CONFIG_BLK_DEV_ALI15X3
        if ((ali_display_info) && (ali_proc))
                create_proc_info_entry("ali", 0, proc_ide_root, ali_display_info);
@@ -853,10 +853,10 @@ void proc_ide_destroy(void)
         * Mmmm.. does this free up all resources,
         * or do we need to do a more proper cleanup here ??
         */
-#ifdef CONFIG_BLK_DEV_AEC6210
-       if ((aec6210_display_info) && (aec6210_proc))
-               remove_proc_entry("ide/aec6210",0);
-#endif /* CONFIG_BLK_DEV_AEC6210 */
+#ifdef CONFIG_BLK_DEV_AEC62XX
+       if ((aec62xx_display_info) && (aec62xx_proc))
+               remove_proc_entry("ide/aec62xx",0);
+#endif /* CONFIG_BLK_DEV_AEC62XX */
 #ifdef CONFIG_BLK_DEV_ALI15X3
        if ((ali_display_info) && (ali_proc))
                remove_proc_entry("ide/ali",0);
index c4424cf904a302d5d8cd30b44c5e1528efce300e..22fdcbfe540343ca60e5c39a0cb2c209228f322c 100644 (file)
@@ -5900,6 +5900,7 @@ static ide_driver_t idetape_driver = {
        idetape_blkdev_open,    /* open */
        idetape_blkdev_release, /* release */
        NULL,                   /* media_change */
+       NULL,                   /* revalidate */
        idetape_pre_reset,      /* pre_reset */
        NULL,                   /* capacity */
        NULL,                   /* special */
index fb24fb0a526fb9e5b47b22f75c43e6fa868c6a6e..1abf214cc24f4fda6903b6d1905759b367620915 100644 (file)
@@ -343,7 +343,7 @@ int ide_system_bus_speed (void)
                        system_bus_speed = idebus_parameter;    /* user supplied value */
 #ifdef CONFIG_PCI
                else if (pci_present())
-                       system_bus_speed = 40;  /* safe default value for PCI */
+                       system_bus_speed = 33;  /* safe default value for PCI */
 #endif /* CONFIG_PCI */
                else
                        system_bus_speed = 50;  /* safe default value for VESA and PCI */
@@ -1091,11 +1091,9 @@ static ide_startstop_t start_request (ide_drive_t *drive)
 #endif
        block    = rq->sector;
        blockend = block + rq->nr_sectors;
-#if 0
+
        if ((rq->cmd == READ || rq->cmd == WRITE) &&
-           (drive->media == ide_disk || drive->media == ide_floppy))
-#endif
-       {
+           (drive->media == ide_disk || drive->media == ide_floppy)) {
                if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK].nr_sects)) {
                        printk("%s%c: bad access: block=%ld, count=%ld\n", drive->name,
                         (minor&PARTN_MASK)?'0'+(minor&PARTN_MASK):' ', block, rq->nr_sectors);
@@ -1777,10 +1775,7 @@ int ide_revalidate_disk (kdev_t i_rdev)
                drive->part[p].nr_sects   = 0;
        };
 
-       grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
-                       (drive->media != ide_disk &&
-                        drive->media != ide_floppy) ? 1 : 1<<PARTN_BITS,
-                               current_capacity(drive));
+       DRIVER(drive)->revalidate(drive);
 
        drive->busy = 0;
        wake_up(&drive->wqueue);
@@ -2095,7 +2090,9 @@ void ide_unregister (unsigned int index)
        hwif->config_data       = old_hwif.config_data;
        hwif->select_data       = old_hwif.select_data;
        hwif->proc              = old_hwif.proc;
+#ifndef CONFIG_BLK_DEV_IDECS
        hwif->irq               = old_hwif.irq;
+#endif /* CONFIG_BLK_DEV_IDECS */
        hwif->major             = old_hwif.major;
        hwif->chipset           = old_hwif.chipset;
        hwif->autodma           = old_hwif.autodma;
@@ -2447,8 +2444,18 @@ int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int secto
  */
 void ide_delay_50ms (void)
 {
+#if 0
        unsigned long timeout = jiffies + ((HZ + 19)/20) + 1;
        while (0 < (signed long)(timeout - jiffies));
+#else
+       __set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout(HZ/20);
+#endif
+}
+
+int system_bus_clock (void)
+{
+       return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
 }
 
 static int ide_ioctl (struct inode *inode, struct file *file,
@@ -3350,7 +3357,7 @@ static void default_pre_reset (ide_drive_t *drive)
 
 static unsigned long default_capacity (ide_drive_t *drive)
 {
-       return 0x7fffffff;      /* cdrom or tape */
+       return 0x7fffffff;
 }
 
 static ide_startstop_t default_special (ide_drive_t *drive)
@@ -3578,6 +3585,8 @@ EXPORT_SYMBOL(hwif_unregister);
 EXPORT_SYMBOL(get_info_ptr);
 EXPORT_SYMBOL(current_capacity);
 
+EXPORT_SYMBOL(system_bus_clock);
+
 /*
  * This is gets invoked once during initialization, to set *everything* up
  */
@@ -3589,7 +3598,7 @@ int __init ide_init (void)
        if (!banner_printed) {
                printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
                ide_devfs_handle = devfs_mk_dir (NULL, "ide", 3, NULL);
-               (void) ide_system_bus_speed();
+               system_bus_speed = ide_system_bus_speed();
                banner_printed = 1;
        }
 
index 46a14ba1993012a68674e8147f131bf56be2ad83..26e4bfae0b2a9d9ffd634d2584c3b4ea76ca953b 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/hdreg.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/machw.h>
 #include <asm/macintosh.h>
index 7a24fce25fa9271a2d0708ddf0b99c5c337e40a9..70f1851088d0b4a0a148c77d63334d2e21d79ee8 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 
index 277f2f490f60345d130139a2462396db43941efe..f11c41d99b955984a6320db530ae73c5fea79269 100644 (file)
@@ -215,8 +215,9 @@ typedef struct pio_clocks_s {
 static void compute_clocks(int pio, pio_clocks_t *clks)
 {
         if (pio != PIO_NOT_EXIST) {
-               int adr_setup, data_pls, bus_speed;
-               bus_speed = ide_system_bus_speed();
+               int adr_setup, data_pls;
+               int bus_speed = system_bus_clock();
+
                adr_setup = ide_pio_timings[pio].setup_time;
                data_pls = ide_pio_timings[pio].active_time;
                clks->address_time = cmpt_clk(adr_setup, bus_speed);
index f42c4946f6dd54063195f41632fb310ee5bc769d..5fe8c06a811b1218606e9a8768ba5f9d2c10d2c2 100644 (file)
@@ -82,6 +82,7 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
index fa453e7d53a132fd614942fe32a8c639221c6e01..fafd0533feef7516648f1a3788a42b8fe3b54e95 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 
index bccf1eb6a18168dc6bc3247cbfa4914ce5d7e5d8..ad56c295ceeb3492e4629d4381e5b7d5c2f99325 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 
index baa293467b7b76d9e5b81764856f869e9c023249..a842a3287466e9b027b476a9dd446cc543386dc1 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/blkdev.h>
 #include <linux/errno.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/ecard.h>
 
index 5bd3db7d577ef609129f24a0ac36ad8ee8ef6088..244d15e27bb56ae3df18356bc7a1e466ae36228a 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/hdreg.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 
index 5c1168972ecd93839e5586a29d3b5179f702f5eb..296d001f27a6f743efa014e3ed82a36ba95f44ee 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 
index bf8e27640862c8153084ce7128cd4d49b5034eaa..f9d96a86560e05ba223734531d6b3e0a7ba97218 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/via82cxxx.c       Version 0.08    Mar. 18, 2000
+ * linux/drivers/ide/via82cxxx.c       Version 0.09    Apr. 02, 2000
  *
  *  Copyright (C) 1998-99      Michel Aubry, Maintainer
  *  Copyright (C) 1999         Jeff Garzik, MVP4 Support
 
 #include <asm/io.h>
 
+#include "ide_modes.h"
+
 static struct pci_dev *host_dev = NULL;
 static struct pci_dev *isa_dev = NULL;
 
+struct chipset_bus_clock_list_entry {
+       byte    xfer_speed;
+
+       byte    chipset_settings_25;
+       byte    ultra_settings_25;
+       byte    chipset_settings_33;
+       byte    ultra_settings_33;
+       byte    chipset_settings_37;
+       byte    ultra_settings_37;
+       byte    chipset_settings_41;
+       byte    ultra_settings_41;
+};
+
+static struct chipset_bus_clock_list_entry * via82cxxx_table = NULL;
+
+struct chipset_bus_clock_list_entry via82cxxx_type_one [] = {
+               /* speed */     /* 25 */        /* 33 */        /* 37.5 */      /* 41.5 */      
+       {       XFER_UDMA_4,    0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00    },
+       {       XFER_UDMA_3,    0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00    },
+       {       XFER_UDMA_2,    0x60,   0x20,   0x60,   0x20,   0x60,   0x21,   0x00,   0x00    },
+       {       XFER_UDMA_1,    0x61,   0x20,   0x61,   0x20,   0x61,   0x21,   0x00,   0x00    },
+       {       XFER_UDMA_0,    0x62,   0x20,   0x62,   0x20,   0x62,   0x21,   0x00,   0x00    },
+
+       {       XFER_MW_DMA_2,  0x03,   0x20,   0x03,   0x20,   0x03,   0x21,   0x00,   0x00    },
+       {       XFER_MW_DMA_1,  0x03,   0x31,   0x03,   0x31,   0x03,   0x32,   0x00,   0x00    },
+       {       XFER_MW_DMA_0,  0x03,   0x31,   0x03,   0x31,   0x03,   0x32,   0x00,   0x00    },
+
+       {       XFER_PIO_4,     0x03,   0x20,   0x03,   0x20,   0x03,   0x21,   0x00,   0x00    },
+       {       XFER_PIO_3,     0x03,   0x31,   0x03,   0x31,   0x03,   0x32,   0x00,   0x00    },
+       {       XFER_PIO_2,     0x03,   0x65,   0x03,   0x65,   0x03,   0x76,   0x00,   0x00    },
+       {       XFER_PIO_1,     0x03,   0x65,   0x03,   0x65,   0x03,   0x76,   0x00,   0x00    },
+       {       XFER_PIO_0,     0x03,   0xA8,   0x03,   0xA8,   0x03,   0xA9,   0x00,   0x00    },
+       {       0,              0x03,   0xA8,   0x03,   0xA8,   0x03,   0xA9,   0x00,   0x00    }
+};
+
+struct chipset_bus_clock_list_entry via82cxxx_type_two [] = {
+               /* speed */     /* 25 */        /* 33 */        /* 37.5 */      /* 41.5 */
+       {       XFER_UDMA_4,    0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00    },
+       {       XFER_UDMA_3,    0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00    },
+       {       XFER_UDMA_2,    0xE0,   0x20,   0xE0,   0x20,   0xE1,   0x31,   0xE1,   0x32    },
+       {       XFER_UDMA_1,    0xE1,   0x20,   0xE1,   0x20,   0xE2,   0x31,   0xE2,   0x32    },
+       {       XFER_UDMA_0,    0xE2,   0x20,   0xE2,   0x20,   0xE2,   0x31,   0xE2,   0x32    },
+
+       {       XFER_MW_DMA_2,  0x03,   0x20,   0x03,   0x20,   0x03,   0x31,   0x03,   0x32    },
+       {       XFER_MW_DMA_1,  0x03,   0x31,   0x03,   0x31,   0x03,   0x42,   0x03,   0x53    },
+       {       XFER_MW_DMA_0,  0x03,   0x31,   0x03,   0x31,   0x03,   0x42,   0x03,   0x53    },
+
+       {       XFER_PIO_4,     0x03,   0x20,   0x03,   0x20,   0x03,   0x31,   0x03,   0x32    },
+       {       XFER_PIO_3,     0x03,   0x31,   0x03,   0x31,   0x03,   0x42,   0x03,   0x53    },
+       {       XFER_PIO_2,     0x03,   0x65,   0x03,   0x65,   0x03,   0x87,   0x03,   0xA8    },
+       {       XFER_PIO_1,     0x03,   0x65,   0x03,   0x65,   0x03,   0x87,   0x03,   0xA8    },
+       {       XFER_PIO_0,     0x03,   0xA8,   0x03,   0xA8,   0x03,   0xDB,   0x03,   0xFE    },
+       {       0,              0x03,   0xA8,   0x03,   0xA8,   0x03,   0xDB,   0x03,   0xFE    }
+};
+
+struct chipset_bus_clock_list_entry via82cxxx_type_three [] = {
+               /* speed */     /* 25 */        /* 33 */        /* 37.5 */      /* 41.5 */
+       {       XFER_UDMA_4,    0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00    },
+       {       XFER_UDMA_3,    0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00    },
+       {       XFER_UDMA_2,    0xE0,   0x20,   0xE0,   0x20,   0xE1,   0x31,   0xE1,   0x32    },
+       {       XFER_UDMA_1,    0xE1,   0x20,   0xE1,   0x20,   0xE2,   0x31,   0xE2,   0x32    },
+       {       XFER_UDMA_0,    0xE2,   0x20,   0xE2,   0x20,   0xE2,   0x31,   0xE2,   0x32    },
+
+       {       XFER_MW_DMA_2,  0x03,   0x20,   0x03,   0x20,   0x03,   0x31,   0x03,   0x32    },
+       {       XFER_MW_DMA_1,  0x03,   0x31,   0x03,   0x31,   0x03,   0x42,   0x03,   0x53    },
+       {       XFER_MW_DMA_0,  0x03,   0x31,   0x03,   0x31,   0x03,   0x42,   0x03,   0x53    },
+
+       {       XFER_PIO_4,     0x03,   0x20,   0x03,   0x20,   0x03,   0x31,   0x03,   0x32    },
+       {       XFER_PIO_3,     0x03,   0x31,   0x03,   0x31,   0x03,   0x42,   0x03,   0x53    },
+       {       XFER_PIO_2,     0x03,   0x65,   0x03,   0x65,   0x03,   0x87,   0x03,   0xA8    },
+       {       XFER_PIO_1,     0x03,   0x65,   0x03,   0x65,   0x03,   0x87,   0x03,   0xA8    },
+       {       XFER_PIO_0,     0x03,   0xA8,   0x03,   0xA8,   0x03,   0xDB,   0x03,   0xFE    },
+       {       0,              0x03,   0xA8,   0x03,   0xA8,   0x03,   0xDB,   0x03,   0xFE    }
+};
+
+struct chipset_bus_clock_list_entry via82cxxx_type_four [] = {
+               /* speed */     /* 25 */        /* 33 */        /* 37.5 */      /* 41.5 */
+       {       XFER_UDMA_4,    0x00,   0x00,   0xE0,   0x20,   0xE1,   0x31,   0x00,   0x00    },
+       {       XFER_UDMA_3,    0x00,   0x00,   0xE1,   0x20,   0xE2,   0x31,   0x00,   0x00    },
+       {       XFER_UDMA_2,    0x00,   0x00,   0xE2,   0x20,   0xE4,   0x31,   0x00,   0x00    },
+       {       XFER_UDMA_1,    0x00,   0x00,   0xE4,   0x20,   0xE6,   0x31,   0x00,   0x00    },
+       {       XFER_UDMA_0,    0x00,   0x00,   0xE6,   0x20,   0xE6,   0x31,   0x00,   0x00    },
+
+       {       XFER_MW_DMA_2,  0x00,   0x00,   0x03,   0x20,   0x03,   0x31,   0x00,   0x00    },
+       {       XFER_MW_DMA_1,  0x00,   0x00,   0x03,   0x31,   0x03,   0x42,   0x00,   0x00    },
+       {       XFER_MW_DMA_0,  0x00,   0x00,   0x03,   0x31,   0x03,   0x42,   0x00,   0x00    },
+
+       {       XFER_PIO_4,     0x00,   0x00,   0x03,   0x20,   0x03,   0x31,   0x00,   0x00    },
+       {       XFER_PIO_3,     0x00,   0x00,   0x03,   0x31,   0x03,   0x42,   0x00,   0x00    },
+       {       XFER_PIO_2,     0x00,   0x00,   0x03,   0x65,   0x03,   0x87,   0x00,   0x00    },
+       {       XFER_PIO_1,     0x00,   0x00,   0x03,   0x65,   0x03,   0x87,   0x00,   0x00    },
+       {       XFER_PIO_0,     0x00,   0x00,   0x03,   0xA8,   0x03,   0xDB,   0x00,   0x00    },
+       {       0,              0x00,   0x00,   0x03,   0xA8,   0x03,   0xDB,   0x00,   0x00    }
+};
+
 static const struct {
        const char *name;
+       unsigned short vendor_id;
        unsigned short host_id;
 } ApolloHostChipInfo[] = {
-       { "VT 82C585 Apollo VP1/VPX",   PCI_DEVICE_ID_VIA_82C585, },
-       { "VT 82C595 Apollo VP2",       PCI_DEVICE_ID_VIA_82C595, },
-       { "VT 82C597 Apollo VP3",       PCI_DEVICE_ID_VIA_82C597_0, },
-       { "VT 82C598 Apollo MVP3",      PCI_DEVICE_ID_VIA_82C598_0, },
-       { "VT 82C598 Apollo MVP3",      PCI_DEVICE_ID_VIA_82C598_0, },
-       { "VT 82C680 Apollo P6",        PCI_DEVICE_ID_VIA_82C680, },
-       { "VT 82C691 Apollo Pro",       PCI_DEVICE_ID_VIA_82C691, },
-       { "VT 82C693 Apollo Pro Plus",  PCI_DEVICE_ID_VIA_82C693, },
-       { "Apollo MVP4",                PCI_DEVICE_ID_VIA_8501_0, },
-       { "VT 8371",                    PCI_DEVICE_ID_VIA_8371_0, },
-       { "VT 8601",                    PCI_DEVICE_ID_VIA_8601_0, },
+       { "VT 82C585 Apollo VP1/VPX",   PCI_VENDOR_ID_VIA,      PCI_DEVICE_ID_VIA_82C585, },
+       { "VT 82C595 Apollo VP2",       PCI_VENDOR_ID_VIA,      PCI_DEVICE_ID_VIA_82C595, },
+       { "VT 82C597 Apollo VP3",       PCI_VENDOR_ID_VIA,      PCI_DEVICE_ID_VIA_82C597_0, },
+       { "VT 82C598 Apollo MVP3",      PCI_VENDOR_ID_VIA,      PCI_DEVICE_ID_VIA_82C598_0, },
+       { "VT 82C598 Apollo MVP3",      PCI_VENDOR_ID_VIA,      PCI_DEVICE_ID_VIA_82C598_0, },
+       { "VT 82C680 Apollo P6",        PCI_VENDOR_ID_VIA,      PCI_DEVICE_ID_VIA_82C680, },
+       { "VT 82C691 Apollo Pro",       PCI_VENDOR_ID_VIA,      PCI_DEVICE_ID_VIA_82C691, },
+       { "VT 82C693 Apollo Pro Plus",  PCI_VENDOR_ID_VIA,      PCI_DEVICE_ID_VIA_82C693, },
+       { "Apollo MVP4",                PCI_VENDOR_ID_VIA,      PCI_DEVICE_ID_VIA_8501_0, },
+       { "VT 8371",                    PCI_VENDOR_ID_VIA,      PCI_DEVICE_ID_VIA_8371_0, },
+       { "VT 8601",                    PCI_VENDOR_ID_VIA,      PCI_DEVICE_ID_VIA_8601_0, },
+       { "AMD IronGate",               PCI_VENDOR_ID_AMD,      PCI_DEVICE_ID_AMD_FE_GATE_7006, },
 };
 
 #define NUM_APOLLO_ISA_CHIP_DEVICES    2
+#define VIA_FLAG_NULL                  0x00000000
 #define VIA_FLAG_CHECK_REV             0x00000001
 #define VIA_FLAG_ATA_66                        0x00000002
 
@@ -121,18 +221,20 @@ static const struct {
        unsigned short host_id;
        unsigned short isa_id;
        unsigned int flags;
+       struct chipset_bus_clock_list_entry * chipset_table;
 } ApolloISAChipInfo[] = {
-       { PCI_DEVICE_ID_VIA_82C585,     PCI_DEVICE_ID_VIA_82C586_1,     VIA_FLAG_CHECK_REV },
-       { PCI_DEVICE_ID_VIA_82C595,     PCI_DEVICE_ID_VIA_82C586_1,     VIA_FLAG_CHECK_REV },
-       { PCI_DEVICE_ID_VIA_82C597_0,   PCI_DEVICE_ID_VIA_82C586_1,     VIA_FLAG_CHECK_REV },
-       { PCI_DEVICE_ID_VIA_82C598_0,   PCI_DEVICE_ID_VIA_82C586_1,     VIA_FLAG_CHECK_REV },
-       { PCI_DEVICE_ID_VIA_82C598_0,   PCI_DEVICE_ID_VIA_82C596,       0 },
-       { PCI_DEVICE_ID_VIA_82C680,     PCI_DEVICE_ID_VIA_82C586_1,     VIA_FLAG_CHECK_REV },
-       { PCI_DEVICE_ID_VIA_82C691,     PCI_DEVICE_ID_VIA_82C596,       VIA_FLAG_ATA_66 },
-       { PCI_DEVICE_ID_VIA_82C693,     PCI_DEVICE_ID_VIA_82C596,       0 },
-       { PCI_DEVICE_ID_VIA_8501_0,     PCI_DEVICE_ID_VIA_82C686,       VIA_FLAG_ATA_66 },
-       { PCI_DEVICE_ID_VIA_8371_0,     PCI_DEVICE_ID_VIA_82C686,       VIA_FLAG_ATA_66 },
-       { PCI_DEVICE_ID_VIA_8601_0,     PCI_DEVICE_ID_VIA_8231,         VIA_FLAG_ATA_66 },
+       { PCI_DEVICE_ID_VIA_82C585,             PCI_DEVICE_ID_VIA_82C586_1,     VIA_FLAG_CHECK_REV,     via82cxxx_type_one      },
+       { PCI_DEVICE_ID_VIA_82C595,             PCI_DEVICE_ID_VIA_82C586_1,     VIA_FLAG_CHECK_REV,     via82cxxx_type_one      },
+       { PCI_DEVICE_ID_VIA_82C597_0,           PCI_DEVICE_ID_VIA_82C586_1,     VIA_FLAG_CHECK_REV,     via82cxxx_type_one      },
+       { PCI_DEVICE_ID_VIA_82C598_0,           PCI_DEVICE_ID_VIA_82C586_1,     VIA_FLAG_CHECK_REV,     via82cxxx_type_one      },
+       { PCI_DEVICE_ID_VIA_82C598_0,           PCI_DEVICE_ID_VIA_82C596,       VIA_FLAG_NULL,          via82cxxx_type_one      },
+       { PCI_DEVICE_ID_VIA_82C680,             PCI_DEVICE_ID_VIA_82C586_1,     VIA_FLAG_CHECK_REV,     via82cxxx_type_one      },
+       { PCI_DEVICE_ID_VIA_82C691,             PCI_DEVICE_ID_VIA_82C596,       VIA_FLAG_ATA_66,        via82cxxx_type_two      },
+       { PCI_DEVICE_ID_VIA_82C693,             PCI_DEVICE_ID_VIA_82C596,       VIA_FLAG_NULL,          via82cxxx_type_one      },
+       { PCI_DEVICE_ID_VIA_8501_0,             PCI_DEVICE_ID_VIA_82C686,       VIA_FLAG_ATA_66,        via82cxxx_type_two      },
+       { PCI_DEVICE_ID_VIA_8371_0,             PCI_DEVICE_ID_VIA_82C686,       VIA_FLAG_ATA_66,        via82cxxx_type_two      },
+       { PCI_DEVICE_ID_VIA_8601_0,             PCI_DEVICE_ID_VIA_8231,         VIA_FLAG_ATA_66,        via82cxxx_type_two      },
+       { PCI_DEVICE_ID_AMD_FE_GATE_7006,       PCI_DEVICE_ID_VIA_82C686,       VIA_FLAG_ATA_66,        via82cxxx_type_two      },
 };
 
 #define arraysize(x)   (sizeof(x)/sizeof(*(x)))
@@ -515,69 +617,40 @@ static int via_set_fifoconfig(ide_hwif_t *hwif)
 }
 
 #ifdef CONFIG_VIA82CXXX_TUNING
+static byte pci_bus_clock_list (byte speed, int ide_clock, struct chipset_bus_clock_list_entry * chipset_table)
+{
+       for ( ; chipset_table->xfer_speed ; chipset_table++)
+               if (chipset_table->xfer_speed == speed) {
+                       switch(ide_clock) {
+                               case 25: return chipset_table->chipset_settings_25;
+                               case 33: return chipset_table->chipset_settings_33;
+                               case 37: return chipset_table->chipset_settings_37;
+                               case 41: return chipset_table->chipset_settings_41;
+                               default: break;
+                       }
+               }
+       return 0x00;
+}
 
-struct chipset_bus_clock_list_entry {
-       unsigned short  bus_speed;
-       byte            xfer_speed;
-       byte            chipset_settings;
-};
-
-PCI_DEVICE_ID_VIA_82C586_1
-PCI_DEVICE_ID_VIA_82C596
-PCI_DEVICE_ID_VIA_82C686
-PCI_DEVICE_ID_VIA_8231
-
-PCI_DEVICE_ID_VIA_82C586_1     TYPE_1
-PCI_DEVICE_ID_VIA_82C596       TYPE_2
-PCI_DEVICE_ID_VIA_82C686       TYPE_2
-PCI_DEVICE_ID_VIA_82C596       TYPE_3
-PCI_DEVICE_ID_VIA_82C686       TYPE_3
-PCI_DEVICE_ID_VIA_8231         TYPE_4
-
-struct chipset_bus_clock_list_entry ultra_33_base [] = {
-{ TYPE_1,25,0x00,0x00,0x60,0x61,0x62,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_1,33,0x00,0x00,0x60,0x61,0x62,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_1,37,0x00,0x00,0x60,0x61,0x62,0x03,0x21,0x32,0x76,0x76,0xA9 },
-{ TYPE_2,25,0x00,0x00,0xE0,0xE1,0xE2,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_2,33,0x00,0x00,0xE0,0xE1,0xE2,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_2,37,0x00,0x00,0xE1,0xE2,0xE2,0x03,0x31,0x42,0x87,0x87,0xDB },
-{ TYPE_2,41,0x00,0x00,0xE1,0xE2,0xE2,0x03,0x32,0x53,0xA8,0xA8,0xFE },
-{ TYPE_3,25,0x00,0x00,0xE0,0xE1,0xE2,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_3,33,0x00,0x00,0xE0,0xE1,0xE2,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_3,37,0x00,0x00,0xE1,0xE2,0xE2,0x03,0x31,0x42,0x87,0x87,0xDB },
-{ TYPE_3,41,0x00,0x00,0xE1,0xE2,0xE2,0x03,0x32,0x53,0xA8,0xA8,0xFE },
-{ TYPE_4,0,0,0,0,0,0,0,0,0,0,0,0 },
-{ 0,0,0,0,0,0,0,0,0,0,0,0,0 }
-};
-
-struct chipset_bus_clock_list_entry timing_66_base [] = {
-       { 37,   XFER_PIO_4,     0x21 },
-       { 37,   XFER_PIO_3,     0x32 },
-       { 37,   XFER_PIO_2,     0x76 },
-       { 37,   XFER_PIO_1,     0x76 },
-       { 37,   XFER_PIO_0,     0xA9 },
-       { ANY,  XFER_PIO_4,     0x20 },
-       { ANY,  XFER_PIO_3,     0x31 },
-       { ANY,  XFER_PIO_2,     0x65 },
-       { ANY,  XFER_PIO_1,     0x65 },
-       { ANY,  XFER_PIO_0,     0xA8 },
-};
-
-static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+static byte pci_bus_clock_list_ultra (byte speed, int ide_clock, struct chipset_bus_clock_list_entry * chipset_table)
 {
        for ( ; chipset_table->xfer_speed ; chipset_table++)
                if (chipset_table->xfer_speed == speed) {
-                       return chipset_table->chipset_settings;
+                       switch(ide_clock) {
+                               case 25: return chipset_table->ultra_settings_25;
+                               case 33: return chipset_table->ultra_settings_33;
+                               case 37: return chipset_table->ultra_settings_37;
+                               case 41: return chipset_table->ultra_settings_41;
+                               default: break;
+                       }
                }
-       return 0x01208585;
+       return 0x00;
 }
 
 static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed)
 {
-       struct hd_driveid *id   = drive->id;
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = hwif->pci_dev;
-       unsigned long dma_base  = hwif->dma_base;
        byte unit               = (drive->select.b.unit & 0x01);
        int drive_number        = ((hwif->channel ? 2 : 0) + unit);
 
@@ -587,43 +660,23 @@ static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed)
        byte ultra              = 0x00;
        int                     err;
 
-       int bus_speed           = ide_system_bus_speed();
+       int bus_speed           = system_bus_clock();
 
        switch(drive_number) {
-               case 0: ata2_pci = 0x48; ata3_pci = 0x50; break;
-               case 1: ata2_pci = 0x49; ata3_pci = 0x51; break;
-               case 2: ata2_pci = 0x4a; ata3_pci = 0x52; break;
-               case 3: ata2_pci = 0x4b; ata3_pci = 0x53; break;
+               case 0: ata2_pci = 0x4b; ata3_pci = 0x53; break;
+               case 1: ata2_pci = 0x4a; ata3_pci = 0x52; break;
+               case 2: ata2_pci = 0x49; ata3_pci = 0x51; break;
+               case 3: ata2_pci = 0x48; ata3_pci = 0x50; break;
                default:
                        return -1;
        }
 
        pci_read_config_byte(dev, ata2_pci, &timing);
-       pci_read_config_byte(dev, ata3_pci, &ultra);
-
-       switch(speed) {
-               case XFER_UDMA_4:
-               case XFER_UDMA_3:
-               case XFER_UDMA_2:
-               case XFER_UDMA_1:
-               case XFER_UDMA_0:
-               case XFER_MW_DMA_2:
-               case XFER_MW_DMA_1:
-               case XFER_MW_DMA_0:
-               case XFER_SW_DMA_2:
-               case XFER_SW_DMA_1:
-               case XFER_SW_DMA_0:
-               case XFER_PIO_4:
-               case XFER_PIO_3:
-               case XFER_PIO_2:
-               case XFER_PIO_1:
-               case XFER_PIO_0:
-               case XFER_PIO_SLOW:
-               default:
-                       break;
-       }
-
+       timing = pci_bus_clock_list(speed, bus_speed, via82cxxx_table);
        pci_write_config_byte(dev, ata2_pci, timing);
+
+       pci_read_config_byte(dev, ata3_pci, &ultra);
+       ultra = pci_bus_clock_list_ultra(speed, bus_speed, via82cxxx_table);
        pci_write_config_byte(dev, ata3_pci, ultra);
 
        err = ide_config_drive_speed(drive, speed);
@@ -830,6 +883,8 @@ unsigned int __init pci_init_via82cxxx (struct pci_dev *dev, const char *name)
 
                        if (ata33 | ata66)
                                printk(" Chipset Core ATA-%s", ata66 ? "66" : "33");
+
+                       via82cxxx_table = ApolloISAChipInfo[j].chipset_table;
                }
                printk("\n");
        }
@@ -847,8 +902,11 @@ unsigned int __init pci_init_via82cxxx (struct pci_dev *dev, const char *name)
 
 unsigned int __init ata66_via82cxxx (ide_hwif_t *hwif)
 {
-       /* (Jeff Garzik) FIXME!!! for MVP4 */
-       return 0;
+       byte ata66      = 0;
+       byte ata66reg   = hwif->channel ? 0x50 : 0x52;
+       pci_read_config_byte(hwif->pci_dev, ata66reg, &ata66);
+
+       return ((ata66 & 0x04) ? 1 : 0);
 }
 
 void __init ide_init_via82cxxx (ide_hwif_t *hwif)
index 2c749c69d718571f2fca7fb42d49523d6a9a64f2..5774080fe454ec26aca72d2a0f276236803c69da 100644 (file)
@@ -64,7 +64,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
index c9b4c54dab889c148e817540af882cc0696e9bb1..b91df4a6d0dd1cc1f656281a977b6dd570c43ebc 100644 (file)
  *
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
index 97f374fa6529389c9ac5a80f0b2356b53dd0d491..fcefa3d6850231e13ed94cf8073b9d4ce74149ae 100644 (file)
 #include <linux/param.h>
 #include <linux/module.h>
 #include <linux/string.h>
-#include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kdev_t.h>
 #include <linux/kernel.h>
 #include <linux/locks.h>
 #include <linux/major.h>
 #include <linux/malloc.h>
-#include <linux/stat.h>
-#include <linux/tty.h>
 #include <linux/ctype.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
index 336a66949eda65b6db0cb6288957ed93bc4e5474..ce573e312b65577ffff2c758fb4c918f1ef9978e 100644 (file)
@@ -439,7 +439,7 @@ static int __devinit rtl8139_init_pci (struct pci_dev *pdev, void **ioaddr_out)
        u8 tmp8;
        int rc;
        u32 pio_start, pio_end, pio_flags, pio_len;
-       u32 mmio_start, mmio_end, mmio_flags, mmio_len;
+       unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
 
        DPRINTK ("ENTER\n");
 
index 04bfab3c8a3549de738c54057dbb2bf3c482a139..466a83dbc41639db9d7dfead2760168f669c79fc 100644 (file)
@@ -683,6 +683,46 @@ static struct net_device tr0_dev = {
 #define        NEXT_DEV        (&sbni0_dev)
 #endif 
        
+/* S/390 channels */
+#ifdef CONFIG_CTC
+    extern int ctc_probe(struct net_device *dev);
+    static struct net_device ctc7_dev =
+       {"ctc7", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV,  ctc_probe};
+    static struct net_device ctc6_dev =
+       {"ctc6", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc7_dev, ctc_probe};
+    static struct net_device ctc5_dev =
+       {"ctc5", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc6_dev, ctc_probe};
+    static struct net_device ctc4_dev =
+       {"ctc4", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc5_dev, ctc_probe};
+    static struct net_device ctc3_dev =
+       {"ctc3", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc4_dev, ctc_probe};
+    static struct net_device ctc2_dev =
+       {"ctc2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc3_dev, ctc_probe};
+    static struct net_device ctc1_dev =
+       {"ctc1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc2_dev, ctc_probe};
+    static struct net_device ctc0_dev =
+       {"ctc0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc1_dev, ctc_probe}; 
+
+    static struct net_device escon7_dev =
+       {"escon7", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc0_dev,   ctc_probe};
+    static struct net_device escon6_dev =
+       {"escon6", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon7_dev, ctc_probe};
+    static struct net_device escon5_dev =
+       {"escon5", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon6_dev, ctc_probe};
+    static struct net_device escon4_dev =
+       {"escon4", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon5_dev, ctc_probe};
+    static struct net_device escon3_dev =
+       {"escon3", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon4_dev, ctc_probe};
+    static struct net_device escon2_dev =
+       {"escon2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon3_dev, ctc_probe};
+    static struct net_device escon1_dev =
+       {"escon1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon2_dev, ctc_probe};
+    static struct net_device escon0_dev =
+       {"escon0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon1_dev, ctc_probe}; 
+
+#undef  NEXT_DEV
+#define NEXT_DEV        (&escon0_dev)                                  
+#endif  
        
        
 /*
index 5ef42cf9c62a189b35beb6fcf66c01b36379a011..9fd9a275ee2a94da6cf9a593fbf15be1ac609925 100644 (file)
                     : Don't call netif_wake_queue() in net_send_packet()
                     : Fixed an out-of-mem bug in dma_rx()
                     : Updated Documentation/cs89x0.txt
+
+  Andrew Morton     : andrewm@uow.edu.au / Kernel 2.3.99-pre1
+                    : Use skb_reserve to longword align IP header (two places)
+                    : Remove a delay loop from dma_rx()
+                    : Replace '100' with HZ
+                    : Clean up a couple of skb API abuses
+                    : Added 'cs89x0_dma=N' kernel boot option
+                    : Correctly initialise lp->lock in non-module compile
+
+  Andrew Morton     : andrewm@uow.edu.au / Kernel 2.3.99-pre4-1
+                    : MOD_INC/DEC race fix (see
+                    : http://www.uwsg.indiana.edu/hypermail/linux/kernel/0003.3/1532.html)
+
 */
 
 static char *version =
-"cs89x0.c: (kernel 2.3.48) Russell Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>\n";
+"cs89x0.c: v2.3.99-pre1-2 Russell Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>\n";
 
 /* ======================= end of configuration ======================= */
 
@@ -121,7 +134,7 @@ static unsigned int netcard_portlist[] __initdata =
    { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
 
 #if DEBUGGING
-static unsigned int net_debug = 5;
+static unsigned int net_debug = DEBUGGING;
 #else
 #define net_debug 0    /* gcc will remove all the debug code for us */
 #endif
@@ -190,6 +203,21 @@ static void release_dma_buff(struct net_local *lp);
 /* Example routines you must write ;->. */
 #define tx_done(dev) 1
 
+/*
+ * Permit 'cs89x0_dma=N' in the kernel boot environment
+ */
+#if !defined(MODULE) && (ALLOW_DMA != 0)
+static int g_cs89x0_dma;
+
+static int __init dma_fn(char *str)
+{
+       g_cs89x0_dma = simple_strtol(str,NULL,0);
+       return 1;
+}
+
+__setup("cs89x0_dma=", dma_fn);
+#endif /* !defined(MODULE) && (ALLOW_DMA != 0) */
+
 \f
 /* Check for a network adaptor of this type, and return '0' iff one exists.
    If dev->base_addr == 0, probe all likely locations.
@@ -318,7 +346,17 @@ cs89x0_probe1(struct net_device *dev, int ioaddr)
                        retval = ENOMEM;
                        goto out;
                }
-                memset(dev->priv, 0, sizeof(struct net_local));
+               lp = (struct net_local *)dev->priv;
+               memset(lp, 0, sizeof(*lp));
+               spin_lock_init(&lp->lock);
+#if !defined(MODULE) && (ALLOW_DMA != 0)
+               if (g_cs89x0_dma)
+               {
+                       lp->use_dma = 1;
+                       lp->dma = g_cs89x0_dma;
+                       lp->dmasize = 16;       /* Could make this an option... */
+               }
+#endif
         }
        lp = (struct net_local *)dev->priv;
 
@@ -612,12 +650,6 @@ dma_rx(struct net_device *dev)
        int status, length;
        unsigned char *bp = lp->rx_dma_ptr;
 
-       {
-               int i;
-               for (i = 0; i < 1000; i++)
-                       ;
-       }
-
        status = bp[0] + (bp[1]<<8);
        length = bp[2] + (bp[3]<<8);
        bp += 4;
@@ -632,7 +664,7 @@ dma_rx(struct net_device *dev)
        }
 
        /* Malloc up new buffer. */
-       skb = alloc_skb(length, GFP_ATOMIC);
+       skb = dev_alloc_skb(length + 2);
        if (skb == NULL) {
                if (net_debug)  /* I don't think we want to do this to a stressed system */
                        printk("%s: Memory squeeze, dropping packet.\n", dev->name);
@@ -645,8 +677,7 @@ skip_this_frame:
                lp->rx_dma_ptr = bp;
                return;
        }
-
-       skb->len = length;
+       skb_reserve(skb, 2);    /* longword align L3 header */
        skb->dev = dev;
 
        if (bp + length > lp->end_dma_buff) {
@@ -720,7 +751,7 @@ control_dc_dc(struct net_device *dev, int on_not_off)
        writereg(dev, PP_SelfCTL, selfcontrol);
 
        /* Wait for the DC/DC converter to power up - 500ms */
-       while (jiffies - timenow < 100)
+       while (jiffies - timenow < HZ)
                ;
 
 }
@@ -914,6 +945,9 @@ net_open(struct net_device *dev)
        struct net_local *lp = (struct net_local *)dev->priv;
        int result = 0;
        int i;
+       int ret;
+
+       MOD_INC_USE_COUNT;
 
        if (dev->irq < 2) {
                /* Allow interrupts to be generated by the chip */
@@ -938,13 +972,15 @@ net_open(struct net_device *dev)
                        writereg(dev, PP_BusCTL, 0);    /* disable interrupts. */
                        if (net_debug)
                                printk("cs89x0: can't get an interrupt\n");
-                       return -EAGAIN;
+                       ret = -EAGAIN;
+                       goto bad_out;
                }
        } else {
                if (((1 << dev->irq) & lp->irq_map) == 0) {
                        printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
                                dev->name, dev->irq, lp->irq_map);
-                       return -EAGAIN;
+                       ret = -EAGAIN;
+                       goto bad_out;
                }
 /* FIXME: Cirrus' release had this: */
                writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
@@ -956,7 +992,8 @@ net_open(struct net_device *dev)
                if (request_irq(dev->irq, &net_interrupt, 0, "cs89x0", dev)) {
                        if (net_debug)
                                printk("cs89x0: request_irq(%d) failed\n", dev->irq);
-                       return -EAGAIN;
+                       ret = -EAGAIN;
+                       goto bad_out;
                }
        }
 
@@ -1032,7 +1069,8 @@ net_open(struct net_device *dev)
 #endif
                 writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
                 free_irq(dev->irq, dev);
-               return -EAGAIN;
+               ret = -EAGAIN;
+               goto bad_out;
        }
 
         /* set the hardware to the configured choice */
@@ -1125,11 +1163,13 @@ net_open(struct net_device *dev)
                 | dma_busctl(dev)
 #endif
                  );
-        MOD_INC_USE_COUNT;
         netif_start_queue(dev);
        if (net_debug)
                printk("cs89x0: net_open() succeeded\n");
        return 0;
+bad_out:
+       MOD_DEC_USE_COUNT;
+       return ret;
 }
 
 static void net_timeout(struct net_device *dev)
@@ -1317,7 +1357,7 @@ net_rx(struct net_device *dev)
        }
 
        /* Malloc up new buffer. */
-       skb = alloc_skb(length, GFP_ATOMIC);
+       skb = dev_alloc_skb(length + 2);
        if (skb == NULL) {
 #if 0          /* Again, this seems a cruel thing to do */
                printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
@@ -1325,10 +1365,10 @@ net_rx(struct net_device *dev)
                lp->stats.rx_dropped++;
                return;
        }
-       skb->len = length;
+       skb_reserve(skb, 2);    /* longword align L3 header */
        skb->dev = dev;
 
-       insw(ioaddr + RX_FRAME_PORT, skb->data, length >> 1);
+       insw(ioaddr + RX_FRAME_PORT, skb_put(skb, length), length >> 1);
        if (length & 1)
                skb->data[length-1] = inw(ioaddr + RX_FRAME_PORT);
 
index a70c1a8db66fd5a52546b93e84f235f05ec722f9..c2cb4dbc62cb45619865efe60c348f405d7c9f68 100644 (file)
@@ -19,7 +19,7 @@
  * PPP driver, written by Michael Callahan and Al Longyear, and
  * subsequently hacked by Paul Mackerras.
  *
- * ==FILEVERSION 20000406==
+ * ==FILEVERSION 20000412==
  */
 
 #include <linux/config.h>
@@ -206,7 +206,7 @@ static ssize_t ppp_file_write(struct ppp_file *pf, const char *buf,
                              size_t count);
 static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
                                unsigned int cmd, unsigned long arg);
-static void ppp_xmit_process(struct ppp *ppp, int wakeup);
+static void ppp_xmit_process(struct ppp *ppp);
 static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb);
 static void ppp_push(struct ppp *ppp);
 static void ppp_channel_push(struct channel *pch);
@@ -427,7 +427,7 @@ static ssize_t ppp_file_write(struct ppp_file *pf, const char *buf,
 
        switch (pf->kind) {
        case INTERFACE:
-               ppp_xmit_process(PF_TO_PPP(pf), 0);
+               ppp_xmit_process(PF_TO_PPP(pf));
                break;
        case CHANNEL:
                ppp_channel_push(PF_TO_CHANNEL(pf));
@@ -774,7 +774,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        netif_stop_queue(dev);
        skb_queue_tail(&ppp->file.xq, skb);
-       ppp_xmit_process(ppp, 0);
+       ppp_xmit_process(ppp);
        return 0;
 
  outf:
@@ -860,13 +860,12 @@ ppp_net_init(struct net_device *dev)
  * that can now be done.
  */
 static void
-ppp_xmit_process(struct ppp *ppp, int wakeup)
+ppp_xmit_process(struct ppp *ppp)
 {
        struct sk_buff *skb;
 
        ppp_xmit_lock(ppp);
-       if (wakeup)
-               ppp_push(ppp);
+       ppp_push(ppp);
        while (ppp->xmit_pending == 0
               && (skb = skb_dequeue(&ppp->file.xq)) != 0)
                ppp_send_frame(ppp, skb);
@@ -1018,14 +1017,12 @@ ppp_push(struct ppp *ppp)
                spin_lock_bh(&pch->downl);
                if (pch->chan) {
                        if (pch->chan->ops->start_xmit(pch->chan, skb))
-                               skb = 0;
+                               ppp->xmit_pending = 0;
                } else {
                        /* channel got unregistered */
                        kfree_skb(skb);
-                       skb = 0;
-               }
-               if (skb_queue_len(&pch->file.xq) == 0 && skb == 0)
                        ppp->xmit_pending = 0;
+               }
                spin_unlock_bh(&pch->downl);
                return;
        }
@@ -1196,6 +1193,7 @@ static void
 ppp_channel_push(struct channel *pch)
 {
        struct sk_buff *skb;
+       struct ppp *ppp;
 
        spin_lock_bh(&pch->downl);
        if (pch->chan != 0) {
@@ -1212,6 +1210,14 @@ ppp_channel_push(struct channel *pch)
                skb_queue_purge(&pch->file.xq);
        }
        spin_unlock_bh(&pch->downl);
+       /* see if there is anything from the attached unit to be sent */
+       if (skb_queue_len(&pch->file.xq) == 0) {
+               read_lock_bh(&pch->upl);
+               ppp = pch->ppp;
+               if (ppp != 0)
+                       ppp_xmit_process(ppp);
+               read_unlock_bh(&pch->upl);
+       }
 }
 
 /*
@@ -1792,18 +1798,10 @@ void
 ppp_output_wakeup(struct ppp_channel *chan)
 {
        struct channel *pch = chan->ppp;
-       struct ppp *ppp;
 
        if (pch == 0)
                return;
        ppp_channel_push(pch);
-       if (skb_queue_len(&pch->file.xq) == 0) {
-               read_lock_bh(&pch->upl);
-               ppp = pch->ppp;
-               if (ppp != 0)
-                       ppp_xmit_process(ppp, 1);
-               read_unlock_bh(&pch->upl);
-       }
 }
 
 /*
index f244874e4d2e487a76138b2ed3719a6f9e67bde8..2bc0a8652187634e3f40ff7790ba317d1ce49f5c 100644 (file)
@@ -88,8 +88,10 @@ void t21142_timer(unsigned long data)
                next_tick = 3*HZ;
        }
 
-       tp->timer.expires = RUN_AT(next_tick);
-       add_timer(&tp->timer);
+       /* mod_timer synchronizes us with potential add_timer calls
+        * from interrupts.
+        */
+       mod_timer(&tp->timer, RUN_AT(next_tick));
 }
 
 
@@ -108,7 +110,10 @@ void t21142_start_nway(struct net_device *dev)
                           dev->name, csr14);
        outl(0x0001, ioaddr + CSR13);
        outl(csr14, ioaddr + CSR14);
-       tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0);
+       if (tp->chip_id == PNIC2)
+         tp->csr6 = 0x01a80000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0);
+       else 
+         tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0);
        tulip_outl_CSR6(tp, tp->csr6);
        if (tp->mtable  &&  tp->mtable->csr15dir) {
                outl(tp->mtable->csr15dir, ioaddr + CSR15);
index 0a40abb48426d5934c740f8af35a244d85bb0291..16e048b828ee28ac9c99cbdda063974c94bd24e0 100644 (file)
@@ -171,8 +171,10 @@ void tulip_timer(unsigned long data)
        }
        break;
        }
-       tp->timer.expires = RUN_AT(next_tick);
-       add_timer(&tp->timer);
+       /* mod_timer synchronizes us with potential add_timer calls
+        * from interrupts.
+        */
+       mod_timer(&tp->timer, RUN_AT(next_tick));
 }
 
 
@@ -188,8 +190,7 @@ void mxic_timer(unsigned long data)
                           inl(ioaddr + CSR12));
        }
        if (next_tick) {
-               tp->timer.expires = RUN_AT(next_tick);
-               add_timer(&tp->timer);
+               mod_timer(&tp->timer, RUN_AT(next_tick));
        }
 }
 
@@ -205,7 +206,9 @@ void comet_timer(unsigned long data)
                printk(KERN_DEBUG "%s: Comet link status %4.4x partner capability "
                           "%4.4x.\n",
                           dev->name, inl(ioaddr + 0xB8), inl(ioaddr + 0xC8));
-       tp->timer.expires = RUN_AT(next_tick);
-       add_timer(&tp->timer);
+       /* mod_timer synchronizes us with potential add_timer calls
+        * from interrupts.
+        */
+       mod_timer(&tp->timer, RUN_AT(next_tick));
 }
 
index 196dcf7f665444ed40ed55c24a6b6f32eec954e3..ca99883281d3acfb3866bd9672b0a2eaf186f27c 100644 (file)
@@ -19,7 +19,7 @@
 
 */
 
-static const char version[] = "Linux Tulip driver version 0.9.4.2 (Mar 21, 2000)\n";
+static const char version[] = "Linux Tulip driver version 0.9.4.3 (Apr 14, 2000)\n";
 
 #include <linux/module.h>
 #include "tulip.h"
index cdf4092fe0d683a2d2cb96a7e02b0cf9b033c6c3..9e11b6a82407407fca52467a0b8824ee4874f002 100644 (file)
 1191  Artop Electronic Corp
        0004  ATP8400
        0005  ATP850UF
+       0006  ATP860 NO-BIOS
+       0007  ATP860
        8002  AEC6710 SCSI-2 Host Adapter
        8010  AEC6712UW SCSI
        8020  AEC6712U SCSI
index b2fc1ffc3e8f3498c9d4cee4c417e83d26c035e2..eb2efac83308c7022f036881e96527b5554598f8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.41 2000/03/13 03:54:17 davem Exp $
+/* $Id: sab82532.c,v 1.42 2000/04/13 07:22:35 ecd Exp $
  * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -176,12 +176,22 @@ static struct ebrg_struct ebrg_table[] = {
 
 #define NR_EBRG_VALUES (sizeof(ebrg_table)/sizeof(struct ebrg_struct))
 
-#define SAB82532_MAX_TEC_DELAY 2000    /* 2 ms */
+#define SAB82532_MAX_TEC_TIMEOUT 200000        /* 1 character time (at 50 baud) */
+#define SAB82532_MAX_CEC_TIMEOUT  50000        /* 2.5 TX CLKs (at 50 baud) */
 
 static __inline__ void sab82532_tec_wait(struct sab82532 *info)
 {
-       int count = SAB82532_MAX_TEC_DELAY;
-       while ((readb(&info->regs->r.star) & SAB82532_STAR_TEC) && --count)
+       int timeout = info->tec_timeout;
+
+       while ((readb(&info->regs->r.star) & SAB82532_STAR_TEC) && --timeout)
+               udelay(1);
+}
+
+static __inline__ void sab82532_cec_wait(struct sab82532 *info)
+{
+       int timeout = info->cec_timeout;
+
+       while ((readb(&info->regs->r.star) & SAB82532_STAR_CEC) && --timeout)
                udelay(1);
 }
 
@@ -209,8 +219,7 @@ static __inline__ void sab82532_start_tx(struct sab82532 *info)
        }
 
        /* Issue a Transmit Frame command. */
-       if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
-               udelay(1);
+       sab82532_cec_wait(info);
        writeb(SAB82532_CMDR_XF, &info->regs->w.cmdr);
 
 out:
@@ -277,8 +286,7 @@ static void batten_down_hatches(struct sab82532 *info)
        tmp = readb(&info->regs->rw.rfc);
        tmp &= ~(SAB82532_RFC_RFDF);
        writeb(tmp, &info->regs->rw.rfc);
-       if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
-               udelay(1);
+       sab82532_cec_wait(info);
        writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
 
 #ifndef __sparc_v9__
@@ -293,8 +301,7 @@ static void batten_down_hatches(struct sab82532 *info)
         * Reset FIFO to character + status mode.
         */
        writeb(saved_rfc, &info->regs->w.rfc);
-       if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
-               udelay(1);
+       sab82532_cec_wait(info);
        writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
 }
 
@@ -345,16 +352,19 @@ static inline void receive_chars(struct sab82532 *info,
                free_fifo++;
        }
 
-       if (stat->sreg.isr0 & SAB82532_ISR0_TCD) {
-               count = readb(&info->regs->r.rbcl) & (info->recv_fifo_size - 1);
-               free_fifo++;
-       }
-
        /* Issue a FIFO read command in case we where idle. */
        if (stat->sreg.isr0 & SAB82532_ISR0_TIME) {
-               if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
-                       udelay(1);
+               sab82532_cec_wait(info);
                writeb(SAB82532_CMDR_RFRD, &info->regs->w.cmdr);
+               /* Wait for command execution, to catch the TCD below. */
+               sab82532_cec_wait(info);
+       }
+
+       if (stat->sreg.isr0 & SAB82532_ISR0_TCD) {
+               count = readb(&info->regs->r.rbcl) & (info->recv_fifo_size - 1);
+               if (count == 0)
+                       count = info->recv_fifo_size;
+               free_fifo++;
        }
 
        if (stat->sreg.isr0 & SAB82532_ISR0_RFO) {
@@ -370,8 +380,7 @@ static inline void receive_chars(struct sab82532 *info,
 
        /* Issue Receive Message Complete command. */
        if (free_fifo) {
-               if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
-                       udelay(1);
+               sab82532_cec_wait(info);
                writeb(SAB82532_CMDR_RMC, &info->regs->w.cmdr);
        }
 
@@ -451,8 +460,7 @@ static inline void transmit_chars(struct sab82532 *info,
        }
 
        /* Issue a Transmit Frame command. */
-       if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
-               udelay(1);
+       sab82532_cec_wait(info);
        writeb(SAB82532_CMDR_XF, &info->regs->w.cmdr);
 
        if (info->xmit_cnt < WAKEUP_CHARS)
@@ -709,18 +717,14 @@ sab82532_init_line(struct sab82532 *info)
        /*
         * Wait for any commands or immediate characters
         */
-       if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
-               udelay(1);
+       sab82532_cec_wait(info);
        sab82532_tec_wait(info);
 
        /*
         * Clear the FIFO buffers.
         */
-       if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
-               udelay(1);
        writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
-       if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
-               udelay(1);
+       sab82532_cec_wait(info);
        writeb(SAB82532_CMDR_XRES, &info->regs->w.cmdr);
 
        /*
@@ -997,10 +1001,15 @@ static void change_speed(struct sab82532 *info)
        ebrg |= (ebrg_table[i].m << 6);
 
        info->baud = ebrg_table[i].baud;
-       if (info->baud)
+       if (info->baud) {
                info->timeout = (info->xmit_fifo_size * HZ * bits) / info->baud;
-       else
+               info->tec_timeout = (10 * 1000000) / info->baud;
+               info->cec_timeout = info->tec_timeout >> 2;
+       } else {
                info->timeout = 0;
+               info->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
+               info->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
+       }
        info->timeout += HZ / 50;               /* Add .02 seconds of slop */
 
        /* CTS flow control flags */
@@ -1037,8 +1046,7 @@ static void change_speed(struct sab82532 *info)
                                            SAB82532_ISR0_TIME;
 
        save_flags(flags); cli();
-       if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
-               udelay(1);
+       sab82532_cec_wait(info);
        sab82532_tec_wait(info);
        writeb(dafo, &info->regs->w.dafo);
        writeb(ebrg & 0xff, &info->regs->w.bgr);
@@ -2163,7 +2171,7 @@ static void __init sab82532_kgdb_hook(int line)
 
 static inline void __init show_serial_version(void)
 {
-       char *revision = "$Revision: 1.41 $";
+       char *revision = "$Revision: 1.42 $";
        char *version, *p;
 
        version = strchr(revision, ' ');
@@ -2267,6 +2275,8 @@ int __init sab82532_init(void)
                info->custom_divisor = 16;
                info->close_delay = 5*HZ/10;
                info->closing_wait = 30*HZ;
+               info->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
+               info->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
                info->x_char = 0;
                info->event = 0;        
                info->blocked_open = 0;
@@ -2550,8 +2560,7 @@ sab82532_console_setup(struct console *con, char *options)
                info->flags |= ASYNC_CHECK_CD;
 
        save_flags(flags); cli();
-       if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
-               udelay(1);
+       sab82532_cec_wait(info);
        sab82532_tec_wait(info);
        writeb(dafo, &info->regs->w.dafo);
        writeb(ebrg & 0xff, &info->regs->w.bgr);
index 1a209c14e5dee4d0c180e841b508b3f3c7b5187b..832a2d9f43c2619ffe661391c4810d5413997243 100644 (file)
@@ -547,6 +547,7 @@ static ide_driver_t idescsi_driver = {
        idescsi_open,           /* open */
        idescsi_ide_release,    /* release */
        NULL,                   /* media_change */
+       NULL,                   /* revalidate */
        NULL,                   /* pre_reset */
        NULL,                   /* capacity */
        NULL,                   /* special */
index ac162c564c7caa0ee807b2e92b3bc9f372e4717a..280cda345991dbb2c4ffe18c68bc4390cd5ddd00 100644 (file)
@@ -166,6 +166,37 @@ static int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd,
                                return -EFAULT;
                        return 0;
                }
+               case HDIO_GETGEO_BIG:
+               {
+                       struct hd_big_geometry *loc = (struct hd_big_geometry *) arg;
+
+                       if(!loc)
+                               return -EINVAL;
+
+                       host = rscsi_disks[DEVICE_NR(dev)].device->host;
+
+                       /* default to most commonly used values */
+
+                       diskinfo[0] = 0x40;
+                       diskinfo[1] = 0x20;
+                       diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11;
+
+                       /* override with calculated, extended default, or driver values */
+
+                       if(host->hostt->bios_param != NULL)
+                               host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)],
+                                           dev,
+                                           &diskinfo[0]);
+                       else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)],
+                                       dev, &diskinfo[0]);
+
+                       if (put_user(diskinfo[0], &loc->heads) ||
+                               put_user(diskinfo[1], &loc->sectors) ||
+                               put_user(diskinfo[2], (unsigned int *) &loc->cylinders) ||
+                               put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start))
+                               return -EFAULT;
+                       return 0;
+               }
                case BLKGETSIZE:   /* Return device size */
                        if (!arg)
                                return -EINVAL;
index 0ebdf61245bf2718bf3580022a64317d41c0282c..6350d96d4486045b0795263e8b052a1cbc6e37c1 100644 (file)
@@ -72,7 +72,7 @@ obj-$(CONFIG_SOUND_MSNDCLAS)  += msnd.o msnd_classic.o
 obj-$(CONFIG_SOUND_MSNDPIN)    += msnd.o msnd_pinnacle.o
 obj-$(CONFIG_SOUND_VWSND)      += vwsnd.o
 obj-$(CONFIG_SOUND_NM256)      += nm256_audio.o ac97.o
-obj-$(CONFIG_SOUND_NM256)      += i810_audio.o ac97.o
+obj-$(CONFIG_SOUND_ICH)                += i810_audio.o ac97.o
 obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o
 obj-$(CONFIG_SOUND_CMPCI)      += cmpci.o
 obj-$(CONFIG_SOUND_ES1370)     += es1370.o
index a0a12fc8143016a61980afb9a29e28db554ee6f7..13e45611173d2dd2f9f9d777efdb93944b83ad03 100644 (file)
@@ -36,7 +36,7 @@
  * 26-03-2000 Fixed acer, esstype and sm_games module options.
  *  Alessandro Zummo <azummo@ita.flashnet.it>
  *
- * 27-03-2000 ISAPnP multiple card detection, cleanup, and reorg.
+ * 12-04-2000 ISAPnP cleanup, reorg, fixes, and multiple card support.
  *  Thanks to Gaël Quéri and Alessandro Zummo for testing and fixes.
  *  Paul E. Laufer <pelaufer@csupomona.edu>
  *
@@ -177,7 +177,8 @@ static struct address_info cfg[SB_CARDS_MAX];
 static struct address_info cfg_mpu[SB_CARDS_MAX];
 
 struct pci_dev         *sb_dev[SB_CARDS_MAX]   = {NULL}, 
-               *mpu_dev[SB_CARDS_MAX]  = {NULL};
+               *mpu_dev[SB_CARDS_MAX]  = {NULL},
+               *opl_dev[SB_CARDS_MAX]  = {NULL};
 
 
 #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
@@ -189,6 +190,7 @@ static int uart401  = 0;
 
 static int audio_activated[SB_CARDS_MAX] = {0};
 static int mpu_activated[SB_CARDS_MAX]   = {0};
+static int opl_activated[SB_CARDS_MAX]   = {0};
 #else
 static int isapnp      = 0;
 static int multiple    = 1;
@@ -234,193 +236,204 @@ MODULE_PARM_DESC(acer,          "Set this to detect cards in some ACER notebooks");
 /* Please add new entries at the end of the table */
 static struct {
        char *name; 
-       unsigned short card_vendor, card_device, audio_vendor, audio_function, mpu_vendor, mpu_function;
+       unsigned short  card_vendor, card_device, 
+                       audio_vendor, audio_function,
+                       mpu_vendor, mpu_function,
+                       opl_vendor, opl_function;
        short dma, dma2, mpu_io, mpu_irq; /* see sb_init() */
 } sb_isapnp_list[] __initdata = {
        {"Sound Blaster 16", 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0024),
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster 16", 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster 16", 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0027), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster 16", 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster 16", 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster Vibra16S", 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster Vibra16C", 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster Vibra16CL", 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster Vibra16X", 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 32", 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 32",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 32",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 32",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 32",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 32",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 32",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009C), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 64",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 64 Gold",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 64",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 64",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 64",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 64",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"Sound Blaster AWE 64",
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
-               0,0,
+               0,0,0,0,
                0,1,1,-1},
        {"ESS 1868",
                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868),
-               0,0,
+               0,0,0,0,
                0,1,2,-1},
        {"ESS 1868",
                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611),
-               0,0,
+               0,0,0,0,
                0,1,2,-1},
        {"ESS 1869 PnP AudioDrive", 
                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003), 
                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
-               0,0,
+               0,0,0,0,
                0,1,2,-1},
        {"ESS 1869",
                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869), 
                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
-               0,0,
+               0,0,0,0,
                0,1,2,-1},
        {"ESS 1878",
                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878), 
                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878),
-               0,0,
+               0,0,0,0,
                0,1,2,-1},
        {"ESS 1879",
                ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879), 
                ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879),
-               0,0,
+               0,0,0,0,
                0,1,2,-1},
        {"CMI 8330 SoundPRO",
                ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
                ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
+               ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
                0,1,0,-1},
        {"Diamond DT0197H",
                ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
+               ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
                0,-1,0,0},
        {"ALS007",
                ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
+               ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
                0,-1,0,0},
        {"ALS100",
                ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
+               ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
                1,0,0,0},
        {"ALS110",
                ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001),
                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001),
+               ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
                1,0,0,0},
        {"ALS120",
                ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
+               ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
                1,0,0,0},
        {"ALS200",
                ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020),
                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020),
+               ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
                1,0,0,0},
        {"RTL3000",
                ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
                ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
+               ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
                1,0,0,0},
        {0}
 };
@@ -478,13 +491,37 @@ static struct pci_dev *sb_init(struct pci_bus *bus, struct address_info *hw_conf
        } else
                return(NULL);
 
+       /* Cards with separate OPL3 device (ALS, CMI, etc.)
+        * This is just to activate the device... */
+       if(sb_isapnp_list[slot].opl_vendor || sb_isapnp_list[slot].opl_function) {
+               if((opl_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].opl_vendor, sb_isapnp_list[slot].opl_function, NULL))) {
+                       int ret = opl_dev[card]->prepare(opl_dev[card]);
+                       /* If device is active, assume configured with
+                        * /proc/isapnp and use anyway */
+                       if(ret && ret != -EBUSY) {
+                               printk(KERN_ERR "sb: OPL device could not be autoconfigured.\n");
+                               return(sb_dev[card]);
+                       }
+                       if(ret == -EBUSY)
+                               opl_activated[card] = 1;
+
+                       /* Some have irq and dma for opl. the opl3 driver wont
+                        * use 'em so don't configure 'em and hope it works -PEL */
+                       opl_dev[card]->irq_resource[0].flags = 0;
+                       opl_dev[card]->dma_resource[0].flags = 0;
+
+                       opl_dev[card] = activate_dev(sb_isapnp_list[slot].name, "opl3", opl_dev[card]);
+               } else
+                       printk(KERN_ERR "sb: %s isapnp panic: opl3 device not found\n", sb_isapnp_list[slot].name);
+       }
+
        /* Cards with MPU as part of Audio device (CTL and ESS) */
        if(!sb_isapnp_list[slot].mpu_vendor) {
                mpu_config->io_base     = sb_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start;
                return(sb_dev[card]);
        }
-
-       /* Cards with separate MPU device (ALS, CMI, etc */
+       
+       /* Cards with separate MPU device (ALS, CMI, etc.) */
        if(!uart401)
                return(sb_dev[card]);
        if((mpu_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].mpu_vendor, sb_isapnp_list[slot].mpu_function, NULL)))
@@ -499,7 +536,7 @@ static struct pci_dev *sb_init(struct pci_bus *bus, struct address_info *hw_conf
                if(ret == -EBUSY)
                        mpu_activated[card] = 1;
                
-               /* Some mpus use audio device irq? Need to test... -PEL */
+               /* Some cards ask for irq but don't need them - azummo */
                if(sb_isapnp_list[slot].mpu_irq == -1)
                        mpu_dev[card]->irq_resource[0].flags = 0;
                
@@ -510,7 +547,7 @@ static struct pci_dev *sb_init(struct pci_bus *bus, struct address_info *hw_conf
                }
        }
        else
-               printk(KERN_ERR "sb: %s panic: mpu not found\n", sb_isapnp_list[slot].name);
+               printk(KERN_ERR "sb: %s isapnp panic: mpu not found\n", sb_isapnp_list[slot].name);
        
        return(sb_dev[card]);
 }
@@ -584,8 +621,9 @@ static int __init init_sb(void)
        
        for(card = 0; card < max; card++, sb_cards_num++) {
 #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
-               /* Please remember that even with CONFIG_ISAPNP defined one should still be
-                  able to disable PNP support for this single driver! */
+               /* Please remember that even with CONFIG_ISAPNP defined one
+                * should still be able to disable PNP support for this 
+                * single driver! */
                if(isapnp && (sb_isapnp_probe(&cfg[card], &cfg_mpu[card], card) < 0) ) {
                        if(!sb_cards_num) {
                                printk(KERN_NOTICE "sb: No ISAPnP cards found, trying standard ones...\n");
@@ -646,6 +684,8 @@ static void __exit cleanup_sb(void)
                        sb_dev[i]->deactivate(sb_dev[i]);
                if(!mpu_activated[i] && mpu_dev[i])
                        mpu_dev[i]->deactivate(mpu_dev[i]);
+               if(!opl_activated[i] && opl_dev[i])
+                       opl_dev[i]->deactivate(opl_dev[i]);
 #endif
        }
        SOUND_LOCK_END; 
@@ -657,7 +697,7 @@ module_exit(cleanup_sb);
 #ifndef MODULE
 static int __init setup_sb(char *str)
 {
-       /* io, irq, dma, dma2 */
+       /* io, irq, dma, dma2 - just the basics */
        int ints[5];
        
        str = get_options(str, ARRAY_SIZE(ints), ints);
index 496363a6b4202edbbae5973790b03d90f37eb7b7..551c362402421b7d8ea746dafe68b0ed01c8b774 100644 (file)
@@ -180,7 +180,7 @@ static unsigned int initdepth __initdata = 8;
 #ifndef MODULE
 static const char *mode_option __initdata = NULL;
 #endif
-#ifndef CONFIG_PPC
+#if !defined(CONFIG_PPC) && !defined(__sparc__)
 static void *bios_seg = NULL;
 #endif
 
@@ -336,7 +336,7 @@ static int aty128_pci_register(struct pci_dev *pdev,
 static struct fb_info_aty128 *aty128_board_list_add(struct fb_info_aty128
                                *board_list, struct fb_info_aty128 *new_node);
 static int aty128find_ROM(struct fb_info_aty128 *info);
-#ifndef CONFIG_PPC
+#if !defined(CONFIG_PPC) && !defined(__sparc__)
 static void aty128_get_pllinfo(struct fb_info_aty128 *info);
 #endif
 static void aty128_timings(struct fb_info_aty128 *info);
@@ -1940,7 +1940,7 @@ aty128_pci_register(struct pci_dev *pdev,
         printk(KERN_INFO "aty128fb: Rage128 BIOS not located. Guessing...\n");
         aty128_timings(info);
     }
-#ifndef CONFIG_PPC
+#if !defined(CONFIG_PPC) && !defined(__sparc__)
  else
         aty128_get_pllinfo(info);
 
@@ -1981,12 +1981,12 @@ unmap_out:
 #endif /* CONFIG_PCI */
 
 
-/* PPC cannot read video ROM, so we fail by default */
+/* PPC and Sparc cannot read video ROM, so we fail by default */
 static int __init
 aty128find_ROM(struct fb_info_aty128 *info)
 {
     int  flag = 0;
-#ifndef CONFIG_PPC
+#if !defined(CONFIG_PPC) && !defined(__sparc__)
     u32  segstart;
     char *rom_base;
     char *rom;
@@ -2048,7 +2048,7 @@ aty128find_ROM(struct fb_info_aty128 *info)
 }
 
 
-#ifndef CONFIG_PPC
+#if !defined(CONFIG_PPC) && !defined(__sparc__)
 static void __init
 aty128_get_pllinfo(struct fb_info_aty128 *info)
 {   
index 8be58150755d15b3c81b199eb8e07e743934a020..1a7e21cfe20a207adcd30c507a25ba5afa34e2a9 100644 (file)
 #include <linux/fb.h>
 
 #include <asm/byteorder.h>
+
+#ifdef __mc68000__
 #include <asm/setup.h>
+#endif
 
 #include <video/fbcon.h>
 #include <video/fbcon-iplan2p2.h>
index 8591783d9b57bef07377eab4230c563fb0d8d078..069c7d406776ca7c0115172da8cc6447907b3a12 100644 (file)
 #include <linux/fb.h>
 
 #include <asm/byteorder.h>
+
+#ifdef __mc68000__
 #include <asm/setup.h>
+#endif
 
 #include <video/fbcon.h>
 #include <video/fbcon-iplan2p4.h>
index 4ee366019de2dda74bcc70561612c5e061490b30..bc3730a1f14176894cd67b173ef07f37e8a31560 100644 (file)
 #include <linux/fb.h>
 
 #include <asm/byteorder.h>
+
+#ifdef __mc68000__
 #include <asm/setup.h>
+#endif
 
 #include <video/fbcon.h>
 #include <video/fbcon-iplan2p8.h>
index 7aa5e14b808ed2a4904da168944092705555e5cf..35dbad536ef876c6b6ec8a3f9e96e1955e994a40 100644 (file)
@@ -583,7 +583,9 @@ static int  noaccel = 0;
 static int  nopan   = 0;
 static int  nowrap  = 1;      // not implemented (yet)
 static int  inverse = 0;
+#ifdef CONFIG_MTRR
 static int  nomtrr = 0;
+#endif
 static int  nohwcursor = 0;
 static char __initdata fontname[40] = { 0 };
 static const char *mode_option __initdata = NULL;
@@ -1987,7 +1989,7 @@ int __init tdfxfb_init(void) {
       fb_info.regbase_phys = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
       fb_info.regbase_size = 1 << 24;
       fb_info.regbase_virt = 
-       (u32)ioremap_nocache(fb_info.regbase_phys, 1 << 24);
+       (unsigned long)ioremap_nocache(fb_info.regbase_phys, 1 << 24);
       if(!fb_info.regbase_virt) {
        printk("fb: Can't remap %s register area.\n", name);
        return;
@@ -2000,7 +2002,7 @@ int __init tdfxfb_init(void) {
        return;
       }
       fb_info.bufbase_virt    = 
-       (u32)ioremap_nocache(fb_info.bufbase_phys, fb_info.bufbase_size);
+       (unsigned long)ioremap_nocache(fb_info.bufbase_phys, fb_info.bufbase_size);
       if(!fb_info.regbase_virt) {
        printk("fb: Can't remap %s framebuffer.\n", name);
        iounmap((void*)fb_info.regbase_virt);
@@ -2012,7 +2014,7 @@ int __init tdfxfb_init(void) {
       fb_info.regbase_phys = pdev->resource[0].start;
       fb_info.regbase_size = 1 << 24;
       fb_info.regbase_virt = 
-       (u32)ioremap_nocache(fb_info.regbase_phys, 1 << 24);
+       (unsigned long)ioremap_nocache(fb_info.regbase_phys, 1 << 24);
       if(!fb_info.regbase_virt) {
        printk("fb: Can't remap %s register area.\n", name);
        return -ENXIO;
@@ -2025,7 +2027,7 @@ int __init tdfxfb_init(void) {
        return -ENXIO;
       }
       fb_info.bufbase_virt    = 
-       (u32)ioremap_nocache(fb_info.bufbase_phys, fb_info.bufbase_size);
+       (unsigned long)ioremap_nocache(fb_info.bufbase_phys, fb_info.bufbase_size);
       if(!fb_info.regbase_virt) {
        printk("fb: Can't remap %s framebuffer.\n", name);
        iounmap((void*)fb_info.regbase_virt);
index 53029b7d35ee8e318c52ae780f2ae29db5866bc4..b553ca32c91363fd39e9855703342d19253e56da 100644 (file)
@@ -12,7 +12,7 @@ tristate 'Kernel automounter version 4 support (also supports v3)' CONFIG_AUTOFS
 dep_tristate 'ADFS file system support' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
 dep_mbool '  ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
 
-tristate 'Amiga FFS file system support' CONFIG_AFFS_FS
+dep_tristate 'Amiga FFS file system support (EXPERIMENTAL)' CONFIG_AFFS_FS $CONFIG_EXPERIMENTAL
 
 dep_tristate 'Apple Macintosh file system support (EXPERIMENTAL)' CONFIG_HFS_FS $CONFIG_EXPERIMENTAL
 
index 7a7faedd0dd62ab57bb27381c21a79b50e6936fc..49fe517ffa0671b131aa3b268915077fab5b7398 100644 (file)
@@ -28,6 +28,12 @@ Known bugs:
 
 Please direct bug reports to: hjw@zvw.de
 
+Version 3.11
+------------
+
+- Converted to use 2.3.x page cache [Dave Jones <dave@powertweak.com>]
+- Corruption in truncate() bugfix [Ken Tyler <kent@werple.net.au>]
+
 Version 3.10
 ------------
 
index 75c6572b742122a38c3f39575250a5011a8c4d48..86fb1251994b8e76c18fec6acac5d65074303184 100644 (file)
@@ -158,6 +158,8 @@ calc_key(struct inode *inode, int *ext)
 
        for (index = 0; index < 4; index++) {
                kc = &inode->u.affs_i.i_ec->kc[index];
+               if (kc->kc_last == -1)
+                       continue;       /* don't look in cache if invalid. */
                if (*ext == kc->kc_this_seq) {
                        return kc->kc_this_key;
                } else if (*ext == kc->kc_this_seq + 1) {
@@ -773,7 +775,7 @@ out_truncate:
        /* Invalidate cache */
        if (inode->u.affs_i.i_ec) {
                inode->u.affs_i.i_ec->max_ext = 0;
-               for (key = 0; key < 3; key++) {
+               for (key = 0; key < 4; key++) {
                        inode->u.affs_i.i_ec->kc[key].kc_next_key = 0;
                        inode->u.affs_i.i_ec->kc[key].kc_last     = -1;
                }
index eb38eff3430935c4e1138af23c5acf585f1a7336..071eb42d48f6394501c0430869f65a9b26e9283b 100644 (file)
@@ -2358,7 +2358,7 @@ static struct inode *get_vfs_inode (struct super_block *sb,
 
 /*  File operations for device entries follow  */
 
-static int devfs_read (struct file *file, char *buf, size_t len, loff_t *ppos)
+static ssize_t devfs_read (struct file *file, char *buf, size_t len, loff_t *ppos)
 {
     if ( S_ISDIR (file->f_dentry->d_inode->i_mode) ) return -EISDIR;
     return -EINVAL;
index 561c8706568479b5e093ddfe4c1c824bfb5d1456..5717c4af9f9955920d2404d31e226156e053b8c2 100644 (file)
@@ -485,9 +485,11 @@ int acorn_partition(struct gendisk *hd, kdev_t dev,
        if (r == 0)
                r = adfspart_check_POWERTEC(hd, dev, first_sector, first_part_minor);
 #endif
-       if (r < 0)
-               if (warn_no_part) printk(" unable to read boot sectors / partition sectors\n");
-       else if (r)
+       if (r < 0) {
+               if (warn_no_part)
+                       printk(" unable to read boot sectors / partition sectors\n");
+       } else if (r) {
                printk("\n");
+       }
        return r;
 }
index 21330f49947e8a68cebca30f979548c41523ec7a..886e2f4c0bd613153439e4bbce44488ecfc68abd 100644 (file)
@@ -27,9 +27,9 @@
 #include <linux/string.h>
 #include <linux/blk.h>
 
-#ifdef CONFIG_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)
 #include <linux/ide.h> /* IDE xlate */
-#endif /* CONFIG_IDE */
+#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */
 
 #include <asm/system.h>
 
@@ -350,19 +350,19 @@ int msdos_partition(struct gendisk *hd, kdev_t dev,
        unsigned char *data;
        int mask = (1 << hd->minor_shift) - 1;
        int sector_size = get_hardsect_size(dev) / 512;
-#ifdef CONFIG_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)
        int tested_for_xlate = 0;
 
 read_mbr:
-#endif /* CONFIG_IDE */
+#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */
        if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
                if (warn_no_part) printk(" unable to read partition table\n");
                return -1;
        }
        data = bh->b_data;
-#ifdef CONFIG_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)
 check_table:
-#endif /* CONFIG_IDE */
+#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */
        /* Use bforget(), because we may have changed the disk geometry */
        if (*(unsigned short *)  (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
                bforget(bh);
@@ -370,7 +370,7 @@ check_table:
        }
        p = (struct partition *) (0x1be + data);
 
-#ifdef CONFIG_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)
        if (!tested_for_xlate++) {      /* Do this only once per disk */
                /*
                 * Look for various forms of IDE disk geometry translation
@@ -426,7 +426,7 @@ check_table:
                        (void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
                }
        }
-#endif /* CONFIG_IDE */
+#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */
 
        /* Look for partitions in two passes:
           First find the primary partitions, and the DOS-type extended partitions.
index 5de7416ecf987de73cad7ee420b69e4f44271196..058750cddca352d1b5700ef604de3066226fcdca 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -25,7 +25,7 @@ do_revalidate(struct dentry *dentry)
 }
 
 
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
 
 /*
  * For backward compatibility?  Maybe this should be moved
@@ -115,7 +115,7 @@ static int cp_new_stat(struct inode * inode, struct stat * statbuf)
 }
 
 
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
 /*
  * For backward compatibility?  Maybe this should be moved
  * into arch/i386 instead?
@@ -161,7 +161,7 @@ asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
        return error;
 }
 
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
 
 /*
  * For backward compatibility?  Maybe this should be moved
@@ -209,7 +209,7 @@ asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
        return error;
 }
 
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
 
 /*
  * For backward compatibility?  Maybe this should be moved
index b775a4b6546f9263b6590515fcb8180f5dbdcc94..c2f54c1508a512ca92e947fef7702676567c5954 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: elf.h,v 1.20 1998/09/14 09:11:10 davem Exp $ */
+/* $Id: elf.h,v 1.21 2000/04/14 09:59:04 davem Exp $ */
 #ifndef __ASMSPARC_ELF_H
 #define __ASMSPARC_ELF_H
 
index cafd6867405d15e0a7f63ed856ad040baa254103..a32ce08feb64e95bd15461aa21bf4efd05b32011 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: io.h,v 1.26 2000/03/30 01:43:26 davem Exp $
+ * $Id: io.h,v 1.27 2000/04/13 04:45:59 davem Exp $
  */
 #ifndef __SPARC_IO_H
 #define __SPARC_IO_H
@@ -169,6 +169,7 @@ static inline void *sbus_memset_io(void *__dst, int c, __kernel_size_t n)
  * This is why we have no bus number argument to ioremap().
  */
 extern void *ioremap(unsigned long offset, unsigned long size);
+#define ioremap_nocache(X,Y)   ioremap((X),(Y))
 extern void iounmap(void *addr);
 
 /* P3: talk davem into dropping "name" argument in favor of res->name */
index 974a0148639185fffc477e7099808d86d66daad5..3ac97a41bf207a8bee5be34773fd5741aff7d53a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: namei.h,v 1.15 2000/04/08 02:15:14 davem Exp $
+/* $Id: namei.h,v 1.16 2000/04/13 00:55:54 davem Exp $
  * linux/include/asm-sparc/namei.h
  *
  * Routines to handle famous /usr/gnemul/s*.
index 1df90bce65565e1ba33874ba5b85b62e81d713c5..6d93fde96794f92375643a652255001909aaeeed 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: delay.h,v 1.7 1997/11/07 18:24:31 mj Exp $
+/* $Id: delay.h,v 1.8 2000/04/13 04:45:59 davem Exp $
  * delay.h: Linux delay routines on the V9.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu).
@@ -8,6 +8,7 @@
 #define __SPARC64_DELAY_H
 
 #ifdef __SMP__
+#include <linux/sched.h>
 #include <asm/smp.h>
 #endif 
 
index 87c37b68c94991fbf407d4d3376302fcf1570ee1..ec946e414f139c086269e44df373c25fe772a6f4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: elf.h,v 1.23 1999/12/15 14:19:06 davem Exp $ */
+/* $Id: elf.h,v 1.24 2000/04/14 09:59:04 davem Exp $ */
 #ifndef __ASM_SPARC64_ELF_H
 #define __ASM_SPARC64_ELF_H
 
index 2ca3b4693eb19d490fef9d6dd0abc99a7acc900f..d829b7c5345b4e80a8b6155453c50097d98fc5f5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.34 2000/03/30 01:40:54 davem Exp $ */
+/* $Id: io.h,v 1.35 2000/04/13 04:45:59 davem Exp $ */
 #ifndef __SPARC64_IO_H
 #define __SPARC64_IO_H
 
@@ -367,6 +367,7 @@ out:
  * using physically addressed loads and stores, so this does nothing.
  */
 #define ioremap(__offset, __size)      ((void *)(__offset))
+#define ioremap_nocache(X,Y)           ioremap((X),(Y))
 #define iounmap(__addr)                        do { } while(0)
 
 /* Similarly for SBUS. */
index f4fc32387f3c95ab1e39d6ffc3083f3a5999a852..25429ad7224e5656ca1cda9b5aabcb53db2f68e2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: namei.h,v 1.16 2000/04/08 02:15:17 davem Exp $
+/* $Id: namei.h,v 1.17 2000/04/13 00:55:54 davem Exp $
  * linux/include/asm-sparc64/namei.h
  *
  * Routines to handle famous /usr/gnemul/s*.
index 7211c7d81846d18a9bc1fa5e18c2388db73660d4..79f4d7448a603e9b90295bd1275cadf800dcf3a8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.33 2000/03/22 02:48:04 davem Exp $ */
+/* $Id: page.h,v 1.35 2000/04/13 04:45:59 davem Exp $ */
 
 #ifndef _SPARC64_PAGE_H
 #define _SPARC64_PAGE_H
 #define BUG()          __builtin_trap()
 #define PAGE_BUG(page) BUG()
 
-extern void clear_page(void *page);
-extern void copy_page(void *to, void *from);
+extern void _clear_page(void *page);
+extern void _copy_page(void *to, void *from);
+#define clear_page(X)  _clear_page((void *)(X))
+#define copy_page(X,Y) _copy_page((void *)(X), (void *)(Y))
 extern void clear_user_page(void *page, unsigned long vaddr);
 extern void copy_user_page(void *to, void *from, unsigned long vaddr);
 
@@ -103,7 +105,7 @@ register unsigned long PAGE_OFFSET asm("g4");
 
 #define __pa(x)                        ((unsigned long)(x) - PAGE_OFFSET)
 #define __va(x)                        ((void *)((unsigned long) (x) + PAGE_OFFSET))
-#define MAP_NR(addr)           (__pa(addr) >> PAGE_SHIFT)
+#define MAP_NR(addr)           ((__pa(addr)-phys_base) >> PAGE_SHIFT)
 
 #define virt_to_phys __pa
 #define phys_to_virt __va
@@ -119,8 +121,8 @@ register unsigned long PAGE_OFFSET asm("g4");
  */
 
 struct sparc_phys_banks {
-  unsigned long base_addr;
-  unsigned long num_bytes;
+       unsigned long base_addr;
+       unsigned long num_bytes;
 };
 
 #define SPARC_PHYS_BANKS 32
index 697dc6fbcfed24dd17ebd16e39cb18980680b996..9a0d67494c5f476b466292d722ef82b105521109 100644 (file)
@@ -153,11 +153,11 @@ extern __inline__ pgd_t *get_pgd_fast(void)
                 ret = (struct page *)(__page_address(ret) + off);
                 pgd_cache_size--;
         } else {
-               ret = (struct page *) __get_free_page(GFP_KERNEL);
-               if(ret) {
-                       struct page *page = mem_map + MAP_NR(ret);
-                       
-                       memset(ret, 0, PAGE_SIZE);
+               struct page *page = alloc_page(GFP_KERNEL);
+
+               if (page) {
+                       ret = (struct page *)page_address(page);
+                       clear_page(ret);
                        (unsigned long)page->pprev_hash = 2;
                        (unsigned long *)page->next_hash = pgd_quicklist;
                        pgd_quicklist = (unsigned long *)page;
index 0d49e700ec8d972fcfb3c53644d86fc46d670de9..f368d64b3f80ff6c6f406e94d0c5b635c0179061 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.124 2000/03/27 10:38:56 davem Exp $
+/* $Id: pgtable.h,v 1.125 2000/04/12 08:10:26 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -152,16 +152,13 @@ extern pte_t __bad_page(void);
 
 #define BAD_PAGE       __bad_page()
 
-/* First physical page can be anywhere, the following is needed so that
- * va-->pa and vice versa conversions work properly without performance
- * hit for all __pa()/__va() operations.
- */
 extern unsigned long phys_base;
-#define ZERO_PAGE(vaddr)       (mem_map + (phys_base>>PAGE_SHIFT))
+
+#define ZERO_PAGE(vaddr)       (mem_map)
 
 /* Warning: These take pointers to page structs now... */
 #define mk_pte(page, pgprot)           \
-       __pte(((page - mem_map) << PAGE_SHIFT) | pgprot_val(pgprot))
+       __pte((((page - mem_map) << PAGE_SHIFT)+phys_base) | pgprot_val(pgprot))
 #define page_pte_prot(page, prot)      mk_pte(page, prot)
 #define page_pte(page)                 page_pte_prot(page, __pgprot(0))
 
@@ -180,7 +177,7 @@ extern inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
        (pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
 #define pgd_set(pgdp, pmdp)    \
        (pgd_val(*(pgdp)) = (__pa((unsigned long) (pmdp)) >> 11UL))
-#define pte_pagenr(pte)   ((unsigned long) ((pte_val(pte)&~PAGE_OFFSET)>>PAGE_SHIFT))
+#define pte_pagenr(pte)   (((unsigned long) ((pte_val(pte)&~PAGE_OFFSET)-phys_base)>>PAGE_SHIFT))
 #define pmd_page(pmd)                  ((unsigned long) __va((pmd_val(pmd)<<11UL)))
 #define pgd_page(pgd)                  ((unsigned long) __va((pgd_val(pgd)<<11UL)))
 #define pte_none(pte)                  (!pte_val(pte))
index 8cb99a22f447763a37a0298b29db82113a45b45b..0467f944de912143e4bcf9c2fda5606dec9cb619 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sab82532.h,v 1.5 1999/05/12 11:21:22 davem Exp $
+/* $Id: sab82532.h,v 1.6 2000/04/13 07:22:35 ecd Exp $
  * sab82532.h: Register Definitions for the Siemens SAB82532 DUSCC
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -144,6 +144,8 @@ struct sab82532 {
        int                              recv_fifo_size;
        int                              custom_divisor;
        int                              baud;
+       unsigned int                     cec_timeout;
+       unsigned int                     tec_timeout;
        int                              x_char;
        int                              close_delay;
        unsigned short                   closing_wait;
index b637522eb768d5200b7e50e3c1de7a8d0c085a62..b5471211945474a759eef253e318c50d1ae5a39c 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _LINUX_ASM_VGA_H_
 #define _LINUX_ASM_VGA_H_
 
+#include <asm/types.h>
+
 #define VT_BUF_HAVE_RW
 
 static inline void scr_writew(u16 val, u16 *addr)
index 0a9eb9762f5f194f4dc207bd2341e91909ae087f..4d5ada52b6e03bd50a5b8ff5fc67076ad00e4c0a 100644 (file)
@@ -257,7 +257,7 @@ enum {
 #define ATM_ATMOPT_CLP 1       /* set CLP bit */
 
 
-typedef struct { unsigned short bits; } atm_vcc_flags_t;
+typedef struct { unsigned int bits; } atm_vcc_flags_t;
 
 
 struct atm_vcc {
@@ -286,7 +286,6 @@ struct atm_vcc {
        struct sk_buff_head recvq;      /* receive queue */
        struct k_atm_aal_stats *stats;  /* pointer to AAL stats group */
        wait_queue_head_t sleep;        /* if socket is busy */
-       wait_queue_head_t wsleep;       /* if waiting for write buffer space */
        struct sock     *sk;            /* socket backpointer */
        struct atm_vcc  *prev,*next;
        /* SVC part --- may move later ------------------------------------- */
index 70635b4910b7fbd6fe08da772c60dd5edf84540f..e28f6bfff8b75377a52a2888c84adbaaad30f46e 100644 (file)
@@ -96,6 +96,8 @@
 #define SMART_AUTOSAVE         0xd2
 #define SMART_SAVE             0xd3
 #define SMART_IMMEDIATE_OFFLINE        0xd4
+#define SMART_READ_LOG_SECTOR  0xd5
+#define SMART_WRITE_LOG_SECTOR 0xd6
 #define SMART_ENABLE           0xd8
 #define SMART_DISABLE          0xd9
 #define SMART_STATUS           0xda
index 10bd7249d8e0fae533cc6c3f91a09bf2941a730b..509b591d283543587f662b3135fb016fb01efcbb 100644 (file)
+/*
+ * linux/include/linux/hdsmart.h
+ *
+ * Copyright (C) 1999-2000     Michael Cornwell <cornwell@acm.org>
+ * Copyright (C) 2000          Andre Hedrick <andre@linux-ide.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example /usr/src/linux/COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
 #ifndef _LINUX_HDSMART_H
 #define _LINUX_HDSMART_H
 
-/*
- * This file contains some defines for the AT-hd-controller.
- * Various sources.  
- */
+/* smart_attribute is the vendor specific in SFF-8035 spec */
+struct ata_smart_attribute {
+       unsigned char                           id;
+       unsigned short                          status_flag;
+       unsigned char                           normalized;
+       unsigned char                           worse_normal;
+       unsigned char                           raw[6];
+       unsigned char                           reserv;
+} __attribute__ ((packed));
+
+/* smart_values is format of the read drive Atrribute command */
+struct ata_smart_values {
+       unsigned short                          revnumber;
+       struct ata_smart_attribute              vendor_attributes [30];
+        unsigned char                          offline_data_collection_status;
+        unsigned char                          self_test_exec_status;
+       unsigned short                          total_time_to_complete_off_line;
+       unsigned char                           vendor_specific_366;
+       unsigned char                           offline_data_collection_capability;
+       unsigned short                          smart_capability;
+       unsigned char                           errorlog_capability;
+       unsigned char                           vendor_specific_371;
+       unsigned char                           short_test_completion_time;
+       unsigned char                           extend_test_completion_time;
+       unsigned char                           reserved_374_385 [12];
+       unsigned char                           vendor_specific_386_509 [125];
+       unsigned char                           chksum;
+} __attribute__ ((packed));
+
+/* Smart Threshold data structures */
+/* Vendor attribute of SMART Threshold */
+struct ata_smart_threshold_entry {
+       unsigned char                           id;
+       unsigned char                           normalized_threshold;
+       unsigned char                           reserved[10];
+} __attribute__ ((packed));
+
+/* Format of Read SMART THreshold Command */
+struct ata_smart_thresholds {
+       unsigned short                          revnumber;
+       struct ata_smart_threshold_entry        thres_entries[30];
+       unsigned char                           reserved[149];
+       unsigned char                           chksum;
+} __attribute__ ((packed));
+
+struct ata_smart_errorlog_command_struct {
+       unsigned char                           devicecontrolreg;
+       unsigned char                           featuresreg;
+       unsigned char                           sector_count;
+       unsigned char                           sector_number;
+       unsigned char                           cylinder_low;
+       unsigned char                           cylinder_high;
+       unsigned char                           drive_head;
+       unsigned char                           commandreg;
+       unsigned int                            timestamp;
+} __attribute__ ((packed));
 
-#define NR_ATTRIBUTES  30
-
-typedef struct threshold_s {
-       unsigned char   id;
-       unsigned char   threshold;
-       unsigned char   reserved[10];
-} __attribute__ ((packed)) threshold_t;
-
-typedef struct thresholds_s {
-       unsigned short  revision;
-       threshold_t     thresholds[NR_ATTRIBUTES];
-       unsigned char   reserved[18];
-       unsigned char   vendor[131];
-       unsigned char   checksum;
-} __attribute__ ((packed)) thresholds_t;
-
-typedef struct value_s {
-       unsigned char   id;
-       unsigned short  status;
-       unsigned char   value;
-       unsigned char   vendor[8];
-} __attribute__ ((packed)) value_t;
-
-typedef struct values_s {
-       unsigned short  revision;
-       value_t         values[NR_ATTRIBUTES];
-       unsigned char   offline_status;
-       unsigned char   vendor1;
-       unsigned short  offline_timeout;
-       unsigned char   vendor2;
-       unsigned char   offline_capability;
-       unsigned short  smart_capability;
-       unsigned char   reserved[16];
-       unsigned char   vendor[125];
-       unsigned char   checksum;
-} __attribute__ ((packed)) values_t;
+struct ata_smart_errorlog_error_struct {
+       unsigned char                           error_condition;
+       unsigned char                           extended_error[14];
+       unsigned char                           state;
+       unsigned short                          timestamp;
+} __attribute__ ((packed));
+
+struct ata_smart_errorlog_struct {
+       struct ata_smart_errorlog_command_struct        commands[6];
+       struct ata_smart_errorlog_error_struct          error_struct;
+}  __attribute__ ((packed));
+
+struct ata_smart_errorlog {
+       unsigned char                           revnumber;
+       unsigned char                           error_log_pointer;
+       struct ata_smart_errorlog_struct        errorlog_struct[5];
+       unsigned short                          ata_error_count;
+       unsigned short                          non_fatal_count;
+       unsigned short                          drive_timeout_count;
+       unsigned char                           reserved[53];
+} __attribute__ ((packed));
+
+struct ata_smart_selftestlog_struct {
+       unsigned char                           selftestnumber;
+       unsigned char                           selfteststatus;
+       unsigned short                          timestamp;
+       unsigned char                           selftestfailurecheckpoint;
+       unsigned int                            lbafirstfailure;
+       unsigned char                           vendorspecific[15];
+} __attribute__ ((packed));
+
+struct ata_smart_selftestlog {
+       unsigned short                          revnumber;
+       struct ata_smart_selftestlog_struct     selftest_struct[21];
+       unsigned char                           vendorspecific[2];
+       unsigned char                           mostrecenttest;
+       unsigned char                           resevered[2];
+       unsigned char                           chksum;
+} __attribute__ ((packed));
 
 #if !defined(__KERNEL__) || defined(_IDE_DISK_C)
-#define NR_OFFLINE_TEXTS       5
-struct {
-       unsigned char   value;
-       char            *text;
-} offline_status_text[NR_OFFLINE_TEXTS] = {
-       { 0x00, "NeverStarted" },
-       { 0x02, "Completed" },
-       { 0x04, "Suspended" },
-       { 0x05, "Aborted" },
-       { 0x06, "Failed" }
-};
+/* smartctl version number */
+#define VERSION_MAJOR                          1
+#define VERSION_MINOR                          2
+
+/* Number of ata device to scan */
+int numdevices;
+
+/* how often SMART is checks in seconds */
+int checktime = 1800;
+
+typedef struct atadevices_s {
+       int                                     fd;
+       char                                    devicename[14];
+       int                                     selftest;
+       struct hd_driveid                       drive;
+       struct ata_smart_values                 smartval;
+       struct ata_smart_thresholds             smartthres;
+} atadevices_t;
+
 #endif /* !defined(__KERNEL__) || defined(_IDE_DISK_C) */
 
 #endif /* _LINUX_HDSMART_H */
index ae597c1513ccb318456f28e502cfd11d9bb88ded..ea395aaa86f8984ea62dfc0b0b2d04f36182d5db 100644 (file)
@@ -300,13 +300,6 @@ typedef struct ide_drive_s {
        struct proc_dir_entry *proc;    /* /proc/ide/ directory entry */
        void            *settings;      /* /proc/ide/ drive settings */
        char            driver_req[10]; /* requests specific driver */
-#if 1
-       struct thresholds_s     *smart_thresholds;
-       struct values_s         *smart_values;
-#else
-       thresholds_t            smart_thresholds;
-       values_t                smart_values;
-#endif
        int             last_lun;       /* last logical unit */
        int             forced_lun;     /* if hdxlun was given at boot */
 } ide_drive_t;
@@ -385,7 +378,7 @@ typedef struct hwif_s {
        ide_resetproc_t *resetproc;     /* routine to reset controller after a disk reset */
        ide_dmaproc_t   *dmaproc;       /* dma read/write/abort routine */
        unsigned int    *dmatable_cpu;  /* dma physical region descriptor table (cpu view) */
-       u32             dmatable_dma;   /* dma physical region descriptor table (dma view) */
+       dma_addr_t      dmatable_dma;   /* dma physical region descriptor table (dma view) */
        struct scatterlist *sg_table;   /* Scatter-gather list used to build the above */
        int sg_nents;                   /* Current number of entries in it */
        int sg_dma_direction;           /* dma transfer direction */
@@ -538,6 +531,7 @@ typedef int         (ide_ioctl_proc)(ide_drive_t *, struct inode *, struct file *, unsi
 typedef int            (ide_open_proc)(struct inode *, struct file *, ide_drive_t *);
 typedef void           (ide_release_proc)(struct inode *, struct file *, ide_drive_t *);
 typedef int            (ide_check_media_change_proc)(ide_drive_t *);
+typedef void           (ide_revalidate_proc)(ide_drive_t *);
 typedef void           (ide_pre_reset_proc)(ide_drive_t *);
 typedef unsigned long  (ide_capacity_proc)(ide_drive_t *);
 typedef ide_startstop_t        (ide_special_proc)(ide_drive_t *);
@@ -557,6 +551,7 @@ typedef struct ide_driver_s {
        ide_open_proc                   *open;
        ide_release_proc                *release;
        ide_check_media_change_proc     *media_change;
+       ide_revalidate_proc             *revalidate;
        ide_pre_reset_proc              *pre_reset;
        ide_capacity_proc               *capacity;
        ide_special_proc                *special;
@@ -735,6 +730,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err);
 int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf);
 
 void ide_delay_50ms (void);
+int system_bus_clock(void);
 
 int ide_driveid_update (ide_drive_t *drive);
 int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature);
index 02341868de236a9d5d26c75d9822545dc696310b..11a85411f447205d9d9815b33f03ac361e7a64d5 100644 (file)
@@ -83,6 +83,12 @@ asmlinkage int printk(const char * fmt, ...)
        ((unsigned char *)&addr)[2], \
        ((unsigned char *)&addr)[3]
 
+#define HIPQUAD(addr) \
+       ((unsigned char *)&addr)[3], \
+       ((unsigned char *)&addr)[2], \
+       ((unsigned char *)&addr)[1], \
+       ((unsigned char *)&addr)[0]
+
 #endif /* __KERNEL__ */
 
 #define SI_LOAD_SHIFT  16
index f85af1f107b0c131c27b160868b234753f26fd15..b669fdafd62dd8483d1c91a3acc135002ed52f8d 100644 (file)
@@ -89,6 +89,8 @@ struct vm_area_struct {
 #define VM_SEQ_READ    0x00008000      /* App will access data sequentially */
 #define VM_RAND_READ   0x00010000      /* App will not benefit from clustered reads */
 
+#define VM_DONTCOPY    0x00020000      /* Do not copy this vma on fork */
+
 #define VM_STACK_FLAGS 0x00000177
 
 #define VM_READHINTMASK                        (VM_SEQ_READ | VM_RAND_READ)
index 3c1b4a4c646bb84b5c51e52c9498b7d0c36a4c8e..f5fd96690f46595a1fd4a4b6a5ec898059bb3607 100644 (file)
@@ -37,10 +37,10 @@ struct ip_conntrack_protocol
                      struct iphdr *iph, size_t len,
                      enum ip_conntrack_info ctinfo);
 
-       /* Called when a new connection for this protocol found; returns
-        * TRUE if it's OK.  If so, packet() called next. */
-       int (*new)(struct ip_conntrack *conntrack,
-                  struct iphdr *iph, size_t len);
+       /* Called when a new connection for this protocol found;
+        * returns timeout.  If so, packet() called next. */
+       unsigned long (*new)(struct ip_conntrack *conntrack,
+                            struct iphdr *iph, size_t len);
 
        /* Module (if any) which this is connected to. */
        struct module *me;
index ad11d316a6441b51d652f90b85b950bdbd0f296b..e298baf1718c2799ee4ac30788c2d919e6984b24 100644 (file)
@@ -1,8 +1,7 @@
 #ifndef _IPT_STATE_H
 #define _IPT_STATE_H
 
-#define _IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)+1))
-#define IPT_STATE_BIT(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? _IPT_STATE_BIT((ctinfo)-IP_CT_IS_REPLY) : _IPT_STATE_BIT(ctinfo))
+#define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
 #define IPT_STATE_INVALID (1 << 0)
 
 struct ipt_state_info
index 5a90f14bdcc4692847c19ebd2a9a14e0ce497f3e..4377b14cd24a93474a172288b9dedeee8cfe701e 100644 (file)
 #define PCI_VENDOR_ID_ARTOP            0x1191
 #define PCI_DEVICE_ID_ARTOP_ATP8400    0x0004
 #define PCI_DEVICE_ID_ARTOP_ATP850UF   0x0005
+#define PCI_DEVICE_ID_ARTOP_ATP860     0x0006
+#define PCI_DEVICE_ID_ARTOP_ATP860R    0x0007
 
 #define PCI_VENDOR_ID_ZEITNET          0x1193
 #define PCI_DEVICE_ID_ZEITNET_1221     0x0001
index f9e7efdaacdbb0d5a4380066884c1daa18c9843e..1bebe5500d269999ac58263b3059169dec6f3f36 100644 (file)
@@ -86,10 +86,10 @@ extern inline int timer_pending(const struct timer_list * timer)
 #define timer_synchronize(t) while (timer_is_running(t)) barrier()
 extern int del_timer_sync(struct timer_list * timer);
 #else
-#define timer_exit(t) do { } while (0)
-#define timer_set_running(t) do { } while (0)
+#define timer_exit(t) (void)(t)
+#define timer_set_running(t) (void)(t)
 #define timer_is_running(t) (0)
-#define timer_synchronize(t) barrier()
+#define timer_synchronize(t) do { (void)(t); barrier(); } while(0)
 #define del_timer_sync(t) del_timer(t)
 #endif
 
index 6f3f300b043bd0a602dd3779448d1fcc06e2a5c0..49bb2a4b39ecb9f32aef7674d64aa60a35aa8b66 100644 (file)
@@ -1,5 +1,9 @@
 /*
  * These are the public elements of the Linux kernel X.25 implementation.
+ *
+ *     History
+ *     mar/20/00       Daniela Squassoni Disabling/enabling of facilities 
+ *                                       negotiation.
  */
 
 #ifndef        X25_KERNEL_H
@@ -49,12 +53,27 @@ struct sockaddr_x25 {
 
 /*
  *     DTE/DCE subscription options.
+ *
+ *      As this is missing lots of options, user should expect major
+ *     changes of this structure in 2.5.x which might break compatibilty.
+ *      The somewhat ugly dimension 200-sizeof() is needed to maintain
+ *     backward compatibility.
  */
 struct x25_subscrip_struct {
-       char device[200];
+       char device[200-sizeof(unsigned long)];
+       unsigned long   global_facil_mask;      /* 0 to disable negotiation */
        unsigned int    extended;
 };
 
+/* values for above global_facil_mask */
+
+#define        X25_MASK_REVERSE        0x01    
+#define        X25_MASK_THROUGHPUT     0x02
+#define        X25_MASK_PACKET_SIZE    0x04
+#define        X25_MASK_WINDOW_SIZE    0x08
+
+
+
 /*
  *     Routing table control structure.
  */
index 73168fda16c5f4a879b11411fe260c7a7026ef57..5df7b8de13cbd56483668ffda8b7903c9b60b3a0 100644 (file)
@@ -817,7 +817,7 @@ extern int                      sock_no_sendmsg(struct socket *,
                                                struct msghdr *, int,
                                                struct scm_cookie *);
 extern int                      sock_no_recvmsg(struct socket *,
-                                               struct msghdr *, int,
+                                               struct msghdr *, int, int,
                                                struct scm_cookie *);
 extern int                     sock_no_mmap(struct file *file,
                                             struct socket *sock,
index 3b28c58ce1aef91d3e8003551647fa204f79257b..66575c464a270c4866863e6205b4784530a663e4 100644 (file)
@@ -1,7 +1,10 @@
 /*
  *     Declarations of X.25 Packet Layer type objects.
  *
- *     Jonathan Naylor         17/11/96
+ *     History
+ *     nov/17/96       Jonathan Naylor   Initial version.              
+ *     mar/20/00       Daniela Squassoni Disabling/enabling of facilities 
+ *                                       negotiation.
  */
 
 #ifndef _X25_H
@@ -113,6 +116,7 @@ struct x25_neigh {
        struct sk_buff_head     queue;
        unsigned long           t20;
        struct timer_list       t20timer;
+       unsigned long           global_facil_mask;
 };
 
 typedef struct {
@@ -132,6 +136,7 @@ typedef struct {
        struct x25_causediag    causediag;
        struct x25_facilities   facilities;
        struct x25_calluserdata calluserdata;
+       unsigned long           vc_facil_mask;  /* inc_call facilities mask */
 } x25_cb;
 
 /* af_x25.c */
@@ -159,8 +164,8 @@ extern void x25_establish_link(struct x25_neigh *);
 extern void x25_terminate_link(struct x25_neigh *);
 
 /* x25_facilities.c */
-extern int  x25_parse_facilities(struct sk_buff *, struct x25_facilities *);
-extern int  x25_create_facilities(unsigned char *, struct x25_facilities *);
+extern int  x25_parse_facilities(struct sk_buff *, struct x25_facilities *, unsigned long *);
+extern int  x25_create_facilities(unsigned char *, struct x25_facilities *, unsigned long);
 extern int  x25_negotiate_facilities(struct sk_buff *, struct sock *, struct x25_facilities *);
 extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
 
index b60a3d9b273d2578c71207bd6b03f36e8a08fb4b..c1af722f55690c8a32a1f98399e478699330cb16 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -370,7 +370,7 @@ static void shm_put_super(struct super_block *sb)
 
 static int shm_statfs(struct super_block *sb, struct statfs *buf)
 {
-       buf->f_type = 0;
+       buf->f_type = SHM_FS_MAGIC;
        buf->f_bsize = PAGE_SIZE;
        buf->f_blocks = shm_ctlall;
        buf->f_bavail = buf->f_bfree = shm_ctlall - shm_tot;
index 6eca792d96e9bbebc938a06a939c1be11521b7ef..793972f6c503d5111845076d01b8cd4e37a62556 100644 (file)
@@ -242,6 +242,8 @@ static inline int dup_mmap(struct mm_struct * mm)
                struct file *file;
 
                retval = -ENOMEM;
+               if(mpnt->vm_flags & VM_DONTCOPY)
+                       continue;
                tmp = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
                if (!tmp)
                        goto fail_nomem;
index e8172bb48e92ffb925905e961fbbefbb73b82117..35e8a7d68181403694bc6634b602ea25ac92cce8 100644 (file)
@@ -927,7 +927,7 @@ asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim)
                        ? -EFAULT : 0;
 }
 
-#if !defined(__ia64__)
+#if !defined(__ia64__) && !defined(__s390__)
 
 /*
  *     Back compatibility for getrlimit. Needed for some apps.
index 35883ed4c62a7ae16a4055a2aed1c8ef99207cbd..5a9bb0215d863d0008d7863e2ffa79821f1d9d2b 100644 (file)
@@ -228,7 +228,7 @@ static ctl_table kern_table[] = {
 static ctl_table vm_table[] = {
        {VM_FREEPG, "freepages", 
         &freepages, sizeof(freepages_t), 0644, NULL, &proc_dointvec},
-       {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0600, NULL,
+       {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0644, NULL,
         &proc_dointvec_minmax, &sysctl_intvec, NULL,
         &bdflush_min, &bdflush_max},
        {VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory,
@@ -240,9 +240,9 @@ static ctl_table vm_table[] = {
        {VM_PAGERDAEMON, "kswapd",
         &pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec},
        {VM_PGT_CACHE, "pagetable_cache", 
-        &pgt_cache_water, 2*sizeof(int), 0600, NULL, &proc_dointvec},
+        &pgt_cache_water, 2*sizeof(int), 0644, NULL, &proc_dointvec},
        {VM_PAGE_CLUSTER, "page-cluster", 
-        &page_cluster, sizeof(int), 0600, NULL, &proc_dointvec},
+        &page_cluster, sizeof(int), 0644, NULL, &proc_dointvec},
        {0}
 };
 
index 4133c2207ebdee71fa7ba7fa8774c1baec0f012a..316cc6a22f55c4b15a414d98ac25e1367c1e5493 100644 (file)
@@ -266,7 +266,7 @@ static void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_d
                if(entry) 
                {
 #if TR_SR_DEBUG
-printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0],
+printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0],
                  trh->daddr[1],trh->daddr[2],trh->daddr[3],trh->daddr[4],trh->daddr[5]);
 #endif
                        if(!entry->local_ring && (ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8)
index 37610d6d6a0efb32974de9d777237e3d9c64eaf0..f1bd99b94d7d28e04595b18c5fabf4140e3b47c7 100644 (file)
@@ -172,7 +172,7 @@ static int clip_arp_rcv(struct sk_buff *skb)
        DPRINTK("clip_arp_rcv\n");
        vcc = ATM_SKB(skb)->vcc;
        if (!vcc || !atm_charge(vcc,skb->truesize)) {
-               kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return 0;
        }
        DPRINTK("pushing to %p\n",vcc);
@@ -197,9 +197,8 @@ void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
        atm_return(vcc,skb->truesize);
        skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
                /* clip_vcc->entry == NULL if we don't have an IP address yet */
-       skb->rx_dev = NULL;
        if (!skb->dev) {
-               kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return;
        }
        ATM_SKB(skb)->vcc = vcc;
@@ -232,18 +231,20 @@ void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
 static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb)
 {
        struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
+       struct net_device *dev = skb->dev;
        int old;
+       unsigned long flags;
 
        DPRINTK("clip_pop(vcc %p)\n",vcc);
        clip_vcc->old_pop(vcc,skb);
        /* skb->dev == NULL in outbound ARP packets */
-       if (!skb->dev) return;
-       spin_lock(&PRIV(skb->dev)->xoff_lock);
+       if (!dev) return;
+       spin_lock_irqsave(&PRIV(dev)->xoff_lock,flags);
        if (atm_may_send(vcc,0)) {
                old = xchg(&clip_vcc->xoff,0);
-               if (old) netif_wake_queue(skb->dev);
+               if (old) netif_wake_queue(dev);
        }
-       spin_unlock(&PRIV(skb->dev)->xoff_lock);
+       spin_unlock_irqrestore(&PRIV(dev)->xoff_lock,flags);
 }
 
 
@@ -377,6 +378,7 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
        struct atmarp_entry *entry;
        struct atm_vcc *vcc;
        int old;
+       unsigned long flags;
 
        DPRINTK("clip_start_xmit (skb %p)\n",skb);
        if (!skb->dst) {
@@ -439,7 +441,7 @@ return 0;
                return 0;
        }
        if (old) return 0;
-       spin_lock(&clip_priv->xoff_lock);
+       spin_lock_irqsave(&clip_priv->xoff_lock,flags);
        netif_stop_queue(dev); /* XOFF -> throttle immediately */
        barrier();
        if (!entry->vccs->xoff)
@@ -448,7 +450,7 @@ return 0;
                   good enough, because nothing should really be asleep because
                   of the brief netif_stop_queue. If this isn't true or if it
                   changes, use netif_wake_queue instead. */
-       spin_unlock(&clip_priv->xoff_lock);
+       spin_unlock_irqrestore(&clip_priv->xoff_lock,flags);
        return 0;
 }
 
index 9625061eb045186b0d960d51240a8e0f928e90b3..867085ed81bf0ed022994321acf671752e497bc9 100644 (file)
@@ -114,7 +114,6 @@ int atm_create(struct socket *sock,int protocol,int family)
        vcc->atm_options = vcc->aal_options = 0;
        vcc->timestamp.tv_sec = vcc->timestamp.tv_usec = 0;
        init_waitqueue_head(&vcc->sleep);
-       init_waitqueue_head(&vcc->wsleep);
        skb_queue_head_init(&vcc->recvq);
        skb_queue_head_init(&vcc->listenq);
        sock->sk = sk;
@@ -412,7 +411,7 @@ int atm_sendmsg(struct socket *sock,struct msghdr *m,int total_len,
        if (!size) return 0;
        /* verify_area is done by net/socket.c */
        eff = (size+3) & ~3; /* align to word boundary */
-       add_wait_queue(&vcc->wsleep,&wait);
+       add_wait_queue(&vcc->sleep,&wait);
        set_current_state(TASK_INTERRUPTIBLE);
        error = 0;
        while (!(skb = vcc->alloc_tx(vcc,eff))) {
@@ -437,7 +436,7 @@ int atm_sendmsg(struct socket *sock,struct msghdr *m,int total_len,
                }
        }
        set_current_state(TASK_RUNNING);
-       remove_wait_queue(&vcc->wsleep,&wait);
+       remove_wait_queue(&vcc->sleep,&wait);
        if (error) return error;
        skb->dev = NULL; /* for paths shared with net_device interfaces */
        ATM_SKB(skb)->iovcnt = 0;
@@ -459,7 +458,6 @@ unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait)
 
        vcc = ATM_SD(sock);
        poll_wait(file,&vcc->sleep,wait);
-       poll_wait(file,&vcc->wsleep,wait);
        mask = 0;
        if (skb_peek(&vcc->recvq) || skb_peek(&vcc->listenq))
                mask |= POLLIN | POLLRDNORM;
index cbd2e4edfd726dad627e1a1dcd58b27063951810..faf1866ac32a58456bab1309deada6213d2c6976 100644 (file)
@@ -1,6 +1,6 @@
 /* net/atm/common.h - ATM sockets (common part for PVC and SVC) */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #ifndef NET_ATM_COMMON_H
@@ -27,9 +27,6 @@ int atm_getsockopt(struct socket *sock,int level,int optname,char *optval,
 int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci);
 void atm_release_vcc_sk(struct sock *sk,int free_sk);
 int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);
-/* -- now in atmdev.h:
-void atm_async_release_vcc(struct atm_vcc *vcc,int reply);
-*/
 void atm_shutdown_dev(struct atm_dev *dev);
 
 int atm_proc_init(void);
index 469685703ea22f3429a29ca0b8c57e6124e19b2e..448826dd25915b277401eef5aa515a088c3096cc 100644 (file)
@@ -38,12 +38,10 @@ void atm_mpoa_init(void)
 
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-rwlock_t lane_bridge_hook_lock = RW_LOCK_UNLOCKED;
 struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
                                                unsigned char *addr) = NULL;
 void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) = NULL;
 #if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE)
-EXPORT_SYMBOL(lane_bridge_hook_lock);
 EXPORT_SYMBOL(br_fdb_get_hook);
 EXPORT_SYMBOL(br_fdb_put_hook);
 #endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */
index 701ece763f9bdee104a17ac73c6fff0dfd7280e2..96f2877cf528fe8c38700fb4561bf154842f0d65 100644 (file)
@@ -34,7 +34,7 @@
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
 #include <linux/if_bridge.h>
 #include "../bridge/br_private.h"
-unsigned char bridge_ula[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
+static unsigned char bridge_ula[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
 #endif
 
 /* Modular too */
@@ -472,11 +472,8 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
                         mesg->content.proxy.mac_addr[2], mesg->content.proxy.mac_addr[3],
                         mesg->content.proxy.mac_addr[4], mesg->content.proxy.mac_addr[5]);
 
-                read_lock(&lane_bridge_hook_lock);
-                if (br_fdb_get_hook == NULL || dev->br_port == NULL) {
-                        read_unlock(&lane_bridge_hook_lock);
+                if (br_fdb_get_hook == NULL || dev->br_port == NULL)
                         break;
-                }
 
                 f = br_fdb_get_hook(dev->br_port->br, mesg->content.proxy.mac_addr);
                 if (f != NULL &&
@@ -489,7 +486,6 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
                         skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
                         if (skb2 == NULL) {
                                 br_fdb_put_hook(f);
-                                read_unlock(&lane_bridge_hook_lock);
                                 break;
                         }
                         skb2->len = sizeof(struct atmlec_msg);
@@ -499,7 +495,6 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
                         wake_up(&priv->lecd->sleep);
                 }
                 if (f != NULL) br_fdb_put_hook(f);
-                read_unlock(&lane_bridge_hook_lock);
 #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
                 }
                 break;
@@ -696,7 +691,6 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
                         lec_arp_check_empties(priv, vcc, skb);
                 }
                 skb->dev = dev;
-               skb->rx_dev = NULL;
                 skb->data += 2; /* skip lec_id */
 #ifdef CONFIG_TR
                 if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev);
@@ -1079,8 +1073,8 @@ lec_arp_clear_vccs(struct lec_arp_table *entry)
         if (entry->recv_vcc) {
                 entry->recv_vcc->push = entry->old_recv_push;
 #if 0
-                set_bit(ATM_VF_RELEASED,&entry->vcc->flags);
-               clear_bit(ATM_VF_READY,&entry->vcc->flags);
+                set_bit(ATM_VF_RELEASED,&entry->recv_vcc->flags);
+               clear_bit(ATM_VF_READY,&entry->recv_vcc->flags);
                 entry->recv_vcc->push(entry->recv_vcc, NULL);
 #endif
                atm_async_release_vcc(entry->recv_vcc, -EPIPE);
index df08e6803ee4d5b80967f57bff6d7a739eef6e21..f40a37fa3f41876b2f3d73764906a415368e3fb3 100644 (file)
@@ -16,7 +16,6 @@
 
 #if defined (CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
 #include <linux/if_bridge.h>
-extern rwlock_t lane_bridge_hook_lock;
 struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
                                                 unsigned char *addr);
 void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
index deeb737f5f93bb2115e7cd146ebd75064dcdede5..1b3e13ad632dcda611002d72b9e2a30f2c4448f1 100644 (file)
@@ -62,7 +62,7 @@ static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *m
 static void set_mps_mac_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc);
 
 static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac,
-                          uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type);
+                         uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type);
 static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry);
 
 static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc);
@@ -76,25 +76,25 @@ static void mpc_timer_refresh(void);
 static void mpc_cache_check( unsigned long checking_time  );
 
 static struct llc_snap_hdr llc_snap_mpoa_ctrl = {
-        0xaa, 0xaa, 0x03,
-        {0x00, 0x00, 0x5e},
-        {0x00, 0x03}         /* For MPOA control PDUs */
+       0xaa, 0xaa, 0x03,
+       {0x00, 0x00, 0x5e},
+       {0x00, 0x03}         /* For MPOA control PDUs */
 };        
 static struct llc_snap_hdr llc_snap_mpoa_data = {
-        0xaa, 0xaa, 0x03,
-        {0x00, 0x00, 0x00},
-        {0x08, 0x00}         /* This is for IP PDUs only */
+       0xaa, 0xaa, 0x03,
+       {0x00, 0x00, 0x00},
+       {0x08, 0x00}         /* This is for IP PDUs only */
 };        
 static struct llc_snap_hdr llc_snap_mpoa_data_tagged = {
-        0xaa, 0xaa, 0x03,
-        {0x00, 0x00, 0x00},
-        {0x88, 0x4c}         /* This is for tagged data PDUs */
+       0xaa, 0xaa, 0x03,
+       {0x00, 0x00, 0x00},
+       {0x88, 0x4c}         /* This is for tagged data PDUs */
 };        
 
 static struct notifier_block mpoa_notifier = {
-        mpoa_event_listener,
-        NULL,
-        0
+       mpoa_event_listener,
+       NULL,
+       0
 };
 
 #ifdef CONFIG_PROC_FS
@@ -109,44 +109,44 @@ static struct timer_list mpc_timer;
 
 static struct mpoa_client *find_mpc_by_itfnum(int itf)
 {
-        struct mpoa_client *mpc;
-        
-        mpc = mpcs;  /* our global linked list */
-        while (mpc != NULL) {
-                if (mpc->dev_num == itf)
-                        return mpc;
-                mpc = mpc->next;    
-        }
-
-        return NULL;   /* not found */
+       struct mpoa_client *mpc;
+       
+       mpc = mpcs;  /* our global linked list */
+       while (mpc != NULL) {
+               if (mpc->dev_num == itf)
+                       return mpc;
+               mpc = mpc->next;    
+       }
+
+       return NULL;   /* not found */
 }
 
 static struct mpoa_client *find_mpc_by_vcc(struct atm_vcc *vcc)
 {
-        struct mpoa_client *mpc;
-        
-        mpc = mpcs;  /* our global linked list */
-        while (mpc != NULL) {
-                if (mpc->mpoad_vcc == vcc)
-                        return mpc;
-                mpc = mpc->next;
-        }
-
-        return NULL;   /* not found */
+       struct mpoa_client *mpc;
+       
+       mpc = mpcs;  /* our global linked list */
+       while (mpc != NULL) {
+               if (mpc->mpoad_vcc == vcc)
+                       return mpc;
+               mpc = mpc->next;
+       }
+
+       return NULL;   /* not found */
 }
 
 static struct mpoa_client *find_mpc_by_lec(struct net_device *dev)
 {
-        struct mpoa_client *mpc;
-        
-        mpc = mpcs;  /* our global linked list */
-        while (mpc != NULL) {
-                if (mpc->dev == dev)
-                        return mpc;
-                mpc = mpc->next;
-        }
-
-        return NULL;   /* not found */
+       struct mpoa_client *mpc;
+       
+       mpc = mpcs;  /* our global linked list */
+       while (mpc != NULL) {
+               if (mpc->dev == dev)
+                       return mpc;
+               mpc = mpc->next;
+       }
+
+       return NULL;   /* not found */
 }
 
 /*
@@ -158,42 +158,42 @@ static struct mpoa_client *find_mpc_by_lec(struct net_device *dev)
  */
 struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos)
 {
-        struct atm_mpoa_qos *entry;
+       struct atm_mpoa_qos *entry;
 
-        entry = atm_mpoa_search_qos(dst_ip);
-        if (entry != NULL) {
-                entry->qos = *qos;
-                return entry;
-        }
+       entry = atm_mpoa_search_qos(dst_ip);
+       if (entry != NULL) {
+               entry->qos = *qos;
+               return entry;
+       }
 
-        entry = kmalloc(sizeof(struct atm_qos), GFP_KERNEL);
-        if (entry == NULL) {
-                printk("mpoa: atm_mpoa_add_qos: out of memory\n");
-                return entry;
-        }
+       entry = kmalloc(sizeof(struct atm_qos), GFP_KERNEL);
+       if (entry == NULL) {
+               printk("mpoa: atm_mpoa_add_qos: out of memory\n");
+               return entry;
+       }
 
-        entry->ipaddr = dst_ip;
-        entry->qos = *qos;
+       entry->ipaddr = dst_ip;
+       entry->qos = *qos;
 
-        entry->next = qos_head;
-        qos_head = entry;
+       entry->next = qos_head;
+       qos_head = entry;
 
-        return entry;
+       return entry;
 }
 
 struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip)
 {
-        struct atm_mpoa_qos *qos;
+       struct atm_mpoa_qos *qos;
 
-        qos = qos_head;
-        while( qos != NULL ){
-                if(qos->ipaddr == dst_ip) {
-                        break;
+       qos = qos_head;
+       while( qos != NULL ){
+               if(qos->ipaddr == dst_ip) {
+                       break;
                }
-                qos = qos->next;
-        }
+               qos = qos->next;
+       }
 
-        return qos;
+       return qos;
 }        
 
 /*
@@ -202,26 +202,26 @@ struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip)
 int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry)
 {
 
-        struct atm_mpoa_qos *curr;
-
-        if (entry == NULL) return 0;
-        if (entry == qos_head) {
-                qos_head = qos_head->next;
-                kfree(entry);
-                return 1;
-        }
-
-        curr = qos_head;
-        while (curr != NULL) {
-                if (curr->next == entry) {
-                        curr->next = entry->next;
-                        kfree(entry);
-                        return 1;
-                }
-                curr = curr->next;
-        }
-
-        return 0;
+       struct atm_mpoa_qos *curr;
+
+       if (entry == NULL) return 0;
+       if (entry == qos_head) {
+               qos_head = qos_head->next;
+               kfree(entry);
+               return 1;
+       }
+
+       curr = qos_head;
+       while (curr != NULL) {
+               if (curr->next == entry) {
+                       curr->next = entry->next;
+                       kfree(entry);
+                       return 1;
+               }
+               curr = curr->next;
+       }
+
+       return 0;
 }
 
 void atm_mpoa_disp_qos(char *page, int *len)
@@ -238,9 +238,9 @@ void atm_mpoa_disp_qos(char *page, int *len)
        ipaddr[sizeof(ipaddr)-1] = '\0';
        while (qos != NULL) {
                ip = (unsigned char *)&qos->ipaddr;
-               sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
-               *len += sprintf(page + *len, "%-16s\n     %-7d %-7d %-7d %-7d %-7d\n     %-7d %-7d %-7d %-7d %-7d\n",
-                               ipaddr,
+               sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(ip));
+               *len += sprintf(page + *len, "%%u.%u.%u.%u\n     %-7d %-7d %-7d %-7d %-7d\n     %-7d %-7d %-7d %-7d %-7d\n",
+                               NIPQUAD(ipaddr),
                                qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu,
                                qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu);
                qos = qos->next;
@@ -251,28 +251,26 @@ void atm_mpoa_disp_qos(char *page, int *len)
 
 static struct net_device *find_lec_by_itfnum(int itf)
 {
-        extern struct atm_lane_ops atm_lane_ops; /* in common.c */
-        
-        if (atm_lane_ops.get_lecs == NULL)
-                return NULL;
+       extern struct atm_lane_ops atm_lane_ops; /* in common.c */
+       
+       if (atm_lane_ops.get_lecs == NULL)
+               return NULL;
 
-        return atm_lane_ops.get_lecs()[itf]; /* FIXME: something better */
+       return atm_lane_ops.get_lecs()[itf]; /* FIXME: something better */
 }
 
 static struct mpoa_client *alloc_mpc(void)
 {
-        struct mpoa_client *mpc;
-
-        mpc = kmalloc(sizeof (struct mpoa_client), GFP_KERNEL);
-        if (mpc == NULL)
-                return NULL;
-        memset(mpc, 0, sizeof(struct mpoa_client));
-#if 0 /* compiler seems to barf on this */
-        mpc->ingress_lock = RW_LOCK_UNLOCKED;
-        mpc->egress_lock  = RW_LOCK_UNLOCKED;
-#endif
-        mpc->next = mpcs;
-        atm_mpoa_init_cache(mpc);
+       struct mpoa_client *mpc;
+
+       mpc = kmalloc(sizeof (struct mpoa_client), GFP_KERNEL);
+       if (mpc == NULL)
+               return NULL;
+       memset(mpc, 0, sizeof(struct mpoa_client));
+       mpc->ingress_lock = RW_LOCK_UNLOCKED;
+       mpc->egress_lock  = RW_LOCK_UNLOCKED;
+       mpc->next = mpcs;
+       atm_mpoa_init_cache(mpc);
 
        mpc->parameters.mpc_p1 = MPC_P1;
        mpc->parameters.mpc_p2 = MPC_P2;
@@ -281,9 +279,9 @@ static struct mpoa_client *alloc_mpc(void)
        mpc->parameters.mpc_p5 = MPC_P5; 
        mpc->parameters.mpc_p6 = MPC_P6;
        
-        mpcs = mpc;
+       mpcs = mpc;
        
-        return mpc;
+       return mpc;
 }
 
 /*
@@ -295,58 +293,58 @@ static struct mpoa_client *alloc_mpc(void)
  */
 static void start_mpc(struct mpoa_client *mpc, struct net_device *dev)
 {
-        
-        dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name); 
-        if (dev->hard_start_xmit == NULL) {
-                printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n",
-                       dev->name);
-                return;
-        }
-        mpc->old_hard_start_xmit = dev->hard_start_xmit;
-        dev->hard_start_xmit = mpc_send_packet;
-
-        return;
+       
+       dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name); 
+       if (dev->hard_start_xmit == NULL) {
+               printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n",
+                      dev->name);
+               return;
+       }
+       mpc->old_hard_start_xmit = dev->hard_start_xmit;
+       dev->hard_start_xmit = mpc_send_packet;
+
+       return;
 }
 
 static void stop_mpc(struct mpoa_client *mpc)
 {
-        
-        dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name); 
-
-        /* Lets not nullify lec device's dev->hard_start_xmit */
-        if (mpc->dev->hard_start_xmit != mpc_send_packet) {
-                dprintk(" mpc already stopped, not fatal\n");
-                return;
-        }
-        dprintk("\n");
-        mpc->dev->hard_start_xmit = mpc->old_hard_start_xmit;
-        mpc->old_hard_start_xmit = NULL;
+       
+       dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name); 
+
+       /* Lets not nullify lec device's dev->hard_start_xmit */
+       if (mpc->dev->hard_start_xmit != mpc_send_packet) {
+               dprintk(" mpc already stopped, not fatal\n");
+               return;
+       }
+       dprintk("\n");
+       mpc->dev->hard_start_xmit = mpc->old_hard_start_xmit;
+       mpc->old_hard_start_xmit = NULL;
        /* close_shortcuts(mpc);    ??? FIXME */
-        
-        return;
+       
+       return;
 }
 
 static const char * __attribute__ ((unused)) mpoa_device_type_string(char type)
 {
-        switch(type) {
-        case NON_MPOA:
-                return "non-MPOA device";
-                break;
-        case MPS:
-                return "MPS";
-                break;
-        case MPC:
-                return "MPC";
-                break;
-        case MPS_AND_MPC:
-                return "both MPS and MPC";
-                break;
-        default:
-                return "unspecified (non-MPOA) device";
-                break;
-        }
-
-        return ""; /* not reached */
+       switch(type) {
+       case NON_MPOA:
+               return "non-MPOA device";
+               break;
+       case MPS:
+               return "MPS";
+               break;
+       case MPC:
+               return "MPC";
+               break;
+       case MPS_AND_MPC:
+               return "both MPS and MPC";
+               break;
+       default:
+               return "unspecified (non-MPOA) device";
+               break;
+       }
+
+       return ""; /* not reached */
 }
 
 /*
@@ -363,77 +361,77 @@ static const char * __attribute__ ((unused)) mpoa_device_type_string(char type)
  *
  */
 static void lane2_assoc_ind(struct net_device *dev, uint8_t *mac_addr,
-                            uint8_t *tlvs, uint32_t sizeoftlvs)
+                           uint8_t *tlvs, uint32_t sizeoftlvs)
 {
-        uint32_t type;
-        uint8_t length, mpoa_device_type, number_of_mps_macs;
-        uint8_t *end_of_tlvs;
-        struct mpoa_client *mpc;
-        
-        mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */
-        dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name);
-        dprintk("total length of all TLVs %d\n", sizeoftlvs);
+       uint32_t type;
+       uint8_t length, mpoa_device_type, number_of_mps_macs;
+       uint8_t *end_of_tlvs;
+       struct mpoa_client *mpc;
+       
+       mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */
+       dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name);
+       dprintk("total length of all TLVs %d\n", sizeoftlvs);
        mpc = find_mpc_by_lec(dev); /* Sampo-Fix: moved here from below */
-        if (mpc == NULL) {
-                printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev->name);
-                return;
-        }
-        end_of_tlvs = tlvs + sizeoftlvs;
-        while (end_of_tlvs - tlvs >= 5) {
-                type = (tlvs[0] << 24) | (tlvs[1] << 16) | (tlvs[2] << 8) | tlvs[3];
-                length = tlvs[4];
-                tlvs += 5;
-                dprintk("    type 0x%x length %02x\n", type, length);
-                if (tlvs + length > end_of_tlvs) {
-                        printk("TLV value extends past its buffer, aborting parse\n");
-                        return;
-                }
-                
-                if (type == 0) {
-                        printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name);
-                        return;
+       if (mpc == NULL) {
+               printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev->name);
+               return;
+       }
+       end_of_tlvs = tlvs + sizeoftlvs;
+       while (end_of_tlvs - tlvs >= 5) {
+               type = (tlvs[0] << 24) | (tlvs[1] << 16) | (tlvs[2] << 8) | tlvs[3];
+               length = tlvs[4];
+               tlvs += 5;
+               dprintk("    type 0x%x length %02x\n", type, length);
+               if (tlvs + length > end_of_tlvs) {
+                       printk("TLV value extends past its buffer, aborting parse\n");
+                       return;
+               }
+               
+               if (type == 0) {
+                       printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name);
+                       return;
                }
 
-                if (type != TLV_MPOA_DEVICE_TYPE) {
-                        tlvs += length;
-                        continue;  /* skip other TLVs */
-                }
-                mpoa_device_type = *tlvs++;
-                number_of_mps_macs = *tlvs++;
-                dprintk("mpoa: (%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type));
-                if (mpoa_device_type == MPS_AND_MPC &&
-                    length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */
-                        printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
-                               dev->name);
-                        continue;
-                }
-                if ((mpoa_device_type == MPS || mpoa_device_type == MPC)
-                    && length < 22 + number_of_mps_macs*ETH_ALEN) {
-                        printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
-                                dev->name);
-                        continue;
-                }
-                if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) {
-                        dprintk("ignoring non-MPS device\n");
-                        if (mpoa_device_type == MPC) tlvs += 20;
-                        continue;  /* we are only interested in MPSs */
-                }
-                if (number_of_mps_macs == 0 && mpoa_device_type == MPS_AND_MPC) {
-                        printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev->name);
-                        continue;  /* someone should read the spec */
-                }
-                dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs);
-                
-                /* ok, now we can go and tell our daemon the control address of MPS */
-                send_set_mps_ctrl_addr(tlvs, mpc);
-                
-                tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type);
-                if (tlvs == NULL) return;
-        }
-        if (end_of_tlvs - tlvs != 0)
-                printk("mpoa: (%s) lane2_assoc_ind: ignoring %d bytes of trailing TLV carbage\n",
-                       dev->name, end_of_tlvs - tlvs);
-        return;
+               if (type != TLV_MPOA_DEVICE_TYPE) {
+                       tlvs += length;
+                       continue;  /* skip other TLVs */
+               }
+               mpoa_device_type = *tlvs++;
+               number_of_mps_macs = *tlvs++;
+               dprintk("mpoa: (%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type));
+               if (mpoa_device_type == MPS_AND_MPC &&
+                   length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */
+                       printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
+                              dev->name);
+                       continue;
+               }
+               if ((mpoa_device_type == MPS || mpoa_device_type == MPC)
+                   && length < 22 + number_of_mps_macs*ETH_ALEN) {
+                       printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
+                               dev->name);
+                       continue;
+               }
+               if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) {
+                       dprintk("ignoring non-MPS device\n");
+                       if (mpoa_device_type == MPC) tlvs += 20;
+                       continue;  /* we are only interested in MPSs */
+               }
+               if (number_of_mps_macs == 0 && mpoa_device_type == MPS_AND_MPC) {
+                       printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev->name);
+                       continue;  /* someone should read the spec */
+               }
+               dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs);
+               
+               /* ok, now we can go and tell our daemon the control address of MPS */
+               send_set_mps_ctrl_addr(tlvs, mpc);
+               
+               tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type);
+               if (tlvs == NULL) return;
+       }
+       if (end_of_tlvs - tlvs != 0)
+               printk("mpoa: (%s) lane2_assoc_ind: ignoring %d bytes of trailing TLV carbage\n",
+                      dev->name, end_of_tlvs - tlvs);
+       return;
 }
 
 /*
@@ -442,91 +440,94 @@ static void lane2_assoc_ind(struct net_device *dev, uint8_t *mac_addr,
  * For a freshly allocated MPOA client mpc->mps_macs == 0.
  */
 static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac,
-                          uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type)
+                         uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type)
 {
-        int num_macs;
-        num_macs = (mps_macs > 1) ? mps_macs : 1;
-
-        if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */
-                if (mpc->number_of_mps_macs != 0) kfree(mpc->mps_macs);
-                mpc->number_of_mps_macs = 0;
-                mpc->mps_macs = kmalloc(num_macs*ETH_ALEN, GFP_KERNEL);
-                if (mpc->mps_macs == NULL) {
-                        printk("mpoa: (%s) copy_macs: out of mem\n", mpc->dev->name);
-                        return NULL;
-                }
-        }
-        memcpy(mpc->mps_macs, router_mac, ETH_ALEN);
-        tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20;
-        if (mps_macs > 0)
-                memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN);
-        tlvs += mps_macs*ETH_ALEN;
-        mpc->number_of_mps_macs = num_macs;
-
-        return tlvs;
+       int num_macs;
+       num_macs = (mps_macs > 1) ? mps_macs : 1;
+
+       if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */
+               if (mpc->number_of_mps_macs != 0) kfree(mpc->mps_macs);
+               mpc->number_of_mps_macs = 0;
+               mpc->mps_macs = kmalloc(num_macs*ETH_ALEN, GFP_KERNEL);
+               if (mpc->mps_macs == NULL) {
+                       printk("mpoa: (%s) copy_macs: out of mem\n", mpc->dev->name);
+                       return NULL;
+               }
+       }
+       memcpy(mpc->mps_macs, router_mac, ETH_ALEN);
+       tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20;
+       if (mps_macs > 0)
+               memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN);
+       tlvs += mps_macs*ETH_ALEN;
+       mpc->number_of_mps_macs = num_macs;
+
+       return tlvs;
 }
 
-/* FIXME: tarvitsee työtä */
 static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
 {
-        in_cache_entry *entry;
-        struct iphdr *iph;
-        char *buff;
-        uint32_t ipaddr = 0;
-
-        static struct {
-                struct llc_snap_hdr hdr;
-                uint32_t tag;
-        } tagged_llc_snap_hdr = {
-                {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
-                0
-        };
-
-        buff = skb->data + mpc->dev->hard_header_len;
-        iph = (struct iphdr *)buff;
+       in_cache_entry *entry;
+       struct iphdr *iph;
+       char *buff;
+       uint32_t ipaddr = 0;
+
+       static struct {
+               struct llc_snap_hdr hdr;
+               uint32_t tag;
+       } tagged_llc_snap_hdr = {
+               {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
+               0
+       };
+
+       buff = skb->data + mpc->dev->hard_header_len;
+       iph = (struct iphdr *)buff;
        ipaddr = iph->daddr;
 
-        ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr);        
-
-        entry = mpc->in_ops->search(ipaddr, mpc);
-        if (entry == NULL) {
-                mpc->in_ops->new_entry(ipaddr, mpc);
-                return 1;
-        }
-        if (mpc->in_ops->cache_hit(entry, mpc) != OPEN){   /* threshold not exceeded or VCC not ready */
-                ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name);        
-                return 1;
-        }
-
-        ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name);        
-        /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */
-        if (iph->ttl <= 1) {
-              ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl);        
-              return 1;
-        }
-        iph->ttl--;
-        iph->check = 0;
-        iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
-        if (entry->ctrl_info.tag != 0) {
-                ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", mpc->dev->name, entry->ctrl_info.tag);
-                tagged_llc_snap_hdr.tag = entry->ctrl_info.tag;
-                skb_pull(skb, ETH_HLEN);                       /* get rid of Eth header */
-                skb_push(skb, sizeof(tagged_llc_snap_hdr));    /* add LLC/SNAP header   */
-                memcpy(skb->data, &tagged_llc_snap_hdr, sizeof(tagged_llc_snap_hdr));
-        } else {
-                skb_pull(skb, ETH_HLEN);                        /* get rid of Eth header */
-                skb_push(skb, sizeof(struct llc_snap_hdr));     /* add LLC/SNAP header + tag  */
-                memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
-        }
-
-        atomic_add(skb->truesize, &entry->shortcut->tx_inuse);
+       ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr);        
+
+       entry = mpc->in_ops->get(ipaddr, mpc);
+       if (entry == NULL) {
+               entry = mpc->in_ops->add_entry(ipaddr, mpc);
+               if (entry != NULL) mpc->in_ops->put(entry);
+               return 1;
+       }
+       if (mpc->in_ops->cache_hit(entry, mpc) != OPEN){   /* threshold not exceeded or VCC not ready */
+               ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name);        
+               mpc->in_ops->put(entry);
+               return 1;
+       }
+
+       ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name);        
+       /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */
+       if (iph->ttl <= 1) {
+               ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl);        
+               mpc->in_ops->put(entry);
+               return 1;
+       }
+       iph->ttl--;
+       iph->check = 0;
+       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+
+       if (entry->ctrl_info.tag != 0) {
+               ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", mpc->dev->name, entry->ctrl_info.tag);
+               tagged_llc_snap_hdr.tag = entry->ctrl_info.tag;
+               skb_pull(skb, ETH_HLEN);                       /* get rid of Eth header */
+               skb_push(skb, sizeof(tagged_llc_snap_hdr));    /* add LLC/SNAP header   */
+               memcpy(skb->data, &tagged_llc_snap_hdr, sizeof(tagged_llc_snap_hdr));
+       } else {
+               skb_pull(skb, ETH_HLEN);                        /* get rid of Eth header */
+               skb_push(skb, sizeof(struct llc_snap_hdr));     /* add LLC/SNAP header + tag  */
+               memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
+       }
+
+       atomic_add(skb->truesize, &entry->shortcut->tx_inuse);
        ATM_SKB(skb)->iovcnt = 0; /* just to be safe ... */
        ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
-        entry->shortcut->send(entry->shortcut, skb);
+       entry->shortcut->send(entry->shortcut, skb);
        entry->packets_fwded++;
+       mpc->in_ops->put(entry);
 
-        return 0;
+       return 0;
 }
 
 /*
@@ -534,75 +535,77 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
  */
 static int mpc_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-        int retval;
-        struct mpoa_client *mpc;
-        struct ethhdr *eth;
-        int i = 0;
-        
-        mpc = find_mpc_by_lec(dev); /* this should NEVER fail */
-        if(mpc == NULL) {
-               printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev->name);
-                goto non_ip;
-       }
-
-        eth = (struct ethhdr *)skb->data;
-        if (eth->h_proto != htons(ETH_P_IP))
-                goto non_ip; /* Multi-Protocol Over ATM :-) */
-
-        while (i < mpc->number_of_mps_macs) {
-                if (memcmp(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN), ETH_ALEN) == 0)
-                        if ( send_via_shortcut(skb, mpc) == 0 )           /* try shortcut */
-                                return 0;                                 /* success!     */
-                i++;
-        }
+       int retval;
+       struct mpoa_client *mpc;
+       struct ethhdr *eth;
+       int i = 0;
+       
+       mpc = find_mpc_by_lec(dev); /* this should NEVER fail */
+       if(mpc == NULL) {
+               printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev->name);
+               goto non_ip;
+       }
+
+       eth = (struct ethhdr *)skb->data;
+       if (eth->h_proto != htons(ETH_P_IP))
+               goto non_ip; /* Multi-Protocol Over ATM :-) */
+
+       while (i < mpc->number_of_mps_macs) {
+               if (memcmp(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN), ETH_ALEN) == 0)
+                       if ( send_via_shortcut(skb, mpc) == 0 )           /* try shortcut */
+                               return 0;                                 /* success!     */
+               i++;
+       }
 
  non_ip:
-        retval = mpc->old_hard_start_xmit(skb,dev);
-        
-        return retval;
+       retval = mpc->old_hard_start_xmit(skb,dev);
+       
+       return retval;
 }
 
 int atm_mpoa_vcc_attach(struct atm_vcc *vcc, long arg)
 {
-        int bytes_left;
-        struct mpoa_client *mpc;
-        struct atmmpc_ioc ioc_data;
-        in_cache_entry *in_entry;
-        uint32_t  ipaddr;
+       int bytes_left;
+       struct mpoa_client *mpc;
+       struct atmmpc_ioc ioc_data;
+       in_cache_entry *in_entry;
+       uint32_t  ipaddr;
        unsigned char *ip;
 
-        bytes_left = copy_from_user(&ioc_data, (void *)arg, sizeof(struct atmmpc_ioc));
-        if (bytes_left != 0) {
-                printk("mpoa: mpc_vcc_attach: Short read (missed %d bytes) from userland\n", bytes_left);
-                return -EFAULT;
-        }
-        ipaddr = ioc_data.ipaddr;
-        if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
-                return -EINVAL;
-        
-        mpc = find_mpc_by_itfnum(ioc_data.dev_num);
-        if (mpc == NULL)
-                return -EINVAL;
-        
-        if (ioc_data.type == MPC_SOCKET_INGRESS) {
-                in_entry = mpc->in_ops->search(ipaddr, mpc);
-                if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) {
-                        printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n",
-                                mpc->dev->name);
-                        return -EINVAL;
-                }
+       bytes_left = copy_from_user(&ioc_data, (void *)arg, sizeof(struct atmmpc_ioc));
+       if (bytes_left != 0) {
+               printk("mpoa: mpc_vcc_attach: Short read (missed %d bytes) from userland\n", bytes_left);
+               return -EFAULT;
+       }
+       ipaddr = ioc_data.ipaddr;
+       if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
+               return -EINVAL;
+       
+       mpc = find_mpc_by_itfnum(ioc_data.dev_num);
+       if (mpc == NULL)
+               return -EINVAL;
+       
+       if (ioc_data.type == MPC_SOCKET_INGRESS) {
+               in_entry = mpc->in_ops->get(ipaddr, mpc);
+               if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) {
+                       printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n",
+                               mpc->dev->name);
+                       if (in_entry != NULL) mpc->in_ops->put(in_entry);
+                       return -EINVAL;
+               }
                ip = (unsigned char*)&in_entry->ctrl_info.in_dst_ip;
-                printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n",
-                       mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
-                in_entry->shortcut = vcc;
-        } else {
-                printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc->dev->name);
-        }
-        
-        vcc->proto_data = mpc->dev;
-        vcc->push = mpc_push;
-
-        return 0;
+               printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n",
+                      mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+               in_entry->shortcut = vcc;
+               mpc->in_ops->put(in_entry);
+       } else {
+               printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc->dev->name);
+       }
+
+       vcc->proto_data = mpc->dev;
+       vcc->push = mpc_push;
+
+       return 0;
 }
 
 /*
@@ -610,251 +613,250 @@ int atm_mpoa_vcc_attach(struct atm_vcc *vcc, long arg)
  */
 static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev)
 {
-        struct mpoa_client *mpc;
-        in_cache_entry *in_entry;
-        eg_cache_entry *eg_entry;
-        
-        mpc = find_mpc_by_lec(dev);
-        if (mpc == NULL) {
-                printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev->name);
-                return;
-        }
-
-        dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
-        in_entry = mpc->in_ops->search_by_vcc(vcc, mpc);
-        if (in_entry) {
-                unsigned char *ip __attribute__ ((unused)) =
+       struct mpoa_client *mpc;
+       in_cache_entry *in_entry;
+       eg_cache_entry *eg_entry;
+       
+       mpc = find_mpc_by_lec(dev);
+       if (mpc == NULL) {
+               printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev->name);
+               return;
+       }
+
+       dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
+       in_entry = mpc->in_ops->get_by_vcc(vcc, mpc);
+       if (in_entry) {
+               unsigned char *ip __attribute__ ((unused)) =
                    (unsigned char *)&in_entry->ctrl_info.in_dst_ip;
-               dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
-                       mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
-                in_entry->shortcut = NULL;
-        }
-        eg_entry = mpc->eg_ops->search_by_vcc(vcc, mpc);
-        if (eg_entry) {
-               dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", mpc->dev->name);
-                eg_entry->shortcut = NULL;
-        }
-
-        if (in_entry == NULL && eg_entry == NULL)
-                dprintk("mpoa: (%s) mpc_vcc_close:  unused vcc closed\n", dev->name);
-
-        return;
+               dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
+                      mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+               in_entry->shortcut = NULL;
+               mpc->in_ops->put(in_entry);
+       }
+       eg_entry = mpc->eg_ops->get_by_vcc(vcc, mpc);
+       if (eg_entry) {
+               dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", mpc->dev->name);
+               eg_entry->shortcut = NULL;
+               mpc->eg_ops->put(eg_entry);
+       }
+
+       if (in_entry == NULL && eg_entry == NULL)
+               dprintk("mpoa: (%s) mpc_vcc_close:  unused vcc closed\n", dev->name);
+
+       return;
 }
 
 static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
 {
-        struct net_device *dev = (struct net_device *)vcc->proto_data;
-        struct sk_buff *new_skb;
-        eg_cache_entry *eg;
-        struct mpoa_client *mpc;
+       struct net_device *dev = (struct net_device *)vcc->proto_data;
+       struct sk_buff *new_skb;
+       eg_cache_entry *eg;
+       struct mpoa_client *mpc;
        uint32_t tag;
-        char *tmp;
-        
-        ddprintk("mpoa: (%s) mpc_push:\n", dev->name);
-        if (skb == NULL) {
-                dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name);
-                mpc_vcc_close(vcc, dev);
-                return;
-        }
-        
-        skb->dev = dev;
-        if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
-                dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
-                skb_queue_tail(&vcc->recvq, skb);           /* Pass control packets to daemon */
-                wake_up(&vcc->sleep);
-                return;
-        }
-
-        /* data coming over the shortcut */
-        atm_return(vcc, skb->truesize);
+       char *tmp;
+       
+       ddprintk("mpoa: (%s) mpc_push:\n", dev->name);
+       if (skb == NULL) {
+               dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name);
+               mpc_vcc_close(vcc, dev);
+               return;
+       }
+       
+       skb->dev = dev;
+       if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
+               dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
+               skb_queue_tail(&vcc->recvq, skb);           /* Pass control packets to daemon */
+               wake_up(&vcc->sleep);
+               return;
+       }
+
+       /* data coming over the shortcut */
+       atm_return(vcc, skb->truesize);
 
        mpc = find_mpc_by_lec(dev);
-        if (mpc == NULL) {
-                printk("mpoa: (%s) mpc_push: unknown MPC\n", dev->name);
-                return;
-        }
+       if (mpc == NULL) {
+               printk("mpoa: (%s) mpc_push: unknown MPC\n", dev->name);
+               return;
+       }
 
-        if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */
-                ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev->name);
+       if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */
+               ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev->name);
 
-        } else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */
-                printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev->name);
-                printk("           mpc_push: non-tagged data unsupported, purging\n");
-               kfree_skb(skb);
-                return;
-        } else {
-                printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev->name);
-               kfree_skb(skb);
-                return;
-        }
-
-        tmp = skb->data + sizeof(struct llc_snap_hdr);
-        tag = *(uint32_t *)tmp;
-
-        eg = mpc->eg_ops->search_by_tag(tag, mpc);
-        if (eg == NULL) {
-                printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n",
-                       dev->name,tag);
-                purge_egress_shortcut(vcc, NULL);
-                kfree_skb(skb);
-                return;
-        }
-        
-        /*
-         * See if ingress MPC is using shortcut we opened as a return channel.
-         * This means we have a bi-directional vcc opened by us.
-         */ 
-        if (eg->shortcut == NULL) {
-                eg->shortcut = vcc;
-                printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name);
-        }
-
-        skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); /* get rid of LLC/SNAP header */
-        new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); /* LLC/SNAP is shorter than MAC header :( */
-        kfree_skb(skb);
-        if (new_skb == NULL) return;
-        skb_push(new_skb, eg->ctrl_info.DH_length);     /* add MAC header */
-        memcpy(new_skb->data, eg->ctrl_info.DLL_header, eg->ctrl_info.DH_length);
-        new_skb->protocol = eth_type_trans(new_skb, dev);
-        new_skb->nh.raw = new_skb->data;
+       } else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */
+               printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev->name);
+               printk("           mpc_push: non-tagged data unsupported, purging\n");
+               dev_kfree_skb_any(skb);
+               return;
+       } else {
+               printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev->name);
+               dev_kfree_skb_any(skb);
+               return;
+       }
+
+       tmp = skb->data + sizeof(struct llc_snap_hdr);
+       tag = *(uint32_t *)tmp;
+
+       eg = mpc->eg_ops->get_by_tag(tag, mpc);
+       if (eg == NULL) {
+               printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n",
+                      dev->name,tag);
+               purge_egress_shortcut(vcc, NULL);
+               dev_kfree_skb_any(skb);
+               return;
+       }
+       
+       /*
+        * See if ingress MPC is using shortcut we opened as a return channel.
+        * This means we have a bi-directional vcc opened by us.
+        */ 
+       if (eg->shortcut == NULL) {
+               eg->shortcut = vcc;
+               printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name);
+       }
+
+       skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); /* get rid of LLC/SNAP header */
+       new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); /* LLC/SNAP is shorter than MAC header :( */
+       dev_kfree_skb_any(skb);
+       if (new_skb == NULL){
+               mpc->eg_ops->put(eg);
+               return;
+       }
+       skb_push(new_skb, eg->ctrl_info.DH_length);     /* add MAC header */
+       memcpy(new_skb->data, eg->ctrl_info.DLL_header, eg->ctrl_info.DH_length);
+       new_skb->protocol = eth_type_trans(new_skb, dev);
+       new_skb->nh.raw = new_skb->data;
 
        eg->latest_ip_addr = new_skb->nh.iph->saddr;
-        eg->packets_rcvd++;
-                
-        netif_rx(new_skb);
+       eg->packets_rcvd++;
+       mpc->eg_ops->put(eg);
+
+       netif_rx(new_skb);
 
-        return;
+       return;
 }
 
 static struct atmdev_ops mpc_ops = { /* only send is required */
-        close: mpoad_close,
-        send:  msg_from_mpoad
+       close:  mpoad_close,
+       send:   msg_from_mpoad
 };
 
 static struct atm_dev mpc_dev = {
-        &mpc_ops,       /* device operations    */
-        NULL,           /* PHY operations       */
-        "mpc",          /* device type name     */
-        42,             /* device index (dummy) */
-        NULL,           /* VCC table            */
-        NULL,           /* last VCC             */
-        NULL,           /* per-device data      */
-        NULL,           /* private PHY data     */
-        { 0 },          /* device flags         */
-        NULL,           /* local ATM address    */
-        { 0 }           /* no ESI               */
-        /* rest of the members will be 0 */
+       &mpc_ops,       /* device operations    */
+       NULL,           /* PHY operations       */
+       "mpc",          /* device type name     */
+       42,             /* device index (dummy) */
+       NULL,           /* VCC table            */
+       NULL,           /* last VCC             */
+       NULL,           /* per-device data      */
+       NULL,           /* private PHY data     */
+       { 0 },          /* device flags         */
+       NULL,           /* local ATM address    */
+       { 0 }           /* no ESI               */
+       /* rest of the members will be 0 */
 };
 
 int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
 {
-        struct mpoa_client *mpc;
-        struct lec_priv *priv;
-        
-        if (mpcs == NULL) {
-                init_timer(&mpc_timer);
-                mpc_timer_refresh();
-
-                /* This lets us now how our LECs are doing */
-                register_netdevice_notifier(&mpoa_notifier);
-        }
-        
-        mpc = find_mpc_by_itfnum(arg);
-        if (mpc == NULL) {
-                dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg);
-                mpc = alloc_mpc();
-                mpc->dev_num = arg;
-                mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */
-        }
-        if (mpc->mpoad_vcc) {
-                printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg);
-                return -EADDRINUSE;
-        }
-
-        if (mpc->dev) { /* check if the lec is LANE2 capable */
-                priv = (struct lec_priv *)mpc->dev->priv;
-                if (priv->lane_version < 2)
-                        mpc->dev = NULL;
+       struct mpoa_client *mpc;
+       struct lec_priv *priv;
+       
+       if (mpcs == NULL) {
+               init_timer(&mpc_timer);
+               mpc_timer_refresh();
+
+               /* This lets us now how our LECs are doing */
+               register_netdevice_notifier(&mpoa_notifier);
+       }
+       
+       mpc = find_mpc_by_itfnum(arg);
+       if (mpc == NULL) {
+               dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg);
+               mpc = alloc_mpc();
+               mpc->dev_num = arg;
+               mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */
+       }
+       if (mpc->mpoad_vcc) {
+               printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg);
+               return -EADDRINUSE;
+       }
+
+       if (mpc->dev) { /* check if the lec is LANE2 capable */
+               priv = (struct lec_priv *)mpc->dev->priv;
+               if (priv->lane_version < 2)
+                       mpc->dev = NULL;
                else
-                        priv->lane2_ops->associate_indicator = lane2_assoc_ind;  
-        }
+                       priv->lane2_ops->associate_indicator = lane2_assoc_ind;  
+       }
 
-        mpc->mpoad_vcc = vcc;
-        bind_vcc(vcc, &mpc_dev);
+       mpc->mpoad_vcc = vcc;
+       bind_vcc(vcc, &mpc_dev);
        set_bit(ATM_VF_META,&vcc->flags);
        set_bit(ATM_VF_READY,&vcc->flags);
 
-        if (mpc->dev) {
-                char empty[ATM_ESA_LEN];
-                memset(empty, 0, ATM_ESA_LEN);
-                
-                start_mpc(mpc, mpc->dev);
-                /* set address if mpcd e.g. gets killed and restarted.
-                 * If we do not do it now we have to wait for the next LE_ARP
-                 */
-                if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 )
-                        send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
-        }
-
-        MOD_INC_USE_COUNT;
-        return arg;
+       if (mpc->dev) {
+               char empty[ATM_ESA_LEN];
+               memset(empty, 0, ATM_ESA_LEN);
+               
+               start_mpc(mpc, mpc->dev);
+               /* set address if mpcd e.g. gets killed and restarted.
+                * If we do not do it now we have to wait for the next LE_ARP
+                */
+               if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 )
+                       send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
+       }
+
+       MOD_INC_USE_COUNT;
+       return arg;
 }
 
 static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc)
 {
-        struct k_message mesg;
+       struct k_message mesg;
 
-        memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN);
-        
-        mesg.type = SET_MPS_CTRL_ADDR;
-        memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN);
-        msg_to_mpoad(&mesg, mpc);
+       memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN);
+       
+       mesg.type = SET_MPS_CTRL_ADDR;
+       memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN);
+       msg_to_mpoad(&mesg, mpc);
 
-        return;
+       return;
 }
 
 static void mpoad_close(struct atm_vcc *vcc)
 {
-        unsigned long flags;
-        struct mpoa_client *mpc;
-        struct sk_buff *skb;
-
-        mpc = find_mpc_by_vcc(vcc);
-        if (mpc == NULL) {
-                printk("mpoa: mpoad_close: did not find MPC\n");
-                return;
-        }
-        if (!mpc->mpoad_vcc) {
-                printk("mpoa: mpoad_close: close for non-present mpoad\n");
-                return;
-        }
-        
-        mpc->mpoad_vcc = NULL;
-        if (mpc->dev) {
-                struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
-                priv->lane2_ops->associate_indicator = NULL;
-                stop_mpc(mpc);
-        }
-
-        /* clear the caches */
-        write_lock_irqsave(&mpc->ingress_lock, flags);
-        while(mpc->in_ops->cache_remove(mpc->in_cache, mpc));
-        write_unlock_irqrestore(&mpc->ingress_lock, flags);
-
-        write_lock_irqsave(&mpc->egress_lock, flags);
-        while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc));
-        write_unlock_irqrestore(&mpc->egress_lock, flags);
+       struct mpoa_client *mpc;
+       struct sk_buff *skb;
+
+       mpc = find_mpc_by_vcc(vcc);
+       if (mpc == NULL) {
+               printk("mpoa: mpoad_close: did not find MPC\n");
+               return;
+       }
+       if (!mpc->mpoad_vcc) {
+               printk("mpoa: mpoad_close: close for non-present mpoad\n");
+               return;
+       }
+       
+       mpc->mpoad_vcc = NULL;
+       if (mpc->dev) {
+               struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
+               priv->lane2_ops->associate_indicator = NULL;
+               stop_mpc(mpc);
+       }
+
+       mpc->in_ops->destroy_cache(mpc);
+       mpc->eg_ops->destroy_cache(mpc);
 
        while ( (skb = skb_dequeue(&vcc->recvq)) ){
-                atm_return(vcc, skb->truesize);
-                kfree_skb(skb);
-        }
-        
-        printk("mpoa: (%s) going down\n",
-                (mpc->dev) ? mpc->dev->name : "<unknown>");
-        MOD_DEC_USE_COUNT;
-
-        return;
+               atm_return(vcc, skb->truesize);
+               kfree_skb(skb);
+       }
+       
+       printk("mpoa: (%s) going down\n",
+               (mpc->dev) ? mpc->dev->name : "<unknown>");
+       MOD_DEC_USE_COUNT;
+
+       return;
 }
 
 /*
@@ -862,163 +864,163 @@ static void mpoad_close(struct atm_vcc *vcc)
  */
 static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
 {
-        
-        struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
-        struct k_message *mesg = (struct k_message*)skb->data;
-        atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
-        
-        if (mpc == NULL) {
-                printk("mpoa: msg_from_mpoad: no mpc found\n");
-                return 0;
-        }
-        dprintk("mpoa: (%s) msg_from_mpoad:", (mpc->dev) ? mpc->dev->name : "<unknown>");
-        switch(mesg->type) {
-        case MPOA_RES_REPLY_RCVD:
-               dprintk(" mpoa_res_reply_rcvd\n");
-                MPOA_res_reply_rcvd(mesg, mpc);
-                break;
-        case MPOA_TRIGGER_RCVD:
-               dprintk(" mpoa_trigger_rcvd\n");
-                MPOA_trigger_rcvd(mesg, mpc);
-                break;
-        case INGRESS_PURGE_RCVD:
-                dprintk(" nhrp_purge_rcvd\n");
-                ingress_purge_rcvd(mesg, mpc);
-                break;
-        case EGRESS_PURGE_RCVD:
-               dprintk(" egress_purge_reply_rcvd\n");
-                egress_purge_rcvd(mesg, mpc);
-                break;
-        case MPS_DEATH:
-               dprintk(" mps_death\n");
-                mps_death(mesg, mpc);
-                break;
-        case CACHE_IMPOS_RCVD:
-               dprintk(" cache_impos_rcvd\n");
-                MPOA_cache_impos_rcvd(mesg, mpc);
-                break;
-        case SET_MPC_CTRL_ADDR:
-                dprintk(" set_mpc_ctrl_addr\n");
-                set_mpc_ctrl_addr_rcvd(mesg, mpc);
-                break;
+       
+       struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
+       struct k_message *mesg = (struct k_message*)skb->data;
+       atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
+       
+       if (mpc == NULL) {
+               printk("mpoa: msg_from_mpoad: no mpc found\n");
+               return 0;
+       }
+       dprintk("mpoa: (%s) msg_from_mpoad:", (mpc->dev) ? mpc->dev->name : "<unknown>");
+       switch(mesg->type) {
+       case MPOA_RES_REPLY_RCVD:
+               dprintk(" mpoa_res_reply_rcvd\n");
+               MPOA_res_reply_rcvd(mesg, mpc);
+               break;
+       case MPOA_TRIGGER_RCVD:
+               dprintk(" mpoa_trigger_rcvd\n");
+               MPOA_trigger_rcvd(mesg, mpc);
+               break;
+       case INGRESS_PURGE_RCVD:
+               dprintk(" nhrp_purge_rcvd\n");
+               ingress_purge_rcvd(mesg, mpc);
+               break;
+       case EGRESS_PURGE_RCVD:
+               dprintk(" egress_purge_reply_rcvd\n");
+               egress_purge_rcvd(mesg, mpc);
+               break;
+       case MPS_DEATH:
+               dprintk(" mps_death\n");
+               mps_death(mesg, mpc);
+               break;
+       case CACHE_IMPOS_RCVD:
+               dprintk(" cache_impos_rcvd\n");
+               MPOA_cache_impos_rcvd(mesg, mpc);
+               break;
+       case SET_MPC_CTRL_ADDR:
+               dprintk(" set_mpc_ctrl_addr\n");
+               set_mpc_ctrl_addr_rcvd(mesg, mpc);
+               break;
        case SET_MPS_MAC_ADDR:
-               dprintk(" set_mps_mac_addr\n");
+               dprintk(" set_mps_mac_addr\n");
                set_mps_mac_addr_rcvd(mesg, mpc);
                break;
        case CLEAN_UP_AND_EXIT:
-                dprintk(" clean_up_and_exit\n");
-                clean_up(mesg, mpc, DIE);
-                break;
-        case RELOAD:
-                dprintk(" reload\n");
-                clean_up(mesg, mpc, RELOAD);
-                break;
-        case SET_MPC_PARAMS:
-                dprintk(" set_mpc_params\n");
-                mpc->parameters = mesg->content.params;
-                break;
-        default:
-                dprintk(" unknown message %d\n", mesg->type);
-                break;
-        }
-        kfree_skb(skb);
-
-        return 0;
+               dprintk(" clean_up_and_exit\n");
+               clean_up(mesg, mpc, DIE);
+               break;
+       case RELOAD:
+               dprintk(" reload\n");
+               clean_up(mesg, mpc, RELOAD);
+               break;
+       case SET_MPC_PARAMS:
+               dprintk(" set_mpc_params\n");
+               mpc->parameters = mesg->content.params;
+               break;
+       default:
+               dprintk(" unknown message %d\n", mesg->type);
+               break;
+       }
+       kfree_skb(skb);
+
+       return 0;
 }
 
+/* Remember that this function may not do things that sleep */
 int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
 {
-        struct sk_buff *skb;
-
-        if (mpc == NULL || !mpc->mpoad_vcc) {
-                printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type);
-                return -ENXIO;
-        }
-
-        skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
-        if (skb == NULL)
-                return -ENOMEM;
-        skb_put(skb, sizeof(struct k_message));
-        memcpy(skb->data, mesg, sizeof(struct k_message));
-        atm_force_charge(mpc->mpoad_vcc, skb->truesize);
-        skb_queue_tail(&mpc->mpoad_vcc->recvq, skb);
-        wake_up(&mpc->mpoad_vcc->sleep);
-
-        return 0;
+       struct sk_buff *skb;
+
+       if (mpc == NULL || !mpc->mpoad_vcc) {
+               printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type);
+               return -ENXIO;
+       }
+
+       skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
+       if (skb == NULL)
+               return -ENOMEM;
+       skb_put(skb, sizeof(struct k_message));
+       memcpy(skb->data, mesg, sizeof(struct k_message));
+       atm_force_charge(mpc->mpoad_vcc, skb->truesize);
+       skb_queue_tail(&mpc->mpoad_vcc->recvq, skb);
+       wake_up(&mpc->mpoad_vcc->sleep);
+
+       return 0;
 }
 
 static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned long event, void *dev_ptr)
 {
-        struct net_device *dev;
-        struct mpoa_client *mpc;
-        struct lec_priv *priv;
-
-        dev = (struct net_device *)dev_ptr;
-        if (dev->name == NULL || strncmp(dev->name, "lec", 3))
-                return NOTIFY_DONE; /* we are only interested in lec:s */
-        
-        switch (event) {
-        case NETDEV_REGISTER:       /* a new lec device was allocated */
-                priv = (struct lec_priv *)dev->priv;
-                if (priv->lane_version < 2)
-                        break;
-                priv->lane2_ops->associate_indicator = lane2_assoc_ind;
-                mpc = find_mpc_by_itfnum(priv->itfnum);
-                if (mpc == NULL) {
-                        dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n",
-                               dev->name);
-                        mpc = alloc_mpc();
-                        if (mpc == NULL) {
-                                printk("mpoa: mpoa_event_listener: no new mpc");
-                                break;
-                        }
-                }
-                mpc->dev_num = priv->itfnum;
-                mpc->dev = dev;
-                dprintk("mpoa: (%s) was initialized\n", dev->name);
-                break;
-        case NETDEV_UNREGISTER:
-                /* the lec device was deallocated */
-                mpc = find_mpc_by_lec(dev);
-                if (mpc == NULL)
-                        break;
-                dprintk("mpoa: device (%s) was deallocated\n", dev->name);
-                stop_mpc(mpc);
-                mpc->dev = NULL;
-                break;
-        case NETDEV_UP:
-                /* the dev was ifconfig'ed up */
-                mpc = find_mpc_by_lec(dev);
-                if (mpc == NULL)
-                        break;
-                if (mpc->mpoad_vcc != NULL) {
-                        start_mpc(mpc, dev);
-                }
-                break;
-        case NETDEV_DOWN:
-                /* the dev was ifconfig'ed down */
-                /* this means dev->start == 0 and
-                 * the flow of packets from the
-                 * upper layer stops
-                 */
-                mpc = find_mpc_by_lec(dev);
-                if (mpc == NULL)
-                        break;
-                if (mpc->mpoad_vcc != NULL) {
-                        stop_mpc(mpc);
-                }
-                break;
-        case NETDEV_REBOOT:
-        case NETDEV_CHANGE:
-        case NETDEV_CHANGEMTU:
-        case NETDEV_CHANGEADDR:
-        case NETDEV_GOING_DOWN:
-                break;
-        default:
-                break;
-        }
-
-        return NOTIFY_DONE;
+       struct net_device *dev;
+       struct mpoa_client *mpc;
+       struct lec_priv *priv;
+
+       dev = (struct net_device *)dev_ptr;
+       if (dev->name == NULL || strncmp(dev->name, "lec", 3))
+               return NOTIFY_DONE; /* we are only interested in lec:s */
+       
+       switch (event) {
+       case NETDEV_REGISTER:       /* a new lec device was allocated */
+               priv = (struct lec_priv *)dev->priv;
+               if (priv->lane_version < 2)
+                       break;
+               priv->lane2_ops->associate_indicator = lane2_assoc_ind;
+               mpc = find_mpc_by_itfnum(priv->itfnum);
+               if (mpc == NULL) {
+                       dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n",
+                              dev->name);
+                       mpc = alloc_mpc();
+                       if (mpc == NULL) {
+                               printk("mpoa: mpoa_event_listener: no new mpc");
+                               break;
+                       }
+               }
+               mpc->dev_num = priv->itfnum;
+               mpc->dev = dev;
+               dprintk("mpoa: (%s) was initialized\n", dev->name);
+               break;
+       case NETDEV_UNREGISTER:
+               /* the lec device was deallocated */
+               mpc = find_mpc_by_lec(dev);
+               if (mpc == NULL)
+                       break;
+               dprintk("mpoa: device (%s) was deallocated\n", dev->name);
+               stop_mpc(mpc);
+               mpc->dev = NULL;
+               break;
+       case NETDEV_UP:
+               /* the dev was ifconfig'ed up */
+               mpc = find_mpc_by_lec(dev);
+               if (mpc == NULL)
+                       break;
+               if (mpc->mpoad_vcc != NULL) {
+                       start_mpc(mpc, dev);
+               }
+               break;
+       case NETDEV_DOWN:
+               /* the dev was ifconfig'ed down */
+               /* this means that the flow of packets from the
+                * upper layer stops
+                */
+               mpc = find_mpc_by_lec(dev);
+               if (mpc == NULL)
+                       break;
+               if (mpc->mpoad_vcc != NULL) {
+                       stop_mpc(mpc);
+               }
+               break;
+       case NETDEV_REBOOT:
+       case NETDEV_CHANGE:
+       case NETDEV_CHANGEMTU:
+       case NETDEV_CHANGEADDR:
+       case NETDEV_GOING_DOWN:
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_DONE;
 }
 
 /*
@@ -1027,33 +1029,36 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo
  */
 
 
-static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *client)
+static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 {
-        uint32_t dst_ip = msg->content.in_info.in_dst_ip;
-        in_cache_entry *entry;
+       uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+       in_cache_entry *entry;
 
-       entry = client->in_ops->search(dst_ip, client);
-        if( entry == NULL ){
-                entry = client->in_ops->new_entry(dst_ip, client);
-                entry->entry_state = INGRESS_RESOLVING;
+       entry = mpc->in_ops->get(dst_ip, mpc);
+       if(entry == NULL){
+               entry = mpc->in_ops->add_entry(dst_ip, mpc);
+               entry->entry_state = INGRESS_RESOLVING;
                msg->type = SND_MPOA_RES_RQST;
-                msg->content.in_info = entry->ctrl_info;
-               msg_to_mpoad(msg,client);
+               msg->content.in_info = entry->ctrl_info;
+               msg_to_mpoad(msg, mpc);
                do_gettimeofday(&(entry->reply_wait));
+               mpc->in_ops->put(entry);
                return;
-        }
-        
-        if( entry->entry_state == INGRESS_INVALID ){
-                entry->entry_state = INGRESS_RESOLVING;
+       }
+       
+       if(entry->entry_state == INGRESS_INVALID){
+               entry->entry_state = INGRESS_RESOLVING;
                msg->type = SND_MPOA_RES_RQST;
-                msg->content.in_info = entry->ctrl_info;
-               msg_to_mpoad(msg,client);
+               msg->content.in_info = entry->ctrl_info;
+               msg_to_mpoad(msg, mpc);
                do_gettimeofday(&(entry->reply_wait));
-                return;
-        }
-        
-        printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n",
-                (client->dev) ? client->dev->name : "<unknown>");
+               mpc->in_ops->put(entry);
+               return;
+       }
+       
+       printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n",
+               (mpc->dev) ? mpc->dev->name : "<unknown>");
+       mpc->in_ops->put(entry);
        return;
 }
 
@@ -1061,30 +1066,36 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *client)
  * Things get complicated because we have to check if there's an egress
  * shortcut with suitable traffic parameters we could use. 
  */
-static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry){
-        uint32_t dst_ip = msg->content.in_info.in_dst_ip;
-        unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
+static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry)
+{
+       uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+       unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
        struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip);
-       eg_cache_entry *eg_entry = client->eg_ops->search_by_src_ip(dst_ip, client);
+       eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client);
+
        if(eg_entry && eg_entry->shortcut){
-               if(eg_entry->shortcut->qos.txtp.traffic_class &
+               if(eg_entry->shortcut->qos.txtp.traffic_class &
                   msg->qos.txtp.traffic_class &
                   (qos ? qos->qos.txtp.traffic_class : ATM_UBR | ATM_CBR)){
-                           if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR)
-                                   entry->shortcut = eg_entry->shortcut;
+                           if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR)
+                                   entry->shortcut = eg_entry->shortcut;
                            else if(eg_entry->shortcut->qos.txtp.max_pcr > 0)
-                                   entry->shortcut = eg_entry->shortcut;
+                                   entry->shortcut = eg_entry->shortcut;
                }
                if(entry->shortcut){
-                       dprintk("mpoa: (%s) using egress SVC to reach %d.%d.%d.%d\n",client->dev->name, ip[0], ip[1], ip[2], ip[3]);
+                       dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(ip));
+                       client->eg_ops->put(eg_entry);
                        return;
                }
        }
+       if (eg_entry != NULL)
+               client->eg_ops->put(eg_entry);
+
        /* No luck in the egress cache we must open an ingress SVC */
        msg->type = OPEN_INGRESS_SVC;
        if (qos && (qos->qos.txtp.traffic_class == msg->qos.txtp.traffic_class))
        {
-               msg->qos = qos->qos;
+               msg->qos = qos->qos;
                printk("mpoa: (%s) trying to get a CBR shortcut\n",client->dev->name);
        }
        else memset(&msg->qos,0,sizeof(struct atm_qos));
@@ -1092,45 +1103,49 @@ static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_clien
        return;
 }
 
-static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *client)
+static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 {
        unsigned char *ip;
 
-        uint32_t dst_ip = msg->content.in_info.in_dst_ip;
-        in_cache_entry *entry = client->in_ops->search(dst_ip, client);
+       uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+       in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);
        ip = (unsigned char *)&dst_ip;
-        dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %d.%d.%d.%d\n", client->dev->name, ip[0], ip[1], ip[2], ip[3]);
-        ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", client->dev->name, entry);
-        if(entry == NULL){
-                printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", client->dev->name);
-                return;
-        }
-        ddprintk(" entry_state = %d ", entry->entry_state);    
-
-        if (entry->entry_state == INGRESS_RESOLVED) {
-                printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", client->dev->name);
-                return;
-        }
-
-        entry->ctrl_info = msg->content.in_info;
-        do_gettimeofday(&(entry->tv));
-        do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */
-        entry->refresh_time = 0;
-        ddprintk("entry->shortcut = %p\n", entry->shortcut);
+       dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(ip));
+       ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry);
+       if(entry == NULL){
+               printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name);
+               return;
+       }
+       ddprintk(" entry_state = %d ", entry->entry_state);     
+
+       if (entry->entry_state == INGRESS_RESOLVED) {
+               printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", mpc->dev->name);
+               mpc->in_ops->put(entry);
+               return;
+       }
+
+       entry->ctrl_info = msg->content.in_info;
+       do_gettimeofday(&(entry->tv));
+       do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */
+       entry->refresh_time = 0;
+       ddprintk("entry->shortcut = %p\n", entry->shortcut);
 
        if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL){
-               entry->entry_state = INGRESS_RESOLVED; 
+               entry->entry_state = INGRESS_RESOLVED; 
+               mpc->in_ops->put(entry);
                return; /* Shortcut already open... */
        }
 
        if (entry->shortcut != NULL) {
                printk("mpoa: (%s) MPOA_res_reply_rcvd: entry->shortcut != NULL, impossible!\n",
-                      client->dev->name);
+                      mpc->dev->name);
+               mpc->in_ops->put(entry);
                return;
        }
        
-       check_qos_and_open_shortcut(msg, client, entry);
+       check_qos_and_open_shortcut(msg, mpc, entry);
        entry->entry_state = INGRESS_RESOLVED;
+       mpc->in_ops->put(entry);
 
        return;
 
@@ -1138,73 +1153,79 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *clien
 
 static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 {
-        uint32_t dst_ip = msg->content.in_info.in_dst_ip;
-        uint32_t mask = msg->ip_mask;
+       uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+       uint32_t mask = msg->ip_mask;
        unsigned char *ip = (unsigned char *)&dst_ip;
+       in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
 
-        in_cache_entry *entry = mpc->in_ops->search_with_mask(dst_ip, mpc, mask);
-        if( entry == NULL ){
-                printk("mpoa: (%s) ingress_purge_rcvd: recieved a purge for an entry that doesn't exist, ", mpc->dev->name);
-                printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
-                return;
-        }
-       while(entry != NULL){
-               dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,
-                      mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
-               mpc->in_ops->cache_remove(entry, mpc);
-               entry = mpc->in_ops->search_with_mask(dst_ip, mpc, mask);
+       if(entry == NULL){
+               printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ", mpc->dev->name);
+               printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
+               return;
        }
-        return;
+
+       do {
+               dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,
+                       mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+               write_lock_bh(&mpc->ingress_lock);
+               mpc->in_ops->remove_entry(entry, mpc);
+               write_unlock_bh(&mpc->ingress_lock);
+               mpc->in_ops->put(entry);
+               entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
+       } while (entry != NULL);
+
+       return;
 } 
 
 static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 {
-        unsigned long flags;
-        uint32_t cache_id = msg->content.eg_info.cache_id;
-        eg_cache_entry *entry = mpc->eg_ops->search_by_cache_id(cache_id, mpc);
-        
-        if( entry == NULL ){
-                printk("mpoa: (%s) egress_purge_rcvd: received a purge reply for an entry that doesn't exist\n", mpc->dev->name);
-                return;
-        }
-
-        write_lock_irqsave(&mpc->egress_lock, flags);
-        mpc->eg_ops->cache_remove(entry, mpc);
-        write_unlock_irqrestore(&mpc->egress_lock, flags);
-
-        return;
+       uint32_t cache_id = msg->content.eg_info.cache_id;
+       eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc);
+       
+       if (entry == NULL) {
+               dprintk("mpoa: (%s) egress_purge_rcvd: purge for a non-existing entry\n", mpc->dev->name);
+               return;
+       }
+
+       write_lock_irq(&mpc->egress_lock);
+       mpc->eg_ops->remove_entry(entry, mpc);
+       write_unlock_irq(&mpc->egress_lock);
+
+       mpc->eg_ops->put(entry);
+
+       return;
 } 
 
 static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
 {
-        struct k_message *purge_msg;
-        struct sk_buff *skb;
-
-        dprintk("mpoa: purge_egress_shortcut: entering\n");
-        if (vcc == NULL) {
-                printk("mpoa: purge_egress_shortcut: vcc == NULL\n");
-                return;
-        }
-
-        skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
-        if (skb == NULL) {
-                 printk("mpoa: purge_egress_shortcut: out of memory\n");
-                return;
-        }
-
-        skb_put(skb, sizeof(struct k_message));
-        memset(skb->data, 0, sizeof(struct k_message));
-        purge_msg = (struct k_message *)skb->data;
-        purge_msg->type = DATA_PLANE_PURGE;
-        if (entry != NULL)
-                purge_msg->content.eg_info = entry->ctrl_info;
-
-        atm_force_charge(vcc, skb->truesize);
-        skb_queue_tail(&vcc->recvq, skb);
-        wake_up(&vcc->sleep);
-        dprintk("mpoa: purge_egress_shortcut: exiting:\n");
-
-        return;
+       struct k_message *purge_msg;
+       struct sk_buff *skb;
+
+       dprintk("mpoa: purge_egress_shortcut: entering\n");
+       if (vcc == NULL) {
+               printk("mpoa: purge_egress_shortcut: vcc == NULL\n");
+               return;
+       }
+
+       skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
+       if (skb == NULL) {
+                printk("mpoa: purge_egress_shortcut: out of memory\n");
+               return;
+       }
+
+       skb_put(skb, sizeof(struct k_message));
+       memset(skb->data, 0, sizeof(struct k_message));
+       purge_msg = (struct k_message *)skb->data;
+       purge_msg->type = DATA_PLANE_PURGE;
+       if (entry != NULL)
+               purge_msg->content.eg_info = entry->ctrl_info;
+
+       atm_force_charge(vcc, skb->truesize);
+       skb_queue_tail(&vcc->recvq, skb);
+       wake_up(&vcc->sleep);
+       dprintk("mpoa: purge_egress_shortcut: exiting:\n");
+
+       return;
 }
 
 /*
@@ -1213,104 +1234,102 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
  */
 static void mps_death( struct k_message * msg, struct mpoa_client * mpc )
 {
+       eg_cache_entry *entry;
 
-        unsigned long flags;
-        eg_cache_entry *entry;
-
-        dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name);
+       dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name);
 
-        if(memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)){
-                printk("mpoa: (%s) mps_death: wrong MPS\n", mpc->dev->name);
-                return;
-        }
-
-        entry = mpc->eg_cache;
-        while (entry != NULL) {
-                purge_egress_shortcut(entry->shortcut, entry);
-                entry = entry->next;
-        }
+       if(memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)){
+               printk("mpoa: (%s) mps_death: wrong MPS\n", mpc->dev->name);
+               return;
+       }
 
-        write_lock_irqsave(&mpc->ingress_lock, flags);
-        while(mpc->in_ops->cache_remove(mpc->in_cache, mpc));
-        write_unlock_irqrestore(&mpc->ingress_lock, flags);
+       /* FIXME: This knows too much of the cache structure */
+       read_lock_irq(&mpc->egress_lock);
+       entry = mpc->eg_cache;
+       while (entry != NULL) {
+               purge_egress_shortcut(entry->shortcut, entry);
+               entry = entry->next;
+       }
+       read_unlock_irq(&mpc->egress_lock);
 
-        write_lock_irqsave(&mpc->egress_lock, flags);
-        while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc));
-        write_unlock_irqrestore(&mpc->egress_lock, flags);
+       mpc->in_ops->destroy_cache(mpc);
+       mpc->eg_ops->destroy_cache(mpc);
 
-        return;
+       return;
 }
 
-static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * mpc){
-
-        uint16_t holding_time;
-        unsigned long flags;
-        eg_cache_entry *entry = mpc->eg_ops->search_by_cache_id(msg->content.eg_info.cache_id, mpc);
-        
-        holding_time = msg->content.eg_info.holding_time;
-        dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n",
-               mpc->dev->name, entry, holding_time);
-        if(entry == NULL && holding_time) {
-                mpc->eg_ops->new_entry(msg, mpc);
-                return;
-        }
-        if(holding_time){
-                mpc->eg_ops->update(entry, holding_time);
-                return;
-        }
-        
-        write_lock_irqsave(&mpc->egress_lock, flags);
-        mpc->eg_ops->cache_remove(entry, mpc);
-        write_unlock_irqrestore(&mpc->egress_lock, flags);
-
-        
-        return;
+static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * mpc)
+{
+       uint16_t holding_time;
+       eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(msg->content.eg_info.cache_id, mpc);
+       
+       holding_time = msg->content.eg_info.holding_time;
+       dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n",
+              mpc->dev->name, entry, holding_time);
+       if(entry == NULL && holding_time) {
+               entry = mpc->eg_ops->add_entry(msg, mpc);
+               mpc->eg_ops->put(entry);
+               return;
+       }
+       if(holding_time){
+               mpc->eg_ops->update(entry, holding_time);
+               return;
+       }
+       
+       write_lock_irq(&mpc->egress_lock);
+       mpc->eg_ops->remove_entry(entry, mpc);
+       write_unlock_irq(&mpc->egress_lock);
+
+       mpc->eg_ops->put(entry);
+       
+       return;
 }
 
 static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc)
 {
-        struct lec_priv *priv;
-        int i, retval ;
-
-        uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN];
-
-        tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type  */
-        tlv[4] = 1 + 1 + ATM_ESA_LEN;  /* length                           */
-        tlv[5] = 0x02;                 /* MPOA client                      */
-        tlv[6] = 0x00;                 /* number of MPS MAC addresses      */
-
-        memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */
-        memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN);
-
-        dprintk("mpoa: (%s) setting MPC ctrl ATM address to ",
-               (mpc->dev) ? mpc->dev->name : "<unknown>");
-        for (i = 7; i < sizeof(tlv); i++)
-                dprintk("%02x ", tlv[i]);
-        dprintk("\n");
-
-        if (mpc->dev) {
-                priv = (struct lec_priv *)mpc->dev->priv;
-                retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv));
-                if (retval == 0)
-                        printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name);
-                retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL);
-                if (retval < 0)
-                        printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc->dev->name);
-        }
-
-        return;
+       struct lec_priv *priv;
+       int i, retval ;
+
+       uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN];
+
+       tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type  */
+       tlv[4] = 1 + 1 + ATM_ESA_LEN;  /* length                           */
+       tlv[5] = 0x02;                 /* MPOA client                      */
+       tlv[6] = 0x00;                 /* number of MPS MAC addresses      */
+
+       memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */
+       memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN);
+
+       dprintk("mpoa: (%s) setting MPC ctrl ATM address to ",
+              (mpc->dev) ? mpc->dev->name : "<unknown>");
+       for (i = 7; i < sizeof(tlv); i++)
+               dprintk("%02x ", tlv[i]);
+       dprintk("\n");
+
+       if (mpc->dev) {
+               priv = (struct lec_priv *)mpc->dev->priv;
+               retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv));
+               if (retval == 0)
+                       printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name);
+               retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL);
+               if (retval < 0)
+                       printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc->dev->name);
+       }
+
+       return;
 }
 
-static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *client){
+static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *client)
+{
 
-        if(client->number_of_mps_macs)
-                kfree(client->mps_macs);
-        client->number_of_mps_macs = 0;
+       if(client->number_of_mps_macs)
+               kfree(client->mps_macs);
+       client->number_of_mps_macs = 0;
        client->mps_macs = kmalloc(ETH_ALEN,GFP_KERNEL);
-        if (client->mps_macs == NULL) {
-               printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n");
-                return;
-        }
+       if (client->mps_macs == NULL) {
+               printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n");
+               return;
+       }
        client->number_of_mps_macs = 1;
        memcpy(client->mps_macs, msg->MPS_ctrl, ETH_ALEN);
        
@@ -1320,22 +1339,23 @@ static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *cli
 /*
  * purge egress cache and tell daemon to 'action' (DIE, RELOAD)
  */
-static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action){
+static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action)
+{
 
-        unsigned long flags;
-        eg_cache_entry *entry;
+       eg_cache_entry *entry;
        msg->type = SND_EGRESS_PURGE;
 
 
-        read_lock_irqsave(&mpc->egress_lock, flags);
-        entry = mpc->eg_cache;
-       while(entry != NULL){
-                   msg->content.eg_info = entry->ctrl_info;
-                    dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id);
+       /* FIXME: This knows too much of the cache structure */
+       read_lock_irq(&mpc->egress_lock);
+       entry = mpc->eg_cache;
+       while (entry != NULL){
+                   msg->content.eg_info = entry->ctrl_info;
+                   dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id);
                    msg_to_mpoad(msg, mpc);
                    entry = entry->next;
        }
-        read_unlock_irqrestore(&mpc->egress_lock, flags);
+       read_unlock_irq(&mpc->egress_lock);
 
        msg->type = action;
        msg_to_mpoad(msg, mpc);
@@ -1344,116 +1364,116 @@ static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action)
 
 static void mpc_timer_refresh()
 {
-        mpc_timer.expires = jiffies + (MPC_P2 * HZ);
-        mpc_timer.data = mpc_timer.expires;
-        mpc_timer.function = mpc_cache_check;
-        add_timer(&mpc_timer);
-        
-        return;
+       mpc_timer.expires = jiffies + (MPC_P2 * HZ);
+       mpc_timer.data = mpc_timer.expires;
+       mpc_timer.function = mpc_cache_check;
+       add_timer(&mpc_timer);
+       
+       return;
 }
 
 static void mpc_cache_check( unsigned long checking_time  )
 {
-        struct mpoa_client *mpc = mpcs;
-        static unsigned long previous_resolving_check_time = 0;
-        static unsigned long previous_refresh_time = 0;
-        
-        while( mpc != NULL ){
-                mpc->in_ops->clear_count(mpc);
+       struct mpoa_client *mpc = mpcs;
+       static unsigned long previous_resolving_check_time = 0;
+       static unsigned long previous_refresh_time = 0;
+       
+       while( mpc != NULL ){
+               mpc->in_ops->clear_count(mpc);
                mpc->eg_ops->clear_expired(mpc);
-                if(checking_time - previous_resolving_check_time > mpc->parameters.mpc_p4 * HZ ){
-                        mpc->in_ops->check_resolving(mpc);
-                        previous_resolving_check_time = checking_time;
-                }
-                if(checking_time - previous_refresh_time > mpc->parameters.mpc_p5 * HZ ){
-                        mpc->in_ops->refresh(mpc);
-                        previous_refresh_time = checking_time;
-                }
-                mpc = mpc->next;
-        }
-        mpc_timer_refresh();
-        
-        return;
+               if(checking_time - previous_resolving_check_time > mpc->parameters.mpc_p4 * HZ ){
+                       mpc->in_ops->check_resolving(mpc);
+                       previous_resolving_check_time = checking_time;
+               }
+               if(checking_time - previous_refresh_time > mpc->parameters.mpc_p5 * HZ ){
+                       mpc->in_ops->refresh(mpc);
+                       previous_refresh_time = checking_time;
+               }
+               mpc = mpc->next;
+       }
+       mpc_timer_refresh();
+       
+       return;
 }
 
 void atm_mpoa_init_ops(struct atm_mpoa_ops *ops)
 {
-        ops->mpoad_attach = atm_mpoa_mpoad_attach;
-        ops->vcc_attach = atm_mpoa_vcc_attach;
+       ops->mpoad_attach = atm_mpoa_mpoad_attach;
+       ops->vcc_attach = atm_mpoa_vcc_attach;
 
 #ifdef CONFIG_PROC_FS
        if(mpc_proc_init() != 0)
-               printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
+               printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
        else
-               printk(KERN_INFO "mpoa: /proc/mpoa initialized\n");
+               printk(KERN_INFO "mpoa: /proc/mpoa initialized\n");
 #endif
 
-        printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
+       printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
 
-        return;
+       return;
 }
 
 #ifdef MODULE
 int init_module(void)
 {
-        extern struct atm_mpoa_ops atm_mpoa_ops;
+       extern struct atm_mpoa_ops atm_mpoa_ops;
 
        atm_mpoa_init_ops(&atm_mpoa_ops);
 
-        return 0;
+       return 0;
 }
 
 void cleanup_module(void)
 {
-        extern struct atm_mpoa_ops atm_mpoa_ops;
-        struct mpoa_client *mpc, *tmp;
-        struct atm_mpoa_qos *qos, *nextqos;
-        struct lec_priv *priv;
-
-        if (MOD_IN_USE) {
-                printk("mpc.c: module in use\n");
-                return;
-        }
+       extern struct atm_mpoa_ops atm_mpoa_ops;
+       struct mpoa_client *mpc, *tmp;
+       struct atm_mpoa_qos *qos, *nextqos;
+       struct lec_priv *priv;
+
+       if (MOD_IN_USE) {
+               printk("mpc.c: module in use\n");
+               return;
+       }
 #ifdef CONFIG_PROC_FS
        mpc_proc_clean();
 #endif
 
-        del_timer(&mpc_timer);
-        unregister_netdevice_notifier(&mpoa_notifier);
-        atm_mpoa_ops.mpoad_attach = NULL;
-        atm_mpoa_ops.vcc_attach = NULL;
-
-        mpc = mpcs;
-        mpcs = NULL;
-        while (mpc != NULL) {
-                tmp = mpc->next;
-                if (mpc->dev != NULL) {
-                        stop_mpc(mpc);
-                        priv = (struct lec_priv *)mpc->dev->priv;
-                        if (priv->lane2_ops != NULL)
-                                priv->lane2_ops->associate_indicator = NULL;
-                }
-                ddprintk("mpoa: cleanup_module: about to clear caches\n");
-                while(mpc->in_ops->cache_remove(mpc->in_cache, mpc));
-                while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc));        
-                ddprintk("mpoa: cleanup_module: caches cleared\n");
-                kfree(mpc->mps_macs);
-                memset(mpc, 0, sizeof(struct mpoa_client));
-                ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc);
-                kfree(mpc);
-                ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp);
-                mpc = tmp;
-        }
-
-        qos = qos_head;
-        qos_head = NULL;
-        while (qos != NULL) {
-                nextqos = qos->next;
-                dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos);
-                kfree(qos);
-                qos = nextqos;
-        }
-
-        return;
+       del_timer(&mpc_timer);
+       unregister_netdevice_notifier(&mpoa_notifier);
+       atm_mpoa_ops.mpoad_attach = NULL;
+       atm_mpoa_ops.vcc_attach = NULL;
+
+       mpc = mpcs;
+       mpcs = NULL;
+       while (mpc != NULL) {
+               tmp = mpc->next;
+               if (mpc->dev != NULL) {
+                       stop_mpc(mpc);
+                       priv = (struct lec_priv *)mpc->dev->priv;
+                       if (priv->lane2_ops != NULL)
+                               priv->lane2_ops->associate_indicator = NULL;
+               }
+               ddprintk("mpoa: cleanup_module: about to clear caches\n");
+               mpc->in_ops->destroy_cache(mpc);
+               mpc->eg_ops->destroy_cache(mpc);
+               ddprintk("mpoa: cleanup_module: caches cleared\n");
+               kfree(mpc->mps_macs);
+               memset(mpc, 0, sizeof(struct mpoa_client));
+               ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc);
+               kfree(mpc);
+               ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp);
+               mpc = tmp;
+       }
+
+       qos = qos_head;
+       qos_head = NULL;
+       while (qos != NULL) {
+               nextqos = qos->next;
+               dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos);
+               kfree(qos);
+               qos = nextqos;
+       }
+
+       return;
 }
 #endif /* MODULE */
index 8b94fb0555b417f44a06f8730dd97b20806d497d..0bca7aa6cc0b62fc152768d05edae3412e8ab117 100644 (file)
 #define ddprintk(format,args...)
 #endif
 
-static in_cache_entry *in_cache_search(uint32_t dst_ip, 
-                                      struct mpoa_client *client)
+static in_cache_entry *in_cache_get(uint32_t dst_ip,
+                                   struct mpoa_client *client)
 {
-        unsigned long flags;
-        in_cache_entry *entry;
-
-        read_lock_irqsave(&client->ingress_lock, flags);
-        entry = client->in_cache;
-        while(entry != NULL){
-                if( entry->ctrl_info.in_dst_ip == dst_ip ){
-                        read_unlock_irqrestore(&client->ingress_lock, flags);
-                        return entry;
-                }
-                entry = entry->next;
-        }
-        read_unlock_irqrestore(&client->ingress_lock, flags);
-
-        return NULL;
+       in_cache_entry *entry;
+
+       read_lock_bh(&client->ingress_lock);
+       entry = client->in_cache;
+       while(entry != NULL){
+               if( entry->ctrl_info.in_dst_ip == dst_ip ){
+                       atomic_inc(&entry->use);
+                       read_unlock_bh(&client->ingress_lock);
+                       return entry;
+               }
+               entry = entry->next;
+       }
+       read_unlock_bh(&client->ingress_lock);
+
+       return NULL;
 }
 
-static in_cache_entry *in_cache_search_with_mask(uint32_t dst_ip,
-                                                struct mpoa_client *client,
-                                                uint32_t mask){
-        unsigned long flags;
-        in_cache_entry *entry;
-
-        read_lock_irqsave(&client->ingress_lock, flags);
-        entry = client->in_cache;
-        while(entry != NULL){
-                if((entry->ctrl_info.in_dst_ip & mask)  == (dst_ip & mask )){
-                        read_unlock_irqrestore(&client->ingress_lock, flags);
-                        return entry;
-                }
-                entry = entry->next;
-        }
-        read_unlock_irqrestore(&client->ingress_lock, flags);
-
-        return NULL;
-  
+static in_cache_entry *in_cache_get_with_mask(uint32_t dst_ip,
+                                             struct mpoa_client *client,
+                                             uint32_t mask)
+{
+       in_cache_entry *entry;
+
+       read_lock_bh(&client->ingress_lock);
+       entry = client->in_cache;
+       while(entry != NULL){
+               if((entry->ctrl_info.in_dst_ip & mask)  == (dst_ip & mask )){
+                       atomic_inc(&entry->use);
+                       read_unlock_bh(&client->ingress_lock);
+                       return entry;
+               }
+               entry = entry->next;
+       }
+       read_unlock_bh(&client->ingress_lock);
+
+       return NULL;
+
 }
 
-static in_cache_entry *in_cache_search_by_vcc(struct atm_vcc *vcc, 
-                                             struct mpoa_client *client )
+static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
+                                          struct mpoa_client *client )
 {
-        unsigned long flags;
-        in_cache_entry *entry;
-
-        read_lock_irqsave(&client->ingress_lock, flags);
-        entry = client->in_cache;
-        while(entry != NULL){
-               if(entry->shortcut == vcc) {
-                        read_unlock_irqrestore(&client->ingress_lock, flags);
-                       return entry;
-                }
+       in_cache_entry *entry;
+
+       read_lock_bh(&client->ingress_lock);
+       entry = client->in_cache;
+       while(entry != NULL){
+               if(entry->shortcut == vcc) {
+                       atomic_inc(&entry->use);
+                       read_unlock_bh(&client->ingress_lock);
+                       return entry;
+               }
                entry = entry->next;
-        }
-        read_unlock_irqrestore(&client->ingress_lock, flags);
+       }
+       read_unlock_bh(&client->ingress_lock);
 
-        return NULL;
+       return NULL;
 }
 
-static in_cache_entry *new_in_cache_entry(uint32_t dst_ip, 
+static in_cache_entry *in_cache_add_entry(uint32_t dst_ip,
                                          struct mpoa_client *client)
 {
-        unsigned long flags;
-        unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
-        in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);
-
-        if (entry == NULL) {
-                printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n");
-                return NULL;
-        }
-
-        dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
-        memset(entry,0,sizeof(in_cache_entry));
-
-        dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n");
-        write_lock_irqsave(&client->ingress_lock, flags);
-        entry->next = client->in_cache;
-        entry->prev = NULL;
-        if (client->in_cache != NULL)
-                client->in_cache->prev = entry;
-        client->in_cache = entry;
-        write_unlock_irqrestore(&client->ingress_lock, flags);
-        dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: unlocked\n");
-
-        memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
-        entry->ctrl_info.in_dst_ip = dst_ip;
-        do_gettimeofday(&(entry->tv));
-        entry->retry_time = client->parameters.mpc_p4;
-        entry->count = 1;
-        entry->entry_state = INGRESS_INVALID; 
-        entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
+       unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
+       in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);
+
+       if (entry == NULL) {
+               printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n");
+               return NULL;
+       }
+
+       dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
+       memset(entry,0,sizeof(in_cache_entry));
+
+       atomic_set(&entry->use, 1);
+       dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n");
+       write_lock_bh(&client->ingress_lock);
+       entry->next = client->in_cache;
+       entry->prev = NULL;
+       if (client->in_cache != NULL)
+               client->in_cache->prev = entry;
+       client->in_cache = entry;
+
+       memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
+       entry->ctrl_info.in_dst_ip = dst_ip;
+       do_gettimeofday(&(entry->tv));
+       entry->retry_time = client->parameters.mpc_p4;
+       entry->count = 1;
+       entry->entry_state = INGRESS_INVALID;
+       entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
+       atomic_inc(&entry->use);
+
+       write_unlock_bh(&client->ingress_lock);
+       dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: unlocked\n");
 
        return entry;
 }
 
-static int cache_hit( in_cache_entry * entry, struct mpoa_client *mpc)
+static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
 {
-        struct atm_mpoa_qos *qos;
-        struct k_message msg;
+       struct atm_mpoa_qos *qos;
+       struct k_message msg;
 
-        entry->count++;
+       entry->count++;
        if(entry->entry_state == INGRESS_RESOLVED && entry->shortcut != NULL)
-                return OPEN;
+               return OPEN;
 
        if(entry->entry_state == INGRESS_REFRESHING){
-               if(entry->count > mpc->parameters.mpc_p1){
-                       msg.type = SND_MPOA_RES_RQST;
+               if(entry->count > mpc->parameters.mpc_p1){
+                       msg.type = SND_MPOA_RES_RQST;
                        msg.content.in_info = entry->ctrl_info;
                        memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN);
-                        qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
-                        if (qos != NULL) msg.qos = qos->qos;
+                       qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
+                       if (qos != NULL) msg.qos = qos->qos;
                        msg_to_mpoad(&msg, mpc);
                        do_gettimeofday(&(entry->reply_wait));
                        entry->entry_state = INGRESS_RESOLVING;
                }
                if(entry->shortcut != NULL)
-                        return OPEN;
+                       return OPEN;
                return CLOSED;
        }
 
-        if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL)
-               return OPEN;
+       if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL)
+               return OPEN;
 
-        if( entry->count > mpc->parameters.mpc_p1 &&
-            entry->entry_state == INGRESS_INVALID){
-                unsigned char *ip __attribute__ ((unused)) =
+       if( entry->count > mpc->parameters.mpc_p1 &&
+           entry->entry_state == INGRESS_INVALID){
+               unsigned char *ip __attribute__ ((unused)) =
                    (unsigned char *)&entry->ctrl_info.in_dst_ip;
 
                dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
-                entry->entry_state = INGRESS_RESOLVING;
-                msg.type =  SND_MPOA_RES_RQST;
-                memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN );
-                msg.content.in_info = entry->ctrl_info;
-                qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
-                if (qos != NULL) msg.qos = qos->qos;
-                msg_to_mpoad( &msg, mpc);
-                do_gettimeofday(&(entry->reply_wait));
-        }
-
-        return CLOSED;
+               entry->entry_state = INGRESS_RESOLVING;
+               msg.type =  SND_MPOA_RES_RQST;
+               memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN );
+               msg.content.in_info = entry->ctrl_info;
+               qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
+               if (qos != NULL) msg.qos = qos->qos;
+               msg_to_mpoad( &msg, mpc);
+               do_gettimeofday(&(entry->reply_wait));
+       }
+
+       return CLOSED;
 }
 
-/*
- * If there are no more references to vcc in egress cache,
- * we are ready to close it.
- */
-static void close_unused_egress_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc)
+static void in_cache_put(in_cache_entry *entry)
 {
-       if (vcc == NULL)
-               return;
-
-       dprintk("mpoa: mpoa_caches.c: close_unused_egress_vcc:\n");
-        if (mpc->eg_ops->search_by_vcc(vcc, mpc) != NULL)
-                return;                             /* entry still in use */
-
-       atm_async_release_vcc(vcc, -EPIPE); /* nobody uses this VCC anymore, close it */
-       dprintk("mpoa: mpoa_caches.c: close_unused_egress_vcc, closed one:\n");
+       if (atomic_dec_and_test(&entry->use)) {
+               memset(entry, 0, sizeof(in_cache_entry));
+               kfree(entry);
+       }
 
        return;
 }
@@ -188,371 +182,395 @@ static void close_unused_egress_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc
 /*
  * This should be called with write lock on
  */
-static int in_cache_remove( in_cache_entry *entry,
-                            struct mpoa_client *client )
+static void in_cache_remove_entry(in_cache_entry *entry,
+                                 struct mpoa_client *client)
 {
        struct atm_vcc *vcc;
-        struct k_message msg;
-        unsigned char *ip;
-
-        if(entry == NULL)
-                return 0;
+       struct k_message msg;
+       unsigned char *ip;
 
        vcc = entry->shortcut;
-        ip = (unsigned char *)&entry->ctrl_info.in_dst_ip;
-        dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",ip[0], ip[1], ip[2], ip[3]);
-
-        if (entry->prev != NULL)
-                entry->prev->next = entry->next;
-        else
-                client->in_cache = entry->next;
-        if (entry->next != NULL)
-                entry->next->prev = entry->prev;
-        memset(entry, 0, sizeof(in_cache_entry));
-        kfree(entry);
+       ip = (unsigned char *)&entry->ctrl_info.in_dst_ip;
+       dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",ip[0], ip[1], ip[2], ip[3]);
+
+       if (entry->prev != NULL)
+               entry->prev->next = entry->next;
+       else
+               client->in_cache = entry->next;
+       if (entry->next != NULL)
+               entry->next->prev = entry->prev;
+       client->in_ops->put(entry);
        if(client->in_cache == NULL && client->eg_cache == NULL){
-               msg.type = STOP_KEEP_ALIVE_SM;
+               msg.type = STOP_KEEP_ALIVE_SM;
                msg_to_mpoad(&msg,client);
        }
 
-       close_unused_egress_vcc(vcc, client);
-        return 1;
-} 
+       /* Check if the egress side still uses this VCC */
+       if (vcc != NULL) {
+               eg_cache_entry *eg_entry = client->eg_ops->get_by_vcc(vcc, client);
+               if (eg_entry != NULL) {
+                       client->eg_ops->put(eg_entry);
+                       return;
+               }
+               atm_async_release_vcc(vcc, -EPIPE);
+       }
 
+       return;
+}
 
-/* Call this every MPC-p2 seconds... Not exactly correct solution, 
-   but an easy one... */
 
+/* Call this every MPC-p2 seconds... Not exactly correct solution,
+   but an easy one... */
 static void clear_count_and_expired(struct mpoa_client *client)
 {
-        unsigned char *ip;
-        unsigned long flags;
-        in_cache_entry *entry, *next_entry;
-        struct timeval now;
+       unsigned char *ip;
+       in_cache_entry *entry, *next_entry;
+       struct timeval now;
 
        do_gettimeofday(&now);
-        
-        write_lock_irqsave(&client->ingress_lock, flags);
-        entry = client->in_cache;
-        while(entry != NULL){
-                entry->count=0;
-                next_entry = entry->next;
-                if((now.tv_sec - entry->tv.tv_sec) 
-                   > entry->ctrl_info.holding_time){
-                       ip = (unsigned char*)&entry->ctrl_info.in_dst_ip;
-                       dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
-                        in_cache_remove(entry, client);
-                }
-                entry = next_entry;
-        }
-        write_unlock_irqrestore(&client->ingress_lock, flags);
-
-        return;
-}
 
-/* Call this every MPC-p4 seconds. */ 
+       write_lock_bh(&client->ingress_lock);
+       entry = client->in_cache;
+       while(entry != NULL){
+               entry->count=0;
+               next_entry = entry->next;
+               if((now.tv_sec - entry->tv.tv_sec)
+                  > entry->ctrl_info.holding_time){
+                       ip = (unsigned char*)&entry->ctrl_info.in_dst_ip;
+                       dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %u.%u.%u.%u\n", NIPQUAD(ip));
+                       client->in_ops->remove_entry(entry, client);
+               }
+               entry = next_entry;
+       }
+       write_unlock_bh(&client->ingress_lock);
+
+       return;
+}
 
-static void check_resolving_entries( struct mpoa_client * client )
+/* Call this every MPC-p4 seconds. */
+static void check_resolving_entries(struct mpoa_client *client)
 {
 
-        struct atm_mpoa_qos *qos;
-        unsigned long flags;
-        in_cache_entry *entry;
-        struct timeval now;
-        struct k_message msg;
+       struct atm_mpoa_qos *qos;
+       in_cache_entry *entry;
+       struct timeval now;
+       struct k_message msg;
 
        do_gettimeofday( &now );
 
-        read_lock_irqsave(&client->ingress_lock, flags);
-        entry = client->in_cache;
-        while( entry != NULL ){
-                if(entry->entry_state == INGRESS_RESOLVING){
-                        if(now.tv_sec - entry->hold_down.tv_sec < client->parameters.mpc_p6){
-                                entry = entry->next;                      /* Entry in hold down */
-                                continue;
-                        }
-                        if( (now.tv_sec - entry->reply_wait.tv_sec) >
-                            entry->retry_time ){
-                                entry->retry_time = MPC_C1*( entry->retry_time );
-                                if(entry->retry_time > client->parameters.mpc_p5){
-                                       /* Retry time maximum exceeded, put entry in hold down. */  
-                                       do_gettimeofday(&(entry->hold_down)); 
-                                        entry->retry_time = client->parameters.mpc_p4; 
-                                        entry = entry->next;
-                                        continue;
-                                }
+       read_lock_bh(&client->ingress_lock);
+       entry = client->in_cache;
+       while( entry != NULL ){
+               if(entry->entry_state == INGRESS_RESOLVING){
+                       if(now.tv_sec - entry->hold_down.tv_sec < client->parameters.mpc_p6){
+                               entry = entry->next;                      /* Entry in hold down */
+                               continue;
+                       }
+                       if( (now.tv_sec - entry->reply_wait.tv_sec) >
+                           entry->retry_time ){
+                               entry->retry_time = MPC_C1*( entry->retry_time );
+                               if(entry->retry_time > client->parameters.mpc_p5){
+                                       /* Retry time maximum exceeded, put entry in hold down. */
+                                       do_gettimeofday(&(entry->hold_down));
+                                       entry->retry_time = client->parameters.mpc_p4;
+                                       entry = entry->next;
+                                       continue;
+                               }
                                /* Ask daemon to send a resolution request. */
-                                memset(&(entry->hold_down),0,sizeof(struct timeval));
-                                msg.type = SND_MPOA_RES_RTRY;
-                                memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN);
-                                msg.content.in_info = entry->ctrl_info;
-                                qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
-                                if (qos != NULL) msg.qos = qos->qos;
-                                msg_to_mpoad(&msg, client);
-                                do_gettimeofday(&(entry->reply_wait));
-                        }
-                }
-                entry = entry->next;
-        }
-        read_unlock_irqrestore(&client->ingress_lock, flags);
+                               memset(&(entry->hold_down),0,sizeof(struct timeval));
+                               msg.type = SND_MPOA_RES_RTRY;
+                               memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN);
+                               msg.content.in_info = entry->ctrl_info;
+                               qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
+                               if (qos != NULL) msg.qos = qos->qos;
+                               msg_to_mpoad(&msg, client);
+                               do_gettimeofday(&(entry->reply_wait));
+                       }
+               }
+               entry = entry->next;
+       }
+       read_unlock_bh(&client->ingress_lock);
 }
 
 /* Call this every MPC-p5 seconds. */
-
-static void refresh_entries( struct mpoa_client * client )
+static void refresh_entries(struct mpoa_client *client)
 {
-        unsigned long flags;
-        struct timeval now;
-        struct in_cache_entry *entry = client->in_cache;
-        
-        ddprintk("mpoa: mpoa_caches.c: refresh_entries\n");
+       struct timeval now;
+       struct in_cache_entry *entry = client->in_cache;
+
+       ddprintk("mpoa: mpoa_caches.c: refresh_entries\n");
        do_gettimeofday(&now);
 
-        read_lock_irqsave(&client->ingress_lock, flags);
-        while( entry != NULL ){
-                if( entry->entry_state == INGRESS_RESOLVED ){
-                        if(!(entry->refresh_time))
-                               entry->refresh_time = (2*(entry->ctrl_info.holding_time))/3;
+       read_lock_bh(&client->ingress_lock);
+       while( entry != NULL ){
+               if( entry->entry_state == INGRESS_RESOLVED ){
+                       if(!(entry->refresh_time))
+                               entry->refresh_time = (2*(entry->ctrl_info.holding_time))/3;
                        if( (now.tv_sec - entry->reply_wait.tv_sec) > entry->refresh_time ){
-                                dprintk("mpoa: mpoa_caches.c: refreshing an entry.\n");
+                               dprintk("mpoa: mpoa_caches.c: refreshing an entry.\n");
                                entry->entry_state = INGRESS_REFRESHING;
-                                
+
                        }
-                }
-                entry = entry->next;
-        }
-        read_unlock_irqrestore(&client->ingress_lock, flags);
+               }
+               entry = entry->next;
+       }
+       read_unlock_bh(&client->ingress_lock);
 }
 
-static eg_cache_entry *eg_cache_search_by_cache_id(uint32_t cache_id,
-                                                 struct mpoa_client *client)
+static void in_destroy_cache(struct mpoa_client *mpc)
 {
-        eg_cache_entry *entry;
-        unsigned long flags;
-
-        read_lock_irqsave(&client->egress_lock, flags);
-        entry = client->eg_cache;
-        while(entry != NULL){
-                if( entry->ctrl_info.cache_id == cache_id){
-                        read_unlock_irqrestore(&client->egress_lock, flags);
-                        return entry;
-                }
-                entry = entry->next;
-        }
-       read_unlock_irqrestore(&client->egress_lock, flags);
-
-        return NULL;
+       write_lock_irq(&mpc->ingress_lock);
+       while(mpc->in_cache != NULL)
+               mpc->in_ops->remove_entry(mpc->in_cache, mpc);
+       write_unlock_irq(&mpc->ingress_lock);
+
+       return;
 }
 
-static eg_cache_entry *eg_cache_search_by_tag(uint32_t tag,
-                                             struct mpoa_client *client)
+static eg_cache_entry *eg_cache_get_by_cache_id(uint32_t cache_id, struct mpoa_client *mpc)
 {
-        unsigned long flags;
-        eg_cache_entry *entry;
-
-        read_lock_irqsave(&client->egress_lock, flags);
-        entry = client->eg_cache;
-        while(entry != NULL){
-                if( entry->ctrl_info.tag == tag){
-                        read_unlock_irqrestore(&client->egress_lock, flags);
-                        return entry;
-                }
-                entry = entry->next;
-        }
-       read_unlock_irqrestore(&client->egress_lock, flags);
-
-        return NULL;
+       eg_cache_entry *entry;
+
+       read_lock_irq(&mpc->egress_lock);
+       entry = mpc->eg_cache;
+       while(entry != NULL){
+               if(entry->ctrl_info.cache_id == cache_id){
+                       atomic_inc(&entry->use);
+                       read_unlock_irq(&mpc->egress_lock);
+                       return entry;
+               }
+               entry = entry->next;
+       }
+       read_unlock_irq(&mpc->egress_lock);
+
+       return NULL;
 }
 
-static eg_cache_entry *eg_cache_search_by_vcc(struct atm_vcc *vcc,
-                                               struct mpoa_client *client )
+/* This can be called from any context since it saves CPU flags */
+static eg_cache_entry *eg_cache_get_by_tag(uint32_t tag, struct mpoa_client *mpc)
 {
-        unsigned long flags;
-        eg_cache_entry *entry;
-
-        read_lock_irqsave(&client->egress_lock, flags);
-        entry = client->eg_cache;
-        while( entry != NULL ){
-                if( entry->shortcut == vcc ) {
-                               read_unlock_irqrestore(&client->egress_lock, flags);
-                        return entry;
+       unsigned long flags;
+       eg_cache_entry *entry;
+
+       read_lock_irqsave(&mpc->egress_lock, flags);
+       entry = mpc->eg_cache;
+       while (entry != NULL){
+               if (entry->ctrl_info.tag == tag) {
+                       atomic_inc(&entry->use);
+                       read_unlock_irqrestore(&mpc->egress_lock, flags);
+                       return entry;
                }
-                entry = entry->next;
-        }
-       read_unlock_irqrestore(&client->egress_lock, flags);
+               entry = entry->next;
+       }
+       read_unlock_irqrestore(&mpc->egress_lock, flags);
 
-        return NULL;
+       return NULL;
 }
 
-static eg_cache_entry *eg_cache_search_by_src_ip(uint32_t ipaddr,
-                                                struct mpoa_client *client)
+/* This can be called from any context since it saves CPU flags */
+static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc)
 {
-        unsigned long flags;
-        eg_cache_entry *entry;
-
-        read_lock_irqsave(&client->egress_lock, flags);
-        entry = client->eg_cache;
-        while( entry != NULL ){
-                if(entry->latest_ip_addr == ipaddr) {
-                        break;
+       unsigned long flags;
+       eg_cache_entry *entry;
+
+       read_lock_irqsave(&mpc->egress_lock, flags);
+       entry = mpc->eg_cache;
+       while (entry != NULL){
+               if (entry->shortcut == vcc) {
+                       atomic_inc(&entry->use);
+                       read_unlock_irqrestore(&mpc->egress_lock, flags);
+                       return entry;
                }
-                entry = entry->next;
-        }
-       read_unlock_irqrestore(&client->egress_lock, flags);
+               entry = entry->next;
+       }
+       read_unlock_irqrestore(&mpc->egress_lock, flags);
 
-        return entry;
+       return NULL;
 }
 
-/*
- * If there are no more references to vcc in ingress cache,
- * we are ready to close it.
- */
-static void close_unused_ingress_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc)
+static eg_cache_entry *eg_cache_get_by_src_ip(uint32_t ipaddr, struct mpoa_client *mpc)
 {
-       if (vcc == NULL)
-               return;
+       eg_cache_entry *entry;
+
+       read_lock_irq(&mpc->egress_lock);
+       entry = mpc->eg_cache;
+       while(entry != NULL){
+               if(entry->latest_ip_addr == ipaddr) {
+                       atomic_inc(&entry->use);
+                       read_unlock_irq(&mpc->egress_lock);
+                       return entry;
+               }
+               entry = entry->next;
+       }
+       read_unlock_irq(&mpc->egress_lock);
 
-       dprintk("mpoa: mpoa_caches.c: close_unused_ingress_vcc:\n");
-        if (mpc->in_ops->search_by_vcc(vcc, mpc) != NULL)
-                return;                             /* entry still in use */
+       return NULL;
+}
 
-       atm_async_release_vcc(vcc, -EPIPE); /* nobody uses this VCC anymore, close it */
-       dprintk("mpoa: mpoa_caches.c: close_unused_ingress_vcc:, closed one\n");
+static void eg_cache_put(eg_cache_entry *entry)
+{
+       if (atomic_dec_and_test(&entry->use)) {
+               memset(entry, 0, sizeof(eg_cache_entry));
+               kfree(entry);
+       }
 
        return;
 }
+
 /*
  * This should be called with write lock on
  */
-static int eg_cache_remove(eg_cache_entry *entry, 
-                           struct mpoa_client *client)
+static void eg_cache_remove_entry(eg_cache_entry *entry,
+                                 struct mpoa_client *client)
 {
        struct atm_vcc *vcc;
-        struct k_message msg; 
-        if(entry == NULL)
-                return 0;
+       struct k_message msg;
 
        vcc = entry->shortcut;
-        dprintk("mpoa: mpoa_caches.c: removing an egress entry.\n");
-        if (entry->prev != NULL)
-                entry->prev->next = entry->next;
-        else
-                client->eg_cache = entry->next;
-        if (entry->next != NULL)
-                entry->next->prev = entry->prev;
-        memset(entry, 0, sizeof(eg_cache_entry));
-        kfree(entry);
+       dprintk("mpoa: mpoa_caches.c: removing an egress entry.\n");
+       if (entry->prev != NULL)
+               entry->prev->next = entry->next;
+       else
+               client->eg_cache = entry->next;
+       if (entry->next != NULL)
+               entry->next->prev = entry->prev;
+       client->eg_ops->put(entry);
        if(client->in_cache == NULL && client->eg_cache == NULL){
-               msg.type = STOP_KEEP_ALIVE_SM;
+               msg.type = STOP_KEEP_ALIVE_SM;
                msg_to_mpoad(&msg,client);
        }
 
-       close_unused_ingress_vcc(vcc, client);
+       /* Check if the ingress side still uses this VCC */
+       if (vcc != NULL) {
+               in_cache_entry *in_entry = client->in_ops->get_by_vcc(vcc, client);
+               if (in_entry != NULL) {
+                       client->in_ops->put(in_entry);
+                       return;
+               }
+               atm_async_release_vcc(vcc, -EPIPE);
+       }
 
-        return 1;
-} 
+       return;
+}
 
-static eg_cache_entry *new_eg_cache_entry(struct k_message *msg, struct mpoa_client *client)
+static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_client *client)
 {
-        unsigned long flags;
-        unsigned char *ip;
-        eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL);
+       unsigned char *ip;
+       eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL);
 
-        if (entry == NULL) {
-                printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n");
-                return NULL;
+       if (entry == NULL) {
+               printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n");
+               return NULL;
        }
 
-        ip = (unsigned char *)&msg->content.eg_info.eg_dst_ip;
-        dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %d.%d.%d.%d, this should be our IP\n", ip[0], ip[1], ip[2], ip[3]);
-        memset(entry, 0, sizeof(eg_cache_entry));
-
-        dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n");
-        write_lock_irqsave(&client->egress_lock, flags);
-        entry->next = client->eg_cache;
-        entry->prev = NULL;
-        if (client->eg_cache != NULL)
-                client->eg_cache->prev = entry;
-        client->eg_cache = entry;
-        write_unlock_irqrestore(&client->egress_lock, flags);
-        dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: unlocked\n");
-
-        memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
-        entry->ctrl_info = msg->content.eg_info;
-        do_gettimeofday(&(entry->tv));
-        entry->entry_state = EGRESS_RESOLVED;
-        dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id));
-        ip = (unsigned char *)&entry->ctrl_info.mps_ip;
-        dprintk("mpoa: mpoa_caches.c: mps_ip = %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
-        return entry;
+       ip = (unsigned char *)&msg->content.eg_info.eg_dst_ip;
+       dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(ip));
+       memset(entry, 0, sizeof(eg_cache_entry));
+
+       atomic_set(&entry->use, 1);
+       dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n");
+       write_lock_irq(&client->egress_lock);
+       entry->next = client->eg_cache;
+       entry->prev = NULL;
+       if (client->eg_cache != NULL)
+               client->eg_cache->prev = entry;
+       client->eg_cache = entry;
+
+       memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
+       entry->ctrl_info = msg->content.eg_info;
+       do_gettimeofday(&(entry->tv));
+       entry->entry_state = EGRESS_RESOLVED;
+       dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id));
+       ip = (unsigned char *)&entry->ctrl_info.mps_ip;
+       dprintk("mpoa: mpoa_caches.c: mps_ip = %u.%u.%u.%u\n", NIPQUAD(ip));
+       atomic_inc(&entry->use);
+
+       write_unlock_irq(&client->egress_lock);
+       dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: unlocked\n");
+
+       return entry;
 }
 
 static void update_eg_cache_entry(eg_cache_entry * entry, uint16_t holding_time)
 {
-        do_gettimeofday(&(entry->tv));
-        entry->entry_state = EGRESS_RESOLVED;
-        entry->ctrl_info.holding_time = holding_time;
+       do_gettimeofday(&(entry->tv));
+       entry->entry_state = EGRESS_RESOLVED;
+       entry->ctrl_info.holding_time = holding_time;
 
-        return;
+       return;
 }
 
-static void clear_expired(struct mpoa_client *client){
-        eg_cache_entry *entry, *next_entry;
-        unsigned long flags;
-        struct timeval now;
+static void clear_expired(struct mpoa_client *client)
+{
+       eg_cache_entry *entry, *next_entry;
+       struct timeval now;
        struct k_message msg;
 
-        do_gettimeofday(&now);
+       do_gettimeofday(&now);
 
-        write_lock_irqsave(&client->egress_lock, flags);
-        entry = client->eg_cache;
-        while(entry != NULL){
-               next_entry = entry->next;
-                if((now.tv_sec - entry->tv.tv_sec) 
-                   > entry->ctrl_info.holding_time){
-                       msg.type = SND_EGRESS_PURGE;
+       write_lock_irq(&client->egress_lock);
+       entry = client->eg_cache;
+       while(entry != NULL){
+               next_entry = entry->next;
+               if((now.tv_sec - entry->tv.tv_sec)
+                  > entry->ctrl_info.holding_time){
+                       msg.type = SND_EGRESS_PURGE;
                        msg.content.eg_info = entry->ctrl_info;
-                       dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id));
+                       dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id));
                        msg_to_mpoad(&msg, client);
-                        eg_cache_remove(entry, client);
-                }
-                entry = next_entry;
-        }
-        write_unlock_irqrestore(&client->egress_lock, flags);
+                       client->eg_ops->remove_entry(entry, client);
+               }
+               entry = next_entry;
+       }
+       write_unlock_irq(&client->egress_lock);
+
+       return;
+}
+
+static void eg_destroy_cache(struct mpoa_client *mpc)
+{
+       write_lock_irq(&mpc->egress_lock);
+       while(mpc->eg_cache != NULL)
+               mpc->eg_ops->remove_entry(mpc->eg_cache, mpc);
+       write_unlock_irq(&mpc->egress_lock);
 
-        return;
+       return;
 }
 
 
 
 static struct in_cache_ops ingress_ops = {
-        new_in_cache_entry,               /* new_entry        */
-        in_cache_search,                  /* search           */
-        in_cache_search_with_mask,        /* search_with_mask */
-       in_cache_search_by_vcc,           /* search_by_vcc    */
-        cache_hit,                        /* cache_hit        */
-        in_cache_remove,                  /* cache_remove     */
-        clear_count_and_expired,          /* clear_count      */
-        check_resolving_entries,          /* check_resolving  */
-        refresh_entries,                  /* refresh          */
+       in_cache_add_entry,               /* add_entry       */
+       in_cache_get,                     /* get             */
+       in_cache_get_with_mask,           /* get_with_mask   */
+       in_cache_get_by_vcc,              /* get_by_vcc      */
+       in_cache_put,                     /* put             */
+       in_cache_remove_entry,            /* remove_entry    */
+       cache_hit,                        /* cache_hit       */
+       clear_count_and_expired,          /* clear_count     */
+       check_resolving_entries,          /* check_resolving */
+       refresh_entries,                  /* refresh         */
+       in_destroy_cache                  /* destroy_cache   */
 };
 
 static struct eg_cache_ops egress_ops = {
-        new_eg_cache_entry,               /* new_entry          */
-        eg_cache_search_by_cache_id,      /* search_by_cache_id */
-        eg_cache_search_by_tag,           /* search_by_tag      */ 
-        eg_cache_search_by_vcc,           /* search_by_vcc      */
-        eg_cache_search_by_src_ip,        /* search_by_src_ip   */
-        eg_cache_remove,                  /* cache_remove       */
-        update_eg_cache_entry,            /* update             */
-       clear_expired                     /* clear_expired      */
+       eg_cache_add_entry,               /* add_entry        */
+       eg_cache_get_by_cache_id,         /* get_by_cache_id  */
+       eg_cache_get_by_tag,              /* get_by_tag       */
+       eg_cache_get_by_vcc,              /* get_by_vcc       */
+       eg_cache_get_by_src_ip,           /* get_by_src_ip    */
+       eg_cache_put,                     /* put              */
+       eg_cache_remove_entry,            /* remove_entry     */
+       update_eg_cache_entry,            /* update           */
+       clear_expired,                    /* clear_expired    */
+       eg_destroy_cache                  /* destroy_cache    */
 };
 
 
 void atm_mpoa_init_cache(struct mpoa_client *mpc)
 {
-        mpc->in_ops = &ingress_ops;
-        mpc->eg_ops = &egress_ops;
+       mpc->in_ops = &ingress_ops;
+       mpc->eg_ops = &egress_ops;
 
-        return;
+       return;
 }
index cdcd6ac163f0131bd9687a7c4406bbd7fa36e664..6c9886a03d0b53d593add2431c4ca6cafc0e9e7e 100644 (file)
@@ -25,24 +25,27 @@ typedef struct in_cache_entry {
         struct   atm_vcc *shortcut;
         uint8_t  MPS_ctrl_ATM_addr[ATM_ESA_LEN];
         struct   in_ctrl_info ctrl_info;
+        atomic_t use;
 } in_cache_entry;
 
 struct in_cache_ops{
-        in_cache_entry *(*new_entry)(uint32_t dst_ip,
-                                    struct mpoa_client *client);
-        in_cache_entry *(*search)(uint32_t dst_ip, struct mpoa_client *client);
-        in_cache_entry *(*search_with_mask)(uint32_t dst_ip, 
-                                           struct mpoa_client *client,
-                                           uint32_t mask);
-        in_cache_entry *(*search_by_vcc)(struct atm_vcc *vcc, 
-                                         struct mpoa_client *client);
-        int            (*cache_hit)(in_cache_entry *entry,
-                                    struct mpoa_client *client);
-        int            (*cache_remove)(in_cache_entry *delEntry,
-                                        struct mpoa_client *client );
-        void           (*clear_count)(struct mpoa_client *client);
-        void           (*check_resolving)(struct mpoa_client *client);
-        void           (*refresh)(struct mpoa_client *client);
+        in_cache_entry *(*add_entry)(uint32_t dst_ip,
+                                      struct mpoa_client *client);
+        in_cache_entry *(*get)(uint32_t dst_ip, struct mpoa_client *client);
+        in_cache_entry *(*get_with_mask)(uint32_t dst_ip, 
+                                        struct mpoa_client *client,
+                                        uint32_t mask);
+        in_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, 
+                                      struct mpoa_client *client);
+        void            (*put)(in_cache_entry *entry);
+        void            (*remove_entry)(in_cache_entry *delEntry,
+                                       struct mpoa_client *client );
+        int             (*cache_hit)(in_cache_entry *entry,
+                                     struct mpoa_client *client);
+        void            (*clear_count)(struct mpoa_client *client);
+        void            (*check_resolving)(struct mpoa_client *client);
+        void            (*refresh)(struct mpoa_client *client);
+        void            (*destroy_cache)(struct mpoa_client *mpc);
 };
 
 typedef struct eg_cache_entry{
@@ -55,17 +58,20 @@ typedef struct eg_cache_entry{
         uint16_t             entry_state;
         uint32_t             latest_ip_addr;    /* The src IP address of the last packet */
         struct eg_ctrl_info  ctrl_info;
+        atomic_t             use;
 } eg_cache_entry;
 
 struct eg_cache_ops{
-        eg_cache_entry *(*new_entry)(struct k_message *msg, struct mpoa_client *client);
-        eg_cache_entry *(*search_by_cache_id)(uint32_t cache_id, struct mpoa_client *client);
-        eg_cache_entry *(*search_by_tag)(uint32_t cache_id, struct mpoa_client *client);
-        eg_cache_entry *(*search_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client);
-        eg_cache_entry *(*search_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client);
-        int            (*cache_remove)(eg_cache_entry *entry, struct mpoa_client *client);
-        void           (*update)(eg_cache_entry *entry, uint16_t holding_time);
-        void           (*clear_expired)(struct mpoa_client *client);
+        eg_cache_entry *(*add_entry)(struct k_message *msg, struct mpoa_client *client);
+        eg_cache_entry *(*get_by_cache_id)(uint32_t cache_id, struct mpoa_client *client);
+        eg_cache_entry *(*get_by_tag)(uint32_t cache_id, struct mpoa_client *client);
+        eg_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client);
+        eg_cache_entry *(*get_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client);
+        void            (*put)(eg_cache_entry *entry);
+        void            (*remove_entry)(eg_cache_entry *entry, struct mpoa_client *client);
+        void            (*update)(eg_cache_entry *entry, uint16_t holding_time);
+        void            (*clear_expired)(struct mpoa_client *client);
+        void            (*destroy_cache)(struct mpoa_client *mpc);
 };
 
 
index 0899c9f934e12b2c75e07bd741179d345029cfe9..738b2a7beaeabeb598d6eab973bd1dce9f1e2267 100644 (file)
@@ -39,7 +39,7 @@ static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb)
        DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->tx_inuse,skb->truesize);
        atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
        dev_kfree_skb_any(skb);
-       wake_up(&vcc->wsleep);
+       wake_up(&vcc->sleep);
 }
 
 
index 0195f363139de8b67eafe106571becfdc8d362ae..bbbd53a60d521a2d0e1fa0a078c7db69a458a4b1 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Lennert Buytenhek               <buytenh@gnu.org>
  *
- *     $Id: br.c,v 1.41 2000/03/24 01:33:36 davem Exp $
+ *     $Id: br.c,v 1.42 2000/04/14 10:10:34 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
@@ -45,10 +45,8 @@ static int __init br_init(void)
        br_handle_frame_hook = br_handle_frame;
        br_ioctl_hook = br_ioctl_deviceless_stub;
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
-       write_lock(&lane_bridge_hook_lock);
        br_fdb_get_hook = br_fdb_get;
        br_fdb_put_hook = br_fdb_put;
-       write_unlock(&lane_bridge_hook_lock);
 #endif
        register_netdevice_notifier(&br_device_notifier);
 
@@ -71,10 +69,8 @@ static void __exit br_deinit(void)
        br_call_ioctl_atomic(__br_clear_ioctl_hook);
        net_call_rx_atomic(__br_clear_frame_hook);
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
-       write_lock(&lane_bridge_hook_lock);
        br_fdb_get_hook = NULL;
        br_fdb_put_hook = NULL;
-       write_unlock(&lane_bridge_hook_lock);
 #endif
 }
 
index 02c3bc9892fa16fb4996f30e80b724992320ec8e..7f9b9e82b6f8f32a12042d0ca3b593726a2f1083 100644 (file)
@@ -186,18 +186,10 @@ void nf_dump_skb(int pf, struct sk_buff *skb)
                        dst_port = ntohs(tcp->dest);
                }
        
-               printk("PROTO=%d %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu"
+               printk("PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu"
                       " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
-                      ip->protocol,
-                      (ntohl(ip->saddr)>>24)&0xFF,
-                      (ntohl(ip->saddr)>>16)&0xFF,
-                      (ntohl(ip->saddr)>>8)&0xFF,
-                      (ntohl(ip->saddr))&0xFF,
-                      src_port,
-                      (ntohl(ip->daddr)>>24)&0xFF,
-                      (ntohl(ip->daddr)>>16)&0xFF,
-                      (ntohl(ip->daddr)>>8)&0xFF,
-                      (ntohl(ip->daddr))&0xFF,
+                      ip->protocol, NIPQUAD(ip->saddr),
+                      src_port, NIPQUAD(ip->daddr),
                       dst_port,
                       ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
                       ntohs(ip->frag_off), ip->ttl);
index c8be17e5b2dba1fd1f9c94d7578caa1e984e7d74..234e9c1825456dbc92d508870fbc331ac73b9890 100644 (file)
@@ -4,7 +4,7 @@
  *     Authors:        Alan Cox <iiitac@pyr.swan.ac.uk>
  *                     Florian La Roche <rzsfl@rz.uni-sb.de>
  *
- *     Version:        $Id: skbuff.c,v 1.71 2000/03/29 11:58:33 davem Exp $
+ *     Version:        $Id: skbuff.c,v 1.72 2000/04/13 00:55:54 davem Exp $
  *
  *     Fixes:  
  *             Alan Cox        :       Fixed the worst of the load balancer bugs.
index 36f890c39b6e843b7abffdad198dc96c13d6c0ab..4044a7f7defe11e8d18a57b007c3bcdb0ee2edec 100644 (file)
@@ -7,7 +7,7 @@
  *             handler for protocols to use and generic option handler.
  *
  *
- * Version:    $Id: sock.c,v 1.92 2000/04/08 07:21:15 davem Exp $
+ * Version:    $Id: sock.c,v 1.93 2000/04/13 03:13:29 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1068,7 +1068,7 @@ int sock_no_sendmsg(struct socket *sock, struct msghdr *m, int flags,
        return -EOPNOTSUPP;
 }
 
-int sock_no_recvmsg(struct socket *sock, struct msghdr *m, int flags,
+int sock_no_recvmsg(struct socket *sock, struct msghdr *m, int len, int flags,
                    struct scm_cookie *scm)
 {
        return -EOPNOTSUPP;
index a22098207a090d97439f7a3d5e4d5bb8af6889cd..a53a69581751fc6d8b8a3188141c51bdafbb9b96 100644 (file)
@@ -1131,7 +1131,7 @@ void __exit econet_proto_exit(void)
 #endif
 }
 
-int __init econet_proto_init(struct net_proto *pro)
+int __init econet_proto_init(void)
 {
        extern void econet_sysctl_register(void);
        sock_register(&econet_family_ops);
index 588cdf03087073c0346d6eba997bd9b3baa50f49..bd6ae7d17ac2f54d1b892105136bb591ce11334b 100644 (file)
@@ -1021,7 +1021,6 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length)
        char hbuffer[HBUFFERLEN];
        int i,j,k;
        const char hexbuf[] =  "0123456789ABCDEF";
-       char abuf[16];
 
        size = sprintf(buffer,"IP address       HW type     Flags       HW address            Mask     Device\n");
 
@@ -1061,8 +1060,8 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length)
 #endif
 
                        size = sprintf(buffer+len,
-                               "%-17s0x%-10x0x%-10x%s",
-                               in_ntoa2(*(u32*)n->primary_key, abuf),
+                               "%u.%u.%u.%u0x%-10x0x%-10x%s",
+                               NIPQUAD(*(u32*)n->primary_key),
                                hatype,
                                arp_state_to_flags(n), 
                                hbuffer);
@@ -1091,8 +1090,8 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length)
                        int hatype = dev ? dev->type : 0;
 
                        size = sprintf(buffer+len,
-                               "%-17s0x%-10x0x%-10x%s",
-                               in_ntoa2(*(u32*)n->key, abuf),
+                               "%u.%u.%u.%u0x%-10x0x%-10x%s",
+                               NIPQUAD(*(u32*)n->key),
                                hatype,
                                ATF_PUBL|ATF_PERM,
                                "00:00:00:00:00:00");
index 5ee1bfd78dbf35be826c37bc3ce22dfc3fd10087..12f57662510c83ea7e7ae00aac9d31f4660f52a5 100644 (file)
@@ -298,7 +298,8 @@ int fib_lookup(const struct rt_key *key, struct fib_result *res)
        u32 daddr = key->dst;
        u32 saddr = key->src;
 
-FRprintk("Lookup: %08x <- %08x ", key->dst, key->src);
+FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
+       NIPQUAD(key->dst), NIPQUAD(key->src));
        read_lock(&fib_rules_lock);
        for (r = fib_rules; r; r=r->r_next) {
                if (((saddr^r->r_src) & r->r_srcmask) ||
index 559bb238e3a6e2805976990217a7b3bbc5091f24..e14cc3f87791b39cf2624544fe1298ee3af0c1a3 100644 (file)
@@ -723,7 +723,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len)
                        case ICMP_FRAG_NEEDED:
                                if (ipv4_config.no_pmtu_disc) {
                                        if (net_ratelimit())
-                                               printk(KERN_INFO "ICMP: %d.%d.%d.%d: fragmentation needed and DF set.\n",
+                                               printk(KERN_INFO "ICMP: %u.%u.%u.%u: fragmentation needed and DF set.\n",
                                                       NIPQUAD(iph->daddr));
                                } else {
                                        unsigned short new_mtu;
@@ -735,7 +735,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len)
                                break;
                        case ICMP_SR_FAILED:
                                if (net_ratelimit())
-                                       printk(KERN_INFO "ICMP: %d.%d.%d.%d: Source Route Failed.\n", NIPQUAD(iph->daddr));
+                                       printk(KERN_INFO "ICMP: %u.%u.%u.%u: Source Route Failed.\n", NIPQUAD(iph->daddr));
                                break;
                        default:
                                break;
@@ -765,7 +765,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len)
                if (inet_addr_type(iph->daddr) == RTN_BROADCAST)
                {
                        if (net_ratelimit())
-                               printk(KERN_WARNING "%d.%d.%d.%d sent an invalid ICMP error to a broadcast.\n",
+                               printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP error to a broadcast.\n",
                                NIPQUAD(skb->nh.iph->saddr));
                        return; 
                }
@@ -986,9 +986,8 @@ static void icmp_address_reply(struct icmphdr *icmph, struct sk_buff *skb, int l
                                break;
                }
                if (!ifa && net_ratelimit()) {
-                       char b1[16], b2[16];
-                       printk(KERN_INFO "Wrong address mask %s from %s/%s\n",
-                              in_ntoa2(mask, b1), in_ntoa2(rt->rt_src, b2), dev->name);
+                       printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from %s/%u.%u.%u.%u\n",
+                              NIPQUAD(mask), dev->name, NIPQUAD(rt->rt_src));
                }
        }
        read_unlock(&in_dev->lock);
index 852a4fb2cbb4ebdf6f8cc49072a4172f6eae71f7..8e3133b31412496563407f023a9c0a97079ccf00 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The IP fragmentation functionality.
  *             
- * Version:    $Id: ip_fragment.c,v 1.47 2000/02/09 21:11:33 davem Exp $
+ * Version:    $Id: ip_fragment.c,v 1.48 2000/04/13 01:05:33 davem Exp $
  *
  * Authors:    Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
  *             Alan Cox <Alan.Cox@linux.org>
@@ -387,8 +387,13 @@ static struct sk_buff *ip_glue(struct ipq *qp)
        */
        skb->security = qp->fragments->skb->security;
 
+#ifdef CONFIG_NETFILTER
+       /* Connection association is same as fragment (if any). */
+       skb->nfct = qp->fragments->skb->nfct;
+       nf_conntrack_get(skb->nfct);
 #ifdef CONFIG_NETFILTER_DEBUG
        skb->nf_debug = qp->fragments->skb->nf_debug;
+#endif
 #endif
 
        /* Done with all fragments. Fixup the new IP header. */
@@ -594,7 +599,7 @@ out:
         */
 out_oversize:
        if (net_ratelimit())
-               printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n",
+               printk(KERN_INFO "Oversized packet received from %u.%u.%u.%u\n",
                        NIPQUAD(iph->saddr));
        /* the skb isn't in a fragment, so fall through to free it */
 out_freeskb:
index 0c755dbcdb45cfeabd73040e63d3ffbcac555d60..e0c550bd99d75ff2b28bd6cdf20495193a2bfe6c 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The Internet Protocol (IP) module.
  *
- * Version:    $Id: ip_input.c,v 1.46 2000/02/22 23:54:26 davem Exp $
+ * Version:    $Id: ip_input.c,v 1.47 2000/04/13 01:11:59 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -162,7 +162,13 @@ int ip_call_ra_chain(struct sk_buff *skb)
        read_lock(&ip_ra_lock);
        for (ra = ip_ra_chain; ra; ra = ra->next) {
                struct sock *sk = ra->sk;
-               if (sk && sk->num == protocol) {
+
+               /* If socket is bound to an interface, only report
+                * the packet if it came  from that interface.
+                */
+               if (sk && sk->num == protocol 
+                   && ((sk->bound_dev_if == 0) 
+                       || (sk->bound_dev_if == skb->dev->ifindex))) {
                        if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
                                skb = ip_defrag(skb);
                                if (skb == NULL) {
@@ -349,7 +355,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb)
                        if (in_dev) {
                                if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
                                        if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
-                                               printk(KERN_INFO "source route option %d.%d.%d.%d -> %d.%d.%d.%d\n",
+                                               printk(KERN_INFO "source route option %u.%u.%u.%u -> %u.%u.%u.%u\n",
                                                       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
                                        in_dev_put(in_dev);
                                        goto drop;
index a0a49cdb22b990da6f7a2d3650840821101d520a..654e98ffae01f3e83e8c551ef55727a13f12fc9c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  $Id: ipconfig.c,v 1.27 2000/02/21 15:51:41 davem Exp $
+ *  $Id: ipconfig.c,v 1.29 2000/04/13 01:16:17 davem Exp $
  *
  *  Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
  *  information to configure own IP address and routes.
@@ -77,7 +77,7 @@ u8 root_server_path[256] __initdata = { 0, };         /* Path to mount as root */
 
 #define CONFIG_IP_PNP_DYNAMIC
 
-static int ic_proto_enabled __initdata = 0                     /* Protocols enabled */
+int ic_proto_enabled __initdata = 0                    /* Protocols enabled */
 #ifdef CONFIG_IP_PNP_BOOTP
                        | IC_BOOTP
 #endif
@@ -227,17 +227,20 @@ static int __init ic_setup_if(void)
        strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name);
        set_sockaddr(sin, ic_myaddr, 0);
        if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) {
-               printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err);
+               printk(KERN_ERR "IP-Config: Unable to set interface address (%u.%u.%u.%u).\n",
+                       NIPQUAD(err));
                return -1;
        }
        set_sockaddr(sin, ic_netmask, 0);
        if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) {
-               printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err);
+               printk(KERN_ERR "IP-Config: Unable to set interface netmask (%u.%u.%u.%u).\n",
+                       NIPQUAD(err));
                return -1;
        }
        set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0);
        if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) {
-               printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err);
+               printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%u.%u.%u.%u).\n",
+                       NIPQUAD(err));
                return -1;
        }
        return 0;
@@ -261,7 +264,8 @@ static int __init ic_setup_routes(void)
                set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0);
                rm.rt_flags = RTF_UP | RTF_GATEWAY;
                if ((err = ic_route_ioctl(SIOCADDRT, &rm)) < 0) {
-                       printk(KERN_ERR "IP-Config: Cannot add default route (%d).\n", err);
+                       printk(KERN_ERR "IP-Config: Cannot add default route (%u.%u.%u.%u).\n",
+                               NIPQUAD(err));
                        return -1;
                }
        }
@@ -294,10 +298,11 @@ static int __init ic_defaults(void)
                else if (IN_CLASSC(ntohl(ic_myaddr)))
                        ic_netmask = htonl(IN_CLASSC_NET);
                else {
-                       printk(KERN_ERR "IP-Config: Unable to guess netmask for address %08x\n", ic_myaddr);
+                       printk(KERN_ERR "IP-Config: Unable to guess netmask for address %u.%u.%u.%u\n",
+                               NIPQUAD(ic_myaddr));
                        return -1;
                }
-               printk("IP-Config: Guessing netmask %s\n", in_ntoa(ic_netmask));
+               printk("IP-Config: Guessing netmask %u.%u.%u.%u\n", NIPQUAD(ic_netmask));
        }
 
        return 0;
@@ -807,10 +812,10 @@ static int __init ic_dynamic(void)
        if (!ic_got_reply)
                return -1;
 
-       printk("IP-Config: Got %s answer from %s, ",
+       printk("IP-Config: Got %s answer from %u.%u.%u.%u, ",
                (ic_got_reply & IC_BOOTP) ? "BOOTP" : "RARP",
-               in_ntoa(ic_servaddr));
-       printk("my address is %s\n", in_ntoa(ic_myaddr));
+               NIPQUAD(ic_servaddr));
+       printk("my address is %u.%u.%u.%u\n", NIPQUAD(ic_myaddr));
 
        return 0;
 }
index 197c2e3b44afc83a0e91e7678a95dddbcd90433d..fdfd747e2ea17858b0b330a917c6abd7ea36a516 100644 (file)
@@ -343,6 +343,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
        size_t hash, repl_hash;
        struct ip_conntrack_expect *expected;
        enum ip_conntrack_info ctinfo;
+       unsigned long extra_jiffies;
        int i;
 
        if (!invert_tuple(&repl_tuple, tuple, protocol)) {
@@ -366,19 +367,24 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
        repl_hash = hash_conntrack(&repl_tuple);
 
        memset(conntrack, 0, sizeof(struct ip_conntrack));
-       atomic_set(&conntrack->ct_general.use, 1);
+       atomic_set(&conntrack->ct_general.use, 2);
        conntrack->ct_general.destroy = destroy_conntrack;
        conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple;
        conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack;
        conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple;
        conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack;
-       for(i=0; i < IP_CT_NUMBER; i++)
+       for (i=0; i < IP_CT_NUMBER; i++)
                conntrack->infos[i].master = &conntrack->ct_general;
 
-       if (!protocol->new(conntrack, skb->nh.iph, skb->len)) {
+       extra_jiffies = protocol->new(conntrack, skb->nh.iph, skb->len);
+       if (!extra_jiffies) {
                kmem_cache_free(ip_conntrack_cachep, conntrack);
                return 1;
        }
+       conntrack->timeout.data = (unsigned long)conntrack;
+       conntrack->timeout.function = death_by_timeout;
+       conntrack->timeout.expires = jiffies + extra_jiffies;
+       add_timer(&conntrack->timeout);
 
        /* Sew in at head of hash list. */
        WRITE_LOCK(&ip_conntrack_lock);
@@ -421,7 +427,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
 }
 
 static void
-resolve_normal_ct(struct sk_buff *skb)
+resolve_normal_ct(struct sk_buff *skb, int create)
 {
        struct ip_conntrack_tuple tuple;
        struct ip_conntrack_tuple_hash *h;
@@ -436,7 +442,7 @@ resolve_normal_ct(struct sk_buff *skb)
        do {
                /* look for tuple match */
                h = ip_conntrack_find_get(&tuple, NULL);
-               if (!h && init_conntrack(&tuple, proto, skb))
+               if (!h && (!create || init_conntrack(&tuple, proto, skb)))
                        return;
        } while (!h);
 
@@ -464,13 +470,15 @@ resolve_normal_ct(struct sk_buff *skb)
 }
 
 /* Return conntrack and conntrack_info a given skb */
-struct ip_conntrack *
-ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+static struct ip_conntrack *
+__ip_conntrack_get(struct sk_buff *skb,
+                  enum ip_conntrack_info *ctinfo,
+                  int create)
 {
        if (!skb->nfct) {
                /* It may be an icmp error... */
                if (!icmp_error_track(skb))
-                       resolve_normal_ct(skb);
+                       resolve_normal_ct(skb, create);
        }
 
        if (skb->nfct) {
@@ -485,6 +493,12 @@ ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
        return NULL;
 }
 
+struct ip_conntrack *
+ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+{
+       return __ip_conntrack_get(skb, ctinfo, 0);
+}
+
 /* Netfilter hook itself. */
 unsigned int ip_conntrack_in(unsigned int hooknum,
                             struct sk_buff **pskb,
@@ -512,13 +526,13 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
                        return NF_STOLEN;
        }
 
-       ct = ip_conntrack_get(*pskb, &ctinfo);
-       if (!ct)
+       ct = __ip_conntrack_get(*pskb, &ctinfo, 1);
+       if (!ct) {
                /* Not valid part of a connection */
                return NF_ACCEPT;
+       }
 
        proto = find_proto((*pskb)->nh.iph->protocol);
-       /* If this is new, this is first time timer will be set */
        ret = proto->packet(ct, (*pskb)->nh.iph, (*pskb)->len, ctinfo);
 
        if (ret == -1) {
@@ -645,24 +659,16 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
        MOD_DEC_USE_COUNT;
 }
 
-/* Refresh conntrack for this many jiffies: if noone calls this,
-   conntrack will vanish with current skb. */
+/* Refresh conntrack for this many jiffies. */
 void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
 {
+       IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
+
        WRITE_LOCK(&ip_conntrack_lock);
-       /* If this hasn't had a timer before, it's still being set up */
-       if (ct->timeout.data == 0) {
-               ct->timeout.data = (unsigned long)ct;
-               ct->timeout.function = death_by_timeout;
+       /* Need del_timer for race avoidance (may already be dying). */
+       if (del_timer(&ct->timeout)) {
                ct->timeout.expires = jiffies + extra_jiffies;
-               atomic_inc(&ct->ct_general.use);
                add_timer(&ct->timeout);
-       } else {
-               /* Need del_timer for race avoidance (may already be dying). */
-               if (del_timer(&ct->timeout)) {
-                       ct->timeout.expires = jiffies + extra_jiffies;
-                       add_timer(&ct->timeout);
-               }
        }
        WRITE_UNLOCK(&ip_conntrack_lock);
 }
index 77a491e349c68740d564dcc9439f2f9292104a2a..6e2bcbcec436807056db3e0cca3c3d8625d82010 100644 (file)
@@ -48,9 +48,10 @@ static int established(struct ip_conntrack *conntrack,
 }
 
 /* Called when a new connection for this protocol found. */
-static int new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len)
+static unsigned long
+new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len)
 {
-       return 1;
+       return GENERIC_TIMEOUT;
 }
 
 struct ip_conntrack_protocol ip_conntrack_generic_protocol
index cbbc1ab8c682a7375bacff8ca9495d7eff4e647e..17e126119b9b5cb5c72d6c46baa7db8b2cfd5320 100644 (file)
@@ -86,8 +86,8 @@ static int icmp_packet(struct ip_conntrack *ct,
 }
 
 /* Called when a new connection for this protocol found. */
-static int icmp_new(struct ip_conntrack *conntrack,
-                    struct iphdr *iph, size_t len)
+static unsigned long icmp_new(struct ip_conntrack *conntrack,
+                             struct iphdr *iph, size_t len)
 {
        static u_int8_t valid_new[]
                = { [ICMP_ECHO] = 1,
@@ -103,7 +103,7 @@ static int icmp_new(struct ip_conntrack *conntrack,
                DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
                return 0;
        }
-       return 1;
+       return ICMP_TIMEOUT;
 }
 
 struct ip_conntrack_protocol ip_conntrack_protocol_icmp
index 89324894395870242d7be8fb2a12cb41ff94b902..997a917bcb60327aeaa50591c913b14a479aaffe 100644 (file)
@@ -189,14 +189,13 @@ static int tcp_packet(struct ip_conntrack *conntrack,
        conntrack->proto.tcp_state = newconntrack;
        WRITE_UNLOCK(&tcp_lock);
 
-       /* Refresh: need write lock to write to conntrack. */
        ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]);
        return NF_ACCEPT;
 }
 
 /* Called when a new connection for this protocol found. */
-static int tcp_new(struct ip_conntrack *conntrack,
-                  struct iphdr *iph, size_t len)
+static unsigned long tcp_new(struct ip_conntrack *conntrack,
+                            struct iphdr *iph, size_t len)
 {
        enum tcp_conntrack newconntrack;
        struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
@@ -210,11 +209,10 @@ static int tcp_new(struct ip_conntrack *conntrack,
        if (newconntrack == TCP_CONNTRACK_MAX) {
                DEBUGP("ip_conntrack_tcp: invalid new deleting.\n");
                return 0;
-       } else {
-               conntrack->proto.tcp_state = newconntrack;
-               ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]);
        }
-       return 1;
+
+       conntrack->proto.tcp_state = newconntrack;
+       return tcp_timeouts[conntrack->proto.tcp_state];
 }
 
 struct ip_conntrack_protocol ip_conntrack_protocol_tcp
index 79ec821513da8004b636b4d8ba7aab334a5484f3..521bd765415a73376fa9232ffb6187df149bb473 100644 (file)
@@ -54,10 +54,10 @@ static int udp_packet(struct ip_conntrack *conntrack,
 }
 
 /* Called when a new connection for this protocol found. */
-static int udp_new(struct ip_conntrack *conntrack,
-                   struct iphdr *iph, size_t len)
+static unsigned long udp_new(struct ip_conntrack *conntrack,
+                            struct iphdr *iph, size_t len)
 {
-       return 1;
+       return UDP_TIMEOUT;
 }
 
 struct ip_conntrack_protocol ip_conntrack_protocol_udp
index 9030d9d41937df51f59357669284418f2255e516..3219f4c8564e240317a3a2e08ae312a7823b371c 100644 (file)
@@ -169,8 +169,6 @@ static unsigned int ip_refrag(unsigned int hooknum,
           interface.  We degfragment them at LOCAL_OUT, however,
           so we have to refragment them here. */
        if ((*pskb)->len > rt->u.dst.pmtu) {
-               DEBUGP("ip_conntrack: refragm %p (size %u) to %u (okfn %p)\n",
-                      *pskb, (*pskb)->len, rt->u.dst.pmtu, okfn);
                /* No hook can be after us, so this should be OK. */
                ip_fragment(*pskb, okfn);
                return NF_STOLEN;
@@ -178,13 +176,29 @@ static unsigned int ip_refrag(unsigned int hooknum,
        return NF_ACCEPT;
 }
 
+static unsigned int ip_conntrack_local(unsigned int hooknum,
+                                      struct sk_buff **pskb,
+                                      const struct net_device *in,
+                                      const struct net_device *out,
+                                      int (*okfn)(struct sk_buff *))
+{
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr)
+           || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
+               if (net_ratelimit())
+                       printk("ipt_hook: happy cracking.\n");
+               return NF_ACCEPT;
+       }
+       return ip_conntrack_in(hooknum, pskb, in, out, okfn);
+}
+
 /* Connection tracking may drop packets, but never alters them, so
    make it the first hook. */
 static struct nf_hook_ops ip_conntrack_in_ops
 = { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
        NF_IP_PRI_CONNTRACK };
 static struct nf_hook_ops ip_conntrack_local_out_ops
-= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_LOCAL_OUT,
+= { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
        NF_IP_PRI_CONNTRACK };
 /* Refragmenter; last chance. */
 static struct nf_hook_ops ip_conntrack_out_ops
index bfcc435c23c36f49ef8ad375c3dc122a0a21da34..0c582b867bef9935f2545a2c517bc6eae49795de 100644 (file)
@@ -130,6 +130,11 @@ ip_nat_out(unsigned int hooknum,
           const struct net_device *out,
           int (*okfn)(struct sk_buff *))
 {
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr)
+           || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+               return NF_ACCEPT;
+
        /* We can hit fragment here; forwarded packets get
           defragmented by connection tracking coming in, then
           fragmented (grr) by the forward code.
@@ -150,6 +155,21 @@ ip_nat_out(unsigned int hooknum,
        return ip_nat_fn(hooknum, pskb, in, out, okfn);
 }
 
+static unsigned int
+ip_nat_local_fn(unsigned int hooknum,
+               struct sk_buff **pskb,
+               const struct net_device *in,
+               const struct net_device *out,
+               int (*okfn)(struct sk_buff *))
+{
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr)
+           || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+               return NF_ACCEPT;
+
+       return ip_nat_fn(hooknum, pskb, in, out, okfn);
+}
+
 /* We must be after connection tracking and before packet filtering. */
 
 /* Before packet filtering, change destination */
@@ -160,7 +180,7 @@ static struct nf_hook_ops ip_nat_out_ops
 = { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC};
 /* Before packet filtering, change destination */
 static struct nf_hook_ops ip_nat_local_out_ops
-= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST };
+= { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST };
 
 /* Protocol registration. */
 int ip_nat_protocol_register(struct ip_nat_protocol *proto)
index 80e43d977605379c02ff698f5ade2f9992009214..72b47568bfb669a3368560c2c6191e1afd646643 100644 (file)
@@ -509,7 +509,7 @@ static int ipq_get_info(char *buffer, char **start, off_t offset, int length)
                      "Peer pid            : %d\n"
                      "Peer died           : %d\n"
                      "Peer copy mode      : %d\n"
-                     "Peer copy range     : %d\n"
+                     "Peer copy range     : %Zu\n"
                      "Queue length        : %d\n"
                      "Queue max. length   : %d\n"
                      "Queue flushing      : %d\n"
index 66f47c3865df6b54e2b9d75e328b6403829e598a..73424cef80d9d0967529d63a1967ae3d70724b71 100644 (file)
@@ -39,7 +39,7 @@
 #define IP_NF_ASSERT(x)                                                \
 do {                                                           \
        if (!(x))                                               \
-               printk("IPT_ASSERT: %s:%s:%u\n",                \
+               printk("IP_NF_ASSERT: %s:%s:%u\n",              \
                       __FUNCTION__, __FILE__, __LINE__);       \
 } while(0)
 #else
@@ -683,7 +683,6 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
        target = find_target_lock(t->u.name, &ret, &ipt_mutex);
        if (!target) {
                duprintf("check_entry: `%s' not found\n", t->u.name);
-               up(&ipt_mutex);
                return ret;
        }
        if (target->me)
@@ -1283,17 +1282,16 @@ ipt_register_target(struct ipt_target *target)
 {
        int ret;
 
+       MOD_INC_USE_COUNT;
        ret = down_interruptible(&ipt_mutex);
        if (ret != 0)
                return ret;
 
-       if (list_named_insert(&ipt_target, target)) {
-               MOD_INC_USE_COUNT;
-               ret = 0;
-       } else {
+       if (!list_named_insert(&ipt_target, target)) {
                duprintf("ipt_register_target: `%s' already in list!\n",
                         target->name);
                ret = -EINVAL;
+               MOD_DEC_USE_COUNT;
        }
        up(&ipt_mutex);
        return ret;
@@ -1313,16 +1311,18 @@ ipt_register_match(struct ipt_match *match)
 {
        int ret;
 
+       MOD_INC_USE_COUNT;
        ret = down_interruptible(&ipt_mutex);
-       if (ret != 0)
+       if (ret != 0) {
+               MOD_DEC_USE_COUNT;
                return ret;
-
+       }
        if (list_named_insert(&ipt_match, match)) {
-               MOD_INC_USE_COUNT;
                ret = 0;
        } else {
                duprintf("ipt_register_match: `%s' already in list!\n",
                         match->name);
+               MOD_DEC_USE_COUNT;
                ret = -EINVAL;
        }
        up(&ipt_mutex);
@@ -1346,10 +1346,12 @@ int ipt_register_table(struct ipt_table *table)
        static struct ipt_table_info bootstrap
                = { 0, 0, { 0 }, { 0 }, { }, { } };
 
+       MOD_INC_USE_COUNT;
        newinfo = vmalloc(sizeof(struct ipt_table_info)
                          + SMP_ALIGN(table->table->size) * smp_num_cpus);
        if (!newinfo) {
                ret = -ENOMEM;
+               MOD_DEC_USE_COUNT;
                return ret;
        }
        memcpy(newinfo->entries, table->table->entries, table->table->size);
@@ -1361,12 +1363,14 @@ int ipt_register_table(struct ipt_table *table)
                              table->table->underflow);
        if (ret != 0) {
                vfree(newinfo);
+               MOD_DEC_USE_COUNT;
                return ret;
        }
 
        ret = down_interruptible(&ipt_mutex);
        if (ret != 0) {
                vfree(newinfo);
+               MOD_DEC_USE_COUNT;
                return ret;
        }
 
@@ -1386,7 +1390,6 @@ int ipt_register_table(struct ipt_table *table)
 
        table->lock = RW_LOCK_UNLOCKED;
        list_prepend(&ipt_tables, table);
-       MOD_INC_USE_COUNT;
 
  unlock:
        up(&ipt_mutex);
@@ -1394,6 +1397,7 @@ int ipt_register_table(struct ipt_table *table)
 
  free_unlock:
        vfree(newinfo);
+       MOD_DEC_USE_COUNT;
        goto unlock;
 }
 
index 419b0382cd49ee85aa003f06ce01ae2bb7be18e1..e22898512c52d98c3b0c81d18ea9ed263711662d 100644 (file)
@@ -419,18 +419,10 @@ static void dump_packet(const struct iphdr *ip,
                        printk("%d ",f->ipfw.fw_redirpt);
        }
 
-       printk("%s PROTO=%d %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu"
+       printk("%s PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu"
               " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
-              ifname, ip->protocol,
-              (ntohl(ip->saddr)>>24)&0xFF,
-              (ntohl(ip->saddr)>>16)&0xFF,
-              (ntohl(ip->saddr)>>8)&0xFF,
-              (ntohl(ip->saddr))&0xFF,
-              src_port,
-              (ntohl(ip->daddr)>>24)&0xFF,
-              (ntohl(ip->daddr)>>16)&0xFF,
-              (ntohl(ip->daddr)>>8)&0xFF,
-              (ntohl(ip->daddr))&0xFF,
+              ifname, ip->protocol, NIPQUAD(ip->saddr),
+              src_port, NIPQUAD(ip->daddr),
               dst_port,
               ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
               ntohs(ip->frag_off), ip->ttl);
index a1f4e16cf4ff17a9fb483c9fc4f7eb05942d2e44..2b07be32c45b97a93fde1489e68eb148152b0aa3 100644 (file)
 #define dprintf4(a1,a2,a3,a4)
 #endif
 
-#define print_ip(a)     printk("%d.%d.%d.%d",(ntohl(a)>>24)&0xFF,\
-                                             (ntohl(a)>>16)&0xFF,\
-                                             (ntohl(a)>>8)&0xFF,\
-                                             (ntohl(a))&0xFF);
+#define print_ip(a)     printk("%u.%u.%u.%u", NIPQUAD(a));
 
 #ifdef DEBUG_IP_FIREWALL
 #define dprint_ip(a)   print_ip(a)
index 4675a94b8b66e785720854533c804c73959e8bd7..395b1b301edad748897989c93d8ada27ad4248e3 100644 (file)
@@ -38,14 +38,7 @@ static void dump_packet(const struct ipt_log_info *info,
         * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
        /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
        printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ",
-              (ntohl(iph->saddr)>>24)&0xFF,
-              (ntohl(iph->saddr)>>16)&0xFF,
-              (ntohl(iph->saddr)>>8)&0xFF,
-              (ntohl(iph->saddr))&0xFF,
-              (ntohl(iph->daddr)>>24)&0xFF,
-              (ntohl(iph->daddr)>>16)&0xFF,
-              (ntohl(iph->daddr)>>8)&0xFF,
-              (ntohl(iph->daddr))&0xFF);
+              NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
 
        /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
        printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
@@ -210,11 +203,7 @@ static void dump_packet(const struct ipt_log_info *info,
                        break;
                case ICMP_REDIRECT:
                        /* Max length: 24 "GATEWAY=255.255.255.255 " */
-                       printk("GATEWAY=%u.%u.%u.%u ",
-                              (ntohl(icmph->un.gateway)>>24)&0xFF,
-                              (ntohl(icmph->un.gateway)>>16)&0xFF,
-                              (ntohl(icmph->un.gateway)>>8)&0xFF,
-                              (ntohl(icmph->un.gateway))&0xFF);
+                       printk("GATEWAY=%u.%u.%u.%u ", NIPQUAD(icmph->un.gateway));
                        /* Fall through */
                case ICMP_DEST_UNREACH:
                case ICMP_SOURCE_QUENCH:
index afab828fb009fbd9897d5e2757a323d34d2510b9..1e9fad9bf25f2bd87e5a70b45d2af61bf3486304 100644 (file)
@@ -616,9 +616,9 @@ restart:
 #if RT_CACHE_DEBUG >= 2
        if (rt->u.rt_next) {
                struct rtable * trt;
-               printk("rt_cache @%02x: %08x", hash, rt->rt_dst);
+               printk("rt_cache @%02x: %u.%u.%u.%u", hash, NIPQUAD(rt->rt_dst));
                for (trt=rt->u.rt_next; trt; trt=trt->u.rt_next)
-                       printk(" . %08x", trt->rt_dst);
+                       printk(" . %u.%u.%u.%u", NIPQUAD(trt->rt_dst));
                printk("\n");
        }
 #endif
@@ -816,10 +816,10 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
 reject_redirect:
 #ifdef CONFIG_IP_ROUTE_VERBOSE
        if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
-               printk(KERN_INFO "Redirect from %X/%s to %X ignored."
-                      "Path = %X -> %X, tos %02x\n",
-                      ntohl(old_gw), dev->name, ntohl(new_gw),
-                      ntohl(saddr), ntohl(daddr), tos);
+               printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about %u.%u.%u.%u ignored.\n"
+                      "  Advised path = %u.%u.%u.%u -> %u.%u.%u.%u, tos %02x\n",
+                      NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw),
+                      NIPQUAD(saddr), NIPQUAD(daddr), tos);
 #endif
        in_dev_put(in_dev);
 }
@@ -836,7 +836,8 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
                if ((rt->rt_flags&RTCF_REDIRECTED) || rt->u.dst.expires) {
                        unsigned hash = rt_hash_code(rt->key.dst, rt->key.src^(rt->key.oif<<5), rt->key.tos);
 #if RT_CACHE_DEBUG >= 1
-                       printk(KERN_DEBUG "ip_rt_advice: redirect to %d.%d.%d.%d/%02x dropped\n", NIPQUAD(rt->rt_dst), rt->key.tos);
+                       printk(KERN_DEBUG "ip_rt_advice: redirect to %u.%u.%u.%u/%02x dropped\n",
+                               NIPQUAD(rt->rt_dst), rt->key.tos);
 #endif
                        rt_del(hash, rt);
                        return NULL;
@@ -896,8 +897,10 @@ void ip_rt_send_redirect(struct sk_buff *skb)
 #ifdef CONFIG_IP_ROUTE_VERBOSE
                if (IN_DEV_LOG_MARTIANS(in_dev) &&
                    rt->u.dst.rate_tokens == ip_rt_redirect_number && net_ratelimit())
-                       printk(KERN_WARNING "host %08x/if%d ignores redirects for %08x to %08x.\n",
-                              rt->rt_src, rt->rt_iif, rt->rt_dst, rt->rt_gateway);
+                       printk(KERN_WARNING "host %u.%u.%u.%u/if%d ignores redirects for "
+                               "%u.%u.%u.%u to %u.%u.%u.%u.\n",
+                               NIPQUAD(rt->rt_src), rt->rt_iif,
+                               NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_gateway));
 #endif
        }
 out:
@@ -1061,8 +1064,9 @@ static void ipv4_link_failure(struct sk_buff *skb)
 
 static int ip_rt_bug(struct sk_buff *skb)
 {
-       printk(KERN_DEBUG "ip_rt_bug: %08x -> %08x, %s\n", skb->nh.iph->saddr,
-              skb->nh.iph->daddr, skb->dev ? skb->dev->name : "?");
+       printk(KERN_DEBUG "ip_rt_bug: %u.%u.%u.%u -> %u.%u.%u.%u, %s\n",
+               NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr),
+               skb->dev ? skb->dev->name : "?");
        kfree_skb(skb);
        return 0;
 }
@@ -1499,7 +1503,8 @@ no_route:
 martian_destination:
 #ifdef CONFIG_IP_ROUTE_VERBOSE
        if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
-               printk(KERN_WARNING "martian destination %08x from %08x, dev %s\n", daddr, saddr, dev->name);
+               printk(KERN_WARNING "martian destination %u.%u.%u.%u from %u.%u.%u.%u, dev %s\n",
+                       NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
 #endif
 e_inval:
        err = -EINVAL;
@@ -1513,16 +1518,20 @@ martian_source:
 #ifdef CONFIG_IP_ROUTE_VERBOSE
        if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) {
                /*
-                *      RFC1812 recommenadtion, if source is martian,
+                *      RFC1812 recommendation, if source is martian,
                 *      the only hint is MAC header.
                 */
-               printk(KERN_WARNING "martian source %08x for %08x, dev %s\n", saddr, daddr, dev->name);
+               printk(KERN_WARNING "martian source %u.%u.%u.%u from %u.%u.%u.%u, on dev %s\n",
+                       NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
                if (dev->hard_header_len) {
                        int i;
                        unsigned char *p = skb->mac.raw;
-                       printk(KERN_WARNING "ll header:");
-                       for (i=0; i<dev->hard_header_len; i++, p++)
-                               printk(" %02x", *p);
+                       printk(KERN_WARNING "ll header: ");
+                       for (i=0; i<dev->hard_header_len; i++, p++) {
+                               printk("%02x", *p);
+                               if(i<(dev->hard_header_len-1))
+                                       printk(":");
+                       }
                        printk("\n");
                }
        }
index 30f86cd97c74d96935f4ff2e888353172b9ca29a..df815a804006459a4f62c57d45a2eecf14742719 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp.c,v 1.167 2000/04/08 07:21:18 davem Exp $
+ * Version:    $Id: tcp.c,v 1.168 2000/04/13 01:13:06 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -583,9 +583,13 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                        answ = 0;
                else if (sk->urginline || !tp->urg_data ||
                         before(tp->urg_seq,tp->copied_seq) ||
-                        !before(tp->urg_seq,tp->rcv_nxt))
+                        !before(tp->urg_seq,tp->rcv_nxt)) {
                        answ = tp->rcv_nxt - tp->copied_seq;
-               else
+
+                       /* Subtract 1, if FIN is in queue. */
+                       if (answ && !skb_queue_empty(&sk->receive_queue))
+                               answ -= ((struct sk_buff*)sk->receive_queue.prev)->h.th->fin;
+               } else
                        answ = tp->urg_seq - tp->copied_seq;
                release_sock(sk);
                break;
index 3c9f4e82b4631056e781ecb720938fba728d1aa0..c0cd9416550fb3966ec58a2dcad27c43b42723c8 100644 (file)
@@ -1384,7 +1384,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
                    peer->v4daddr == saddr) {
                        if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
                            (s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW) {
-                               NETDEBUG(printk(KERN_DEBUG "TW_REC: reject openreq %u/%u %08x/%u\n", peer->tcp_ts, req->ts_recent, saddr, ntohs(skb->h.th->source)));
+                               NETDEBUG(printk(KERN_DEBUG "TW_REC: reject openreq %u/%u %u.%u.%u.%u/%u\n", \
+                                       peer->tcp_ts, req->ts_recent, NIPQUAD(saddr), ntohs(skb->h.th->source)));
                                NET_INC_STATS_BH(PAWSPassiveRejected);
                                dst_release(dst);
                                goto drop_and_free;
@@ -1402,7 +1403,9 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
                         * to destinations, already remembered
                         * to the moment of synflood.
                         */
-                       NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "TCP: drop open request from %08x/%u\n", saddr, ntohs(skb->h.th->source)));
+                       NETDEBUG(if (net_ratelimit()) \
+                               printk(KERN_DEBUG "TCP: drop open request from %u.%u.%u.%u/%u\n", \
+                                       NIPQUAD(saddr), ntohs(skb->h.th->source)));
                        TCP_INC_STATS_BH(TcpAttemptFails);
                        dst_release(dst);
                        goto drop_and_free;
index e463b33caa9917e859a6a9cbac1a04cf68a40d01..abf0bac9105e0ae8739770d41bf93954d6ab5b92 100644 (file)
@@ -512,7 +512,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
        opt=kmalloc(sizeof(struct tc_gred_qopt)*MAX_DPs, GFP_KERNEL);
 
        if (opt  == NULL) {
-               DPRINTK("gred_dump:failed to malloc for %d\n",
+               DPRINTK("gred_dump:failed to malloc for %Zd\n",
                    sizeof(struct tc_gred_qopt)*MAX_DPs);
                goto rtattr_failure;
        }
index 6afb28e887440e6fcf7d9b1b6d26a8399c20d4ff..026edcd708b89f795ac3aa50c60a91cc8565cf8e 100644 (file)
@@ -91,8 +91,8 @@ rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
        char            hostname[32];
        int             status;
 
-       dprintk("RPC:      rpc_getport_external(%s, %d, %d, %d)\n",
-                       in_ntoa(sin->sin_addr.s_addr), prog, vers, prot);
+       dprintk("RPC:      rpc_getport_external(%u.%u.%u.%u, %d, %d, %d)\n",
+                       NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
 
        strcpy(hostname, in_ntoa(sin->sin_addr.s_addr));
        if (!(pmap_clnt = pmap_create(hostname, sin, prot)))
index d99033fa5da37807c3e763790f841c0f4f6b1726..f646531200a847a3f1965d91602e2f6aefcc1dac 100644 (file)
@@ -544,14 +544,14 @@ svc_tcp_accept(struct svc_sock *svsk)
        if (ntohs(sin.sin_port) >= 1024) {
                if (net_ratelimit())
                        printk(KERN_WARNING
-                                  "%s: connect from unprivileged port: %s:%d",
+                                  "%s: connect from unprivileged port: %u.%u.%u.%u:%d",
                                   serv->sv_name, 
-                                  in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+                                  NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
                goto failed;
        }
 
-       dprintk("%s: connect from %s:%04x\n", serv->sv_name,
-                       in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+       dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name,
+                       NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
 
        if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0)))
                goto failed;
@@ -915,9 +915,9 @@ svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
        int             error;
        int             type;
 
-       dprintk("svc: svc_create_socket(%s, %d, %08x:%d)\n",
+       dprintk("svc: svc_create_socket(%s, %d, %u.%u.%u.%u:%d)\n",
                                serv->sv_program->pg_name, protocol,
-                               ntohl(sin->sin_addr.s_addr),
+                               NIPQUAD(sin->sin_addr.s_addr),
                                ntohs(sin->sin_port));
 
        if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
index e042ce1d8c10c154f7ba8c074554a89a62c8d613..a37830db1be6fb67939920dce2d6c66bd762582b 100644 (file)
@@ -17,6 +17,9 @@
  *     X.25 002        Jonathan Naylor Centralised disconnect handling.
  *                                     New timer architecture.
  *     2000-11-03      Henner Eisen    MSG_EOR handling more POSIX compliant.
+ *     2000-22-03      Daniela Squassoni Allowed disabling/enabling of 
+ *                                       facilities negotiation and increased 
+ *                                       the throughput upper limit.
  */
 
 #include <linux/config.h>
@@ -811,6 +814,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
        make->protinfo.x25->source_addr   = source_addr;
        make->protinfo.x25->neighbour     = neigh;
        make->protinfo.x25->facilities    = facilities;
+       make->protinfo.x25->vc_facil_mask = sk->protinfo.x25->vc_facil_mask;
 
        x25_write_internal(make, X25_CALL_ACCEPTED);
 
@@ -1133,7 +1137,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                                return -EINVAL;
                        if (facilities.winsize_in < 1 || facilities.winsize_in > 127)
                                return -EINVAL;
-                       if (facilities.throughput < 0x03 || facilities.throughput > 0x2C)
+                       if (facilities.throughput < 0x03 || facilities.throughput > 0xDD)
                                return -EINVAL;
                        if (facilities.reverse != 0 && facilities.reverse != 1)
                                return -EINVAL;
index 18de2da1a9c0ee3846b614e85271de08ed2b847e..ad41d1cde1ce6dc7c51ea4a50c9d4f3a450d842a 100644 (file)
@@ -14,6 +14,8 @@
  *
  *     History
  *     X.25 001        Split from x25_subr.c
+ *     mar/20/00       Daniela Squassoni Disabling/enabling of facilities 
+ *                                       negotiation.
  */
 
 #include <linux/config.h>
  *     Parse a set of facilities into the facilities structure. Unrecognised
  *     facilities are written to the debug log file.
  */
-int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities)
+int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, unsigned long *vc_fac_mask)
 {
        unsigned int len;
        unsigned char *p = skb->data;
 
        len = *p++;
+       *vc_fac_mask = 0;
 
        while (len > 0) {
                switch (*p & X25_FAC_CLASS_MASK) {
@@ -56,9 +59,11 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities)
                                switch (*p) {
                                        case X25_FAC_REVERSE:
                                                facilities->reverse = (p[1] & 0x01);
+                                               *vc_fac_mask |= X25_MASK_REVERSE;
                                                break;
                                        case X25_FAC_THROUGHPUT:
                                                facilities->throughput = p[1];
+                                               *vc_fac_mask |= X25_MASK_THROUGHPUT;
                                                break;
                                        default:
                                                printk(KERN_DEBUG "X.25: unknown facility %02X, value %02X\n", p[0], p[1]);
@@ -73,10 +78,12 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities)
                                        case X25_FAC_PACKET_SIZE:
                                                facilities->pacsize_in  = p[1];
                                                facilities->pacsize_out = p[2];
+                                               *vc_fac_mask |= X25_MASK_PACKET_SIZE;
                                                break;
                                        case X25_FAC_WINDOW_SIZE:
                                                facilities->winsize_in  = p[1];
                                                facilities->winsize_out = p[2];
+                                               *vc_fac_mask |= X25_MASK_WINDOW_SIZE;
                                                break;
                                        default:
                                                printk(KERN_DEBUG "X.25: unknown facility %02X, values %02X, %02X\n", p[0], p[1], p[2]);
@@ -106,28 +113,34 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities)
 /*
  *     Create a set of facilities.
  */
-int x25_create_facilities(unsigned char *buffer, struct x25_facilities *facilities)
+int x25_create_facilities(unsigned char *buffer, struct x25_facilities *facilities, unsigned long facil_mask)
 {
        unsigned char *p = buffer + 1;
        int len;
 
-       if (facilities->reverse != 0) {
+       if (facil_mask == 0) {
+               buffer [0] = 0; /* length of the facilities field in call_req or call_accept packets */
+               len = 1; /* 1 byte for the length field */
+               return len;
+       }
+
+       if ((facilities->reverse != 0) && (facil_mask & X25_MASK_REVERSE)) {
                *p++ = X25_FAC_REVERSE;
                *p++ = (facilities->reverse) ? 0x01 : 0x00;
        }
 
-       if (facilities->throughput != 0) {
+       if ((facilities->throughput != 0) && (facil_mask & X25_MASK_THROUGHPUT)) {
                *p++ = X25_FAC_THROUGHPUT;
                *p++ = facilities->throughput;
        }
 
-       if (facilities->pacsize_in != 0 || facilities->pacsize_out != 0) {
+       if ((facilities->pacsize_in != 0 || facilities->pacsize_out != 0) && (facil_mask & X25_MASK_PACKET_SIZE)) {
                *p++ = X25_FAC_PACKET_SIZE;
                *p++ = (facilities->pacsize_in  == 0) ? facilities->pacsize_out : facilities->pacsize_in;
                *p++ = (facilities->pacsize_out == 0) ? facilities->pacsize_in  : facilities->pacsize_out;
        }
 
-       if (facilities->winsize_in != 0 || facilities->winsize_out != 0) {
+       if ((facilities->winsize_in != 0 || facilities->winsize_out != 0) && (facil_mask & X25_MASK_WINDOW_SIZE)) {
                *p++ = X25_FAC_WINDOW_SIZE;
                *p++ = (facilities->winsize_in  == 0) ? facilities->winsize_out : facilities->winsize_in;
                *p++ = (facilities->winsize_out == 0) ? facilities->winsize_in  : facilities->winsize_out;
@@ -156,7 +169,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, struct x25_fa
 
        *new = *ours;
 
-       len = x25_parse_facilities(skb, &theirs);
+       len = x25_parse_facilities(skb, &theirs, &sk->protinfo.x25->vc_facil_mask);
 
        /*
         *      They want reverse charging, we won't accept it.
index a8a2905fe10f603242d05a9fe8de85d75e8b71ba..5110d327ab83b517f3b607616b9b2683bd74cc51 100644 (file)
  *             2 of the License, or (at your option) any later version.
  *
  *     History
- *     X.25 001        Jonathan Naylor Started coding.
- *     X.25 002        Jonathan Naylor Centralised disconnection code.
- *                                     New timer architecture.
+ *     X.25 001        Jonathan Naylor   Started coding.
+ *     X.25 002        Jonathan Naylor   Centralised disconnection code.
+ *                                       New timer architecture.
+ *     mar/20/00       Daniela Squassoni Disabling/enabling of facilities 
+ *                                       negotiation.
  */
 
 #include <linux/config.h>
@@ -111,7 +113,7 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp
                         */
                        skb_pull(skb, X25_STD_MIN_LEN);
                        skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
-                       skb_pull(skb, x25_parse_facilities(skb, &sk->protinfo.x25->facilities));
+                       skb_pull(skb, x25_parse_facilities(skb, &sk->protinfo.x25->facilities, &sk->protinfo.x25->vc_facil_mask));
                        /*
                         *      Copy any Call User Data.
                         */
index d33dc63c3cedf80e4da7fce7f4b1125a30bfa616..34d065b833b3c663f9eed8054fc8ae391aa341fe 100644 (file)
  *             2 of the License, or (at your option) any later version.
  *
  *     History
- *     X.25 001        Jonathan Naylor Started coding.
- *     X.25 002        Jonathan Naylor New timer architecture.
+ *     X.25 001        Jonathan Naylor   Started coding.
+ *     X.25 002        Jonathan Naylor   New timer architecture.
+ *     mar/20/00       Daniela Squassoni Disabling/enabling of facilities 
+ *                                       negotiation.
  */
 
 #include <linux/config.h>
@@ -293,6 +295,7 @@ void x25_link_device_up(struct net_device *dev)
        x25_neigh->dev      = dev;
        x25_neigh->state    = X25_LINK_STATE_0;
        x25_neigh->extended = 0;
+       x25_neigh->global_facil_mask = (X25_MASK_REVERSE | X25_MASK_THROUGHPUT | X25_MASK_PACKET_SIZE | X25_MASK_WINDOW_SIZE); /* enables negotiation */
        x25_neigh->t20      = sysctl_x25_restart_request_timeout;
 
        save_flags(flags); cli();
@@ -377,6 +380,8 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
        switch (cmd) {
 
                case SIOCX25GSUBSCRIP:
+                       if (copy_from_user(&x25_subscr, arg, sizeof(struct x25_subscrip_struct)))
+                               return -EFAULT;
                        if ((dev = x25_dev_get(x25_subscr.device)) == NULL)
                                return -EINVAL;
                        if ((x25_neigh = x25_get_neigh(dev)) == NULL) {
@@ -385,6 +390,7 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
                        }
                        dev_put(dev);
                        x25_subscr.extended = x25_neigh->extended;
+                       x25_subscr.global_facil_mask = x25_neigh->global_facil_mask;
                        if (copy_to_user(arg, &x25_subscr, sizeof(struct x25_subscrip_struct)))
                                return -EFAULT;
                        break;
@@ -402,6 +408,7 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
                        if (x25_subscr.extended != 0 && x25_subscr.extended != 1)
                                return -EINVAL;
                        x25_neigh->extended = x25_subscr.extended;
+                       x25_neigh->global_facil_mask = x25_subscr.global_facil_mask;
                        break;
 
                default:
index 8b055e40e0759452b8e964d37511de87cc4f9f48..25a700af937b87c34f8401eb413cf9bfb8dc347a 100644 (file)
  *             2 of the License, or (at your option) any later version.
  *
  *     History
- *     X.25 001        Jonathan Naylor Started coding.
- *     X.25 002        Jonathan Naylor Centralised disconnection processing.
+ *     X.25 001        Jonathan Naylor   Started coding.
+ *     X.25 002        Jonathan Naylor   Centralised disconnection processing.
+ *     mar/20/00       Daniela Squassoni Disabling/enabling of facilities 
+ *                                       negotiation.
  */
 
 #include <linux/config.h>
@@ -206,7 +208,7 @@ void x25_write_internal(struct sock *sk, int frametype)
                        len     = x25_addr_aton(addresses, &sk->protinfo.x25->dest_addr, &sk->protinfo.x25->source_addr);
                        dptr    = skb_put(skb, len);
                        memcpy(dptr, addresses, len);
-                       len     = x25_create_facilities(facilities, &sk->protinfo.x25->facilities);
+                       len     = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->neighbour->global_facil_mask);
                        dptr    = skb_put(skb, len);
                        memcpy(dptr, facilities, len);
                        dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength);
@@ -218,7 +220,7 @@ void x25_write_internal(struct sock *sk, int frametype)
                        dptr    = skb_put(skb, 2);
                        *dptr++ = X25_CALL_ACCEPTED;
                        *dptr++ = 0x00;         /* Address lengths */
-                       len     = x25_create_facilities(facilities, &sk->protinfo.x25->facilities);
+                       len     = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->vc_facil_mask);
                        dptr    = skb_put(skb, len);
                        memcpy(dptr, facilities, len);
                        dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength);