diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/CREDITS linux-2.4.28-pre3/CREDITS --- linux-2.4.27/CREDITS 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/CREDITS 2004-09-10 19:35:58.000000000 +0000 @@ -2130,14 +2130,13 @@ S: 7546 JA Enschede S: Netherlands N: David S. Miller -E: davem@redhat.com +E: davem@davemloft.net D: Sparc and blue box hacker D: Vger Linux mailing list co-maintainer D: Linux Emacs elf/qmagic support + other libc/gcc things D: Yee bore de yee bore! ;-) -S: 750 N. Shoreline Blvd. -S: Apt. #111 -S: Mountain View, California 94043 +S: 575 Harrison St. #103 +S: San Francisco, California 94105 S: USA N: Rick Miller diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/Configure.help linux-2.4.28-pre3/Documentation/Configure.help --- linux-2.4.27/Documentation/Configure.help 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/Documentation/Configure.help 2004-09-10 19:36:53.000000000 +0000 @@ -696,6 +696,24 @@ CONFIG_BLK_DEV_IDE could say N here, and select the "Old hard disk driver" below instead to save about 13 KB of memory in the kernel. +Support for SATA (deprecated; conflicts with libata SATA driver) +CONFIG_BLK_DEV_IDE_SATA + There are two drivers for Serial ATA controllers. + + The main driver, "libata", exists inside the SCSI subsystem + and supports most modern SATA controllers. + + The IDE driver (which you are currently configuring) supports + a few first-generation SATA controllers. + + In order to eliminate conflicts between the two subsystems, + this config option enables the IDE driver's SATA support. + Normally this is disabled, as it is preferred that libata + supports SATA controllers, and this (IDE) driver supports + PATA controllers. + + If unsure, say N. + Old hard disk (MFM/RLL/IDE) driver CONFIG_BLK_DEV_HD_ONLY There are two drivers for MFM/RLL/IDE hard disks. Most people use @@ -4678,12 +4696,6 @@ CONFIG_BINFMT_ELF ld.so (check the file for location and latest version). - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called binfmt_elf.o. Saying M or N here is dangerous because - some crucial programs on your system might be in ELF format. - Kernel support for a.out binaries CONFIG_BINFMT_AOUT A.out (Assembler.OUTput) is a set of formats for libraries and @@ -7953,7 +7965,7 @@ CONFIG_SCSI_LOGGING QDIO base support for IBM S/390 and zSeries CONFIG_QDIO This driver provides the Queued Direct I/O base support for the - IBM S/390 (G5 and G6) and eServer zSeries (z800 and z900). + IBM S/390 (G5 and G6) and eServer zSeries (z800, z900 and z990). For details please refer to the documentation provided by IBM at @@ -7971,6 +7983,37 @@ CONFIG_QDIO_PERF_STATS If unsure, say N. +IBM S/390 and zSeries OSA-Express and HiperSockets device driver +CONFIG_QETH + This driver supports the IBM S/390 and zSeries OSA Express adapters + in QDIO mode (all media types), HiperSockets interfaces and VM GuestLAN + interfaces in QDIO and HIPER mode. + + For details please refer to the documentation provided by IBM at + + + This driver is also available as a module (code which can be + inserted in and removed from the running kernel whenever you + want). If you want to compile it as a module, say 'M' here and + read file Documentation/modules.txt. + +IPv6 support for qeth +CONFIG_QETH_IPV6 + If CONFIG_QETH is switched on, this option will include IPv6 + support in the qeth device driver. + +IEEE 802.1q VLAN support for qeth +CONFIG_QETH_VLAN + If CONFIG_QETH is switched on, this option will include IEEE + 802.1q VLAN support in the qeth device driver. + +Performance statistics for the qeth drivers +CONFIG_QETH_PERF_STATS + When switched on, this option will add a file in the proc-fs + (/proc/qeth_perf_stats) containing performance statistics. It + may slightly impact performance, so this is only recommended for + internal tuning of the device driver. + SGI WD93C93 SCSI Driver CONFIG_SCSI_SGIWD93 Say Y here to support the on-board WD93C93 SCSI controller found (a) @@ -9281,6 +9324,16 @@ CONFIG_SCSI_SATA_SVW If unsure, say N. +CONFIG_SCSI_ATA_PIIX + This option enables support for ICH5 Serial ATA. + + If unsure, say N. + +CONFIG_SCSI_SATA_NV + This option enables support for NVIDIA Serial ATA. + + If unsure, say N. + CONFIG_SCSI_SATA_PROMISE This option enables support for Promise Serial ATA TX2/TX4. @@ -10077,6 +10130,49 @@ CONFIG_AIRONET4500_CS compile it as a module, say M here and read . +Intersil 802.11(a/b/g) Prism GT/Duette/Indigo support +CONFIG_PRISM54 + Enable PCI and Cardbus support for the following chipset based cards: + + ISL3880 - Prism GT 802.11 b/g + ISL3877 - Prism Indigo 802.11 a + ISL3890 - Prism Duette 802.11 a/b/g + + For a complete list of supported cards visit . + Here is the latest confirmed list of supported cards: + + 3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72 + Allnet ALL0271 PCI Card + Compex WL54G Cardbus Card + Corega CG-WLCB54GT Cardbus Card + D-Link Air Plus Xtreme G A1 Cardbus Card aka DWL-g650 + I-O Data WN-G54/CB Cardbus Card + Kobishi XG-300 aka Z-Com Cardbus Card + Netgear WG511 Cardbus Card + Ovislink WL-5400PCI PCI Card + Peabird WLG-PCI PCI Card + Sitecom WL-100i Cardbus Card + Sitecom WL-110i PCI Card + SMC2802W - EZ Connect g 2.4GHz 54 Mbps Wireless PCI Card + SMC2835W - EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Card + Z-Com XG-900 PCI Card + Zyxel G-100 Cardbus Card + + If you enable this, you require a firmware file as well. + You will need to copy this to /usr/lib/hotplug/firmware/isl3890. + You can get this non-GPL'd firmware file from the Prism54 project page: + . + You will also need the /etc/hotplug/firmware.agent script from + a current hotplug package. + + + Note: You need a motherboard with DMA support to use any of these cards + + If you want to compile the driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read . The module + will be called prism54.o. + Aironet 4500/4800 PROC interface CONFIG_AIRONET4500_PROC If you say Y here (and to the "/proc file system" below), you will @@ -17211,10 +17307,11 @@ CONFIG_NFSD_V3 If you would like to include the NFSv3 server as well as the NFSv2 server, say Y here. If unsure, say Y. -Provide NFS over TCP server support EXPERIMENTAL +Provide NFS over TCP server support CONFIG_NFSD_TCP - Enable NFS service over TCP connections. This the officially - still experimental, but seems to work well. + If you want your NFS server to support TCP connections, say Y here. + TCP connections usually perform better than the default UDP when + the network is lossy or congested. If unsure, say Y. OS/2 HPFS file system support CONFIG_HPFS_FS @@ -25344,13 +25441,13 @@ CONFIG_S390_PARTITION Support for DASD hard disks CONFIG_DASD Enable this option if you want to access DASDs directly utilizing - S/390s channel subsystem commands. This is necessary for running + S/390's or zSeries' channel subsystem commands. This is necessary for running natively on a single image or an LPAR. Support for ECKD hard disks CONFIG_DASD_ECKD ECKD (Extended Count Key Data) devices are the most commonly used - devices on S/390s. You should enable this option unless you are + devices on zSeries and S/390. You should enable this option unless you are very sure you have no ECKD device. ECKD demand loading @@ -28864,6 +28961,18 @@ CONFIG_CRYPTO_SHA512 This code also includes SHA-384, a 384 bit hash with 192 bits of security against collision attacks. +CONFIG_CRYPTO_WHIRLPOOL + Whirlpool hash algorithm. + + Whirlpool is part of the NESSIE cryptographic primtives. + Whirlpool works on messages shorter than 2^256 bits and + produces a 512 bit hash. + + Whirlpool will be part of the ISO/IEC 10118-3:2003(E) standard + + See also: + http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html + CONFIG_CRYPTO_DES DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). @@ -28932,7 +29041,7 @@ CONFIG_CRYPTO_TEA many rounds for security. It is very fast and uses little memory. - Xtendend Tiny Encryption Algorithm is a modifcation to + Xtendend Tiny Encryption Algorithm is a modification to the TEA algorithm to address a potential key weakness in the TEA algorithm. @@ -28944,6 +29053,16 @@ CONFIG_CRYPTO_ARC4 WEP, but it should not be for other purposes because of the weakness of the algorithm. +CONFIG_CRYPTO_KHAZAD + Khazad cipher algorithm. + + Khazad was a finalist in the initial NESSIE competition. It is + an algorithm optimized for 64-bit processors with good performance + on 32-bit processors. Khazad uses an 128 bit key size. + + See also: + http://planeta.terra.com.br/informatica/paulobarreto/KhazadPage.html + CONFIG_CRYPTO_DEFLATE This is the Deflate algorithm (RFC1951), specified for use in IPSec with the IPCOMP protocol (RFC3173, RFC2394). diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/crypto/api-intro.txt linux-2.4.28-pre3/Documentation/crypto/api-intro.txt --- linux-2.4.27/Documentation/crypto/api-intro.txt 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/Documentation/crypto/api-intro.txt 2004-09-10 19:37:20.000000000 +0000 @@ -219,6 +219,15 @@ AES algorithm contributors: CAST5/CAST6 algorithm contributors: Kartikey Mahendra Bhatt (original developers unknown, FSF copyright). +TEA/XTEA algorithm contributors: + Aaron Grothe + +Khazad algorithm contributors: + Aaron Grothe + +Whirlpool algorithm contributors: + Aaron Grothe + Generic scatterwalk code by Adam J. Richter Please send any credits updates or corrections to: diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/filesystems/xfs.txt linux-2.4.28-pre3/Documentation/filesystems/xfs.txt --- linux-2.4.27/Documentation/filesystems/xfs.txt 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/Documentation/filesystems/xfs.txt 2004-09-10 19:33:06.000000000 +0000 @@ -120,19 +120,19 @@ The following sysctls are available for fs.xfs.stats_clear (Min: 0 Default: 0 Max: 1) Setting this to "1" clears accumulated XFS statistics - in /proc/fs/xfs/stat. It then immediately reset to "0". + in /proc/fs/xfs/stat. It then immediately resets to "0". - fs.xfs.sync_interval (Min: HZ Default: 30*HZ Max: 60*HZ) + fs.xfs.xfssyncd_centisecs (Min: 100 Default: 3000 Max: 6000) The interval at which the xfssyncd thread flushes metadata out to disk. This thread will flush log activity out, and do some processing on unlinked inodes. - fs.xfs.age_buffer (Min: 1*HZ Default: 15*HZ Max: 300*HZ) - The age at which xfsbufd flushes dirty metadata buffers to disk. - - fs.xfs.flush_interval (Min: HZ/2 Default: HZ Max: 30*HZ) + fs.xfs.xfsbufd_centisecs (Min: 50 Default: 100 Max: 3000) The interval at which xfsbufd scans the dirty metadata buffers list. + fs.xfs.age_buffer_centisecs (Min: 100 Default: 1500 Max: 30000) + The age at which xfsbufd flushes dirty metadata buffers to disk. + fs.xfs.error_level (Min: 0 Default: 3 Max: 11) A volume knob for error reporting when internal errors occur. This will generate detailed messages & backtraces for filesystem diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/ftape.txt linux-2.4.28-pre3/Documentation/ftape.txt --- linux-2.4.27/Documentation/ftape.txt 1999-11-06 18:38:40.000000000 +0000 +++ linux-2.4.28-pre3/Documentation/ftape.txt 2004-09-10 19:32:23.000000000 +0000 @@ -15,7 +15,7 @@ as a feature or bug of zftape). ftape has a home page at -http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape +http://www.instmath.rwth-aachen.de/~heine/ftape/ which contains further information about ftape. Please cross check this WWW address against the address given (if any) in the MAINTAINERS @@ -58,7 +58,7 @@ changed. Up to date documentation as wel versions of ftape and useful links to related topics can be found at the ftape home page at -http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape +http://www.instmath.rwth-aachen.de/~heine/ftape/ ******************************************************************************* @@ -132,7 +132,7 @@ A. Changes or from the ftape home page at - http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape + http://www.instmath.rwth-aachen.de/~heine/ftape/ `ftformat' is contained in the `./contrib/' subdirectory of that separate ftape package. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/isdn/CREDITS linux-2.4.28-pre3/Documentation/isdn/CREDITS --- linux-2.4.27/Documentation/isdn/CREDITS 2000-02-15 19:40:42.000000000 +0000 +++ linux-2.4.28-pre3/Documentation/isdn/CREDITS 2004-09-10 19:32:41.000000000 +0000 @@ -37,7 +37,7 @@ Michael Knigge (knick@cove.han.de) Andreas Kool (akool@Kool.f.EUnet.de) For contribution of the isdnlog/isdnrep-tool -Pedro Roque Marques (roque@di.fc.ul.pt) +Pedro Roque Marques (pedro_m@yahoo.com) For lot of new ideas and the pcbit driver. Eberhard Moenkeberg (emoenke@gwdg.de) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/isdn/README.pcbit linux-2.4.28-pre3/Documentation/isdn/README.pcbit --- linux-2.4.27/Documentation/isdn/README.pcbit 1999-11-08 00:34:00.000000000 +0000 +++ linux-2.4.28-pre3/Documentation/isdn/README.pcbit 2004-09-10 19:36:31.000000000 +0000 @@ -37,4 +37,4 @@ mailing list (isdn4linux@listserv.isdn4l regards, Pedro. - + diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/MAINTAINERS linux-2.4.28-pre3/MAINTAINERS --- linux-2.4.27/MAINTAINERS 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/MAINTAINERS 2004-09-10 19:35:28.000000000 +0000 @@ -177,10 +177,8 @@ S: Maintained AD1816 SOUND DRIVER P: Thorsten Knabe -M: Thorsten Knabe -M: Thorsten Knabe -W: http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html -W: http://www.tu-darmstadt.de/~tek01/projects/linux.html +M: Thorsten Knabe +W: http://linux.thorsten-knabe.de S: Maintained ADVANSYS SCSI DRIVER @@ -456,14 +454,20 @@ L: omnibook@zurich.ai.mit.edu S: Maintained +HP 66Mhz FIBRE CHANNEL DRIVER +P: Chirag Kantharia +M: chirag.kantharia@hp.com +L: iss_storagedev@hp.com +S: Maintained + HP SMART2 RAID DRIVER -P: Francis Wiran -M: francis.wiran@hp.com +P: Chirag Kantharia +M: chirag.kantharia@hp.com L: iss_storagedev@hp.com -S: Odd Fixes +S: Maintained -HP SMART CISS RAID DRIVER -P: Mike Miller, Michael Ni +HP SMART ARRAY CISS RAID DRIVER (cciss) +P: Mike Miller M: mike.miller@hp.com L: iss_storagedev@hp.com S: Supported @@ -530,15 +534,7 @@ CRYPTO API P: James Morris M: jmorris@intercode.com.au P: David S. Miller -M: davem@redhat.com -MARVELL YUKON / SYSKONNECT DRIVER -P: Mirko Lindner -M: mlindner@syskonnect.de -P: Ralph Roesler -M: rroesler@syskonnect.de -W: http://www.syskonnect.com -S: Supported -M: davem@redhat.com +M: davem@davemloft.net W http://samba.org/~jamesm/crypto/ L: linux-kernel@vger.kernel.org S: Maintained @@ -1188,6 +1184,14 @@ L: linux-mips@linux-mips.org L: netdev@oss.sgi.com S: Supported +MARVELL YUKON / SYSKONNECT DRIVER +P: Mirko Lindner +M: mlindner@syskonnect.de +P: Ralph Roesler +M: rroesler@syskonnect.de +W: http://www.syskonnect.com +S: Supported + MATROX FRAMEBUFFER DRIVER P: Petr Vandrovec M: vandrove@vc.cvut.cz @@ -1312,7 +1316,7 @@ S: Maintained NETWORKING [IPv4/IPv6] P: David S. Miller -M: davem@redhat.com +M: davem@davemloft.net P: Alexey Kuznetsov M: kuznet@ms2.inr.ac.ru P: Pekka Savola (ipv6) @@ -1448,9 +1452,8 @@ L: linux-kernel@vger.kernel.org S: Odd Fixes PCI HOTPLUG CORE -P: Greg Kroah-Hartman -M: greg@kroah.com -M: gregkh@us.ibm.com +P: Gary Hade +M: garyhade@us.ibm.com S: Supported PCI HOTPLUG COMPAQ DRIVER @@ -1723,7 +1726,7 @@ S: Maintained UltraSPARC (sparc64): P: David S. Miller -M: davem@redhat.com +M: davem@davemloft.net P: Eddie C. Dost M: ecd@skynet.be P: Jakub Jelinek @@ -1735,8 +1738,8 @@ L: ultralinux@vger.kernel.org S: Maintained SPARC (sparc32): -P: Keith M. Wesolowski -M: wesolows@foobazco.org +P: William L. Irwin +M: wli@holomorphy.com L: sparclinux@vger.kernel.org S: Maintained diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Makefile linux-2.4.28-pre3/Makefile --- linux-2.4.27/Makefile 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/Makefile 2004-09-10 19:35:43.000000000 +0000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 -SUBLEVEL = 27 -EXTRAVERSION = +SUBLEVEL = 28 +EXTRAVERSION = -pre3 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/alpha/config.in linux-2.4.28-pre3/arch/alpha/config.in --- linux-2.4.27/arch/alpha/config.in 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/alpha/config.in 2004-09-10 19:33:17.000000000 +0000 @@ -314,7 +314,7 @@ if [ "$CONFIG_BINFMT_AOUT" != "n" ]; the bool ' OSF/1 v4 readv/writev compatibility' CONFIG_OSF4_COMPAT fi -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86 source drivers/parport/Config.in diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/arm/config.in linux-2.4.28-pre3/arch/arm/config.in --- linux-2.4.27/arch/arm/config.in 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/arm/config.in 2004-09-10 19:33:04.000000000 +0000 @@ -498,7 +498,7 @@ choice 'Kernel core (/proc/kcore) format "ELF CONFIG_KCORE_ELF \ A.OUT CONFIG_KCORE_AOUT" ELF tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL dep_tristate 'RISC OS personality' CONFIG_ARTHUR $CONFIG_CPU_32 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/cris/config.in linux-2.4.28-pre3/arch/cris/config.in --- linux-2.4.27/arch/cris/config.in 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/cris/config.in 2004-09-10 19:35:17.000000000 +0000 @@ -30,7 +30,7 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF string 'Kernel command line' CONFIG_ETRAX_CMDLINE "root=/dev/mtdblock3" diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/Makefile linux-2.4.28-pre3/arch/i386/Makefile --- linux-2.4.27/arch/i386/Makefile 2003-06-13 14:51:29.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/Makefile 2004-09-10 19:34:00.000000000 +0000 @@ -94,6 +94,10 @@ ifdef CONFIG_MVIAC3_2 CFLAGS += $(call check_gcc,-march=c3-2,-march=i686) endif +# Disable unit-at-a-time mode, it makes gcc use a lot more stack +# due to the lack of sharing of stacklots. +CFLAGS += $(call check_gcc,-fno-unit-at-a-time,) + HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o SUBDIRS += arch/i386/kernel arch/i386/mm arch/i386/lib diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/boot/compressed/misc.c linux-2.4.28-pre3/arch/i386/boot/compressed/misc.c --- linux-2.4.27/arch/i386/boot/compressed/misc.c 2003-08-25 11:44:39.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/boot/compressed/misc.c 2004-09-10 19:35:24.000000000 +0000 @@ -104,7 +104,7 @@ static unsigned long output_ptr = 0; static void *malloc(int size); static void free(void *where); -static void puts(const char *); +static void putstr(const char *); extern int end; static long free_mem_ptr = (long)&end; @@ -165,7 +165,7 @@ static void scroll(void) vidmem[i] = ' '; } -static void puts(const char *s) +static void putstr(const char *s) { int x,y,pos; char c; @@ -283,9 +283,9 @@ static void flush_window(void) static void error(char *x) { - puts("\n\n"); - puts(x); - puts("\n\n -- System halted"); + putstr("\n\n"); + putstr(x); + putstr("\n\n -- System halted"); while(1); /* Halt */ } @@ -369,9 +369,9 @@ asmlinkage int decompress_kernel(struct else setup_output_buffer_if_we_run_high(mv); makecrc(); - puts("Uncompressing Linux... "); + putstr("Uncompressing Linux... "); gunzip(); - puts("Ok, booting the kernel.\n"); + putstr("Ok, booting the kernel.\n"); if (high_loaded) close_output_buffer_if_we_run_high(mv); return high_loaded; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/config.in linux-2.4.28-pre3/arch/i386/config.in --- linux-2.4.27/arch/i386/config.in 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/config.in 2004-09-10 19:33:44.000000000 +0000 @@ -326,7 +326,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then A.OUT CONFIG_KCORE_AOUT" ELF fi tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/defconfig linux-2.4.28-pre3/arch/i386/defconfig --- linux-2.4.27/arch/i386/defconfig 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/defconfig 2004-09-10 19:32:41.000000000 +0000 @@ -758,7 +758,7 @@ CONFIG_NFS_FS=y # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD_TCP=y CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/dmi_scan.c linux-2.4.28-pre3/arch/i386/kernel/dmi_scan.c --- linux-2.4.27/arch/i386/kernel/dmi_scan.c 2004-04-14 13:05:25.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/kernel/dmi_scan.c 2004-09-10 19:34:06.000000000 +0000 @@ -459,6 +459,22 @@ static __init int fix_broken_hp_bios_irq } /* + * Work around broken Acer TravelMate 360 Notebooks which assign Cardbus to + * IRQ 11 even though it is actually wired to IRQ 10 + */ +static __init int fix_acer_tm360_irqrouting(struct dmi_blacklist *d) +{ +#ifdef CONFIG_PCI + extern int acer_tm360_irqrouting; + if (acer_tm360_irqrouting == 0) { + acer_tm360_irqrouting = 1; + printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident); + } +#endif + return 0; +} + +/* * Exploding PnPBIOS. Don't yet know if its the BIOS or us for * some entries */ @@ -820,6 +836,12 @@ static __initdata struct dmi_blacklist d MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736") } }, + { fix_acer_tm360_irqrouting, "Acer TravelMate 36x Laptop", { + MATCH(DMI_SYS_VENDOR, "Acer"), + MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), + NO_MATCH, NO_MATCH + } }, + /* * Generic per vendor APM settings */ @@ -935,6 +957,13 @@ static __initdata struct dmi_blacklist d /* newer BIOS, Revision 1011, does work */ MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"), NO_MATCH }}, + + { disable_acpi_pci, "Acer TravelMate 36x Laptop", { + MATCH(DMI_SYS_VENDOR, "Acer"), + MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), + NO_MATCH, NO_MATCH + } }, + #endif /* CONFIG_ACPI_PCI */ { NULL, } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/io_apic.c linux-2.4.28-pre3/arch/i386/kernel/io_apic.c --- linux-2.4.27/arch/i386/kernel/io_apic.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/kernel/io_apic.c 2004-09-10 19:33:48.000000000 +0000 @@ -1349,7 +1349,7 @@ static void mask_and_ack_level_ioapic_ir #ifndef CONFIG_SMP -void send_IPI_self(int vector) +void fastcall send_IPI_self(int vector) { unsigned int cfg; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/pci-irq.c linux-2.4.28-pre3/arch/i386/kernel/pci-irq.c --- linux-2.4.27/arch/i386/kernel/pci-irq.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/kernel/pci-irq.c 2004-09-10 19:37:18.000000000 +0000 @@ -23,6 +23,7 @@ #define PIRQ_VERSION 0x0100 int broken_hp_bios_irq9; +int acer_tm360_irqrouting; static struct irq_routing_table *pirq_table; @@ -894,6 +895,14 @@ static int pcibios_lookup_irq(struct pci r->set(pirq_router_dev, dev, pirq, 11); } + /* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */ + if (acer_tm360_irqrouting && dev->irq == 11 && dev->vendor == PCI_VENDOR_ID_O2) { + pirq = 0x68; + mask = 0x400; + dev->irq = r->get(pirq_router_dev, dev, pirq); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } + /* * Find the best IRQ to assign: use the one * reported by the device if possible. @@ -1103,10 +1112,6 @@ void pcibios_enable_irq(struct pci_dev * } dev = temp_dev; if (irq >= 0) { -#ifdef CONFIG_PCI_USE_VECTOR - if (!platform_legacy_irq(irq)) - irq = IO_APIC_VECTOR(irq); -#endif printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n", dev->bus->number, PCI_SLOT(dev->devfn), pin, irq); dev->irq = irq; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/pci-pc.c linux-2.4.28-pre3/arch/i386/kernel/pci-pc.c --- linux-2.4.27/arch/i386/kernel/pci-pc.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/kernel/pci-pc.c 2004-09-10 19:34:17.000000000 +0000 @@ -177,6 +177,7 @@ static struct pci_ops pci_direct_mq_conf }; #endif /* !CONFIG_MULTIQUAD */ +#undef PCI_CONF1_ADDRESS #define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \ (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) @@ -1017,11 +1018,13 @@ struct irq_routing_table * __devinit pci "1:" : "=a" (ret), "=b" (map), - "+m" (opt) + "=m" (opt) : "0" (PCIBIOS_GET_ROUTING_OPTIONS), "1" (0), "D" ((long) &opt), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "m" (opt) + : "memory"); DBG("OK ret=%d, size=%d, map=%x\n", ret, opt.size, map); if (ret & 0xff00) printk(KERN_ERR "PCI: Error %02x when fetching IRQ routing table.\n", (ret >> 8) & 0xff); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/process.c linux-2.4.28-pre3/arch/i386/kernel/process.c --- linux-2.4.27/arch/i386/kernel/process.c 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/kernel/process.c 2004-09-10 19:31:49.000000000 +0000 @@ -644,7 +644,7 @@ void dump_thread(struct pt_regs * regs, * More important, however, is the fact that this allows us much * more flexibility. */ -void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) +void fastcall __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/signal.c linux-2.4.28-pre3/arch/i386/kernel/signal.c --- linux-2.4.27/arch/i386/kernel/signal.c 2002-08-03 00:39:42.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/kernel/signal.c 2004-09-10 19:34:37.000000000 +0000 @@ -581,7 +581,7 @@ handle_signal(unsigned long sig, struct * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -int do_signal(struct pt_regs *regs, sigset_t *oldset) +int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset) { siginfo_t info; struct k_sigaction *ka; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/smp.c linux-2.4.28-pre3/arch/i386/kernel/smp.c --- linux-2.4.27/arch/i386/kernel/smp.c 2003-06-13 14:51:29.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/kernel/smp.c 2004-09-10 19:32:31.000000000 +0000 @@ -150,7 +150,7 @@ static inline void __send_IPI_shortcut(u apic_write_around(APIC_ICR, cfg); } -void send_IPI_self(int vector) +void fastcall send_IPI_self(int vector) { __send_IPI_shortcut(APIC_DEST_SELF, vector); } @@ -497,7 +497,7 @@ void flush_tlb_all(void) * anything. Worst case is that we lose a reschedule ... */ -void smp_send_reschedule(int cpu) +void fastcall smp_send_reschedule(int cpu) { send_IPI_mask(1 << cpu, RESCHEDULE_VECTOR); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/vm86.c linux-2.4.28-pre3/arch/i386/kernel/vm86.c --- linux-2.4.27/arch/i386/kernel/vm86.c 2003-08-25 11:44:39.000000000 +0000 +++ linux-2.4.28-pre3/arch/i386/kernel/vm86.c 2004-09-10 19:32:38.000000000 +0000 @@ -91,7 +91,7 @@ #define VM86_REGS_SIZE2 (sizeof(struct kernel_vm86_regs) - VM86_REGS_SIZE1) struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs)); -struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs) +struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs) { struct tss_struct *tss; struct pt_regs *ret; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/ia64/config.in linux-2.4.28-pre3/arch/ia64/config.in --- linux-2.4.27/arch/ia64/config.in 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/ia64/config.in 2004-09-10 19:37:29.000000000 +0000 @@ -123,7 +123,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/ia64/defconfig linux-2.4.28-pre3/arch/ia64/defconfig --- linux-2.4.27/arch/ia64/defconfig 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/ia64/defconfig 2004-09-10 19:32:31.000000000 +0000 @@ -755,7 +755,7 @@ CONFIG_NFS_V3=y # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD_TCP=y CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/m68k/config.in linux-2.4.28-pre3/arch/m68k/config.in --- linux-2.4.27/arch/m68k/config.in 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/m68k/config.in 2004-09-10 19:36:05.000000000 +0000 @@ -98,7 +98,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then A.OUT CONFIG_KCORE_AOUT" ELF fi tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC if [ "$CONFIG_AMIGA" = "y" ]; then diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/mips/config-shared.in linux-2.4.28-pre3/arch/mips/config-shared.in --- linux-2.4.27/arch/mips/config-shared.in 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/mips/config-shared.in 2004-09-10 19:35:04.000000000 +0000 @@ -943,7 +943,7 @@ bool 'Sysctl support' CONFIG_SYSCTL define_bool CONFIG_KCORE_ELF y define_bool CONFIG_KCORE_AOUT n define_bool CONFIG_BINFMT_AOUT n -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF dep_bool 'Kernel support for Linux/MIPS 32-bit binary compatibility' CONFIG_MIPS32_COMPAT $CONFIG_MIPS64 dep_bool 'Kernel support for o32 binaries' CONFIG_MIPS32_O32 $CONFIG_MIPS32_COMPAT dep_bool 'Kernel support for n32 binaries' CONFIG_MIPS32_N32 $CONFIG_MIPS32_COMPAT diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/mips/defconfig linux-2.4.28-pre3/arch/mips/defconfig --- linux-2.4.27/arch/mips/defconfig 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/mips/defconfig 2004-09-10 19:32:45.000000000 +0000 @@ -607,7 +607,7 @@ CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD_TCP=y CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/mips64/defconfig linux-2.4.28-pre3/arch/mips64/defconfig --- linux-2.4.27/arch/mips64/defconfig 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/mips64/defconfig 2004-09-10 19:33:10.000000000 +0000 @@ -563,7 +563,7 @@ CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD_TCP=y CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/parisc/config.in linux-2.4.28-pre3/arch/parisc/config.in --- linux-2.4.27/arch/parisc/config.in 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/parisc/config.in 2004-09-10 19:37:18.000000000 +0000 @@ -88,7 +88,7 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL define_bool CONFIG_KCORE_ELF y -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for SOM binaries' CONFIG_BINFMT_SOM tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/ppc/defconfig linux-2.4.28-pre3/arch/ppc/defconfig --- linux-2.4.27/arch/ppc/defconfig 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/ppc/defconfig 2004-09-10 19:36:28.000000000 +0000 @@ -812,7 +812,7 @@ CONFIG_NFS_FS=y # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD_TCP=y CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/ppc/kernel/ppc_htab.c linux-2.4.28-pre3/arch/ppc/kernel/ppc_htab.c --- linux-2.4.27/arch/ppc/kernel/ppc_htab.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/ppc/kernel/ppc_htab.c 2004-09-10 19:32:19.000000000 +0000 @@ -489,7 +489,7 @@ int proc_dol2crvec(ctl_table *table, int if (!isspace(c)) break; left--; - ((char *) buffer)++; + buffer++; } if (!left) break; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/ppc64/defconfig linux-2.4.28-pre3/arch/ppc64/defconfig --- linux-2.4.27/arch/ppc64/defconfig 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/ppc64/defconfig 2004-09-10 19:34:39.000000000 +0000 @@ -668,7 +668,7 @@ CONFIG_NFS_V3=y # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD_TCP=y CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/config.in linux-2.4.28-pre3/arch/s390/config.in --- linux-2.4.27/arch/s390/config.in 2003-11-28 18:26:19.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390/config.in 2004-09-10 19:36:19.000000000 +0000 @@ -57,7 +57,7 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL define_bool CONFIG_KCORE_ELF y -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC bool 'Show crashed user process info' CONFIG_PROCESS_DEBUG bool 'Pseudo page fault support' CONFIG_PFAULT diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/defconfig linux-2.4.28-pre3/arch/s390/defconfig --- linux-2.4.27/arch/s390/defconfig 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390/defconfig 2004-09-10 19:36:34.000000000 +0000 @@ -129,6 +129,14 @@ CONFIG_FDDI=y # CONFIG_CHANDEV=y CONFIG_HOTPLUG=y +CONFIG_QETH=m + +# +# Gigabit Ethernet default settings +# +CONFIG_QETH_IPV6=y +CONFIG_QETH_VLAN=y +# CONFIG_QETH_PERF_STATS is not set CONFIG_CTC=m CONFIG_IUCV=m @@ -242,7 +250,6 @@ CONFIG_IP6_NF_TARGET_MARK=m # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=m # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set CONFIG_VLAN_8021Q=m @@ -351,7 +358,7 @@ CONFIG_NFS_V3=y # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD_TCP=y CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/kernel/entry.S linux-2.4.28-pre3/arch/s390/kernel/entry.S --- linux-2.4.27/arch/s390/kernel/entry.S 2003-06-13 14:51:32.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390/kernel/entry.S 2004-09-10 19:32:58.000000000 +0000 @@ -690,7 +690,12 @@ pgm_tracesys: io_int_handler: SAVE_ALL_BASE SAVE_ALL __LC_IO_OLD_PSW,0 + mc 0,0 GET_CURRENT # load pointer to task_struct to R9 + stck __LC_INT_CLOCK + clc __LC_INT_CLOCK(8),__LC_JIFFY_TIMER + bhe BASED(io_handle_tick) +io_call_handler: l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ la %r2,SP_PTREGS(%r15) # address of register-save area sr %r3,%r3 @@ -725,6 +730,15 @@ io_leave: RESTORE_ALL 0 # +# account tick +# +io_handle_tick: + l %r1,BASED(.Laccount_ticks) + la %r2,SP_PTREGS(%r15) # address of register-save area + la %r14,BASED(io_call_handler) + br %r1 + +# # call do_softirq # io_handle_bottom_half: @@ -758,8 +772,13 @@ io_signal_return: ext_int_handler: SAVE_ALL_BASE SAVE_ALL __LC_EXT_OLD_PSW,0 - GET_CURRENT # load pointer to task_struct to R9 + mc 0, 0 + GET_CURRENT # load pointer to task_struct to R9 lh %r6,__LC_EXT_INT_CODE # get interruption code + stck __LC_INT_CLOCK + clc __LC_INT_CLOCK(8),__LC_JIFFY_TIMER + bhe BASED(ext_handle_tick) +ext_call_handler: lr %r1,%r6 # calculate index = code & 0xff n %r1,BASED(.Lc0xff) sll %r1,2 @@ -770,7 +789,8 @@ ext_int_handler: ext_int_loop: ch %r6,8(%r7) # compare external interrupt code bne BASED(ext_int_next) - l %r1,4(%r7) # get handler address + icm %r1,15,4(%r7) # get handler address + bz BASED(ext_int_next) la %r2,SP_PTREGS(%r15) # address of register-save area lr %r3,%r6 # interruption code basr %r14,%r1 # call handler @@ -779,6 +799,15 @@ ext_int_next: bnz BASED(ext_int_loop) b BASED(io_return) +# +# account tick +# +ext_handle_tick: + l %r1,BASED(.Laccount_ticks) + la %r2,SP_PTREGS(%r15) # address of register-save area + la %r14,BASED(ext_call_handler) + br %r1 + /* * Machine check handler routines */ @@ -787,6 +816,7 @@ ext_int_next: mcck_int_handler: SAVE_ALL_BASE SAVE_ALL __LC_MCK_OLD_PSW,0 + mc 0, 0 l %r1,BASED(.Ls390_mcck) basr %r14,%r1 # call machine check handler mcck_return: @@ -869,4 +899,4 @@ restart_go: .Lvfork: .long sys_vfork .Lschedtail: .long schedule_tail - +.Laccount_ticks:.long account_ticks diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/kernel/s390_ksyms.c linux-2.4.28-pre3/arch/s390/kernel/s390_ksyms.c --- linux-2.4.27/arch/s390/kernel/s390_ksyms.c 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390/kernel/s390_ksyms.c 2004-09-10 19:35:32.000000000 +0000 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -66,3 +67,7 @@ EXPORT_SYMBOL(pfix_get_page_addr); EXPORT_SYMBOL(get_storage_key); EXPORT_SYMBOL_NOVERS(do_call_softirq); EXPORT_SYMBOL(sys_wait4); +EXPORT_SYMBOL(smp_call_function_on); +EXPORT_SYMBOL(show_trace); +EXPORT_SYMBOL(cpcmd); + diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/kernel/smp.c linux-2.4.28-pre3/arch/s390/kernel/smp.c --- linux-2.4.27/arch/s390/kernel/smp.c 2002-11-28 23:53:11.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390/kernel/smp.c 2004-09-10 19:31:55.000000000 +0000 @@ -92,7 +92,7 @@ extern char vmpoff_cmd[]; extern void reipl(unsigned long devno); -static sigp_ccode smp_ext_bitcall(int, ec_bit_sig); +static void smp_ext_bitcall(int, ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig); /* @@ -131,7 +131,7 @@ static void do_call_function(void) * in the system. */ -int smp_call_function (void (*func) (void *info), void *info, int nonatomic, +int smp_call_function(void (*func) (void *info), void *info, int nonatomic, int wait) /* * [SUMMARY] Run a function on all other CPUs. @@ -162,7 +162,7 @@ int smp_call_function (void (*func) (voi spin_lock_bh(&call_lock); call_data = &data; /* Send a message to all other CPUs and wait for them to respond */ - smp_ext_bitcall_others(ec_call_function); + smp_ext_bitcall_others(ec_call_function); /* Wait for response */ while (atomic_read(&data.started) != cpus) @@ -176,9 +176,54 @@ int smp_call_function (void (*func) (voi return 0; } +/* + * Call a function on one CPU + * cpu : the CPU the function should be executed on + * + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler, you may call it from a bottom half handler. + */ +int smp_call_function_on(void (*func) (void *info), void *info, + int nonatomic, int wait, int cpu) +{ + struct call_data_struct data; + + if (!atomic_read(&smp_commenced)) + return 0; + + if (smp_processor_id() == cpu) { + /* direct call to function */ + func(info); + return 0; + } + + data.func = func; + data.info = info; + + atomic_set(&data.started, 0); + data.wait = wait; + if (wait) + atomic_set(&data.finished, 0); + + spin_lock_bh(&call_lock); + call_data = &data; + smp_ext_bitcall(cpu, ec_call_function); + + /* Wait for response */ + while (atomic_read(&data.started) != 1) + barrier(); + + if (wait) + while (atomic_read(&data.finished) != 1) + barrier(); + + spin_unlock_bh(&call_lock); + return 0; +} + static inline void do_send_stop(void) { - u32 dummy; + unsigned long dummy; int i; /* stop all processors */ @@ -199,7 +244,7 @@ static inline void do_send_stop(void) static inline void do_store_status(void) { unsigned long low_core_addr; - u32 dummy; + unsigned long dummy; int i; /* store status of all processors in their lowcores (real 0) */ @@ -328,42 +373,41 @@ void do_ext_call_interrupt(struct pt_reg } /* - * Send an external call sigp to another cpu and return without waiting + * Send an external call sigp to another cpu and wait * for its completion. */ -static sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig) +static void smp_ext_bitcall(int cpu, ec_bit_sig sig) { - struct _lowcore *lowcore = get_cpu_lowcore(cpu); - sigp_ccode ccode; + struct _lowcore *lowcore = get_cpu_lowcore(cpu); - /* - * Set signaling bit in lowcore of target cpu and kick it - */ - atomic_set_mask(1<ext_call_fast); - ccode = signal_processor(cpu, sigp_external_call); - return ccode; + /* + * Set signaling bit in lowcore of target cpu and kick it + */ + atomic_set_mask(1<ext_call_fast); + while(signal_processor(cpu, sigp_external_call) == sigp_busy) + udelay(10); } /* * Send an external call sigp to every other cpu in the system and - * return without waiting for its completion. + * wait for its completion. */ static void smp_ext_bitcall_others(ec_bit_sig sig) { - struct _lowcore *lowcore; - int i; + struct _lowcore *lowcore; + int i; - for (i = 0; i < smp_num_cpus; i++) { - if (smp_processor_id() == i) - continue; - lowcore = get_cpu_lowcore(i); - /* - * Set signaling bit in lowcore of target cpu and kick it - */ - atomic_set_mask(1<ext_call_fast); - while (signal_processor(i, sigp_external_call) == sigp_busy) + for (i = 0; i < smp_num_cpus; i++) { + if (smp_processor_id() == i) + continue; + lowcore = get_cpu_lowcore(i); + /* + * Set signaling bit in lowcore of target cpu and kick it + */ + atomic_set_mask(1<ext_call_fast); + while (signal_processor(i, sigp_external_call) == sigp_busy) udelay(10); - } + } } /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/kernel/time.c linux-2.4.28-pre3/arch/s390/kernel/time.c --- linux-2.4.27/arch/s390/kernel/time.c 2003-06-13 14:51:32.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390/kernel/time.c 2004-09-10 19:31:59.000000000 +0000 @@ -34,13 +34,20 @@ #include /* change this if you have some constant time drift */ -#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ) #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12) +/* + * Create a small time difference between the timer interrupts + * on the different cpus to avoid lock contention. + */ +#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ) +#define CPU_DEVIATION (smp_processor_id() << 12) + #define TICK_SIZE tick static ext_int_info_t ext_int_info_timer; -static uint64_t init_timer_cc; +static u64 init_timer_cc; +static u64 xtime_cc; extern rwlock_t xtime_lock; extern unsigned long wall_jiffies; @@ -83,7 +90,7 @@ static inline unsigned long do_gettimeof { __u64 now; - asm ("STCK 0(%0)" : : "a" (&now) : "memory", "cc"); + asm volatile ("STCK 0(%0)" : : "a" (&now) : "memory", "cc"); now = (now - init_timer_cc) >> 12; /* We require the offset from the latest update of xtime */ now -= (__u64) wall_jiffies*USECS_PER_JIFFY; @@ -137,41 +144,72 @@ void do_settimeofday(struct timeval *tv) write_unlock_irq(&xtime_lock); } +static inline __u32 div64_32(__u64 dividend, __u32 divisor) +{ + register_pair rp; + + rp.pair = dividend; + asm ("dr %0,%1" : "+d" (rp) : "d" (divisor)); + return rp.subreg.odd; +} + /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ - -#ifdef CONFIG_SMP -extern __u16 boot_cpu_addr; -#endif - -static void do_comparator_interrupt(struct pt_regs *regs, __u16 error_code) +void account_ticks(struct pt_regs *regs) { int cpu = smp_processor_id(); + __u64 tmp; + __u32 ticks; + + /* Calculate how many ticks have passed. */ + tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer; + if (tmp >= 2*CLK_TICKS_PER_JIFFY) { + ticks = div64_32(tmp >> 1, CLK_TICKS_PER_JIFFY >> 1) + 1; + S390_lowcore.jiffy_timer += + CLK_TICKS_PER_JIFFY * (__u64) ticks; + } else if (tmp > CLK_TICKS_PER_JIFFY) { + ticks = 2; + S390_lowcore.jiffy_timer += 2*CLK_TICKS_PER_JIFFY; + } else { + ticks = 1; + S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY; + } + + /* set clock comparator for next tick */ + tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION; + asm volatile ("SCKC %0" : : "m" (tmp)); irq_enter(cpu, 0); +#ifdef CONFIG_SMP /* - * set clock comparator for next tick + * Do not rely on the boot cpu to do the calls to do_timer. + * Spread it over all cpus instead. */ - S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY; - asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer)); - -#ifdef CONFIG_SMP - if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr) - write_lock(&xtime_lock); - - update_process_times(user_mode(regs)); - - if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr) { - do_timer(regs); - write_unlock(&xtime_lock); + write_lock(&xtime_lock); + if (S390_lowcore.jiffy_timer > xtime_cc) { + __u32 xticks; + + tmp = S390_lowcore.jiffy_timer - xtime_cc; + if (tmp >= 2*CLK_TICKS_PER_JIFFY) { + xticks = div64_32(tmp >> 1, CLK_TICKS_PER_JIFFY >> 1); + xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY; + } else { + xticks = 1; + xtime_cc += CLK_TICKS_PER_JIFFY; + } + while (xticks--) + do_timer(regs); } + write_unlock(&xtime_lock); + while (ticks--) + update_process_times(user_mode(regs)); #else - do_timer(regs); + while (ticks--) + do_timer(regs); #endif - irq_exit(cpu, 0); } @@ -180,11 +218,13 @@ static void do_comparator_interrupt(stru */ void init_cpu_timer(void) { - unsigned long cr0; + unsigned long cr0; + __u64 timer; - S390_lowcore.jiffy_timer = (__u64) jiffies * CLK_TICKS_PER_JIFFY; - S390_lowcore.jiffy_timer += init_timer_cc + CLK_TICKS_PER_JIFFY; - asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer)); + timer = init_timer_cc + (__u64) jiffies * CLK_TICKS_PER_JIFFY; + S390_lowcore.jiffy_timer = timer + CLK_TICKS_PER_JIFFY; + timer += CLK_TICKS_PER_JIFFY + CPU_DEVIATION; + asm volatile ("SCKC %0" : : "m" (timer)); /* allow clock comparator timer interrupt */ asm volatile ("STCTL 0,0,%0" : "=m" (cr0) : : "memory"); cr0 |= 0x800; @@ -220,12 +260,13 @@ void __init time_init(void) } /* set xtime */ + xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY; set_time_cc = init_timer_cc - 0x8126d60e46000000LL + (0x3c26700LL*1000000*4096); tod_to_timeval(set_time_cc, &xtime); /* request the 0x1004 external interrupt */ - if (register_early_external_interrupt(0x1004, do_comparator_interrupt, + if (register_early_external_interrupt(0x1004, NULL, &ext_int_info_timer) != 0) panic("Couldn't request external interrupt 0x1004"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/config.in linux-2.4.28-pre3/arch/s390x/config.in --- linux-2.4.27/arch/s390x/config.in 2003-11-28 18:26:19.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390x/config.in 2004-09-10 19:32:37.000000000 +0000 @@ -60,7 +60,7 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL define_bool CONFIG_KCORE_ELF y -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC bool 'Show crashed user process info' CONFIG_PROCESS_DEBUG bool 'Pseudo page fault support' CONFIG_PFAULT diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/defconfig linux-2.4.28-pre3/arch/s390x/defconfig --- linux-2.4.27/arch/s390x/defconfig 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390x/defconfig 2004-09-10 19:31:52.000000000 +0000 @@ -129,6 +129,14 @@ CONFIG_FDDI=y # CONFIG_CHANDEV=y CONFIG_HOTPLUG=y +CONFIG_QETH=m + +# +# Gigabit Ethernet default settings +# +CONFIG_QETH_IPV6=y +CONFIG_QETH_VLAN=y +# CONFIG_QETH_PERF_STATS is not set CONFIG_CTC=m CONFIG_IUCV=m @@ -291,7 +299,7 @@ CONFIG_NFS_V3=y # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD_TCP=y CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/entry.S linux-2.4.28-pre3/arch/s390x/kernel/entry.S --- linux-2.4.27/arch/s390x/kernel/entry.S 2003-08-25 11:44:40.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390x/kernel/entry.S 2004-09-10 19:33:22.000000000 +0000 @@ -722,7 +722,12 @@ pgm_tracesys: .globl io_int_handler io_int_handler: SAVE_ALL __LC_IO_OLD_PSW,0 + mc 0, 0 GET_CURRENT # load pointer to task_struct to R9 + stck __LC_INT_CLOCK + clc __LC_INT_CLOCK(8),__LC_JIFFY_TIMER + jhe io_handle_tick +io_call_handler: la %r2,SP_PTREGS(%r15) # address of register-save area llgh %r3,__LC_SUBCHANNEL_NR # load subchannel number llgf %r4,__LC_IO_INT_PARM # load interuption parm @@ -780,14 +785,27 @@ io_signal_return: larl %r14,io_leave jg do_signal # return point is io_leave +# +# account tick +# +io_handle_tick: + la %r2,SP_PTREGS(%r15) # address of register-save area + larl %r14,io_call_handler + jg account_ticks + /* * External interrupt handler routine */ .globl ext_int_handler ext_int_handler: SAVE_ALL __LC_EXT_OLD_PSW,0 + mc 0, 0 GET_CURRENT # load pointer to task_struct to R9 llgh %r6,__LC_EXT_INT_CODE # get interruption code + stck __LC_INT_CLOCK + clc __LC_INT_CLOCK(8),__LC_JIFFY_TIMER + jhe ext_handle_tick +ext_call_handler: lgr %r1,%r6 # calculate index = code & 0xff nill %r1,0xff sll %r1,3 @@ -799,6 +817,8 @@ ext_int_loop: ch %r6,16(%r7) # compare external interrupt code jne ext_int_next lg %r1,8(%r7) # get handler address + ltgr %r1,%r1 + jz ext_int_next la %r2,SP_PTREGS(%r15) # address of register-save area lgr %r3,%r6 # interruption code basr %r14,%r1 # call handler @@ -808,12 +828,21 @@ ext_int_next: jnz ext_int_loop j io_return +# +# account tick +# +ext_handle_tick: + la %r2,SP_PTREGS(%r15) # address of register-save area + larl %r14,ext_call_handler + jg account_ticks + /* * Machine check handler routines */ .globl mcck_int_handler mcck_int_handler: SAVE_ALL __LC_MCK_OLD_PSW,0 + mc 0, 0 brasl %r14,s390_do_machine_check mcck_return: RESTORE_ALL 0 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/ioctl32.c linux-2.4.28-pre3/arch/s390x/kernel/ioctl32.c --- linux-2.4.27/arch/s390x/kernel/ioctl32.c 2003-08-25 11:44:40.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390x/kernel/ioctl32.c 2004-09-10 19:36:54.000000000 +0000 @@ -34,6 +34,7 @@ #include #include #include +#include "../../../drivers/s390/char/tubio.h" #include "linux32.h" @@ -535,6 +536,12 @@ static struct ioctl32_list ioctl32_handl IOCTL32_HANDLER(HDIO_GETGEO, hd_geometry_ioctl), + IOCTL32_DEFAULT(TUBICMD), + IOCTL32_DEFAULT(TUBOCMD), + IOCTL32_DEFAULT(TUBGETI), + IOCTL32_DEFAULT(TUBGETO), + IOCTL32_DEFAULT(TUBSETMOD), + IOCTL32_DEFAULT(TUBGETMOD), IOCTL32_DEFAULT(TCGETA), IOCTL32_DEFAULT(TCSETA), IOCTL32_DEFAULT(TCSETAW), diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/linux32.c linux-2.4.28-pre3/arch/s390x/kernel/linux32.c --- linux-2.4.27/arch/s390x/kernel/linux32.c 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390x/kernel/linux32.c 2004-09-10 19:36:02.000000000 +0000 @@ -4427,7 +4427,7 @@ asmlinkage long sys32_stat64(char * file ret = sys_newstat(tmp, &s); set_fs (old_fs); putname(tmp); - if (putstat64 (statbuf, &s)) + if (!ret && putstat64 (statbuf, &s)) return -EFAULT; return ret; } @@ -4451,7 +4451,7 @@ asmlinkage long sys32_lstat64(char * fil ret = sys_newlstat(tmp, &s); set_fs (old_fs); putname(tmp); - if (putstat64 (statbuf, &s)) + if (!ret && putstat64 (statbuf, &s)) return -EFAULT; return ret; } @@ -4467,7 +4467,7 @@ asmlinkage long sys32_fstat64(unsigned l set_fs (KERNEL_DS); ret = sys_newfstat(fd, &s); set_fs (old_fs); - if (putstat64 (statbuf, &s)) + if (!ret && putstat64 (statbuf, &s)) return -EFAULT; return ret; } @@ -4507,7 +4507,7 @@ static inline long do_mmap2( error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) { /* Result is out of bounds. */ - do_munmap(current->mm, addr, len); + do_munmap(current->mm, error, len); error = -ENOMEM; } up_write(¤t->mm->mmap_sem); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/s390_ksyms.c linux-2.4.28-pre3/arch/s390x/kernel/s390_ksyms.c --- linux-2.4.27/arch/s390x/kernel/s390_ksyms.c 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390x/kernel/s390_ksyms.c 2004-09-10 19:36:30.000000000 +0000 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -83,3 +84,7 @@ EXPORT_SYMBOL(console_mode); EXPORT_SYMBOL(console_device); EXPORT_SYMBOL_NOVERS(do_call_softirq); EXPORT_SYMBOL(sys_wait4); +EXPORT_SYMBOL(smp_call_function_on); +EXPORT_SYMBOL(show_trace); +EXPORT_SYMBOL(cpcmd); + diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/smp.c linux-2.4.28-pre3/arch/s390x/kernel/smp.c --- linux-2.4.27/arch/s390x/kernel/smp.c 2003-06-13 14:51:32.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390x/kernel/smp.c 2004-09-10 19:35:00.000000000 +0000 @@ -92,7 +92,7 @@ extern char vmpoff_cmd[]; extern void reipl(unsigned long devno); -static sigp_ccode smp_ext_bitcall(int, ec_bit_sig); +static void smp_ext_bitcall(int, ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig); /* @@ -131,7 +131,7 @@ static void do_call_function(void) * in the system. */ -int smp_call_function (void (*func) (void *info), void *info, int nonatomic, +int smp_call_function(void (*func) (void *info), void *info, int nonatomic, int wait) /* * [SUMMARY] Run a function on all other CPUs. @@ -176,46 +176,92 @@ int smp_call_function (void (*func) (voi return 0; } +/* + * Call a function only on one CPU + * cpu : the CPU the function should be executed on + * + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler, you may call it from a bottom half handler. + */ +int smp_call_function_on(void (*func) (void *info), void *info, + int nonatomic, int wait, int cpu) +{ + struct call_data_struct data; + + if (!atomic_read(&smp_commenced)) + return 0; + + if (smp_processor_id() == cpu) { + /* direct call to function */ + func(info); + return 0; + } + + data.func = func; + data.info = info; + + atomic_set(&data.started, 0); + data.wait = wait; + if (wait) + atomic_set(&data.finished, 0); + + spin_lock_bh(&call_lock); + call_data = &data; + smp_ext_bitcall(cpu, ec_call_function); + + /* Wait for response */ + while (atomic_read(&data.started) != 1) + barrier(); + + if (wait) + while (atomic_read(&data.finished) != 1) + barrier(); + + spin_unlock_bh(&call_lock); + return 0; +} + + static inline void do_send_stop(void) { - u32 dummy; - int i; + unsigned long dummy; + int i; - /* stop all processors */ - for (i = 0; i < smp_num_cpus; i++) { - if (smp_processor_id() != i) { - int ccode; - do { - ccode = signal_processor_ps( - &dummy, - 0, - i, - sigp_stop); - } while(ccode == sigp_busy); - } - } + /* stop all processors */ + for (i = 0; i < smp_num_cpus; i++) { + if (smp_processor_id() != i) { + int ccode; + do { + ccode = signal_processor_ps( + &dummy, + 0, + i, + sigp_stop); + } while(ccode == sigp_busy); + } + } } static inline void do_store_status(void) { - unsigned long low_core_addr; - u32 dummy; - int i; + unsigned long low_core_addr; + unsigned long dummy; + int i; - /* store status of all processors in their lowcores (real 0) */ - for (i = 0; i < smp_num_cpus; i++) { - if (smp_processor_id() != i) { - int ccode; - low_core_addr = (unsigned long)get_cpu_lowcore(i); - do { - ccode = signal_processor_ps( - &dummy, - low_core_addr, - i, - sigp_store_status_at_address); - } while(ccode == sigp_busy); - } - } + /* store status of all processors in their lowcores (real 0) */ + for (i = 0; i < smp_num_cpus; i++) { + if (smp_processor_id() != i) { + int ccode; + low_core_addr = (unsigned long)get_cpu_lowcore(i); + do { + ccode = signal_processor_ps( + &dummy, + low_core_addr, + i, + sigp_store_status_at_address); + } while(ccode == sigp_busy); + } + } } /* @@ -224,8 +270,8 @@ static inline void do_store_status(void) */ void smp_send_stop(void) { - /* write magic number to zero page (absolute 0) */ - get_cpu_lowcore(smp_processor_id())->panic_magic = __PANIC_MAGIC; + /* write magic number to zero page (absolute 0) */ + get_cpu_lowcore(smp_processor_id())->panic_magic = __PANIC_MAGIC; /* stop other processors. */ do_send_stop(); @@ -263,7 +309,7 @@ static void do_machine_restart(void * __ void machine_restart_smp(char * __unused) { cpu_restart_map = cpu_online_map; - smp_call_function(do_machine_restart, NULL, 0, 0); + smp_call_function(do_machine_restart, NULL, 0, 0); do_machine_restart(NULL); } @@ -282,7 +328,7 @@ static void do_machine_halt(void * __unu void machine_halt_smp(void) { - smp_call_function(do_machine_halt, NULL, 0, 0); + smp_call_function(do_machine_halt, NULL, 0, 0); do_machine_halt(NULL); } @@ -301,7 +347,7 @@ static void do_machine_power_off(void * void machine_power_off_smp(void) { - smp_call_function(do_machine_power_off, NULL, 0, 0); + smp_call_function(do_machine_power_off, NULL, 0, 0); do_machine_power_off(NULL); } @@ -312,55 +358,52 @@ void machine_power_off_smp(void) void do_ext_call_interrupt(struct pt_regs *regs, __u16 code) { - unsigned long bits; + unsigned long bits; - /* - * handle bit signal external calls - * - * For the ec_schedule signal we have to do nothing. All the work - * is done automatically when we return from the interrupt. - */ + /* + * handle bit signal external calls + * + * For the ec_schedule signal we have to do nothing. All the work + * is done automatically when we return from the interrupt. + */ bits = xchg(&S390_lowcore.ext_call_fast, 0); - if (test_bit(ec_call_function, &bits)) + if (test_bit(ec_call_function, &bits)) do_call_function(); } /* - * Send an external call sigp to another cpu and return without waiting + * Send an external call sigp to another cpu and wait * for its completion. */ -static sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig) +static void smp_ext_bitcall(int cpu, ec_bit_sig sig) { - sigp_ccode ccode; - - /* - * Set signaling bit in lowcore of target cpu and kick it - */ + /* + * Set signaling bit in lowcore of target cpu and kick it + */ set_bit(sig, &(get_cpu_lowcore(cpu)->ext_call_fast)); - ccode = signal_processor(cpu, sigp_external_call); - return ccode; + while (signal_processor(cpu, sigp_external_call) == sigp_busy) + udelay(10); } /* * Send an external call sigp to every other cpu in the system and - * return without waiting for its completion. + * wait for its completion. */ static void smp_ext_bitcall_others(ec_bit_sig sig) { - sigp_ccode ccode; - int i; + int i; - for (i = 0; i < smp_num_cpus; i++) { - if (smp_processor_id() == i) - continue; - /* - * Set signaling bit in lowcore of target cpu and kick it - */ + for (i = 0; i < smp_num_cpus; i++) { + if (smp_processor_id() == i) + continue; + /* + * Set signaling bit in lowcore of target cpu and kick it + */ set_bit(sig, &(get_cpu_lowcore(i)->ext_call_fast)); - while (signal_processor(i, sigp_external_call) == sigp_busy) + while (signal_processor(i, sigp_external_call) == sigp_busy) udelay(10); - } + } } /* @@ -650,3 +693,4 @@ EXPORT_SYMBOL(smp_ctl_set_bit); EXPORT_SYMBOL(smp_ctl_clear_bit); EXPORT_SYMBOL(smp_num_cpus); EXPORT_SYMBOL(smp_call_function); + diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/time.c linux-2.4.28-pre3/arch/s390x/kernel/time.c --- linux-2.4.27/arch/s390x/kernel/time.c 2003-06-13 14:51:32.000000000 +0000 +++ linux-2.4.28-pre3/arch/s390x/kernel/time.c 2004-09-10 19:36:30.000000000 +0000 @@ -37,10 +37,17 @@ #define USECS_PER_JIFFY ((unsigned long) 1000000/HZ) #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12) +/* + * Create a small time difference between the timer interrupts + * on the different cpus to avoid lock contention. + */ +#define CPU_DEVIATION (smp_processor_id() << 12) + #define TICK_SIZE tick static ext_int_info_t ext_int_info_timer; -static uint64_t init_timer_cc; +static u64 init_timer_cc; +static u64 xtime_cc; extern rwlock_t xtime_lock; extern unsigned long wall_jiffies; @@ -56,7 +63,7 @@ static inline unsigned long do_gettimeof { __u64 now; - asm ("STCK 0(%0)" : : "a" (&now) : "memory", "cc"); + asm volatile ("STCK 0(%0)" : : "a" (&now) : "memory", "cc"); now = (now - init_timer_cc) >> 12; /* We require the offset from the latest update of xtime */ now -= (__u64) wall_jiffies*USECS_PER_JIFFY; @@ -114,35 +121,58 @@ void do_settimeofday(struct timeval *tv) * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ - -#ifdef CONFIG_SMP -extern __u16 boot_cpu_addr; -#endif - -static void do_comparator_interrupt(struct pt_regs *regs, __u16 error_code) +void account_ticks(struct pt_regs *regs) { int cpu = smp_processor_id(); + __u64 tmp; + __u32 ticks; + + /* Calculate how many ticks have passed. */ + tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer; + if (tmp >= 2*CLK_TICKS_PER_JIFFY) { /* more than one tick ? */ + ticks = tmp / CLK_TICKS_PER_JIFFY + 1; + S390_lowcore.jiffy_timer += + CLK_TICKS_PER_JIFFY * (__u64) ticks; + } else if (tmp > CLK_TICKS_PER_JIFFY) { + ticks = 2; + S390_lowcore.jiffy_timer += 2*CLK_TICKS_PER_JIFFY; + } else { + ticks = 1; + S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY; + } + + /* set clock comparator for next tick */ + tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION; + asm volatile ("SCKC %0" : : "m" (tmp)); irq_enter(cpu, 0); +#ifdef CONFIG_SMP /* - * set clock comparator for next tick + * Do not rely on the boot cpu to do the calls to do_timer. + * Spread it over all cpus instead. */ - S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY; - asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer)); - -#ifdef CONFIG_SMP - if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr) - write_lock(&xtime_lock); - - update_process_times(user_mode(regs)); - - if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr) { - do_timer(regs); - write_unlock(&xtime_lock); + write_lock(&xtime_lock); + if (S390_lowcore.jiffy_timer > xtime_cc) { + __u32 xticks; + + tmp = S390_lowcore.jiffy_timer - xtime_cc; + if (tmp >= 2*CLK_TICKS_PER_JIFFY) { + xticks = tmp / CLK_TICKS_PER_JIFFY; + xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY; + } else { + xticks = 1; + xtime_cc += CLK_TICKS_PER_JIFFY; + } + while (xticks--) + do_timer(regs); } + write_unlock(&xtime_lock); + while (ticks--) + update_process_times(user_mode(regs)); #else - do_timer(regs); + while (ticks--) + do_timer(regs); #endif irq_exit(cpu, 0); @@ -153,11 +183,13 @@ static void do_comparator_interrupt(stru */ void init_cpu_timer(void) { - unsigned long cr0; + unsigned long cr0; + __u64 timer; - S390_lowcore.jiffy_timer = (__u64) jiffies * CLK_TICKS_PER_JIFFY; - S390_lowcore.jiffy_timer += init_timer_cc + CLK_TICKS_PER_JIFFY; - asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer)); + timer = init_timer_cc + (__u64) jiffies * CLK_TICKS_PER_JIFFY; + S390_lowcore.jiffy_timer = timer + CLK_TICKS_PER_JIFFY; + timer += CLK_TICKS_PER_JIFFY + CPU_DEVIATION; + asm volatile ("SCKC %0" : : "m" (timer)); /* allow clock comparator timer interrupt */ asm volatile ("STCTG 0,0,%0" : "=m" (cr0) : : "memory"); cr0 |= 0x800; @@ -193,12 +225,13 @@ void __init time_init(void) } /* set xtime */ + xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY; set_time_cc = init_timer_cc - 0x8126d60e46000000LL + (0x3c26700LL*1000000*4096); tod_to_timeval(set_time_cc, &xtime); /* request the 0x1004 external interrupt */ - if (register_early_external_interrupt(0x1004, do_comparator_interrupt, + if (register_early_external_interrupt(0x1004, NULL, &ext_int_info_timer) != 0) panic("Couldn't request external interrupt 0x1004"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sh/config.in linux-2.4.28-pre3/arch/sh/config.in --- linux-2.4.27/arch/sh/config.in 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/sh/config.in 2004-09-10 19:34:57.000000000 +0000 @@ -282,7 +282,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then "ELF CONFIG_KCORE_ELF \ A.OUT CONFIG_KCORE_AOUT" ELF fi -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sh64/config.in linux-2.4.28-pre3/arch/sh64/config.in --- linux-2.4.27/arch/sh64/config.in 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/sh64/config.in 2004-09-10 19:37:23.000000000 +0000 @@ -150,7 +150,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then "ELF CONFIG_KCORE_ELF \ A.OUT CONFIG_KCORE_AOUT" ELF fi -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sh64/defconfig linux-2.4.28-pre3/arch/sh64/defconfig --- linux-2.4.27/arch/sh64/defconfig 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/sh64/defconfig 2004-09-10 19:36:59.000000000 +0000 @@ -386,7 +386,7 @@ CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD_TCP=y CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc/config.in linux-2.4.28-pre3/arch/sparc/config.in --- linux-2.4.27/arch/sparc/config.in 2004-02-18 13:36:30.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc/config.in 2004-09-10 19:32:23.000000000 +0000 @@ -73,7 +73,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then define_bool CONFIG_KCORE_ELF y fi tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC bool 'SunOS binary emulation' CONFIG_SUNOS_EMUL bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc/lib/copy_user.S linux-2.4.28-pre3/arch/sparc/lib/copy_user.S --- linux-2.4.27/arch/sparc/lib/copy_user.S 2003-11-28 18:26:19.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc/lib/copy_user.S 2004-09-10 19:35:12.000000000 +0000 @@ -65,52 +65,52 @@ /* Both these macros have to start with exactly the same insn */ #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - ldd [%src + offset + 0x10], %t4; \ - ldd [%src + offset + 0x18], %t6; \ - st %t0, [%dst + offset + 0x00]; \ - st %t1, [%dst + offset + 0x04]; \ - st %t2, [%dst + offset + 0x08]; \ - st %t3, [%dst + offset + 0x0c]; \ - st %t4, [%dst + offset + 0x10]; \ - st %t5, [%dst + offset + 0x14]; \ - st %t6, [%dst + offset + 0x18]; \ - st %t7, [%dst + offset + 0x1c]; + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + ldd [%src + (offset) + 0x10], %t4; \ + ldd [%src + (offset) + 0x18], %t6; \ + st %t0, [%dst + (offset) + 0x00]; \ + st %t1, [%dst + (offset) + 0x04]; \ + st %t2, [%dst + (offset) + 0x08]; \ + st %t3, [%dst + (offset) + 0x0c]; \ + st %t4, [%dst + (offset) + 0x10]; \ + st %t5, [%dst + (offset) + 0x14]; \ + st %t6, [%dst + (offset) + 0x18]; \ + st %t7, [%dst + (offset) + 0x1c]; #define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [%src + offset + 0x00], %t0; \ - ldd [%src + offset + 0x08], %t2; \ - ldd [%src + offset + 0x10], %t4; \ - ldd [%src + offset + 0x18], %t6; \ - std %t0, [%dst + offset + 0x00]; \ - std %t2, [%dst + offset + 0x08]; \ - std %t4, [%dst + offset + 0x10]; \ - std %t6, [%dst + offset + 0x18]; + ldd [%src + (offset) + 0x00], %t0; \ + ldd [%src + (offset) + 0x08], %t2; \ + ldd [%src + (offset) + 0x10], %t4; \ + ldd [%src + (offset) + 0x18], %t6; \ + std %t0, [%dst + (offset) + 0x00]; \ + std %t2, [%dst + (offset) + 0x08]; \ + std %t4, [%dst + (offset) + 0x10]; \ + std %t6, [%dst + (offset) + 0x18]; #define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ - ldd [%src - offset - 0x10], %t0; \ - ldd [%src - offset - 0x08], %t2; \ - st %t0, [%dst - offset - 0x10]; \ - st %t1, [%dst - offset - 0x0c]; \ - st %t2, [%dst - offset - 0x08]; \ - st %t3, [%dst - offset - 0x04]; + ldd [%src - (offset) - 0x10], %t0; \ + ldd [%src - (offset) - 0x08], %t2; \ + st %t0, [%dst - (offset) - 0x10]; \ + st %t1, [%dst - (offset) - 0x0c]; \ + st %t2, [%dst - (offset) - 0x08]; \ + st %t3, [%dst - (offset) - 0x04]; #define MOVE_HALFCHUNK(src, dst, offset, t0, t1, t2, t3) \ - lduh [%src + offset + 0x00], %t0; \ - lduh [%src + offset + 0x02], %t1; \ - lduh [%src + offset + 0x04], %t2; \ - lduh [%src + offset + 0x06], %t3; \ - sth %t0, [%dst + offset + 0x00]; \ - sth %t1, [%dst + offset + 0x02]; \ - sth %t2, [%dst + offset + 0x04]; \ - sth %t3, [%dst + offset + 0x06]; + lduh [%src + (offset) + 0x00], %t0; \ + lduh [%src + (offset) + 0x02], %t1; \ + lduh [%src + (offset) + 0x04], %t2; \ + lduh [%src + (offset) + 0x06], %t3; \ + sth %t0, [%dst + (offset) + 0x00]; \ + sth %t1, [%dst + (offset) + 0x02]; \ + sth %t2, [%dst + (offset) + 0x04]; \ + sth %t3, [%dst + (offset) + 0x06]; #define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ - ldub [%src - offset - 0x02], %t0; \ - ldub [%src - offset - 0x01], %t1; \ - stb %t0, [%dst - offset - 0x02]; \ - stb %t1, [%dst - offset - 0x01]; + ldub [%src - (offset) - 0x02], %t0; \ + ldub [%src - (offset) - 0x01], %t1; \ + stb %t0, [%dst - (offset) - 0x02]; \ + stb %t1, [%dst - (offset) - 0x01]; .text .align 4 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/config.in linux-2.4.28-pre3/arch/sparc64/config.in --- linux-2.4.27/arch/sparc64/config.in 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/config.in 2004-09-10 19:33:39.000000000 +0000 @@ -78,7 +78,7 @@ if [ "$CONFIG_SPARC32_COMPAT" != "n" ]; tristate ' Kernel support for 32-bit ELF binaries' CONFIG_BINFMT_ELF32 bool ' Kernel support for 32-bit (ie. SunOS) a.out binaries' CONFIG_BINFMT_AOUT32 fi -tristate 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC bool 'SunOS binary emulation' CONFIG_SUNOS_EMUL if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/defconfig linux-2.4.28-pre3/arch/sparc64/defconfig --- linux-2.4.27/arch/sparc64/defconfig 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/defconfig 2004-09-10 19:33:49.000000000 +0000 @@ -375,7 +375,7 @@ CONFIG_NET_SCH_SFQ=m CONFIG_NET_SCH_TEQL=m CONFIG_NET_SCH_TBF=m CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DELAY=m +CONFIG_NET_SCH_NETEM=m CONFIG_NET_SCH_DSMARK=m CONFIG_NET_SCH_INGRESS=m CONFIG_NET_QOS=y @@ -410,6 +410,7 @@ CONFIG_BLK_DEV_IDE=y # # CONFIG_BLK_DEV_HD_IDE is not set # CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set # CONFIG_IDEDISK_STROKE is not set @@ -1134,6 +1135,8 @@ CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_KHAZAD=m CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=m diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/head.S linux-2.4.28-pre3/arch/sparc64/kernel/head.S --- linux-2.4.27/arch/sparc64/kernel/head.S 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/head.S 2004-09-10 19:34:07.000000000 +0000 @@ -50,7 +50,7 @@ bootup_user_stack: */ .global root_flags, ram_flags, root_dev .global sparc_ramdisk_image, sparc_ramdisk_size - .globl silo_args + .global sparc_ramdisk_image64 .ascii "HdrS" .word LINUX_VERSION_CODE @@ -61,7 +61,7 @@ bootup_user_stack: * 0x0202 : Supports kernel params string * 0x0201 : Supports reboot_command */ - .half 0x0300 /* HdrS version */ + .half 0x0301 /* HdrS version */ root_flags: .half 1 @@ -75,6 +75,8 @@ sparc_ramdisk_size: .word 0 .xword reboot_command .xword bootstr_info +sparc_ramdisk_image64: + .xword 0 .word _end /* We must be careful, 32-bit OpenBOOT will get confused if it diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/ioctl32.c linux-2.4.28-pre3/arch/sparc64/kernel/ioctl32.c --- linux-2.4.27/arch/sparc64/kernel/ioctl32.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/ioctl32.c 2004-09-10 19:36:44.000000000 +0000 @@ -2948,7 +2948,7 @@ static int do_lvm_ioctl(unsigned int fd, case LV_REMOVE: case LV_RENAME: case LV_STATUS_BYNAME: - err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name)); + err = copy_from_user(&u.lv_req, arg, sizeof(u.lv_req.lv_name)); if (err) return -EFAULT; if (cmd != LV_REMOVE) { @@ -2991,7 +2991,7 @@ static int do_lvm_ioctl(unsigned int fd, case PV_CHANGE: case PV_STATUS: - err = copy_from_user(&u.pv_status, arg, sizeof(u.lv_req.lv_name)); + err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name)); if (err) return -EFAULT; err = __get_user(ptr, &((pv_status_req32_t *)arg)->pv); @@ -3063,7 +3063,7 @@ static int do_lvm_ioctl(unsigned int fd, if (u.lv_bydev.lv) { if (!err) err = copy_lv_t(ptr, u.lv_bydev.lv); - put_lv_t(u.lv_byindex.lv); + put_lv_t(u.lv_bydev.lv); } break; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/itlb_base.S linux-2.4.28-pre3/arch/sparc64/kernel/itlb_base.S --- linux-2.4.27/arch/sparc64/kernel/itlb_base.S 2003-06-13 14:51:32.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/itlb_base.S 2004-09-10 19:32:39.000000000 +0000 @@ -41,6 +41,9 @@ CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset ldxa [%g3 + %g6] ASI_P, %g5 ! Load VPTE 1: brgez,pn %g5, 3f ! Not valid, branch out + sethi %hi(_PAGE_EXEC), %g4 ! Delay-slot + andcc %g5, %g4, %g0 ! Executable? + be,pn %xcc, 3f ! Nope, branch. nop ! Delay-slot 2: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB retry ! Trap return @@ -73,9 +76,6 @@ winfix_trampoline: nop nop nop - nop - nop - nop CREATE_VPTE_NOP #undef CREATE_VPTE_OFFSET1 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/pci_iommu.c linux-2.4.28-pre3/arch/sparc64/kernel/pci_iommu.c --- linux-2.4.27/arch/sparc64/kernel/pci_iommu.c 2003-11-28 18:26:19.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/pci_iommu.c 2004-09-10 19:32:45.000000000 +0000 @@ -56,6 +56,39 @@ static void __iommu_flushall(struct pci_ } } +#define IOPTE_CONSISTENT(CTX) \ + (IOPTE_VALID | IOPTE_CACHE | \ + (((CTX) << 47) & IOPTE_CONTEXT)) + +#define IOPTE_STREAMING(CTX) \ + (IOPTE_CONSISTENT(CTX) | IOPTE_STBUF) + +/* Existing mappings are never marked invalid, instead they + * are pointed to a dummy page. + */ +#define IOPTE_IS_DUMMY(iommu, iopte) \ + ((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa) + +static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) +{ + unsigned long val = iopte_val(*iopte); + + val &= ~IOPTE_PAGE; + val |= iommu->dummy_page_pa; + + iopte_val(*iopte) = val; +} + +void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize) +{ + int i; + + tsbsize /= sizeof(iopte_t); + + for (i = 0; i < tsbsize; i++) + iopte_make_dummy(iommu, &iommu->page_table[i]); +} + static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages) { iopte_t *iopte, *limit, *first; @@ -79,7 +112,7 @@ static iopte_t *alloc_streaming_cluster( first = iopte; for (;;) { - if (iopte_val(*iopte) == 0UL) { + if (IOPTE_IS_DUMMY(iommu, iopte)) { if ((iopte + (1 << cnum)) >= limit) ent = 0; else @@ -142,12 +175,12 @@ static iopte_t *alloc_consistent_cluster iopte = iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)); while (iopte > iommu->page_table) { iopte--; - if (!(iopte_val(*iopte) & IOPTE_VALID)) { + if (IOPTE_IS_DUMMY(iommu, iopte)) { unsigned long tmp = npages; while (--tmp) { iopte--; - if (iopte_val(*iopte) & IOPTE_VALID) + if (!IOPTE_IS_DUMMY(iommu, iopte)) break; } if (tmp == 0) { @@ -162,15 +195,6 @@ static iopte_t *alloc_consistent_cluster return NULL; } -#define IOPTE_CONSISTENT(CTX) \ - (IOPTE_VALID | IOPTE_CACHE | \ - (((CTX) << 47) & IOPTE_CONTEXT)) - -#define IOPTE_STREAMING(CTX) \ - (IOPTE_CONSISTENT(CTX) | IOPTE_STBUF) - -#define IOPTE_INVALID 0UL - /* Allocate and map kernel buffer of size SIZE using consistent mode * DMA for PCI device PDEV. Return non-NULL cpu-side address if * successful and set *DMA_ADDRP to the PCI side dma address. @@ -261,7 +285,7 @@ void pci_free_consistent(struct pci_dev limit = (iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS))); while (walk < limit) { - if (iopte_val(*walk) != IOPTE_INVALID) + if (!IOPTE_IS_DUMMY(iommu, walk)) break; walk++; } @@ -280,7 +304,7 @@ void pci_free_consistent(struct pci_dev ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; for (i = 0; i < npages; i++, iopte++) - iopte_val(*iopte) = IOPTE_INVALID; + iopte_make_dummy(iommu, iopte); if (iommu->iommu_ctxflush) { pci_iommu_write(iommu->iommu_ctxflush, ctx); @@ -377,7 +401,7 @@ void pci_unmap_single(struct pci_dev *pd base = iommu->page_table + ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); #ifdef DEBUG_PCI_IOMMU - if (iopte_val(*base) == IOPTE_INVALID) + if (IOPTE_IS_DUMMY(iommu, base)) printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n", bus_addr, sz, __builtin_return_address(0)); #endif @@ -416,7 +440,7 @@ void pci_unmap_single(struct pci_dev *pd } /* Step 2: Clear out first TSB entry. */ - iopte_val(*base) = IOPTE_INVALID; + iopte_make_dummy(iommu, base); free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages, ctx); @@ -617,7 +641,7 @@ void pci_unmap_sg(struct pci_dev *pdev, ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); #ifdef DEBUG_PCI_IOMMU - if (iopte_val(*base) == IOPTE_INVALID) + if (IOPTE_IS_DUMMY(iommu, base)) printk("pci_unmap_sg called on non-mapped region %016lx,%d from %016lx\n", sglist->dma_address, nelems, __builtin_return_address(0)); #endif @@ -654,7 +678,7 @@ void pci_unmap_sg(struct pci_dev *pdev, } /* Step 2: Clear out first TSB entry. */ - iopte_val(*base) = IOPTE_INVALID; + iopte_make_dummy(iommu, base); free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages, ctx); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/pci_psycho.c linux-2.4.28-pre3/arch/sparc64/kernel/pci_psycho.c --- linux-2.4.27/arch/sparc64/kernel/pci_psycho.c 2003-11-28 18:26:19.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/pci_psycho.c 2004-09-10 19:35:22.000000000 +0000 @@ -1373,6 +1373,14 @@ static void __init psycho_iommu_init(str * in pci_iommu.c */ + iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); + if (!iommu->dummy_page) { + prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); + prom_halt(); + } + memset((void *)iommu->dummy_page, 0, PAGE_SIZE); + iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); + /* Using assumed page size 8K with 128K entries we need 1MB iommu page * table (128K ioptes * 8 bytes per iopte). This is * page order 7 on UltraSparc. @@ -1386,7 +1394,7 @@ static void __init psycho_iommu_init(str iommu->page_table_sz_bits = 17; iommu->page_table_map_base = 0xc0000000; iommu->dma_addr_mask = 0xffffffff; - memset((char *)tsbbase, 0, IO_TSB_SIZE); + pci_iommu_table_init(iommu, IO_TSB_SIZE); /* We start with no consistent mappings. */ iommu->lowest_consistent_map = diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/pci_sabre.c linux-2.4.28-pre3/arch/sparc64/kernel/pci_sabre.c --- linux-2.4.27/arch/sparc64/kernel/pci_sabre.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/pci_sabre.c 2004-09-10 19:34:33.000000000 +0000 @@ -1315,6 +1315,14 @@ static void __init sabre_iommu_init(stru * in pci_iommu.c */ + iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); + if (!iommu->dummy_page) { + prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); + prom_halt(); + } + memset((void *)iommu->dummy_page, 0, PAGE_SIZE); + iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); + tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8)); if (!tsbbase) { prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n"); @@ -1323,7 +1331,7 @@ static void __init sabre_iommu_init(stru iommu->page_table = (iopte_t *)tsbbase; iommu->page_table_map_base = dvma_offset; iommu->dma_addr_mask = dma_mask; - memset((char *)tsbbase, 0, PAGE_SIZE << order); + pci_iommu_table_init(iommu, PAGE_SIZE << order); sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase)); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/pci_schizo.c linux-2.4.28-pre3/arch/sparc64/kernel/pci_schizo.c --- linux-2.4.27/arch/sparc64/kernel/pci_schizo.c 2003-11-28 18:26:19.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/pci_schizo.c 2004-09-10 19:32:41.000000000 +0000 @@ -1843,6 +1843,14 @@ static void schizo_pbm_iommu_init(struct * in pci_iommu.c */ + iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); + if (!iommu->dummy_page) { + prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); + prom_halt(); + } + memset((void *)iommu->dummy_page, 0, PAGE_SIZE); + iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); + /* Using assumed page size 8K with 128K entries we need 1MB iommu page * table (128K ioptes * 8 bytes per iopte). This is * page order 7 on UltraSparc. @@ -1857,7 +1865,7 @@ static void schizo_pbm_iommu_init(struct iommu->page_table = (iopte_t *)tsbbase; iommu->page_table_map_base = vdma[0]; iommu->dma_addr_mask = dma_mask; - memset((char *)tsbbase, 0, PAGE_SIZE << order); + pci_iommu_table_init(iommu, PAGE_SIZE << order); switch (tsbsize) { case 64: diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/process.c linux-2.4.28-pre3/arch/sparc64/kernel/process.c --- linux-2.4.27/arch/sparc64/kernel/process.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/process.c 2004-09-10 19:34:24.000000000 +0000 @@ -503,7 +503,7 @@ static unsigned long clone_stackframe(un distance = fp - psp; rval = (csp - distance); - if (copy_in_user(rval, psp, distance)) + if (copy_in_user((void *)rval, (void *)psp, distance)) rval = 0; else if (current->thread.flags & SPARC_FLAG_32BIT) { if (put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6]))) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/sbus.c linux-2.4.28-pre3/arch/sparc64/kernel/sbus.c --- linux-2.4.27/arch/sparc64/kernel/sbus.c 2002-08-03 00:39:43.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/sbus.c 2004-09-10 19:37:20.000000000 +0000 @@ -27,10 +27,10 @@ * * On SYSIO, using an 8K page size we have 1GB of SBUS * DMA space mapped. We divide this space into equally - * sized clusters. Currently we allow clusters up to a - * size of 1MB. If anything begins to generate DMA - * mapping requests larger than this we will need to - * increase things a bit. + * sized clusters. We allocate a DMA mapping from the + * cluster that matches the order of the allocation, or + * if the order is greater than the number of clusters, + * we try to allocate from the last cluster. */ #define NCLUSTERS 8UL @@ -133,12 +133,17 @@ static void strbuf_flush(struct sbus_iom static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) { - iopte_t *iopte, *limit, *first; - unsigned long cnum, ent, flush_point; + iopte_t *iopte, *limit, *first, *cluster; + unsigned long cnum, ent, nent, flush_point, found; cnum = 0; + nent = 1; while ((1UL << cnum) < npages) cnum++; + if(cnum >= NCLUSTERS) { + nent = 1UL << (cnum - NCLUSTERS); + cnum = NCLUSTERS - 1; + } iopte = iommu->page_table + (cnum * CLUSTER_NPAGES); if (cnum == 0) @@ -151,22 +156,31 @@ static iopte_t *alloc_streaming_cluster( flush_point = iommu->alloc_info[cnum].flush; first = iopte; + cluster = NULL; + found = 0; for (;;) { if (iopte_val(*iopte) == 0UL) { - if ((iopte + (1 << cnum)) >= limit) - ent = 0; - else - ent = ent + 1; - iommu->alloc_info[cnum].next = ent; - if (ent == flush_point) - __iommu_flushall(iommu); - break; + found++; + if (!cluster) + cluster = iopte; + } else { + /* Used cluster in the way */ + cluster = NULL; + found = 0; } + + if (found == nent) + break; + iopte += (1 << cnum); ent++; if (iopte >= limit) { iopte = (iommu->page_table + (cnum * CLUSTER_NPAGES)); ent = 0; + + /* Multiple cluster allocations must not wrap */ + cluster = NULL; + found = 0; } if (ent == flush_point) __iommu_flushall(iommu); @@ -174,8 +188,19 @@ static iopte_t *alloc_streaming_cluster( goto bad; } + /* ent/iopte points to the last cluster entry we're going to use, + * so save our place for the next allocation. + */ + if ((iopte + (1 << cnum)) >= limit) + ent = 0; + else + ent = ent + 1; + iommu->alloc_info[cnum].next = ent; + if (ent == flush_point) + __iommu_flushall(iommu); + /* I've got your streaming cluster right here buddy boy... */ - return iopte; + return cluster; bad: printk(KERN_EMERG "sbus: alloc_streaming_cluster of npages(%ld) failed!\n", @@ -185,15 +210,23 @@ bad: static void free_streaming_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages) { - unsigned long cnum, ent; + unsigned long cnum, ent, nent; iopte_t *iopte; cnum = 0; + nent = 1; while ((1UL << cnum) < npages) cnum++; + if(cnum >= NCLUSTERS) { + nent = 1UL << (cnum - NCLUSTERS); + cnum = NCLUSTERS - 1; + } ent = (base & CLUSTER_MASK) >> (IO_PAGE_SHIFT + cnum); iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT); - iopte_val(*iopte) = 0UL; + do { + iopte_val(*iopte) = 0UL; + iopte += 1 << cnum; + } while(--nent); /* If the global flush might not have caught this entry, * adjust the flush point such that we will flush before diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/signal.c linux-2.4.28-pre3/arch/sparc64/kernel/signal.c --- linux-2.4.27/arch/sparc64/kernel/signal.c 2003-08-25 11:44:40.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/signal.c 2004-09-10 19:35:20.000000000 +0000 @@ -116,8 +116,8 @@ asmlinkage void sparc64_set_context(stru regs->tnpc = npc; err |= __get_user(regs->y, &((*grp)[MC_Y])); err |= __get_user(tstate, &((*grp)[MC_TSTATE])); - regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC); - regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC)); + regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC); + regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1])); err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2])); err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3])); @@ -437,9 +437,9 @@ void do_rt_sigreturn(struct pt_regs *reg err |= __get_user(tstate, &sf->regs.tstate); err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs)); - /* User can only change condition codes in %tstate. */ - regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC); - regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC)); + /* User can only change condition codes and %asi in %tstate. */ + regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC); + regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); err |= __get_user(fpu_save, &sf->fpu_save); if (fpu_save) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/signal32.c linux-2.4.28-pre3/arch/sparc64/kernel/signal32.c --- linux-2.4.27/arch/sparc64/kernel/signal32.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/signal32.c 2004-09-10 19:31:52.000000000 +0000 @@ -62,6 +62,16 @@ struct signal_sframe32 { unsigned extramask[_NSIG_WORDS32 - 1]; }; +/* This magic should be in g_upper[0] for all upper parts + * to be valid. + */ +#define SIGINFO_EXTRA_V8PLUS_MAGIC 0x130e269 +typedef struct { + unsigned int g_upper[8]; + unsigned int o_upper[8]; + unsigned int asi; +} siginfo_extra_v8plus_t; + /* * And the new one, intended to be used for Linux applications only * (we have enough in there to work with clone). @@ -292,8 +302,13 @@ void do_new_sigreturn32(struct pt_regs * if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) { err |= __get_user(i, &sf->v8plus.g_upper[0]); if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) { + unsigned long asi; + for (i = UREG_G1; i <= UREG_I7; i++) err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]); + err |= __get_user(asi, &sf->v8plus.asi); + regs->tstate &= ~TSTATE_ASI; + regs->tstate |= ((asi & 0xffUL) << 24UL); } } @@ -431,8 +446,13 @@ asmlinkage void do_rt_sigreturn32(struct if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) { err |= __get_user(i, &sf->v8plus.g_upper[0]); if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) { + unsigned long asi; + for (i = UREG_G1; i <= UREG_I7; i++) err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]); + err |= __get_user(asi, &sf->v8plus.asi); + regs->tstate &= ~TSTATE_ASI; + regs->tstate |= ((asi & 0xffUL) << 24UL); } } @@ -728,7 +748,10 @@ static inline void new_setup_frame32(str err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size); err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]); for (i = 1; i < 16; i++) - err |= __put_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]); + err |= __put_user(((u32 *)regs->u_regs)[2*i], + &sf->v8plus.g_upper[i]); + err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL, + &sf->v8plus.asi); if (psr & PSR_EF) { err |= save_fpu_state32(regs, &sf->fpu_state); @@ -1175,7 +1198,10 @@ static inline void setup_rt_frame32(stru err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size); err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]); for (i = 1; i < 16; i++) - err |= __put_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]); + err |= __put_user(((u32 *)regs->u_regs)[2*i], + &sf->v8plus.g_upper[i]); + err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL, + &sf->v8plus.asi); if (psr & PSR_EF) { err |= save_fpu_state32(regs, &sf->fpu_state); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/sparc64_ksyms.c linux-2.4.28-pre3/arch/sparc64/kernel/sparc64_ksyms.c --- linux-2.4.27/arch/sparc64/kernel/sparc64_ksyms.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/sparc64_ksyms.c 2004-09-10 19:36:30.000000000 +0000 @@ -324,8 +324,6 @@ EXPORT_SYMBOL(sparc32_open); #endif /* Special internal versions of library functions. */ -EXPORT_SYMBOL(__memcpy); -EXPORT_SYMBOL(__memset); EXPORT_SYMBOL(_clear_page); EXPORT_SYMBOL(clear_user_page); EXPORT_SYMBOL(copy_user_page); @@ -334,14 +332,17 @@ EXPORT_SYMBOL(__memscan_zero); EXPORT_SYMBOL(__memscan_generic); EXPORT_SYMBOL(__memcmp); EXPORT_SYMBOL(__strncmp); -EXPORT_SYMBOL(__memmove); +EXPORT_SYMBOL(__memset); EXPORT_SYMBOL(csum_partial_copy_sparc64); /* Moving data to/from userspace. */ -EXPORT_SYMBOL(__copy_to_user); -EXPORT_SYMBOL(__copy_from_user); -EXPORT_SYMBOL(__strncpy_from_user); +EXPORT_SYMBOL(___copy_to_user); +EXPORT_SYMBOL(___copy_from_user); +EXPORT_SYMBOL(___copy_in_user); +EXPORT_SYMBOL(copy_to_user_fixup); +EXPORT_SYMBOL(copy_from_user_fixup); +EXPORT_SYMBOL(copy_in_user_fixup); EXPORT_SYMBOL(__bzero_noasi); /* Various address conversion macros use this. */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/time.c linux-2.4.28-pre3/arch/sparc64/kernel/time.c --- linux-2.4.27/arch/sparc64/kernel/time.c 2003-11-28 18:26:19.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/kernel/time.c 2004-09-10 19:34:52.000000000 +0000 @@ -432,18 +432,12 @@ void sparc64_do_profile(unsigned long pc 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 __bzero_begin, __bzero_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) &__bzero_begin && - pc < (unsigned long) &__bzero_end) || (pc >= (unsigned long) &__bitops_begin && pc < (unsigned long) &__bitops_end)) pc = o7; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/Makefile linux-2.4.28-pre3/arch/sparc64/lib/Makefile --- linux-2.4.27/arch/sparc64/lib/Makefile 2002-08-03 00:39:43.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/Makefile 2004-09-10 19:32:22.000000000 +0000 @@ -8,9 +8,11 @@ EXTRA_AFLAGS := -ansi L_TARGET = lib.a obj-y := PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \ memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \ - VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \ + VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \ VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \ - dec_and_lock.o U3memcpy.o U3copy_from_user.o U3copy_to_user.o \ - U3copy_in_user.o mcount.o + U1memcpy.o U1copy_from_user.o U1copy_to_user.o \ + U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \ + copy_in_user.o user_fixup.o memmove.o \ + dec_and_lock.o mcount.o include $(TOPDIR)/Rules.make diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U1copy_from_user.S linux-2.4.28-pre3/arch/sparc64/lib/U1copy_from_user.S --- linux-2.4.27/arch/sparc64/lib/U1copy_from_user.S 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/U1copy_from_user.S 2004-09-10 19:33:27.000000000 +0000 @@ -0,0 +1,33 @@ +/* U1copy_from_user.S: UltraSparc-I/II/IIi/IIe optimized copy from userspace. + * + * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) + */ + +#define EX_LD(x) \ +98: x; \ + .section .fixup; \ + .align 4; \ +99: retl; \ + mov 1, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; + +#define FUNC_NAME ___copy_from_user +#define LOAD(type,addr,dest) type##a [addr] %asi, dest +#define LOAD_BLK(addr,dest) ldda [addr] ASI_BLK_AIUS, dest +#define EX_RETVAL(x) 0 + + /* Writing to %asi is _expensive_ so we hardcode it. + * Reading %asi to check for KERNEL_DS is comparatively + * cheap. + */ +#define PREAMBLE \ + rd %asi, %g1; \ + cmp %g1, ASI_AIUS; \ + bne,pn %icc, memcpy_user_stub; \ + nop; \ + +#include "U1memcpy.S" diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U1copy_to_user.S linux-2.4.28-pre3/arch/sparc64/lib/U1copy_to_user.S --- linux-2.4.27/arch/sparc64/lib/U1copy_to_user.S 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/U1copy_to_user.S 2004-09-10 19:35:13.000000000 +0000 @@ -0,0 +1,33 @@ +/* U1copy_to_user.S: UltraSparc-I/II/IIi/IIe optimized copy to userspace. + * + * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) + */ + +#define EX_ST(x) \ +98: x; \ + .section .fixup; \ + .align 4; \ +99: retl; \ + mov 1, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; + +#define FUNC_NAME ___copy_to_user +#define STORE(type,src,addr) type##a src, [addr] ASI_AIUS +#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_AIUS +#define EX_RETVAL(x) 0 + + /* Writing to %asi is _expensive_ so we hardcode it. + * Reading %asi to check for KERNEL_DS is comparatively + * cheap. + */ +#define PREAMBLE \ + rd %asi, %g1; \ + cmp %g1, ASI_AIUS; \ + bne,pn %icc, memcpy_user_stub; \ + nop; \ + +#include "U1memcpy.S" diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U1memcpy.S linux-2.4.28-pre3/arch/sparc64/lib/U1memcpy.S --- linux-2.4.27/arch/sparc64/lib/U1memcpy.S 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/U1memcpy.S 2004-09-10 19:36:46.000000000 +0000 @@ -0,0 +1,552 @@ +/* U1memcpy.S: UltraSPARC-I/II/IIi/IIe optimized memcpy. + * + * Copyright (C) 1997, 2004 David S. Miller (davem@redhat.com) + * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz) + */ + +#ifdef __KERNEL__ +#include +#include +#else +#define ASI_BLK_P 0xf0 +#define FPRS_FEF 0x04 +#ifdef MEMCPY_DEBUG +#define VISEntry rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \ + clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0; +#define VISExit and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs +#else +#define VISEntry rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs +#define VISExit and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs +#endif +#endif + +#ifndef EX_LD +#define EX_LD(x) x +#endif + +#ifndef EX_ST +#define EX_ST(x) x +#endif + +#ifndef EX_RETVAL +#define EX_RETVAL(x) x +#endif + +#ifndef LOAD +#define LOAD(type,addr,dest) type [addr], dest +#endif + +#ifndef LOAD_BLK +#define LOAD_BLK(addr,dest) ldda [addr] ASI_BLK_P, dest +#endif + +#ifndef STORE +#define STORE(type,src,addr) type src, [addr] +#endif + +#ifndef STORE_BLK +#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_P +#endif + +#ifndef FUNC_NAME +#define FUNC_NAME memcpy +#endif + +#ifndef PREAMBLE +#define PREAMBLE +#endif + +#ifndef XCC +#define XCC xcc +#endif + +#define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9) \ + faligndata %f1, %f2, %f48; \ + faligndata %f2, %f3, %f50; \ + faligndata %f3, %f4, %f52; \ + faligndata %f4, %f5, %f54; \ + faligndata %f5, %f6, %f56; \ + faligndata %f6, %f7, %f58; \ + faligndata %f7, %f8, %f60; \ + faligndata %f8, %f9, %f62; + +#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt) \ + EX_LD(LOAD_BLK(%src, %fdest)); \ + EX_ST(STORE_BLK(%fsrc, %dest)); \ + add %src, 0x40, %src; \ + subcc %len, 0x40, %len; \ + be,pn %xcc, jmptgt; \ + add %dest, 0x40, %dest; \ + +#define LOOP_CHUNK1(src, dest, len, branch_dest) \ + MAIN_LOOP_CHUNK(src, dest, f0, f48, len, branch_dest) +#define LOOP_CHUNK2(src, dest, len, branch_dest) \ + MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest) +#define LOOP_CHUNK3(src, dest, len, branch_dest) \ + MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest) + +#define STORE_SYNC(dest, fsrc) \ + EX_ST(STORE_BLK(%fsrc, %dest)); \ + add %dest, 0x40, %dest; + +#define STORE_JUMP(dest, fsrc, target) \ + EX_ST(STORE_BLK(%fsrc, %dest)); \ + add %dest, 0x40, %dest; \ + ba,pt %xcc, target; + +#define FINISH_VISCHUNK(dest, f0, f1, left) \ + subcc %left, 8, %left;\ + bl,pn %xcc, 95f; \ + faligndata %f0, %f1, %f48; \ + EX_ST(STORE(std, %f48, %dest)); \ + add %dest, 8, %dest; + +#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left) \ + subcc %left, 8, %left; \ + bl,pn %xcc, 95f; \ + fsrc1 %f0, %f1; + +#define UNEVEN_VISCHUNK(dest, f0, f1, left) \ + UNEVEN_VISCHUNK_LAST(dest, f0, f1, left) \ + ba,a,pt %xcc, 93f; + + .register %g2,#scratch + .register %g3,#scratch + + .text + .align 64 + + .globl FUNC_NAME +FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ + PREAMBLE + mov %o0, %g5 + cmp %o2, 0 + be,pn %XCC, 85f + or %o0, %o1, %o3 + cmp %o2, 16 + blu,a,pn %XCC, 80f + or %o3, %o2, %o3 + + cmp %o2, (5 * 64) + blu,pt %XCC, 70f + andcc %o3, 0x7, %g0 + + /* Clobbers o5/g1/g2/g3/g7/icc/xcc. */ + VISEntry + + /* Is 'dst' already aligned on an 64-byte boundary? */ + andcc %o0, 0x3f, %g2 + be,pt %XCC, 2f + + /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number + * of bytes to copy to make 'dst' 64-byte aligned. We pre- + * subtract this from 'len'. + */ + sub %o0, %o1, %o4 + sub %g2, 0x40, %g2 + sub %g0, %g2, %g2 + sub %o2, %g2, %o2 + andcc %g2, 0x7, %g1 + be,pt %icc, 2f + and %g2, 0x38, %g2 + +1: subcc %g1, 0x1, %g1 + EX_LD(LOAD(ldub, %o1 + 0x00, %o3)) + EX_ST(STORE(stb, %o3, %o1 + %o4)) + bgu,pt %XCC, 1b + add %o1, 0x1, %o1 + + add %o1, %o4, %o0 + +2: cmp %g2, 0x0 + and %o1, 0x7, %g1 + be,pt %icc, 3f + alignaddr %o1, %g0, %o1 + + EX_LD(LOAD(ldd, %o1, %f4)) +1: EX_LD(LOAD(ldd, %o1 + 0x8, %f6)) + add %o1, 0x8, %o1 + subcc %g2, 0x8, %g2 + faligndata %f4, %f6, %f0 + EX_ST(STORE(std, %f0, %o0)) + be,pn %icc, 3f + add %o0, 0x8, %o0 + + EX_LD(LOAD(ldd, %o1 + 0x8, %f4)) + add %o1, 0x8, %o1 + subcc %g2, 0x8, %g2 + faligndata %f6, %f4, %f0 + EX_ST(STORE(std, %f0, %o0)) + bne,pt %icc, 1b + add %o0, 0x8, %o0 + + /* Destination is 64-byte aligned. */ +3: + membar #LoadStore | #StoreStore | #StoreLoad + + subcc %o2, 0x40, %o4 + add %o1, %g1, %g1 + andncc %o4, (0x40 - 1), %o4 + srl %g1, 3, %g2 + sub %o2, %o4, %g3 + andn %o1, (0x40 - 1), %o1 + and %g2, 7, %g2 + andncc %g3, 0x7, %g3 + fmovd %f0, %f2 + sub %g3, 0x8, %g3 + sub %o2, %o4, %o2 + + add %g1, %o4, %g1 + subcc %o2, %g3, %o2 + + EX_LD(LOAD_BLK(%o1, %f0)) + add %o1, 0x40, %o1 + add %g1, %g3, %g1 + EX_LD(LOAD_BLK(%o1, %f16)) + add %o1, 0x40, %o1 + sub %o4, 0x80, %o4 + EX_LD(LOAD_BLK(%o1, %f32)) + add %o1, 0x40, %o1 + + /* There are 8 instances of the unrolled loop, + * one for each possible alignment of the + * source buffer. Each loop instance is 452 + * bytes. + */ + sll %g2, 3, %o3 + sub %o3, %g2, %o3 + sllx %o3, 4, %o3 + add %o3, %g2, %o3 + sllx %o3, 2, %g2 +1: rd %pc, %o3 + add %o3, %lo(1f - 1b), %o3 + jmpl %o3 + %g2, %g0 + nop + + .align 64 +1: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) + LOOP_CHUNK1(o1, o0, o4, 1f) + FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) + LOOP_CHUNK2(o1, o0, o4, 2f) + FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) + LOOP_CHUNK3(o1, o0, o4, 3f) + ba,pt %xcc, 1b+4 + faligndata %f0, %f2, %f48 +1: FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) + STORE_JUMP(o0, f48, 40f) membar #Sync +2: FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) + STORE_JUMP(o0, f48, 48f) membar #Sync +3: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) + STORE_JUMP(o0, f48, 56f) membar #Sync + +1: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) + LOOP_CHUNK1(o1, o0, o4, 1f) + FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) + LOOP_CHUNK2(o1, o0, o4, 2f) + FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) + LOOP_CHUNK3(o1, o0, o4, 3f) + ba,pt %xcc, 1b+4 + faligndata %f2, %f4, %f48 +1: FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) + STORE_JUMP(o0, f48, 41f) membar #Sync +2: FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) + STORE_JUMP(o0, f48, 49f) membar #Sync +3: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) + STORE_JUMP(o0, f48, 57f) membar #Sync + +1: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) + LOOP_CHUNK1(o1, o0, o4, 1f) + FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) + LOOP_CHUNK2(o1, o0, o4, 2f) + FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) + LOOP_CHUNK3(o1, o0, o4, 3f) + ba,pt %xcc, 1b+4 + faligndata %f4, %f6, %f48 +1: FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) + STORE_JUMP(o0, f48, 42f) membar #Sync +2: FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) + STORE_JUMP(o0, f48, 50f) membar #Sync +3: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) + STORE_JUMP(o0, f48, 58f) membar #Sync + +1: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) + LOOP_CHUNK1(o1, o0, o4, 1f) + FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) + LOOP_CHUNK2(o1, o0, o4, 2f) + FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) + LOOP_CHUNK3(o1, o0, o4, 3f) + ba,pt %xcc, 1b+4 + faligndata %f6, %f8, %f48 +1: FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) + STORE_JUMP(o0, f48, 43f) membar #Sync +2: FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) + STORE_JUMP(o0, f48, 51f) membar #Sync +3: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) + STORE_JUMP(o0, f48, 59f) membar #Sync + +1: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) + LOOP_CHUNK1(o1, o0, o4, 1f) + FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) + LOOP_CHUNK2(o1, o0, o4, 2f) + FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) + LOOP_CHUNK3(o1, o0, o4, 3f) + ba,pt %xcc, 1b+4 + faligndata %f8, %f10, %f48 +1: FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) + STORE_JUMP(o0, f48, 44f) membar #Sync +2: FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) + STORE_JUMP(o0, f48, 52f) membar #Sync +3: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) + STORE_JUMP(o0, f48, 60f) membar #Sync + +1: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) + LOOP_CHUNK1(o1, o0, o4, 1f) + FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) + LOOP_CHUNK2(o1, o0, o4, 2f) + FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) + LOOP_CHUNK3(o1, o0, o4, 3f) + ba,pt %xcc, 1b+4 + faligndata %f10, %f12, %f48 +1: FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) + STORE_JUMP(o0, f48, 45f) membar #Sync +2: FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) + STORE_JUMP(o0, f48, 53f) membar #Sync +3: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) + STORE_JUMP(o0, f48, 61f) membar #Sync + +1: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) + LOOP_CHUNK1(o1, o0, o4, 1f) + FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) + LOOP_CHUNK2(o1, o0, o4, 2f) + FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) + LOOP_CHUNK3(o1, o0, o4, 3f) + ba,pt %xcc, 1b+4 + faligndata %f12, %f14, %f48 +1: FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) + STORE_JUMP(o0, f48, 46f) membar #Sync +2: FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) + STORE_JUMP(o0, f48, 54f) membar #Sync +3: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) + STORE_JUMP(o0, f48, 62f) membar #Sync + +1: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) + LOOP_CHUNK1(o1, o0, o4, 1f) + FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) + LOOP_CHUNK2(o1, o0, o4, 2f) + FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) + LOOP_CHUNK3(o1, o0, o4, 3f) + ba,pt %xcc, 1b+4 + faligndata %f14, %f16, %f48 +1: FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) + STORE_JUMP(o0, f48, 47f) membar #Sync +2: FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) + STORE_JUMP(o0, f48, 55f) membar #Sync +3: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) + STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) + STORE_JUMP(o0, f48, 63f) membar #Sync + +40: FINISH_VISCHUNK(o0, f0, f2, g3) +41: FINISH_VISCHUNK(o0, f2, f4, g3) +42: FINISH_VISCHUNK(o0, f4, f6, g3) +43: FINISH_VISCHUNK(o0, f6, f8, g3) +44: FINISH_VISCHUNK(o0, f8, f10, g3) +45: FINISH_VISCHUNK(o0, f10, f12, g3) +46: FINISH_VISCHUNK(o0, f12, f14, g3) +47: UNEVEN_VISCHUNK(o0, f14, f0, g3) +48: FINISH_VISCHUNK(o0, f16, f18, g3) +49: FINISH_VISCHUNK(o0, f18, f20, g3) +50: FINISH_VISCHUNK(o0, f20, f22, g3) +51: FINISH_VISCHUNK(o0, f22, f24, g3) +52: FINISH_VISCHUNK(o0, f24, f26, g3) +53: FINISH_VISCHUNK(o0, f26, f28, g3) +54: FINISH_VISCHUNK(o0, f28, f30, g3) +55: UNEVEN_VISCHUNK(o0, f30, f0, g3) +56: FINISH_VISCHUNK(o0, f32, f34, g3) +57: FINISH_VISCHUNK(o0, f34, f36, g3) +58: FINISH_VISCHUNK(o0, f36, f38, g3) +59: FINISH_VISCHUNK(o0, f38, f40, g3) +60: FINISH_VISCHUNK(o0, f40, f42, g3) +61: FINISH_VISCHUNK(o0, f42, f44, g3) +62: FINISH_VISCHUNK(o0, f44, f46, g3) +63: UNEVEN_VISCHUNK_LAST(o0, f46, f0, g3) + +93: EX_LD(LOAD(ldd, %o1, %f2)) + add %o1, 8, %o1 + subcc %g3, 8, %g3 + faligndata %f0, %f2, %f8 + EX_ST(STORE(std, %f8, %o0)) + bl,pn %xcc, 95f + add %o0, 8, %o0 + EX_LD(LOAD(ldd, %o1, %f0)) + add %o1, 8, %o1 + subcc %g3, 8, %g3 + faligndata %f2, %f0, %f8 + EX_ST(STORE(std, %f8, %o0)) + bge,pt %xcc, 93b + add %o0, 8, %o0 + +95: brz,pt %o2, 2f + mov %g1, %o1 + +1: EX_LD(LOAD(ldub, %o1, %o3)) + add %o1, 1, %o1 + subcc %o2, 1, %o2 + EX_ST(STORE(stb, %o3, %o0)) + bne,pt %xcc, 1b + add %o0, 1, %o0 + +2: membar #StoreLoad | #StoreStore + VISExit + retl + mov EX_RETVAL(%g5), %o0 + + .align 64 +70: /* 16 < len <= (5 * 64) */ + bne,pn %XCC, 75f + sub %o0, %o1, %o3 + +72: andn %o2, 0xf, %o4 + and %o2, 0xf, %o2 +1: EX_LD(LOAD(ldx, %o1 + 0x00, %o5)) + EX_LD(LOAD(ldx, %o1 + 0x08, %g1)) + subcc %o4, 0x10, %o4 + EX_ST(STORE(stx, %o5, %o1 + %o3)) + add %o1, 0x8, %o1 + EX_ST(STORE(stx, %g1, %o1 + %o3)) + bgu,pt %XCC, 1b + add %o1, 0x8, %o1 +73: andcc %o2, 0x8, %g0 + be,pt %XCC, 1f + nop + EX_LD(LOAD(ldx, %o1, %o5)) + sub %o2, 0x8, %o2 + EX_ST(STORE(stx, %o5, %o1 + %o3)) + add %o1, 0x8, %o1 +1: andcc %o2, 0x4, %g0 + be,pt %XCC, 1f + nop + EX_LD(LOAD(lduw, %o1, %o5)) + sub %o2, 0x4, %o2 + EX_ST(STORE(stw, %o5, %o1 + %o3)) + add %o1, 0x4, %o1 +1: cmp %o2, 0 + be,pt %XCC, 85f + nop + ba,pt %xcc, 90f + nop + +75: andcc %o0, 0x7, %g1 + sub %g1, 0x8, %g1 + be,pn %icc, 2f + sub %g0, %g1, %g1 + sub %o2, %g1, %o2 + +1: EX_LD(LOAD(ldub, %o1, %o5)) + subcc %g1, 1, %g1 + EX_ST(STORE(stb, %o5, %o1 + %o3)) + bgu,pt %icc, 1b + add %o1, 1, %o1 + +2: add %o1, %o3, %o0 + andcc %o1, 0x7, %g1 + bne,pt %icc, 8f + sll %g1, 3, %g1 + + cmp %o2, 16 + bgeu,pt %icc, 72b + nop + ba,a,pt %xcc, 73b + +8: mov 64, %o3 + andn %o1, 0x7, %o1 + EX_LD(LOAD(ldx, %o1, %g2)) + sub %o3, %g1, %o3 + andn %o2, 0x7, %o4 + sllx %g2, %g1, %g2 +1: EX_LD(LOAD(ldx, %o1 + 0x8, %g3)) + subcc %o4, 0x8, %o4 + add %o1, 0x8, %o1 + srlx %g3, %o3, %o5 + or %o5, %g2, %o5 + EX_ST(STORE(stx, %o5, %o0)) + add %o0, 0x8, %o0 + bgu,pt %icc, 1b + sllx %g3, %g1, %g2 + + srl %g1, 3, %g1 + andcc %o2, 0x7, %o2 + be,pn %icc, 85f + add %o1, %g1, %o1 + ba,pt %xcc, 90f + sub %o0, %o1, %o3 + + .align 64 +80: /* 0 < len <= 16 */ + andcc %o3, 0x3, %g0 + bne,pn %XCC, 90f + sub %o0, %o1, %o3 + +1: EX_LD(LOAD(lduw, %o1, %g1)) + subcc %o2, 4, %o2 + EX_ST(STORE(stw, %g1, %o1 + %o3)) + bgu,pt %XCC, 1b + add %o1, 4, %o1 + +85: retl + mov EX_RETVAL(%g5), %o0 + + .align 32 +90: EX_LD(LOAD(ldub, %o1, %g1)) + subcc %o2, 1, %o2 + EX_ST(STORE(stb, %g1, %o1 + %o3)) + bgu,pt %XCC, 90b + add %o1, 1, %o1 + retl + mov EX_RETVAL(%g5), %o0 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U3copy_from_user.S linux-2.4.28-pre3/arch/sparc64/lib/U3copy_from_user.S --- linux-2.4.27/arch/sparc64/lib/U3copy_from_user.S 2002-11-28 23:53:12.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/U3copy_from_user.S 2004-09-10 19:33:03.000000000 +0000 @@ -1,519 +1,22 @@ -/* $Id: U3copy_from_user.S,v 1.3.2.1 2002/01/15 07:17:47 davem Exp $ - * U3memcpy.S: UltraSparc-III optimized copy from userspace. +/* U3copy_from_user.S: UltraSparc-III optimized copy from userspace. * - * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com) + * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) */ -#ifdef __KERNEL__ -#include -#include -#include -#include -#undef SMALL_COPY_USES_FPU -#define EXNV(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - ba U3cfu_fixup; \ - a, b, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ +#define EX_LD(x) \ +98: x; \ + .section .fixup; \ + .align 4; \ +99: retl; \ + mov 1, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ .align 4; -#define EX(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - ba U3cfu_fixup; \ - a, b, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EX2(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o1; \ - add %o1, %o4, %o1; \ - ba U3cfu_fixup; \ - add %o1, 0x1c0, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EX3(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o1; \ - sll %g3, 6, %g3; \ - add %o1, 0x80, %o1; \ - ba U3cfu_fixup; \ - add %o1, %g3, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EX4(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o1; \ - add %o1, 0x40, %o1; \ - ba U3cfu_fixup; \ - add %o1, %g3, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#else -#define ASI_BLK_P 0xf0 -#define FPRS_FEF 0x04 -#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs -#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs -#define SMALL_COPY_USES_FPU -#define EXNV(x,y,a,b) x,y; -#define EX(x,y,a,b) x,y; -#define EX2(x,y) x,y; -#define EX3(x,y) x,y; -#define EX4(x,y) x,y; -#endif - - /* Special/non-trivial issues of this code: - * - * 1) %o5 is preserved from VISEntryHalf to VISExitHalf - * 2) Only low 32 FPU registers are used so that only the - * lower half of the FPU register set is dirtied by this - * code. This is especially important in the kernel. - * 3) This code never prefetches cachelines past the end - * of the source buffer. - */ - - .text - .align 32 - - /* The cheetah's flexible spine, oversized liver, enlarged heart, - * slender muscular body, and claws make it the swiftest hunter - * in Africa and the fastest animal on land. Can reach speeds - * of up to 2.4GB per second. - */ - - .globl U3copy_from_user -U3copy_from_user: /* %o0=dst, %o1=src, %o2=len */ -#ifndef __KERNEL__ - /* Save away original 'dst' for memcpy return value. */ - mov %o0, %g3 ! A0 Group -#endif - /* Anything to copy at all? */ - cmp %o2, 0 ! A1 - ble,pn %icc, U3copy_from_user_short_ret! BR - - /* Extremely small copy? */ - cmp %o2, 31 ! A0 Group - ble,pn %icc, U3copy_from_user_short ! BR - - /* Large enough to use unrolled prefetch loops? */ - cmp %o2, 0x100 ! A1 - bge,a,pt %icc, U3copy_from_user_enter ! BR Group - andcc %o0, 0x3f, %g2 ! A0 - - ba,pt %xcc, U3copy_from_user_toosmall ! BR Group - andcc %o0, 0x7, %g2 ! A0 - - .align 32 -U3copy_from_user_short: - /* Copy %o2 bytes from src to dst, one byte at a time. */ - EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g0)! MS Group - add %o1, 0x1, %o1 ! A0 - add %o0, 0x1, %o0 ! A1 - subcc %o2, 1, %o2 ! A0 Group - - bg,pt %icc, U3copy_from_user_short ! BR - stb %o3, [%o0 + -1] ! MS Group (1-cycle stall) - -U3copy_from_user_short_ret: -#ifdef __KERNEL__ - retl ! BR Group (0-4 cycle stall) - clr %o0 ! A0 -#else - retl ! BR Group (0-4 cycle stall) - mov %g3, %o0 ! A0 -#endif - - /* Here len >= (6 * 64) and condition codes reflect execution - * of "andcc %o0, 0x7, %g2", done by caller. - */ - .align 64 -U3copy_from_user_enter: - /* Is 'dst' already aligned on an 64-byte boundary? */ - be,pt %xcc, 2f ! BR - - /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number - * of bytes to copy to make 'dst' 64-byte aligned. We pre- - * subtract this from 'len'. - */ - sub %g2, 0x40, %g2 ! A0 Group - sub %g0, %g2, %g2 ! A0 Group - sub %o2, %g2, %o2 ! A0 Group - - /* Copy %g2 bytes from src to dst, one byte at a time. */ -1: EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS (Group) - add %o1, 0x1, %o1 ! A1 - add %o0, 0x1, %o0 ! A0 Group - subcc %g2, 0x1, %g2 ! A1 - - bg,pt %icc, 1b ! BR Group - stb %o3, [%o0 + -1] ! MS Group - -2: VISEntryHalf ! MS+MS - and %o1, 0x7, %g1 ! A1 - ba,pt %xcc, U3copy_from_user_begin ! BR - alignaddr %o1, %g0, %o1 ! MS (Break-after) - - .align 64 -U3copy_from_user_begin: -#ifdef __KERNEL__ - .globl U3copy_from_user_nop_1_6 -U3copy_from_user_nop_1_6: - ldxa [%g0] ASI_DCU_CONTROL_REG, %g3 - sethi %uhi(DCU_PE), %o3 - sllx %o3, 32, %o3 - or %g3, %o3, %o3 - stxa %o3, [%g0] ASI_DCU_CONTROL_REG ! Enable P-cache - membar #Sync -#endif - prefetcha [%o1 + 0x000] %asi, #one_read ! MS Group1 - prefetcha [%o1 + 0x040] %asi, #one_read ! MS Group2 - andn %o2, (0x40 - 1), %o4 ! A0 - prefetcha [%o1 + 0x080] %asi, #one_read ! MS Group3 - cmp %o4, 0x140 ! A0 - prefetcha [%o1 + 0x0c0] %asi, #one_read ! MS Group4 - EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0) ! MS Group5 (%f0 results at G8) - bge,a,pt %icc, 1f ! BR - - prefetcha [%o1 + 0x100] %asi, #one_read ! MS Group6 -1: EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0) ! AX (%f2 results at G9) - cmp %o4, 0x180 ! A1 - bge,a,pt %icc, 1f ! BR - prefetcha [%o1 + 0x140] %asi, #one_read ! MS Group7 -1: EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0) ! AX (%f4 results at G10) - cmp %o4, 0x1c0 ! A1 - bge,a,pt %icc, 1f ! BR - - prefetcha [%o1 + 0x180] %asi, #one_read ! MS Group8 -1: faligndata %f0, %f2, %f16 ! FGA Group9 (%f16 at G12) - EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0) ! AX (%f6 results at G12) - faligndata %f2, %f4, %f18 ! FGA Group10 (%f18 results at G13) - EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0) ! MS (%f8 results at G13) - faligndata %f4, %f6, %f20 ! FGA Group12 (1-cycle stall,%f20 at G15) - EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0) ! MS (%f10 results at G15) - faligndata %f6, %f8, %f22 ! FGA Group13 (%f22 results at G16) - - EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0) ! MS (%f12 results at G16) - faligndata %f8, %f10, %f24 ! FGA Group15 (1-cycle stall,%f24 at G18) - EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0) ! MS (%f14 results at G18) - faligndata %f10, %f12, %f26 ! FGA Group16 (%f26 results at G19) - EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0) ! MS (%f0 results at G19) - - /* We only use the first loop if len > (7 * 64). */ - subcc %o4, 0x1c0, %o4 ! A0 Group17 - bg,pt %icc, U3copy_from_user_loop1 ! BR - add %o1, 0x40, %o1 ! A1 - - add %o4, 0x140, %o4 ! A0 Group18 - ba,pt %xcc, U3copy_from_user_loop2 ! BR - srl %o4, 6, %o3 ! A0 Group19 - nop - nop - nop - nop - nop - - nop - nop - - /* This loop performs the copy and queues new prefetches. - * We drop into the second loop when len <= (5 * 64). Note - * that this (5 * 64) factor has been subtracted from len - * already. - */ -U3copy_from_user_loop1: - EX2(ldda [%o1 + 0x008] %asi, %f2) ! MS Group2 (%f2 results at G5) - faligndata %f12, %f14, %f28 ! FGA (%f28 results at G5) - EX2(ldda [%o1 + 0x010] %asi, %f4) ! MS Group3 (%f4 results at G6) - faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall, %f30 at G7) - stda %f16, [%o0] ASI_BLK_P ! MS - EX2(ldda [%o1 + 0x018] %asi, %f6) ! AX (%f6 results at G7) - - faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) - EX2(ldda [%o1 + 0x020] %asi, %f8) ! MS (%f8 results at G15) - faligndata %f2, %f4, %f18 ! FGA Group13 (%f18 results at G16) - EX2(ldda [%o1 + 0x028] %asi, %f10) ! MS (%f10 results at G16) - faligndata %f4, %f6, %f20 ! FGA Group14 (%f20 results at G17) - EX2(ldda [%o1 + 0x030] %asi, %f12) ! MS (%f12 results at G17) - faligndata %f6, %f8, %f22 ! FGA Group15 (%f22 results at G18) - EX2(ldda [%o1 + 0x038] %asi, %f14) ! MS (%f14 results at G18) - - faligndata %f8, %f10, %f24 ! FGA Group16 (%f24 results at G19) - EX2(ldda [%o1 + 0x040] %asi, %f0) ! AX (%f0 results at G19) - prefetcha [%o1 + 0x180] %asi, #one_read ! MS - faligndata %f10, %f12, %f26 ! FGA Group17 (%f26 results at G20) - subcc %o4, 0x40, %o4 ! A0 - add %o1, 0x40, %o1 ! A1 - bg,pt %xcc, U3copy_from_user_loop1 ! BR - add %o0, 0x40, %o0 ! A0 Group18 - -U3copy_from_user_loop2_enter: - mov 5, %o3 ! A1 - - /* This loop performs on the copy, no new prefetches are - * queued. We do things this way so that we do not perform - * any spurious prefetches past the end of the src buffer. - */ -U3copy_from_user_loop2: - EX3(ldda [%o1 + 0x008] %asi, %f2) ! MS - faligndata %f12, %f14, %f28 ! FGA Group2 - EX3(ldda [%o1 + 0x010] %asi, %f4) ! MS - faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall) - stda %f16, [%o0] ASI_BLK_P ! MS - EX3(ldda [%o1 + 0x018] %asi, %f6) ! AX - faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) - - EX3(ldda [%o1 + 0x020] %asi, %f8) ! MS - faligndata %f2, %f4, %f18 ! FGA Group13 - EX3(ldda [%o1 + 0x028] %asi, %f10) ! MS - faligndata %f4, %f6, %f20 ! FGA Group14 - EX3(ldda [%o1 + 0x030] %asi, %f12) ! MS - faligndata %f6, %f8, %f22 ! FGA Group15 - EX3(ldda [%o1 + 0x038] %asi, %f14) ! MS - faligndata %f8, %f10, %f24 ! FGA Group16 - - EX3(ldda [%o1 + 0x040] %asi, %f0) ! AX - faligndata %f10, %f12, %f26 ! FGA Group17 - subcc %o3, 0x01, %o3 ! A0 - add %o1, 0x40, %o1 ! A1 - bg,pt %xcc, U3copy_from_user_loop2 ! BR - add %o0, 0x40, %o0 ! A0 Group18 - - /* Finally we copy the last full 64-byte block. */ -U3copy_from_user_loopfini: - EX3(ldda [%o1 + 0x008] %asi, %f2) ! MS - faligndata %f12, %f14, %f28 ! FGA - EX3(ldda [%o1 + 0x010] %asi, %f4) ! MS Group19 - faligndata %f14, %f0, %f30 ! FGA - stda %f16, [%o0] ASI_BLK_P ! MS Group20 - EX3(ldda [%o1 + 0x018] %asi, %f6) ! AX - faligndata %f0, %f2, %f16 ! FGA Group11 (7-cycle stall) - EX3(ldda [%o1 + 0x020] %asi, %f8) ! MS - faligndata %f2, %f4, %f18 ! FGA Group12 - EX3(ldda [%o1 + 0x028] %asi, %f10) ! MS - faligndata %f4, %f6, %f20 ! FGA Group13 - EX3(ldda [%o1 + 0x030] %asi, %f12) ! MS - faligndata %f6, %f8, %f22 ! FGA Group14 - EX3(ldda [%o1 + 0x038] %asi, %f14) ! MS - faligndata %f8, %f10, %f24 ! FGA Group15 - cmp %g1, 0 ! A0 - be,pt %icc, 1f ! BR - add %o0, 0x40, %o0 ! A1 - EX4(ldda [%o1 + 0x040] %asi, %f0) ! MS -1: faligndata %f10, %f12, %f26 ! FGA Group16 - faligndata %f12, %f14, %f28 ! FGA Group17 - faligndata %f14, %f0, %f30 ! FGA Group18 - stda %f16, [%o0] ASI_BLK_P ! MS - add %o0, 0x40, %o0 ! A0 - add %o1, 0x40, %o1 ! A1 -#ifdef __KERNEL__ - .globl U3copy_from_user_nop_2_3 -U3copy_from_user_nop_2_3: - mov PRIMARY_CONTEXT, %o3 - stxa %g0, [%o3] ASI_DMMU ! Flush P-cache - stxa %g3, [%g0] ASI_DCU_CONTROL_REG ! Disable P-cache -#endif - membar #Sync ! MS Group26 (7-cycle stall) - - /* Now we copy the (len modulo 64) bytes at the end. - * Note how we borrow the %f0 loaded above. - * - * Also notice how this code is careful not to perform a - * load past the end of the src buffer just like similar - * code found in U3copy_from_user_toosmall processing. - */ -U3copy_from_user_loopend: - and %o2, 0x3f, %o2 ! A0 Group - andcc %o2, 0x38, %g2 ! A0 Group - be,pn %icc, U3copy_from_user_endcruft ! BR - subcc %g2, 0x8, %g2 ! A1 - be,pn %icc, U3copy_from_user_endcruft ! BR Group - cmp %g1, 0 ! A0 - - be,a,pt %icc, 1f ! BR Group - EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0) ! MS - -1: EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0) ! MS Group - add %o1, 0x8, %o1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f0, %f2, %f8 ! FGA Group - std %f8, [%o0 + 0x00] ! MS (XXX does it stall here? XXX) - be,pn %icc, U3copy_from_user_endcruft ! BR - add %o0, 0x8, %o0 ! A0 - EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0) ! MS Group - add %o1, 0x8, %o1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f2, %f0, %f8 ! FGA - std %f8, [%o0 + 0x00] ! MS (XXX does it stall here? XXX) - bne,pn %icc, 1b ! BR - add %o0, 0x8, %o0 ! A0 Group - - /* If anything is left, we copy it one byte at a time. - * Note that %g1 is (src & 0x3) saved above before the - * alignaddr was performed. - */ -U3copy_from_user_endcruft: - cmp %o2, 0 - add %o1, %g1, %o1 - VISExitHalf - be,pn %icc, U3copy_from_user_short_ret - nop - ba,a,pt %xcc, U3copy_from_user_short - - /* If we get here, then 32 <= len < (6 * 64) */ -U3copy_from_user_toosmall: - -#ifdef SMALL_COPY_USES_FPU - - /* Is 'dst' already aligned on an 8-byte boundary? */ - be,pt %xcc, 2f ! BR Group - - /* Compute abs((dst & 7) - 8) into %g2. This is the number - * of bytes to copy to make 'dst' 8-byte aligned. We pre- - * subtract this from 'len'. - */ - sub %g2, 0x8, %g2 ! A0 - sub %g0, %g2, %g2 ! A0 Group (reg-dep) - sub %o2, %g2, %o2 ! A0 Group (reg-dep) - - /* Copy %g2 bytes from src to dst, one byte at a time. */ -1: EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS (Group) (%o3 in 3 cycles) - add %o1, 0x1, %o1 ! A1 - add %o0, 0x1, %o0 ! A0 Group - subcc %g2, 0x1, %g2 ! A1 - - bg,pt %icc, 1b ! BR Group - stb %o3, [%o0 + -1] ! MS Group - -2: VISEntryHalf ! MS+MS - - /* Compute (len - (len % 8)) into %g2. This is guarenteed - * to be nonzero. - */ - andn %o2, 0x7, %g2 ! A0 Group - - /* You may read this and believe that it allows reading - * one 8-byte longword past the end of src. It actually - * does not, as %g2 is subtracted as loads are done from - * src, so we always stop before running off the end. - * Also, we are guarenteed to have at least 0x10 bytes - * to move here. - */ - sub %g2, 0x8, %g2 ! A0 Group (reg-dep) - alignaddr %o1, %g0, %g1 ! MS (Break-after) - EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0) ! MS Group (1-cycle stall) - add %g1, 0x8, %g1 ! A0 - -1: EX(ldda [%g1 + 0x00] %asi, %f2, add %o2, %g0) ! MS Group - add %g1, 0x8, %g1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - - faligndata %f0, %f2, %f8 ! FGA Group (1-cycle stall) - std %f8, [%o0 + 0x00] ! MS Group (2-cycle stall) - add %o1, 0x8, %o1 ! A0 - be,pn %icc, 2f ! BR - - add %o0, 0x8, %o0 ! A1 - EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0) ! MS Group - add %g1, 0x8, %g1 ! A0 - sub %o2, 0x8, %o2 ! A1 - - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f2, %f0, %f8 ! FGA Group (1-cycle stall) - std %f8, [%o0 + 0x00] ! MS Group (2-cycle stall) - add %o1, 0x8, %o1 ! A0 - - bne,pn %icc, 1b ! BR - add %o0, 0x8, %o0 ! A1 - - /* Nothing left to copy? */ -2: cmp %o2, 0 ! A0 Group - VISExitHalf ! A0+MS - be,pn %icc, U3copy_from_user_short_ret! BR Group - nop ! A0 - ba,a,pt %xcc, U3copy_from_user_short ! BR Group - -#else /* !(SMALL_COPY_USES_FPU) */ - - xor %o1, %o0, %g2 - andcc %g2, 0x7, %g0 - bne,pn %icc, U3copy_from_user_short - andcc %o1, 0x7, %g2 - - be,pt %xcc, 2f - sub %g2, 0x8, %g2 - sub %g0, %g2, %g2 - sub %o2, %g2, %o2 - -1: EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2) - add %o1, 0x1, %o1 - add %o0, 0x1, %o0 - subcc %g2, 0x1, %g2 - bg,pt %icc, 1b - stb %o3, [%o0 + -1] - -2: andn %o2, 0x7, %g2 - sub %o2, %g2, %o2 - -3: EXNV(ldxa [%o1 + 0x00] %asi, %o3, add %o2, %g2) - add %o1, 0x8, %o1 - add %o0, 0x8, %o0 - subcc %g2, 0x8, %g2 - bg,pt %icc, 3b - stx %o3, [%o0 + -8] - - cmp %o2, 0 - bne,pn %icc, U3copy_from_user_short - nop - ba,a,pt %xcc, U3copy_from_user_short_ret - -#endif /* !(SMALL_COPY_USES_FPU) */ - -#ifdef __KERNEL__ - .globl U3cfu_fixup -U3cfu_fixup: - /* Since this is copy_from_user(), zero out the rest of the - * kernel buffer. - */ - cmp %o1, 0 - ble,pn %icc, 2f - mov %o1, %g2 -1: subcc %g2, 1, %g2 - stb %g0, [%o0] - bne,pt %icc, 1b - add %o0, 1, %o0 +#define FUNC_NAME U3copy_from_user +#define LOAD(type,addr,dest) type##a [addr] %asi, dest +#define EX_RETVAL(x) 0 -2: retl - mov %o1, %o0 -#endif +#include "U3memcpy.S" diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U3copy_in_user.S linux-2.4.28-pre3/arch/sparc64/lib/U3copy_in_user.S --- linux-2.4.27/arch/sparc64/lib/U3copy_in_user.S 2001-03-26 02:14:21.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/U3copy_in_user.S 1970-01-01 00:00:00.000000000 +0000 @@ -1,531 +0,0 @@ -/* $Id: U3copy_in_user.S,v 1.4 2001/03/21 05:58:47 davem Exp $ - * U3memcpy.S: UltraSparc-III optimized copy within userspace. - * - * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com) - */ - -#ifdef __KERNEL__ -#include -#include -#undef SMALL_COPY_USES_FPU -#define EXNV(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: retl; \ - a, b, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXNV2(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: a, b, %o0; \ - retl; \ - add %o0, 1, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXNV3(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: a, b, %o0; \ - retl; \ - add %o0, 8, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EX(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - retl; \ - a, b, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXBLK1(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - add %o4, 0x1c0, %o1; \ - and %o2, (0x40 - 1), %o2; \ - retl; \ - add %o1, %o2, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXBLK2(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - sll %o3, 6, %o3; \ - and %o2, (0x40 - 1), %o2; \ - add %o3, 0x80, %o1; \ - retl; \ - add %o1, %o2, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXBLK3(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o2; \ - retl; \ - add %o2, 0x80, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXBLK4(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o2; \ - retl; \ - add %o2, 0x40, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#else -#define ASI_AIUS 0x80 -#define ASI_BLK_AIUS 0xf0 -#define FPRS_FEF 0x04 -#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs -#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs -#define SMALL_COPY_USES_FPU -#define EXNV(x,y,a,b) x,y; -#define EXNV2(x,y,a,b) x,y; -#define EXNV3(x,y,a,b) x,y; -#define EX(x,y,a,b) x,y; -#define EXBLK1(x,y) x,y; -#define EXBLK2(x,y) x,y; -#define EXBLK3(x,y) x,y; -#define EXBLK4(x,y) x,y; -#endif - - /* Special/non-trivial issues of this code: - * - * 1) %o5 is preserved from VISEntryHalf to VISExitHalf - * 2) Only low 32 FPU registers are used so that only the - * lower half of the FPU register set is dirtied by this - * code. This is especially important in the kernel. - * 3) This code never prefetches cachelines past the end - * of the source buffer. - * - * XXX Actually, Cheetah can buffer up to 8 concurrent - * XXX prefetches, revisit this... - */ - - .text - .align 32 - - /* The cheetah's flexible spine, oversized liver, enlarged heart, - * slender muscular body, and claws make it the swiftest hunter - * in Africa and the fastest animal on land. Can reach speeds - * of up to 2.4GB per second. - */ - - .globl U3copy_in_user -U3copy_in_user: /* %o0=dst, %o1=src, %o2=len */ - /* Writing to %asi is _expensive_ so we hardcode it. - * Reading %asi to check for KERNEL_DS is comparatively - * cheap. - */ - rd %asi, %g1 ! MS Group (4 cycles) - cmp %g1, ASI_AIUS ! A0 Group - bne U3memcpy ! BR - nop ! A1 -#ifndef __KERNEL__ - /* Save away original 'dst' for memcpy return value. */ - mov %o0, %g3 ! A0 Group -#endif - /* Anything to copy at all? */ - cmp %o2, 0 ! A1 - ble,pn %icc, U3copy_in_user_short_ret ! BR - - /* Extremely small copy? */ - cmp %o2, 31 ! A0 Group - ble,pn %icc, U3copy_in_user_short ! BR - - /* Large enough to use unrolled prefetch loops? */ - cmp %o2, 0x100 ! A1 - bge,a,pt %icc, U3copy_in_user_enter ! BR Group - andcc %o0, 0x3f, %g2 ! A0 - - ba,pt %xcc, U3copy_in_user_toosmall ! BR Group - andcc %o0, 0x7, %g2 ! A0 - - .align 32 -U3copy_in_user_short: - /* Copy %o2 bytes from src to dst, one byte at a time. */ - EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g0)! MS Group - add %o1, 0x1, %o1 ! A0 - add %o0, 0x1, %o0 ! A1 - subcc %o2, 1, %o2 ! A0 Group - - bg,pt %icc, U3copy_in_user_short ! BR - EXNV(stba %o3, [%o0 + -1] %asi, add %o2, 1) ! MS Group (1-cycle stall) - -U3copy_in_user_short_ret: -#ifdef __KERNEL__ - retl ! BR Group (0-4 cycle stall) - clr %o0 ! A0 -#else - retl ! BR Group (0-4 cycle stall) - mov %g3, %o0 ! A0 -#endif - - /* Here len >= (6 * 64) and condition codes reflect execution - * of "andcc %o0, 0x7, %g2", done by caller. - */ - .align 64 -U3copy_in_user_enter: - /* Is 'dst' already aligned on an 64-byte boundary? */ - be,pt %xcc, 2f ! BR - - /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number - * of bytes to copy to make 'dst' 64-byte aligned. We pre- - * subtract this from 'len'. - */ - sub %g2, 0x40, %g2 ! A0 Group - sub %g0, %g2, %g2 ! A0 Group - sub %o2, %g2, %o2 ! A0 Group - - /* Copy %g2 bytes from src to dst, one byte at a time. */ -1: EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS (Group) - add %o1, 0x1, %o1 ! A1 - add %o0, 0x1, %o0 ! A0 Group - subcc %g2, 0x1, %g2 ! A1 - - bg,pt %icc, 1b ! BR Group - EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS Group - -2: VISEntryHalf ! MS+MS - and %o1, 0x7, %g1 ! A1 - ba,pt %xcc, U3copy_in_user_begin ! BR - alignaddr %o1, %g0, %o1 ! MS (Break-after) - - .align 64 -U3copy_in_user_begin: - prefetcha [%o1 + 0x000] %asi, #one_read ! MS Group1 - prefetcha [%o1 + 0x040] %asi, #one_read ! MS Group2 - andn %o2, (0x40 - 1), %o4 ! A0 - prefetcha [%o1 + 0x080] %asi, #one_read ! MS Group3 - cmp %o4, 0x140 ! A0 - prefetcha [%o1 + 0x0c0] %asi, #one_read ! MS Group4 - EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0) ! MS Group5 (%f0 results at G8) - bge,a,pt %icc, 1f ! BR - - prefetcha [%o1 + 0x100] %asi, #one_read ! MS Group6 -1: EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0) ! AX (%f2 results at G9) - cmp %o4, 0x180 ! A1 - bge,a,pt %icc, 1f ! BR - prefetcha [%o1 + 0x140] %asi, #one_read ! MS Group7 -1: EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0) ! AX (%f4 results at G10) - cmp %o4, 0x1c0 ! A1 - bge,a,pt %icc, 1f ! BR - - prefetcha [%o1 + 0x180] %asi, #one_read ! MS Group8 -1: faligndata %f0, %f2, %f16 ! FGA Group9 (%f16 at G12) - EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0) ! AX (%f6 results at G12) - faligndata %f2, %f4, %f18 ! FGA Group10 (%f18 results at G13) - EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0) ! MS (%f8 results at G13) - faligndata %f4, %f6, %f20 ! FGA Group12 (1-cycle stall,%f20 at G15) - EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0) ! MS (%f10 results at G15) - faligndata %f6, %f8, %f22 ! FGA Group13 (%f22 results at G16) - - EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0) ! MS (%f12 results at G16) - faligndata %f8, %f10, %f24 ! FGA Group15 (1-cycle stall,%f24 at G18) - EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0) ! MS (%f14 results at G18) - faligndata %f10, %f12, %f26 ! FGA Group16 (%f26 results at G19) - EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0) ! MS (%f0 results at G19) - - /* We only use the first loop if len > (7 * 64). */ - subcc %o4, 0x1c0, %o4 ! A0 Group17 - bg,pt %icc, U3copy_in_user_loop1 ! BR - add %o1, 0x40, %o1 ! A1 - - add %o4, 0x140, %o4 ! A0 Group18 - ba,pt %xcc, U3copy_in_user_loop2 ! BR - srl %o4, 6, %o3 ! A0 Group19 - nop - nop - nop - nop - nop - - nop - nop - - /* This loop performs the copy and queues new prefetches. - * We drop into the second loop when len <= (5 * 64). Note - * that this (5 * 64) factor has been subtracted from len - * already. - */ -U3copy_in_user_loop1: - EXBLK1(ldda [%o1 + 0x008] %asi, %f2) ! MS Group2 (%f2 results at G5) - faligndata %f12, %f14, %f28 ! FGA (%f28 results at G5) - EXBLK1(ldda [%o1 + 0x010] %asi, %f4) ! MS Group3 (%f4 results at G6) - faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall, %f30 at G7) - EXBLK1(stda %f16, [%o0] ASI_BLK_AIUS) ! MS - EXBLK1(ldda [%o1 + 0x018] %asi, %f6) ! AX (%f6 results at G7) - - faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) - EXBLK1(ldda [%o1 + 0x020] %asi, %f8) ! MS (%f8 results at G15) - faligndata %f2, %f4, %f18 ! FGA Group13 (%f18 results at G16) - EXBLK1(ldda [%o1 + 0x028] %asi, %f10) ! MS (%f10 results at G16) - faligndata %f4, %f6, %f20 ! FGA Group14 (%f20 results at G17) - EXBLK1(ldda [%o1 + 0x030] %asi, %f12) ! MS (%f12 results at G17) - faligndata %f6, %f8, %f22 ! FGA Group15 (%f22 results at G18) - EXBLK1(ldda [%o1 + 0x038] %asi, %f14) ! MS (%f14 results at G18) - - faligndata %f8, %f10, %f24 ! FGA Group16 (%f24 results at G19) - EXBLK1(ldda [%o1 + 0x040] %asi, %f0) ! AX (%f0 results at G19) - prefetcha [%o1 + 0x180] %asi, #one_read ! MS - faligndata %f10, %f12, %f26 ! FGA Group17 (%f26 results at G20) - subcc %o4, 0x40, %o4 ! A0 - add %o1, 0x40, %o1 ! A1 - bg,pt %xcc, U3copy_in_user_loop1 ! BR - add %o0, 0x40, %o0 ! A0 Group18 - -U3copy_in_user_loop2_enter: - mov 5, %o3 ! A1 - - /* This loop performs on the copy, no new prefetches are - * queued. We do things this way so that we do not perform - * any spurious prefetches past the end of the src buffer. - */ -U3copy_in_user_loop2: - EXBLK2(ldda [%o1 + 0x008] %asi, %f2) ! MS - faligndata %f12, %f14, %f28 ! FGA Group2 - EXBLK2(ldda [%o1 + 0x010] %asi, %f4) ! MS - faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall) - EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS) ! MS - EXBLK2(ldda [%o1 + 0x018] %asi, %f6) ! AX - faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) - - EXBLK2(ldda [%o1 + 0x020] %asi, %f8) ! MS - faligndata %f2, %f4, %f18 ! FGA Group13 - EXBLK2(ldda [%o1 + 0x028] %asi, %f10) ! MS - faligndata %f4, %f6, %f20 ! FGA Group14 - EXBLK2(ldda [%o1 + 0x030] %asi, %f12) ! MS - faligndata %f6, %f8, %f22 ! FGA Group15 - EXBLK2(ldda [%o1 + 0x038] %asi, %f14) ! MS - faligndata %f8, %f10, %f24 ! FGA Group16 - - EXBLK2(ldda [%o1 + 0x040] %asi, %f0) ! AX - faligndata %f10, %f12, %f26 ! FGA Group17 - subcc %o3, 0x01, %o3 ! A0 - add %o1, 0x40, %o1 ! A1 - bg,pt %xcc, U3copy_in_user_loop2 ! BR - add %o0, 0x40, %o0 ! A0 Group18 - - /* Finally we copy the last full 64-byte block. */ -U3copy_in_user_loopfini: - EXBLK3(ldda [%o1 + 0x008] %asi, %f2) ! MS - faligndata %f12, %f14, %f28 ! FGA - EXBLK3(ldda [%o1 + 0x010] %asi, %f4) ! MS Group19 - faligndata %f14, %f0, %f30 ! FGA - EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS) ! MS Group20 - EXBLK4(ldda [%o1 + 0x018] %asi, %f6) ! AX - faligndata %f0, %f2, %f16 ! FGA Group11 (7-cycle stall) - EXBLK4(ldda [%o1 + 0x020] %asi, %f8) ! MS - faligndata %f2, %f4, %f18 ! FGA Group12 - EXBLK4(ldda [%o1 + 0x028] %asi, %f10) ! MS - faligndata %f4, %f6, %f20 ! FGA Group13 - EXBLK4(ldda [%o1 + 0x030] %asi, %f12) ! MS - faligndata %f6, %f8, %f22 ! FGA Group14 - EXBLK4(ldda [%o1 + 0x038] %asi, %f14) ! MS - faligndata %f8, %f10, %f24 ! FGA Group15 - cmp %g1, 0 ! A0 - be,pt %icc, 1f ! BR - add %o0, 0x40, %o0 ! A1 - EXBLK4(ldda [%o1 + 0x040] %asi, %f0) ! MS -1: faligndata %f10, %f12, %f26 ! FGA Group16 - faligndata %f12, %f14, %f28 ! FGA Group17 - faligndata %f14, %f0, %f30 ! FGA Group18 - EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS) ! MS - add %o0, 0x40, %o0 ! A0 - add %o1, 0x40, %o1 ! A1 - membar #Sync ! MS Group26 (7-cycle stall) - - /* Now we copy the (len modulo 64) bytes at the end. - * Note how we borrow the %f0 loaded above. - * - * Also notice how this code is careful not to perform a - * load past the end of the src buffer just like similar - * code found in U3copy_in_user_toosmall processing. - */ -U3copy_in_user_loopend: - and %o2, 0x3f, %o2 ! A0 Group - andcc %o2, 0x38, %g2 ! A0 Group - be,pn %icc, U3copy_in_user_endcruft ! BR - subcc %g2, 0x8, %g2 ! A1 - be,pn %icc, U3copy_in_user_endcruft ! BR Group - cmp %g1, 0 ! A0 - - be,a,pt %icc, 1f ! BR Group - EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0) ! MS - -1: EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0) ! MS Group - add %o1, 0x8, %o1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f0, %f2, %f8 ! FGA Group - EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS (XXX does it stall here? XXX) - be,pn %icc, U3copy_in_user_endcruft ! BR - add %o0, 0x8, %o0 ! A0 - EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0) ! MS Group - add %o1, 0x8, %o1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f2, %f0, %f8 ! FGA - EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS (XXX does it stall here? XXX) - bne,pn %icc, 1b ! BR - add %o0, 0x8, %o0 ! A0 Group - - /* If anything is left, we copy it one byte at a time. - * Note that %g1 is (src & 0x3) saved above before the - * alignaddr was performed. - */ -U3copy_in_user_endcruft: - cmp %o2, 0 - add %o1, %g1, %o1 - VISExitHalf - be,pn %icc, U3copy_in_user_short_ret - nop - ba,a,pt %xcc, U3copy_in_user_short - - /* If we get here, then 32 <= len < (6 * 64) */ -U3copy_in_user_toosmall: - -#ifdef SMALL_COPY_USES_FPU - - /* Is 'dst' already aligned on an 8-byte boundary? */ - be,pt %xcc, 2f ! BR Group - - /* Compute abs((dst & 7) - 8) into %g2. This is the number - * of bytes to copy to make 'dst' 8-byte aligned. We pre- - * subtract this from 'len'. - */ - sub %g2, 0x8, %g2 ! A0 - sub %g0, %g2, %g2 ! A0 Group (reg-dep) - sub %o2, %g2, %o2 ! A0 Group (reg-dep) - - /* Copy %g2 bytes from src to dst, one byte at a time. */ -1: EXNV2(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS (Group) (%o3 in 3 cycles) - add %o1, 0x1, %o1 ! A1 - add %o0, 0x1, %o0 ! A0 Group - subcc %g2, 0x1, %g2 ! A1 - - bg,pt %icc, 1b ! BR Group - EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS Group - -2: VISEntryHalf ! MS+MS - - /* Compute (len - (len % 8)) into %g2. This is guarenteed - * to be nonzero. - */ - andn %o2, 0x7, %g2 ! A0 Group - - /* You may read this and believe that it allows reading - * one 8-byte longword past the end of src. It actually - * does not, as %g2 is subtracted as loads are done from - * src, so we always stop before running off the end. - * Also, we are guarenteed to have at least 0x10 bytes - * to move here. - */ - sub %g2, 0x8, %g2 ! A0 Group (reg-dep) - alignaddr %o1, %g0, %g1 ! MS (Break-after) - EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0) ! MS Group (1-cycle stall) - add %g1, 0x8, %g1 ! A0 - -1: EX(ldda [%g1 + 0x00] %asi, %f2, add %o2, %g0) ! MS Group - add %g1, 0x8, %g1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - - faligndata %f0, %f2, %f8 ! FGA Group (1-cycle stall) - EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS Group (2-cycle stall) - add %o1, 0x8, %o1 ! A0 - be,pn %icc, 2f ! BR - - add %o0, 0x8, %o0 ! A1 - EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0) ! MS Group - add %g1, 0x8, %g1 ! A0 - sub %o2, 0x8, %o2 ! A1 - - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f2, %f0, %f8 ! FGA Group (1-cycle stall) - EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS Group (2-cycle stall) - add %o1, 0x8, %o1 ! A0 - - bne,pn %icc, 1b ! BR - add %o0, 0x8, %o0 ! A1 - - /* Nothing left to copy? */ -2: cmp %o2, 0 ! A0 Group - VISExitHalf ! A0+MS - be,pn %icc, U3copy_in_user_short_ret ! BR Group - nop ! A0 - ba,a,pt %xcc, U3copy_in_user_short ! BR Group - -#else /* !(SMALL_COPY_USES_FPU) */ - - xor %o1, %o0, %g2 - andcc %g2, 0x7, %g0 - bne,pn %icc, U3copy_in_user_short - andcc %o1, 0x7, %g2 - - be,pt %xcc, 2f - sub %g2, 0x8, %g2 - sub %g0, %g2, %g2 - sub %o2, %g2, %o2 - -1: EXNV2(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2) - add %o1, 0x1, %o1 - add %o0, 0x1, %o0 - subcc %g2, 0x1, %g2 - bg,pt %icc, 1b - EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) - -2: andn %o2, 0x7, %g2 - sub %o2, %g2, %o2 - -3: EXNV3(ldxa [%o1 + 0x00] %asi, %o3, add %o2, %g2) - add %o1, 0x8, %o1 - add %o0, 0x8, %o0 - subcc %g2, 0x8, %g2 - bg,pt %icc, 3b - EXNV3(stxa %o3, [%o0 + -8] %asi, add %o2, %g2) - - cmp %o2, 0 - bne,pn %icc, U3copy_in_user_short - nop - ba,a,pt %xcc, U3copy_in_user_short_ret - -#endif /* !(SMALL_COPY_USES_FPU) */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U3copy_to_user.S linux-2.4.28-pre3/arch/sparc64/lib/U3copy_to_user.S --- linux-2.4.27/arch/sparc64/lib/U3copy_to_user.S 2002-11-28 23:53:12.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/U3copy_to_user.S 2004-09-10 19:31:50.000000000 +0000 @@ -1,547 +1,33 @@ -/* $Id: U3copy_to_user.S,v 1.3 2000/11/01 09:29:19 davem Exp $ - * U3memcpy.S: UltraSparc-III optimized copy to userspace. +/* U3copy_to_user.S: UltraSparc-III optimized copy to userspace. * - * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com) + * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) */ -#ifdef __KERNEL__ -#include -#include -#include -#include -#undef SMALL_COPY_USES_FPU -#define EXNV(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: retl; \ - a, b, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXNV2(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: a, b, %o0; \ - retl; \ - add %o0, 1, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXNV3(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: a, b, %o0; \ - retl; \ - add %o0, 8, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EX(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - retl; \ - a, b, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXBLK1(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - add %o4, 0x1c0, %o1; \ - and %o2, (0x40 - 1), %o2; \ - retl; \ - add %o1, %o2, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXBLK2(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - sll %o3, 6, %o3; \ - and %o2, (0x40 - 1), %o2; \ - add %o3, 0x80, %o1; \ - retl; \ - add %o1, %o2, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXBLK3(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o2; \ - retl; \ - add %o2, 0x80, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXBLK4(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o2; \ - retl; \ - add %o2, 0x40, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#else -#define ASI_AIUS 0x80 -#define ASI_BLK_AIUS 0xf0 -#define FPRS_FEF 0x04 -#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs -#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs -#define SMALL_COPY_USES_FPU -#define EXNV(x,y,a,b) x,y; -#define EXNV2(x,y,a,b) x,y; -#define EXNV3(x,y,a,b) x,y; -#define EX(x,y,a,b) x,y; -#define EXBLK1(x,y) x,y; -#define EXBLK2(x,y) x,y; -#define EXBLK3(x,y) x,y; -#define EXBLK4(x,y) x,y; -#endif - - /* Special/non-trivial issues of this code: - * - * 1) %o5 is preserved from VISEntryHalf to VISExitHalf - * 2) Only low 32 FPU registers are used so that only the - * lower half of the FPU register set is dirtied by this - * code. This is especially important in the kernel. - * 3) This code never prefetches cachelines past the end - * of the source buffer. - */ +#define EX_ST(x) \ +98: x; \ + .section .fixup; \ + .align 4; \ +99: retl; \ + mov 1, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; + +#define FUNC_NAME U3copy_to_user +#define STORE(type,src,addr) type##a src, [addr] ASI_AIUS +#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_AIUS +#define EX_RETVAL(x) 0 - .text - .align 32 - - /* The cheetah's flexible spine, oversized liver, enlarged heart, - * slender muscular body, and claws make it the swiftest hunter - * in Africa and the fastest animal on land. Can reach speeds - * of up to 2.4GB per second. - */ - - .globl U3copy_to_user -U3copy_to_user: /* %o0=dst, %o1=src, %o2=len */ /* Writing to %asi is _expensive_ so we hardcode it. * Reading %asi to check for KERNEL_DS is comparatively * cheap. */ - rd %asi, %g1 ! MS Group (4 cycles) - cmp %g1, ASI_AIUS ! A0 Group - bne U3memcpy ! BR - nop ! A1 -#ifndef __KERNEL__ - /* Save away original 'dst' for memcpy return value. */ - mov %o0, %g3 ! A0 Group -#endif - /* Anything to copy at all? */ - cmp %o2, 0 ! A1 - ble,pn %icc, U3copy_to_user_short_ret ! BR - - /* Extremely small copy? */ - cmp %o2, 31 ! A0 Group - ble,pn %icc, U3copy_to_user_short ! BR - - /* Large enough to use unrolled prefetch loops? */ - cmp %o2, 0x100 ! A1 - bge,a,pt %icc, U3copy_to_user_enter ! BR Group - andcc %o0, 0x3f, %g2 ! A0 - - ba,pt %xcc, U3copy_to_user_toosmall ! BR Group - andcc %o0, 0x7, %g2 ! A0 - - .align 32 -U3copy_to_user_short: - /* Copy %o2 bytes from src to dst, one byte at a time. */ - ldub [%o1 + 0x00], %o3 ! MS Group - add %o1, 0x1, %o1 ! A0 - add %o0, 0x1, %o0 ! A1 - subcc %o2, 1, %o2 ! A0 Group - - bg,pt %icc, U3copy_to_user_short ! BR - EXNV(stba %o3, [%o0 + -1] %asi, add %o2, 1) ! MS Group (1-cycle stall) - -U3copy_to_user_short_ret: -#ifdef __KERNEL__ - retl ! BR Group (0-4 cycle stall) - clr %o0 ! A0 -#else - retl ! BR Group (0-4 cycle stall) - mov %g3, %o0 ! A0 -#endif - - /* Here len >= (6 * 64) and condition codes reflect execution - * of "andcc %o0, 0x7, %g2", done by caller. - */ - .align 64 -U3copy_to_user_enter: - /* Is 'dst' already aligned on an 64-byte boundary? */ - be,pt %xcc, 2f ! BR - - /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number - * of bytes to copy to make 'dst' 64-byte aligned. We pre- - * subtract this from 'len'. - */ - sub %g2, 0x40, %g2 ! A0 Group - sub %g0, %g2, %g2 ! A0 Group - sub %o2, %g2, %o2 ! A0 Group - - /* Copy %g2 bytes from src to dst, one byte at a time. */ -1: ldub [%o1 + 0x00], %o3 ! MS (Group) - add %o1, 0x1, %o1 ! A1 - add %o0, 0x1, %o0 ! A0 Group - subcc %g2, 0x1, %g2 ! A1 - - bg,pt %icc, 1b ! BR Group - EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS Group - -2: VISEntryHalf ! MS+MS - and %o1, 0x7, %g1 ! A1 - ba,pt %xcc, U3copy_to_user_begin ! BR - alignaddr %o1, %g0, %o1 ! MS (Break-after) - - .align 64 -U3copy_to_user_begin: -#ifdef __KERNEL__ - .globl U3copy_to_user_nop_1_6 -U3copy_to_user_nop_1_6: - ldxa [%g0] ASI_DCU_CONTROL_REG, %g3 - sethi %uhi(DCU_PE), %o3 - sllx %o3, 32, %o3 - or %g3, %o3, %o3 - stxa %o3, [%g0] ASI_DCU_CONTROL_REG ! Enable P-cache - membar #Sync -#endif - prefetch [%o1 + 0x000], #one_read ! MS Group1 - prefetch [%o1 + 0x040], #one_read ! MS Group2 - andn %o2, (0x40 - 1), %o4 ! A0 - prefetch [%o1 + 0x080], #one_read ! MS Group3 - cmp %o4, 0x140 ! A0 - prefetch [%o1 + 0x0c0], #one_read ! MS Group4 - ldd [%o1 + 0x000], %f0 ! MS Group5 (%f0 results at G8) - bge,a,pt %icc, 1f ! BR - - prefetch [%o1 + 0x100], #one_read ! MS Group6 -1: ldd [%o1 + 0x008], %f2 ! AX (%f2 results at G9) - cmp %o4, 0x180 ! A1 - bge,a,pt %icc, 1f ! BR - prefetch [%o1 + 0x140], #one_read ! MS Group7 -1: ldd [%o1 + 0x010], %f4 ! AX (%f4 results at G10) - cmp %o4, 0x1c0 ! A1 - bge,a,pt %icc, 1f ! BR - - prefetch [%o1 + 0x180], #one_read ! MS Group8 -1: faligndata %f0, %f2, %f16 ! FGA Group9 (%f16 at G12) - ldd [%o1 + 0x018], %f6 ! AX (%f6 results at G12) - faligndata %f2, %f4, %f18 ! FGA Group10 (%f18 results at G13) - ldd [%o1 + 0x020], %f8 ! MS (%f8 results at G13) - faligndata %f4, %f6, %f20 ! FGA Group12 (1-cycle stall,%f20 at G15) - ldd [%o1 + 0x028], %f10 ! MS (%f10 results at G15) - faligndata %f6, %f8, %f22 ! FGA Group13 (%f22 results at G16) - - ldd [%o1 + 0x030], %f12 ! MS (%f12 results at G16) - faligndata %f8, %f10, %f24 ! FGA Group15 (1-cycle stall,%f24 at G18) - ldd [%o1 + 0x038], %f14 ! MS (%f14 results at G18) - faligndata %f10, %f12, %f26 ! FGA Group16 (%f26 results at G19) - ldd [%o1 + 0x040], %f0 ! MS (%f0 results at G19) - - /* We only use the first loop if len > (7 * 64). */ - subcc %o4, 0x1c0, %o4 ! A0 Group17 - bg,pt %icc, U3copy_to_user_loop1 ! BR - add %o1, 0x40, %o1 ! A1 - - add %o4, 0x140, %o4 ! A0 Group18 - ba,pt %xcc, U3copy_to_user_loop2 ! BR - srl %o4, 6, %o3 ! A0 Group19 - nop - nop - nop - nop - nop - - nop - nop - - /* This loop performs the copy and queues new prefetches. - * We drop into the second loop when len <= (5 * 64). Note - * that this (5 * 64) factor has been subtracted from len - * already. - */ -U3copy_to_user_loop1: - ldd [%o1 + 0x008], %f2 ! MS Group2 (%f2 results at G5) - faligndata %f12, %f14, %f28 ! FGA (%f28 results at G5) - ldd [%o1 + 0x010], %f4 ! MS Group3 (%f4 results at G6) - faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall, %f30 at G7) - EXBLK1(stda %f16, [%o0] ASI_BLK_AIUS) ! MS - ldd [%o1 + 0x018], %f6 ! AX (%f6 results at G7) - - faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) - ldd [%o1 + 0x020], %f8 ! MS (%f8 results at G15) - faligndata %f2, %f4, %f18 ! FGA Group13 (%f18 results at G16) - ldd [%o1 + 0x028], %f10 ! MS (%f10 results at G16) - faligndata %f4, %f6, %f20 ! FGA Group14 (%f20 results at G17) - ldd [%o1 + 0x030], %f12 ! MS (%f12 results at G17) - faligndata %f6, %f8, %f22 ! FGA Group15 (%f22 results at G18) - ldd [%o1 + 0x038], %f14 ! MS (%f14 results at G18) - - faligndata %f8, %f10, %f24 ! FGA Group16 (%f24 results at G19) - ldd [%o1 + 0x040], %f0 ! AX (%f0 results at G19) - prefetch [%o1 + 0x180], #one_read ! MS - faligndata %f10, %f12, %f26 ! FGA Group17 (%f26 results at G20) - subcc %o4, 0x40, %o4 ! A0 - add %o1, 0x40, %o1 ! A1 - bg,pt %xcc, U3copy_to_user_loop1 ! BR - add %o0, 0x40, %o0 ! A0 Group18 - -U3copy_to_user_loop2_enter: - mov 5, %o3 ! A1 - - /* This loop performs on the copy, no new prefetches are - * queued. We do things this way so that we do not perform - * any spurious prefetches past the end of the src buffer. - */ -U3copy_to_user_loop2: - ldd [%o1 + 0x008], %f2 ! MS - faligndata %f12, %f14, %f28 ! FGA Group2 - ldd [%o1 + 0x010], %f4 ! MS - faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall) - EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS) ! MS - ldd [%o1 + 0x018], %f6 ! AX - faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) - - ldd [%o1 + 0x020], %f8 ! MS - faligndata %f2, %f4, %f18 ! FGA Group13 - ldd [%o1 + 0x028], %f10 ! MS - faligndata %f4, %f6, %f20 ! FGA Group14 - ldd [%o1 + 0x030], %f12 ! MS - faligndata %f6, %f8, %f22 ! FGA Group15 - ldd [%o1 + 0x038], %f14 ! MS - faligndata %f8, %f10, %f24 ! FGA Group16 - - ldd [%o1 + 0x040], %f0 ! AX - faligndata %f10, %f12, %f26 ! FGA Group17 - subcc %o3, 0x01, %o3 ! A0 - add %o1, 0x40, %o1 ! A1 - bg,pt %xcc, U3copy_to_user_loop2 ! BR - add %o0, 0x40, %o0 ! A0 Group18 - - /* Finally we copy the last full 64-byte block. */ -U3copy_to_user_loopfini: - ldd [%o1 + 0x008], %f2 ! MS - faligndata %f12, %f14, %f28 ! FGA - ldd [%o1 + 0x010], %f4 ! MS Group19 - faligndata %f14, %f0, %f30 ! FGA - EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS) ! MS Group20 - ldd [%o1 + 0x018], %f6 ! AX - faligndata %f0, %f2, %f16 ! FGA Group11 (7-cycle stall) - ldd [%o1 + 0x020], %f8 ! MS - faligndata %f2, %f4, %f18 ! FGA Group12 - ldd [%o1 + 0x028], %f10 ! MS - faligndata %f4, %f6, %f20 ! FGA Group13 - ldd [%o1 + 0x030], %f12 ! MS - faligndata %f6, %f8, %f22 ! FGA Group14 - ldd [%o1 + 0x038], %f14 ! MS - faligndata %f8, %f10, %f24 ! FGA Group15 - cmp %g1, 0 ! A0 - be,pt %icc, 1f ! BR - add %o0, 0x40, %o0 ! A1 - ldd [%o1 + 0x040], %f0 ! MS -1: faligndata %f10, %f12, %f26 ! FGA Group16 - faligndata %f12, %f14, %f28 ! FGA Group17 - faligndata %f14, %f0, %f30 ! FGA Group18 - EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS) ! MS - add %o0, 0x40, %o0 ! A0 - add %o1, 0x40, %o1 ! A1 -#ifdef __KERNEL__ - .globl U3copy_to_user_nop_2_3 -U3copy_to_user_nop_2_3: - mov PRIMARY_CONTEXT, %o3 - stxa %g0, [%o3] ASI_DMMU ! Flush P-cache - stxa %g3, [%g0] ASI_DCU_CONTROL_REG ! Disable P-cache -#endif - membar #Sync ! MS Group26 (7-cycle stall) - - /* Now we copy the (len modulo 64) bytes at the end. - * Note how we borrow the %f0 loaded above. - * - * Also notice how this code is careful not to perform a - * load past the end of the src buffer just like similar - * code found in U3copy_to_user_toosmall processing. - */ -U3copy_to_user_loopend: - and %o2, 0x3f, %o2 ! A0 Group - andcc %o2, 0x38, %g2 ! A0 Group - be,pn %icc, U3copy_to_user_endcruft ! BR - subcc %g2, 0x8, %g2 ! A1 - be,pn %icc, U3copy_to_user_endcruft ! BR Group - cmp %g1, 0 ! A0 - - be,a,pt %icc, 1f ! BR Group - ldd [%o1 + 0x00], %f0 ! MS - -1: ldd [%o1 + 0x08], %f2 ! MS Group - add %o1, 0x8, %o1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f0, %f2, %f8 ! FGA Group - EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS (XXX does it stall here? XXX) - be,pn %icc, U3copy_to_user_endcruft ! BR - add %o0, 0x8, %o0 ! A0 - ldd [%o1 + 0x08], %f0 ! MS Group - add %o1, 0x8, %o1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f2, %f0, %f8 ! FGA - EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS (XXX does it stall here? XXX) - bne,pn %icc, 1b ! BR - add %o0, 0x8, %o0 ! A0 Group - - /* If anything is left, we copy it one byte at a time. - * Note that %g1 is (src & 0x3) saved above before the - * alignaddr was performed. - */ -U3copy_to_user_endcruft: - cmp %o2, 0 - add %o1, %g1, %o1 - VISExitHalf - be,pn %icc, U3copy_to_user_short_ret - nop - ba,a,pt %xcc, U3copy_to_user_short - - /* If we get here, then 32 <= len < (6 * 64) */ -U3copy_to_user_toosmall: - -#ifdef SMALL_COPY_USES_FPU - - /* Is 'dst' already aligned on an 8-byte boundary? */ - be,pt %xcc, 2f ! BR Group - - /* Compute abs((dst & 7) - 8) into %g2. This is the number - * of bytes to copy to make 'dst' 8-byte aligned. We pre- - * subtract this from 'len'. - */ - sub %g2, 0x8, %g2 ! A0 - sub %g0, %g2, %g2 ! A0 Group (reg-dep) - sub %o2, %g2, %o2 ! A0 Group (reg-dep) - - /* Copy %g2 bytes from src to dst, one byte at a time. */ -1: ldub [%o1 + 0x00], %o3 ! MS (Group) (%o3 in 3 cycles) - add %o1, 0x1, %o1 ! A1 - add %o0, 0x1, %o0 ! A0 Group - subcc %g2, 0x1, %g2 ! A1 - - bg,pt %icc, 1b ! BR Group - EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS Group - -2: VISEntryHalf ! MS+MS - - /* Compute (len - (len % 8)) into %g2. This is guarenteed - * to be nonzero. - */ - andn %o2, 0x7, %g2 ! A0 Group - - /* You may read this and believe that it allows reading - * one 8-byte longword past the end of src. It actually - * does not, as %g2 is subtracted as loads are done from - * src, so we always stop before running off the end. - * Also, we are guarenteed to have at least 0x10 bytes - * to move here. - */ - sub %g2, 0x8, %g2 ! A0 Group (reg-dep) - alignaddr %o1, %g0, %g1 ! MS (Break-after) - ldd [%g1 + 0x00], %f0 ! MS Group (1-cycle stall) - add %g1, 0x8, %g1 ! A0 - -1: ldd [%g1 + 0x00], %f2 ! MS Group - add %g1, 0x8, %g1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - - faligndata %f0, %f2, %f8 ! FGA Group (1-cycle stall) - EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS Group (2-cycle stall) - add %o1, 0x8, %o1 ! A0 - be,pn %icc, 2f ! BR - - add %o0, 0x8, %o0 ! A1 - ldd [%g1 + 0x00], %f0 ! MS Group - add %g1, 0x8, %g1 ! A0 - sub %o2, 0x8, %o2 ! A1 - - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f2, %f0, %f8 ! FGA Group (1-cycle stall) - EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS Group (2-cycle stall) - add %o1, 0x8, %o1 ! A0 - - bne,pn %icc, 1b ! BR - add %o0, 0x8, %o0 ! A1 - - /* Nothing left to copy? */ -2: cmp %o2, 0 ! A0 Group - VISExitHalf ! A0+MS - be,pn %icc, U3copy_to_user_short_ret ! BR Group - nop ! A0 - ba,a,pt %xcc, U3copy_to_user_short ! BR Group - -#else /* !(SMALL_COPY_USES_FPU) */ - - xor %o1, %o0, %g2 - andcc %g2, 0x7, %g0 - bne,pn %icc, U3copy_to_user_short - andcc %o1, 0x7, %g2 - - be,pt %xcc, 2f - sub %g2, 0x8, %g2 - sub %g0, %g2, %g2 - sub %o2, %g2, %o2 - -1: ldub [%o1 + 0x00], %o3 - add %o1, 0x1, %o1 - add %o0, 0x1, %o0 - subcc %g2, 0x1, %g2 - bg,pt %icc, 1b - EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) - -2: andn %o2, 0x7, %g2 - sub %o2, %g2, %o2 - -3: ldx [%o1 + 0x00], %o3 - add %o1, 0x8, %o1 - add %o0, 0x8, %o0 - subcc %g2, 0x8, %g2 - bg,pt %icc, 3b - EXNV3(stxa %o3, [%o0 + -8] %asi, add %o2, %g2) - - cmp %o2, 0 - bne,pn %icc, U3copy_to_user_short - nop - ba,a,pt %xcc, U3copy_to_user_short_ret +#define PREAMBLE \ + rd %asi, %g1; \ + cmp %g1, ASI_AIUS; \ + bne,pn %icc, memcpy_user_stub; \ + nop; \ -#endif /* !(SMALL_COPY_USES_FPU) */ +#include "U3memcpy.S" diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U3memcpy.S linux-2.4.28-pre3/arch/sparc64/lib/U3memcpy.S --- linux-2.4.27/arch/sparc64/lib/U3memcpy.S 2002-11-28 23:53:12.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/U3memcpy.S 2004-09-10 19:37:24.000000000 +0000 @@ -1,23 +1,63 @@ -/* $Id: U3memcpy.S,v 1.2 2000/11/01 09:29:19 davem Exp $ - * U3memcpy.S: UltraSparc-III optimized memcpy. +/* U3memcpy.S: UltraSparc-III optimized memcpy. * - * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com) + * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) */ #ifdef __KERNEL__ #include #include -#include -#include -#undef SMALL_COPY_USES_FPU #else #define ASI_BLK_P 0xf0 #define FPRS_FEF 0x04 +#ifdef MEMCPY_DEBUG +#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \ + clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0; +#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs +#else #define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs -#define SMALL_COPY_USES_FPU +#endif +#endif + +#ifndef EX_LD +#define EX_LD(x) x +#endif + +#ifndef EX_ST +#define EX_ST(x) x +#endif + +#ifndef EX_RETVAL +#define EX_RETVAL(x) x #endif +#ifndef LOAD +#define LOAD(type,addr,dest) type [addr], dest +#endif + +#ifndef STORE +#define STORE(type,src,addr) type src, [addr] +#endif + +#ifndef STORE_BLK +#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_P +#endif + +#ifndef FUNC_NAME +#define FUNC_NAME U3memcpy +#endif + +#ifndef PREAMBLE +#define PREAMBLE +#endif + +#ifndef XCC +#define XCC xcc +#endif + + .register %g2,#scratch + .register %g3,#scratch + /* Special/non-trivial issues of this code: * * 1) %o5 is preserved from VISEntryHalf to VISExitHalf @@ -29,7 +69,7 @@ */ .text - .align 32 + .align 64 /* The cheetah's flexible spine, oversized liver, enlarged heart, * slender muscular body, and claws make it the swiftest hunter @@ -37,392 +77,338 @@ * of up to 2.4GB per second. */ - .globl U3memcpy -U3memcpy: /* %o0=dst, %o1=src, %o2=len */ -#ifndef __KERNEL__ - /* Save away original 'dst' for memcpy return value. */ - mov %o0, %g3 ! A0 Group -#endif - /* Anything to copy at all? */ - cmp %o2, 0 ! A1 - ble,pn %icc, U3memcpy_short_ret ! BR - - /* Extremely small copy? */ - cmp %o2, 31 ! A0 Group - ble,pn %icc, U3memcpy_short ! BR - - /* Large enough to use unrolled prefetch loops? */ - cmp %o2, 0x100 ! A1 - bge,a,pt %icc, U3memcpy_enter ! BR Group - andcc %o0, 0x3f, %g2 ! A0 - - ba,pt %xcc, U3memcpy_toosmall ! BR Group - andcc %o0, 0x7, %g2 ! A0 - - .align 32 -U3memcpy_short: - /* Copy %o2 bytes from src to dst, one byte at a time. */ - ldub [%o1 + 0x00], %o3 ! MS Group - add %o1, 0x1, %o1 ! A0 - add %o0, 0x1, %o0 ! A1 - subcc %o2, 1, %o2 ! A0 Group - - bg,pt %icc, U3memcpy_short ! BR - stb %o3, [%o0 + -1] ! MS Group (1-cycle stall) - -U3memcpy_short_ret: -#ifdef __KERNEL__ - retl ! BR Group (0-4 cycle stall) - clr %o0 ! A0 -#else - retl ! BR Group (0-4 cycle stall) - mov %g3, %o0 ! A0 -#endif + .globl FUNC_NAME +FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ + PREAMBLE + mov %o0, %g5 + cmp %o2, 0 + be,pn %XCC, 85f + or %o0, %o1, %o3 + cmp %o2, 16 + blu,a,pn %XCC, 80f + or %o3, %o2, %o3 + + cmp %o2, (3 * 64) + blu,pt %XCC, 70f + andcc %o3, 0x7, %g0 - /* Here len >= (6 * 64) and condition codes reflect execution - * of "andcc %o0, 0x7, %g2", done by caller. + /* Clobbers o5/g1/g2/g3/g7/icc/xcc. We must preserve + * o5 from here until we hit VISExitHalf. */ - .align 64 -U3memcpy_enter: + VISEntryHalf + /* Is 'dst' already aligned on an 64-byte boundary? */ - be,pt %xcc, 2f ! BR + andcc %o0, 0x3f, %g2 + be,pt %XCC, 2f /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number * of bytes to copy to make 'dst' 64-byte aligned. We pre- * subtract this from 'len'. */ - sub %g2, 0x40, %g2 ! A0 Group - sub %g0, %g2, %g2 ! A0 Group - sub %o2, %g2, %o2 ! A0 Group - - /* Copy %g2 bytes from src to dst, one byte at a time. */ -1: ldub [%o1 + 0x00], %o3 ! MS (Group) - add %o1, 0x1, %o1 ! A1 - add %o0, 0x1, %o0 ! A0 Group - subcc %g2, 0x1, %g2 ! A1 - - bg,pt %icc, 1b ! BR Group - stb %o3, [%o0 + -1] ! MS Group - -2: VISEntryHalf ! MS+MS - and %o1, 0x7, %g1 ! A1 - ba,pt %xcc, U3memcpy_begin ! BR - alignaddr %o1, %g0, %o1 ! MS (Break-after) + sub %o0, %o1, %o4 + sub %g2, 0x40, %g2 + sub %g0, %g2, %g2 + sub %o2, %g2, %o2 + andcc %g2, 0x7, %g1 + be,pt %icc, 2f + and %g2, 0x38, %g2 + +1: subcc %g1, 0x1, %g1 + EX_LD(LOAD(ldub, %o1 + 0x00, %o3)) + EX_ST(STORE(stb, %o3, %o1 + %o4)) + bgu,pt %XCC, 1b + add %o1, 0x1, %o1 + + add %o1, %o4, %o0 + +2: cmp %g2, 0x0 + and %o1, 0x7, %g1 + be,pt %icc, 3f + alignaddr %o1, %g0, %o1 + + EX_LD(LOAD(ldd, %o1, %f4)) +1: EX_LD(LOAD(ldd, %o1 + 0x8, %f6)) + add %o1, 0x8, %o1 + subcc %g2, 0x8, %g2 + faligndata %f4, %f6, %f0 + EX_ST(STORE(std, %f0, %o0)) + be,pn %icc, 3f + add %o0, 0x8, %o0 + + EX_LD(LOAD(ldd, %o1 + 0x8, %f4)) + add %o1, 0x8, %o1 + subcc %g2, 0x8, %g2 + faligndata %f6, %f4, %f2 + EX_ST(STORE(std, %f2, %o0)) + bne,pt %icc, 1b + add %o0, 0x8, %o0 + +3: LOAD(prefetch, %o1 + 0x000, #one_read) + LOAD(prefetch, %o1 + 0x040, #one_read) + andn %o2, (0x40 - 1), %o4 + LOAD(prefetch, %o1 + 0x080, #one_read) + LOAD(prefetch, %o1 + 0x0c0, #one_read) + LOAD(prefetch, %o1 + 0x100, #one_read) + EX_LD(LOAD(ldd, %o1 + 0x000, %f0)) + LOAD(prefetch, %o1 + 0x140, #one_read) + EX_LD(LOAD(ldd, %o1 + 0x008, %f2)) + LOAD(prefetch, %o1 + 0x180, #one_read) + EX_LD(LOAD(ldd, %o1 + 0x010, %f4)) + LOAD(prefetch, %o1 + 0x1c0, #one_read) + faligndata %f0, %f2, %f16 + EX_LD(LOAD(ldd, %o1 + 0x018, %f6)) + faligndata %f2, %f4, %f18 + EX_LD(LOAD(ldd, %o1 + 0x020, %f8)) + faligndata %f4, %f6, %f20 + EX_LD(LOAD(ldd, %o1 + 0x028, %f10)) + faligndata %f6, %f8, %f22 + + EX_LD(LOAD(ldd, %o1 + 0x030, %f12)) + faligndata %f8, %f10, %f24 + EX_LD(LOAD(ldd, %o1 + 0x038, %f14)) + faligndata %f10, %f12, %f26 + EX_LD(LOAD(ldd, %o1 + 0x040, %f0)) + + subcc %o4, 0x80, %o4 + add %o1, 0x40, %o1 + bgu,pt %XCC, 1f + srl %o4, 6, %o3 + ba,pt %xcc, 2f + nop .align 64 -U3memcpy_begin: -#ifdef __KERNEL__ - .globl U3memcpy_nop_1_6 -U3memcpy_nop_1_6: - ldxa [%g0] ASI_DCU_CONTROL_REG, %g3 - sethi %uhi(DCU_PE), %o3 - sllx %o3, 32, %o3 - or %g3, %o3, %o3 - stxa %o3, [%g0] ASI_DCU_CONTROL_REG ! Enable P-cache - membar #Sync -#endif - prefetch [%o1 + 0x000], #one_read ! MS Group1 - prefetch [%o1 + 0x040], #one_read ! MS Group2 - andn %o2, (0x40 - 1), %o4 ! A0 - prefetch [%o1 + 0x080], #one_read ! MS Group3 - cmp %o4, 0x140 ! A0 - prefetch [%o1 + 0x0c0], #one_read ! MS Group4 - ldd [%o1 + 0x000], %f0 ! MS Group5 (%f0 results at G8) - bge,a,pt %icc, 1f ! BR - - prefetch [%o1 + 0x100], #one_read ! MS Group6 -1: ldd [%o1 + 0x008], %f2 ! AX (%f2 results at G9) - cmp %o4, 0x180 ! A1 - bge,a,pt %icc, 1f ! BR - prefetch [%o1 + 0x140], #one_read ! MS Group7 -1: ldd [%o1 + 0x010], %f4 ! AX (%f4 results at G10) - cmp %o4, 0x1c0 ! A1 - bge,a,pt %icc, 1f ! BR - - prefetch [%o1 + 0x180], #one_read ! MS Group8 -1: faligndata %f0, %f2, %f16 ! FGA Group9 (%f16 at G12) - ldd [%o1 + 0x018], %f6 ! AX (%f6 results at G12) - faligndata %f2, %f4, %f18 ! FGA Group10 (%f18 results at G13) - ldd [%o1 + 0x020], %f8 ! MS (%f8 results at G13) - faligndata %f4, %f6, %f20 ! FGA Group12 (1-cycle stall,%f20 at G15) - ldd [%o1 + 0x028], %f10 ! MS (%f10 results at G15) - faligndata %f6, %f8, %f22 ! FGA Group13 (%f22 results at G16) - - ldd [%o1 + 0x030], %f12 ! MS (%f12 results at G16) - faligndata %f8, %f10, %f24 ! FGA Group15 (1-cycle stall,%f24 at G18) - ldd [%o1 + 0x038], %f14 ! MS (%f14 results at G18) - faligndata %f10, %f12, %f26 ! FGA Group16 (%f26 results at G19) - ldd [%o1 + 0x040], %f0 ! MS (%f0 results at G19) - - /* We only use the first loop if len > (7 * 64). */ - subcc %o4, 0x1c0, %o4 ! A0 Group17 - bg,pt %icc, U3memcpy_loop1 ! BR - add %o1, 0x40, %o1 ! A1 - - add %o4, 0x140, %o4 ! A0 Group18 - ba,pt %xcc, U3memcpy_loop2 ! BR - srl %o4, 6, %o3 ! A0 Group19 - nop - nop - nop - nop - nop - - nop - nop - - /* This loop performs the copy and queues new prefetches. - * We drop into the second loop when len <= (5 * 64). Note - * that this (5 * 64) factor has been subtracted from len - * already. - */ -U3memcpy_loop1: - ldd [%o1 + 0x008], %f2 ! MS Group2 (%f2 results at G5) - faligndata %f12, %f14, %f28 ! FGA (%f28 results at G5) - ldd [%o1 + 0x010], %f4 ! MS Group3 (%f4 results at G6) - faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall, %f30 at G7) - stda %f16, [%o0] ASI_BLK_P ! MS - ldd [%o1 + 0x018], %f6 ! AX (%f6 results at G7) - - faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) - ldd [%o1 + 0x020], %f8 ! MS (%f8 results at G15) - faligndata %f2, %f4, %f18 ! FGA Group13 (%f18 results at G16) - ldd [%o1 + 0x028], %f10 ! MS (%f10 results at G16) - faligndata %f4, %f6, %f20 ! FGA Group14 (%f20 results at G17) - ldd [%o1 + 0x030], %f12 ! MS (%f12 results at G17) - faligndata %f6, %f8, %f22 ! FGA Group15 (%f22 results at G18) - ldd [%o1 + 0x038], %f14 ! MS (%f14 results at G18) - - faligndata %f8, %f10, %f24 ! FGA Group16 (%f24 results at G19) - ldd [%o1 + 0x040], %f0 ! AX (%f0 results at G19) - prefetch [%o1 + 0x180], #one_read ! MS - faligndata %f10, %f12, %f26 ! FGA Group17 (%f26 results at G20) - subcc %o4, 0x40, %o4 ! A0 - add %o1, 0x40, %o1 ! A1 - bg,pt %xcc, U3memcpy_loop1 ! BR - add %o0, 0x40, %o0 ! A0 Group18 - -U3memcpy_loop2_enter: - mov 5, %o3 ! A1 - - /* This loop performs on the copy, no new prefetches are - * queued. We do things this way so that we do not perform - * any spurious prefetches past the end of the src buffer. - */ -U3memcpy_loop2: - ldd [%o1 + 0x008], %f2 ! MS - faligndata %f12, %f14, %f28 ! FGA Group2 - ldd [%o1 + 0x010], %f4 ! MS - faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall) - stda %f16, [%o0] ASI_BLK_P ! MS - ldd [%o1 + 0x018], %f6 ! AX - faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) - - ldd [%o1 + 0x020], %f8 ! MS - faligndata %f2, %f4, %f18 ! FGA Group13 - ldd [%o1 + 0x028], %f10 ! MS - faligndata %f4, %f6, %f20 ! FGA Group14 - ldd [%o1 + 0x030], %f12 ! MS - faligndata %f6, %f8, %f22 ! FGA Group15 - ldd [%o1 + 0x038], %f14 ! MS - faligndata %f8, %f10, %f24 ! FGA Group16 - - ldd [%o1 + 0x040], %f0 ! AX - faligndata %f10, %f12, %f26 ! FGA Group17 - subcc %o3, 0x01, %o3 ! A0 - add %o1, 0x40, %o1 ! A1 - bg,pt %xcc, U3memcpy_loop2 ! BR - add %o0, 0x40, %o0 ! A0 Group18 +1: + EX_LD(LOAD(ldd, %o1 + 0x008, %f2)) + faligndata %f12, %f14, %f28 + EX_LD(LOAD(ldd, %o1 + 0x010, %f4)) + faligndata %f14, %f0, %f30 + EX_ST(STORE_BLK(%f16, %o0)) + EX_LD(LOAD(ldd, %o1 + 0x018, %f6)) + faligndata %f0, %f2, %f16 + add %o0, 0x40, %o0 + + EX_LD(LOAD(ldd, %o1 + 0x020, %f8)) + faligndata %f2, %f4, %f18 + EX_LD(LOAD(ldd, %o1 + 0x028, %f10)) + faligndata %f4, %f6, %f20 + EX_LD(LOAD(ldd, %o1 + 0x030, %f12)) + subcc %o3, 0x01, %o3 + faligndata %f6, %f8, %f22 + EX_LD(LOAD(ldd, %o1 + 0x038, %f14)) + + faligndata %f8, %f10, %f24 + EX_LD(LOAD(ldd, %o1 + 0x040, %f0)) + LOAD(prefetch, %o1 + 0x1c0, #one_read) + faligndata %f10, %f12, %f26 + bg,pt %XCC, 1b + add %o1, 0x40, %o1 /* Finally we copy the last full 64-byte block. */ -U3memcpy_loopfini: - ldd [%o1 + 0x008], %f2 ! MS - faligndata %f12, %f14, %f28 ! FGA - ldd [%o1 + 0x010], %f4 ! MS Group19 - faligndata %f14, %f0, %f30 ! FGA - stda %f16, [%o0] ASI_BLK_P ! MS Group20 - ldd [%o1 + 0x018], %f6 ! AX - faligndata %f0, %f2, %f16 ! FGA Group11 (7-cycle stall) - ldd [%o1 + 0x020], %f8 ! MS - faligndata %f2, %f4, %f18 ! FGA Group12 - ldd [%o1 + 0x028], %f10 ! MS - faligndata %f4, %f6, %f20 ! FGA Group13 - ldd [%o1 + 0x030], %f12 ! MS - faligndata %f6, %f8, %f22 ! FGA Group14 - ldd [%o1 + 0x038], %f14 ! MS - faligndata %f8, %f10, %f24 ! FGA Group15 - cmp %g1, 0 ! A0 - be,pt %icc, 1f ! BR - add %o0, 0x40, %o0 ! A1 - ldd [%o1 + 0x040], %f0 ! MS -1: faligndata %f10, %f12, %f26 ! FGA Group16 - faligndata %f12, %f14, %f28 ! FGA Group17 - faligndata %f14, %f0, %f30 ! FGA Group18 - stda %f16, [%o0] ASI_BLK_P ! MS - add %o0, 0x40, %o0 ! A0 - add %o1, 0x40, %o1 ! A1 -#ifdef __KERNEL__ - .globl U3memcpy_nop_2_3 -U3memcpy_nop_2_3: - mov PRIMARY_CONTEXT, %o3 - stxa %g0, [%o3] ASI_DMMU ! Flush P-cache - stxa %g3, [%g0] ASI_DCU_CONTROL_REG ! Disable P-cache -#endif - membar #Sync ! MS Group26 (7-cycle stall) +2: + EX_LD(LOAD(ldd, %o1 + 0x008, %f2)) + faligndata %f12, %f14, %f28 + EX_LD(LOAD(ldd, %o1 + 0x010, %f4)) + faligndata %f14, %f0, %f30 + EX_ST(STORE_BLK(%f16, %o0)) + EX_LD(LOAD(ldd, %o1 + 0x018, %f6)) + faligndata %f0, %f2, %f16 + EX_LD(LOAD(ldd, %o1 + 0x020, %f8)) + faligndata %f2, %f4, %f18 + EX_LD(LOAD(ldd, %o1 + 0x028, %f10)) + faligndata %f4, %f6, %f20 + EX_LD(LOAD(ldd, %o1 + 0x030, %f12)) + faligndata %f6, %f8, %f22 + EX_LD(LOAD(ldd, %o1 + 0x038, %f14)) + faligndata %f8, %f10, %f24 + cmp %g1, 0 + be,pt %XCC, 1f + add %o0, 0x40, %o0 + EX_LD(LOAD(ldd, %o1 + 0x040, %f0)) +1: faligndata %f10, %f12, %f26 + faligndata %f12, %f14, %f28 + faligndata %f14, %f0, %f30 + EX_ST(STORE_BLK(%f16, %o0)) + add %o0, 0x40, %o0 + add %o1, 0x40, %o1 + membar #Sync /* Now we copy the (len modulo 64) bytes at the end. * Note how we borrow the %f0 loaded above. * * Also notice how this code is careful not to perform a - * load past the end of the src buffer just like similar - * code found in U3memcpy_toosmall processing. + * load past the end of the src buffer. */ -U3memcpy_loopend: - and %o2, 0x3f, %o2 ! A0 Group - andcc %o2, 0x38, %g2 ! A0 Group - be,pn %icc, U3memcpy_endcruft ! BR - subcc %g2, 0x8, %g2 ! A1 - be,pn %icc, U3memcpy_endcruft ! BR Group - cmp %g1, 0 ! A0 - - be,a,pt %icc, 1f ! BR Group - ldd [%o1 + 0x00], %f0 ! MS - -1: ldd [%o1 + 0x08], %f2 ! MS Group - add %o1, 0x8, %o1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f0, %f2, %f8 ! FGA Group - std %f8, [%o0 + 0x00] ! MS (XXX does it stall here? XXX) - be,pn %icc, U3memcpy_endcruft ! BR - add %o0, 0x8, %o0 ! A0 - ldd [%o1 + 0x08], %f0 ! MS Group - add %o1, 0x8, %o1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f2, %f0, %f8 ! FGA - std %f8, [%o0 + 0x00] ! MS (XXX does it stall here? XXX) - bne,pn %icc, 1b ! BR - add %o0, 0x8, %o0 ! A0 Group + and %o2, 0x3f, %o2 + andcc %o2, 0x38, %g2 + be,pn %XCC, 2f + subcc %g2, 0x8, %g2 + be,pn %XCC, 2f + cmp %g1, 0 + + sub %o2, %g2, %o2 + be,a,pt %XCC, 1f + EX_LD(LOAD(ldd, %o1 + 0x00, %f0)) + +1: EX_LD(LOAD(ldd, %o1 + 0x08, %f2)) + add %o1, 0x8, %o1 + subcc %g2, 0x8, %g2 + faligndata %f0, %f2, %f8 + EX_ST(STORE(std, %f8, %o0)) + be,pn %XCC, 2f + add %o0, 0x8, %o0 + EX_LD(LOAD(ldd, %o1 + 0x08, %f0)) + add %o1, 0x8, %o1 + subcc %g2, 0x8, %g2 + faligndata %f2, %f0, %f8 + EX_ST(STORE(std, %f8, %o0)) + bne,pn %XCC, 1b + add %o0, 0x8, %o0 /* If anything is left, we copy it one byte at a time. * Note that %g1 is (src & 0x3) saved above before the * alignaddr was performed. */ -U3memcpy_endcruft: +2: cmp %o2, 0 add %o1, %g1, %o1 VISExitHalf - be,pn %icc, U3memcpy_short_ret - nop - ba,a,pt %xcc, U3memcpy_short - - /* If we get here, then 32 <= len < (6 * 64) */ -U3memcpy_toosmall: + be,pn %XCC, 85f + sub %o0, %o1, %o3 -#ifdef SMALL_COPY_USES_FPU - - /* Is 'dst' already aligned on an 8-byte boundary? */ - be,pt %xcc, 2f ! BR Group - - /* Compute abs((dst & 7) - 8) into %g2. This is the number - * of bytes to copy to make 'dst' 8-byte aligned. We pre- - * subtract this from 'len'. - */ - sub %g2, 0x8, %g2 ! A0 - sub %g0, %g2, %g2 ! A0 Group (reg-dep) - sub %o2, %g2, %o2 ! A0 Group (reg-dep) - - /* Copy %g2 bytes from src to dst, one byte at a time. */ -1: ldub [%o1 + 0x00], %o3 ! MS (Group) (%o3 in 3 cycles) - add %o1, 0x1, %o1 ! A1 - add %o0, 0x1, %o0 ! A0 Group - subcc %g2, 0x1, %g2 ! A1 - - bg,pt %icc, 1b ! BR Group - stb %o3, [%o0 + -1] ! MS Group + andcc %g1, 0x7, %g0 + bne,pn %icc, 90f + andcc %o2, 0x8, %g0 + be,pt %icc, 1f + nop + EX_LD(LOAD(ldx, %o1, %o5)) + EX_ST(STORE(stx, %o5, %o1 + %o3)) + add %o1, 0x8, %o1 -2: VISEntryHalf ! MS+MS +1: andcc %o2, 0x4, %g0 + be,pt %icc, 1f + nop + EX_LD(LOAD(lduw, %o1, %o5)) + EX_ST(STORE(stw, %o5, %o1 + %o3)) + add %o1, 0x4, %o1 - /* Compute (len - (len % 8)) into %g2. This is guarenteed - * to be nonzero. - */ - andn %o2, 0x7, %g2 ! A0 Group +1: andcc %o2, 0x2, %g0 + be,pt %icc, 1f + nop + EX_LD(LOAD(lduh, %o1, %o5)) + EX_ST(STORE(sth, %o5, %o1 + %o3)) + add %o1, 0x2, %o1 - /* You may read this and believe that it allows reading - * one 8-byte longword past the end of src. It actually - * does not, as %g2 is subtracted as loads are done from - * src, so we always stop before running off the end. - * Also, we are guarenteed to have at least 0x10 bytes - * to move here. - */ - sub %g2, 0x8, %g2 ! A0 Group (reg-dep) - alignaddr %o1, %g0, %g1 ! MS (Break-after) - ldd [%g1 + 0x00], %f0 ! MS Group (1-cycle stall) - add %g1, 0x8, %g1 ! A0 - -1: ldd [%g1 + 0x00], %f2 ! MS Group - add %g1, 0x8, %g1 ! A0 - sub %o2, 0x8, %o2 ! A1 - subcc %g2, 0x8, %g2 ! A0 Group - - faligndata %f0, %f2, %f8 ! FGA Group (1-cycle stall) - std %f8, [%o0 + 0x00] ! MS Group (2-cycle stall) - add %o1, 0x8, %o1 ! A0 - be,pn %icc, 2f ! BR - - add %o0, 0x8, %o0 ! A1 - ldd [%g1 + 0x00], %f0 ! MS Group - add %g1, 0x8, %g1 ! A0 - sub %o2, 0x8, %o2 ! A1 - - subcc %g2, 0x8, %g2 ! A0 Group - faligndata %f2, %f0, %f8 ! FGA Group (1-cycle stall) - std %f8, [%o0 + 0x00] ! MS Group (2-cycle stall) - add %o1, 0x8, %o1 ! A0 - - bne,pn %icc, 1b ! BR - add %o0, 0x8, %o0 ! A1 - - /* Nothing left to copy? */ -2: cmp %o2, 0 ! A0 Group - VISExitHalf ! A0+MS - be,pn %icc, U3memcpy_short_ret ! BR Group - nop ! A0 - ba,a,pt %xcc, U3memcpy_short ! BR Group - -#else /* !(SMALL_COPY_USES_FPU) */ - - xor %o1, %o0, %g2 - andcc %g2, 0x7, %g0 - bne,pn %icc, U3memcpy_short - andcc %o1, 0x7, %g2 +1: andcc %o2, 0x1, %g0 + be,pt %icc, 85f + nop + EX_LD(LOAD(ldub, %o1, %o5)) + ba,pt %xcc, 85f + EX_ST(STORE(stb, %o5, %o1 + %o3)) - be,pt %xcc, 2f - sub %g2, 0x8, %g2 - sub %g0, %g2, %g2 - sub %o2, %g2, %o2 + .align 64 +70: /* 16 < len <= 64 */ + bne,pn %XCC, 75f + sub %o0, %o1, %o3 + +72: + andn %o2, 0xf, %o4 + and %o2, 0xf, %o2 +1: subcc %o4, 0x10, %o4 + EX_LD(LOAD(ldx, %o1 + 0x00, %o5)) + EX_LD(LOAD(ldx, %o1 + 0x08, %g1)) + EX_ST(STORE(stx, %o5, %o1 + %o3)) + add %o1, 0x8, %o1 + EX_ST(STORE(stx, %g1, %o1 + %o3)) + bgu,pt %XCC, 1b + add %o1, 0x8, %o1 +73: andcc %o2, 0x8, %g0 + be,pt %XCC, 1f + nop + sub %o2, 0x8, %o2 + EX_LD(LOAD(ldx, %o1, %o5)) + EX_ST(STORE(stx, %o5, %o1 + %o3)) + add %o1, 0x8, %o1 +1: andcc %o2, 0x4, %g0 + be,pt %XCC, 1f + nop + sub %o2, 0x4, %o2 + EX_LD(LOAD(lduw, %o1, %o5)) + EX_ST(STORE(stw, %o5, %o1 + %o3)) + add %o1, 0x4, %o1 +1: cmp %o2, 0 + be,pt %XCC, 85f + nop + ba,pt %xcc, 90f + nop -1: ldub [%o1 + 0x00], %o3 - add %o1, 0x1, %o1 - add %o0, 0x1, %o0 - subcc %g2, 0x1, %g2 - bg,pt %icc, 1b - stb %o3, [%o0 + -1] +75: + andcc %o0, 0x7, %g1 + sub %g1, 0x8, %g1 + be,pn %icc, 2f + sub %g0, %g1, %g1 + sub %o2, %g1, %o2 + +1: subcc %g1, 1, %g1 + EX_LD(LOAD(ldub, %o1, %o5)) + EX_ST(STORE(stb, %o5, %o1 + %o3)) + bgu,pt %icc, 1b + add %o1, 1, %o1 + +2: add %o1, %o3, %o0 + andcc %o1, 0x7, %g1 + bne,pt %icc, 8f + sll %g1, 3, %g1 -2: andn %o2, 0x7, %g2 - sub %o2, %g2, %o2 + cmp %o2, 16 + bgeu,pt %icc, 72b + nop + ba,a,pt %xcc, 73b -3: ldx [%o1 + 0x00], %o3 +8: mov 64, %o3 + andn %o1, 0x7, %o1 + EX_LD(LOAD(ldx, %o1, %g2)) + sub %o3, %g1, %o3 + andn %o2, 0x7, %o4 + sllx %g2, %g1, %g2 +1: EX_LD(LOAD(ldx, %o1 + 0x8, %g3)) + subcc %o4, 0x8, %o4 add %o1, 0x8, %o1 + srlx %g3, %o3, %o5 + or %o5, %g2, %o5 + EX_ST(STORE(stx, %o5, %o0)) add %o0, 0x8, %o0 - subcc %g2, 0x8, %g2 - bg,pt %icc, 3b - stx %o3, [%o0 + -8] + bgu,pt %icc, 1b + sllx %g3, %g1, %g2 - cmp %o2, 0 - bne,pn %icc, U3memcpy_short - nop - ba,a,pt %xcc, U3memcpy_short_ret + srl %g1, 3, %g1 + andcc %o2, 0x7, %o2 + be,pn %icc, 85f + add %o1, %g1, %o1 + ba,pt %xcc, 90f + sub %o0, %o1, %o3 + + .align 64 +80: /* 0 < len <= 16 */ + andcc %o3, 0x3, %g0 + bne,pn %XCC, 90f + sub %o0, %o1, %o3 + +1: + subcc %o2, 4, %o2 + EX_LD(LOAD(lduw, %o1, %g1)) + EX_ST(STORE(stw, %g1, %o1 + %o3)) + bgu,pt %XCC, 1b + add %o1, 4, %o1 -#endif /* !(SMALL_COPY_USES_FPU) */ +85: retl + mov EX_RETVAL(%g5), %o0 + + .align 32 +90: + subcc %o2, 1, %o2 + EX_LD(LOAD(ldub, %o1, %g1)) + EX_ST(STORE(stb, %g1, %o1 + %o3)) + bgu,pt %XCC, 90b + add %o1, 1, %o1 + retl + mov EX_RETVAL(%g5), %o0 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U3patch.S linux-2.4.28-pre3/arch/sparc64/lib/U3patch.S --- linux-2.4.27/arch/sparc64/lib/U3patch.S 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/U3patch.S 2004-09-10 19:36:16.000000000 +0000 @@ -0,0 +1,30 @@ +/* U3patch.S: Patch Ultra-I routines with Ultra-III variant. + * + * Copyright (C) 2004 David S. Miller + */ + +#define BRANCH_ALWAYS 0x10680000 +#define NOP 0x01000000 +#define ULTRA3_DO_PATCH(OLD, NEW) \ + sethi %hi(NEW), %g1; \ + or %g1, %lo(NEW), %g1; \ + sethi %hi(OLD), %g2; \ + or %g2, %lo(OLD), %g2; \ + sub %g1, %g2, %g1; \ + sethi %hi(BRANCH_ALWAYS), %g3; \ + srl %g1, 2, %g1; \ + or %g3, %lo(BRANCH_ALWAYS), %g3; \ + or %g3, %g1, %g3; \ + stw %g3, [%g2]; \ + sethi %hi(NOP), %g3; \ + or %g3, %lo(NOP), %g3; \ + stw %g3, [%g2 + 0x4]; \ + flush %g2; + + .globl cheetah_patch_copyops +cheetah_patch_copyops: + ULTRA3_DO_PATCH(memcpy, U3memcpy) + ULTRA3_DO_PATCH(___copy_from_user, U3copy_from_user) + ULTRA3_DO_PATCH(___copy_to_user, U3copy_to_user) + retl + nop diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/VIScopy.S linux-2.4.28-pre3/arch/sparc64/lib/VIScopy.S --- linux-2.4.27/arch/sparc64/lib/VIScopy.S 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/VIScopy.S 1970-01-01 00:00:00.000000000 +0000 @@ -1,1187 +0,0 @@ -/* $Id: VIScopy.S,v 1.26 2001/09/27 04:36:24 kanoj Exp $ - * VIScopy.S: High speed copy operations utilizing the UltraSparc - * Visual Instruction Set. - * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#include "VIS.h" - - /* VIS code can be used for numerous copy/set operation variants. - * It can be made to work in the kernel, one single instance, - * for all of memcpy, copy_to_user, and copy_from_user by setting - * the ASI src/dest globals correctly. Furthermore it can - * be used for kernel-->kernel page copies as well, a hook label - * is put in here just for this purpose. - * - * For userland, compiling this without __KERNEL__ defined makes - * it work just fine as a generic libc bcopy and memcpy. - * If for userland it is compiled with a 32bit gcc (but you need - * -Wa,-Av9a for as), the code will just rely on lower 32bits of - * IEU registers, if you compile it with 64bit gcc (ie. define - * __sparc_v9__), the code will use full 64bit. - */ - -#ifdef __KERNEL__ - -#include -#include - -#define FPU_CLEAN_RETL \ - ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1; \ - VISExit \ - clr %o0; \ - retl; \ - wr %o1, %g0, %asi; -#define FPU_RETL \ - ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1; \ - VISExit \ - clr %o0; \ - retl; \ - wr %o1, %g0, %asi; -#define NORMAL_RETL \ - ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1; \ - clr %o0; \ - retl; \ - wr %o1, %g0, %asi; -#define EX(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: ba VIScopyfixup_ret; \ - a, b, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EX2(x,y,c,d,e,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: c, d, e; \ - ba VIScopyfixup_ret; \ - a, b, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXO2(x,y) \ -98: x,y; \ - .section __ex_table; \ - .align 4; \ - .word 98b, VIScopyfixup_reto2; \ - .text; \ - .align 4; -#define EXVISN(x,y,n) \ -98: x,y; \ - .section __ex_table; \ - .align 4; \ - .word 98b, VIScopyfixup_vis##n; \ - .text; \ - .align 4; -#define EXT(start,end,handler) \ - .section __ex_table; \ - .align 4; \ - .word start, 0, end, handler; \ - .text; \ - .align 4; -#else -#ifdef REGS_64BIT -#define FPU_CLEAN_RETL \ - retl; \ - mov %g6, %o0; -#define FPU_RETL \ - retl; \ - mov %g6, %o0; -#else -#define FPU_CLEAN_RETL \ - wr %g0, FPRS_FEF, %fprs; \ - retl; \ - mov %g6, %o0; -#define FPU_RETL \ - wr %g0, FPRS_FEF, %fprs; \ - retl; \ - mov %g6, %o0; -#endif -#define NORMAL_RETL \ - retl; \ - mov %g6, %o0; -#define EX(x,y,a,b) x,y -#define EX2(x,y,c,d,e,a,b) x,y -#define EXO2(x,y) x,y -#define EXVISN(x,y,n) x,y -#define EXT(a,b,c) -#endif -#define EXVIS(x,y) EXVISN(x,y,0) -#define EXVIS1(x,y) EXVISN(x,y,1) -#define EXVIS2(x,y) EXVISN(x,y,2) -#define EXVIS3(x,y) EXVISN(x,y,3) -#define EXVIS4(x,y) EXVISN(x,y,4) - -#define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9) \ - faligndata %f1, %f2, %f48; \ - faligndata %f2, %f3, %f50; \ - faligndata %f3, %f4, %f52; \ - faligndata %f4, %f5, %f54; \ - faligndata %f5, %f6, %f56; \ - faligndata %f6, %f7, %f58; \ - faligndata %f7, %f8, %f60; \ - faligndata %f8, %f9, %f62; - -#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt) \ - EXVIS(LDBLK [%src] ASIBLK, %fdest); \ - ASI_SETDST_BLK \ - EXVIS(STBLK %fsrc, [%dest] ASIBLK); \ - add %src, 0x40, %src; \ - subcc %len, 0x40, %len; \ - be,pn %xcc, jmptgt; \ - add %dest, 0x40, %dest; \ - ASI_SETSRC_BLK - -#define LOOP_CHUNK1(src, dest, len, branch_dest) \ - MAIN_LOOP_CHUNK(src, dest, f0, f48, len, branch_dest) -#define LOOP_CHUNK2(src, dest, len, branch_dest) \ - MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest) -#define LOOP_CHUNK3(src, dest, len, branch_dest) \ - MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest) - -#define STORE_SYNC(dest, fsrc) \ - EXVIS(STBLK %fsrc, [%dest] ASIBLK); \ - add %dest, 0x40, %dest; - -#ifdef __KERNEL__ -#define STORE_JUMP(dest, fsrc, target) \ - srl asi_dest, 3, %g5; \ - EXVIS2(STBLK %fsrc, [%dest] ASIBLK); \ - xor asi_dest, ASI_BLK_XOR1, asi_dest;\ - add %dest, 0x40, %dest; \ - xor asi_dest, %g5, asi_dest; \ - ba,pt %xcc, target; -#else -#define STORE_JUMP(dest, fsrc, target) \ - EXVIS2(STBLK %fsrc, [%dest] ASIBLK); \ - add %dest, 0x40, %dest; \ - ba,pt %xcc, target; -#endif - -#ifndef __KERNEL__ -#define VISLOOP_PAD nop; nop; nop; nop; \ - nop; nop; nop; nop; \ - nop; nop; nop; nop; \ - nop; nop; nop; -#else -#define VISLOOP_PAD -#endif - -#define FINISH_VISCHUNK(dest, f0, f1, left) \ - ASI_SETDST_NOBLK \ - subcc %left, 8, %left; \ - bl,pn %xcc, vis_out; \ - faligndata %f0, %f1, %f48; \ - EXVIS3(STDF %f48, [%dest] ASINORMAL); \ - add %dest, 8, %dest; - -#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left) \ - subcc %left, 8, %left; \ - bl,pn %xcc, vis_out; \ - fsrc1 %f0, %f1; -#define UNEVEN_VISCHUNK(dest, f0, f1, left) \ - UNEVEN_VISCHUNK_LAST(dest, f0, f1, left) \ - ba,a,pt %xcc, vis_out_slk; - - /* Macros for non-VIS memcpy code. */ -#ifdef REGS_64BIT - -#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ - ASI_SETSRC_NOBLK \ - LDX [%src + offset + 0x00] ASINORMAL, %t0; \ - LDX [%src + offset + 0x08] ASINORMAL, %t1; \ - LDX [%src + offset + 0x10] ASINORMAL, %t2; \ - LDX [%src + offset + 0x18] ASINORMAL, %t3; \ - ASI_SETDST_NOBLK \ - STW %t0, [%dst + offset + 0x04] ASINORMAL; \ - srlx %t0, 32, %t0; \ - STW %t0, [%dst + offset + 0x00] ASINORMAL; \ - STW %t1, [%dst + offset + 0x0c] ASINORMAL; \ - srlx %t1, 32, %t1; \ - STW %t1, [%dst + offset + 0x08] ASINORMAL; \ - STW %t2, [%dst + offset + 0x14] ASINORMAL; \ - srlx %t2, 32, %t2; \ - STW %t2, [%dst + offset + 0x10] ASINORMAL; \ - STW %t3, [%dst + offset + 0x1c] ASINORMAL; \ - srlx %t3, 32, %t3; \ - STW %t3, [%dst + offset + 0x18] ASINORMAL; - -#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ - ASI_SETSRC_NOBLK \ - LDX [%src + offset + 0x00] ASINORMAL, %t0; \ - LDX [%src + offset + 0x08] ASINORMAL, %t1; \ - LDX [%src + offset + 0x10] ASINORMAL, %t2; \ - LDX [%src + offset + 0x18] ASINORMAL, %t3; \ - ASI_SETDST_NOBLK \ - STX %t0, [%dst + offset + 0x00] ASINORMAL; \ - STX %t1, [%dst + offset + 0x08] ASINORMAL; \ - STX %t2, [%dst + offset + 0x10] ASINORMAL; \ - STX %t3, [%dst + offset + 0x18] ASINORMAL; \ - ASI_SETSRC_NOBLK \ - LDX [%src + offset + 0x20] ASINORMAL, %t0; \ - LDX [%src + offset + 0x28] ASINORMAL, %t1; \ - LDX [%src + offset + 0x30] ASINORMAL, %t2; \ - LDX [%src + offset + 0x38] ASINORMAL, %t3; \ - ASI_SETDST_NOBLK \ - STX %t0, [%dst + offset + 0x20] ASINORMAL; \ - STX %t1, [%dst + offset + 0x28] ASINORMAL; \ - STX %t2, [%dst + offset + 0x30] ASINORMAL; \ - STX %t3, [%dst + offset + 0x38] ASINORMAL; - -#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ - ASI_SETSRC_NOBLK \ - LDX [%src - offset - 0x10] ASINORMAL, %t0; \ - LDX [%src - offset - 0x08] ASINORMAL, %t1; \ - ASI_SETDST_NOBLK \ - STW %t0, [%dst - offset - 0x0c] ASINORMAL; \ - srlx %t0, 32, %t2; \ - STW %t2, [%dst - offset - 0x10] ASINORMAL; \ - STW %t1, [%dst - offset - 0x04] ASINORMAL; \ - srlx %t1, 32, %t3; \ - STW %t3, [%dst - offset - 0x08] ASINORMAL; - -#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1) \ - ASI_SETSRC_NOBLK \ - LDX [%src - offset - 0x10] ASINORMAL, %t0; \ - LDX [%src - offset - 0x08] ASINORMAL, %t1; \ - ASI_SETDST_NOBLK \ - STX %t0, [%dst - offset - 0x10] ASINORMAL; \ - STX %t1, [%dst - offset - 0x08] ASINORMAL; - -#else /* !REGS_64BIT */ - -#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ - lduw [%src + offset + 0x00], %t0; \ - lduw [%src + offset + 0x04], %t1; \ - lduw [%src + offset + 0x08], %t2; \ - lduw [%src + offset + 0x0c], %t3; \ - stw %t0, [%dst + offset + 0x00]; \ - stw %t1, [%dst + offset + 0x04]; \ - stw %t2, [%dst + offset + 0x08]; \ - stw %t3, [%dst + offset + 0x0c]; \ - lduw [%src + offset + 0x10], %t0; \ - lduw [%src + offset + 0x14], %t1; \ - lduw [%src + offset + 0x18], %t2; \ - lduw [%src + offset + 0x1c], %t3; \ - stw %t0, [%dst + offset + 0x10]; \ - stw %t1, [%dst + offset + 0x14]; \ - stw %t2, [%dst + offset + 0x18]; \ - stw %t3, [%dst + offset + 0x1c]; - -#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ - lduw [%src - offset - 0x10], %t0; \ - lduw [%src - offset - 0x0c], %t1; \ - lduw [%src - offset - 0x08], %t2; \ - lduw [%src - offset - 0x04], %t3; \ - stw %t0, [%dst - offset - 0x10]; \ - stw %t1, [%dst - offset - 0x0c]; \ - stw %t2, [%dst - offset - 0x08]; \ - stw %t3, [%dst - offset - 0x04]; - -#endif /* !REGS_64BIT */ - -#ifdef __KERNEL__ - .section __ex_table,#alloc - .section .fixup,#alloc,#execinstr -#endif - - .text - .align 32 - .globl memcpy - .type memcpy,@function - - .globl bcopy - .type bcopy,@function - -#ifdef __KERNEL__ - .globl __memcpy_begin -__memcpy_begin: - - .globl __memcpy - .type __memcpy,@function - -memcpy_private: -__memcpy: -memcpy: mov ASI_P, asi_src ! IEU0 Group - brnz,pt %o2, __memcpy_entry ! CTI - mov ASI_P, asi_dest ! IEU1 - retl - clr %o0 - - .align 32 - .globl __copy_from_user - .type __copy_from_user,@function -__copy_from_user:rd %asi, asi_src ! IEU0 Group - brnz,pt %o2, __memcpy_entry ! CTI - mov ASI_P, asi_dest ! IEU1 - - .globl __copy_to_user - .type __copy_to_user,@function -__copy_to_user: mov ASI_P, asi_src ! IEU0 Group - brnz,pt %o2, __memcpy_entry ! CTI - rd %asi, asi_dest ! IEU1 - retl ! CTI Group - clr %o0 ! IEU0 Group - - .globl __copy_in_user - .type __copy_in_user,@function -__copy_in_user: rd %asi, asi_src ! IEU0 Group - brnz,pt %o2, __memcpy_entry ! CTI - mov asi_src, asi_dest ! IEU1 - retl ! CTI Group - clr %o0 ! IEU0 Group -#endif - -bcopy: or %o0, 0, %g3 ! IEU0 Group - addcc %o1, 0, %o0 ! IEU1 - brgez,pt %o2, memcpy_private ! CTI - or %g3, 0, %o1 ! IEU0 Group - retl ! CTI Group brk forced - clr %o0 ! IEU0 - - -#ifdef __KERNEL__ -#define BRANCH_ALWAYS 0x10680000 -#define NOP 0x01000000 -#define ULTRA3_DO_PATCH(OLD, NEW) \ - sethi %hi(NEW), %g1; \ - or %g1, %lo(NEW), %g1; \ - sethi %hi(OLD), %g2; \ - or %g2, %lo(OLD), %g2; \ - sub %g1, %g2, %g1; \ - sethi %hi(BRANCH_ALWAYS), %g3; \ - srl %g1, 2, %g1; \ - or %g3, %lo(BRANCH_ALWAYS), %g3; \ - or %g3, %g1, %g3; \ - stw %g3, [%g2]; \ - sethi %hi(NOP), %g3; \ - or %g3, %lo(NOP), %g3; \ - stw %g3, [%g2 + 0x4]; \ - flush %g2; -#define ULTRA3_PCACHE_DO_NOP(symbol) \ - sethi %hi(symbol##_nop_1_6), %g1; \ - or %g1, %lo(symbol##_nop_1_6), %g1; \ - sethi %hi(NOP), %g2; \ - stw %g2, [%g1 + 0x00]; \ - stw %g2, [%g1 + 0x04]; \ - flush %g1 + 0x00; \ - stw %g2, [%g1 + 0x08]; \ - stw %g2, [%g1 + 0x0c]; \ - flush %g1 + 0x08; \ - stw %g2, [%g1 + 0x10]; \ - stw %g2, [%g1 + 0x04]; \ - flush %g1 + 0x10; \ - sethi %hi(symbol##_nop_2_3), %g1; \ - or %g1, %lo(symbol##_nop_2_3), %g1; \ - stw %g2, [%g1 + 0x00]; \ - stw %g2, [%g1 + 0x04]; \ - flush %g1 + 0x00; \ - stw %g2, [%g1 + 0x08]; \ - flush %g1 + 0x08; - -#include - - .globl cheetah_patch_copyops -cheetah_patch_copyops: - ULTRA3_DO_PATCH(memcpy, U3memcpy) - ULTRA3_DO_PATCH(__copy_from_user, U3copy_from_user) - ULTRA3_DO_PATCH(__copy_to_user, U3copy_to_user) - ULTRA3_DO_PATCH(__copy_in_user, U3copy_in_user) -#if 0 /* Causes data corruption, nop out the optimization - * for now -DaveM - */ - ldxa [%g0] ASI_DCU_CONTROL_REG, %g3 - sethi %uhi(DCU_PE), %o3 - sllx %o3, 32, %o3 - andcc %g3, %o3, %g0 - be,pn %xcc, pcache_disabled - nop -#endif - ULTRA3_PCACHE_DO_NOP(U3memcpy) - ULTRA3_PCACHE_DO_NOP(U3copy_from_user) - ULTRA3_PCACHE_DO_NOP(U3copy_to_user) - ULTRA3_PCACHE_DO_NOP(cheetah_copy_user_page) -#if 0 -pcache_disabled: -#endif - retl - nop -#undef BRANCH_ALWAYS -#undef NOP -#undef ULTRA3_DO_PATCH -#endif /* __KERNEL__ */ - - .align 32 -#ifdef __KERNEL__ - andcc %o0, 7, %g2 ! IEU1 Group -#endif -VIS_enter: - be,pt %xcc, dest_is_8byte_aligned ! CTI -#ifdef __KERNEL__ - nop ! IEU0 Group -#else - andcc %o0, 0x38, %g5 ! IEU1 Group -#endif -do_dest_8byte_align: - mov 8, %g1 ! IEU0 - sub %g1, %g2, %g2 ! IEU0 Group - andcc %o0, 1, %g0 ! IEU1 - be,pt %icc, 2f ! CTI - sub %o2, %g2, %o2 ! IEU0 Group -1: ASI_SETSRC_NOBLK ! LSU Group - EX(LDUB [%o1] ASINORMAL, %o5, - add %o2, %g2) ! Load Group - add %o1, 1, %o1 ! IEU0 - add %o0, 1, %o0 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - subcc %g2, 1, %g2 ! IEU1 Group - be,pn %xcc, 3f ! CTI - EX2(STB %o5, [%o0 - 1] ASINORMAL, - add %g2, 1, %g2, - add %o2, %g2) ! Store -2: ASI_SETSRC_NOBLK ! LSU Group - EX(LDUB [%o1] ASINORMAL, %o5, - add %o2, %g2) ! Load Group - add %o0, 2, %o0 ! IEU0 - EX2(LDUB [%o1 + 1] ASINORMAL, %g3, - sub %o0, 2, %o0, - add %o2, %g2) ! Load Group - ASI_SETDST_NOBLK ! LSU Group - subcc %g2, 2, %g2 ! IEU1 Group - EX2(STB %o5, [%o0 - 2] ASINORMAL, - add %g2, 2, %g2, - add %o2, %g2) ! Store - add %o1, 2, %o1 ! IEU0 - bne,pt %xcc, 2b ! CTI Group - EX2(STB %g3, [%o0 - 1] ASINORMAL, - add %g2, 1, %g2, - add %o2, %g2) ! Store -#ifdef __KERNEL__ -3: -dest_is_8byte_aligned: - VISEntry - andcc %o0, 0x38, %g5 ! IEU1 Group -#else -3: andcc %o0, 0x38, %g5 ! IEU1 Group -dest_is_8byte_aligned: -#endif - be,pt %icc, dest_is_64byte_aligned ! CTI - mov 64, %g1 ! IEU0 - fmovd %f0, %f2 ! FPU - sub %g1, %g5, %g5 ! IEU0 Group - ASI_SETSRC_NOBLK ! LSU Group - alignaddr %o1, %g0, %g1 ! GRU Group - EXO2(LDDF [%g1] ASINORMAL, %f4) ! Load Group - sub %o2, %g5, %o2 ! IEU0 -1: EX(LDDF [%g1 + 0x8] ASINORMAL, %f6, - add %o2, %g5) ! Load Group - add %g1, 0x8, %g1 ! IEU0 Group - subcc %g5, 8, %g5 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - faligndata %f4, %f6, %f0 ! GRU Group - EX2(STDF %f0, [%o0] ASINORMAL, - add %g5, 8, %g5, - add %o2, %g5) ! Store - add %o1, 8, %o1 ! IEU0 Group - be,pn %xcc, dest_is_64byte_aligned ! CTI - add %o0, 8, %o0 ! IEU1 - ASI_SETSRC_NOBLK ! LSU Group - EX(LDDF [%g1 + 0x8] ASINORMAL, %f4, - add %o2, %g5) ! Load Group - add %g1, 8, %g1 ! IEU0 - subcc %g5, 8, %g5 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - faligndata %f6, %f4, %f0 ! GRU Group - EX2(STDF %f0, [%o0] ASINORMAL, - add %g5, 8, %g5, - add %o2, %g5) ! Store - add %o1, 8, %o1 ! IEU0 - ASI_SETSRC_NOBLK ! LSU Group - bne,pt %xcc, 1b ! CTI Group - add %o0, 8, %o0 ! IEU0 -dest_is_64byte_aligned: - membar #LoadStore | #StoreStore | #StoreLoad ! LSU Group -#ifndef __KERNEL__ - wr %g0, ASI_BLK_P, %asi ! LSU Group -#endif - subcc %o2, 0x40, %g7 ! IEU1 Group - mov %o1, %g1 ! IEU0 - andncc %g7, (0x40 - 1), %g7 ! IEU1 Group - srl %g1, 3, %g2 ! IEU0 - sub %o2, %g7, %g3 ! IEU0 Group - andn %o1, (0x40 - 1), %o1 ! IEU1 - and %g2, 7, %g2 ! IEU0 Group - andncc %g3, 0x7, %g3 ! IEU1 - fmovd %f0, %f2 ! FPU - sub %g3, 0x10, %g3 ! IEU0 Group - sub %o2, %g7, %o2 ! IEU1 -#ifdef __KERNEL__ - or asi_src, ASI_BLK_OR, asi_src ! IEU0 Group - or asi_dest, ASI_BLK_OR, asi_dest ! IEU1 -#endif - alignaddr %g1, %g0, %g0 ! GRU Group - add %g1, %g7, %g1 ! IEU0 Group - subcc %o2, %g3, %o2 ! IEU1 - ASI_SETSRC_BLK ! LSU Group - EXVIS1(LDBLK [%o1 + 0x00] ASIBLK, %f0) ! LSU Group - add %g1, %g3, %g1 ! IEU0 - EXVIS1(LDBLK [%o1 + 0x40] ASIBLK, %f16) ! LSU Group - sub %g7, 0x80, %g7 ! IEU0 - EXVIS(LDBLK [%o1 + 0x80] ASIBLK, %f32) ! LSU Group -#ifdef __KERNEL__ -vispc: sll %g2, 9, %g2 ! IEU0 Group - sethi %hi(vis00), %g5 ! IEU1 - or %g5, %lo(vis00), %g5 ! IEU0 Group - jmpl %g5 + %g2, %g0 ! CTI Group brk forced - addcc %o1, 0xc0, %o1 ! IEU1 Group -#else - ! Clk1 Group 8-( - ! Clk2 Group 8-( - ! Clk3 Group 8-( - ! Clk4 Group 8-( -vispc: rd %pc, %g5 ! PDU Group 8-( - addcc %g5, %lo(vis00 - vispc), %g5 ! IEU1 Group - sll %g2, 9, %g2 ! IEU0 - jmpl %g5 + %g2, %g0 ! CTI Group brk forced - addcc %o1, 0xc0, %o1 ! IEU1 Group -#endif - .align 512 /* OK, here comes the fun part... */ -vis00:FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) LOOP_CHUNK1(o1, o0, g7, vis01) - FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) LOOP_CHUNK2(o1, o0, g7, vis02) - FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) LOOP_CHUNK3(o1, o0, g7, vis03) - b,pt %xcc, vis00+4; faligndata %f0, %f2, %f48 -vis01:FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) STORE_JUMP(o0, f48, finish_f0) membar #Sync -vis02:FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_JUMP(o0, f48, finish_f16) membar #Sync -vis03:FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_JUMP(o0, f48, finish_f32) membar #Sync - VISLOOP_PAD -vis10:FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) LOOP_CHUNK1(o1, o0, g7, vis11) - FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) LOOP_CHUNK2(o1, o0, g7, vis12) - FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) LOOP_CHUNK3(o1, o0, g7, vis13) - b,pt %xcc, vis10+4; faligndata %f2, %f4, %f48 -vis11:FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) STORE_JUMP(o0, f48, finish_f2) membar #Sync -vis12:FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_JUMP(o0, f48, finish_f18) membar #Sync -vis13:FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_JUMP(o0, f48, finish_f34) membar #Sync - VISLOOP_PAD -vis20:FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) LOOP_CHUNK1(o1, o0, g7, vis21) - FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) LOOP_CHUNK2(o1, o0, g7, vis22) - FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) LOOP_CHUNK3(o1, o0, g7, vis23) - b,pt %xcc, vis20+4; faligndata %f4, %f6, %f48 -vis21:FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) STORE_JUMP(o0, f48, finish_f4) membar #Sync -vis22:FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_JUMP(o0, f48, finish_f20) membar #Sync -vis23:FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_JUMP(o0, f48, finish_f36) membar #Sync - VISLOOP_PAD -vis30:FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) LOOP_CHUNK1(o1, o0, g7, vis31) - FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) LOOP_CHUNK2(o1, o0, g7, vis32) - FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) LOOP_CHUNK3(o1, o0, g7, vis33) - b,pt %xcc, vis30+4; faligndata %f6, %f8, %f48 -vis31:FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) STORE_JUMP(o0, f48, finish_f6) membar #Sync -vis32:FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_JUMP(o0, f48, finish_f22) membar #Sync -vis33:FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_JUMP(o0, f48, finish_f38) membar #Sync - VISLOOP_PAD -vis40:FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) LOOP_CHUNK1(o1, o0, g7, vis41) - FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) LOOP_CHUNK2(o1, o0, g7, vis42) - FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) LOOP_CHUNK3(o1, o0, g7, vis43) - b,pt %xcc, vis40+4; faligndata %f8, %f10, %f48 -vis41:FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) STORE_JUMP(o0, f48, finish_f8) membar #Sync -vis42:FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_JUMP(o0, f48, finish_f24) membar #Sync -vis43:FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_JUMP(o0, f48, finish_f40) membar #Sync - VISLOOP_PAD -vis50:FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) LOOP_CHUNK1(o1, o0, g7, vis51) - FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) LOOP_CHUNK2(o1, o0, g7, vis52) - FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) LOOP_CHUNK3(o1, o0, g7, vis53) - b,pt %xcc, vis50+4; faligndata %f10, %f12, %f48 -vis51:FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_JUMP(o0, f48, finish_f10) membar #Sync -vis52:FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_JUMP(o0, f48, finish_f26) membar #Sync -vis53:FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_JUMP(o0, f48, finish_f42) membar #Sync - VISLOOP_PAD -vis60:FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) LOOP_CHUNK1(o1, o0, g7, vis61) - FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) LOOP_CHUNK2(o1, o0, g7, vis62) - FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) LOOP_CHUNK3(o1, o0, g7, vis63) - b,pt %xcc, vis60+4; faligndata %f12, %f14, %f48 -vis61:FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_JUMP(o0, f48, finish_f12) membar #Sync -vis62:FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_JUMP(o0, f48, finish_f28) membar #Sync -vis63:FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_JUMP(o0, f48, finish_f44) membar #Sync - VISLOOP_PAD -vis70:FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) LOOP_CHUNK1(o1, o0, g7, vis71) - FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) LOOP_CHUNK2(o1, o0, g7, vis72) - FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) LOOP_CHUNK3(o1, o0, g7, vis73) - b,pt %xcc, vis70+4; faligndata %f14, %f16, %f48 -vis71:FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_JUMP(o0, f48, finish_f14) membar #Sync -vis72:FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_JUMP(o0, f48, finish_f30) membar #Sync -vis73:FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_SYNC(o0, f48) membar #Sync - FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_JUMP(o0, f48, finish_f46) membar #Sync - VISLOOP_PAD -finish_f0: FINISH_VISCHUNK(o0, f0, f2, g3) -finish_f2: FINISH_VISCHUNK(o0, f2, f4, g3) -finish_f4: FINISH_VISCHUNK(o0, f4, f6, g3) -finish_f6: FINISH_VISCHUNK(o0, f6, f8, g3) -finish_f8: FINISH_VISCHUNK(o0, f8, f10, g3) -finish_f10: FINISH_VISCHUNK(o0, f10, f12, g3) -finish_f12: FINISH_VISCHUNK(o0, f12, f14, g3) -finish_f14: UNEVEN_VISCHUNK(o0, f14, f0, g3) -finish_f16: FINISH_VISCHUNK(o0, f16, f18, g3) -finish_f18: FINISH_VISCHUNK(o0, f18, f20, g3) -finish_f20: FINISH_VISCHUNK(o0, f20, f22, g3) -finish_f22: FINISH_VISCHUNK(o0, f22, f24, g3) -finish_f24: FINISH_VISCHUNK(o0, f24, f26, g3) -finish_f26: FINISH_VISCHUNK(o0, f26, f28, g3) -finish_f28: FINISH_VISCHUNK(o0, f28, f30, g3) -finish_f30: UNEVEN_VISCHUNK(o0, f30, f0, g3) -finish_f32: FINISH_VISCHUNK(o0, f32, f34, g3) -finish_f34: FINISH_VISCHUNK(o0, f34, f36, g3) -finish_f36: FINISH_VISCHUNK(o0, f36, f38, g3) -finish_f38: FINISH_VISCHUNK(o0, f38, f40, g3) -finish_f40: FINISH_VISCHUNK(o0, f40, f42, g3) -finish_f42: FINISH_VISCHUNK(o0, f42, f44, g3) -finish_f44: FINISH_VISCHUNK(o0, f44, f46, g3) -finish_f46: UNEVEN_VISCHUNK_LAST(o0, f46, f0, g3) -vis_out_slk: -#ifdef __KERNEL__ - srl asi_src, 3, %g5 ! IEU0 Group - xor asi_src, ASI_BLK_XOR1, asi_src ! IEU1 - xor asi_src, %g5, asi_src ! IEU0 Group -#endif -vis_slk:ASI_SETSRC_NOBLK ! LSU Group - EXVIS3(LDDF [%o1] ASINORMAL, %f2) ! Load Group - add %o1, 8, %o1 ! IEU0 - subcc %g3, 8, %g3 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - faligndata %f0, %f2, %f8 ! GRU Group - EXVIS4(STDF %f8, [%o0] ASINORMAL) ! Store - bl,pn %xcc, vis_out_slp ! CTI - add %o0, 8, %o0 ! IEU0 Group - ASI_SETSRC_NOBLK ! LSU Group - EXVIS3(LDDF [%o1] ASINORMAL, %f0) ! Load Group - add %o1, 8, %o1 ! IEU0 - subcc %g3, 8, %g3 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - faligndata %f2, %f0, %f8 ! GRU Group - EXVIS4(STDF %f8, [%o0] ASINORMAL) ! Store - bge,pt %xcc, vis_slk ! CTI - add %o0, 8, %o0 ! IEU0 Group -vis_out_slp: -#ifdef __KERNEL__ - brz,pt %o2, vis_ret ! CTI Group - mov %g1, %o1 ! IEU0 - ba,pt %xcc, vis_slp+4 ! CTI Group - ASI_SETSRC_NOBLK ! LSU Group -#endif -vis_out:brz,pt %o2, vis_ret ! CTI Group - mov %g1, %o1 ! IEU0 -#ifdef __KERNEL__ - srl asi_src, 3, %g5 ! IEU0 Group - xor asi_src, ASI_BLK_XOR1, asi_src ! IEU1 - xor asi_src, %g5, asi_src ! IEU0 Group -#endif -vis_slp:ASI_SETSRC_NOBLK ! LSU Group - EXO2(LDUB [%o1] ASINORMAL, %g5) ! LOAD - add %o1, 1, %o1 ! IEU0 - add %o0, 1, %o0 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - subcc %o2, 1, %o2 ! IEU1 - bne,pt %xcc, vis_slp ! CTI - EX(STB %g5, [%o0 - 1] ASINORMAL, - add %o2, 1) ! Store Group -vis_ret:membar #StoreLoad | #StoreStore ! LSU Group - FPU_CLEAN_RETL - - -__memcpy_short: - andcc %o2, 1, %g0 ! IEU1 Group - be,pt %icc, 2f ! CTI -1: ASI_SETSRC_NOBLK ! LSU Group - EXO2(LDUB [%o1] ASINORMAL, %g5) ! LOAD Group - add %o1, 1, %o1 ! IEU0 - add %o0, 1, %o0 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - subcc %o2, 1, %o2 ! IEU1 Group - be,pn %xcc, short_ret ! CTI - EX(STB %g5, [%o0 - 1] ASINORMAL, - add %o2, 1) ! Store -2: ASI_SETSRC_NOBLK ! LSU Group - EXO2(LDUB [%o1] ASINORMAL, %g5) ! LOAD Group - add %o0, 2, %o0 ! IEU0 - EX2(LDUB [%o1 + 1] ASINORMAL, %o5, - sub %o0, 2, %o0, - add %o2, %g0) ! LOAD Group - add %o1, 2, %o1 ! IEU0 - ASI_SETDST_NOBLK ! LSU Group - subcc %o2, 2, %o2 ! IEU1 Group - EX(STB %g5, [%o0 - 2] ASINORMAL, - add %o2, 2) ! Store - bne,pt %xcc, 2b ! CTI - EX(STB %o5, [%o0 - 1] ASINORMAL, - add %o2, 1) ! Store -short_ret: - NORMAL_RETL - -#ifndef __KERNEL__ -memcpy_private: -memcpy: -#ifndef REGS_64BIT - srl %o2, 0, %o2 ! IEU1 Group -#endif - brz,pn %o2, short_ret ! CTI Group - mov %o0, %g6 ! IEU0 -#endif -__memcpy_entry: - cmp %o2, 15 ! IEU1 Group - bleu,pn %xcc, __memcpy_short ! CTI - cmp %o2, (64 * 6) ! IEU1 Group - bgeu,pn %xcc, VIS_enter ! CTI - andcc %o0, 7, %g2 ! IEU1 Group - sub %o0, %o1, %g5 ! IEU0 - andcc %g5, 3, %o5 ! IEU1 Group - bne,pn %xcc, memcpy_noVIS_misaligned ! CTI - andcc %o1, 3, %g0 ! IEU1 Group -#ifdef REGS_64BIT - be,a,pt %xcc, 3f ! CTI - andcc %o1, 4, %g0 ! IEU1 Group - andcc %o1, 1, %g0 ! IEU1 Group -#else /* !REGS_64BIT */ - be,pt %xcc, 5f ! CTI - andcc %o1, 1, %g0 ! IEU1 Group -#endif /* !REGS_64BIT */ - be,pn %xcc, 4f ! CTI - andcc %o1, 2, %g0 ! IEU1 Group - ASI_SETSRC_NOBLK ! LSU Group - EXO2(LDUB [%o1] ASINORMAL, %g2) ! Load Group - add %o1, 1, %o1 ! IEU0 - add %o0, 1, %o0 ! IEU1 - sub %o2, 1, %o2 ! IEU0 Group - ASI_SETDST_NOBLK ! LSU Group - bne,pn %xcc, 5f ! CTI Group - EX(STB %g2, [%o0 - 1] ASINORMAL, - add %o2, 1) ! Store -4: ASI_SETSRC_NOBLK ! LSU Group - EXO2(LDUH [%o1] ASINORMAL, %g2) ! Load Group - add %o1, 2, %o1 ! IEU0 - add %o0, 2, %o0 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - sub %o2, 2, %o2 ! IEU0 - EX(STH %g2, [%o0 - 2] ASINORMAL, - add %o2, 2) ! Store Group + bubble -#ifdef REGS_64BIT -5: andcc %o1, 4, %g0 ! IEU1 -3: be,a,pn %xcc, 2f ! CTI - andcc %o2, -128, %g7 ! IEU1 Group - ASI_SETSRC_NOBLK ! LSU Group - EXO2(LDUW [%o1] ASINORMAL, %g5) ! Load Group - add %o1, 4, %o1 ! IEU0 - add %o0, 4, %o0 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - sub %o2, 4, %o2 ! IEU0 Group - EX(STW %g5, [%o0 - 4] ASINORMAL, - add %o2, 4) ! Store - andcc %o2, -128, %g7 ! IEU1 Group -2: be,pn %xcc, 3f ! CTI - andcc %o0, 4, %g0 ! IEU1 Group - be,pn %xcc, 82f + 4 ! CTI Group -#else /* !REGS_64BIT */ -5: andcc %o2, -128, %g7 ! IEU1 - be,a,pn %xcc, 41f ! CTI - andcc %o2, 0x70, %g7 ! IEU1 Group -#endif /* !REGS_64BIT */ -5: MOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5) - MOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5) - MOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5) - MOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5) - EXT(5b,35f,VIScopyfixup1) -35: subcc %g7, 128, %g7 ! IEU1 Group - add %o1, 128, %o1 ! IEU0 - bne,pt %xcc, 5b ! CTI - add %o0, 128, %o0 ! IEU0 Group -3: andcc %o2, 0x70, %g7 ! IEU1 Group -41: be,pn %xcc, 80f ! CTI - andcc %o2, 8, %g0 ! IEU1 Group -#ifdef __KERNEL__ -79: sethi %hi(80f), %o5 ! IEU0 - sll %g7, 1, %g5 ! IEU0 Group - add %o1, %g7, %o1 ! IEU1 - srl %g7, 1, %g2 ! IEU0 Group - sub %o5, %g5, %o5 ! IEU1 - sub %o5, %g2, %o5 ! IEU0 Group - jmpl %o5 + %lo(80f), %g0 ! CTI Group brk forced - add %o0, %g7, %o0 ! IEU0 Group -#else - ! Clk1 8-( - ! Clk2 8-( - ! Clk3 8-( - ! Clk4 8-( -79: rd %pc, %o5 ! PDU Group - sll %g7, 1, %g5 ! IEU0 Group - add %o1, %g7, %o1 ! IEU1 - sub %o5, %g5, %o5 ! IEU0 Group - jmpl %o5 + %lo(80f - 79b), %g0 ! CTI Group brk forced - add %o0, %g7, %o0 ! IEU0 Group -#endif -36: MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5) - MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5) - MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5) - MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5) - MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5) - MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5) - MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5) - EXT(36b,80f,VIScopyfixup2) -80: be,pt %xcc, 81f ! CTI - andcc %o2, 4, %g0 ! IEU1 -#ifdef REGS_64BIT - ASI_SETSRC_NOBLK ! LSU Group - EX(LDX [%o1] ASINORMAL, %g2, - and %o2, 0xf) ! Load Group - add %o0, 8, %o0 ! IEU0 - ASI_SETDST_NOBLK ! LSU Group - EX(STW %g2, [%o0 - 0x4] ASINORMAL, - and %o2, 0xf) ! Store Group - add %o1, 8, %o1 ! IEU1 - srlx %g2, 32, %g2 ! IEU0 Group - EX2(STW %g2, [%o0 - 0x8] ASINORMAL, - and %o2, 0xf, %o2, - sub %o2, 4) ! Store -#else /* !REGS_64BIT */ - lduw [%o1], %g2 ! Load Group - add %o0, 8, %o0 ! IEU0 - lduw [%o1 + 0x4], %g3 ! Load Group - add %o1, 8, %o1 ! IEU0 - stw %g2, [%o0 - 0x8] ! Store Group - stw %g3, [%o0 - 0x4] ! Store Group -#endif /* !REGS_64BIT */ -81: be,pt %xcc, 1f ! CTI - andcc %o2, 2, %g0 ! IEU1 Group - ASI_SETSRC_NOBLK ! LSU Group - EX(LDUW [%o1] ASINORMAL, %g2, - and %o2, 0x7) ! Load Group - add %o1, 4, %o1 ! IEU0 - ASI_SETDST_NOBLK ! LSU Group - EX(STW %g2, [%o0] ASINORMAL, - and %o2, 0x7) ! Store Group - add %o0, 4, %o0 ! IEU0 -1: be,pt %xcc, 1f ! CTI - andcc %o2, 1, %g0 ! IEU1 Group - ASI_SETSRC_NOBLK ! LSU Group - EX(LDUH [%o1] ASINORMAL, %g2, - and %o2, 0x3) ! Load Group - add %o1, 2, %o1 ! IEU0 - ASI_SETDST_NOBLK ! LSU Group - EX(STH %g2, [%o0] ASINORMAL, - and %o2, 0x3) ! Store Group - add %o0, 2, %o0 ! IEU0 -1: be,pt %xcc, normal_retl ! CTI - nop ! IEU1 - ASI_SETSRC_NOBLK ! LSU Group - EX(LDUB [%o1] ASINORMAL, %g2, - add %g0, 1) ! Load Group - ASI_SETDST_NOBLK ! LSU Group - EX(STB %g2, [%o0] ASINORMAL, - add %g0, 1) ! Store Group + bubble -normal_retl: - NORMAL_RETL - -#ifdef REGS_64BIT -82: MOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5) - MOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5) - EXT(82b,37f,VIScopyfixup3) -37: subcc %g7, 128, %g7 ! IEU1 Group - add %o1, 128, %o1 ! IEU0 - bne,pt %xcc, 82b ! CTI - add %o0, 128, %o0 ! IEU0 Group - andcc %o2, 0x70, %g7 ! IEU1 - be,pn %xcc, 84f ! CTI - andcc %o2, 8, %g0 ! IEU1 Group -#ifdef __KERNEL__ -83: srl %g7, 1, %g5 ! IEU0 - sethi %hi(84f), %o5 ! IEU0 Group - add %g7, %g5, %g5 ! IEU1 - add %o1, %g7, %o1 ! IEU0 Group - sub %o5, %g5, %o5 ! IEU1 - jmpl %o5 + %lo(84f), %g0 ! CTI Group brk forced - add %o0, %g7, %o0 ! IEU0 Group -#else - ! Clk1 8-( - ! Clk2 8-( - ! Clk3 8-( - ! Clk4 8-( -83: rd %pc, %o5 ! PDU Group - add %o1, %g7, %o1 ! IEU0 Group - sub %o5, %g7, %o5 ! IEU1 - jmpl %o5 + %lo(84f - 83b), %g0 ! CTI Group brk forced - add %o0, %g7, %o0 ! IEU0 Group -#endif -38: MOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3) - MOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3) - MOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3) - MOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3) - MOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3) - MOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3) - MOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3) - EXT(38b,84f,VIScopyfixup4) -84: be,pt %xcc, 85f ! CTI Group - andcc %o2, 4, %g0 ! IEU1 - ASI_SETSRC_NOBLK ! LSU Group - EX(LDX [%o1] ASINORMAL, %g2, - and %o2, 0xf) ! Load Group - add %o0, 8, %o0 ! IEU0 - ASI_SETDST_NOBLK ! LSU Group - add %o1, 8, %o1 ! IEU0 Group - EX(STX %g2, [%o0 - 0x8] ASINORMAL, - and %o2, 0xf) ! Store -85: be,pt %xcc, 1f ! CTI - andcc %o2, 2, %g0 ! IEU1 Group - ASI_SETSRC_NOBLK ! LSU Group - EX(LDUW [%o1] ASINORMAL, %g2, - and %o2, 0x7) ! Load Group - add %o0, 4, %o0 ! IEU0 - ASI_SETDST_NOBLK ! LSU Group - add %o1, 4, %o1 ! IEU0 Group - EX(STW %g2, [%o0 - 0x4] ASINORMAL, - and %o2, 0x7) ! Store -1: be,pt %xcc, 1f ! CTI - andcc %o2, 1, %g0 ! IEU1 Group - ASI_SETSRC_NOBLK ! LSU Group - EX(LDUH [%o1] ASINORMAL, %g2, - and %o2, 0x3) ! Load Group - add %o0, 2, %o0 ! IEU0 - ASI_SETDST_NOBLK ! LSU Group - add %o1, 2, %o1 ! IEU0 Group - EX(STH %g2, [%o0 - 0x2] ASINORMAL, - and %o2, 0x3) ! Store -1: be,pt %xcc, 1f ! CTI - nop ! IEU0 Group - ASI_SETSRC_NOBLK ! LSU Group - EX(LDUB [%o1] ASINORMAL, %g2, - add %g0, 1) ! Load Group - ASI_SETDST_NOBLK ! LSU Group - EX(STB %g2, [%o0] ASINORMAL, - add %g0, 1) ! Store Group + bubble -1: NORMAL_RETL -#endif /* REGS_64BIT */ - -memcpy_noVIS_misaligned: - brz,pt %g2, 2f ! CTI Group - mov 8, %g1 ! IEU0 - sub %g1, %g2, %g2 ! IEU0 Group - sub %o2, %g2, %o2 ! IEU0 Group -1: ASI_SETSRC_NOBLK ! LSU Group - EX(LDUB [%o1] ASINORMAL, %g5, - add %o2, %g2) ! Load Group - add %o1, 1, %o1 ! IEU0 - add %o0, 1, %o0 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - subcc %g2, 1, %g2 ! IEU1 Group - bne,pt %xcc, 1b ! CTI - EX2(STB %g5, [%o0 - 1] ASINORMAL, - add %o2, %g2, %o2, - add %o2, 1) ! Store -2: -#ifdef __KERNEL__ - VISEntry -#endif - andn %o2, 7, %g5 ! IEU0 Group - and %o2, 7, %o2 ! IEU1 - fmovd %f0, %f2 ! FPU - ASI_SETSRC_NOBLK ! LSU Group - alignaddr %o1, %g0, %g1 ! GRU Group - EXO2(LDDF [%g1] ASINORMAL, %f4) ! Load Group -1: EX(LDDF [%g1 + 0x8] ASINORMAL, %f6, - add %o2, %g5) ! Load Group - add %g1, 0x8, %g1 ! IEU0 Group - subcc %g5, 8, %g5 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - faligndata %f4, %f6, %f0 ! GRU Group - EX2(STDF %f0, [%o0] ASINORMAL, - add %o2, %g5, %o2, - add %o2, 8) ! Store - add %o1, 8, %o1 ! IEU0 Group - be,pn %xcc, end_cruft ! CTI - add %o0, 8, %o0 ! IEU1 - ASI_SETSRC_NOBLK ! LSU Group - EX(LDDF [%g1 + 0x8] ASINORMAL, %f4, - add %o2, %g5) ! Load Group - add %g1, 8, %g1 ! IEU0 - subcc %g5, 8, %g5 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - faligndata %f6, %f4, %f0 ! GRU Group - EX2(STDF %f0, [%o0] ASINORMAL, - add %o2, %g5, %o2, - add %o2, 8) ! Store - add %o1, 8, %o1 ! IEU0 - ASI_SETSRC_NOBLK ! LSU Group - bne,pn %xcc, 1b ! CTI Group - add %o0, 8, %o0 ! IEU0 -end_cruft: - brz,pn %o2, fpu_retl ! CTI Group -#ifndef __KERNEL__ - nop ! IEU0 -#else - ASI_SETSRC_NOBLK ! LSU Group -#endif - EXO2(LDUB [%o1] ASINORMAL, %g5) ! LOAD - add %o1, 1, %o1 ! IEU0 - add %o0, 1, %o0 ! IEU1 - ASI_SETDST_NOBLK ! LSU Group - subcc %o2, 1, %o2 ! IEU1 - bne,pt %xcc, vis_slp ! CTI - EX(STB %g5, [%o0 - 1] ASINORMAL, - add %o2, 1) ! Store Group -fpu_retl: - FPU_RETL - -#ifdef __KERNEL__ - .globl __memcpy_end -__memcpy_end: - - .section .fixup - .align 4 -VIScopyfixup_reto2: - mov %o2, %o1 -VIScopyfixup_ret: - /* If this is copy_from_user(), zero out the rest of the - * kernel buffer. - */ - ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o4 - andcc asi_src, 0x1, %g0 - be,pt %icc, 1f - VISExit - andcc asi_dest, 0x1, %g0 - bne,pn %icc, 1f - nop - save %sp, -160, %sp - mov %i0, %o0 - call __bzero - mov %i1, %o1 - restore -1: mov %o1, %o0 - retl - wr %o4, %g0, %asi -VIScopyfixup1: subcc %g2, 18, %g2 - add %o0, 32, %o0 - bgeu,a,pt %icc, VIScopyfixup1 - sub %g7, 32, %g7 - sub %o0, 32, %o0 - rd %pc, %g5 - add %g2, (18 + 16), %g2 - ldub [%g5 + %g2], %g2 - ba,a,pt %xcc, 2f -.byte 0, 0, 0, 0, 0, 0, 0, 4, 4, 8, 12, 12, 16, 20, 20, 24, 28, 28 - .align 4 -VIScopyfixup2: mov (7 * 16), %g7 -1: subcc %g2, 10, %g2 - bgeu,a,pt %icc, 1b - sub %g7, 16, %g7 - sub %o0, %g7, %o0 - rd %pc, %g5 - add %g2, (10 + 16), %g2 - ldub [%g5 + %g2], %g2 - ba,a,pt %xcc, 4f -.byte 0, 0, 0, 0, 0, 4, 4, 8, 12, 12 - .align 4 -VIScopyfixup3: subcc %g2, 10, %g2 - add %o0, 32, %o0 - bgeu,a,pt %icc, VIScopyfixup3 - sub %g7, 32, %g7 - sub %o0, 32, %o0 - rd %pc, %g5 - add %g2, (10 + 16), %g2 - ldub [%g5 + %g2], %g2 - ba,a,pt %xcc, 2f -.byte 0, 0, 0, 0, 0, 0, 0, 8, 16, 24 - .align 4 -2: and %o2, 0x7f, %o2 - sub %g7, %g2, %g7 - ba,pt %xcc, VIScopyfixup_ret - add %g7, %o2, %o1 -VIScopyfixup4: mov (7 * 16), %g7 -3: subcc %g2, 6, %g2 - bgeu,a,pt %icc, 3b - sub %g7, 16, %g7 - sub %o0, %g7, %o0 - rd %pc, %g5 - add %g2, (6 + 16), %g2 - ldub [%g5 + %g2], %g2 - ba,a,pt %xcc, 4f -.byte 0, 0, 0, 0, 0, 8 - .align 4 -4: and %o2, 0xf, %o2 - sub %g7, %g2, %g7 - ba,pt %xcc, VIScopyfixup_ret - add %g7, %o2, %o1 -VIScopyfixup_vis2: - sub %o2, 0x40, %o2 -VIScopyfixup_vis0: - add %o2, 0x80, %o2 -VIScopyfixup_vis1: - add %g7, %g3, %g7 - ba,pt %xcc, VIScopyfixup_ret - add %o2, %g7, %o1 -VIScopyfixup_vis4: - add %g3, 8, %g3 -VIScopyfixup_vis3: - add %g3, 8, %g3 - ba,pt %xcc, VIScopyfixup_ret - add %o2, %g3, %o1 -#endif - -#ifdef __KERNEL__ - .text - .align 32 - - .globl __memmove - .type __memmove,@function - - .globl memmove - .type memmove,@function - -memmove: -__memmove: cmp %o0, %o1 - blu,pt %xcc, memcpy_private - sub %o0, %o1, %g5 - add %o1, %o2, %g3 - cmp %g3, %o0 - bleu,pt %xcc, memcpy_private - add %o1, %o2, %g5 - add %o0, %o2, %o5 - - sub %g5, 1, %o1 - sub %o5, 1, %o0 -1: ldub [%o1], %g5 - subcc %o2, 1, %o2 - sub %o1, 1, %o1 - stb %g5, [%o0] - bne,pt %icc, 1b - sub %o0, 1, %o0 - - retl - clr %o0 -#endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/copy_in_user.S linux-2.4.28-pre3/arch/sparc64/lib/copy_in_user.S --- linux-2.4.27/arch/sparc64/lib/copy_in_user.S 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/copy_in_user.S 2004-09-10 19:34:57.000000000 +0000 @@ -0,0 +1,114 @@ +/* copy_in_user.S: Copy from userspace to userspace. + * + * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) + */ + +#include + +#define XCC xcc + +#define EX(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: retl; \ + mov 1, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; + + .register %g2,#scratch + .register %g3,#scratch + + .text + .align 32 + + /* Don't try to get too fancy here, just nice and + * simple. This is predominantly used for well aligned + * small copies in the compat layer. It is also used + * to copy register windows around during thread cloning. + */ + + .globl ___copy_in_user +___copy_in_user: /* %o0=dst, %o1=src, %o2=len */ + /* Writing to %asi is _expensive_ so we hardcode it. + * Reading %asi to check for KERNEL_DS is comparatively + * cheap. + */ + rd %asi, %g1 + cmp %g1, ASI_AIUS + bne,pn %icc, memcpy_user_stub + nop + + cmp %o2, 0 + be,pn %XCC, 85f + or %o0, %o1, %o3 + cmp %o2, 16 + bleu,a,pn %XCC, 80f + or %o3, %o2, %o3 + + /* 16 < len <= 64 */ + andcc %o3, 0x7, %g0 + bne,pn %XCC, 90f + sub %o0, %o1, %o3 + + andn %o2, 0x7, %o4 + and %o2, 0x7, %o2 +1: subcc %o4, 0x8, %o4 + EX(ldxa [%o1] %asi, %o5) + EX(stxa %o5, [%o1 + %o3] ASI_AIUS) + bgu,pt %XCC, 1b + add %o1, 0x8, %o1 + andcc %o2, 0x4, %g0 + be,pt %XCC, 1f + nop + sub %o2, 0x4, %o2 + EX(lduwa [%o1] %asi, %o5) + EX(stwa %o5, [%o1 + %o3] ASI_AIUS) + add %o1, 0x4, %o1 +1: cmp %o2, 0 + be,pt %XCC, 85f + nop + ba,pt %xcc, 90f + nop + +80: /* 0 < len <= 16 */ + andcc %o3, 0x3, %g0 + bne,pn %XCC, 90f + sub %o0, %o1, %o3 + +82: + subcc %o2, 4, %o2 + EX(lduwa [%o1] %asi, %g1) + EX(stwa %g1, [%o1 + %o3] ASI_AIUS) + bgu,pt %XCC, 82b + add %o1, 4, %o1 + +85: retl + clr %o0 + + .align 32 +90: + subcc %o2, 1, %o2 + EX(lduba [%o1] %asi, %g1) + EX(stba %g1, [%o1 + %o3] ASI_AIUS) + bgu,pt %XCC, 90b + add %o1, 1, %o1 + retl + clr %o0 + + /* Act like copy_{to,in}_user(), ie. return zero instead + * of original destination pointer. This is invoked when + * copy_{to,in}_user() finds that %asi is kernel space. + */ + .globl memcpy_user_stub +memcpy_user_stub: + save %sp, -192, %sp + mov %i0, %o0 + mov %i1, %o1 + call memcpy + mov %i2, %o2 + ret + restore %g0, %g0, %o0 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/memmove.S linux-2.4.28-pre3/arch/sparc64/lib/memmove.S --- linux-2.4.27/arch/sparc64/lib/memmove.S 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/memmove.S 2004-09-10 19:37:12.000000000 +0000 @@ -0,0 +1,31 @@ +/* memmove.S: Simple memmove implementation. + * + * Copyright (C) 1997, 2004 David S. Miller (davem@redhat.com) + * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz) + */ + + .text + .align 32 + .globl memmove +memmove: + mov %o0, %g1 + cmp %o0, %o1 + blu,pt %xcc, memcpy + sub %o0, %o1, %g5 + add %o1, %o2, %g3 + cmp %g3, %o0 + bleu,pt %xcc, memcpy + add %o1, %o2, %g5 + add %o0, %o2, %o5 + + sub %g5, 1, %o1 + sub %o5, 1, %o0 +1: ldub [%o1], %g5 + subcc %o2, 1, %o2 + sub %o1, 1, %o1 + stb %g5, [%o0] + bne,pt %icc, 1b + sub %o0, 1, %o0 + + retl + mov %g1, %o0 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/user_fixup.c linux-2.4.28-pre3/arch/sparc64/lib/user_fixup.c --- linux-2.4.27/arch/sparc64/lib/user_fixup.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/lib/user_fixup.c 2004-09-10 19:36:14.000000000 +0000 @@ -0,0 +1,68 @@ +/* user_fixup.c: Fix up user copy faults. + * + * Copyright (C) 2004 David S. Miller + */ + +#include +#include +#include +#include +#include + +/* Calculating the exact fault address when using + * block loads and stores can be very complicated. + * Instead of trying to be clever and handling all + * of the cases, just fix things up simply here. + */ + +unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size) +{ + char *dst = to; + const char __user *src = from; + + while (size--) { + if (__get_user(*dst, src)) + break; + dst++; + src++; + } + + if (size) + memset(dst, 0, size); + + return size; +} + +unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size) +{ + char __user *dst = to; + const char *src = from; + + while (size--) { + if (__put_user(*src, dst)) + break; + dst++; + src++; + } + + return size; +} + +unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size) +{ + char __user *dst = to; + char __user *src = from; + + while (size--) { + char tmp; + + if (__get_user(tmp, src)) + break; + if (__put_user(tmp, dst)) + break; + dst++; + src++; + } + + return size; +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/mm/fault.c linux-2.4.28-pre3/arch/sparc64/mm/fault.c --- linux-2.4.27/arch/sparc64/mm/fault.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/mm/fault.c 2004-09-10 19:37:06.000000000 +0000 @@ -253,7 +253,7 @@ static void do_kernel_fault(struct pt_re * in that case. */ - if (!(fault_code & FAULT_CODE_WRITE) && + if (!(fault_code & (FAULT_CODE_WRITE|FAULT_CODE_ITLB)) && (insn & 0xc0800000) == 0xc0800000) { if (insn & 0x2000) asi = (regs->tstate >> 24); @@ -404,6 +404,16 @@ continue_fault: */ good_area: si_code = SEGV_ACCERR; + + /* If we took a ITLB miss on a non-executable page, catch + * that here. + */ + if ((fault_code & FAULT_CODE_ITLB) && !(vma->vm_flags & VM_EXEC)) { + BUG_ON(address != regs->tpc); + BUG_ON(regs->tstate & TSTATE_PRIV); + goto bad_area; + } + if (fault_code & FAULT_CODE_WRITE) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/mm/init.c linux-2.4.28-pre3/arch/sparc64/mm/init.c --- linux-2.4.27/arch/sparc64/mm/init.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/arch/sparc64/mm/init.c 2004-09-10 19:34:04.000000000 +0000 @@ -63,6 +63,7 @@ unsigned long tlb_context_cache = CTX_FI unsigned long mmu_context_bmap[CTX_BMAP_SLOTS]; /* Initial ramdisk setup */ +extern unsigned long sparc_ramdisk_image64; extern unsigned int sparc_ramdisk_image; extern unsigned int sparc_ramdisk_size; @@ -1251,10 +1252,12 @@ unsigned long __init bootmem_init(unsign #ifdef CONFIG_BLK_DEV_INITRD /* Now have to check initial ramdisk, so that bootmap does not overwrite it */ - if (sparc_ramdisk_image) { - if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE) - sparc_ramdisk_image -= KERNBASE; - initrd_start = sparc_ramdisk_image + phys_base; + if (sparc_ramdisk_image || sparc_ramdisk_image64) { + unsigned long ramdisk_image = sparc_ramdisk_image ? + sparc_ramdisk_image : sparc_ramdisk_image64; + if (ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE) + ramdisk_image -= KERNBASE; + initrd_start = ramdisk_image + phys_base; initrd_end = initrd_start + sparc_ramdisk_size; if (initrd_end > end_of_phys_memory) { printk(KERN_CRIT "initrd extends beyond end of memory " @@ -1300,6 +1303,10 @@ unsigned long __init bootmem_init(unsign initrd_start, size); #endif /* Resert the initrd image area. */ +#ifdef CONFIG_DEBUG_BOOTMEM + prom_printf("reserve_bootmem(initrd): base[%llx] size[%lx]\n", + initrd_start, initrd_end); +#endif reserve_bootmem(initrd_start, size); *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; @@ -1353,7 +1360,7 @@ void __init paging_init(void) if ((real_end > ((unsigned long)KERNBASE + 0x400000))) bigkernel = 1; #ifdef CONFIG_BLK_DEV_INITRD - if (sparc_ramdisk_image) + if (sparc_ramdisk_image || sparc_ramdisk_image64) real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size)); #endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/boot/compressed/misc.c linux-2.4.28-pre3/arch/x86_64/boot/compressed/misc.c --- linux-2.4.27/arch/x86_64/boot/compressed/misc.c 2003-06-13 14:51:32.000000000 +0000 +++ linux-2.4.28-pre3/arch/x86_64/boot/compressed/misc.c 2004-09-10 19:33:29.000000000 +0000 @@ -96,7 +96,7 @@ static void error(char *m); static void gzip_mark(void **); static void gzip_release(void **); -static void puts(const char *); +static void putstr(const char *); extern int end; static long free_mem_ptr = (long)&end; @@ -157,7 +157,7 @@ static void scroll(void) vidmem[i] = ' '; } -static void puts(const char *s) +static void putstr(const char *s) { int x,y,pos; char c; @@ -275,9 +275,9 @@ static void flush_window(void) static void error(char *x) { - puts("\n\n"); - puts(x); - puts("\n\n -- System halted"); + putstr("\n\n"); + putstr(x); + putstr("\n\n -- System halted"); while(1); } @@ -351,9 +351,9 @@ int decompress_kernel(struct moveparams else setup_output_buffer_if_we_run_high(mv); makecrc(); - puts(".\nDecompressing Linux..."); + putstr(".\nDecompressing Linux..."); gunzip(); - puts("done.\nBooting the kernel.\n"); + putstr("done.\nBooting the kernel.\n"); if (high_loaded) close_output_buffer_if_we_run_high(mv); return high_loaded; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/config.in linux-2.4.28-pre3/arch/x86_64/config.in --- linux-2.4.27/arch/x86_64/config.in 2004-04-14 13:05:28.000000000 +0000 +++ linux-2.4.28-pre3/arch/x86_64/config.in 2004-09-10 19:35:57.000000000 +0000 @@ -117,7 +117,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then define_bool CONFIG_KCORE_ELF y fi #tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT -tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC bool 'Power Management support' CONFIG_PM diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/ia32/ia32_ioctl.c linux-2.4.28-pre3/arch/x86_64/ia32/ia32_ioctl.c --- linux-2.4.27/arch/x86_64/ia32/ia32_ioctl.c 2004-04-14 13:05:28.000000000 +0000 +++ linux-2.4.28-pre3/arch/x86_64/ia32/ia32_ioctl.c 2004-09-10 19:36:33.000000000 +0000 @@ -1171,6 +1171,7 @@ static int fd_ioctl_trans(unsigned int f case FDDEFPRM32: case FDGETPRM32: { + u32 name; struct floppy_struct *f; f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); @@ -1187,7 +1188,8 @@ static int fd_ioctl_trans(unsigned int f err |= __get_user(f->rate, &((struct floppy_struct32 *)arg)->rate); err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1); err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap); - err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name); + err |= __get_user(name, &((struct floppy_struct32 *)arg)->name); + f->name = (void*)(u64)name; if (err) { err = -EFAULT; goto out; @@ -2726,13 +2728,15 @@ static int blkpg_ioctl_trans(unsigned in { struct blkpg_ioctl_arg a; struct blkpg_partition p; + u32 udata; int err; mm_segment_t old_fs = get_fs(); err = get_user(a.op, &arg->op); err |= __get_user(a.flags, &arg->flags); err |= __get_user(a.datalen, &arg->datalen); - err |= __get_user((long)a.data, &arg->data); + err |= __get_user(udata, &arg->data); + a.data = (void*)(u64)udata; if (err) return err; switch (a.op) { case BLKPG_ADD_PARTITION: diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/ia32/sys_ia32.c linux-2.4.28-pre3/arch/x86_64/ia32/sys_ia32.c --- linux-2.4.27/arch/x86_64/ia32/sys_ia32.c 2004-04-14 13:05:28.000000000 +0000 +++ linux-2.4.28-pre3/arch/x86_64/ia32/sys_ia32.c 2004-09-10 19:36:38.000000000 +0000 @@ -384,12 +384,16 @@ sys32_rt_sigaction(int sig, struct sigac return -EINVAL; if (act) { + u32 handler, restorer; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user((long)new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(handler, &act->sa_handler) || __get_user(new_ka.sa.sa_flags, &act->sa_flags) || - __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer)|| + __get_user(restorer, &act->sa_restorer)|| __copy_from_user(&set32, &act->sa_mask, sizeof(sigset32_t))) return -EFAULT; + new_ka.sa.sa_handler = (void*)(u64)handler; + new_ka.sa.sa_restorer = (void*)(u64)restorer; /* FIXME: here we rely on _IA32_NSIG_WORS to be >= than _NSIG_WORDS << 1 */ switch (_NSIG_WORDS) { @@ -441,13 +445,16 @@ sys32_sigaction (int sig, struct old_sig if (act) { old_sigset32_t mask; + u32 handler, restorer; if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user((long)new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(handler, &act->sa_handler) || __get_user(new_ka.sa.sa_flags, &act->sa_flags) || - __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer) || + __get_user(restorer, &act->sa_restorer) || __get_user(mask, &act->sa_mask)) return -EFAULT; + new_ka.sa.sa_handler = (void*)(u64)handler; + new_ka.sa.sa_restorer = (void*)(u64)restorer; siginitset(&new_ka.sa.sa_mask, mask); } @@ -778,7 +785,7 @@ filldir32 (void *__buf, const char *name put_user(reclen, &dirent->d_reclen); copy_to_user(dirent->d_name, name, namlen); put_user(0, dirent->d_name + namlen); - ((char *) dirent) += reclen; + dirent = ((void *)dirent) + reclen; buf->current_dir = dirent; buf->count -= reclen; return 0; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/kernel/x8664_ksyms.c linux-2.4.28-pre3/arch/x86_64/kernel/x8664_ksyms.c --- linux-2.4.27/arch/x86_64/kernel/x8664_ksyms.c 2004-04-14 13:05:28.000000000 +0000 +++ linux-2.4.28-pre3/arch/x86_64/kernel/x8664_ksyms.c 2004-09-10 19:35:33.000000000 +0000 @@ -157,7 +157,7 @@ extern void * memset(void *,int,__kernel extern __kernel_size_t strlen(const char *); extern int strcmp(const char *,const char *); extern char * strcpy(char *,const char *); -extern char * bcopy(const char * src, char * dest, int count); +extern void bcopy(const void * src, void * dest, size_t count); EXPORT_SYMBOL_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(__memcpy); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/lib/usercopy.c linux-2.4.28-pre3/arch/x86_64/lib/usercopy.c --- linux-2.4.27/arch/x86_64/lib/usercopy.c 2004-04-14 13:05:28.000000000 +0000 +++ linux-2.4.28-pre3/arch/x86_64/lib/usercopy.c 2004-09-10 19:35:20.000000000 +0000 @@ -88,7 +88,7 @@ unsigned long __clear_user(void *addr, u " .quad 1b,2b\n" ".previous" : [size8] "=c"(size), [dst] "=&D" (__d0) - : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst] "(addr), + : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr), [zero] "r" (0UL), [eight] "r" (8UL)); return size; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/Config.in linux-2.4.28-pre3/crypto/Config.in --- linux-2.4.27/crypto/Config.in 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/crypto/Config.in 2004-09-10 19:36:44.000000000 +0000 @@ -58,6 +58,7 @@ if [ "$CONFIG_CRYPTO" = "y" ]; then fi tristate ' SHA256 digest algorithm' CONFIG_CRYPTO_SHA256 tristate ' SHA384 and SHA512 digest algorithms' CONFIG_CRYPTO_SHA512 + tristate ' Whirlpool digest algorithm' CONFIG_CRYPTO_WHIRLPOOL if [ "$CONFIG_INET_ESP" = "y" -o \ "$CONFIG_INET_ESP" = "m" -o \ "$CONFIG_INET6_ESP" = "y" -o \ @@ -73,6 +74,7 @@ if [ "$CONFIG_CRYPTO" = "y" ]; then tristate ' CAST5 (CAST-128) cipher algorithm' CONFIG_CRYPTO_CAST5 tristate ' CAST6 (CAST-256) cipher algorithm' CONFIG_CRYPTO_CAST6 tristate ' TEA and XTEA cipher algorithms' CONFIG_CRYPTO_TEA + tristate ' Khazad cipher algorithm' CONFIG_CRYPTO_KHAZAD tristate ' ARC4 cipher algorithm' CONFIG_CRYPTO_ARC4 if [ "$CONFIG_INET_IPCOMP" = "y" -o \ "$CONFIG_INET_IPCOMP" = "m" -o \ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/Makefile linux-2.4.28-pre3/crypto/Makefile --- linux-2.4.27/crypto/Makefile 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/crypto/Makefile 2004-09-10 19:33:26.000000000 +0000 @@ -19,6 +19,7 @@ obj-$(CONFIG_CRYPTO_MD5) += md5.o obj-$(CONFIG_CRYPTO_SHA1) += sha1.o obj-$(CONFIG_CRYPTO_SHA256) += sha256.o obj-$(CONFIG_CRYPTO_SHA512) += sha512.o +obj-$(CONFIG_CRYPTO_WHIRLPOOL) += whirlpool.o obj-$(CONFIG_CRYPTO_DES) += des.o obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o @@ -28,6 +29,7 @@ obj-$(CONFIG_CRYPTO_CAST5) += cast5.o obj-$(CONFIG_CRYPTO_CAST6) += cast6.o obj-$(CONFIG_CRYPTO_ARC4) += arc4.o obj-$(CONFIG_CRYPTO_TEA) += tea.o +obj-$(CONFIG_CRYPTO_KHAZAD) += khazad.o obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/aes.c linux-2.4.28-pre3/crypto/aes.c --- linux-2.4.27/crypto/aes.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/crypto/aes.c 2004-09-10 19:33:05.000000000 +0000 @@ -160,7 +160,7 @@ gen_tabs (void) u8 p, q; /* log and power tables for GF(2**8) finite field with - 0x011b as modular polynomial - the simplest prmitive + 0x011b as modular polynomial - the simplest primitive root is 0x03, used here to generate the tables */ for (i = 0, p = 1; i < 256; ++i) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/arc4.c linux-2.4.28-pre3/crypto/arc4.c --- linux-2.4.27/crypto/arc4.c 2004-04-14 13:05:28.000000000 +0000 +++ linux-2.4.28-pre3/crypto/arc4.c 2004-09-10 19:34:57.000000000 +0000 @@ -3,7 +3,7 @@ * * ARC4 Cipher Algorithm * - * Jon Oberheide + * Jon Oberheide * * 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 @@ -100,4 +100,4 @@ module_exit(arc4_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); -MODULE_AUTHOR("Jon Oberheide "); +MODULE_AUTHOR("Jon Oberheide "); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/blowfish.c linux-2.4.28-pre3/crypto/blowfish.c --- linux-2.4.27/crypto/blowfish.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/crypto/blowfish.c 2004-09-10 19:35:48.000000000 +0000 @@ -3,9 +3,9 @@ * * Blowfish Cipher Algorithm, by Bruce Schneier. * http://www.counterpane.com/blowfish.html - * - * Adapated from Kerneli implementation. - * + * + * Adapted from Kerneli implementation. + * * Copyright (c) Herbert Valerio Riedel * Copyright (c) Kyle McMartin * Copyright (c) 2002 James Morris diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/khazad.c linux-2.4.28-pre3/crypto/khazad.c --- linux-2.4.27/crypto/khazad.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/crypto/khazad.c 2004-09-10 19:35:59.000000000 +0000 @@ -0,0 +1,915 @@ +/* + * Cryptographic API. + * + * Khazad Algorithm + * + * The Khazad algorithm was developed by Paulo S. L. M. Barreto and + * Vincent Rijmen. It was a finalist in the NESSIE encryption contest. + * + * The original authors have disclaimed all copyright interest in this + * code and thus put it in the public domain. The subsequent authors + * have put this under the GNU General Public License. + * + * By Aaron Grothe ajgrothe@yahoo.com, August 1, 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include + +#define KHAZAD_KEY_SIZE 16 +#define KHAZAD_BLOCK_SIZE 8 +#define KHAZAD_ROUNDS 8 + +struct khazad_ctx { + u64 E[KHAZAD_ROUNDS + 1]; + u64 D[KHAZAD_ROUNDS + 1]; +}; + +static const u64 T0[256] = { + 0xbad3d268bbb96a01ULL, 0x54fc4d19e59a66b1ULL, 0x2f71bc93e26514cdULL, + 0x749ccdb925871b51ULL, 0x53f55102f7a257a4ULL, 0xd3686bb8d0d6be03ULL, + 0xd26b6fbdd6deb504ULL, 0x4dd72964b35285feULL, 0x50f05d0dfdba4aadULL, + 0xace98a26cf09e063ULL, 0x8d8a0e83091c9684ULL, 0xbfdcc679a5914d1aULL, + 0x7090ddad3da7374dULL, 0x52f65507f1aa5ca3ULL, 0x9ab352c87ba417e1ULL, + 0x4cd42d61b55a8ef9ULL, 0xea238f65460320acULL, 0xd56273a6c4e68411ULL, + 0x97a466f155cc68c2ULL, 0xd16e63b2dcc6a80dULL, 0x3355ccffaa85d099ULL, + 0x51f35908fbb241aaULL, 0x5bed712ac7e20f9cULL, 0xa6f7a204f359ae55ULL, + 0xde7f5f81febec120ULL, 0x48d83d75ad7aa2e5ULL, 0xa8e59a32d729cc7fULL, + 0x99b65ec771bc0ae8ULL, 0xdb704b90e096e63bULL, 0x3256c8faac8ddb9eULL, + 0xb7c4e65195d11522ULL, 0xfc19d72b32b3aaceULL, 0xe338ab48704b7393ULL, + 0x9ebf42dc63843bfdULL, 0x91ae7eef41fc52d0ULL, 0x9bb056cd7dac1ce6ULL, + 0xe23baf4d76437894ULL, 0xbbd0d66dbdb16106ULL, 0x41c319589b32f1daULL, + 0x6eb2a5cb7957e517ULL, 0xa5f2ae0bf941b35cULL, 0xcb400bc08016564bULL, + 0x6bbdb1da677fc20cULL, 0x95a26efb59dc7eccULL, 0xa1febe1fe1619f40ULL, + 0xf308eb1810cbc3e3ULL, 0xb1cefe4f81e12f30ULL, 0x0206080a0c10160eULL, + 0xcc4917db922e675eULL, 0xc45137f3a26e3f66ULL, 0x1d2774694ee8cf53ULL, + 0x143c504478a09c6cULL, 0xc3582be8b0560e73ULL, 0x63a591f2573f9a34ULL, + 0xda734f95e69eed3cULL, 0x5de76934d3d2358eULL, 0x5fe1613edfc22380ULL, + 0xdc79578bf2aed72eULL, 0x7d87e99413cf486eULL, 0xcd4a13de94266c59ULL, + 0x7f81e19e1fdf5e60ULL, 0x5aee752fc1ea049bULL, 0x6cb4adc17547f319ULL, + 0x5ce46d31d5da3e89ULL, 0xf704fb0c08ebefffULL, 0x266a98bed42d47f2ULL, + 0xff1cdb2438abb7c7ULL, 0xed2a937e543b11b9ULL, 0xe825876f4a1336a2ULL, + 0x9dba4ed3699c26f4ULL, 0x6fb1a1ce7f5fee10ULL, 0x8e8f028c03048b8dULL, + 0x192b647d56c8e34fULL, 0xa0fdba1ae7699447ULL, 0xf00de7171ad3deeaULL, + 0x89861e97113cba98ULL, 0x0f113c332278692dULL, 0x07091c1b12383115ULL, + 0xafec8629c511fd6aULL, 0xfb10cb30208b9bdbULL, 0x0818202830405838ULL, + 0x153f54417ea8976bULL, 0x0d1734392e687f23ULL, 0x040c101418202c1cULL, + 0x0103040506080b07ULL, 0x64ac8de94507ab21ULL, 0xdf7c5b84f8b6ca27ULL, + 0x769ac5b329970d5fULL, 0x798bf9800bef6472ULL, 0xdd7a538ef4a6dc29ULL, + 0x3d47f4c98ef5b2b3ULL, 0x163a584e74b08a62ULL, 0x3f41fcc382e5a4bdULL, + 0x3759dcebb2a5fc85ULL, 0x6db7a9c4734ff81eULL, 0x3848e0d890dd95a8ULL, + 0xb9d6de67b1a17708ULL, 0x7395d1a237bf2a44ULL, 0xe926836a4c1b3da5ULL, + 0x355fd4e1beb5ea8bULL, 0x55ff491ce3926db6ULL, 0x7193d9a83baf3c4aULL, + 0x7b8df18a07ff727cULL, 0x8c890a860f149d83ULL, 0x7296d5a731b72143ULL, + 0x88851a921734b19fULL, 0xf607ff090ee3e4f8ULL, 0x2a7ea882fc4d33d6ULL, + 0x3e42f8c684edafbaULL, 0x5ee2653bd9ca2887ULL, 0x27699cbbd2254cf5ULL, + 0x46ca0543890ac0cfULL, 0x0c14303c28607424ULL, 0x65af89ec430fa026ULL, + 0x68b8bdd56d67df05ULL, 0x61a399f85b2f8c3aULL, 0x03050c0f0a181d09ULL, + 0xc15e23e2bc46187dULL, 0x57f94116ef827bb8ULL, 0xd6677fa9cefe9918ULL, + 0xd976439aec86f035ULL, 0x58e87d25cdfa1295ULL, 0xd875479fea8efb32ULL, + 0x66aa85e34917bd2fULL, 0xd7647bacc8f6921fULL, 0x3a4ee8d29ccd83a6ULL, + 0xc84507cf8a0e4b42ULL, 0x3c44f0cc88fdb9b4ULL, 0xfa13cf35268390dcULL, + 0x96a762f453c463c5ULL, 0xa7f4a601f551a552ULL, 0x98b55ac277b401efULL, + 0xec29977b52331abeULL, 0xb8d5da62b7a97c0fULL, 0xc7543bfca876226fULL, + 0xaeef822cc319f66dULL, 0x69bbb9d06b6fd402ULL, 0x4bdd317aa762bfecULL, + 0xabe0963ddd31d176ULL, 0xa9e69e37d121c778ULL, 0x67a981e64f1fb628ULL, + 0x0a1e28223c504e36ULL, 0x47c901468f02cbc8ULL, 0xf20bef1d16c3c8e4ULL, + 0xb5c2ee5b99c1032cULL, 0x226688aacc0d6beeULL, 0xe532b356647b4981ULL, + 0xee2f9f715e230cb0ULL, 0xbedfc27ca399461dULL, 0x2b7dac87fa4538d1ULL, + 0x819e3ebf217ce2a0ULL, 0x1236485a6c90a67eULL, 0x839836b52d6cf4aeULL, + 0x1b2d6c775ad8f541ULL, 0x0e1238362470622aULL, 0x23658cafca0560e9ULL, + 0xf502f30604fbf9f1ULL, 0x45cf094c8312ddc6ULL, 0x216384a5c61576e7ULL, + 0xce4f1fd19e3e7150ULL, 0x49db3970ab72a9e2ULL, 0x2c74b09ce87d09c4ULL, + 0xf916c33a2c9b8dd5ULL, 0xe637bf596e635488ULL, 0xb6c7e25493d91e25ULL, + 0x2878a088f05d25d8ULL, 0x17395c4b72b88165ULL, 0x829b32b02b64ffa9ULL, + 0x1a2e68725cd0fe46ULL, 0x8b80169d1d2cac96ULL, 0xfe1fdf213ea3bcc0ULL, + 0x8a8312981b24a791ULL, 0x091b242d3648533fULL, 0xc94603ca8c064045ULL, + 0x879426a1354cd8b2ULL, 0x4ed2256bb94a98f7ULL, 0xe13ea3427c5b659dULL, + 0x2e72b896e46d1fcaULL, 0xe431b75362734286ULL, 0xe03da7477a536e9aULL, + 0xeb208b60400b2babULL, 0x90ad7aea47f459d7ULL, 0xa4f1aa0eff49b85bULL, + 0x1e22786644f0d25aULL, 0x85922eab395ccebcULL, 0x60a09dfd5d27873dULL, + 0x0000000000000000ULL, 0x256f94b1de355afbULL, 0xf401f70302f3f2f6ULL, + 0xf10ee3121cdbd5edULL, 0x94a16afe5fd475cbULL, 0x0b1d2c273a584531ULL, + 0xe734bb5c686b5f8fULL, 0x759fc9bc238f1056ULL, 0xef2c9b74582b07b7ULL, + 0x345cd0e4b8bde18cULL, 0x3153c4f5a695c697ULL, 0xd46177a3c2ee8f16ULL, + 0xd06d67b7dacea30aULL, 0x869722a43344d3b5ULL, 0x7e82e59b19d75567ULL, + 0xadea8e23c901eb64ULL, 0xfd1ad32e34bba1c9ULL, 0x297ba48df6552edfULL, + 0x3050c0f0a09dcd90ULL, 0x3b4decd79ac588a1ULL, 0x9fbc46d9658c30faULL, + 0xf815c73f2a9386d2ULL, 0xc6573ff9ae7e2968ULL, 0x13354c5f6a98ad79ULL, + 0x060a181e14303a12ULL, 0x050f14111e28271bULL, 0xc55233f6a4663461ULL, + 0x113344556688bb77ULL, 0x7799c1b62f9f0658ULL, 0x7c84ed9115c74369ULL, + 0x7a8ef58f01f7797bULL, 0x7888fd850de76f75ULL, 0x365ad8eeb4adf782ULL, + 0x1c24706c48e0c454ULL, 0x394be4dd96d59eafULL, 0x59eb7920cbf21992ULL, + 0x1828607850c0e848ULL, 0x56fa4513e98a70bfULL, 0xb3c8f6458df1393eULL, + 0xb0cdfa4a87e92437ULL, 0x246c90b4d83d51fcULL, 0x206080a0c01d7de0ULL, + 0xb2cbf2408bf93239ULL, 0x92ab72e04be44fd9ULL, 0xa3f8b615ed71894eULL, + 0xc05d27e7ba4e137aULL, 0x44cc0d49851ad6c1ULL, 0x62a695f751379133ULL, + 0x103040506080b070ULL, 0xb4c1ea5e9fc9082bULL, 0x84912aae3f54c5bbULL, + 0x43c511529722e7d4ULL, 0x93a876e54dec44deULL, 0xc25b2fedb65e0574ULL, + 0x4ade357fa16ab4ebULL, 0xbddace73a9815b14ULL, 0x8f8c0689050c808aULL, + 0x2d77b499ee7502c3ULL, 0xbcd9ca76af895013ULL, 0x9cb94ad66f942df3ULL, + 0x6abeb5df6177c90bULL, 0x40c01d5d9d3afaddULL, 0xcf4c1bd498367a57ULL, + 0xa2fbb210eb798249ULL, 0x809d3aba2774e9a7ULL, 0x4fd1216ebf4293f0ULL, + 0x1f217c6342f8d95dULL, 0xca430fc5861e5d4cULL, 0xaae39238db39da71ULL, + 0x42c61557912aecd3ULL +}; + +static const u64 T1[256] = { + 0xd3ba68d2b9bb016aULL, 0xfc54194d9ae5b166ULL, 0x712f93bc65e2cd14ULL, + 0x9c74b9cd8725511bULL, 0xf5530251a2f7a457ULL, 0x68d3b86bd6d003beULL, + 0x6bd2bd6fded604b5ULL, 0xd74d642952b3fe85ULL, 0xf0500d5dbafdad4aULL, + 0xe9ac268a09cf63e0ULL, 0x8a8d830e1c098496ULL, 0xdcbf79c691a51a4dULL, + 0x9070addda73d4d37ULL, 0xf6520755aaf1a35cULL, 0xb39ac852a47be117ULL, + 0xd44c612d5ab5f98eULL, 0x23ea658f0346ac20ULL, 0x62d5a673e6c41184ULL, + 0xa497f166cc55c268ULL, 0x6ed1b263c6dc0da8ULL, 0x5533ffcc85aa99d0ULL, + 0xf3510859b2fbaa41ULL, 0xed5b2a71e2c79c0fULL, 0xf7a604a259f355aeULL, + 0x7fde815fbefe20c1ULL, 0xd848753d7aade5a2ULL, 0xe5a8329a29d77fccULL, + 0xb699c75ebc71e80aULL, 0x70db904b96e03be6ULL, 0x5632fac88dac9edbULL, + 0xc4b751e6d1952215ULL, 0x19fc2bd7b332ceaaULL, 0x38e348ab4b709373ULL, + 0xbf9edc428463fd3bULL, 0xae91ef7efc41d052ULL, 0xb09bcd56ac7de61cULL, + 0x3be24daf43769478ULL, 0xd0bb6dd6b1bd0661ULL, 0xc3415819329bdaf1ULL, + 0xb26ecba5577917e5ULL, 0xf2a50bae41f95cb3ULL, 0x40cbc00b16804b56ULL, + 0xbd6bdab17f670cc2ULL, 0xa295fb6edc59cc7eULL, 0xfea11fbe61e1409fULL, + 0x08f318ebcb10e3c3ULL, 0xceb14ffee181302fULL, 0x06020a08100c0e16ULL, + 0x49ccdb172e925e67ULL, 0x51c4f3376ea2663fULL, 0x271d6974e84e53cfULL, + 0x3c144450a0786c9cULL, 0x58c3e82b56b0730eULL, 0xa563f2913f57349aULL, + 0x73da954f9ee63cedULL, 0xe75d3469d2d38e35ULL, 0xe15f3e61c2df8023ULL, + 0x79dc8b57aef22ed7ULL, 0x877d94e9cf136e48ULL, 0x4acdde132694596cULL, + 0x817f9ee1df1f605eULL, 0xee5a2f75eac19b04ULL, 0xb46cc1ad477519f3ULL, + 0xe45c316ddad5893eULL, 0x04f70cfbeb08ffefULL, 0x6a26be982dd4f247ULL, + 0x1cff24dbab38c7b7ULL, 0x2aed7e933b54b911ULL, 0x25e86f87134aa236ULL, + 0xba9dd34e9c69f426ULL, 0xb16fcea15f7f10eeULL, 0x8f8e8c0204038d8bULL, + 0x2b197d64c8564fe3ULL, 0xfda01aba69e74794ULL, 0x0df017e7d31aeadeULL, + 0x8689971e3c1198baULL, 0x110f333c78222d69ULL, 0x09071b1c38121531ULL, + 0xecaf298611c56afdULL, 0x10fb30cb8b20db9bULL, 0x1808282040303858ULL, + 0x3f154154a87e6b97ULL, 0x170d3934682e237fULL, 0x0c04141020181c2cULL, + 0x030105040806070bULL, 0xac64e98d074521abULL, 0x7cdf845bb6f827caULL, + 0x9a76b3c597295f0dULL, 0x8b7980f9ef0b7264ULL, 0x7add8e53a6f429dcULL, + 0x473dc9f4f58eb3b2ULL, 0x3a164e58b074628aULL, 0x413fc3fce582bda4ULL, + 0x5937ebdca5b285fcULL, 0xb76dc4a94f731ef8ULL, 0x4838d8e0dd90a895ULL, + 0xd6b967dea1b10877ULL, 0x9573a2d1bf37442aULL, 0x26e96a831b4ca53dULL, + 0x5f35e1d4b5be8beaULL, 0xff551c4992e3b66dULL, 0x9371a8d9af3b4a3cULL, + 0x8d7b8af1ff077c72ULL, 0x898c860a140f839dULL, 0x9672a7d5b7314321ULL, + 0x8588921a34179fb1ULL, 0x07f609ffe30ef8e4ULL, 0x7e2a82a84dfcd633ULL, + 0x423ec6f8ed84baafULL, 0xe25e3b65cad98728ULL, 0x6927bb9c25d2f54cULL, + 0xca4643050a89cfc0ULL, 0x140c3c3060282474ULL, 0xaf65ec890f4326a0ULL, + 0xb868d5bd676d05dfULL, 0xa361f8992f5b3a8cULL, 0x05030f0c180a091dULL, + 0x5ec1e22346bc7d18ULL, 0xf957164182efb87bULL, 0x67d6a97ffece1899ULL, + 0x76d99a4386ec35f0ULL, 0xe858257dfacd9512ULL, 0x75d89f478eea32fbULL, + 0xaa66e38517492fbdULL, 0x64d7ac7bf6c81f92ULL, 0x4e3ad2e8cd9ca683ULL, + 0x45c8cf070e8a424bULL, 0x443cccf0fd88b4b9ULL, 0x13fa35cf8326dc90ULL, + 0xa796f462c453c563ULL, 0xf4a701a651f552a5ULL, 0xb598c25ab477ef01ULL, + 0x29ec7b973352be1aULL, 0xd5b862daa9b70f7cULL, 0x54c7fc3b76a86f22ULL, + 0xefae2c8219c36df6ULL, 0xbb69d0b96f6b02d4ULL, 0xdd4b7a3162a7ecbfULL, + 0xe0ab3d9631dd76d1ULL, 0xe6a9379e21d178c7ULL, 0xa967e6811f4f28b6ULL, + 0x1e0a2228503c364eULL, 0xc9474601028fc8cbULL, 0x0bf21defc316e4c8ULL, + 0xc2b55beec1992c03ULL, 0x6622aa880dccee6bULL, 0x32e556b37b648149ULL, + 0x2fee719f235eb00cULL, 0xdfbe7cc299a31d46ULL, 0x7d2b87ac45fad138ULL, + 0x9e81bf3e7c21a0e2ULL, 0x36125a48906c7ea6ULL, 0x9883b5366c2daef4ULL, + 0x2d1b776cd85a41f5ULL, 0x120e363870242a62ULL, 0x6523af8c05cae960ULL, + 0x02f506f3fb04f1f9ULL, 0xcf454c091283c6ddULL, 0x6321a58415c6e776ULL, + 0x4fced11f3e9e5071ULL, 0xdb49703972abe2a9ULL, 0x742c9cb07de8c409ULL, + 0x16f93ac39b2cd58dULL, 0x37e659bf636e8854ULL, 0xc7b654e2d993251eULL, + 0x782888a05df0d825ULL, 0x39174b5cb8726581ULL, 0x9b82b032642ba9ffULL, + 0x2e1a7268d05c46feULL, 0x808b9d162c1d96acULL, 0x1ffe21dfa33ec0bcULL, + 0x838a9812241b91a7ULL, 0x1b092d2448363f53ULL, 0x46c9ca03068c4540ULL, + 0x9487a1264c35b2d8ULL, 0xd24e6b254ab9f798ULL, 0x3ee142a35b7c9d65ULL, + 0x722e96b86de4ca1fULL, 0x31e453b773628642ULL, 0x3de047a7537a9a6eULL, + 0x20eb608b0b40ab2bULL, 0xad90ea7af447d759ULL, 0xf1a40eaa49ff5bb8ULL, + 0x221e6678f0445ad2ULL, 0x9285ab2e5c39bcceULL, 0xa060fd9d275d3d87ULL, + 0x0000000000000000ULL, 0x6f25b19435defb5aULL, 0x01f403f7f302f6f2ULL, + 0x0ef112e3db1cedd5ULL, 0xa194fe6ad45fcb75ULL, 0x1d0b272c583a3145ULL, + 0x34e75cbb6b688f5fULL, 0x9f75bcc98f235610ULL, 0x2cef749b2b58b707ULL, + 0x5c34e4d0bdb88ce1ULL, 0x5331f5c495a697c6ULL, 0x61d4a377eec2168fULL, + 0x6dd0b767ceda0aa3ULL, 0x9786a4224433b5d3ULL, 0x827e9be5d7196755ULL, + 0xeaad238e01c964ebULL, 0x1afd2ed3bb34c9a1ULL, 0x7b298da455f6df2eULL, + 0x5030f0c09da090cdULL, 0x4d3bd7ecc59aa188ULL, 0xbc9fd9468c65fa30ULL, + 0x15f83fc7932ad286ULL, 0x57c6f93f7eae6829ULL, 0x35135f4c986a79adULL, + 0x0a061e183014123aULL, 0x0f051114281e1b27ULL, 0x52c5f63366a46134ULL, + 0x33115544886677bbULL, 0x9977b6c19f2f5806ULL, 0x847c91edc7156943ULL, + 0x8e7a8ff5f7017b79ULL, 0x887885fde70d756fULL, 0x5a36eed8adb482f7ULL, + 0x241c6c70e04854c4ULL, 0x4b39dde4d596af9eULL, 0xeb592079f2cb9219ULL, + 0x28187860c05048e8ULL, 0xfa5613458ae9bf70ULL, 0xc8b345f6f18d3e39ULL, + 0xcdb04afae9873724ULL, 0x6c24b4903dd8fc51ULL, 0x6020a0801dc0e07dULL, + 0xcbb240f2f98b3932ULL, 0xab92e072e44bd94fULL, 0xf8a315b671ed4e89ULL, + 0x5dc0e7274eba7a13ULL, 0xcc44490d1a85c1d6ULL, 0xa662f79537513391ULL, + 0x30105040806070b0ULL, 0xc1b45eeac99f2b08ULL, 0x9184ae2a543fbbc5ULL, + 0xc54352112297d4e7ULL, 0xa893e576ec4dde44ULL, 0x5bc2ed2f5eb67405ULL, + 0xde4a7f356aa1ebb4ULL, 0xdabd73ce81a9145bULL, 0x8c8f89060c058a80ULL, + 0x772d99b475eec302ULL, 0xd9bc76ca89af1350ULL, 0xb99cd64a946ff32dULL, + 0xbe6adfb577610bc9ULL, 0xc0405d1d3a9dddfaULL, 0x4ccfd41b3698577aULL, + 0xfba210b279eb4982ULL, 0x9d80ba3a7427a7e9ULL, 0xd14f6e2142bff093ULL, + 0x211f637cf8425dd9ULL, 0x43cac50f1e864c5dULL, 0xe3aa389239db71daULL, + 0xc64257152a91d3ecULL +}; + +static const u64 T2[256] = { + 0xd268bad36a01bbb9ULL, 0x4d1954fc66b1e59aULL, 0xbc932f7114cde265ULL, + 0xcdb9749c1b512587ULL, 0x510253f557a4f7a2ULL, 0x6bb8d368be03d0d6ULL, + 0x6fbdd26bb504d6deULL, 0x29644dd785feb352ULL, 0x5d0d50f04aadfdbaULL, + 0x8a26ace9e063cf09ULL, 0x0e838d8a9684091cULL, 0xc679bfdc4d1aa591ULL, + 0xddad7090374d3da7ULL, 0x550752f65ca3f1aaULL, 0x52c89ab317e17ba4ULL, + 0x2d614cd48ef9b55aULL, 0x8f65ea2320ac4603ULL, 0x73a6d5628411c4e6ULL, + 0x66f197a468c255ccULL, 0x63b2d16ea80ddcc6ULL, 0xccff3355d099aa85ULL, + 0x590851f341aafbb2ULL, 0x712a5bed0f9cc7e2ULL, 0xa204a6f7ae55f359ULL, + 0x5f81de7fc120febeULL, 0x3d7548d8a2e5ad7aULL, 0x9a32a8e5cc7fd729ULL, + 0x5ec799b60ae871bcULL, 0x4b90db70e63be096ULL, 0xc8fa3256db9eac8dULL, + 0xe651b7c4152295d1ULL, 0xd72bfc19aace32b3ULL, 0xab48e3387393704bULL, + 0x42dc9ebf3bfd6384ULL, 0x7eef91ae52d041fcULL, 0x56cd9bb01ce67dacULL, + 0xaf4de23b78947643ULL, 0xd66dbbd06106bdb1ULL, 0x195841c3f1da9b32ULL, + 0xa5cb6eb2e5177957ULL, 0xae0ba5f2b35cf941ULL, 0x0bc0cb40564b8016ULL, + 0xb1da6bbdc20c677fULL, 0x6efb95a27ecc59dcULL, 0xbe1fa1fe9f40e161ULL, + 0xeb18f308c3e310cbULL, 0xfe4fb1ce2f3081e1ULL, 0x080a0206160e0c10ULL, + 0x17dbcc49675e922eULL, 0x37f3c4513f66a26eULL, 0x74691d27cf534ee8ULL, + 0x5044143c9c6c78a0ULL, 0x2be8c3580e73b056ULL, 0x91f263a59a34573fULL, + 0x4f95da73ed3ce69eULL, 0x69345de7358ed3d2ULL, 0x613e5fe12380dfc2ULL, + 0x578bdc79d72ef2aeULL, 0xe9947d87486e13cfULL, 0x13decd4a6c599426ULL, + 0xe19e7f815e601fdfULL, 0x752f5aee049bc1eaULL, 0xadc16cb4f3197547ULL, + 0x6d315ce43e89d5daULL, 0xfb0cf704efff08ebULL, 0x98be266a47f2d42dULL, + 0xdb24ff1cb7c738abULL, 0x937eed2a11b9543bULL, 0x876fe82536a24a13ULL, + 0x4ed39dba26f4699cULL, 0xa1ce6fb1ee107f5fULL, 0x028c8e8f8b8d0304ULL, + 0x647d192be34f56c8ULL, 0xba1aa0fd9447e769ULL, 0xe717f00ddeea1ad3ULL, + 0x1e978986ba98113cULL, 0x3c330f11692d2278ULL, 0x1c1b070931151238ULL, + 0x8629afecfd6ac511ULL, 0xcb30fb109bdb208bULL, 0x2028081858383040ULL, + 0x5441153f976b7ea8ULL, 0x34390d177f232e68ULL, 0x1014040c2c1c1820ULL, + 0x040501030b070608ULL, 0x8de964acab214507ULL, 0x5b84df7cca27f8b6ULL, + 0xc5b3769a0d5f2997ULL, 0xf980798b64720befULL, 0x538edd7adc29f4a6ULL, + 0xf4c93d47b2b38ef5ULL, 0x584e163a8a6274b0ULL, 0xfcc33f41a4bd82e5ULL, + 0xdceb3759fc85b2a5ULL, 0xa9c46db7f81e734fULL, 0xe0d8384895a890ddULL, + 0xde67b9d67708b1a1ULL, 0xd1a273952a4437bfULL, 0x836ae9263da54c1bULL, + 0xd4e1355fea8bbeb5ULL, 0x491c55ff6db6e392ULL, 0xd9a871933c4a3bafULL, + 0xf18a7b8d727c07ffULL, 0x0a868c899d830f14ULL, 0xd5a77296214331b7ULL, + 0x1a928885b19f1734ULL, 0xff09f607e4f80ee3ULL, 0xa8822a7e33d6fc4dULL, + 0xf8c63e42afba84edULL, 0x653b5ee22887d9caULL, 0x9cbb27694cf5d225ULL, + 0x054346cac0cf890aULL, 0x303c0c1474242860ULL, 0x89ec65afa026430fULL, + 0xbdd568b8df056d67ULL, 0x99f861a38c3a5b2fULL, 0x0c0f03051d090a18ULL, + 0x23e2c15e187dbc46ULL, 0x411657f97bb8ef82ULL, 0x7fa9d6679918cefeULL, + 0x439ad976f035ec86ULL, 0x7d2558e81295cdfaULL, 0x479fd875fb32ea8eULL, + 0x85e366aabd2f4917ULL, 0x7bacd764921fc8f6ULL, 0xe8d23a4e83a69ccdULL, + 0x07cfc8454b428a0eULL, 0xf0cc3c44b9b488fdULL, 0xcf35fa1390dc2683ULL, + 0x62f496a763c553c4ULL, 0xa601a7f4a552f551ULL, 0x5ac298b501ef77b4ULL, + 0x977bec291abe5233ULL, 0xda62b8d57c0fb7a9ULL, 0x3bfcc754226fa876ULL, + 0x822caeeff66dc319ULL, 0xb9d069bbd4026b6fULL, 0x317a4bddbfeca762ULL, + 0x963dabe0d176dd31ULL, 0x9e37a9e6c778d121ULL, 0x81e667a9b6284f1fULL, + 0x28220a1e4e363c50ULL, 0x014647c9cbc88f02ULL, 0xef1df20bc8e416c3ULL, + 0xee5bb5c2032c99c1ULL, 0x88aa22666beecc0dULL, 0xb356e5324981647bULL, + 0x9f71ee2f0cb05e23ULL, 0xc27cbedf461da399ULL, 0xac872b7d38d1fa45ULL, + 0x3ebf819ee2a0217cULL, 0x485a1236a67e6c90ULL, 0x36b58398f4ae2d6cULL, + 0x6c771b2df5415ad8ULL, 0x38360e12622a2470ULL, 0x8caf236560e9ca05ULL, + 0xf306f502f9f104fbULL, 0x094c45cfddc68312ULL, 0x84a5216376e7c615ULL, + 0x1fd1ce4f71509e3eULL, 0x397049dba9e2ab72ULL, 0xb09c2c7409c4e87dULL, + 0xc33af9168dd52c9bULL, 0xbf59e63754886e63ULL, 0xe254b6c71e2593d9ULL, + 0xa088287825d8f05dULL, 0x5c4b1739816572b8ULL, 0x32b0829bffa92b64ULL, + 0x68721a2efe465cd0ULL, 0x169d8b80ac961d2cULL, 0xdf21fe1fbcc03ea3ULL, + 0x12988a83a7911b24ULL, 0x242d091b533f3648ULL, 0x03cac94640458c06ULL, + 0x26a18794d8b2354cULL, 0x256b4ed298f7b94aULL, 0xa342e13e659d7c5bULL, + 0xb8962e721fcae46dULL, 0xb753e43142866273ULL, 0xa747e03d6e9a7a53ULL, + 0x8b60eb202bab400bULL, 0x7aea90ad59d747f4ULL, 0xaa0ea4f1b85bff49ULL, + 0x78661e22d25a44f0ULL, 0x2eab8592cebc395cULL, 0x9dfd60a0873d5d27ULL, + 0x0000000000000000ULL, 0x94b1256f5afbde35ULL, 0xf703f401f2f602f3ULL, + 0xe312f10ed5ed1cdbULL, 0x6afe94a175cb5fd4ULL, 0x2c270b1d45313a58ULL, + 0xbb5ce7345f8f686bULL, 0xc9bc759f1056238fULL, 0x9b74ef2c07b7582bULL, + 0xd0e4345ce18cb8bdULL, 0xc4f53153c697a695ULL, 0x77a3d4618f16c2eeULL, + 0x67b7d06da30adaceULL, 0x22a48697d3b53344ULL, 0xe59b7e82556719d7ULL, + 0x8e23adeaeb64c901ULL, 0xd32efd1aa1c934bbULL, 0xa48d297b2edff655ULL, + 0xc0f03050cd90a09dULL, 0xecd73b4d88a19ac5ULL, 0x46d99fbc30fa658cULL, + 0xc73ff81586d22a93ULL, 0x3ff9c6572968ae7eULL, 0x4c5f1335ad796a98ULL, + 0x181e060a3a121430ULL, 0x1411050f271b1e28ULL, 0x33f6c5523461a466ULL, + 0x44551133bb776688ULL, 0xc1b6779906582f9fULL, 0xed917c84436915c7ULL, + 0xf58f7a8e797b01f7ULL, 0xfd8578886f750de7ULL, 0xd8ee365af782b4adULL, + 0x706c1c24c45448e0ULL, 0xe4dd394b9eaf96d5ULL, 0x792059eb1992cbf2ULL, + 0x60781828e84850c0ULL, 0x451356fa70bfe98aULL, 0xf645b3c8393e8df1ULL, + 0xfa4ab0cd243787e9ULL, 0x90b4246c51fcd83dULL, 0x80a020607de0c01dULL, + 0xf240b2cb32398bf9ULL, 0x72e092ab4fd94be4ULL, 0xb615a3f8894eed71ULL, + 0x27e7c05d137aba4eULL, 0x0d4944ccd6c1851aULL, 0x95f762a691335137ULL, + 0x40501030b0706080ULL, 0xea5eb4c1082b9fc9ULL, 0x2aae8491c5bb3f54ULL, + 0x115243c5e7d49722ULL, 0x76e593a844de4decULL, 0x2fedc25b0574b65eULL, + 0x357f4adeb4eba16aULL, 0xce73bdda5b14a981ULL, 0x06898f8c808a050cULL, + 0xb4992d7702c3ee75ULL, 0xca76bcd95013af89ULL, 0x4ad69cb92df36f94ULL, + 0xb5df6abec90b6177ULL, 0x1d5d40c0fadd9d3aULL, 0x1bd4cf4c7a579836ULL, + 0xb210a2fb8249eb79ULL, 0x3aba809de9a72774ULL, 0x216e4fd193f0bf42ULL, + 0x7c631f21d95d42f8ULL, 0x0fc5ca435d4c861eULL, 0x9238aae3da71db39ULL, + 0x155742c6ecd3912aULL +}; + +static const u64 T3[256] = { + 0x68d2d3ba016ab9bbULL, 0x194dfc54b1669ae5ULL, 0x93bc712fcd1465e2ULL, + 0xb9cd9c74511b8725ULL, 0x0251f553a457a2f7ULL, 0xb86b68d303bed6d0ULL, + 0xbd6f6bd204b5ded6ULL, 0x6429d74dfe8552b3ULL, 0x0d5df050ad4abafdULL, + 0x268ae9ac63e009cfULL, 0x830e8a8d84961c09ULL, 0x79c6dcbf1a4d91a5ULL, + 0xaddd90704d37a73dULL, 0x0755f652a35caaf1ULL, 0xc852b39ae117a47bULL, + 0x612dd44cf98e5ab5ULL, 0x658f23eaac200346ULL, 0xa67362d51184e6c4ULL, + 0xf166a497c268cc55ULL, 0xb2636ed10da8c6dcULL, 0xffcc553399d085aaULL, + 0x0859f351aa41b2fbULL, 0x2a71ed5b9c0fe2c7ULL, 0x04a2f7a655ae59f3ULL, + 0x815f7fde20c1befeULL, 0x753dd848e5a27aadULL, 0x329ae5a87fcc29d7ULL, + 0xc75eb699e80abc71ULL, 0x904b70db3be696e0ULL, 0xfac856329edb8dacULL, + 0x51e6c4b72215d195ULL, 0x2bd719fcceaab332ULL, 0x48ab38e393734b70ULL, + 0xdc42bf9efd3b8463ULL, 0xef7eae91d052fc41ULL, 0xcd56b09be61cac7dULL, + 0x4daf3be294784376ULL, 0x6dd6d0bb0661b1bdULL, 0x5819c341daf1329bULL, + 0xcba5b26e17e55779ULL, 0x0baef2a55cb341f9ULL, 0xc00b40cb4b561680ULL, + 0xdab1bd6b0cc27f67ULL, 0xfb6ea295cc7edc59ULL, 0x1fbefea1409f61e1ULL, + 0x18eb08f3e3c3cb10ULL, 0x4ffeceb1302fe181ULL, 0x0a0806020e16100cULL, + 0xdb1749cc5e672e92ULL, 0xf33751c4663f6ea2ULL, 0x6974271d53cfe84eULL, + 0x44503c146c9ca078ULL, 0xe82b58c3730e56b0ULL, 0xf291a563349a3f57ULL, + 0x954f73da3ced9ee6ULL, 0x3469e75d8e35d2d3ULL, 0x3e61e15f8023c2dfULL, + 0x8b5779dc2ed7aef2ULL, 0x94e9877d6e48cf13ULL, 0xde134acd596c2694ULL, + 0x9ee1817f605edf1fULL, 0x2f75ee5a9b04eac1ULL, 0xc1adb46c19f34775ULL, + 0x316de45c893edad5ULL, 0x0cfb04f7ffefeb08ULL, 0xbe986a26f2472dd4ULL, + 0x24db1cffc7b7ab38ULL, 0x7e932aedb9113b54ULL, 0x6f8725e8a236134aULL, + 0xd34eba9df4269c69ULL, 0xcea1b16f10ee5f7fULL, 0x8c028f8e8d8b0403ULL, + 0x7d642b194fe3c856ULL, 0x1abafda0479469e7ULL, 0x17e70df0eaded31aULL, + 0x971e868998ba3c11ULL, 0x333c110f2d697822ULL, 0x1b1c090715313812ULL, + 0x2986ecaf6afd11c5ULL, 0x30cb10fbdb9b8b20ULL, 0x2820180838584030ULL, + 0x41543f156b97a87eULL, 0x3934170d237f682eULL, 0x14100c041c2c2018ULL, + 0x05040301070b0806ULL, 0xe98dac6421ab0745ULL, 0x845b7cdf27cab6f8ULL, + 0xb3c59a765f0d9729ULL, 0x80f98b797264ef0bULL, 0x8e537add29dca6f4ULL, + 0xc9f4473db3b2f58eULL, 0x4e583a16628ab074ULL, 0xc3fc413fbda4e582ULL, + 0xebdc593785fca5b2ULL, 0xc4a9b76d1ef84f73ULL, 0xd8e04838a895dd90ULL, + 0x67ded6b90877a1b1ULL, 0xa2d19573442abf37ULL, 0x6a8326e9a53d1b4cULL, + 0xe1d45f358beab5beULL, 0x1c49ff55b66d92e3ULL, 0xa8d993714a3caf3bULL, + 0x8af18d7b7c72ff07ULL, 0x860a898c839d140fULL, 0xa7d596724321b731ULL, + 0x921a85889fb13417ULL, 0x09ff07f6f8e4e30eULL, 0x82a87e2ad6334dfcULL, + 0xc6f8423ebaafed84ULL, 0x3b65e25e8728cad9ULL, 0xbb9c6927f54c25d2ULL, + 0x4305ca46cfc00a89ULL, 0x3c30140c24746028ULL, 0xec89af6526a00f43ULL, + 0xd5bdb86805df676dULL, 0xf899a3613a8c2f5bULL, 0x0f0c0503091d180aULL, + 0xe2235ec17d1846bcULL, 0x1641f957b87b82efULL, 0xa97f67d61899feceULL, + 0x9a4376d935f086ecULL, 0x257de8589512facdULL, 0x9f4775d832fb8eeaULL, + 0xe385aa662fbd1749ULL, 0xac7b64d71f92f6c8ULL, 0xd2e84e3aa683cd9cULL, + 0xcf0745c8424b0e8aULL, 0xccf0443cb4b9fd88ULL, 0x35cf13fadc908326ULL, + 0xf462a796c563c453ULL, 0x01a6f4a752a551f5ULL, 0xc25ab598ef01b477ULL, + 0x7b9729ecbe1a3352ULL, 0x62dad5b80f7ca9b7ULL, 0xfc3b54c76f2276a8ULL, + 0x2c82efae6df619c3ULL, 0xd0b9bb6902d46f6bULL, 0x7a31dd4becbf62a7ULL, + 0x3d96e0ab76d131ddULL, 0x379ee6a978c721d1ULL, 0xe681a96728b61f4fULL, + 0x22281e0a364e503cULL, 0x4601c947c8cb028fULL, 0x1def0bf2e4c8c316ULL, + 0x5beec2b52c03c199ULL, 0xaa886622ee6b0dccULL, 0x56b332e581497b64ULL, + 0x719f2feeb00c235eULL, 0x7cc2dfbe1d4699a3ULL, 0x87ac7d2bd13845faULL, + 0xbf3e9e81a0e27c21ULL, 0x5a4836127ea6906cULL, 0xb5369883aef46c2dULL, + 0x776c2d1b41f5d85aULL, 0x3638120e2a627024ULL, 0xaf8c6523e96005caULL, + 0x06f302f5f1f9fb04ULL, 0x4c09cf45c6dd1283ULL, 0xa5846321e77615c6ULL, + 0xd11f4fce50713e9eULL, 0x7039db49e2a972abULL, 0x9cb0742cc4097de8ULL, + 0x3ac316f9d58d9b2cULL, 0x59bf37e68854636eULL, 0x54e2c7b6251ed993ULL, + 0x88a07828d8255df0ULL, 0x4b5c39176581b872ULL, 0xb0329b82a9ff642bULL, + 0x72682e1a46fed05cULL, 0x9d16808b96ac2c1dULL, 0x21df1ffec0bca33eULL, + 0x9812838a91a7241bULL, 0x2d241b093f534836ULL, 0xca0346c94540068cULL, + 0xa1269487b2d84c35ULL, 0x6b25d24ef7984ab9ULL, 0x42a33ee19d655b7cULL, + 0x96b8722eca1f6de4ULL, 0x53b731e486427362ULL, 0x47a73de09a6e537aULL, + 0x608b20ebab2b0b40ULL, 0xea7aad90d759f447ULL, 0x0eaaf1a45bb849ffULL, + 0x6678221e5ad2f044ULL, 0xab2e9285bcce5c39ULL, 0xfd9da0603d87275dULL, + 0x0000000000000000ULL, 0xb1946f25fb5a35deULL, 0x03f701f4f6f2f302ULL, + 0x12e30ef1edd5db1cULL, 0xfe6aa194cb75d45fULL, 0x272c1d0b3145583aULL, + 0x5cbb34e78f5f6b68ULL, 0xbcc99f7556108f23ULL, 0x749b2cefb7072b58ULL, + 0xe4d05c348ce1bdb8ULL, 0xf5c4533197c695a6ULL, 0xa37761d4168feec2ULL, + 0xb7676dd00aa3cedaULL, 0xa4229786b5d34433ULL, 0x9be5827e6755d719ULL, + 0x238eeaad64eb01c9ULL, 0x2ed31afdc9a1bb34ULL, 0x8da47b29df2e55f6ULL, + 0xf0c0503090cd9da0ULL, 0xd7ec4d3ba188c59aULL, 0xd946bc9ffa308c65ULL, + 0x3fc715f8d286932aULL, 0xf93f57c668297eaeULL, 0x5f4c351379ad986aULL, + 0x1e180a06123a3014ULL, 0x11140f051b27281eULL, 0xf63352c5613466a4ULL, + 0x5544331177bb8866ULL, 0xb6c1997758069f2fULL, 0x91ed847c6943c715ULL, + 0x8ff58e7a7b79f701ULL, 0x85fd8878756fe70dULL, 0xeed85a3682f7adb4ULL, + 0x6c70241c54c4e048ULL, 0xdde44b39af9ed596ULL, 0x2079eb599219f2cbULL, + 0x7860281848e8c050ULL, 0x1345fa56bf708ae9ULL, 0x45f6c8b33e39f18dULL, + 0x4afacdb03724e987ULL, 0xb4906c24fc513dd8ULL, 0xa0806020e07d1dc0ULL, + 0x40f2cbb23932f98bULL, 0xe072ab92d94fe44bULL, 0x15b6f8a34e8971edULL, + 0xe7275dc07a134ebaULL, 0x490dcc44c1d61a85ULL, 0xf795a66233913751ULL, + 0x5040301070b08060ULL, 0x5eeac1b42b08c99fULL, 0xae2a9184bbc5543fULL, + 0x5211c543d4e72297ULL, 0xe576a893de44ec4dULL, 0xed2f5bc274055eb6ULL, + 0x7f35de4aebb46aa1ULL, 0x73cedabd145b81a9ULL, 0x89068c8f8a800c05ULL, + 0x99b4772dc30275eeULL, 0x76cad9bc135089afULL, 0xd64ab99cf32d946fULL, + 0xdfb5be6a0bc97761ULL, 0x5d1dc040ddfa3a9dULL, 0xd41b4ccf577a3698ULL, + 0x10b2fba2498279ebULL, 0xba3a9d80a7e97427ULL, 0x6e21d14ff09342bfULL, + 0x637c211f5dd9f842ULL, 0xc50f43ca4c5d1e86ULL, 0x3892e3aa71da39dbULL, + 0x5715c642d3ec2a91ULL +}; + +static const u64 T4[256] = { + 0xbbb96a01bad3d268ULL, 0xe59a66b154fc4d19ULL, 0xe26514cd2f71bc93ULL, + 0x25871b51749ccdb9ULL, 0xf7a257a453f55102ULL, 0xd0d6be03d3686bb8ULL, + 0xd6deb504d26b6fbdULL, 0xb35285fe4dd72964ULL, 0xfdba4aad50f05d0dULL, + 0xcf09e063ace98a26ULL, 0x091c96848d8a0e83ULL, 0xa5914d1abfdcc679ULL, + 0x3da7374d7090ddadULL, 0xf1aa5ca352f65507ULL, 0x7ba417e19ab352c8ULL, + 0xb55a8ef94cd42d61ULL, 0x460320acea238f65ULL, 0xc4e68411d56273a6ULL, + 0x55cc68c297a466f1ULL, 0xdcc6a80dd16e63b2ULL, 0xaa85d0993355ccffULL, + 0xfbb241aa51f35908ULL, 0xc7e20f9c5bed712aULL, 0xf359ae55a6f7a204ULL, + 0xfebec120de7f5f81ULL, 0xad7aa2e548d83d75ULL, 0xd729cc7fa8e59a32ULL, + 0x71bc0ae899b65ec7ULL, 0xe096e63bdb704b90ULL, 0xac8ddb9e3256c8faULL, + 0x95d11522b7c4e651ULL, 0x32b3aacefc19d72bULL, 0x704b7393e338ab48ULL, + 0x63843bfd9ebf42dcULL, 0x41fc52d091ae7eefULL, 0x7dac1ce69bb056cdULL, + 0x76437894e23baf4dULL, 0xbdb16106bbd0d66dULL, 0x9b32f1da41c31958ULL, + 0x7957e5176eb2a5cbULL, 0xf941b35ca5f2ae0bULL, 0x8016564bcb400bc0ULL, + 0x677fc20c6bbdb1daULL, 0x59dc7ecc95a26efbULL, 0xe1619f40a1febe1fULL, + 0x10cbc3e3f308eb18ULL, 0x81e12f30b1cefe4fULL, 0x0c10160e0206080aULL, + 0x922e675ecc4917dbULL, 0xa26e3f66c45137f3ULL, 0x4ee8cf531d277469ULL, + 0x78a09c6c143c5044ULL, 0xb0560e73c3582be8ULL, 0x573f9a3463a591f2ULL, + 0xe69eed3cda734f95ULL, 0xd3d2358e5de76934ULL, 0xdfc223805fe1613eULL, + 0xf2aed72edc79578bULL, 0x13cf486e7d87e994ULL, 0x94266c59cd4a13deULL, + 0x1fdf5e607f81e19eULL, 0xc1ea049b5aee752fULL, 0x7547f3196cb4adc1ULL, + 0xd5da3e895ce46d31ULL, 0x08ebeffff704fb0cULL, 0xd42d47f2266a98beULL, + 0x38abb7c7ff1cdb24ULL, 0x543b11b9ed2a937eULL, 0x4a1336a2e825876fULL, + 0x699c26f49dba4ed3ULL, 0x7f5fee106fb1a1ceULL, 0x03048b8d8e8f028cULL, + 0x56c8e34f192b647dULL, 0xe7699447a0fdba1aULL, 0x1ad3deeaf00de717ULL, + 0x113cba9889861e97ULL, 0x2278692d0f113c33ULL, 0x1238311507091c1bULL, + 0xc511fd6aafec8629ULL, 0x208b9bdbfb10cb30ULL, 0x3040583808182028ULL, + 0x7ea8976b153f5441ULL, 0x2e687f230d173439ULL, 0x18202c1c040c1014ULL, + 0x06080b0701030405ULL, 0x4507ab2164ac8de9ULL, 0xf8b6ca27df7c5b84ULL, + 0x29970d5f769ac5b3ULL, 0x0bef6472798bf980ULL, 0xf4a6dc29dd7a538eULL, + 0x8ef5b2b33d47f4c9ULL, 0x74b08a62163a584eULL, 0x82e5a4bd3f41fcc3ULL, + 0xb2a5fc853759dcebULL, 0x734ff81e6db7a9c4ULL, 0x90dd95a83848e0d8ULL, + 0xb1a17708b9d6de67ULL, 0x37bf2a447395d1a2ULL, 0x4c1b3da5e926836aULL, + 0xbeb5ea8b355fd4e1ULL, 0xe3926db655ff491cULL, 0x3baf3c4a7193d9a8ULL, + 0x07ff727c7b8df18aULL, 0x0f149d838c890a86ULL, 0x31b721437296d5a7ULL, + 0x1734b19f88851a92ULL, 0x0ee3e4f8f607ff09ULL, 0xfc4d33d62a7ea882ULL, + 0x84edafba3e42f8c6ULL, 0xd9ca28875ee2653bULL, 0xd2254cf527699cbbULL, + 0x890ac0cf46ca0543ULL, 0x286074240c14303cULL, 0x430fa02665af89ecULL, + 0x6d67df0568b8bdd5ULL, 0x5b2f8c3a61a399f8ULL, 0x0a181d0903050c0fULL, + 0xbc46187dc15e23e2ULL, 0xef827bb857f94116ULL, 0xcefe9918d6677fa9ULL, + 0xec86f035d976439aULL, 0xcdfa129558e87d25ULL, 0xea8efb32d875479fULL, + 0x4917bd2f66aa85e3ULL, 0xc8f6921fd7647bacULL, 0x9ccd83a63a4ee8d2ULL, + 0x8a0e4b42c84507cfULL, 0x88fdb9b43c44f0ccULL, 0x268390dcfa13cf35ULL, + 0x53c463c596a762f4ULL, 0xf551a552a7f4a601ULL, 0x77b401ef98b55ac2ULL, + 0x52331abeec29977bULL, 0xb7a97c0fb8d5da62ULL, 0xa876226fc7543bfcULL, + 0xc319f66daeef822cULL, 0x6b6fd40269bbb9d0ULL, 0xa762bfec4bdd317aULL, + 0xdd31d176abe0963dULL, 0xd121c778a9e69e37ULL, 0x4f1fb62867a981e6ULL, + 0x3c504e360a1e2822ULL, 0x8f02cbc847c90146ULL, 0x16c3c8e4f20bef1dULL, + 0x99c1032cb5c2ee5bULL, 0xcc0d6bee226688aaULL, 0x647b4981e532b356ULL, + 0x5e230cb0ee2f9f71ULL, 0xa399461dbedfc27cULL, 0xfa4538d12b7dac87ULL, + 0x217ce2a0819e3ebfULL, 0x6c90a67e1236485aULL, 0x2d6cf4ae839836b5ULL, + 0x5ad8f5411b2d6c77ULL, 0x2470622a0e123836ULL, 0xca0560e923658cafULL, + 0x04fbf9f1f502f306ULL, 0x8312ddc645cf094cULL, 0xc61576e7216384a5ULL, + 0x9e3e7150ce4f1fd1ULL, 0xab72a9e249db3970ULL, 0xe87d09c42c74b09cULL, + 0x2c9b8dd5f916c33aULL, 0x6e635488e637bf59ULL, 0x93d91e25b6c7e254ULL, + 0xf05d25d82878a088ULL, 0x72b8816517395c4bULL, 0x2b64ffa9829b32b0ULL, + 0x5cd0fe461a2e6872ULL, 0x1d2cac968b80169dULL, 0x3ea3bcc0fe1fdf21ULL, + 0x1b24a7918a831298ULL, 0x3648533f091b242dULL, 0x8c064045c94603caULL, + 0x354cd8b2879426a1ULL, 0xb94a98f74ed2256bULL, 0x7c5b659de13ea342ULL, + 0xe46d1fca2e72b896ULL, 0x62734286e431b753ULL, 0x7a536e9ae03da747ULL, + 0x400b2babeb208b60ULL, 0x47f459d790ad7aeaULL, 0xff49b85ba4f1aa0eULL, + 0x44f0d25a1e227866ULL, 0x395ccebc85922eabULL, 0x5d27873d60a09dfdULL, + 0x0000000000000000ULL, 0xde355afb256f94b1ULL, 0x02f3f2f6f401f703ULL, + 0x1cdbd5edf10ee312ULL, 0x5fd475cb94a16afeULL, 0x3a5845310b1d2c27ULL, + 0x686b5f8fe734bb5cULL, 0x238f1056759fc9bcULL, 0x582b07b7ef2c9b74ULL, + 0xb8bde18c345cd0e4ULL, 0xa695c6973153c4f5ULL, 0xc2ee8f16d46177a3ULL, + 0xdacea30ad06d67b7ULL, 0x3344d3b5869722a4ULL, 0x19d755677e82e59bULL, + 0xc901eb64adea8e23ULL, 0x34bba1c9fd1ad32eULL, 0xf6552edf297ba48dULL, + 0xa09dcd903050c0f0ULL, 0x9ac588a13b4decd7ULL, 0x658c30fa9fbc46d9ULL, + 0x2a9386d2f815c73fULL, 0xae7e2968c6573ff9ULL, 0x6a98ad7913354c5fULL, + 0x14303a12060a181eULL, 0x1e28271b050f1411ULL, 0xa4663461c55233f6ULL, + 0x6688bb7711334455ULL, 0x2f9f06587799c1b6ULL, 0x15c743697c84ed91ULL, + 0x01f7797b7a8ef58fULL, 0x0de76f757888fd85ULL, 0xb4adf782365ad8eeULL, + 0x48e0c4541c24706cULL, 0x96d59eaf394be4ddULL, 0xcbf2199259eb7920ULL, + 0x50c0e84818286078ULL, 0xe98a70bf56fa4513ULL, 0x8df1393eb3c8f645ULL, + 0x87e92437b0cdfa4aULL, 0xd83d51fc246c90b4ULL, 0xc01d7de0206080a0ULL, + 0x8bf93239b2cbf240ULL, 0x4be44fd992ab72e0ULL, 0xed71894ea3f8b615ULL, + 0xba4e137ac05d27e7ULL, 0x851ad6c144cc0d49ULL, 0x5137913362a695f7ULL, + 0x6080b07010304050ULL, 0x9fc9082bb4c1ea5eULL, 0x3f54c5bb84912aaeULL, + 0x9722e7d443c51152ULL, 0x4dec44de93a876e5ULL, 0xb65e0574c25b2fedULL, + 0xa16ab4eb4ade357fULL, 0xa9815b14bddace73ULL, 0x050c808a8f8c0689ULL, + 0xee7502c32d77b499ULL, 0xaf895013bcd9ca76ULL, 0x6f942df39cb94ad6ULL, + 0x6177c90b6abeb5dfULL, 0x9d3afadd40c01d5dULL, 0x98367a57cf4c1bd4ULL, + 0xeb798249a2fbb210ULL, 0x2774e9a7809d3abaULL, 0xbf4293f04fd1216eULL, + 0x42f8d95d1f217c63ULL, 0x861e5d4cca430fc5ULL, 0xdb39da71aae39238ULL, + 0x912aecd342c61557ULL +}; + +static const u64 T5[256] = { + 0xb9bb016ad3ba68d2ULL, 0x9ae5b166fc54194dULL, 0x65e2cd14712f93bcULL, + 0x8725511b9c74b9cdULL, 0xa2f7a457f5530251ULL, 0xd6d003be68d3b86bULL, + 0xded604b56bd2bd6fULL, 0x52b3fe85d74d6429ULL, 0xbafdad4af0500d5dULL, + 0x09cf63e0e9ac268aULL, 0x1c0984968a8d830eULL, 0x91a51a4ddcbf79c6ULL, + 0xa73d4d379070adddULL, 0xaaf1a35cf6520755ULL, 0xa47be117b39ac852ULL, + 0x5ab5f98ed44c612dULL, 0x0346ac2023ea658fULL, 0xe6c4118462d5a673ULL, + 0xcc55c268a497f166ULL, 0xc6dc0da86ed1b263ULL, 0x85aa99d05533ffccULL, + 0xb2fbaa41f3510859ULL, 0xe2c79c0fed5b2a71ULL, 0x59f355aef7a604a2ULL, + 0xbefe20c17fde815fULL, 0x7aade5a2d848753dULL, 0x29d77fcce5a8329aULL, + 0xbc71e80ab699c75eULL, 0x96e03be670db904bULL, 0x8dac9edb5632fac8ULL, + 0xd1952215c4b751e6ULL, 0xb332ceaa19fc2bd7ULL, 0x4b70937338e348abULL, + 0x8463fd3bbf9edc42ULL, 0xfc41d052ae91ef7eULL, 0xac7de61cb09bcd56ULL, + 0x437694783be24dafULL, 0xb1bd0661d0bb6dd6ULL, 0x329bdaf1c3415819ULL, + 0x577917e5b26ecba5ULL, 0x41f95cb3f2a50baeULL, 0x16804b5640cbc00bULL, + 0x7f670cc2bd6bdab1ULL, 0xdc59cc7ea295fb6eULL, 0x61e1409ffea11fbeULL, + 0xcb10e3c308f318ebULL, 0xe181302fceb14ffeULL, 0x100c0e1606020a08ULL, + 0x2e925e6749ccdb17ULL, 0x6ea2663f51c4f337ULL, 0xe84e53cf271d6974ULL, + 0xa0786c9c3c144450ULL, 0x56b0730e58c3e82bULL, 0x3f57349aa563f291ULL, + 0x9ee63ced73da954fULL, 0xd2d38e35e75d3469ULL, 0xc2df8023e15f3e61ULL, + 0xaef22ed779dc8b57ULL, 0xcf136e48877d94e9ULL, 0x2694596c4acdde13ULL, + 0xdf1f605e817f9ee1ULL, 0xeac19b04ee5a2f75ULL, 0x477519f3b46cc1adULL, + 0xdad5893ee45c316dULL, 0xeb08ffef04f70cfbULL, 0x2dd4f2476a26be98ULL, + 0xab38c7b71cff24dbULL, 0x3b54b9112aed7e93ULL, 0x134aa23625e86f87ULL, + 0x9c69f426ba9dd34eULL, 0x5f7f10eeb16fcea1ULL, 0x04038d8b8f8e8c02ULL, + 0xc8564fe32b197d64ULL, 0x69e74794fda01abaULL, 0xd31aeade0df017e7ULL, + 0x3c1198ba8689971eULL, 0x78222d69110f333cULL, 0x3812153109071b1cULL, + 0x11c56afdecaf2986ULL, 0x8b20db9b10fb30cbULL, 0x4030385818082820ULL, + 0xa87e6b973f154154ULL, 0x682e237f170d3934ULL, 0x20181c2c0c041410ULL, + 0x0806070b03010504ULL, 0x074521abac64e98dULL, 0xb6f827ca7cdf845bULL, + 0x97295f0d9a76b3c5ULL, 0xef0b72648b7980f9ULL, 0xa6f429dc7add8e53ULL, + 0xf58eb3b2473dc9f4ULL, 0xb074628a3a164e58ULL, 0xe582bda4413fc3fcULL, + 0xa5b285fc5937ebdcULL, 0x4f731ef8b76dc4a9ULL, 0xdd90a8954838d8e0ULL, + 0xa1b10877d6b967deULL, 0xbf37442a9573a2d1ULL, 0x1b4ca53d26e96a83ULL, + 0xb5be8bea5f35e1d4ULL, 0x92e3b66dff551c49ULL, 0xaf3b4a3c9371a8d9ULL, + 0xff077c728d7b8af1ULL, 0x140f839d898c860aULL, 0xb73143219672a7d5ULL, + 0x34179fb18588921aULL, 0xe30ef8e407f609ffULL, 0x4dfcd6337e2a82a8ULL, + 0xed84baaf423ec6f8ULL, 0xcad98728e25e3b65ULL, 0x25d2f54c6927bb9cULL, + 0x0a89cfc0ca464305ULL, 0x60282474140c3c30ULL, 0x0f4326a0af65ec89ULL, + 0x676d05dfb868d5bdULL, 0x2f5b3a8ca361f899ULL, 0x180a091d05030f0cULL, + 0x46bc7d185ec1e223ULL, 0x82efb87bf9571641ULL, 0xfece189967d6a97fULL, + 0x86ec35f076d99a43ULL, 0xfacd9512e858257dULL, 0x8eea32fb75d89f47ULL, + 0x17492fbdaa66e385ULL, 0xf6c81f9264d7ac7bULL, 0xcd9ca6834e3ad2e8ULL, + 0x0e8a424b45c8cf07ULL, 0xfd88b4b9443cccf0ULL, 0x8326dc9013fa35cfULL, + 0xc453c563a796f462ULL, 0x51f552a5f4a701a6ULL, 0xb477ef01b598c25aULL, + 0x3352be1a29ec7b97ULL, 0xa9b70f7cd5b862daULL, 0x76a86f2254c7fc3bULL, + 0x19c36df6efae2c82ULL, 0x6f6b02d4bb69d0b9ULL, 0x62a7ecbfdd4b7a31ULL, + 0x31dd76d1e0ab3d96ULL, 0x21d178c7e6a9379eULL, 0x1f4f28b6a967e681ULL, + 0x503c364e1e0a2228ULL, 0x028fc8cbc9474601ULL, 0xc316e4c80bf21defULL, + 0xc1992c03c2b55beeULL, 0x0dccee6b6622aa88ULL, 0x7b64814932e556b3ULL, + 0x235eb00c2fee719fULL, 0x99a31d46dfbe7cc2ULL, 0x45fad1387d2b87acULL, + 0x7c21a0e29e81bf3eULL, 0x906c7ea636125a48ULL, 0x6c2daef49883b536ULL, + 0xd85a41f52d1b776cULL, 0x70242a62120e3638ULL, 0x05cae9606523af8cULL, + 0xfb04f1f902f506f3ULL, 0x1283c6ddcf454c09ULL, 0x15c6e7766321a584ULL, + 0x3e9e50714fced11fULL, 0x72abe2a9db497039ULL, 0x7de8c409742c9cb0ULL, + 0x9b2cd58d16f93ac3ULL, 0x636e885437e659bfULL, 0xd993251ec7b654e2ULL, + 0x5df0d825782888a0ULL, 0xb872658139174b5cULL, 0x642ba9ff9b82b032ULL, + 0xd05c46fe2e1a7268ULL, 0x2c1d96ac808b9d16ULL, 0xa33ec0bc1ffe21dfULL, + 0x241b91a7838a9812ULL, 0x48363f531b092d24ULL, 0x068c454046c9ca03ULL, + 0x4c35b2d89487a126ULL, 0x4ab9f798d24e6b25ULL, 0x5b7c9d653ee142a3ULL, + 0x6de4ca1f722e96b8ULL, 0x7362864231e453b7ULL, 0x537a9a6e3de047a7ULL, + 0x0b40ab2b20eb608bULL, 0xf447d759ad90ea7aULL, 0x49ff5bb8f1a40eaaULL, + 0xf0445ad2221e6678ULL, 0x5c39bcce9285ab2eULL, 0x275d3d87a060fd9dULL, + 0x0000000000000000ULL, 0x35defb5a6f25b194ULL, 0xf302f6f201f403f7ULL, + 0xdb1cedd50ef112e3ULL, 0xd45fcb75a194fe6aULL, 0x583a31451d0b272cULL, + 0x6b688f5f34e75cbbULL, 0x8f2356109f75bcc9ULL, 0x2b58b7072cef749bULL, + 0xbdb88ce15c34e4d0ULL, 0x95a697c65331f5c4ULL, 0xeec2168f61d4a377ULL, + 0xceda0aa36dd0b767ULL, 0x4433b5d39786a422ULL, 0xd7196755827e9be5ULL, + 0x01c964ebeaad238eULL, 0xbb34c9a11afd2ed3ULL, 0x55f6df2e7b298da4ULL, + 0x9da090cd5030f0c0ULL, 0xc59aa1884d3bd7ecULL, 0x8c65fa30bc9fd946ULL, + 0x932ad28615f83fc7ULL, 0x7eae682957c6f93fULL, 0x986a79ad35135f4cULL, + 0x3014123a0a061e18ULL, 0x281e1b270f051114ULL, 0x66a4613452c5f633ULL, + 0x886677bb33115544ULL, 0x9f2f58069977b6c1ULL, 0xc7156943847c91edULL, + 0xf7017b798e7a8ff5ULL, 0xe70d756f887885fdULL, 0xadb482f75a36eed8ULL, + 0xe04854c4241c6c70ULL, 0xd596af9e4b39dde4ULL, 0xf2cb9219eb592079ULL, + 0xc05048e828187860ULL, 0x8ae9bf70fa561345ULL, 0xf18d3e39c8b345f6ULL, + 0xe9873724cdb04afaULL, 0x3dd8fc516c24b490ULL, 0x1dc0e07d6020a080ULL, + 0xf98b3932cbb240f2ULL, 0xe44bd94fab92e072ULL, 0x71ed4e89f8a315b6ULL, + 0x4eba7a135dc0e727ULL, 0x1a85c1d6cc44490dULL, 0x37513391a662f795ULL, + 0x806070b030105040ULL, 0xc99f2b08c1b45eeaULL, 0x543fbbc59184ae2aULL, + 0x2297d4e7c5435211ULL, 0xec4dde44a893e576ULL, 0x5eb674055bc2ed2fULL, + 0x6aa1ebb4de4a7f35ULL, 0x81a9145bdabd73ceULL, 0x0c058a808c8f8906ULL, + 0x75eec302772d99b4ULL, 0x89af1350d9bc76caULL, 0x946ff32db99cd64aULL, + 0x77610bc9be6adfb5ULL, 0x3a9dddfac0405d1dULL, 0x3698577a4ccfd41bULL, + 0x79eb4982fba210b2ULL, 0x7427a7e99d80ba3aULL, 0x42bff093d14f6e21ULL, + 0xf8425dd9211f637cULL, 0x1e864c5d43cac50fULL, 0x39db71dae3aa3892ULL, + 0x2a91d3ecc6425715ULL +}; + +static const u64 T6[256] = { + 0x6a01bbb9d268bad3ULL, 0x66b1e59a4d1954fcULL, 0x14cde265bc932f71ULL, + 0x1b512587cdb9749cULL, 0x57a4f7a2510253f5ULL, 0xbe03d0d66bb8d368ULL, + 0xb504d6de6fbdd26bULL, 0x85feb35229644dd7ULL, 0x4aadfdba5d0d50f0ULL, + 0xe063cf098a26ace9ULL, 0x9684091c0e838d8aULL, 0x4d1aa591c679bfdcULL, + 0x374d3da7ddad7090ULL, 0x5ca3f1aa550752f6ULL, 0x17e17ba452c89ab3ULL, + 0x8ef9b55a2d614cd4ULL, 0x20ac46038f65ea23ULL, 0x8411c4e673a6d562ULL, + 0x68c255cc66f197a4ULL, 0xa80ddcc663b2d16eULL, 0xd099aa85ccff3355ULL, + 0x41aafbb2590851f3ULL, 0x0f9cc7e2712a5bedULL, 0xae55f359a204a6f7ULL, + 0xc120febe5f81de7fULL, 0xa2e5ad7a3d7548d8ULL, 0xcc7fd7299a32a8e5ULL, + 0x0ae871bc5ec799b6ULL, 0xe63be0964b90db70ULL, 0xdb9eac8dc8fa3256ULL, + 0x152295d1e651b7c4ULL, 0xaace32b3d72bfc19ULL, 0x7393704bab48e338ULL, + 0x3bfd638442dc9ebfULL, 0x52d041fc7eef91aeULL, 0x1ce67dac56cd9bb0ULL, + 0x78947643af4de23bULL, 0x6106bdb1d66dbbd0ULL, 0xf1da9b32195841c3ULL, + 0xe5177957a5cb6eb2ULL, 0xb35cf941ae0ba5f2ULL, 0x564b80160bc0cb40ULL, + 0xc20c677fb1da6bbdULL, 0x7ecc59dc6efb95a2ULL, 0x9f40e161be1fa1feULL, + 0xc3e310cbeb18f308ULL, 0x2f3081e1fe4fb1ceULL, 0x160e0c10080a0206ULL, + 0x675e922e17dbcc49ULL, 0x3f66a26e37f3c451ULL, 0xcf534ee874691d27ULL, + 0x9c6c78a05044143cULL, 0x0e73b0562be8c358ULL, 0x9a34573f91f263a5ULL, + 0xed3ce69e4f95da73ULL, 0x358ed3d269345de7ULL, 0x2380dfc2613e5fe1ULL, + 0xd72ef2ae578bdc79ULL, 0x486e13cfe9947d87ULL, 0x6c59942613decd4aULL, + 0x5e601fdfe19e7f81ULL, 0x049bc1ea752f5aeeULL, 0xf3197547adc16cb4ULL, + 0x3e89d5da6d315ce4ULL, 0xefff08ebfb0cf704ULL, 0x47f2d42d98be266aULL, + 0xb7c738abdb24ff1cULL, 0x11b9543b937eed2aULL, 0x36a24a13876fe825ULL, + 0x26f4699c4ed39dbaULL, 0xee107f5fa1ce6fb1ULL, 0x8b8d0304028c8e8fULL, + 0xe34f56c8647d192bULL, 0x9447e769ba1aa0fdULL, 0xdeea1ad3e717f00dULL, + 0xba98113c1e978986ULL, 0x692d22783c330f11ULL, 0x311512381c1b0709ULL, + 0xfd6ac5118629afecULL, 0x9bdb208bcb30fb10ULL, 0x5838304020280818ULL, + 0x976b7ea85441153fULL, 0x7f232e6834390d17ULL, 0x2c1c18201014040cULL, + 0x0b07060804050103ULL, 0xab2145078de964acULL, 0xca27f8b65b84df7cULL, + 0x0d5f2997c5b3769aULL, 0x64720beff980798bULL, 0xdc29f4a6538edd7aULL, + 0xb2b38ef5f4c93d47ULL, 0x8a6274b0584e163aULL, 0xa4bd82e5fcc33f41ULL, + 0xfc85b2a5dceb3759ULL, 0xf81e734fa9c46db7ULL, 0x95a890dde0d83848ULL, + 0x7708b1a1de67b9d6ULL, 0x2a4437bfd1a27395ULL, 0x3da54c1b836ae926ULL, + 0xea8bbeb5d4e1355fULL, 0x6db6e392491c55ffULL, 0x3c4a3bafd9a87193ULL, + 0x727c07fff18a7b8dULL, 0x9d830f140a868c89ULL, 0x214331b7d5a77296ULL, + 0xb19f17341a928885ULL, 0xe4f80ee3ff09f607ULL, 0x33d6fc4da8822a7eULL, + 0xafba84edf8c63e42ULL, 0x2887d9ca653b5ee2ULL, 0x4cf5d2259cbb2769ULL, + 0xc0cf890a054346caULL, 0x74242860303c0c14ULL, 0xa026430f89ec65afULL, + 0xdf056d67bdd568b8ULL, 0x8c3a5b2f99f861a3ULL, 0x1d090a180c0f0305ULL, + 0x187dbc4623e2c15eULL, 0x7bb8ef82411657f9ULL, 0x9918cefe7fa9d667ULL, + 0xf035ec86439ad976ULL, 0x1295cdfa7d2558e8ULL, 0xfb32ea8e479fd875ULL, + 0xbd2f491785e366aaULL, 0x921fc8f67bacd764ULL, 0x83a69ccde8d23a4eULL, + 0x4b428a0e07cfc845ULL, 0xb9b488fdf0cc3c44ULL, 0x90dc2683cf35fa13ULL, + 0x63c553c462f496a7ULL, 0xa552f551a601a7f4ULL, 0x01ef77b45ac298b5ULL, + 0x1abe5233977bec29ULL, 0x7c0fb7a9da62b8d5ULL, 0x226fa8763bfcc754ULL, + 0xf66dc319822caeefULL, 0xd4026b6fb9d069bbULL, 0xbfeca762317a4bddULL, + 0xd176dd31963dabe0ULL, 0xc778d1219e37a9e6ULL, 0xb6284f1f81e667a9ULL, + 0x4e363c5028220a1eULL, 0xcbc88f02014647c9ULL, 0xc8e416c3ef1df20bULL, + 0x032c99c1ee5bb5c2ULL, 0x6beecc0d88aa2266ULL, 0x4981647bb356e532ULL, + 0x0cb05e239f71ee2fULL, 0x461da399c27cbedfULL, 0x38d1fa45ac872b7dULL, + 0xe2a0217c3ebf819eULL, 0xa67e6c90485a1236ULL, 0xf4ae2d6c36b58398ULL, + 0xf5415ad86c771b2dULL, 0x622a247038360e12ULL, 0x60e9ca058caf2365ULL, + 0xf9f104fbf306f502ULL, 0xddc68312094c45cfULL, 0x76e7c61584a52163ULL, + 0x71509e3e1fd1ce4fULL, 0xa9e2ab72397049dbULL, 0x09c4e87db09c2c74ULL, + 0x8dd52c9bc33af916ULL, 0x54886e63bf59e637ULL, 0x1e2593d9e254b6c7ULL, + 0x25d8f05da0882878ULL, 0x816572b85c4b1739ULL, 0xffa92b6432b0829bULL, + 0xfe465cd068721a2eULL, 0xac961d2c169d8b80ULL, 0xbcc03ea3df21fe1fULL, + 0xa7911b2412988a83ULL, 0x533f3648242d091bULL, 0x40458c0603cac946ULL, + 0xd8b2354c26a18794ULL, 0x98f7b94a256b4ed2ULL, 0x659d7c5ba342e13eULL, + 0x1fcae46db8962e72ULL, 0x42866273b753e431ULL, 0x6e9a7a53a747e03dULL, + 0x2bab400b8b60eb20ULL, 0x59d747f47aea90adULL, 0xb85bff49aa0ea4f1ULL, + 0xd25a44f078661e22ULL, 0xcebc395c2eab8592ULL, 0x873d5d279dfd60a0ULL, + 0x0000000000000000ULL, 0x5afbde3594b1256fULL, 0xf2f602f3f703f401ULL, + 0xd5ed1cdbe312f10eULL, 0x75cb5fd46afe94a1ULL, 0x45313a582c270b1dULL, + 0x5f8f686bbb5ce734ULL, 0x1056238fc9bc759fULL, 0x07b7582b9b74ef2cULL, + 0xe18cb8bdd0e4345cULL, 0xc697a695c4f53153ULL, 0x8f16c2ee77a3d461ULL, + 0xa30adace67b7d06dULL, 0xd3b5334422a48697ULL, 0x556719d7e59b7e82ULL, + 0xeb64c9018e23adeaULL, 0xa1c934bbd32efd1aULL, 0x2edff655a48d297bULL, + 0xcd90a09dc0f03050ULL, 0x88a19ac5ecd73b4dULL, 0x30fa658c46d99fbcULL, + 0x86d22a93c73ff815ULL, 0x2968ae7e3ff9c657ULL, 0xad796a984c5f1335ULL, + 0x3a121430181e060aULL, 0x271b1e281411050fULL, 0x3461a46633f6c552ULL, + 0xbb77668844551133ULL, 0x06582f9fc1b67799ULL, 0x436915c7ed917c84ULL, + 0x797b01f7f58f7a8eULL, 0x6f750de7fd857888ULL, 0xf782b4add8ee365aULL, + 0xc45448e0706c1c24ULL, 0x9eaf96d5e4dd394bULL, 0x1992cbf2792059ebULL, + 0xe84850c060781828ULL, 0x70bfe98a451356faULL, 0x393e8df1f645b3c8ULL, + 0x243787e9fa4ab0cdULL, 0x51fcd83d90b4246cULL, 0x7de0c01d80a02060ULL, + 0x32398bf9f240b2cbULL, 0x4fd94be472e092abULL, 0x894eed71b615a3f8ULL, + 0x137aba4e27e7c05dULL, 0xd6c1851a0d4944ccULL, 0x9133513795f762a6ULL, + 0xb070608040501030ULL, 0x082b9fc9ea5eb4c1ULL, 0xc5bb3f542aae8491ULL, + 0xe7d49722115243c5ULL, 0x44de4dec76e593a8ULL, 0x0574b65e2fedc25bULL, + 0xb4eba16a357f4adeULL, 0x5b14a981ce73bddaULL, 0x808a050c06898f8cULL, + 0x02c3ee75b4992d77ULL, 0x5013af89ca76bcd9ULL, 0x2df36f944ad69cb9ULL, + 0xc90b6177b5df6abeULL, 0xfadd9d3a1d5d40c0ULL, 0x7a5798361bd4cf4cULL, + 0x8249eb79b210a2fbULL, 0xe9a727743aba809dULL, 0x93f0bf42216e4fd1ULL, + 0xd95d42f87c631f21ULL, 0x5d4c861e0fc5ca43ULL, 0xda71db399238aae3ULL, + 0xecd3912a155742c6ULL +}; + +static const u64 T7[256] = { + 0x016ab9bb68d2d3baULL, 0xb1669ae5194dfc54ULL, 0xcd1465e293bc712fULL, + 0x511b8725b9cd9c74ULL, 0xa457a2f70251f553ULL, 0x03bed6d0b86b68d3ULL, + 0x04b5ded6bd6f6bd2ULL, 0xfe8552b36429d74dULL, 0xad4abafd0d5df050ULL, + 0x63e009cf268ae9acULL, 0x84961c09830e8a8dULL, 0x1a4d91a579c6dcbfULL, + 0x4d37a73daddd9070ULL, 0xa35caaf10755f652ULL, 0xe117a47bc852b39aULL, + 0xf98e5ab5612dd44cULL, 0xac200346658f23eaULL, 0x1184e6c4a67362d5ULL, + 0xc268cc55f166a497ULL, 0x0da8c6dcb2636ed1ULL, 0x99d085aaffcc5533ULL, + 0xaa41b2fb0859f351ULL, 0x9c0fe2c72a71ed5bULL, 0x55ae59f304a2f7a6ULL, + 0x20c1befe815f7fdeULL, 0xe5a27aad753dd848ULL, 0x7fcc29d7329ae5a8ULL, + 0xe80abc71c75eb699ULL, 0x3be696e0904b70dbULL, 0x9edb8dacfac85632ULL, + 0x2215d19551e6c4b7ULL, 0xceaab3322bd719fcULL, 0x93734b7048ab38e3ULL, + 0xfd3b8463dc42bf9eULL, 0xd052fc41ef7eae91ULL, 0xe61cac7dcd56b09bULL, + 0x947843764daf3be2ULL, 0x0661b1bd6dd6d0bbULL, 0xdaf1329b5819c341ULL, + 0x17e55779cba5b26eULL, 0x5cb341f90baef2a5ULL, 0x4b561680c00b40cbULL, + 0x0cc27f67dab1bd6bULL, 0xcc7edc59fb6ea295ULL, 0x409f61e11fbefea1ULL, + 0xe3c3cb1018eb08f3ULL, 0x302fe1814ffeceb1ULL, 0x0e16100c0a080602ULL, + 0x5e672e92db1749ccULL, 0x663f6ea2f33751c4ULL, 0x53cfe84e6974271dULL, + 0x6c9ca07844503c14ULL, 0x730e56b0e82b58c3ULL, 0x349a3f57f291a563ULL, + 0x3ced9ee6954f73daULL, 0x8e35d2d33469e75dULL, 0x8023c2df3e61e15fULL, + 0x2ed7aef28b5779dcULL, 0x6e48cf1394e9877dULL, 0x596c2694de134acdULL, + 0x605edf1f9ee1817fULL, 0x9b04eac12f75ee5aULL, 0x19f34775c1adb46cULL, + 0x893edad5316de45cULL, 0xffefeb080cfb04f7ULL, 0xf2472dd4be986a26ULL, + 0xc7b7ab3824db1cffULL, 0xb9113b547e932aedULL, 0xa236134a6f8725e8ULL, + 0xf4269c69d34eba9dULL, 0x10ee5f7fcea1b16fULL, 0x8d8b04038c028f8eULL, + 0x4fe3c8567d642b19ULL, 0x479469e71abafda0ULL, 0xeaded31a17e70df0ULL, + 0x98ba3c11971e8689ULL, 0x2d697822333c110fULL, 0x153138121b1c0907ULL, + 0x6afd11c52986ecafULL, 0xdb9b8b2030cb10fbULL, 0x3858403028201808ULL, + 0x6b97a87e41543f15ULL, 0x237f682e3934170dULL, 0x1c2c201814100c04ULL, + 0x070b080605040301ULL, 0x21ab0745e98dac64ULL, 0x27cab6f8845b7cdfULL, + 0x5f0d9729b3c59a76ULL, 0x7264ef0b80f98b79ULL, 0x29dca6f48e537addULL, + 0xb3b2f58ec9f4473dULL, 0x628ab0744e583a16ULL, 0xbda4e582c3fc413fULL, + 0x85fca5b2ebdc5937ULL, 0x1ef84f73c4a9b76dULL, 0xa895dd90d8e04838ULL, + 0x0877a1b167ded6b9ULL, 0x442abf37a2d19573ULL, 0xa53d1b4c6a8326e9ULL, + 0x8beab5bee1d45f35ULL, 0xb66d92e31c49ff55ULL, 0x4a3caf3ba8d99371ULL, + 0x7c72ff078af18d7bULL, 0x839d140f860a898cULL, 0x4321b731a7d59672ULL, + 0x9fb13417921a8588ULL, 0xf8e4e30e09ff07f6ULL, 0xd6334dfc82a87e2aULL, + 0xbaafed84c6f8423eULL, 0x8728cad93b65e25eULL, 0xf54c25d2bb9c6927ULL, + 0xcfc00a894305ca46ULL, 0x247460283c30140cULL, 0x26a00f43ec89af65ULL, + 0x05df676dd5bdb868ULL, 0x3a8c2f5bf899a361ULL, 0x091d180a0f0c0503ULL, + 0x7d1846bce2235ec1ULL, 0xb87b82ef1641f957ULL, 0x1899fecea97f67d6ULL, + 0x35f086ec9a4376d9ULL, 0x9512facd257de858ULL, 0x32fb8eea9f4775d8ULL, + 0x2fbd1749e385aa66ULL, 0x1f92f6c8ac7b64d7ULL, 0xa683cd9cd2e84e3aULL, + 0x424b0e8acf0745c8ULL, 0xb4b9fd88ccf0443cULL, 0xdc90832635cf13faULL, + 0xc563c453f462a796ULL, 0x52a551f501a6f4a7ULL, 0xef01b477c25ab598ULL, + 0xbe1a33527b9729ecULL, 0x0f7ca9b762dad5b8ULL, 0x6f2276a8fc3b54c7ULL, + 0x6df619c32c82efaeULL, 0x02d46f6bd0b9bb69ULL, 0xecbf62a77a31dd4bULL, + 0x76d131dd3d96e0abULL, 0x78c721d1379ee6a9ULL, 0x28b61f4fe681a967ULL, + 0x364e503c22281e0aULL, 0xc8cb028f4601c947ULL, 0xe4c8c3161def0bf2ULL, + 0x2c03c1995beec2b5ULL, 0xee6b0dccaa886622ULL, 0x81497b6456b332e5ULL, + 0xb00c235e719f2feeULL, 0x1d4699a37cc2dfbeULL, 0xd13845fa87ac7d2bULL, + 0xa0e27c21bf3e9e81ULL, 0x7ea6906c5a483612ULL, 0xaef46c2db5369883ULL, + 0x41f5d85a776c2d1bULL, 0x2a6270243638120eULL, 0xe96005caaf8c6523ULL, + 0xf1f9fb0406f302f5ULL, 0xc6dd12834c09cf45ULL, 0xe77615c6a5846321ULL, + 0x50713e9ed11f4fceULL, 0xe2a972ab7039db49ULL, 0xc4097de89cb0742cULL, + 0xd58d9b2c3ac316f9ULL, 0x8854636e59bf37e6ULL, 0x251ed99354e2c7b6ULL, + 0xd8255df088a07828ULL, 0x6581b8724b5c3917ULL, 0xa9ff642bb0329b82ULL, + 0x46fed05c72682e1aULL, 0x96ac2c1d9d16808bULL, 0xc0bca33e21df1ffeULL, + 0x91a7241b9812838aULL, 0x3f5348362d241b09ULL, 0x4540068cca0346c9ULL, + 0xb2d84c35a1269487ULL, 0xf7984ab96b25d24eULL, 0x9d655b7c42a33ee1ULL, + 0xca1f6de496b8722eULL, 0x8642736253b731e4ULL, 0x9a6e537a47a73de0ULL, + 0xab2b0b40608b20ebULL, 0xd759f447ea7aad90ULL, 0x5bb849ff0eaaf1a4ULL, + 0x5ad2f0446678221eULL, 0xbcce5c39ab2e9285ULL, 0x3d87275dfd9da060ULL, + 0x0000000000000000ULL, 0xfb5a35deb1946f25ULL, 0xf6f2f30203f701f4ULL, + 0xedd5db1c12e30ef1ULL, 0xcb75d45ffe6aa194ULL, 0x3145583a272c1d0bULL, + 0x8f5f6b685cbb34e7ULL, 0x56108f23bcc99f75ULL, 0xb7072b58749b2cefULL, + 0x8ce1bdb8e4d05c34ULL, 0x97c695a6f5c45331ULL, 0x168feec2a37761d4ULL, + 0x0aa3cedab7676dd0ULL, 0xb5d34433a4229786ULL, 0x6755d7199be5827eULL, + 0x64eb01c9238eeaadULL, 0xc9a1bb342ed31afdULL, 0xdf2e55f68da47b29ULL, + 0x90cd9da0f0c05030ULL, 0xa188c59ad7ec4d3bULL, 0xfa308c65d946bc9fULL, + 0xd286932a3fc715f8ULL, 0x68297eaef93f57c6ULL, 0x79ad986a5f4c3513ULL, + 0x123a30141e180a06ULL, 0x1b27281e11140f05ULL, 0x613466a4f63352c5ULL, + 0x77bb886655443311ULL, 0x58069f2fb6c19977ULL, 0x6943c71591ed847cULL, + 0x7b79f7018ff58e7aULL, 0x756fe70d85fd8878ULL, 0x82f7adb4eed85a36ULL, + 0x54c4e0486c70241cULL, 0xaf9ed596dde44b39ULL, 0x9219f2cb2079eb59ULL, + 0x48e8c05078602818ULL, 0xbf708ae91345fa56ULL, 0x3e39f18d45f6c8b3ULL, + 0x3724e9874afacdb0ULL, 0xfc513dd8b4906c24ULL, 0xe07d1dc0a0806020ULL, + 0x3932f98b40f2cbb2ULL, 0xd94fe44be072ab92ULL, 0x4e8971ed15b6f8a3ULL, + 0x7a134ebae7275dc0ULL, 0xc1d61a85490dcc44ULL, 0x33913751f795a662ULL, + 0x70b0806050403010ULL, 0x2b08c99f5eeac1b4ULL, 0xbbc5543fae2a9184ULL, + 0xd4e722975211c543ULL, 0xde44ec4de576a893ULL, 0x74055eb6ed2f5bc2ULL, + 0xebb46aa17f35de4aULL, 0x145b81a973cedabdULL, 0x8a800c0589068c8fULL, + 0xc30275ee99b4772dULL, 0x135089af76cad9bcULL, 0xf32d946fd64ab99cULL, + 0x0bc97761dfb5be6aULL, 0xddfa3a9d5d1dc040ULL, 0x577a3698d41b4ccfULL, + 0x498279eb10b2fba2ULL, 0xa7e97427ba3a9d80ULL, 0xf09342bf6e21d14fULL, + 0x5dd9f842637c211fULL, 0x4c5d1e86c50f43caULL, 0x71da39db3892e3aaULL, + 0xd3ec2a915715c642ULL +}; + +static const u64 c[KHAZAD_ROUNDS + 1] = { + 0xba542f7453d3d24dULL, 0x50ac8dbf70529a4cULL, 0xead597d133515ba6ULL, + 0xde48a899db32b7fcULL, 0xe39e919be2bb416eULL, 0xa5cb6b95a1f3b102ULL, + 0xccc41d14c363da5dULL, 0x5fdc7dcd7f5a6c5cULL, 0xf726ffede89d6f8eULL +}; + +static int khazad_setkey(void *ctx_arg, const u8 *in_key, + unsigned int key_len, u32 *flags) +{ + + struct khazad_ctx *ctx = ctx_arg; + int r; + const u64 *S = T7; + u64 K2, K1; + + if (key_len != 16) + { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + K2 = ((u64)in_key[ 0] << 56) ^ + ((u64)in_key[ 1] << 48) ^ + ((u64)in_key[ 2] << 40) ^ + ((u64)in_key[ 3] << 32) ^ + ((u64)in_key[ 4] << 24) ^ + ((u64)in_key[ 5] << 16) ^ + ((u64)in_key[ 6] << 8) ^ + ((u64)in_key[ 7] ); + K1 = ((u64)in_key[ 8] << 56) ^ + ((u64)in_key[ 9] << 48) ^ + ((u64)in_key[10] << 40) ^ + ((u64)in_key[11] << 32) ^ + ((u64)in_key[12] << 24) ^ + ((u64)in_key[13] << 16) ^ + ((u64)in_key[14] << 8) ^ + ((u64)in_key[15] ); + + /* setup the encrypt key */ + for (r = 0; r <= KHAZAD_ROUNDS; r++) { + ctx->E[r] = T0[(int)(K1 >> 56) ] ^ + T1[(int)(K1 >> 48) & 0xff] ^ + T2[(int)(K1 >> 40) & 0xff] ^ + T3[(int)(K1 >> 32) & 0xff] ^ + T4[(int)(K1 >> 24) & 0xff] ^ + T5[(int)(K1 >> 16) & 0xff] ^ + T6[(int)(K1 >> 8) & 0xff] ^ + T7[(int)(K1 ) & 0xff] ^ + c[r] ^ K2; + K2 = K1; + K1 = ctx->E[r]; + } + /* Setup the decrypt key */ + ctx->D[0] = ctx->E[KHAZAD_ROUNDS]; + for (r = 1; r < KHAZAD_ROUNDS; r++) { + K1 = ctx->E[KHAZAD_ROUNDS - r]; + ctx->D[r] = T0[(int)S[(int)(K1 >> 56) ] & 0xff] ^ + T1[(int)S[(int)(K1 >> 48) & 0xff] & 0xff] ^ + T2[(int)S[(int)(K1 >> 40) & 0xff] & 0xff] ^ + T3[(int)S[(int)(K1 >> 32) & 0xff] & 0xff] ^ + T4[(int)S[(int)(K1 >> 24) & 0xff] & 0xff] ^ + T5[(int)S[(int)(K1 >> 16) & 0xff] & 0xff] ^ + T6[(int)S[(int)(K1 >> 8) & 0xff] & 0xff] ^ + T7[(int)S[(int)(K1 ) & 0xff] & 0xff]; + } + ctx->D[KHAZAD_ROUNDS] = ctx->E[0]; + + return 0; + +} + +static void khazad_crypt(const u64 roundKey[KHAZAD_ROUNDS + 1], + u8 *ciphertext, const u8 *plaintext) +{ + + int r; + u64 state; + + state = ((u64)plaintext[0] << 56) ^ + ((u64)plaintext[1] << 48) ^ + ((u64)plaintext[2] << 40) ^ + ((u64)plaintext[3] << 32) ^ + ((u64)plaintext[4] << 24) ^ + ((u64)plaintext[5] << 16) ^ + ((u64)plaintext[6] << 8) ^ + ((u64)plaintext[7] ) ^ + roundKey[0]; + + for (r = 1; r < KHAZAD_ROUNDS; r++) { + state = T0[(int)(state >> 56) ] ^ + T1[(int)(state >> 48) & 0xff] ^ + T2[(int)(state >> 40) & 0xff] ^ + T3[(int)(state >> 32) & 0xff] ^ + T4[(int)(state >> 24) & 0xff] ^ + T5[(int)(state >> 16) & 0xff] ^ + T6[(int)(state >> 8) & 0xff] ^ + T7[(int)(state ) & 0xff] ^ + roundKey[r]; + } + + state = (T0[(int)(state >> 56) ] & 0xff00000000000000ULL) ^ + (T1[(int)(state >> 48) & 0xff] & 0x00ff000000000000ULL) ^ + (T2[(int)(state >> 40) & 0xff] & 0x0000ff0000000000ULL) ^ + (T3[(int)(state >> 32) & 0xff] & 0x000000ff00000000ULL) ^ + (T4[(int)(state >> 24) & 0xff] & 0x00000000ff000000ULL) ^ + (T5[(int)(state >> 16) & 0xff] & 0x0000000000ff0000ULL) ^ + (T6[(int)(state >> 8) & 0xff] & 0x000000000000ff00ULL) ^ + (T7[(int)(state ) & 0xff] & 0x00000000000000ffULL) ^ + roundKey[KHAZAD_ROUNDS]; + + ciphertext[0] = (u8)(state >> 56); + ciphertext[1] = (u8)(state >> 48); + ciphertext[2] = (u8)(state >> 40); + ciphertext[3] = (u8)(state >> 32); + ciphertext[4] = (u8)(state >> 24); + ciphertext[5] = (u8)(state >> 16); + ciphertext[6] = (u8)(state >> 8); + ciphertext[7] = (u8)(state ); + +} + +static void khazad_encrypt(void *ctx_arg, u8 *dst, const u8 *src) +{ + struct khazad_ctx *ctx = ctx_arg; + khazad_crypt(ctx->E, dst, src); +} + +static void khazad_decrypt(void *ctx_arg, u8 *dst, const u8 *src) +{ + struct khazad_ctx *ctx = ctx_arg; + khazad_crypt(ctx->D, dst, src); +} + +static struct crypto_alg khazad_alg = { + .cra_name = "khazad", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = KHAZAD_BLOCK_SIZE, + .cra_ctxsize = sizeof (struct khazad_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(khazad_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = KHAZAD_KEY_SIZE, + .cia_max_keysize = KHAZAD_KEY_SIZE, + .cia_setkey = khazad_setkey, + .cia_encrypt = khazad_encrypt, + .cia_decrypt = khazad_decrypt } } +}; + +static int __init init(void) +{ + int ret = 0; + + ret = crypto_register_alg(&khazad_alg); + return ret; +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&khazad_alg); +} + + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Khazad Cryptographic Algorithm"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/scatterwalk.c linux-2.4.28-pre3/crypto/scatterwalk.c --- linux-2.4.27/crypto/scatterwalk.c 2004-04-14 13:05:28.000000000 +0000 +++ linux-2.4.28-pre3/crypto/scatterwalk.c 2004-09-10 19:31:55.000000000 +0000 @@ -70,7 +70,7 @@ static void scatterwalk_pagedone(struct { /* walk->data may be pointing the first byte of the next page; however, we know we transfered at least one byte. So, - walk->data - 1 will be a virutual address in the mapped page. */ + walk->data - 1 will be a virtual address in the mapped page. */ if (out) flush_dcache_page(walk->page); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/tcrypt.c linux-2.4.28-pre3/crypto/tcrypt.c --- linux-2.4.27/crypto/tcrypt.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/crypto/tcrypt.c 2004-09-10 19:35:38.000000000 +0000 @@ -63,7 +63,7 @@ static char *tvmem; static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", - "arc4", "michael_mic", "deflate", "tea", "xtea", NULL + "arc4", "michael_mic", "deflate", "tea", "xtea", "whirlpool", NULL }; static void @@ -575,8 +575,13 @@ do_test(void) test_cipher ("xtea", MODE_ECB, ENCRYPT, xtea_enc_tv_template, XTEA_ENC_TEST_VECTORS); test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS); + //KHAZAD + test_cipher ("khazad", MODE_ECB, ENCRYPT, khazad_enc_tv_template, KHAZAD_ENC_TEST_VECTORS); + test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS); + test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); + test_hash("whirlpool", whirlpool_tv_template, WHIRLPOOL_TEST_VECTORS); test_deflate(); #ifdef CONFIG_CRYPTO_HMAC test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); @@ -678,6 +683,14 @@ do_test(void) test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS); break; + case 21: + test_cipher ("khazad", MODE_ECB, ENCRYPT, khazad_enc_tv_template, KHAZAD_ENC_TEST_VECTORS); + test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS); + break; + case 22: + test_hash("whirlpool", whirlpool_tv_template, WHIRLPOOL_TEST_VECTORS); + break; + #ifdef CONFIG_CRYPTO_HMAC case 100: test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/tcrypt.h linux-2.4.28-pre3/crypto/tcrypt.h --- linux-2.4.27/crypto/tcrypt.h 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/crypto/tcrypt.h 2004-09-10 19:37:06.000000000 +0000 @@ -551,6 +551,109 @@ struct hmac_testvec hmac_sha256_tv_templ #endif /* CONFIG_CRYPTO_HMAC */ /* + * WHIRLPOOL test vectors from Whirlpool package + * by Vincent Rijmen and Paulo S. L. M. Barreto as part of the NESSIE + * submission + */ +#define WHIRLPOOL_TEST_VECTORS 8 + +struct hash_testvec whirlpool_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, + 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26, + 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, + 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7, + 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, + 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57, + 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, + 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 }, + + + }, { + .plaintext = "a", + .psize = 1, + .digest = { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F, + 0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7, + 0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69, + 0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42, + 0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6, + 0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59, + 0x1A, 0x92, 0x20, 0x0D, 0x56, 0x01, 0x95, 0xE5, + 0x3B, 0x47, 0x85, 0x84, 0xFD, 0xAE, 0x23, 0x1A }, + }, { + .plaintext = "abc", + .psize = 3, + .digest = { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB, + 0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B, + 0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72, + 0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C, + 0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27, + 0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6, + 0xC7, 0x97, 0xFC, 0x9D, 0x95, 0xD8, 0xB5, 0x82, + 0xD2, 0x25, 0x29, 0x20, 0x76, 0xD4, 0xEE, 0xF5 }, + }, { + .plaintext = "message digest", + .psize = 14, + .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, + 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, + 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, + 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B, + 0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1, + 0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6, + 0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33, + 0x62, 0xE8, 0x6D, 0xBD, 0x37, 0xA8, 0x90, 0x3E }, + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9, + 0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A, + 0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5, + 0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B, + 0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A, + 0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6, + 0xF6, 0x8F, 0x67, 0x3E, 0x72, 0x07, 0x86, 0x5D, + 0x5D, 0x98, 0x19, 0xA3, 0xDB, 0xA4, 0xEB, 0x3B }, + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B, + 0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90, + 0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC, + 0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E, + 0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F, + 0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6, + 0x55, 0x17, 0xCC, 0x87, 0x9D, 0x7B, 0x96, 0x21, + 0x42, 0xC6, 0x5F, 0x5A, 0x7A, 0xF0, 0x14, 0x67 }, + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D, + 0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0, + 0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6, + 0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29, + 0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5, + 0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A, + 0x2C, 0x60, 0x48, 0x1E, 0x88, 0xC5, 0xA2, 0x0B, + 0x2C, 0x2A, 0x80, 0xCF, 0x3A, 0x9A, 0x08, 0x3B }, + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijk", + .psize = 32, + .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, + 0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48, + 0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62, + 0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69, + 0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B, + 0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56, + 0x93, 0x9B, 0xAA, 0xA0, 0xAD, 0xFF, 0x9A, 0xE6, + 0x74, 0x5B, 0x7B, 0x18, 0x1C, 0x3B, 0xE3, 0xFD }, + }, +}; + +/* * DES test vectors. */ #define DES_ENC_TEST_VECTORS 10 @@ -1186,7 +1289,7 @@ struct cipher_testvec tf_cbc_dec_tv_temp /* * Serpent test vectors. These are backwards because Serpent writes - * octect sequences in right-to-left mode. + * octet sequences in right-to-left mode. */ #define SERPENT_ENC_TEST_VECTORS 4 #define SERPENT_DEC_TEST_VECTORS 4 @@ -1818,7 +1921,103 @@ struct cipher_testvec xtea_dec_tv_templa } }; +/* + * KHAZAD test vectors. + */ +#define KHAZAD_ENC_TEST_VECTORS 5 +#define KHAZAD_DEC_TEST_VECTORS 5 + +struct cipher_testvec khazad_enc_tv_template[] = { + { + .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 16, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .ilen = 8, + .result = { 0x49, 0xa4, 0xce, 0x32, 0xac, 0x19, 0x0e, 0x3f }, + .rlen = 8, + }, { + .key = { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 }, + .klen = 16, + .input = { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 }, + .ilen = 8, + .result = { 0x7e, 0x82, 0x12, 0xa1, 0Xd9, 0X5b, 0Xe4, 0Xf9 }, + .rlen = 8, + }, { + .key = { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, + 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 }, + .klen = 16, + .input = { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 }, + .ilen = 8, + .result = { 0Xaa, 0Xbe, 0Xc1, 0X95, 0Xc5, 0X94, 0X1a, 0X9c }, + .rlen = 8, + }, { + .key = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, + 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f }, + .klen = 16, + .input = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f }, + .ilen = 8, + .result = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 }, + .rlen = 8, + }, { + .key = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, + 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f }, + .klen = 16, + .input = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f , + 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f }, + .ilen = 16, + .result = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 , + 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 }, + .rlen = 16, + }, +}; +struct cipher_testvec khazad_dec_tv_template[] = { + { + .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 16, + .input = { 0X49, 0Xa4, 0Xce, 0X32, 0Xac, 0X19, 0X0e, 0X3f }, + .ilen = 8, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .rlen = 8, + }, { + .key = { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 }, + .klen = 16, + .input = { 0X7e, 0X82, 0X12, 0Xa1, 0Xd9, 0X5b, 0Xe4, 0Xf9 }, + .ilen = 8, + .result = { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 }, + .rlen = 8, + }, { + .key = { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, + 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 }, + .klen = 16, + .input = { 0Xaa, 0Xbe, 0Xc1, 0X95, 0Xc5, 0X94, 0X1a, 0X9c }, + .ilen = 8, + .result = { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 }, + .rlen = 8, + }, { + .key = { 0x2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, + 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f }, + .klen = 16, + .input = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 }, + .ilen = 8, + .result = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f }, + .rlen = 8, + }, { + .key = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, + 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f }, + .klen = 16, + .input = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 , + 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 }, + .ilen = 16, + .result = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f , + 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f }, + .rlen = 16, + }, +}; /* * Compression stuff. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/twofish.c linux-2.4.28-pre3/crypto/twofish.c --- linux-2.4.27/crypto/twofish.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/crypto/twofish.c 2004-09-10 19:32:40.000000000 +0000 @@ -1,7 +1,7 @@ /* * Twofish for CryptoAPI * - * Originaly Twofish for GPG + * Originally Twofish for GPG * By Matthew Skala , July 26, 1998 * 256-bit key length added March 20, 1999 * Some modifications to reduce the text size by Werner Koch, April, 1998 @@ -514,7 +514,7 @@ static const u8 calc_sb_tbl[512] = { * preprocessed through q0 and q1 respectively; for longer keys they are the * output of previous stages. j is the index of the first key byte to use. * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 - * twice, doing the Psuedo-Hadamard Transform, and doing the necessary + * twice, doing the Pseudo-Hadamard Transform, and doing the necessary * rotations. Its parameters are: a, the array to write the results into, * j, the index of the first output entry, k and l, the preprocessed indices * for index 2i, and m and n, the preprocessed indices for index 2i+1. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/whirlpool.c linux-2.4.28-pre3/crypto/whirlpool.c --- linux-2.4.27/crypto/whirlpool.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/crypto/whirlpool.c 2004-09-10 19:37:30.000000000 +0000 @@ -0,0 +1,1131 @@ +/* + * Cryptographic API. + * + * Whirlpool hashing Algorithm + * + * The Whirlpool algorithm was developed by Paulo S. L. M. Barreto and + * Vincent Rijmen. It has been selected as one of cryptographic + * primitives by the NESSIE project http://www.cryptonessie.org/ + * + * The original authors have disclaimed all copyright interest in this + * code and thus put it in the public domain. The subsequent authors + * have put this under the GNU General Public License. + * + * By Aaron Grothe ajgrothe@yahoo.com, August 23, 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include +#include +#include + +#define WHIRLPOOL_DIGEST_SIZE 64 +#define WHIRLPOOL_BLOCK_SIZE 64 +#define WHIRLPOOL_LENGTHBYTES 32 + +#define WHIRLPOOL_ROUNDS 10 + +struct whirlpool_ctx { + u8 bitLength[WHIRLPOOL_LENGTHBYTES]; + u8 buffer[WHIRLPOOL_BLOCK_SIZE]; + int bufferBits; + int bufferPos; + u64 hash[WHIRLPOOL_DIGEST_SIZE/8]; +}; + +/* + * Though Whirlpool is endianness-neutral, the encryption tables are listed + * in BIG-ENDIAN format, which is adopted throughout this implementation + * (but little-endian notation would be equally suitable if consistently + * employed). + */ + +static const u64 C0[256] = { + 0x18186018c07830d8ULL, 0x23238c2305af4626ULL, 0xc6c63fc67ef991b8ULL, + 0xe8e887e8136fcdfbULL, 0x878726874ca113cbULL, 0xb8b8dab8a9626d11ULL, + 0x0101040108050209ULL, 0x4f4f214f426e9e0dULL, 0x3636d836adee6c9bULL, + 0xa6a6a2a6590451ffULL, 0xd2d26fd2debdb90cULL, 0xf5f5f3f5fb06f70eULL, + 0x7979f979ef80f296ULL, 0x6f6fa16f5fcede30ULL, 0x91917e91fcef3f6dULL, + 0x52525552aa07a4f8ULL, 0x60609d6027fdc047ULL, 0xbcbccabc89766535ULL, + 0x9b9b569baccd2b37ULL, 0x8e8e028e048c018aULL, 0xa3a3b6a371155bd2ULL, + 0x0c0c300c603c186cULL, 0x7b7bf17bff8af684ULL, 0x3535d435b5e16a80ULL, + 0x1d1d741de8693af5ULL, 0xe0e0a7e05347ddb3ULL, 0xd7d77bd7f6acb321ULL, + 0xc2c22fc25eed999cULL, 0x2e2eb82e6d965c43ULL, 0x4b4b314b627a9629ULL, + 0xfefedffea321e15dULL, 0x575741578216aed5ULL, 0x15155415a8412abdULL, + 0x7777c1779fb6eee8ULL, 0x3737dc37a5eb6e92ULL, 0xe5e5b3e57b56d79eULL, + 0x9f9f469f8cd92313ULL, 0xf0f0e7f0d317fd23ULL, 0x4a4a354a6a7f9420ULL, + 0xdada4fda9e95a944ULL, 0x58587d58fa25b0a2ULL, 0xc9c903c906ca8fcfULL, + 0x2929a429558d527cULL, 0x0a0a280a5022145aULL, 0xb1b1feb1e14f7f50ULL, + 0xa0a0baa0691a5dc9ULL, 0x6b6bb16b7fdad614ULL, 0x85852e855cab17d9ULL, + 0xbdbdcebd8173673cULL, 0x5d5d695dd234ba8fULL, 0x1010401080502090ULL, + 0xf4f4f7f4f303f507ULL, 0xcbcb0bcb16c08bddULL, 0x3e3ef83eedc67cd3ULL, + 0x0505140528110a2dULL, 0x676781671fe6ce78ULL, 0xe4e4b7e47353d597ULL, + 0x27279c2725bb4e02ULL, 0x4141194132588273ULL, 0x8b8b168b2c9d0ba7ULL, + 0xa7a7a6a7510153f6ULL, 0x7d7de97dcf94fab2ULL, 0x95956e95dcfb3749ULL, + 0xd8d847d88e9fad56ULL, 0xfbfbcbfb8b30eb70ULL, 0xeeee9fee2371c1cdULL, + 0x7c7ced7cc791f8bbULL, 0x6666856617e3cc71ULL, 0xdddd53dda68ea77bULL, + 0x17175c17b84b2eafULL, 0x4747014702468e45ULL, 0x9e9e429e84dc211aULL, + 0xcaca0fca1ec589d4ULL, 0x2d2db42d75995a58ULL, 0xbfbfc6bf9179632eULL, + 0x07071c07381b0e3fULL, 0xadad8ead012347acULL, 0x5a5a755aea2fb4b0ULL, + 0x838336836cb51befULL, 0x3333cc3385ff66b6ULL, 0x636391633ff2c65cULL, + 0x02020802100a0412ULL, 0xaaaa92aa39384993ULL, 0x7171d971afa8e2deULL, + 0xc8c807c80ecf8dc6ULL, 0x19196419c87d32d1ULL, 0x494939497270923bULL, + 0xd9d943d9869aaf5fULL, 0xf2f2eff2c31df931ULL, 0xe3e3abe34b48dba8ULL, + 0x5b5b715be22ab6b9ULL, 0x88881a8834920dbcULL, 0x9a9a529aa4c8293eULL, + 0x262698262dbe4c0bULL, 0x3232c8328dfa64bfULL, 0xb0b0fab0e94a7d59ULL, + 0xe9e983e91b6acff2ULL, 0x0f0f3c0f78331e77ULL, 0xd5d573d5e6a6b733ULL, + 0x80803a8074ba1df4ULL, 0xbebec2be997c6127ULL, 0xcdcd13cd26de87ebULL, + 0x3434d034bde46889ULL, 0x48483d487a759032ULL, 0xffffdbffab24e354ULL, + 0x7a7af57af78ff48dULL, 0x90907a90f4ea3d64ULL, 0x5f5f615fc23ebe9dULL, + 0x202080201da0403dULL, 0x6868bd6867d5d00fULL, 0x1a1a681ad07234caULL, + 0xaeae82ae192c41b7ULL, 0xb4b4eab4c95e757dULL, 0x54544d549a19a8ceULL, + 0x93937693ece53b7fULL, 0x222288220daa442fULL, 0x64648d6407e9c863ULL, + 0xf1f1e3f1db12ff2aULL, 0x7373d173bfa2e6ccULL, 0x12124812905a2482ULL, + 0x40401d403a5d807aULL, 0x0808200840281048ULL, 0xc3c32bc356e89b95ULL, + 0xecec97ec337bc5dfULL, 0xdbdb4bdb9690ab4dULL, 0xa1a1bea1611f5fc0ULL, + 0x8d8d0e8d1c830791ULL, 0x3d3df43df5c97ac8ULL, 0x97976697ccf1335bULL, + 0x0000000000000000ULL, 0xcfcf1bcf36d483f9ULL, 0x2b2bac2b4587566eULL, + 0x7676c57697b3ece1ULL, 0x8282328264b019e6ULL, 0xd6d67fd6fea9b128ULL, + 0x1b1b6c1bd87736c3ULL, 0xb5b5eeb5c15b7774ULL, 0xafaf86af112943beULL, + 0x6a6ab56a77dfd41dULL, 0x50505d50ba0da0eaULL, 0x45450945124c8a57ULL, + 0xf3f3ebf3cb18fb38ULL, 0x3030c0309df060adULL, 0xefef9bef2b74c3c4ULL, + 0x3f3ffc3fe5c37edaULL, 0x55554955921caac7ULL, 0xa2a2b2a2791059dbULL, + 0xeaea8fea0365c9e9ULL, 0x656589650fecca6aULL, 0xbabad2bab9686903ULL, + 0x2f2fbc2f65935e4aULL, 0xc0c027c04ee79d8eULL, 0xdede5fdebe81a160ULL, + 0x1c1c701ce06c38fcULL, 0xfdfdd3fdbb2ee746ULL, 0x4d4d294d52649a1fULL, + 0x92927292e4e03976ULL, 0x7575c9758fbceafaULL, 0x06061806301e0c36ULL, + 0x8a8a128a249809aeULL, 0xb2b2f2b2f940794bULL, 0xe6e6bfe66359d185ULL, + 0x0e0e380e70361c7eULL, 0x1f1f7c1ff8633ee7ULL, 0x6262956237f7c455ULL, + 0xd4d477d4eea3b53aULL, 0xa8a89aa829324d81ULL, 0x96966296c4f43152ULL, + 0xf9f9c3f99b3aef62ULL, 0xc5c533c566f697a3ULL, 0x2525942535b14a10ULL, + 0x59597959f220b2abULL, 0x84842a8454ae15d0ULL, 0x7272d572b7a7e4c5ULL, + 0x3939e439d5dd72ecULL, 0x4c4c2d4c5a619816ULL, 0x5e5e655eca3bbc94ULL, + 0x7878fd78e785f09fULL, 0x3838e038ddd870e5ULL, 0x8c8c0a8c14860598ULL, + 0xd1d163d1c6b2bf17ULL, 0xa5a5aea5410b57e4ULL, 0xe2e2afe2434dd9a1ULL, + 0x616199612ff8c24eULL, 0xb3b3f6b3f1457b42ULL, 0x2121842115a54234ULL, + 0x9c9c4a9c94d62508ULL, 0x1e1e781ef0663ceeULL, 0x4343114322528661ULL, + 0xc7c73bc776fc93b1ULL, 0xfcfcd7fcb32be54fULL, 0x0404100420140824ULL, + 0x51515951b208a2e3ULL, 0x99995e99bcc72f25ULL, 0x6d6da96d4fc4da22ULL, + 0x0d0d340d68391a65ULL, 0xfafacffa8335e979ULL, 0xdfdf5bdfb684a369ULL, + 0x7e7ee57ed79bfca9ULL, 0x242490243db44819ULL, 0x3b3bec3bc5d776feULL, + 0xabab96ab313d4b9aULL, 0xcece1fce3ed181f0ULL, 0x1111441188552299ULL, + 0x8f8f068f0c890383ULL, 0x4e4e254e4a6b9c04ULL, 0xb7b7e6b7d1517366ULL, + 0xebeb8beb0b60cbe0ULL, 0x3c3cf03cfdcc78c1ULL, 0x81813e817cbf1ffdULL, + 0x94946a94d4fe3540ULL, 0xf7f7fbf7eb0cf31cULL, 0xb9b9deb9a1676f18ULL, + 0x13134c13985f268bULL, 0x2c2cb02c7d9c5851ULL, 0xd3d36bd3d6b8bb05ULL, + 0xe7e7bbe76b5cd38cULL, 0x6e6ea56e57cbdc39ULL, 0xc4c437c46ef395aaULL, + 0x03030c03180f061bULL, 0x565645568a13acdcULL, 0x44440d441a49885eULL, + 0x7f7fe17fdf9efea0ULL, 0xa9a99ea921374f88ULL, 0x2a2aa82a4d825467ULL, + 0xbbbbd6bbb16d6b0aULL, 0xc1c123c146e29f87ULL, 0x53535153a202a6f1ULL, + 0xdcdc57dcae8ba572ULL, 0x0b0b2c0b58271653ULL, 0x9d9d4e9d9cd32701ULL, + 0x6c6cad6c47c1d82bULL, 0x3131c43195f562a4ULL, 0x7474cd7487b9e8f3ULL, + 0xf6f6fff6e309f115ULL, 0x464605460a438c4cULL, 0xacac8aac092645a5ULL, + 0x89891e893c970fb5ULL, 0x14145014a04428b4ULL, 0xe1e1a3e15b42dfbaULL, + 0x16165816b04e2ca6ULL, 0x3a3ae83acdd274f7ULL, 0x6969b9696fd0d206ULL, + 0x09092409482d1241ULL, 0x7070dd70a7ade0d7ULL, 0xb6b6e2b6d954716fULL, + 0xd0d067d0ceb7bd1eULL, 0xeded93ed3b7ec7d6ULL, 0xcccc17cc2edb85e2ULL, + 0x424215422a578468ULL, 0x98985a98b4c22d2cULL, 0xa4a4aaa4490e55edULL, + 0x2828a0285d885075ULL, 0x5c5c6d5cda31b886ULL, 0xf8f8c7f8933fed6bULL, + 0x8686228644a411c2ULL, +}; + +static const u64 C1[256] = { + 0xd818186018c07830ULL, 0x2623238c2305af46ULL, 0xb8c6c63fc67ef991ULL, + 0xfbe8e887e8136fcdULL, 0xcb878726874ca113ULL, 0x11b8b8dab8a9626dULL, + 0x0901010401080502ULL, 0x0d4f4f214f426e9eULL, 0x9b3636d836adee6cULL, + 0xffa6a6a2a6590451ULL, 0x0cd2d26fd2debdb9ULL, 0x0ef5f5f3f5fb06f7ULL, + 0x967979f979ef80f2ULL, 0x306f6fa16f5fcedeULL, 0x6d91917e91fcef3fULL, + 0xf852525552aa07a4ULL, 0x4760609d6027fdc0ULL, 0x35bcbccabc897665ULL, + 0x379b9b569baccd2bULL, 0x8a8e8e028e048c01ULL, 0xd2a3a3b6a371155bULL, + 0x6c0c0c300c603c18ULL, 0x847b7bf17bff8af6ULL, 0x803535d435b5e16aULL, + 0xf51d1d741de8693aULL, 0xb3e0e0a7e05347ddULL, 0x21d7d77bd7f6acb3ULL, + 0x9cc2c22fc25eed99ULL, 0x432e2eb82e6d965cULL, 0x294b4b314b627a96ULL, + 0x5dfefedffea321e1ULL, 0xd5575741578216aeULL, 0xbd15155415a8412aULL, + 0xe87777c1779fb6eeULL, 0x923737dc37a5eb6eULL, 0x9ee5e5b3e57b56d7ULL, + 0x139f9f469f8cd923ULL, 0x23f0f0e7f0d317fdULL, 0x204a4a354a6a7f94ULL, + 0x44dada4fda9e95a9ULL, 0xa258587d58fa25b0ULL, 0xcfc9c903c906ca8fULL, + 0x7c2929a429558d52ULL, 0x5a0a0a280a502214ULL, 0x50b1b1feb1e14f7fULL, + 0xc9a0a0baa0691a5dULL, 0x146b6bb16b7fdad6ULL, 0xd985852e855cab17ULL, + 0x3cbdbdcebd817367ULL, 0x8f5d5d695dd234baULL, 0x9010104010805020ULL, + 0x07f4f4f7f4f303f5ULL, 0xddcbcb0bcb16c08bULL, 0xd33e3ef83eedc67cULL, + 0x2d0505140528110aULL, 0x78676781671fe6ceULL, 0x97e4e4b7e47353d5ULL, + 0x0227279c2725bb4eULL, 0x7341411941325882ULL, 0xa78b8b168b2c9d0bULL, + 0xf6a7a7a6a7510153ULL, 0xb27d7de97dcf94faULL, 0x4995956e95dcfb37ULL, + 0x56d8d847d88e9fadULL, 0x70fbfbcbfb8b30ebULL, 0xcdeeee9fee2371c1ULL, + 0xbb7c7ced7cc791f8ULL, 0x716666856617e3ccULL, 0x7bdddd53dda68ea7ULL, + 0xaf17175c17b84b2eULL, 0x454747014702468eULL, 0x1a9e9e429e84dc21ULL, + 0xd4caca0fca1ec589ULL, 0x582d2db42d75995aULL, 0x2ebfbfc6bf917963ULL, + 0x3f07071c07381b0eULL, 0xacadad8ead012347ULL, 0xb05a5a755aea2fb4ULL, + 0xef838336836cb51bULL, 0xb63333cc3385ff66ULL, 0x5c636391633ff2c6ULL, + 0x1202020802100a04ULL, 0x93aaaa92aa393849ULL, 0xde7171d971afa8e2ULL, + 0xc6c8c807c80ecf8dULL, 0xd119196419c87d32ULL, 0x3b49493949727092ULL, + 0x5fd9d943d9869aafULL, 0x31f2f2eff2c31df9ULL, 0xa8e3e3abe34b48dbULL, + 0xb95b5b715be22ab6ULL, 0xbc88881a8834920dULL, 0x3e9a9a529aa4c829ULL, + 0x0b262698262dbe4cULL, 0xbf3232c8328dfa64ULL, 0x59b0b0fab0e94a7dULL, + 0xf2e9e983e91b6acfULL, 0x770f0f3c0f78331eULL, 0x33d5d573d5e6a6b7ULL, + 0xf480803a8074ba1dULL, 0x27bebec2be997c61ULL, 0xebcdcd13cd26de87ULL, + 0x893434d034bde468ULL, 0x3248483d487a7590ULL, 0x54ffffdbffab24e3ULL, + 0x8d7a7af57af78ff4ULL, 0x6490907a90f4ea3dULL, 0x9d5f5f615fc23ebeULL, + 0x3d202080201da040ULL, 0x0f6868bd6867d5d0ULL, 0xca1a1a681ad07234ULL, + 0xb7aeae82ae192c41ULL, 0x7db4b4eab4c95e75ULL, 0xce54544d549a19a8ULL, + 0x7f93937693ece53bULL, 0x2f222288220daa44ULL, 0x6364648d6407e9c8ULL, + 0x2af1f1e3f1db12ffULL, 0xcc7373d173bfa2e6ULL, 0x8212124812905a24ULL, + 0x7a40401d403a5d80ULL, 0x4808082008402810ULL, 0x95c3c32bc356e89bULL, + 0xdfecec97ec337bc5ULL, 0x4ddbdb4bdb9690abULL, 0xc0a1a1bea1611f5fULL, + 0x918d8d0e8d1c8307ULL, 0xc83d3df43df5c97aULL, 0x5b97976697ccf133ULL, + 0x0000000000000000ULL, 0xf9cfcf1bcf36d483ULL, 0x6e2b2bac2b458756ULL, + 0xe17676c57697b3ecULL, 0xe68282328264b019ULL, 0x28d6d67fd6fea9b1ULL, + 0xc31b1b6c1bd87736ULL, 0x74b5b5eeb5c15b77ULL, 0xbeafaf86af112943ULL, + 0x1d6a6ab56a77dfd4ULL, 0xea50505d50ba0da0ULL, 0x5745450945124c8aULL, + 0x38f3f3ebf3cb18fbULL, 0xad3030c0309df060ULL, 0xc4efef9bef2b74c3ULL, + 0xda3f3ffc3fe5c37eULL, 0xc755554955921caaULL, 0xdba2a2b2a2791059ULL, + 0xe9eaea8fea0365c9ULL, 0x6a656589650feccaULL, 0x03babad2bab96869ULL, + 0x4a2f2fbc2f65935eULL, 0x8ec0c027c04ee79dULL, 0x60dede5fdebe81a1ULL, + 0xfc1c1c701ce06c38ULL, 0x46fdfdd3fdbb2ee7ULL, 0x1f4d4d294d52649aULL, + 0x7692927292e4e039ULL, 0xfa7575c9758fbceaULL, 0x3606061806301e0cULL, + 0xae8a8a128a249809ULL, 0x4bb2b2f2b2f94079ULL, 0x85e6e6bfe66359d1ULL, + 0x7e0e0e380e70361cULL, 0xe71f1f7c1ff8633eULL, 0x556262956237f7c4ULL, + 0x3ad4d477d4eea3b5ULL, 0x81a8a89aa829324dULL, 0x5296966296c4f431ULL, + 0x62f9f9c3f99b3aefULL, 0xa3c5c533c566f697ULL, 0x102525942535b14aULL, + 0xab59597959f220b2ULL, 0xd084842a8454ae15ULL, 0xc57272d572b7a7e4ULL, + 0xec3939e439d5dd72ULL, 0x164c4c2d4c5a6198ULL, 0x945e5e655eca3bbcULL, + 0x9f7878fd78e785f0ULL, 0xe53838e038ddd870ULL, 0x988c8c0a8c148605ULL, + 0x17d1d163d1c6b2bfULL, 0xe4a5a5aea5410b57ULL, 0xa1e2e2afe2434dd9ULL, + 0x4e616199612ff8c2ULL, 0x42b3b3f6b3f1457bULL, 0x342121842115a542ULL, + 0x089c9c4a9c94d625ULL, 0xee1e1e781ef0663cULL, 0x6143431143225286ULL, + 0xb1c7c73bc776fc93ULL, 0x4ffcfcd7fcb32be5ULL, 0x2404041004201408ULL, + 0xe351515951b208a2ULL, 0x2599995e99bcc72fULL, 0x226d6da96d4fc4daULL, + 0x650d0d340d68391aULL, 0x79fafacffa8335e9ULL, 0x69dfdf5bdfb684a3ULL, + 0xa97e7ee57ed79bfcULL, 0x19242490243db448ULL, 0xfe3b3bec3bc5d776ULL, + 0x9aabab96ab313d4bULL, 0xf0cece1fce3ed181ULL, 0x9911114411885522ULL, + 0x838f8f068f0c8903ULL, 0x044e4e254e4a6b9cULL, 0x66b7b7e6b7d15173ULL, + 0xe0ebeb8beb0b60cbULL, 0xc13c3cf03cfdcc78ULL, 0xfd81813e817cbf1fULL, + 0x4094946a94d4fe35ULL, 0x1cf7f7fbf7eb0cf3ULL, 0x18b9b9deb9a1676fULL, + 0x8b13134c13985f26ULL, 0x512c2cb02c7d9c58ULL, 0x05d3d36bd3d6b8bbULL, + 0x8ce7e7bbe76b5cd3ULL, 0x396e6ea56e57cbdcULL, 0xaac4c437c46ef395ULL, + 0x1b03030c03180f06ULL, 0xdc565645568a13acULL, 0x5e44440d441a4988ULL, + 0xa07f7fe17fdf9efeULL, 0x88a9a99ea921374fULL, 0x672a2aa82a4d8254ULL, + 0x0abbbbd6bbb16d6bULL, 0x87c1c123c146e29fULL, 0xf153535153a202a6ULL, + 0x72dcdc57dcae8ba5ULL, 0x530b0b2c0b582716ULL, 0x019d9d4e9d9cd327ULL, + 0x2b6c6cad6c47c1d8ULL, 0xa43131c43195f562ULL, 0xf37474cd7487b9e8ULL, + 0x15f6f6fff6e309f1ULL, 0x4c464605460a438cULL, 0xa5acac8aac092645ULL, + 0xb589891e893c970fULL, 0xb414145014a04428ULL, 0xbae1e1a3e15b42dfULL, + 0xa616165816b04e2cULL, 0xf73a3ae83acdd274ULL, 0x066969b9696fd0d2ULL, + 0x4109092409482d12ULL, 0xd77070dd70a7ade0ULL, 0x6fb6b6e2b6d95471ULL, + 0x1ed0d067d0ceb7bdULL, 0xd6eded93ed3b7ec7ULL, 0xe2cccc17cc2edb85ULL, + 0x68424215422a5784ULL, 0x2c98985a98b4c22dULL, 0xeda4a4aaa4490e55ULL, + 0x752828a0285d8850ULL, 0x865c5c6d5cda31b8ULL, 0x6bf8f8c7f8933fedULL, + 0xc28686228644a411ULL, +}; + +static const u64 C2[256] = { + 0x30d818186018c078ULL, 0x462623238c2305afULL, 0x91b8c6c63fc67ef9ULL, + 0xcdfbe8e887e8136fULL, 0x13cb878726874ca1ULL, 0x6d11b8b8dab8a962ULL, + 0x0209010104010805ULL, 0x9e0d4f4f214f426eULL, 0x6c9b3636d836adeeULL, + 0x51ffa6a6a2a65904ULL, 0xb90cd2d26fd2debdULL, 0xf70ef5f5f3f5fb06ULL, + 0xf2967979f979ef80ULL, 0xde306f6fa16f5fceULL, 0x3f6d91917e91fcefULL, + 0xa4f852525552aa07ULL, 0xc04760609d6027fdULL, 0x6535bcbccabc8976ULL, + 0x2b379b9b569baccdULL, 0x018a8e8e028e048cULL, 0x5bd2a3a3b6a37115ULL, + 0x186c0c0c300c603cULL, 0xf6847b7bf17bff8aULL, 0x6a803535d435b5e1ULL, + 0x3af51d1d741de869ULL, 0xddb3e0e0a7e05347ULL, 0xb321d7d77bd7f6acULL, + 0x999cc2c22fc25eedULL, 0x5c432e2eb82e6d96ULL, 0x96294b4b314b627aULL, + 0xe15dfefedffea321ULL, 0xaed5575741578216ULL, 0x2abd15155415a841ULL, + 0xeee87777c1779fb6ULL, 0x6e923737dc37a5ebULL, 0xd79ee5e5b3e57b56ULL, + 0x23139f9f469f8cd9ULL, 0xfd23f0f0e7f0d317ULL, 0x94204a4a354a6a7fULL, + 0xa944dada4fda9e95ULL, 0xb0a258587d58fa25ULL, 0x8fcfc9c903c906caULL, + 0x527c2929a429558dULL, 0x145a0a0a280a5022ULL, 0x7f50b1b1feb1e14fULL, + 0x5dc9a0a0baa0691aULL, 0xd6146b6bb16b7fdaULL, 0x17d985852e855cabULL, + 0x673cbdbdcebd8173ULL, 0xba8f5d5d695dd234ULL, 0x2090101040108050ULL, + 0xf507f4f4f7f4f303ULL, 0x8bddcbcb0bcb16c0ULL, 0x7cd33e3ef83eedc6ULL, + 0x0a2d050514052811ULL, 0xce78676781671fe6ULL, 0xd597e4e4b7e47353ULL, + 0x4e0227279c2725bbULL, 0x8273414119413258ULL, 0x0ba78b8b168b2c9dULL, + 0x53f6a7a7a6a75101ULL, 0xfab27d7de97dcf94ULL, 0x374995956e95dcfbULL, + 0xad56d8d847d88e9fULL, 0xeb70fbfbcbfb8b30ULL, 0xc1cdeeee9fee2371ULL, + 0xf8bb7c7ced7cc791ULL, 0xcc716666856617e3ULL, 0xa77bdddd53dda68eULL, + 0x2eaf17175c17b84bULL, 0x8e45474701470246ULL, 0x211a9e9e429e84dcULL, + 0x89d4caca0fca1ec5ULL, 0x5a582d2db42d7599ULL, 0x632ebfbfc6bf9179ULL, + 0x0e3f07071c07381bULL, 0x47acadad8ead0123ULL, 0xb4b05a5a755aea2fULL, + 0x1bef838336836cb5ULL, 0x66b63333cc3385ffULL, 0xc65c636391633ff2ULL, + 0x041202020802100aULL, 0x4993aaaa92aa3938ULL, 0xe2de7171d971afa8ULL, + 0x8dc6c8c807c80ecfULL, 0x32d119196419c87dULL, 0x923b494939497270ULL, + 0xaf5fd9d943d9869aULL, 0xf931f2f2eff2c31dULL, 0xdba8e3e3abe34b48ULL, + 0xb6b95b5b715be22aULL, 0x0dbc88881a883492ULL, 0x293e9a9a529aa4c8ULL, + 0x4c0b262698262dbeULL, 0x64bf3232c8328dfaULL, 0x7d59b0b0fab0e94aULL, + 0xcff2e9e983e91b6aULL, 0x1e770f0f3c0f7833ULL, 0xb733d5d573d5e6a6ULL, + 0x1df480803a8074baULL, 0x6127bebec2be997cULL, 0x87ebcdcd13cd26deULL, + 0x68893434d034bde4ULL, 0x903248483d487a75ULL, 0xe354ffffdbffab24ULL, + 0xf48d7a7af57af78fULL, 0x3d6490907a90f4eaULL, 0xbe9d5f5f615fc23eULL, + 0x403d202080201da0ULL, 0xd00f6868bd6867d5ULL, 0x34ca1a1a681ad072ULL, + 0x41b7aeae82ae192cULL, 0x757db4b4eab4c95eULL, 0xa8ce54544d549a19ULL, + 0x3b7f93937693ece5ULL, 0x442f222288220daaULL, 0xc86364648d6407e9ULL, + 0xff2af1f1e3f1db12ULL, 0xe6cc7373d173bfa2ULL, 0x248212124812905aULL, + 0x807a40401d403a5dULL, 0x1048080820084028ULL, 0x9b95c3c32bc356e8ULL, + 0xc5dfecec97ec337bULL, 0xab4ddbdb4bdb9690ULL, 0x5fc0a1a1bea1611fULL, + 0x07918d8d0e8d1c83ULL, 0x7ac83d3df43df5c9ULL, 0x335b97976697ccf1ULL, + 0x0000000000000000ULL, 0x83f9cfcf1bcf36d4ULL, 0x566e2b2bac2b4587ULL, + 0xece17676c57697b3ULL, 0x19e68282328264b0ULL, 0xb128d6d67fd6fea9ULL, + 0x36c31b1b6c1bd877ULL, 0x7774b5b5eeb5c15bULL, 0x43beafaf86af1129ULL, + 0xd41d6a6ab56a77dfULL, 0xa0ea50505d50ba0dULL, 0x8a5745450945124cULL, + 0xfb38f3f3ebf3cb18ULL, 0x60ad3030c0309df0ULL, 0xc3c4efef9bef2b74ULL, + 0x7eda3f3ffc3fe5c3ULL, 0xaac755554955921cULL, 0x59dba2a2b2a27910ULL, + 0xc9e9eaea8fea0365ULL, 0xca6a656589650fecULL, 0x6903babad2bab968ULL, + 0x5e4a2f2fbc2f6593ULL, 0x9d8ec0c027c04ee7ULL, 0xa160dede5fdebe81ULL, + 0x38fc1c1c701ce06cULL, 0xe746fdfdd3fdbb2eULL, 0x9a1f4d4d294d5264ULL, + 0x397692927292e4e0ULL, 0xeafa7575c9758fbcULL, 0x0c3606061806301eULL, + 0x09ae8a8a128a2498ULL, 0x794bb2b2f2b2f940ULL, 0xd185e6e6bfe66359ULL, + 0x1c7e0e0e380e7036ULL, 0x3ee71f1f7c1ff863ULL, 0xc4556262956237f7ULL, + 0xb53ad4d477d4eea3ULL, 0x4d81a8a89aa82932ULL, 0x315296966296c4f4ULL, + 0xef62f9f9c3f99b3aULL, 0x97a3c5c533c566f6ULL, 0x4a102525942535b1ULL, + 0xb2ab59597959f220ULL, 0x15d084842a8454aeULL, 0xe4c57272d572b7a7ULL, + 0x72ec3939e439d5ddULL, 0x98164c4c2d4c5a61ULL, 0xbc945e5e655eca3bULL, + 0xf09f7878fd78e785ULL, 0x70e53838e038ddd8ULL, 0x05988c8c0a8c1486ULL, + 0xbf17d1d163d1c6b2ULL, 0x57e4a5a5aea5410bULL, 0xd9a1e2e2afe2434dULL, + 0xc24e616199612ff8ULL, 0x7b42b3b3f6b3f145ULL, 0x42342121842115a5ULL, + 0x25089c9c4a9c94d6ULL, 0x3cee1e1e781ef066ULL, 0x8661434311432252ULL, + 0x93b1c7c73bc776fcULL, 0xe54ffcfcd7fcb32bULL, 0x0824040410042014ULL, + 0xa2e351515951b208ULL, 0x2f2599995e99bcc7ULL, 0xda226d6da96d4fc4ULL, + 0x1a650d0d340d6839ULL, 0xe979fafacffa8335ULL, 0xa369dfdf5bdfb684ULL, + 0xfca97e7ee57ed79bULL, 0x4819242490243db4ULL, 0x76fe3b3bec3bc5d7ULL, + 0x4b9aabab96ab313dULL, 0x81f0cece1fce3ed1ULL, 0x2299111144118855ULL, + 0x03838f8f068f0c89ULL, 0x9c044e4e254e4a6bULL, 0x7366b7b7e6b7d151ULL, + 0xcbe0ebeb8beb0b60ULL, 0x78c13c3cf03cfdccULL, 0x1ffd81813e817cbfULL, + 0x354094946a94d4feULL, 0xf31cf7f7fbf7eb0cULL, 0x6f18b9b9deb9a167ULL, + 0x268b13134c13985fULL, 0x58512c2cb02c7d9cULL, 0xbb05d3d36bd3d6b8ULL, + 0xd38ce7e7bbe76b5cULL, 0xdc396e6ea56e57cbULL, 0x95aac4c437c46ef3ULL, + 0x061b03030c03180fULL, 0xacdc565645568a13ULL, 0x885e44440d441a49ULL, + 0xfea07f7fe17fdf9eULL, 0x4f88a9a99ea92137ULL, 0x54672a2aa82a4d82ULL, + 0x6b0abbbbd6bbb16dULL, 0x9f87c1c123c146e2ULL, 0xa6f153535153a202ULL, + 0xa572dcdc57dcae8bULL, 0x16530b0b2c0b5827ULL, 0x27019d9d4e9d9cd3ULL, + 0xd82b6c6cad6c47c1ULL, 0x62a43131c43195f5ULL, 0xe8f37474cd7487b9ULL, + 0xf115f6f6fff6e309ULL, 0x8c4c464605460a43ULL, 0x45a5acac8aac0926ULL, + 0x0fb589891e893c97ULL, 0x28b414145014a044ULL, 0xdfbae1e1a3e15b42ULL, + 0x2ca616165816b04eULL, 0x74f73a3ae83acdd2ULL, 0xd2066969b9696fd0ULL, + 0x124109092409482dULL, 0xe0d77070dd70a7adULL, 0x716fb6b6e2b6d954ULL, + 0xbd1ed0d067d0ceb7ULL, 0xc7d6eded93ed3b7eULL, 0x85e2cccc17cc2edbULL, + 0x8468424215422a57ULL, 0x2d2c98985a98b4c2ULL, 0x55eda4a4aaa4490eULL, + 0x50752828a0285d88ULL, 0xb8865c5c6d5cda31ULL, 0xed6bf8f8c7f8933fULL, + 0x11c28686228644a4ULL, +}; + +static const u64 C3[256] = { + 0x7830d818186018c0ULL, 0xaf462623238c2305ULL, 0xf991b8c6c63fc67eULL, + 0x6fcdfbe8e887e813ULL, 0xa113cb878726874cULL, 0x626d11b8b8dab8a9ULL, + 0x0502090101040108ULL, 0x6e9e0d4f4f214f42ULL, 0xee6c9b3636d836adULL, + 0x0451ffa6a6a2a659ULL, 0xbdb90cd2d26fd2deULL, 0x06f70ef5f5f3f5fbULL, + 0x80f2967979f979efULL, 0xcede306f6fa16f5fULL, 0xef3f6d91917e91fcULL, + 0x07a4f852525552aaULL, 0xfdc04760609d6027ULL, 0x766535bcbccabc89ULL, + 0xcd2b379b9b569bacULL, 0x8c018a8e8e028e04ULL, 0x155bd2a3a3b6a371ULL, + 0x3c186c0c0c300c60ULL, 0x8af6847b7bf17bffULL, 0xe16a803535d435b5ULL, + 0x693af51d1d741de8ULL, 0x47ddb3e0e0a7e053ULL, 0xacb321d7d77bd7f6ULL, + 0xed999cc2c22fc25eULL, 0x965c432e2eb82e6dULL, 0x7a96294b4b314b62ULL, + 0x21e15dfefedffea3ULL, 0x16aed55757415782ULL, 0x412abd15155415a8ULL, + 0xb6eee87777c1779fULL, 0xeb6e923737dc37a5ULL, 0x56d79ee5e5b3e57bULL, + 0xd923139f9f469f8cULL, 0x17fd23f0f0e7f0d3ULL, 0x7f94204a4a354a6aULL, + 0x95a944dada4fda9eULL, 0x25b0a258587d58faULL, 0xca8fcfc9c903c906ULL, + 0x8d527c2929a42955ULL, 0x22145a0a0a280a50ULL, 0x4f7f50b1b1feb1e1ULL, + 0x1a5dc9a0a0baa069ULL, 0xdad6146b6bb16b7fULL, 0xab17d985852e855cULL, + 0x73673cbdbdcebd81ULL, 0x34ba8f5d5d695dd2ULL, 0x5020901010401080ULL, + 0x03f507f4f4f7f4f3ULL, 0xc08bddcbcb0bcb16ULL, 0xc67cd33e3ef83eedULL, + 0x110a2d0505140528ULL, 0xe6ce78676781671fULL, 0x53d597e4e4b7e473ULL, + 0xbb4e0227279c2725ULL, 0x5882734141194132ULL, 0x9d0ba78b8b168b2cULL, + 0x0153f6a7a7a6a751ULL, 0x94fab27d7de97dcfULL, 0xfb374995956e95dcULL, + 0x9fad56d8d847d88eULL, 0x30eb70fbfbcbfb8bULL, 0x71c1cdeeee9fee23ULL, + 0x91f8bb7c7ced7cc7ULL, 0xe3cc716666856617ULL, 0x8ea77bdddd53dda6ULL, + 0x4b2eaf17175c17b8ULL, 0x468e454747014702ULL, 0xdc211a9e9e429e84ULL, + 0xc589d4caca0fca1eULL, 0x995a582d2db42d75ULL, 0x79632ebfbfc6bf91ULL, + 0x1b0e3f07071c0738ULL, 0x2347acadad8ead01ULL, 0x2fb4b05a5a755aeaULL, + 0xb51bef838336836cULL, 0xff66b63333cc3385ULL, 0xf2c65c636391633fULL, + 0x0a04120202080210ULL, 0x384993aaaa92aa39ULL, 0xa8e2de7171d971afULL, + 0xcf8dc6c8c807c80eULL, 0x7d32d119196419c8ULL, 0x70923b4949394972ULL, + 0x9aaf5fd9d943d986ULL, 0x1df931f2f2eff2c3ULL, 0x48dba8e3e3abe34bULL, + 0x2ab6b95b5b715be2ULL, 0x920dbc88881a8834ULL, 0xc8293e9a9a529aa4ULL, + 0xbe4c0b262698262dULL, 0xfa64bf3232c8328dULL, 0x4a7d59b0b0fab0e9ULL, + 0x6acff2e9e983e91bULL, 0x331e770f0f3c0f78ULL, 0xa6b733d5d573d5e6ULL, + 0xba1df480803a8074ULL, 0x7c6127bebec2be99ULL, 0xde87ebcdcd13cd26ULL, + 0xe468893434d034bdULL, 0x75903248483d487aULL, 0x24e354ffffdbffabULL, + 0x8ff48d7a7af57af7ULL, 0xea3d6490907a90f4ULL, 0x3ebe9d5f5f615fc2ULL, + 0xa0403d202080201dULL, 0xd5d00f6868bd6867ULL, 0x7234ca1a1a681ad0ULL, + 0x2c41b7aeae82ae19ULL, 0x5e757db4b4eab4c9ULL, 0x19a8ce54544d549aULL, + 0xe53b7f93937693ecULL, 0xaa442f222288220dULL, 0xe9c86364648d6407ULL, + 0x12ff2af1f1e3f1dbULL, 0xa2e6cc7373d173bfULL, 0x5a24821212481290ULL, + 0x5d807a40401d403aULL, 0x2810480808200840ULL, 0xe89b95c3c32bc356ULL, + 0x7bc5dfecec97ec33ULL, 0x90ab4ddbdb4bdb96ULL, 0x1f5fc0a1a1bea161ULL, + 0x8307918d8d0e8d1cULL, 0xc97ac83d3df43df5ULL, 0xf1335b97976697ccULL, + 0x0000000000000000ULL, 0xd483f9cfcf1bcf36ULL, 0x87566e2b2bac2b45ULL, + 0xb3ece17676c57697ULL, 0xb019e68282328264ULL, 0xa9b128d6d67fd6feULL, + 0x7736c31b1b6c1bd8ULL, 0x5b7774b5b5eeb5c1ULL, 0x2943beafaf86af11ULL, + 0xdfd41d6a6ab56a77ULL, 0x0da0ea50505d50baULL, 0x4c8a574545094512ULL, + 0x18fb38f3f3ebf3cbULL, 0xf060ad3030c0309dULL, 0x74c3c4efef9bef2bULL, + 0xc37eda3f3ffc3fe5ULL, 0x1caac75555495592ULL, 0x1059dba2a2b2a279ULL, + 0x65c9e9eaea8fea03ULL, 0xecca6a656589650fULL, 0x686903babad2bab9ULL, + 0x935e4a2f2fbc2f65ULL, 0xe79d8ec0c027c04eULL, 0x81a160dede5fdebeULL, + 0x6c38fc1c1c701ce0ULL, 0x2ee746fdfdd3fdbbULL, 0x649a1f4d4d294d52ULL, + 0xe0397692927292e4ULL, 0xbceafa7575c9758fULL, 0x1e0c360606180630ULL, + 0x9809ae8a8a128a24ULL, 0x40794bb2b2f2b2f9ULL, 0x59d185e6e6bfe663ULL, + 0x361c7e0e0e380e70ULL, 0x633ee71f1f7c1ff8ULL, 0xf7c4556262956237ULL, + 0xa3b53ad4d477d4eeULL, 0x324d81a8a89aa829ULL, 0xf4315296966296c4ULL, + 0x3aef62f9f9c3f99bULL, 0xf697a3c5c533c566ULL, 0xb14a102525942535ULL, + 0x20b2ab59597959f2ULL, 0xae15d084842a8454ULL, 0xa7e4c57272d572b7ULL, + 0xdd72ec3939e439d5ULL, 0x6198164c4c2d4c5aULL, 0x3bbc945e5e655ecaULL, + 0x85f09f7878fd78e7ULL, 0xd870e53838e038ddULL, 0x8605988c8c0a8c14ULL, + 0xb2bf17d1d163d1c6ULL, 0x0b57e4a5a5aea541ULL, 0x4dd9a1e2e2afe243ULL, + 0xf8c24e616199612fULL, 0x457b42b3b3f6b3f1ULL, 0xa542342121842115ULL, + 0xd625089c9c4a9c94ULL, 0x663cee1e1e781ef0ULL, 0x5286614343114322ULL, + 0xfc93b1c7c73bc776ULL, 0x2be54ffcfcd7fcb3ULL, 0x1408240404100420ULL, + 0x08a2e351515951b2ULL, 0xc72f2599995e99bcULL, 0xc4da226d6da96d4fULL, + 0x391a650d0d340d68ULL, 0x35e979fafacffa83ULL, 0x84a369dfdf5bdfb6ULL, + 0x9bfca97e7ee57ed7ULL, 0xb44819242490243dULL, 0xd776fe3b3bec3bc5ULL, + 0x3d4b9aabab96ab31ULL, 0xd181f0cece1fce3eULL, 0x5522991111441188ULL, + 0x8903838f8f068f0cULL, 0x6b9c044e4e254e4aULL, 0x517366b7b7e6b7d1ULL, + 0x60cbe0ebeb8beb0bULL, 0xcc78c13c3cf03cfdULL, 0xbf1ffd81813e817cULL, + 0xfe354094946a94d4ULL, 0x0cf31cf7f7fbf7ebULL, 0x676f18b9b9deb9a1ULL, + 0x5f268b13134c1398ULL, 0x9c58512c2cb02c7dULL, 0xb8bb05d3d36bd3d6ULL, + 0x5cd38ce7e7bbe76bULL, 0xcbdc396e6ea56e57ULL, 0xf395aac4c437c46eULL, + 0x0f061b03030c0318ULL, 0x13acdc565645568aULL, 0x49885e44440d441aULL, + 0x9efea07f7fe17fdfULL, 0x374f88a9a99ea921ULL, 0x8254672a2aa82a4dULL, + 0x6d6b0abbbbd6bbb1ULL, 0xe29f87c1c123c146ULL, 0x02a6f153535153a2ULL, + 0x8ba572dcdc57dcaeULL, 0x2716530b0b2c0b58ULL, 0xd327019d9d4e9d9cULL, + 0xc1d82b6c6cad6c47ULL, 0xf562a43131c43195ULL, 0xb9e8f37474cd7487ULL, + 0x09f115f6f6fff6e3ULL, 0x438c4c464605460aULL, 0x2645a5acac8aac09ULL, + 0x970fb589891e893cULL, 0x4428b414145014a0ULL, 0x42dfbae1e1a3e15bULL, + 0x4e2ca616165816b0ULL, 0xd274f73a3ae83acdULL, 0xd0d2066969b9696fULL, + 0x2d12410909240948ULL, 0xade0d77070dd70a7ULL, 0x54716fb6b6e2b6d9ULL, + 0xb7bd1ed0d067d0ceULL, 0x7ec7d6eded93ed3bULL, 0xdb85e2cccc17cc2eULL, + 0x578468424215422aULL, 0xc22d2c98985a98b4ULL, 0x0e55eda4a4aaa449ULL, + 0x8850752828a0285dULL, 0x31b8865c5c6d5cdaULL, 0x3fed6bf8f8c7f893ULL, + 0xa411c28686228644ULL, +}; + +static const u64 C4[256] = { + 0xc07830d818186018ULL, 0x05af462623238c23ULL, 0x7ef991b8c6c63fc6ULL, + 0x136fcdfbe8e887e8ULL, 0x4ca113cb87872687ULL, 0xa9626d11b8b8dab8ULL, + 0x0805020901010401ULL, 0x426e9e0d4f4f214fULL, 0xadee6c9b3636d836ULL, + 0x590451ffa6a6a2a6ULL, 0xdebdb90cd2d26fd2ULL, 0xfb06f70ef5f5f3f5ULL, + 0xef80f2967979f979ULL, 0x5fcede306f6fa16fULL, 0xfcef3f6d91917e91ULL, + 0xaa07a4f852525552ULL, 0x27fdc04760609d60ULL, 0x89766535bcbccabcULL, + 0xaccd2b379b9b569bULL, 0x048c018a8e8e028eULL, 0x71155bd2a3a3b6a3ULL, + 0x603c186c0c0c300cULL, 0xff8af6847b7bf17bULL, 0xb5e16a803535d435ULL, + 0xe8693af51d1d741dULL, 0x5347ddb3e0e0a7e0ULL, 0xf6acb321d7d77bd7ULL, + 0x5eed999cc2c22fc2ULL, 0x6d965c432e2eb82eULL, 0x627a96294b4b314bULL, + 0xa321e15dfefedffeULL, 0x8216aed557574157ULL, 0xa8412abd15155415ULL, + 0x9fb6eee87777c177ULL, 0xa5eb6e923737dc37ULL, 0x7b56d79ee5e5b3e5ULL, + 0x8cd923139f9f469fULL, 0xd317fd23f0f0e7f0ULL, 0x6a7f94204a4a354aULL, + 0x9e95a944dada4fdaULL, 0xfa25b0a258587d58ULL, 0x06ca8fcfc9c903c9ULL, + 0x558d527c2929a429ULL, 0x5022145a0a0a280aULL, 0xe14f7f50b1b1feb1ULL, + 0x691a5dc9a0a0baa0ULL, 0x7fdad6146b6bb16bULL, 0x5cab17d985852e85ULL, + 0x8173673cbdbdcebdULL, 0xd234ba8f5d5d695dULL, 0x8050209010104010ULL, + 0xf303f507f4f4f7f4ULL, 0x16c08bddcbcb0bcbULL, 0xedc67cd33e3ef83eULL, + 0x28110a2d05051405ULL, 0x1fe6ce7867678167ULL, 0x7353d597e4e4b7e4ULL, + 0x25bb4e0227279c27ULL, 0x3258827341411941ULL, 0x2c9d0ba78b8b168bULL, + 0x510153f6a7a7a6a7ULL, 0xcf94fab27d7de97dULL, 0xdcfb374995956e95ULL, + 0x8e9fad56d8d847d8ULL, 0x8b30eb70fbfbcbfbULL, 0x2371c1cdeeee9feeULL, + 0xc791f8bb7c7ced7cULL, 0x17e3cc7166668566ULL, 0xa68ea77bdddd53ddULL, + 0xb84b2eaf17175c17ULL, 0x02468e4547470147ULL, 0x84dc211a9e9e429eULL, + 0x1ec589d4caca0fcaULL, 0x75995a582d2db42dULL, 0x9179632ebfbfc6bfULL, + 0x381b0e3f07071c07ULL, 0x012347acadad8eadULL, 0xea2fb4b05a5a755aULL, + 0x6cb51bef83833683ULL, 0x85ff66b63333cc33ULL, 0x3ff2c65c63639163ULL, + 0x100a041202020802ULL, 0x39384993aaaa92aaULL, 0xafa8e2de7171d971ULL, + 0x0ecf8dc6c8c807c8ULL, 0xc87d32d119196419ULL, 0x7270923b49493949ULL, + 0x869aaf5fd9d943d9ULL, 0xc31df931f2f2eff2ULL, 0x4b48dba8e3e3abe3ULL, + 0xe22ab6b95b5b715bULL, 0x34920dbc88881a88ULL, 0xa4c8293e9a9a529aULL, + 0x2dbe4c0b26269826ULL, 0x8dfa64bf3232c832ULL, 0xe94a7d59b0b0fab0ULL, + 0x1b6acff2e9e983e9ULL, 0x78331e770f0f3c0fULL, 0xe6a6b733d5d573d5ULL, + 0x74ba1df480803a80ULL, 0x997c6127bebec2beULL, 0x26de87ebcdcd13cdULL, + 0xbde468893434d034ULL, 0x7a75903248483d48ULL, 0xab24e354ffffdbffULL, + 0xf78ff48d7a7af57aULL, 0xf4ea3d6490907a90ULL, 0xc23ebe9d5f5f615fULL, + 0x1da0403d20208020ULL, 0x67d5d00f6868bd68ULL, 0xd07234ca1a1a681aULL, + 0x192c41b7aeae82aeULL, 0xc95e757db4b4eab4ULL, 0x9a19a8ce54544d54ULL, + 0xece53b7f93937693ULL, 0x0daa442f22228822ULL, 0x07e9c86364648d64ULL, + 0xdb12ff2af1f1e3f1ULL, 0xbfa2e6cc7373d173ULL, 0x905a248212124812ULL, + 0x3a5d807a40401d40ULL, 0x4028104808082008ULL, 0x56e89b95c3c32bc3ULL, + 0x337bc5dfecec97ecULL, 0x9690ab4ddbdb4bdbULL, 0x611f5fc0a1a1bea1ULL, + 0x1c8307918d8d0e8dULL, 0xf5c97ac83d3df43dULL, 0xccf1335b97976697ULL, + 0x0000000000000000ULL, 0x36d483f9cfcf1bcfULL, 0x4587566e2b2bac2bULL, + 0x97b3ece17676c576ULL, 0x64b019e682823282ULL, 0xfea9b128d6d67fd6ULL, + 0xd87736c31b1b6c1bULL, 0xc15b7774b5b5eeb5ULL, 0x112943beafaf86afULL, + 0x77dfd41d6a6ab56aULL, 0xba0da0ea50505d50ULL, 0x124c8a5745450945ULL, + 0xcb18fb38f3f3ebf3ULL, 0x9df060ad3030c030ULL, 0x2b74c3c4efef9befULL, + 0xe5c37eda3f3ffc3fULL, 0x921caac755554955ULL, 0x791059dba2a2b2a2ULL, + 0x0365c9e9eaea8feaULL, 0x0fecca6a65658965ULL, 0xb9686903babad2baULL, + 0x65935e4a2f2fbc2fULL, 0x4ee79d8ec0c027c0ULL, 0xbe81a160dede5fdeULL, + 0xe06c38fc1c1c701cULL, 0xbb2ee746fdfdd3fdULL, 0x52649a1f4d4d294dULL, + 0xe4e0397692927292ULL, 0x8fbceafa7575c975ULL, 0x301e0c3606061806ULL, + 0x249809ae8a8a128aULL, 0xf940794bb2b2f2b2ULL, 0x6359d185e6e6bfe6ULL, + 0x70361c7e0e0e380eULL, 0xf8633ee71f1f7c1fULL, 0x37f7c45562629562ULL, + 0xeea3b53ad4d477d4ULL, 0x29324d81a8a89aa8ULL, 0xc4f4315296966296ULL, + 0x9b3aef62f9f9c3f9ULL, 0x66f697a3c5c533c5ULL, 0x35b14a1025259425ULL, + 0xf220b2ab59597959ULL, 0x54ae15d084842a84ULL, 0xb7a7e4c57272d572ULL, + 0xd5dd72ec3939e439ULL, 0x5a6198164c4c2d4cULL, 0xca3bbc945e5e655eULL, + 0xe785f09f7878fd78ULL, 0xddd870e53838e038ULL, 0x148605988c8c0a8cULL, + 0xc6b2bf17d1d163d1ULL, 0x410b57e4a5a5aea5ULL, 0x434dd9a1e2e2afe2ULL, + 0x2ff8c24e61619961ULL, 0xf1457b42b3b3f6b3ULL, 0x15a5423421218421ULL, + 0x94d625089c9c4a9cULL, 0xf0663cee1e1e781eULL, 0x2252866143431143ULL, + 0x76fc93b1c7c73bc7ULL, 0xb32be54ffcfcd7fcULL, 0x2014082404041004ULL, + 0xb208a2e351515951ULL, 0xbcc72f2599995e99ULL, 0x4fc4da226d6da96dULL, + 0x68391a650d0d340dULL, 0x8335e979fafacffaULL, 0xb684a369dfdf5bdfULL, + 0xd79bfca97e7ee57eULL, 0x3db4481924249024ULL, 0xc5d776fe3b3bec3bULL, + 0x313d4b9aabab96abULL, 0x3ed181f0cece1fceULL, 0x8855229911114411ULL, + 0x0c8903838f8f068fULL, 0x4a6b9c044e4e254eULL, 0xd1517366b7b7e6b7ULL, + 0x0b60cbe0ebeb8bebULL, 0xfdcc78c13c3cf03cULL, 0x7cbf1ffd81813e81ULL, + 0xd4fe354094946a94ULL, 0xeb0cf31cf7f7fbf7ULL, 0xa1676f18b9b9deb9ULL, + 0x985f268b13134c13ULL, 0x7d9c58512c2cb02cULL, 0xd6b8bb05d3d36bd3ULL, + 0x6b5cd38ce7e7bbe7ULL, 0x57cbdc396e6ea56eULL, 0x6ef395aac4c437c4ULL, + 0x180f061b03030c03ULL, 0x8a13acdc56564556ULL, 0x1a49885e44440d44ULL, + 0xdf9efea07f7fe17fULL, 0x21374f88a9a99ea9ULL, 0x4d8254672a2aa82aULL, + 0xb16d6b0abbbbd6bbULL, 0x46e29f87c1c123c1ULL, 0xa202a6f153535153ULL, + 0xae8ba572dcdc57dcULL, 0x582716530b0b2c0bULL, 0x9cd327019d9d4e9dULL, + 0x47c1d82b6c6cad6cULL, 0x95f562a43131c431ULL, 0x87b9e8f37474cd74ULL, + 0xe309f115f6f6fff6ULL, 0x0a438c4c46460546ULL, 0x092645a5acac8aacULL, + 0x3c970fb589891e89ULL, 0xa04428b414145014ULL, 0x5b42dfbae1e1a3e1ULL, + 0xb04e2ca616165816ULL, 0xcdd274f73a3ae83aULL, 0x6fd0d2066969b969ULL, + 0x482d124109092409ULL, 0xa7ade0d77070dd70ULL, 0xd954716fb6b6e2b6ULL, + 0xceb7bd1ed0d067d0ULL, 0x3b7ec7d6eded93edULL, 0x2edb85e2cccc17ccULL, + 0x2a57846842421542ULL, 0xb4c22d2c98985a98ULL, 0x490e55eda4a4aaa4ULL, + 0x5d8850752828a028ULL, 0xda31b8865c5c6d5cULL, 0x933fed6bf8f8c7f8ULL, + 0x44a411c286862286ULL, +}; + +static const u64 C5[256] = { + 0x18c07830d8181860ULL, 0x2305af462623238cULL, 0xc67ef991b8c6c63fULL, + 0xe8136fcdfbe8e887ULL, 0x874ca113cb878726ULL, 0xb8a9626d11b8b8daULL, + 0x0108050209010104ULL, 0x4f426e9e0d4f4f21ULL, 0x36adee6c9b3636d8ULL, + 0xa6590451ffa6a6a2ULL, 0xd2debdb90cd2d26fULL, 0xf5fb06f70ef5f5f3ULL, + 0x79ef80f2967979f9ULL, 0x6f5fcede306f6fa1ULL, 0x91fcef3f6d91917eULL, + 0x52aa07a4f8525255ULL, 0x6027fdc04760609dULL, 0xbc89766535bcbccaULL, + 0x9baccd2b379b9b56ULL, 0x8e048c018a8e8e02ULL, 0xa371155bd2a3a3b6ULL, + 0x0c603c186c0c0c30ULL, 0x7bff8af6847b7bf1ULL, 0x35b5e16a803535d4ULL, + 0x1de8693af51d1d74ULL, 0xe05347ddb3e0e0a7ULL, 0xd7f6acb321d7d77bULL, + 0xc25eed999cc2c22fULL, 0x2e6d965c432e2eb8ULL, 0x4b627a96294b4b31ULL, + 0xfea321e15dfefedfULL, 0x578216aed5575741ULL, 0x15a8412abd151554ULL, + 0x779fb6eee87777c1ULL, 0x37a5eb6e923737dcULL, 0xe57b56d79ee5e5b3ULL, + 0x9f8cd923139f9f46ULL, 0xf0d317fd23f0f0e7ULL, 0x4a6a7f94204a4a35ULL, + 0xda9e95a944dada4fULL, 0x58fa25b0a258587dULL, 0xc906ca8fcfc9c903ULL, + 0x29558d527c2929a4ULL, 0x0a5022145a0a0a28ULL, 0xb1e14f7f50b1b1feULL, + 0xa0691a5dc9a0a0baULL, 0x6b7fdad6146b6bb1ULL, 0x855cab17d985852eULL, + 0xbd8173673cbdbdceULL, 0x5dd234ba8f5d5d69ULL, 0x1080502090101040ULL, + 0xf4f303f507f4f4f7ULL, 0xcb16c08bddcbcb0bULL, 0x3eedc67cd33e3ef8ULL, + 0x0528110a2d050514ULL, 0x671fe6ce78676781ULL, 0xe47353d597e4e4b7ULL, + 0x2725bb4e0227279cULL, 0x4132588273414119ULL, 0x8b2c9d0ba78b8b16ULL, + 0xa7510153f6a7a7a6ULL, 0x7dcf94fab27d7de9ULL, 0x95dcfb374995956eULL, + 0xd88e9fad56d8d847ULL, 0xfb8b30eb70fbfbcbULL, 0xee2371c1cdeeee9fULL, + 0x7cc791f8bb7c7cedULL, 0x6617e3cc71666685ULL, 0xdda68ea77bdddd53ULL, + 0x17b84b2eaf17175cULL, 0x4702468e45474701ULL, 0x9e84dc211a9e9e42ULL, + 0xca1ec589d4caca0fULL, 0x2d75995a582d2db4ULL, 0xbf9179632ebfbfc6ULL, + 0x07381b0e3f07071cULL, 0xad012347acadad8eULL, 0x5aea2fb4b05a5a75ULL, + 0x836cb51bef838336ULL, 0x3385ff66b63333ccULL, 0x633ff2c65c636391ULL, + 0x02100a0412020208ULL, 0xaa39384993aaaa92ULL, 0x71afa8e2de7171d9ULL, + 0xc80ecf8dc6c8c807ULL, 0x19c87d32d1191964ULL, 0x497270923b494939ULL, + 0xd9869aaf5fd9d943ULL, 0xf2c31df931f2f2efULL, 0xe34b48dba8e3e3abULL, + 0x5be22ab6b95b5b71ULL, 0x8834920dbc88881aULL, 0x9aa4c8293e9a9a52ULL, + 0x262dbe4c0b262698ULL, 0x328dfa64bf3232c8ULL, 0xb0e94a7d59b0b0faULL, + 0xe91b6acff2e9e983ULL, 0x0f78331e770f0f3cULL, 0xd5e6a6b733d5d573ULL, + 0x8074ba1df480803aULL, 0xbe997c6127bebec2ULL, 0xcd26de87ebcdcd13ULL, + 0x34bde468893434d0ULL, 0x487a75903248483dULL, 0xffab24e354ffffdbULL, + 0x7af78ff48d7a7af5ULL, 0x90f4ea3d6490907aULL, 0x5fc23ebe9d5f5f61ULL, + 0x201da0403d202080ULL, 0x6867d5d00f6868bdULL, 0x1ad07234ca1a1a68ULL, + 0xae192c41b7aeae82ULL, 0xb4c95e757db4b4eaULL, 0x549a19a8ce54544dULL, + 0x93ece53b7f939376ULL, 0x220daa442f222288ULL, 0x6407e9c86364648dULL, + 0xf1db12ff2af1f1e3ULL, 0x73bfa2e6cc7373d1ULL, 0x12905a2482121248ULL, + 0x403a5d807a40401dULL, 0x0840281048080820ULL, 0xc356e89b95c3c32bULL, + 0xec337bc5dfecec97ULL, 0xdb9690ab4ddbdb4bULL, 0xa1611f5fc0a1a1beULL, + 0x8d1c8307918d8d0eULL, 0x3df5c97ac83d3df4ULL, 0x97ccf1335b979766ULL, + 0x0000000000000000ULL, 0xcf36d483f9cfcf1bULL, 0x2b4587566e2b2bacULL, + 0x7697b3ece17676c5ULL, 0x8264b019e6828232ULL, 0xd6fea9b128d6d67fULL, + 0x1bd87736c31b1b6cULL, 0xb5c15b7774b5b5eeULL, 0xaf112943beafaf86ULL, + 0x6a77dfd41d6a6ab5ULL, 0x50ba0da0ea50505dULL, 0x45124c8a57454509ULL, + 0xf3cb18fb38f3f3ebULL, 0x309df060ad3030c0ULL, 0xef2b74c3c4efef9bULL, + 0x3fe5c37eda3f3ffcULL, 0x55921caac7555549ULL, 0xa2791059dba2a2b2ULL, + 0xea0365c9e9eaea8fULL, 0x650fecca6a656589ULL, 0xbab9686903babad2ULL, + 0x2f65935e4a2f2fbcULL, 0xc04ee79d8ec0c027ULL, 0xdebe81a160dede5fULL, + 0x1ce06c38fc1c1c70ULL, 0xfdbb2ee746fdfdd3ULL, 0x4d52649a1f4d4d29ULL, + 0x92e4e03976929272ULL, 0x758fbceafa7575c9ULL, 0x06301e0c36060618ULL, + 0x8a249809ae8a8a12ULL, 0xb2f940794bb2b2f2ULL, 0xe66359d185e6e6bfULL, + 0x0e70361c7e0e0e38ULL, 0x1ff8633ee71f1f7cULL, 0x6237f7c455626295ULL, + 0xd4eea3b53ad4d477ULL, 0xa829324d81a8a89aULL, 0x96c4f43152969662ULL, + 0xf99b3aef62f9f9c3ULL, 0xc566f697a3c5c533ULL, 0x2535b14a10252594ULL, + 0x59f220b2ab595979ULL, 0x8454ae15d084842aULL, 0x72b7a7e4c57272d5ULL, + 0x39d5dd72ec3939e4ULL, 0x4c5a6198164c4c2dULL, 0x5eca3bbc945e5e65ULL, + 0x78e785f09f7878fdULL, 0x38ddd870e53838e0ULL, 0x8c148605988c8c0aULL, + 0xd1c6b2bf17d1d163ULL, 0xa5410b57e4a5a5aeULL, 0xe2434dd9a1e2e2afULL, + 0x612ff8c24e616199ULL, 0xb3f1457b42b3b3f6ULL, 0x2115a54234212184ULL, + 0x9c94d625089c9c4aULL, 0x1ef0663cee1e1e78ULL, 0x4322528661434311ULL, + 0xc776fc93b1c7c73bULL, 0xfcb32be54ffcfcd7ULL, 0x0420140824040410ULL, + 0x51b208a2e3515159ULL, 0x99bcc72f2599995eULL, 0x6d4fc4da226d6da9ULL, + 0x0d68391a650d0d34ULL, 0xfa8335e979fafacfULL, 0xdfb684a369dfdf5bULL, + 0x7ed79bfca97e7ee5ULL, 0x243db44819242490ULL, 0x3bc5d776fe3b3becULL, + 0xab313d4b9aabab96ULL, 0xce3ed181f0cece1fULL, 0x1188552299111144ULL, + 0x8f0c8903838f8f06ULL, 0x4e4a6b9c044e4e25ULL, 0xb7d1517366b7b7e6ULL, + 0xeb0b60cbe0ebeb8bULL, 0x3cfdcc78c13c3cf0ULL, 0x817cbf1ffd81813eULL, + 0x94d4fe354094946aULL, 0xf7eb0cf31cf7f7fbULL, 0xb9a1676f18b9b9deULL, + 0x13985f268b13134cULL, 0x2c7d9c58512c2cb0ULL, 0xd3d6b8bb05d3d36bULL, + 0xe76b5cd38ce7e7bbULL, 0x6e57cbdc396e6ea5ULL, 0xc46ef395aac4c437ULL, + 0x03180f061b03030cULL, 0x568a13acdc565645ULL, 0x441a49885e44440dULL, + 0x7fdf9efea07f7fe1ULL, 0xa921374f88a9a99eULL, 0x2a4d8254672a2aa8ULL, + 0xbbb16d6b0abbbbd6ULL, 0xc146e29f87c1c123ULL, 0x53a202a6f1535351ULL, + 0xdcae8ba572dcdc57ULL, 0x0b582716530b0b2cULL, 0x9d9cd327019d9d4eULL, + 0x6c47c1d82b6c6cadULL, 0x3195f562a43131c4ULL, 0x7487b9e8f37474cdULL, + 0xf6e309f115f6f6ffULL, 0x460a438c4c464605ULL, 0xac092645a5acac8aULL, + 0x893c970fb589891eULL, 0x14a04428b4141450ULL, 0xe15b42dfbae1e1a3ULL, + 0x16b04e2ca6161658ULL, 0x3acdd274f73a3ae8ULL, 0x696fd0d2066969b9ULL, + 0x09482d1241090924ULL, 0x70a7ade0d77070ddULL, 0xb6d954716fb6b6e2ULL, + 0xd0ceb7bd1ed0d067ULL, 0xed3b7ec7d6eded93ULL, 0xcc2edb85e2cccc17ULL, + 0x422a578468424215ULL, 0x98b4c22d2c98985aULL, 0xa4490e55eda4a4aaULL, + 0x285d8850752828a0ULL, 0x5cda31b8865c5c6dULL, 0xf8933fed6bf8f8c7ULL, + 0x8644a411c2868622ULL, +}; + +static const u64 C6[256] = { + 0x6018c07830d81818ULL, 0x8c2305af46262323ULL, 0x3fc67ef991b8c6c6ULL, + 0x87e8136fcdfbe8e8ULL, 0x26874ca113cb8787ULL, 0xdab8a9626d11b8b8ULL, + 0x0401080502090101ULL, 0x214f426e9e0d4f4fULL, 0xd836adee6c9b3636ULL, + 0xa2a6590451ffa6a6ULL, 0x6fd2debdb90cd2d2ULL, 0xf3f5fb06f70ef5f5ULL, + 0xf979ef80f2967979ULL, 0xa16f5fcede306f6fULL, 0x7e91fcef3f6d9191ULL, + 0x5552aa07a4f85252ULL, 0x9d6027fdc0476060ULL, 0xcabc89766535bcbcULL, + 0x569baccd2b379b9bULL, 0x028e048c018a8e8eULL, 0xb6a371155bd2a3a3ULL, + 0x300c603c186c0c0cULL, 0xf17bff8af6847b7bULL, 0xd435b5e16a803535ULL, + 0x741de8693af51d1dULL, 0xa7e05347ddb3e0e0ULL, 0x7bd7f6acb321d7d7ULL, + 0x2fc25eed999cc2c2ULL, 0xb82e6d965c432e2eULL, 0x314b627a96294b4bULL, + 0xdffea321e15dfefeULL, 0x41578216aed55757ULL, 0x5415a8412abd1515ULL, + 0xc1779fb6eee87777ULL, 0xdc37a5eb6e923737ULL, 0xb3e57b56d79ee5e5ULL, + 0x469f8cd923139f9fULL, 0xe7f0d317fd23f0f0ULL, 0x354a6a7f94204a4aULL, + 0x4fda9e95a944dadaULL, 0x7d58fa25b0a25858ULL, 0x03c906ca8fcfc9c9ULL, + 0xa429558d527c2929ULL, 0x280a5022145a0a0aULL, 0xfeb1e14f7f50b1b1ULL, + 0xbaa0691a5dc9a0a0ULL, 0xb16b7fdad6146b6bULL, 0x2e855cab17d98585ULL, + 0xcebd8173673cbdbdULL, 0x695dd234ba8f5d5dULL, 0x4010805020901010ULL, + 0xf7f4f303f507f4f4ULL, 0x0bcb16c08bddcbcbULL, 0xf83eedc67cd33e3eULL, + 0x140528110a2d0505ULL, 0x81671fe6ce786767ULL, 0xb7e47353d597e4e4ULL, + 0x9c2725bb4e022727ULL, 0x1941325882734141ULL, 0x168b2c9d0ba78b8bULL, + 0xa6a7510153f6a7a7ULL, 0xe97dcf94fab27d7dULL, 0x6e95dcfb37499595ULL, + 0x47d88e9fad56d8d8ULL, 0xcbfb8b30eb70fbfbULL, 0x9fee2371c1cdeeeeULL, + 0xed7cc791f8bb7c7cULL, 0x856617e3cc716666ULL, 0x53dda68ea77bddddULL, + 0x5c17b84b2eaf1717ULL, 0x014702468e454747ULL, 0x429e84dc211a9e9eULL, + 0x0fca1ec589d4cacaULL, 0xb42d75995a582d2dULL, 0xc6bf9179632ebfbfULL, + 0x1c07381b0e3f0707ULL, 0x8ead012347acadadULL, 0x755aea2fb4b05a5aULL, + 0x36836cb51bef8383ULL, 0xcc3385ff66b63333ULL, 0x91633ff2c65c6363ULL, + 0x0802100a04120202ULL, 0x92aa39384993aaaaULL, 0xd971afa8e2de7171ULL, + 0x07c80ecf8dc6c8c8ULL, 0x6419c87d32d11919ULL, 0x39497270923b4949ULL, + 0x43d9869aaf5fd9d9ULL, 0xeff2c31df931f2f2ULL, 0xabe34b48dba8e3e3ULL, + 0x715be22ab6b95b5bULL, 0x1a8834920dbc8888ULL, 0x529aa4c8293e9a9aULL, + 0x98262dbe4c0b2626ULL, 0xc8328dfa64bf3232ULL, 0xfab0e94a7d59b0b0ULL, + 0x83e91b6acff2e9e9ULL, 0x3c0f78331e770f0fULL, 0x73d5e6a6b733d5d5ULL, + 0x3a8074ba1df48080ULL, 0xc2be997c6127bebeULL, 0x13cd26de87ebcdcdULL, + 0xd034bde468893434ULL, 0x3d487a7590324848ULL, 0xdbffab24e354ffffULL, + 0xf57af78ff48d7a7aULL, 0x7a90f4ea3d649090ULL, 0x615fc23ebe9d5f5fULL, + 0x80201da0403d2020ULL, 0xbd6867d5d00f6868ULL, 0x681ad07234ca1a1aULL, + 0x82ae192c41b7aeaeULL, 0xeab4c95e757db4b4ULL, 0x4d549a19a8ce5454ULL, + 0x7693ece53b7f9393ULL, 0x88220daa442f2222ULL, 0x8d6407e9c8636464ULL, + 0xe3f1db12ff2af1f1ULL, 0xd173bfa2e6cc7373ULL, 0x4812905a24821212ULL, + 0x1d403a5d807a4040ULL, 0x2008402810480808ULL, 0x2bc356e89b95c3c3ULL, + 0x97ec337bc5dfececULL, 0x4bdb9690ab4ddbdbULL, 0xbea1611f5fc0a1a1ULL, + 0x0e8d1c8307918d8dULL, 0xf43df5c97ac83d3dULL, 0x6697ccf1335b9797ULL, + 0x0000000000000000ULL, 0x1bcf36d483f9cfcfULL, 0xac2b4587566e2b2bULL, + 0xc57697b3ece17676ULL, 0x328264b019e68282ULL, 0x7fd6fea9b128d6d6ULL, + 0x6c1bd87736c31b1bULL, 0xeeb5c15b7774b5b5ULL, 0x86af112943beafafULL, + 0xb56a77dfd41d6a6aULL, 0x5d50ba0da0ea5050ULL, 0x0945124c8a574545ULL, + 0xebf3cb18fb38f3f3ULL, 0xc0309df060ad3030ULL, 0x9bef2b74c3c4efefULL, + 0xfc3fe5c37eda3f3fULL, 0x4955921caac75555ULL, 0xb2a2791059dba2a2ULL, + 0x8fea0365c9e9eaeaULL, 0x89650fecca6a6565ULL, 0xd2bab9686903babaULL, + 0xbc2f65935e4a2f2fULL, 0x27c04ee79d8ec0c0ULL, 0x5fdebe81a160dedeULL, + 0x701ce06c38fc1c1cULL, 0xd3fdbb2ee746fdfdULL, 0x294d52649a1f4d4dULL, + 0x7292e4e039769292ULL, 0xc9758fbceafa7575ULL, 0x1806301e0c360606ULL, + 0x128a249809ae8a8aULL, 0xf2b2f940794bb2b2ULL, 0xbfe66359d185e6e6ULL, + 0x380e70361c7e0e0eULL, 0x7c1ff8633ee71f1fULL, 0x956237f7c4556262ULL, + 0x77d4eea3b53ad4d4ULL, 0x9aa829324d81a8a8ULL, 0x6296c4f431529696ULL, + 0xc3f99b3aef62f9f9ULL, 0x33c566f697a3c5c5ULL, 0x942535b14a102525ULL, + 0x7959f220b2ab5959ULL, 0x2a8454ae15d08484ULL, 0xd572b7a7e4c57272ULL, + 0xe439d5dd72ec3939ULL, 0x2d4c5a6198164c4cULL, 0x655eca3bbc945e5eULL, + 0xfd78e785f09f7878ULL, 0xe038ddd870e53838ULL, 0x0a8c148605988c8cULL, + 0x63d1c6b2bf17d1d1ULL, 0xaea5410b57e4a5a5ULL, 0xafe2434dd9a1e2e2ULL, + 0x99612ff8c24e6161ULL, 0xf6b3f1457b42b3b3ULL, 0x842115a542342121ULL, + 0x4a9c94d625089c9cULL, 0x781ef0663cee1e1eULL, 0x1143225286614343ULL, + 0x3bc776fc93b1c7c7ULL, 0xd7fcb32be54ffcfcULL, 0x1004201408240404ULL, + 0x5951b208a2e35151ULL, 0x5e99bcc72f259999ULL, 0xa96d4fc4da226d6dULL, + 0x340d68391a650d0dULL, 0xcffa8335e979fafaULL, 0x5bdfb684a369dfdfULL, + 0xe57ed79bfca97e7eULL, 0x90243db448192424ULL, 0xec3bc5d776fe3b3bULL, + 0x96ab313d4b9aababULL, 0x1fce3ed181f0ceceULL, 0x4411885522991111ULL, + 0x068f0c8903838f8fULL, 0x254e4a6b9c044e4eULL, 0xe6b7d1517366b7b7ULL, + 0x8beb0b60cbe0ebebULL, 0xf03cfdcc78c13c3cULL, 0x3e817cbf1ffd8181ULL, + 0x6a94d4fe35409494ULL, 0xfbf7eb0cf31cf7f7ULL, 0xdeb9a1676f18b9b9ULL, + 0x4c13985f268b1313ULL, 0xb02c7d9c58512c2cULL, 0x6bd3d6b8bb05d3d3ULL, + 0xbbe76b5cd38ce7e7ULL, 0xa56e57cbdc396e6eULL, 0x37c46ef395aac4c4ULL, + 0x0c03180f061b0303ULL, 0x45568a13acdc5656ULL, 0x0d441a49885e4444ULL, + 0xe17fdf9efea07f7fULL, 0x9ea921374f88a9a9ULL, 0xa82a4d8254672a2aULL, + 0xd6bbb16d6b0abbbbULL, 0x23c146e29f87c1c1ULL, 0x5153a202a6f15353ULL, + 0x57dcae8ba572dcdcULL, 0x2c0b582716530b0bULL, 0x4e9d9cd327019d9dULL, + 0xad6c47c1d82b6c6cULL, 0xc43195f562a43131ULL, 0xcd7487b9e8f37474ULL, + 0xfff6e309f115f6f6ULL, 0x05460a438c4c4646ULL, 0x8aac092645a5acacULL, + 0x1e893c970fb58989ULL, 0x5014a04428b41414ULL, 0xa3e15b42dfbae1e1ULL, + 0x5816b04e2ca61616ULL, 0xe83acdd274f73a3aULL, 0xb9696fd0d2066969ULL, + 0x2409482d12410909ULL, 0xdd70a7ade0d77070ULL, 0xe2b6d954716fb6b6ULL, + 0x67d0ceb7bd1ed0d0ULL, 0x93ed3b7ec7d6ededULL, 0x17cc2edb85e2ccccULL, + 0x15422a5784684242ULL, 0x5a98b4c22d2c9898ULL, 0xaaa4490e55eda4a4ULL, + 0xa0285d8850752828ULL, 0x6d5cda31b8865c5cULL, 0xc7f8933fed6bf8f8ULL, + 0x228644a411c28686ULL, +}; + +static const u64 C7[256] = { + 0x186018c07830d818ULL, 0x238c2305af462623ULL, 0xc63fc67ef991b8c6ULL, + 0xe887e8136fcdfbe8ULL, 0x8726874ca113cb87ULL, 0xb8dab8a9626d11b8ULL, + 0x0104010805020901ULL, 0x4f214f426e9e0d4fULL, 0x36d836adee6c9b36ULL, + 0xa6a2a6590451ffa6ULL, 0xd26fd2debdb90cd2ULL, 0xf5f3f5fb06f70ef5ULL, + 0x79f979ef80f29679ULL, 0x6fa16f5fcede306fULL, 0x917e91fcef3f6d91ULL, + 0x525552aa07a4f852ULL, 0x609d6027fdc04760ULL, 0xbccabc89766535bcULL, + 0x9b569baccd2b379bULL, 0x8e028e048c018a8eULL, 0xa3b6a371155bd2a3ULL, + 0x0c300c603c186c0cULL, 0x7bf17bff8af6847bULL, 0x35d435b5e16a8035ULL, + 0x1d741de8693af51dULL, 0xe0a7e05347ddb3e0ULL, 0xd77bd7f6acb321d7ULL, + 0xc22fc25eed999cc2ULL, 0x2eb82e6d965c432eULL, 0x4b314b627a96294bULL, + 0xfedffea321e15dfeULL, 0x5741578216aed557ULL, 0x155415a8412abd15ULL, + 0x77c1779fb6eee877ULL, 0x37dc37a5eb6e9237ULL, 0xe5b3e57b56d79ee5ULL, + 0x9f469f8cd923139fULL, 0xf0e7f0d317fd23f0ULL, 0x4a354a6a7f94204aULL, + 0xda4fda9e95a944daULL, 0x587d58fa25b0a258ULL, 0xc903c906ca8fcfc9ULL, + 0x29a429558d527c29ULL, 0x0a280a5022145a0aULL, 0xb1feb1e14f7f50b1ULL, + 0xa0baa0691a5dc9a0ULL, 0x6bb16b7fdad6146bULL, 0x852e855cab17d985ULL, + 0xbdcebd8173673cbdULL, 0x5d695dd234ba8f5dULL, 0x1040108050209010ULL, + 0xf4f7f4f303f507f4ULL, 0xcb0bcb16c08bddcbULL, 0x3ef83eedc67cd33eULL, + 0x05140528110a2d05ULL, 0x6781671fe6ce7867ULL, 0xe4b7e47353d597e4ULL, + 0x279c2725bb4e0227ULL, 0x4119413258827341ULL, 0x8b168b2c9d0ba78bULL, + 0xa7a6a7510153f6a7ULL, 0x7de97dcf94fab27dULL, 0x956e95dcfb374995ULL, + 0xd847d88e9fad56d8ULL, 0xfbcbfb8b30eb70fbULL, 0xee9fee2371c1cdeeULL, + 0x7ced7cc791f8bb7cULL, 0x66856617e3cc7166ULL, 0xdd53dda68ea77bddULL, + 0x175c17b84b2eaf17ULL, 0x47014702468e4547ULL, 0x9e429e84dc211a9eULL, + 0xca0fca1ec589d4caULL, 0x2db42d75995a582dULL, 0xbfc6bf9179632ebfULL, + 0x071c07381b0e3f07ULL, 0xad8ead012347acadULL, 0x5a755aea2fb4b05aULL, + 0x8336836cb51bef83ULL, 0x33cc3385ff66b633ULL, 0x6391633ff2c65c63ULL, + 0x020802100a041202ULL, 0xaa92aa39384993aaULL, 0x71d971afa8e2de71ULL, + 0xc807c80ecf8dc6c8ULL, 0x196419c87d32d119ULL, 0x4939497270923b49ULL, + 0xd943d9869aaf5fd9ULL, 0xf2eff2c31df931f2ULL, 0xe3abe34b48dba8e3ULL, + 0x5b715be22ab6b95bULL, 0x881a8834920dbc88ULL, 0x9a529aa4c8293e9aULL, + 0x2698262dbe4c0b26ULL, 0x32c8328dfa64bf32ULL, 0xb0fab0e94a7d59b0ULL, + 0xe983e91b6acff2e9ULL, 0x0f3c0f78331e770fULL, 0xd573d5e6a6b733d5ULL, + 0x803a8074ba1df480ULL, 0xbec2be997c6127beULL, 0xcd13cd26de87ebcdULL, + 0x34d034bde4688934ULL, 0x483d487a75903248ULL, 0xffdbffab24e354ffULL, + 0x7af57af78ff48d7aULL, 0x907a90f4ea3d6490ULL, 0x5f615fc23ebe9d5fULL, + 0x2080201da0403d20ULL, 0x68bd6867d5d00f68ULL, 0x1a681ad07234ca1aULL, + 0xae82ae192c41b7aeULL, 0xb4eab4c95e757db4ULL, 0x544d549a19a8ce54ULL, + 0x937693ece53b7f93ULL, 0x2288220daa442f22ULL, 0x648d6407e9c86364ULL, + 0xf1e3f1db12ff2af1ULL, 0x73d173bfa2e6cc73ULL, 0x124812905a248212ULL, + 0x401d403a5d807a40ULL, 0x0820084028104808ULL, 0xc32bc356e89b95c3ULL, + 0xec97ec337bc5dfecULL, 0xdb4bdb9690ab4ddbULL, 0xa1bea1611f5fc0a1ULL, + 0x8d0e8d1c8307918dULL, 0x3df43df5c97ac83dULL, 0x976697ccf1335b97ULL, + 0x0000000000000000ULL, 0xcf1bcf36d483f9cfULL, 0x2bac2b4587566e2bULL, + 0x76c57697b3ece176ULL, 0x82328264b019e682ULL, 0xd67fd6fea9b128d6ULL, + 0x1b6c1bd87736c31bULL, 0xb5eeb5c15b7774b5ULL, 0xaf86af112943beafULL, + 0x6ab56a77dfd41d6aULL, 0x505d50ba0da0ea50ULL, 0x450945124c8a5745ULL, + 0xf3ebf3cb18fb38f3ULL, 0x30c0309df060ad30ULL, 0xef9bef2b74c3c4efULL, + 0x3ffc3fe5c37eda3fULL, 0x554955921caac755ULL, 0xa2b2a2791059dba2ULL, + 0xea8fea0365c9e9eaULL, 0x6589650fecca6a65ULL, 0xbad2bab9686903baULL, + 0x2fbc2f65935e4a2fULL, 0xc027c04ee79d8ec0ULL, 0xde5fdebe81a160deULL, + 0x1c701ce06c38fc1cULL, 0xfdd3fdbb2ee746fdULL, 0x4d294d52649a1f4dULL, + 0x927292e4e0397692ULL, 0x75c9758fbceafa75ULL, 0x061806301e0c3606ULL, + 0x8a128a249809ae8aULL, 0xb2f2b2f940794bb2ULL, 0xe6bfe66359d185e6ULL, + 0x0e380e70361c7e0eULL, 0x1f7c1ff8633ee71fULL, 0x62956237f7c45562ULL, + 0xd477d4eea3b53ad4ULL, 0xa89aa829324d81a8ULL, 0x966296c4f4315296ULL, + 0xf9c3f99b3aef62f9ULL, 0xc533c566f697a3c5ULL, 0x25942535b14a1025ULL, + 0x597959f220b2ab59ULL, 0x842a8454ae15d084ULL, 0x72d572b7a7e4c572ULL, + 0x39e439d5dd72ec39ULL, 0x4c2d4c5a6198164cULL, 0x5e655eca3bbc945eULL, + 0x78fd78e785f09f78ULL, 0x38e038ddd870e538ULL, 0x8c0a8c148605988cULL, + 0xd163d1c6b2bf17d1ULL, 0xa5aea5410b57e4a5ULL, 0xe2afe2434dd9a1e2ULL, + 0x6199612ff8c24e61ULL, 0xb3f6b3f1457b42b3ULL, 0x21842115a5423421ULL, + 0x9c4a9c94d625089cULL, 0x1e781ef0663cee1eULL, 0x4311432252866143ULL, + 0xc73bc776fc93b1c7ULL, 0xfcd7fcb32be54ffcULL, 0x0410042014082404ULL, + 0x515951b208a2e351ULL, 0x995e99bcc72f2599ULL, 0x6da96d4fc4da226dULL, + 0x0d340d68391a650dULL, 0xfacffa8335e979faULL, 0xdf5bdfb684a369dfULL, + 0x7ee57ed79bfca97eULL, 0x2490243db4481924ULL, 0x3bec3bc5d776fe3bULL, + 0xab96ab313d4b9aabULL, 0xce1fce3ed181f0ceULL, 0x1144118855229911ULL, + 0x8f068f0c8903838fULL, 0x4e254e4a6b9c044eULL, 0xb7e6b7d1517366b7ULL, + 0xeb8beb0b60cbe0ebULL, 0x3cf03cfdcc78c13cULL, 0x813e817cbf1ffd81ULL, + 0x946a94d4fe354094ULL, 0xf7fbf7eb0cf31cf7ULL, 0xb9deb9a1676f18b9ULL, + 0x134c13985f268b13ULL, 0x2cb02c7d9c58512cULL, 0xd36bd3d6b8bb05d3ULL, + 0xe7bbe76b5cd38ce7ULL, 0x6ea56e57cbdc396eULL, 0xc437c46ef395aac4ULL, + 0x030c03180f061b03ULL, 0x5645568a13acdc56ULL, 0x440d441a49885e44ULL, + 0x7fe17fdf9efea07fULL, 0xa99ea921374f88a9ULL, 0x2aa82a4d8254672aULL, + 0xbbd6bbb16d6b0abbULL, 0xc123c146e29f87c1ULL, 0x535153a202a6f153ULL, + 0xdc57dcae8ba572dcULL, 0x0b2c0b582716530bULL, 0x9d4e9d9cd327019dULL, + 0x6cad6c47c1d82b6cULL, 0x31c43195f562a431ULL, 0x74cd7487b9e8f374ULL, + 0xf6fff6e309f115f6ULL, 0x4605460a438c4c46ULL, 0xac8aac092645a5acULL, + 0x891e893c970fb589ULL, 0x145014a04428b414ULL, 0xe1a3e15b42dfbae1ULL, + 0x165816b04e2ca616ULL, 0x3ae83acdd274f73aULL, 0x69b9696fd0d20669ULL, + 0x092409482d124109ULL, 0x70dd70a7ade0d770ULL, 0xb6e2b6d954716fb6ULL, + 0xd067d0ceb7bd1ed0ULL, 0xed93ed3b7ec7d6edULL, 0xcc17cc2edb85e2ccULL, + 0x4215422a57846842ULL, 0x985a98b4c22d2c98ULL, 0xa4aaa4490e55eda4ULL, + 0x28a0285d88507528ULL, 0x5c6d5cda31b8865cULL, 0xf8c7f8933fed6bf8ULL, + 0x86228644a411c286ULL, +}; + +static const u64 rc[WHIRLPOOL_ROUNDS + 1] = { + 0x0000000000000000ULL, 0x1823c6e887b8014fULL, 0x36a6d2f5796f9152ULL, + 0x60bc9b8ea30c7b35ULL, 0x1de0d7c22e4bfe57ULL, 0x157737e59ff04adaULL, + 0x58c9290ab1a06b85ULL, 0xbd5d10f4cb3e0567ULL, 0xe427418ba77d95d8ULL, + 0xfbee7c66dd17479eULL, 0xca2dbf07ad5a8333ULL, +}; + +/** + * The core Whirlpool transform. + */ + +static void whirlpool_process_buffer(struct whirlpool_ctx *wctx) { + int i, r; + u64 K[8]; /* the round key */ + u64 block[8]; /* mu(buffer) */ + u64 state[8]; /* the cipher state */ + u64 L[8]; + u8 *buffer = wctx->buffer; + + for (i = 0; i < 8; i++, buffer += 8) { + block[i] = + (((u64)buffer[0] ) << 56) ^ + (((u64)buffer[1] & 0xffL) << 48) ^ + (((u64)buffer[2] & 0xffL) << 40) ^ + (((u64)buffer[3] & 0xffL) << 32) ^ + (((u64)buffer[4] & 0xffL) << 24) ^ + (((u64)buffer[5] & 0xffL) << 16) ^ + (((u64)buffer[6] & 0xffL) << 8) ^ + (((u64)buffer[7] & 0xffL) ); + } + + state[0] = block[0] ^ (K[0] = wctx->hash[0]); + state[1] = block[1] ^ (K[1] = wctx->hash[1]); + state[2] = block[2] ^ (K[2] = wctx->hash[2]); + state[3] = block[3] ^ (K[3] = wctx->hash[3]); + state[4] = block[4] ^ (K[4] = wctx->hash[4]); + state[5] = block[5] ^ (K[5] = wctx->hash[5]); + state[6] = block[6] ^ (K[6] = wctx->hash[6]); + state[7] = block[7] ^ (K[7] = wctx->hash[7]); + + for (r = 1; r <= WHIRLPOOL_ROUNDS; r++) { + + L[0] = C0[(int)(K[0] >> 56) ] ^ + C1[(int)(K[7] >> 48) & 0xff] ^ + C2[(int)(K[6] >> 40) & 0xff] ^ + C3[(int)(K[5] >> 32) & 0xff] ^ + C4[(int)(K[4] >> 24) & 0xff] ^ + C5[(int)(K[3] >> 16) & 0xff] ^ + C6[(int)(K[2] >> 8) & 0xff] ^ + C7[(int)(K[1] ) & 0xff] ^ + rc[r]; + + L[1] = C0[(int)(K[1] >> 56) ] ^ + C1[(int)(K[0] >> 48) & 0xff] ^ + C2[(int)(K[7] >> 40) & 0xff] ^ + C3[(int)(K[6] >> 32) & 0xff] ^ + C4[(int)(K[5] >> 24) & 0xff] ^ + C5[(int)(K[4] >> 16) & 0xff] ^ + C6[(int)(K[3] >> 8) & 0xff] ^ + C7[(int)(K[2] ) & 0xff]; + + L[2] = C0[(int)(K[2] >> 56) ] ^ + C1[(int)(K[1] >> 48) & 0xff] ^ + C2[(int)(K[0] >> 40) & 0xff] ^ + C3[(int)(K[7] >> 32) & 0xff] ^ + C4[(int)(K[6] >> 24) & 0xff] ^ + C5[(int)(K[5] >> 16) & 0xff] ^ + C6[(int)(K[4] >> 8) & 0xff] ^ + C7[(int)(K[3] ) & 0xff]; + + L[3] = C0[(int)(K[3] >> 56) ] ^ + C1[(int)(K[2] >> 48) & 0xff] ^ + C2[(int)(K[1] >> 40) & 0xff] ^ + C3[(int)(K[0] >> 32) & 0xff] ^ + C4[(int)(K[7] >> 24) & 0xff] ^ + C5[(int)(K[6] >> 16) & 0xff] ^ + C6[(int)(K[5] >> 8) & 0xff] ^ + C7[(int)(K[4] ) & 0xff]; + + L[4] = C0[(int)(K[4] >> 56) ] ^ + C1[(int)(K[3] >> 48) & 0xff] ^ + C2[(int)(K[2] >> 40) & 0xff] ^ + C3[(int)(K[1] >> 32) & 0xff] ^ + C4[(int)(K[0] >> 24) & 0xff] ^ + C5[(int)(K[7] >> 16) & 0xff] ^ + C6[(int)(K[6] >> 8) & 0xff] ^ + C7[(int)(K[5] ) & 0xff]; + + L[5] = C0[(int)(K[5] >> 56) ] ^ + C1[(int)(K[4] >> 48) & 0xff] ^ + C2[(int)(K[3] >> 40) & 0xff] ^ + C3[(int)(K[2] >> 32) & 0xff] ^ + C4[(int)(K[1] >> 24) & 0xff] ^ + C5[(int)(K[0] >> 16) & 0xff] ^ + C6[(int)(K[7] >> 8) & 0xff] ^ + C7[(int)(K[6] ) & 0xff]; + + L[6] = C0[(int)(K[6] >> 56) ] ^ + C1[(int)(K[5] >> 48) & 0xff] ^ + C2[(int)(K[4] >> 40) & 0xff] ^ + C3[(int)(K[3] >> 32) & 0xff] ^ + C4[(int)(K[2] >> 24) & 0xff] ^ + C5[(int)(K[1] >> 16) & 0xff] ^ + C6[(int)(K[0] >> 8) & 0xff] ^ + C7[(int)(K[7] ) & 0xff]; + + L[7] = C0[(int)(K[7] >> 56) ] ^ + C1[(int)(K[6] >> 48) & 0xff] ^ + C2[(int)(K[5] >> 40) & 0xff] ^ + C3[(int)(K[4] >> 32) & 0xff] ^ + C4[(int)(K[3] >> 24) & 0xff] ^ + C5[(int)(K[2] >> 16) & 0xff] ^ + C6[(int)(K[1] >> 8) & 0xff] ^ + C7[(int)(K[0] ) & 0xff]; + + K[0] = L[0]; + K[1] = L[1]; + K[2] = L[2]; + K[3] = L[3]; + K[4] = L[4]; + K[5] = L[5]; + K[6] = L[6]; + K[7] = L[7]; + + L[0] = C0[(int)(state[0] >> 56) ] ^ + C1[(int)(state[7] >> 48) & 0xff] ^ + C2[(int)(state[6] >> 40) & 0xff] ^ + C3[(int)(state[5] >> 32) & 0xff] ^ + C4[(int)(state[4] >> 24) & 0xff] ^ + C5[(int)(state[3] >> 16) & 0xff] ^ + C6[(int)(state[2] >> 8) & 0xff] ^ + C7[(int)(state[1] ) & 0xff] ^ + K[0]; + + L[1] = C0[(int)(state[1] >> 56) ] ^ + C1[(int)(state[0] >> 48) & 0xff] ^ + C2[(int)(state[7] >> 40) & 0xff] ^ + C3[(int)(state[6] >> 32) & 0xff] ^ + C4[(int)(state[5] >> 24) & 0xff] ^ + C5[(int)(state[4] >> 16) & 0xff] ^ + C6[(int)(state[3] >> 8) & 0xff] ^ + C7[(int)(state[2] ) & 0xff] ^ + K[1]; + + L[2] = C0[(int)(state[2] >> 56) ] ^ + C1[(int)(state[1] >> 48) & 0xff] ^ + C2[(int)(state[0] >> 40) & 0xff] ^ + C3[(int)(state[7] >> 32) & 0xff] ^ + C4[(int)(state[6] >> 24) & 0xff] ^ + C5[(int)(state[5] >> 16) & 0xff] ^ + C6[(int)(state[4] >> 8) & 0xff] ^ + C7[(int)(state[3] ) & 0xff] ^ + K[2]; + + L[3] = C0[(int)(state[3] >> 56) ] ^ + C1[(int)(state[2] >> 48) & 0xff] ^ + C2[(int)(state[1] >> 40) & 0xff] ^ + C3[(int)(state[0] >> 32) & 0xff] ^ + C4[(int)(state[7] >> 24) & 0xff] ^ + C5[(int)(state[6] >> 16) & 0xff] ^ + C6[(int)(state[5] >> 8) & 0xff] ^ + C7[(int)(state[4] ) & 0xff] ^ + K[3]; + + L[4] = C0[(int)(state[4] >> 56) ] ^ + C1[(int)(state[3] >> 48) & 0xff] ^ + C2[(int)(state[2] >> 40) & 0xff] ^ + C3[(int)(state[1] >> 32) & 0xff] ^ + C4[(int)(state[0] >> 24) & 0xff] ^ + C5[(int)(state[7] >> 16) & 0xff] ^ + C6[(int)(state[6] >> 8) & 0xff] ^ + C7[(int)(state[5] ) & 0xff] ^ + K[4]; + + L[5] = C0[(int)(state[5] >> 56) ] ^ + C1[(int)(state[4] >> 48) & 0xff] ^ + C2[(int)(state[3] >> 40) & 0xff] ^ + C3[(int)(state[2] >> 32) & 0xff] ^ + C4[(int)(state[1] >> 24) & 0xff] ^ + C5[(int)(state[0] >> 16) & 0xff] ^ + C6[(int)(state[7] >> 8) & 0xff] ^ + C7[(int)(state[6] ) & 0xff] ^ + K[5]; + + L[6] = C0[(int)(state[6] >> 56) ] ^ + C1[(int)(state[5] >> 48) & 0xff] ^ + C2[(int)(state[4] >> 40) & 0xff] ^ + C3[(int)(state[3] >> 32) & 0xff] ^ + C4[(int)(state[2] >> 24) & 0xff] ^ + C5[(int)(state[1] >> 16) & 0xff] ^ + C6[(int)(state[0] >> 8) & 0xff] ^ + C7[(int)(state[7] ) & 0xff] ^ + K[6]; + + L[7] = C0[(int)(state[7] >> 56) ] ^ + C1[(int)(state[6] >> 48) & 0xff] ^ + C2[(int)(state[5] >> 40) & 0xff] ^ + C3[(int)(state[4] >> 32) & 0xff] ^ + C4[(int)(state[3] >> 24) & 0xff] ^ + C5[(int)(state[2] >> 16) & 0xff] ^ + C6[(int)(state[1] >> 8) & 0xff] ^ + C7[(int)(state[0] ) & 0xff] ^ + K[7]; + + state[0] = L[0]; + state[1] = L[1]; + state[2] = L[2]; + state[3] = L[3]; + state[4] = L[4]; + state[5] = L[5]; + state[6] = L[6]; + state[7] = L[7]; + } + /* + * apply the Miyaguchi-Preneel compression function: + */ + wctx->hash[0] ^= state[0] ^ block[0]; + wctx->hash[1] ^= state[1] ^ block[1]; + wctx->hash[2] ^= state[2] ^ block[2]; + wctx->hash[3] ^= state[3] ^ block[3]; + wctx->hash[4] ^= state[4] ^ block[4]; + wctx->hash[5] ^= state[5] ^ block[5]; + wctx->hash[6] ^= state[6] ^ block[6]; + wctx->hash[7] ^= state[7] ^ block[7]; + +} + +static void whirlpool_init (void *ctx) { + int i; + struct whirlpool_ctx *wctx = ctx; + + memset(wctx->bitLength, 0, 32); + wctx->bufferBits = wctx->bufferPos = 0; + wctx->buffer[0] = 0; + for (i = 0; i < 8; i++) { + wctx->hash[i] = 0L; + } +} + +static void whirlpool_update(void *ctx, const u8 *source, unsigned int len) +{ + + struct whirlpool_ctx *wctx = ctx; + int sourcePos = 0; + unsigned int bits_len = len * 8; // convert to number of bits + int sourceGap = (8 - ((int)bits_len & 7)) & 7; + int bufferRem = wctx->bufferBits & 7; + int i; + u32 b, carry; + u8 *buffer = wctx->buffer; + u8 *bitLength = wctx->bitLength; + int bufferBits = wctx->bufferBits; + int bufferPos = wctx->bufferPos; + + u64 value = bits_len; + for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != 0ULL); i--) { + carry += bitLength[i] + ((u32)value & 0xff); + bitLength[i] = (u8)carry; + carry >>= 8; + value >>= 8; + } + while (bits_len > 8) { + b = ((source[sourcePos] << sourceGap) & 0xff) | + ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap)); + buffer[bufferPos++] |= (u8)(b >> bufferRem); + bufferBits += 8 - bufferRem; + if (bufferBits == WHIRLPOOL_DIGEST_SIZE * 8) { + whirlpool_process_buffer(wctx); + bufferBits = bufferPos = 0; + } + buffer[bufferPos] = b << (8 - bufferRem); + bufferBits += bufferRem; + bits_len -= 8; + sourcePos++; + } + if (bits_len > 0) { + b = (source[sourcePos] << sourceGap) & 0xff; + buffer[bufferPos] |= b >> bufferRem; + } else { + b = 0; + } + if (bufferRem + bits_len < 8) { + bufferBits += bits_len; + } else { + bufferPos++; + bufferBits += 8 - bufferRem; + bits_len -= 8 - bufferRem; + if (bufferBits == WHIRLPOOL_DIGEST_SIZE * 8) { + whirlpool_process_buffer(wctx); + bufferBits = bufferPos = 0; + } + buffer[bufferPos] = b << (8 - bufferRem); + bufferBits += (int)bits_len; + } + + wctx->bufferBits = bufferBits; + wctx->bufferPos = bufferPos; + +} + +static void whirlpool_final(void *ctx, u8 *out) +{ + struct whirlpool_ctx *wctx = ctx; + int i; + u8 *buffer = wctx->buffer; + u8 *bitLength = wctx->bitLength; + int bufferBits = wctx->bufferBits; + int bufferPos = wctx->bufferPos; + u8 *digest = out; + + buffer[bufferPos] |= 0x80U >> (bufferBits & 7); + bufferPos++; + if (bufferPos > WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) { + if (bufferPos < WHIRLPOOL_BLOCK_SIZE) { + memset(&buffer[bufferPos], 0, WHIRLPOOL_BLOCK_SIZE - bufferPos); + } + whirlpool_process_buffer(wctx); + bufferPos = 0; + } + if (bufferPos < WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) { + memset(&buffer[bufferPos], 0, + (WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) - bufferPos); + } + bufferPos = WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES; + memcpy(&buffer[WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES], + bitLength, WHIRLPOOL_LENGTHBYTES); + whirlpool_process_buffer(wctx); + for (i = 0; i < WHIRLPOOL_DIGEST_SIZE/8; i++) { + digest[0] = (u8)(wctx->hash[i] >> 56); + digest[1] = (u8)(wctx->hash[i] >> 48); + digest[2] = (u8)(wctx->hash[i] >> 40); + digest[3] = (u8)(wctx->hash[i] >> 32); + digest[4] = (u8)(wctx->hash[i] >> 24); + digest[5] = (u8)(wctx->hash[i] >> 16); + digest[6] = (u8)(wctx->hash[i] >> 8); + digest[7] = (u8)(wctx->hash[i] ); + digest += 8; + } + wctx->bufferBits = bufferBits; + wctx->bufferPos = bufferPos; +} + +static struct crypto_alg alg = { + .cra_name = "whirlpool", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = WHIRLPOOL_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct whirlpool_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = WHIRLPOOL_DIGEST_SIZE, + .dia_init = whirlpool_init, + .dia_update = whirlpool_update, + .dia_final = whirlpool_final } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Whirlpool Message Digest Algorithm"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/atm/eni.c linux-2.4.28-pre3/drivers/atm/eni.c --- linux-2.4.27/drivers/atm/eni.c 2003-11-28 18:26:19.000000000 +0000 +++ linux-2.4.28-pre3/drivers/atm/eni.c 2004-09-10 19:33:15.000000000 +0000 @@ -1879,7 +1879,7 @@ static void eni_close(struct atm_vcc *vc DPRINTK("eni_close: done waiting\n"); /* deallocate memory */ kfree(ENI_VCC(vcc)); - ENI_VCC(vcc) = NULL; + vcc->dev_data = NULL; clear_bit(ATM_VF_ADDR,&vcc->flags); /*foo();*/ } @@ -1951,7 +1951,7 @@ static int eni_open(struct atm_vcc *vcc, DPRINTK(">eni_open\n"); EVENT("eni_open\n",0,0); - if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) ENI_VCC(vcc) = NULL; + if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) vcc->dev_data = NULL; eni_dev = ENI_DEV(vcc->dev); error = get_ci(vcc,&vpi,&vci); if (error) return error; @@ -1966,7 +1966,7 @@ static int eni_open(struct atm_vcc *vcc, if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) { eni_vcc = kmalloc(sizeof(struct eni_vcc),GFP_KERNEL); if (!eni_vcc) return -ENOMEM; - ENI_VCC(vcc) = eni_vcc; + vcc->dev_data = eni_vcc; eni_vcc->tx = NULL; /* for eni_close after open_rx */ if ((error = open_rx_first(vcc))) { eni_close(vcc); @@ -2302,7 +2302,7 @@ static int __devinit eni_init_one(struct if (!dev) goto out2; pci_set_drvdata(pci_dev, dev); eni_dev->pci_dev = pci_dev; - ENI_DEV(dev) = eni_dev; + dev->dev_data = eni_dev; eni_dev->asic = ent->driver_data; error = eni_do_init(dev); if (error) goto out3; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/atm/fore200e.c linux-2.4.28-pre3/drivers/atm/fore200e.c --- linux-2.4.27/drivers/atm/fore200e.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/atm/fore200e.c 2004-09-10 19:37:16.000000000 +0000 @@ -101,6 +101,7 @@ #if 1 +#undef ASSERT #define ASSERT(expr) if (!(expr)) { \ printk(FORE200E "assertion failed! %s[%d]: %s\n", \ __FUNCTION__, __LINE__, #expr); \ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/atm/suni.c linux-2.4.28-pre3/drivers/atm/suni.c --- linux-2.4.27/drivers/atm/suni.c 2003-06-13 14:51:32.000000000 +0000 +++ linux-2.4.28-pre3/drivers/atm/suni.c 2004-09-10 19:36:25.000000000 +0000 @@ -230,7 +230,7 @@ static int suni_start(struct atm_dev *de unsigned long flags; int first; - if (!(PRIV(dev) = kmalloc(sizeof(struct suni_priv),GFP_KERNEL))) + if (!(dev->phy_data = kmalloc(sizeof(struct suni_priv),GFP_KERNEL))) return -ENOMEM; PRIV(dev)->dev = dev; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/block/cciss.c linux-2.4.28-pre3/drivers/block/cciss.c --- linux-2.4.27/drivers/block/cciss.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/block/cciss.c 2004-09-10 19:37:07.000000000 +0000 @@ -80,7 +80,7 @@ const struct pci_device_id cciss_pci_dev 0x0E11, 0x4091, 0, 0, 0}, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409E, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISS, 0x103C, 0x3211, 0, 0, 0}, {0,} }; @@ -125,7 +125,7 @@ static struct board_type products[] = { /* Originally cciss driver only supports 8 major number */ #define MAX_CTLR_ORIG COMPAQ_CISS_MAJOR7 - COMPAQ_CISS_MAJOR + 1 -#define CCISS_DMA_MASK 0xFFFFFFFFFFFFFFFF /* 64 bit DMA */ +#define CCISS_DMA_MASK 0xFFFFFFFFFFFFFFFFULL /* 64 bit DMA */ #ifdef CONFIG_CISS_MONITOR_THREAD static int cciss_monitor(void *ctlr); @@ -168,6 +168,35 @@ static int cciss_proc_get_info(char *buf static void cciss_procinit(int i) {} #endif /* CONFIG_PROC_FS */ +/* + * Enqueuing and dequeuing functions for cmdlists. + */ +static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c) +{ + if (*Qptr == NULL) { + *Qptr = c; + c->next = c->prev = c; + } else { + c->prev = (*Qptr)->prev; + c->next = (*Qptr); + (*Qptr)->prev->next = c; + (*Qptr)->prev = c; + } +} + +static inline CommandList_struct *removeQ(CommandList_struct **Qptr, + CommandList_struct *c) +{ + if (c && c->next != c) { + if (*Qptr == c) *Qptr = c->next; + c->prev->next = c->next; + c->next->prev = c->prev; + } else { + *Qptr = NULL; + } + return c; +} + static struct block_device_operations cciss_fops = { owner: THIS_MODULE, open: cciss_open, @@ -592,7 +621,7 @@ int cciss_ioctl32_passthru(unsigned int set_fs(old_fs); if (err) return err; - err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info)); + err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(arg32->error_info)); if (err) return -EFAULT; return err; @@ -620,7 +649,7 @@ int cciss_ioctl32_big_passthru(unsigned set_fs(old_fs); if (err) return err; - err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info)); + err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(arg32->error_info)); if (err) return -EFAULT; return err; @@ -629,6 +658,7 @@ int cciss_ioctl32_big_passthru(unsigned static inline void register_cciss_ioctl32(void) {} static inline void unregister_cciss_ioctl32(void) {} #endif + /* * ioctl */ @@ -942,6 +972,8 @@ static int cciss_ioctl(struct inode *ino { kfree(buff); return -EFAULT; + } else { + memset(buff, 0, iocommand.buf_size); } } if ((c = cmd_alloc(h , 0)) == NULL) { @@ -1060,12 +1092,15 @@ static int cciss_ioctl(struct inode *ino goto cleanup1; } if (iocommand.Request.Type.Direction == - XFER_WRITE) + XFER_WRITE) { /* Copy the data into the buffer created */ if (copy_from_user(buff[sg_used], data_ptr, buff_size[sg_used])) { status = -ENOMEM; goto cleanup1; + } else { + memset(buff[sg_used], 0, buff_size[sg_used]); + } } size_left_alloc -= buff_size[sg_used]; data_ptr += buff_size[sg_used]; @@ -2129,35 +2164,6 @@ static ulong remap_pci_mem(ulong base, u return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL); } -/* - * Enqueuing and dequeuing functions for cmdlists. - */ -static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c) -{ - if (*Qptr == NULL) { - *Qptr = c; - c->next = c->prev = c; - } else { - c->prev = (*Qptr)->prev; - c->next = (*Qptr); - (*Qptr)->prev->next = c; - (*Qptr)->prev = c; - } -} - -static inline CommandList_struct *removeQ(CommandList_struct **Qptr, - CommandList_struct *c) -{ - if (c && c->next != c) { - if (*Qptr == c) *Qptr = c->next; - c->prev->next = c->next; - c->next->prev = c->prev; - } else { - *Qptr = NULL; - } - return c; -} - /* * Takes jobs of the Q and sends them to the hardware, then puts it on * the Q to wait for completion. @@ -2671,7 +2677,7 @@ static int find_PCI_BAR_index(struct pci static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) { ushort subsystem_vendor_id, subsystem_device_id, command; - unchar irq = pdev->irq, ready = 0; + int ready = 0; __u32 board_id, scratchpad; __u64 cfg_offset; __u32 cfg_base_addr; @@ -2727,11 +2733,11 @@ static int cciss_pci_init(ctlr_info_t *c #ifdef CCISS_DEBUG printk("command = %x\n", command); - printk("irq = %x\n", irq); + printk("irq = %x\n", pdev->irq); printk("board_id = %x\n", board_id); #endif /* CCISS_DEBUG */ - c->intr = irq; + c->intr = pdev->irq; /* * Memory base addr is first addr , the second points to the config diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/block/cciss.h linux-2.4.28-pre3/drivers/block/cciss.h --- linux-2.4.27/drivers/block/cciss.h 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/block/cciss.h 2004-09-10 19:31:54.000000000 +0000 @@ -51,7 +51,7 @@ struct ctlr_info unsigned long io_mem_addr; unsigned long io_mem_length; CfgTable_struct *cfgtable; - int intr; + unsigned int intr; int interrupts_enabled; int max_commands; int commands_outstanding; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/block/cpqarray.c linux-2.4.28-pre3/drivers/block/cpqarray.c --- linux-2.4.27/drivers/block/cpqarray.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/block/cpqarray.c 2004-09-10 19:32:46.000000000 +0000 @@ -960,6 +960,20 @@ static inline cmdlist_t *removeQ(cmdlist return c; } +static inline void complete_buffers(struct buffer_head *bh, int ok) +{ + struct buffer_head *xbh; + while(bh) { + xbh = bh->b_reqnext; + bh->b_reqnext = NULL; + + blk_finished_io(bh->b_size >> 9); + bh->b_end_io(bh, ok); + + bh = xbh; + } +} + /* * Get a request and submit it to the controller. * This routine needs to grab all the requests it possibly can from the @@ -1094,19 +1108,6 @@ static void start_io(ctlr_info_t *h) } } -static inline void complete_buffers(struct buffer_head *bh, int ok) -{ - struct buffer_head *xbh; - while(bh) { - xbh = bh->b_reqnext; - bh->b_reqnext = NULL; - - blk_finished_io(bh->b_size >> 9); - bh->b_end_io(bh, ok); - - bh = xbh; - } -} /* * Mark all buffers that cmd was responsible for */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/block/ll_rw_blk.c linux-2.4.28-pre3/drivers/block/ll_rw_blk.c --- linux-2.4.27/drivers/block/ll_rw_blk.c 2004-04-14 13:05:29.000000000 +0000 +++ linux-2.4.28-pre3/drivers/block/ll_rw_blk.c 2004-09-10 19:32:38.000000000 +0000 @@ -132,7 +132,7 @@ static inline int get_max_sectors(kdev_t return max_sectors[MAJOR(dev)][MINOR(dev)]; } -inline request_queue_t *blk_get_queue(kdev_t dev) +static inline request_queue_t *__blk_get_queue(kdev_t dev) { struct blk_dev_struct *bdev = blk_dev + MAJOR(dev); @@ -142,6 +142,11 @@ inline request_queue_t *blk_get_queue(kd return &blk_dev[MAJOR(dev)].request_queue; } +request_queue_t *blk_get_queue(kdev_t dev) +{ + return __blk_get_queue(dev); +} + static int __blk_cleanup_queue(struct request_list *list) { struct list_head *head = &list->free; @@ -303,7 +308,7 @@ void blk_queue_bounce_limit(request_queu /* * can we merge the two segments, or do we need to start a new one? */ -inline int blk_seg_merge_ok(struct buffer_head *bh, struct buffer_head *nxt) +static inline int __blk_seg_merge_ok(struct buffer_head *bh, struct buffer_head *nxt) { /* * if bh and nxt are contigous and don't cross a 4g boundary, it's ok @@ -314,6 +319,11 @@ inline int blk_seg_merge_ok(struct buffe return 0; } +int blk_seg_merge_ok(struct buffer_head *bh, struct buffer_head *nxt) +{ + return __blk_seg_merge_ok(bh, nxt); +} + static inline int ll_new_segment(request_queue_t *q, struct request *req, int max_segments) { if (req->nr_segments < max_segments) { @@ -326,7 +336,7 @@ static inline int ll_new_segment(request static int ll_back_merge_fn(request_queue_t *q, struct request *req, struct buffer_head *bh, int max_segments) { - if (blk_seg_merge_ok(req->bhtail, bh)) + if (__blk_seg_merge_ok(req->bhtail, bh)) return 1; return ll_new_segment(q, req, max_segments); @@ -335,7 +345,7 @@ static int ll_back_merge_fn(request_queu static int ll_front_merge_fn(request_queue_t *q, struct request *req, struct buffer_head *bh, int max_segments) { - if (blk_seg_merge_ok(bh, req->bh)) + if (__blk_seg_merge_ok(bh, req->bh)) return 1; return ll_new_segment(q, req, max_segments); @@ -346,7 +356,7 @@ static int ll_merge_requests_fn(request_ { int total_segments = req->nr_segments + next->nr_segments; - if (blk_seg_merge_ok(req->bhtail, next->bh)) + if (__blk_seg_merge_ok(req->bhtail, next->bh)) total_segments--; if (total_segments > max_segments) @@ -1255,7 +1265,7 @@ void generic_make_request (int rw, struc * Stacking drivers are expected to know what they are doing. */ do { - q = blk_get_queue(bh->b_rdev); + q = __blk_get_queue(bh->b_rdev); if (!q) { printk(KERN_ERR "generic_make_request: Trying to access " diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/agp/agp.h linux-2.4.28-pre3/drivers/char/agp/agp.h --- linux-2.4.27/drivers/char/agp/agp.h 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/agp/agp.h 2004-09-10 19:34:22.000000000 +0000 @@ -211,6 +211,12 @@ struct agp_bridge_data { #ifndef PCI_DEVICE_ID_INTEL_865_G_1 #define PCI_DEVICE_ID_INTEL_865_G_1 0x2572 #endif +#ifndef PCI_DEVICE_ID_INTEL_915_G_0 +#define PCI_DEVICE_ID_INTEL_915_G_0 0x2580 +#endif +#ifndef PCI_DEVICE_ID_INTEL_915_G_1 +#define PCI_DEVICE_ID_INTEL_915_G_1 0x2582 +#endif #ifndef PCI_DEVICE_ID_INTEL_820_0 #define PCI_DEVICE_ID_INTEL_820_0 0x2500 #endif @@ -441,6 +447,12 @@ struct agp_bridge_data { #define I810_DRAM_ROW_0 0x00000001 #define I810_DRAM_ROW_0_SDRAM 0x00000001 +/* intel I915 registers */ +#define I915_GMADDR 0x18 +#define I915_MMADDR 0x10 +#define I915_PTEADDR 0x1C +#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4) +#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4) /* VIA register */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/agp/agpgart_be.c linux-2.4.28-pre3/drivers/char/agp/agpgart_be.c --- linux-2.4.27/drivers/char/agp/agpgart_be.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/agp/agpgart_be.c 2004-09-10 19:32:47.000000000 +0000 @@ -794,7 +794,29 @@ static unsigned long agp_generic_alloc_p } #endif get_page(page); - LockPage(page); + set_bit(PG_locked, &page->flags); + atomic_inc(&agp_bridge.current_memory_agp); + return (unsigned long)page_address(page); +} + +/* Exists to support ARGB cursors */ +static unsigned long i830_alloc_pages(void) +{ + struct page * page; + + page = alloc_pages(GFP_KERNEL, 2); + if (page == NULL) { + return 0; + } + +#ifdef CONFIG_X86 + if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) { + __free_page(page); + return 0; + } +#endif + get_page(page); + set_bit(PG_locked, &page->flags); atomic_inc(&agp_bridge.current_memory_agp); return (unsigned long)page_address(page); } @@ -818,6 +840,25 @@ static void agp_generic_destroy_page(uns atomic_dec(&agp_bridge.current_memory_agp); } +static void i830_destroy_pages(unsigned long addr) +{ + void *pt = (void *) addr; + struct page *page; + + if (pt == NULL) { + return; + } + + page = virt_to_page(pt); +#ifdef CONFIG_X86 + change_page_attr(page, 4, PAGE_KERNEL); +#endif + put_page(page); + UnlockPage(page); + free_pages((unsigned long) pt, 2); + atomic_dec(&agp_bridge.current_memory_agp); +} + /* End Basic Page Allocation Routines */ void agp_enable(u32 mode) @@ -1022,33 +1063,49 @@ static agp_memory *intel_i810_alloc_by_t return new; } if(type == AGP_PHYS_MEMORY) { + unsigned long physical; + /* The I810 requires a physical address to program * it's mouse pointer into hardware. However the * Xserver still writes to it through the agp * aperture */ - if (pg_count != 1) { - return NULL; - } - new = agp_create_memory(1); + if (pg_count != 1 && pg_count != 4) return(NULL); - if (new == NULL) { - return NULL; + new = agp_create_memory(pg_count); + + if (new == NULL) return(NULL); + + MOD_INC_USE_COUNT; + if (pg_count == 1) + new->memory[0] = agp_bridge.agp_alloc_page(); + else { + /* kludge to get 4 physical pages for ARGB cursor */ + new->memory[0] = i830_alloc_pages(); + new->memory[1] = new->memory[0] + PAGE_SIZE; + new->memory[2] = new->memory[1] + PAGE_SIZE; + new->memory[3] = new->memory[2] + PAGE_SIZE; } - MOD_INC_USE_COUNT; - new->memory[0] = agp_bridge.agp_alloc_page(); if (new->memory[0] == 0) { /* Free this structure */ agp_free_memory(new); return NULL; } + physical = new->memory[0]; + new->memory[0] = virt_to_phys((void *) new->memory[0]); - new->page_count = 1; - new->num_scratch_pages = 1; - new->type = AGP_PHYS_MEMORY; - new->physical = virt_to_phys((void *) new->memory[0]); - return new; + if (pg_count == 4) { + /* kludge to enable 4 physical pages for ARGB cursor */ + new->memory[1] = virt_to_phys((void *) new->memory[1]); + new->memory[2] = virt_to_phys((void *) new->memory[2]); + new->memory[3] = virt_to_phys((void *) new->memory[3]); + } + new->page_count = pg_count; + new->num_scratch_pages = pg_count; + new->type = AGP_PHYS_MEMORY; + new->physical = virt_to_phys((void *) physical); + return(new); } return NULL; @@ -1058,7 +1115,11 @@ static void intel_i810_free_by_type(agp_ { agp_free_key(curr->key); if(curr->type == AGP_PHYS_MEMORY) { - agp_bridge.agp_destroy_page((unsigned long) + if (curr->page_count == 4) + i830_destroy_pages((unsigned long) + phys_to_virt(curr->memory[0])); + else + agp_bridge.agp_destroy_page((unsigned long) phys_to_virt(curr->memory[0])); vfree(curr->memory); } @@ -1108,15 +1169,20 @@ static aper_size_info_fixed intel_i830_s { {128, 32768, 5}, /* The 64M mode still requires a 128k gatt */ - {64, 16384, 5} + {64, 16384, 5}, + /* For I915G */ + {256, 65536, 6} }; static struct _intel_i830_private { struct pci_dev *i830_dev; /* device one */ volatile u8 *registers; + volatile u32 *gtt; /* I915G */ int gtt_entries; } intel_i830_private; +static int intel_i830_fetch_size(void); + static void intel_i830_init_gtt_entries(void) { u16 gmch_ctrl; @@ -1124,26 +1190,47 @@ static void intel_i830_init_gtt_entries( u8 rdct; int local = 0; static const int ddt[4] = { 0, 16, 32, 64 }; + int size; + pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl); + /* We obtain the size of the GTT, which is also stored (for some + * reason) at the top of stolen memory. Then we add 4KB to that + * for the video BIOS popup, which is also stored in there. */ + size = intel_i830_fetch_size() + 4; + if (agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_830_M_0 && agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_845_G_0) { switch (gmch_ctrl & I855_GMCH_GMS_MASK) { case I855_GMCH_GMS_STOLEN_1M: - gtt_entries = MB(1) - KB(132); + gtt_entries = MB(1) - KB(size); break; case I855_GMCH_GMS_STOLEN_4M: - gtt_entries = MB(4) - KB(132); + gtt_entries = MB(4) - KB(size); break; case I855_GMCH_GMS_STOLEN_8M: - gtt_entries = MB(8) - KB(132); + gtt_entries = MB(8) - KB(size); break; case I855_GMCH_GMS_STOLEN_16M: - gtt_entries = MB(16) - KB(132); + gtt_entries = MB(16) - KB(size); break; case I855_GMCH_GMS_STOLEN_32M: - gtt_entries = MB(32) - KB(132); + gtt_entries = MB(32) - KB(size); + break; + case I915_GMCH_GMS_STOLEN_48M: + /* Check it's really I915 */ + if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) + gtt_entries = MB(48) - KB(size); + else + gtt_entries = 0; + break; + case I915_GMCH_GMS_STOLEN_64M: + /* Check it's really I915 */ + if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) + gtt_entries = MB(64) - KB(size); + else + gtt_entries = 0; break; default: gtt_entries = 0; @@ -1153,13 +1240,13 @@ static void intel_i830_init_gtt_entries( { switch (gmch_ctrl & I830_GMCH_GMS_MASK) { case I830_GMCH_GMS_STOLEN_512: - gtt_entries = KB(512) - KB(132); + gtt_entries = KB(512) - KB(size); break; case I830_GMCH_GMS_STOLEN_1024: - gtt_entries = MB(1) - KB(132); + gtt_entries = MB(1) - KB(size); break; case I830_GMCH_GMS_STOLEN_8192: - gtt_entries = MB(8) - KB(132); + gtt_entries = MB(8) - KB(size); break; case I830_GMCH_GMS_LOCAL: rdct = INREG8(intel_i830_private.registers, @@ -1193,14 +1280,24 @@ static int intel_i830_create_gatt_table( int page_order; aper_size_info_fixed *size; int num_entries; - u32 temp; + u32 temp, temp2; size = agp_bridge.current_size; page_order = size->page_order; num_entries = size->num_entries; agp_bridge.gatt_table_real = 0; - pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp); + if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) { + pci_read_config_dword(intel_i830_private.i830_dev, + I915_MMADDR,&temp); + pci_read_config_dword(intel_i830_private.i830_dev, + I915_PTEADDR,&temp2); + intel_i830_private.gtt = (volatile u32 *) ioremap(temp2, 256 * 1024); + if (!intel_i830_private.gtt) return (-ENOMEM); + } else + pci_read_config_dword(intel_i830_private.i830_dev, + I810_MMADDR,&temp); + temp &= 0xfff80000; intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096); @@ -1234,6 +1331,20 @@ static int intel_i830_fetch_size(void) values = A_SIZE_FIX(agp_bridge.aperture_sizes); + if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) { + u32 temp, offset = 0; + pci_read_config_dword(intel_i830_private.i830_dev, + I915_GMADDR,&temp); +#define I915_256MB_ADDRESS_MASK (1<<27) + if (temp & I915_256MB_ADDRESS_MASK) + offset = 0; /* 128MB aperture */ + else + offset = 2; /* 256MB aperture */ + agp_bridge.previous_size = agp_bridge.current_size = (void *)(values + offset); + agp_bridge.aperture_size_idx = offset; + return(values[offset].size); + } + if (agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_830_M_0 && agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_845_G_0) { agp_bridge.previous_size = agp_bridge.current_size = (void *) values; @@ -1247,7 +1358,7 @@ static int intel_i830_fetch_size(void) agp_bridge.aperture_size_idx = 0; return(values[0].size); } else { - agp_bridge.previous_size = agp_bridge.current_size = (void *) values; + agp_bridge.previous_size = agp_bridge.current_size = (void *)(values + 1); agp_bridge.aperture_size_idx = 1; return(values[1].size); } @@ -1264,7 +1375,13 @@ static int intel_i830_configure(void) current_size = A_SIZE_FIX(agp_bridge.current_size); - pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp); + if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) + pci_read_config_dword(intel_i830_private.i830_dev, + I915_GMADDR,&temp); + else + pci_read_config_dword(intel_i830_private.i830_dev, + I810_GMADDR,&temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl); @@ -1274,15 +1391,24 @@ static int intel_i830_configure(void) OUTREG32(intel_i830_private.registers,I810_PGETBL_CTL,agp_bridge.gatt_bus_addr | I810_PGETBL_ENABLED); CACHE_FLUSH(); - if (agp_bridge.needs_scratch_page == TRUE) - for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) - OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page); + if (agp_bridge.needs_scratch_page == TRUE) { + if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) { + for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) + OUTREG32(intel_i830_private.gtt, i, agp_bridge.scratch_page); + } else { + for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) + OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page); + } + } return (0); } static void intel_i830_cleanup(void) { + if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) + iounmap((void *)intel_i830_private.gtt); + iounmap((void *) intel_i830_private.registers); } @@ -1315,9 +1441,13 @@ static int intel_i830_insert_entries(agp CACHE_FLUSH(); - for (i = 0, j = pg_start; i < mem->page_count; i++, j++) - OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4), - agp_bridge.mask_memory(mem->memory[i], mem->type)); + if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) { + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) + OUTREG32(intel_i830_private.gtt, j, agp_bridge.mask_memory(mem->memory[i], mem->type)); + } else { + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) + OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4),agp_bridge.mask_memory(mem->memory[i], mem->type)); + } CACHE_FLUSH(); @@ -1337,8 +1467,13 @@ static int intel_i830_remove_entries(agp return (-EINVAL); } - for (i = pg_start; i < (mem->page_count + pg_start); i++) - OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page); + if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) { + for (i = pg_start; i < (mem->page_count + pg_start); i++) + OUTREG32(intel_i830_private.gtt, i, agp_bridge.scratch_page); + } else { + for (i = pg_start; i < (mem->page_count + pg_start); i++) + OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page); + } CACHE_FLUSH(); @@ -1363,24 +1498,40 @@ static agp_memory *intel_i830_alloc_by_t * aperture */ - if (pg_count != 1) return(NULL); + if (pg_count != 1 && pg_count != 4) return(NULL); - nw = agp_create_memory(1); + nw = agp_create_memory(pg_count); if (nw == NULL) return(NULL); MOD_INC_USE_COUNT; - nw->memory[0] = agp_bridge.agp_alloc_page(); - physical = nw->memory[0]; + if (pg_count == 1) + nw->memory[0] = agp_bridge.agp_alloc_page(); + else { + /* kludge to get 4 physical pages for ARGB cursor */ + nw->memory[0] = i830_alloc_pages(); + nw->memory[1] = nw->memory[0] + PAGE_SIZE; + nw->memory[2] = nw->memory[1] + PAGE_SIZE; + nw->memory[3] = nw->memory[2] + PAGE_SIZE; + } + if (nw->memory[0] == 0) { /* free this structure */ agp_free_memory(nw); return(NULL); } + physical = nw->memory[0]; + nw->memory[0] = virt_to_phys((void *) nw->memory[0]); - nw->page_count = 1; - nw->num_scratch_pages = 1; + if (pg_count == 4) { + /* kludge to enable 4 physical pages for ARGB cursor */ + nw->memory[1] = virt_to_phys((void *) nw->memory[1]); + nw->memory[2] = virt_to_phys((void *) nw->memory[2]); + nw->memory[3] = virt_to_phys((void *) nw->memory[3]); + } + nw->page_count = pg_count; + nw->num_scratch_pages = pg_count; nw->type = AGP_PHYS_MEMORY; nw->physical = virt_to_phys((void *) physical); return(nw); @@ -3447,9 +3598,9 @@ static int x86_64_insert_memory(agp_memo for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { tmp = agp_bridge.mask_memory(mem->memory[i], mem->type); - BUG_ON(tmp & 0xffffff0000000ffc); - pte = (tmp & 0x000000ff00000000) >> 28; - pte |=(tmp & 0x00000000fffff000); + BUG_ON(tmp & 0xffffff0000000ffcULL); + pte = (tmp & 0x000000ff00000000ULL) >> 28; + pte |=(tmp & 0x00000000fffff000ULL); pte |= 1<<1|1<<0; agp_bridge.gatt_table[j] = pte; @@ -6112,6 +6263,13 @@ static struct { "865G", intel_845_setup }, + { PCI_DEVICE_ID_INTEL_915_G_0, + PCI_VENDOR_ID_INTEL, + INTEL_I915_G, + "Intel(R)", + "915G", + intel_845_setup }, + { PCI_DEVICE_ID_INTEL_840_0, PCI_VENDOR_ID_INTEL, INTEL_I840, @@ -6835,6 +6993,34 @@ static int __init agp_init_one(struct pc "865G Chipset.\n"); agp_bridge.type = INTEL_I810; return intel_i830_setup(i810_dev); + + case PCI_DEVICE_ID_INTEL_915_G_0: + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_915_G_1, NULL); + if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) { + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_915_G_1, i810_dev); + } + + if (i810_dev == NULL) { + /* + * We probably have a 915G chipset + * with an external graphics + * card. It will be initialized later + */ + printk(KERN_ERR PFX "Detected an " + "Intel(R) 915G, but could not" + " find the" + " secondary device. Assuming a " + "non-integrated video card.\n"); + agp_bridge.type = INTEL_I915_G; + break; + } + printk(KERN_INFO PFX "Detected an Intel(R) " + "915G Chipset.\n"); + agp_bridge.type = INTEL_I810; + return intel_i830_setup(i810_dev); + default: break; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/applicom.c linux-2.4.28-pre3/drivers/char/applicom.c --- linux-2.4.27/drivers/char/applicom.c 2002-08-03 00:39:43.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/applicom.c 2004-09-10 19:36:55.000000000 +0000 @@ -222,6 +222,7 @@ int __init applicom_init(void) if (!RamIO) { printk(KERN_INFO "ac.o: Failed to ioremap PCI memory space at 0x%lx\n", PCI_BASE_ADDRESS(dev)); + pci_disable_device(dev); return -EIO; } @@ -233,12 +234,14 @@ int __init applicom_init(void) (unsigned long)RamIO,0))) { printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n"); iounmap(RamIO); + pci_disable_device(dev); continue; } if (request_irq(dev->irq, &ac_interrupt, SA_SHIRQ, "Applicom PCI", &dummy)) { printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq); iounmap(RamIO); + pci_disable_device(dev); apbs[boardno - 1].RamIO = 0; continue; } @@ -265,12 +268,6 @@ int __init applicom_init(void) /* Now try the specified ISA cards */ -#warning "LEAK" - RamIO = ioremap(mem, LEN_RAM_IO * MAX_ISA_BOARD); - - if (!RamIO) - printk(KERN_INFO "ac.o: Failed to ioremap ISA memory space at 0x%lx\n", mem); - for (i = 0; i < MAX_ISA_BOARD; i++) { RamIO = ioremap(mem + (LEN_RAM_IO * i), LEN_RAM_IO); @@ -293,7 +290,8 @@ int __init applicom_init(void) iounmap((void *) RamIO); apbs[boardno - 1].RamIO = 0; } - apbs[boardno - 1].irq = irq; + else + apbs[boardno - 1].irq = irq; } else apbs[boardno - 1].irq = 0; @@ -368,7 +366,7 @@ static ssize_t ac_write(struct file *fil if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) { static int warncount = 5; if (warncount) { - printk(KERN_INFO "Hmmm. write() of Applicom card, length %d != expected %d\n", + printk(KERN_INFO "Hmmm. write() of Applicom card, length %zd != expected %zd\n", count, sizeof(struct st_ram_io) + sizeof(struct mailbox)); warncount--; } @@ -476,18 +474,17 @@ static ssize_t ac_write(struct file *fil return 0; } -static int do_ac_read(int IndexCard, char *buf) +static int do_ac_read(int IndexCard, char *buf, + struct st_ram_io *st_loc, struct mailbox *mailbox) { - struct st_ram_io st_loc; - struct mailbox tmpmailbox; /* bounce buffer - can't copy to user space with cli() */ unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC; - unsigned char *to = (unsigned char *)&tmpmailbox; + unsigned char *to = (unsigned char *)&mailbox; #ifdef DEBUG int c; #endif - st_loc.tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC); - st_loc.numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC); + st_loc->tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC); + st_loc->numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC); { @@ -510,32 +507,24 @@ static int do_ac_read(int IndexCard, cha printk("Read from applicom card #%d. struct st_ram_io follows:", NumCard); for (c = 0; c < sizeof(struct st_ram_io);) { - printk("\n%5.5X: %2.2X", c, ((unsigned char *) &st_loc)[c]); + printk("\n%5.5X: %2.2X", c, ((unsigned char *)st_loc)[c]); for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) { - printk(" %2.2X", ((unsigned char *) &st_loc)[c]); + printk(" %2.2X", ((unsigned char *)st_loc)[c]); } } printk("\nstruct mailbox follows:"); for (c = 0; c < sizeof(struct mailbox);) { - printk("\n%5.5X: %2.2X", c, ((unsigned char *) &tmpmailbox)[c]); + printk("\n%5.5X: %2.2X", c, ((unsigned char *)mailbox)[c]); for (c++; c % 8 && c < sizeof(struct mailbox); c++) { - printk(" %2.2X", ((unsigned char *) &tmpmailbox)[c]); + printk(" %2.2X", ((unsigned char *)mailbox)[c]); } } printk("\n"); #endif - -#warning "Je suis stupide. DW. - copy*user in cli" - - if (copy_to_user(buf, &st_loc, sizeof(struct st_ram_io))) - return -EFAULT; - if (copy_to_user(&buf[sizeof(struct st_ram_io)], &tmpmailbox, sizeof(struct mailbox))) - return -EFAULT; - return (sizeof(struct st_ram_io) + sizeof(struct mailbox)); } @@ -551,7 +540,7 @@ static ssize_t ac_read (struct file *fil #endif /* No need to ratelimit this. Only root can trigger it anyway */ if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) { - printk( KERN_WARNING "Hmmm. read() of Applicom card, length %d != expected %d\n", + printk( KERN_WARNING "Hmmm. read() of Applicom card, length %zd != expected %zd\n", count,sizeof(struct st_ram_io) + sizeof(struct mailbox)); return -EINVAL; } @@ -570,11 +559,19 @@ static ssize_t ac_read (struct file *fil tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY); if (tmp == 2) { + struct st_ram_io st_loc; + struct mailbox mailbox; + /* Got a packet for us */ - ret = do_ac_read(i, buf); + ret = do_ac_read(i, buf, &st_loc, &mailbox); spin_unlock_irqrestore(&apbs[i].mutex, flags); set_current_state(TASK_RUNNING); remove_wait_queue(&FlagSleepRec, &wait); + + if (copy_to_user(buf, &st_loc, sizeof(st_loc))) + return -EFAULT; + if (copy_to_user(buf + sizeof(st_loc), &mailbox, sizeof(mailbox))) + return -EFAULT; return tmp; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/drm/drm_dma.h linux-2.4.28-pre3/drivers/char/drm/drm_dma.h --- linux-2.4.27/drivers/char/drm/drm_dma.h 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/drm/drm_dma.h 2004-09-10 19:35:35.000000000 +0000 @@ -648,7 +648,7 @@ int DRM(wait_vblank)(struct inode *inode * for the same vblank sequence number; nothing to be done in * that case */ - list_for_each( ( (struct list_head *) vbl_sig ), &dev->vbl_sigs.head ) { + list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) { if (vbl_sig->sequence == vblwait.request.sequence && vbl_sig->info.si_signo == vblwait.request.signal && vbl_sig->task == current) @@ -699,19 +699,20 @@ done: void DRM(vbl_send_signals)( drm_device_t *dev ) { - struct list_head *tmp; + struct list_head *list, *tmp; drm_vbl_sig_t *vbl_sig; unsigned int vbl_seq = atomic_read( &dev->vbl_received ); unsigned long flags; spin_lock_irqsave( &dev->vbl_lock, flags ); - list_for_each_safe( ( (struct list_head *) vbl_sig ), tmp, &dev->vbl_sigs.head ) { + list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) { + vbl_sig = list_entry( list, drm_vbl_sig_t, head ); if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) { vbl_sig->info.si_code = vbl_seq; send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task ); - list_del( (struct list_head *) vbl_sig ); + list_del( list ); kfree( vbl_sig ); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/drm/radeon_state.c linux-2.4.28-pre3/drivers/char/drm/radeon_state.c --- linux-2.4.27/drivers/char/drm/radeon_state.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/drm/radeon_state.c 2004-09-10 19:36:31.000000000 +0000 @@ -1223,7 +1223,7 @@ static int radeon_cp_dispatch_texture( d /* Update the input parameters for next time */ image->y += height; image->height -= height; - (const u8 *)image->data += size; + image->data = (const u8 *)image->data + size; } while (image->height > 0); /* Flush the pixel cache after the blit completes. This ensures diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/ftape/lowlevel/ftape-bsm.c linux-2.4.28-pre3/drivers/char/ftape/lowlevel/ftape-bsm.c --- linux-2.4.27/drivers/char/ftape/lowlevel/ftape-bsm.c 2000-10-16 19:58:51.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/ftape/lowlevel/ftape-bsm.c 2004-09-10 19:33:21.000000000 +0000 @@ -203,6 +203,7 @@ static void print_bad_sector_map(void) ft_format_code == fmt_1100ft) { SectorCount *ptr = (SectorCount *)bad_sector_map; unsigned int sector; + __u16 *ptr16; while((sector = get_sector(ptr++)) != 0) { if ((ft_format_code == fmt_big || @@ -218,9 +219,10 @@ static void print_bad_sector_map(void) } /* Display old ftape's end-of-file marks */ - while ((sector = get_unaligned(((__u16*)ptr)++)) != 0) { + ptr16 = (__u16*)ptr; + while ((sector = get_unaligned(ptr16++)) != 0) { TRACE(ft_t_noise, "Old ftape eof mark: %4d/%2d", - sector, get_unaligned(((__u16*)ptr)++)); + sector, get_unaligned(ptr16++)); } } else { /* fixed size format */ for (i = ft_first_data_segment; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/ftape/lowlevel/ftape-bsm.h linux-2.4.28-pre3/drivers/char/ftape/lowlevel/ftape-bsm.h --- linux-2.4.27/drivers/char/ftape/lowlevel/ftape-bsm.h 1997-11-25 22:45:27.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/ftape/lowlevel/ftape-bsm.h 2004-09-10 19:31:49.000000000 +0000 @@ -47,7 +47,7 @@ typedef __u32 SectorMap; */ typedef struct NewSectorMap { __u8 bytes[3]; -} SectorCount __attribute__((packed)); +} __attribute__((packed)) SectorCount; /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/ftape/zftape/zftape-eof.c linux-2.4.28-pre3/drivers/char/ftape/zftape/zftape-eof.c --- linux-2.4.27/drivers/char/ftape/zftape/zftape-eof.c 1999-11-23 18:29:15.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/ftape/zftape/zftape-eof.c 2004-09-10 19:37:30.000000000 +0000 @@ -123,7 +123,7 @@ static __u8 * find_end_of_eof_list(__u8 while (ptr + 3 < limit) { if (get_unaligned((__u32*)ptr)) { - ++(__u32*)ptr; + ptr += sizeof(__u32); } else { return ptr; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/ib700wdt.c linux-2.4.28-pre3/drivers/char/ib700wdt.c --- linux-2.4.27/drivers/char/ib700wdt.c 2002-11-28 23:53:12.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/ib700wdt.c 2004-09-10 19:36:48.000000000 +0000 @@ -133,7 +133,7 @@ static void ibwdt_ping(void) { /* Write a watchdog value */ - outb_p(wd_times[wd_margin], WDT_START); + outb_p(wd_margin, WDT_START); } static ssize_t diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/ip2main.c linux-2.4.28-pre3/drivers/char/ip2main.c --- linux-2.4.27/drivers/char/ip2main.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/ip2main.c 2004-09-10 19:37:27.000000000 +0000 @@ -282,8 +282,8 @@ static void ip2_interrupt_bh(i2eBordStrP static void ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs); static void ip2_poll(unsigned long arg); static inline void service_all_boards(void); -static inline void do_input(i2ChanStrPtr pCh); -static inline void do_status(i2ChanStrPtr pCh); +static void do_input(i2ChanStrPtr pCh); +static void do_status(i2ChanStrPtr pCh); static void ip2_wait_until_sent(PTTY,int); @@ -1433,7 +1433,7 @@ ip2_poll(unsigned long arg) ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); } -static inline void +static void do_input( i2ChanStrPtr pCh ) { unsigned long flags; @@ -1468,7 +1468,7 @@ isig(int sig, struct tty_struct *tty, in } } -static inline void +static void do_status( i2ChanStrPtr pCh ) { int status; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/istallion.c linux-2.4.28-pre3/drivers/char/istallion.c --- linux-2.4.27/drivers/char/istallion.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/istallion.c 2004-09-10 19:35:31.000000000 +0000 @@ -4546,6 +4546,26 @@ static inline int stli_eisamemprobe(stli /*****************************************************************************/ /* + * Find the next available board number that is free. + */ + +static inline int stli_getbrdnr() +{ + int i; + + for (i = 0; (i < STL_MAXBRDS); i++) { + if (stli_brds[i] == (stlibrd_t *) NULL) { + if (i >= stli_nrbrds) + stli_nrbrds = i + 1; + return(i); + } + } + return(-1); +} + +/*****************************************************************************/ + +/* * Probe around and try to find any EISA boards in system. The biggest * problem here is finding out what memory address is associated with * an EISA board after it is found. The registers of the ECPE and @@ -4625,26 +4645,6 @@ static inline int stli_findeisabrds() /*****************************************************************************/ -/* - * Find the next available board number that is free. - */ - -static inline int stli_getbrdnr() -{ - int i; - - for (i = 0; (i < STL_MAXBRDS); i++) { - if (stli_brds[i] == (stlibrd_t *) NULL) { - if (i >= stli_nrbrds) - stli_nrbrds = i + 1; - return(i); - } - } - return(-1); -} - -/*****************************************************************************/ - #ifdef CONFIG_PCI /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/mxser.c linux-2.4.28-pre3/drivers/char/mxser.c --- linux-2.4.27/drivers/char/mxser.c 2002-11-28 23:53:12.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/mxser.c 2004-09-10 19:35:52.000000000 +0000 @@ -1385,66 +1385,6 @@ void mxser_hangup(struct tty_struct *tty wake_up_interruptible(&info->open_wait); } -/* - * This is the serial driver's generic interrupt routine - */ -static void mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - int status, i; - struct mxser_struct *info; - struct mxser_struct *port; - int max, irqbits, bits, msr; - int pass_counter = 0; - - port = 0; - for (i = 0; i < MXSER_BOARDS; i++) { - if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) { - port = dev_id; - break; - } - } - - if (i == MXSER_BOARDS) - return; - if (port == 0) - return; - max = mxser_numports[mxsercfg[i].board_type]; - - while (1) { - irqbits = inb(port->vector) & port->vectormask; - if (irqbits == port->vectormask) - break; - for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { - if (irqbits == port->vectormask) - break; - if (bits & irqbits) - continue; - info = port + i; - if (!info->tty || - (inb(info->base + UART_IIR) & UART_IIR_NO_INT)) - continue; - status = inb(info->base + UART_LSR) & info->read_status_mask; - if (status & UART_LSR_DR) - mxser_receive_chars(info, &status); - msr = inb(info->base + UART_MSR); - if (msr & UART_MSR_ANY_DELTA) - mxser_check_modem_status(info, msr); - if (status & UART_LSR_THRE) { -/* 8-2-99 by William - if ( info->x_char || (info->xmit_cnt > 0) ) - */ - mxser_transmit_chars(info); - } - } - if (pass_counter++ > MXSER_ISR_PASS_LIMIT) { -#if 0 - printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n"); -#endif - break; /* Prevent infinite loops */ - } - } -} - static inline void mxser_receive_chars(struct mxser_struct *info, int *status) { @@ -1487,44 +1427,6 @@ static inline void mxser_receive_chars(s } -static inline void mxser_transmit_chars(struct mxser_struct *info) -{ - int count, cnt; - - if (info->x_char) { - outb(info->x_char, info->base + UART_TX); - info->x_char = 0; - mxvar_log.txcnt[info->port]++; - return; - } - if ((info->xmit_cnt <= 0) || info->tty->stopped || - info->tty->hw_stopped) { - info->IER &= ~UART_IER_THRI; - outb(info->IER, info->base + UART_IER); - return; - } - cnt = info->xmit_cnt; - count = info->xmit_fifo_size; - do { - outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX); - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1); - if (--info->xmit_cnt <= 0) - break; - } while (--count > 0); - mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt); - - if (info->xmit_cnt < WAKEUP_CHARS) { - set_bit(MXSER_EVENT_TXLOW, &info->event); - MOD_INC_USE_COUNT; - if (schedule_task(&info->tqueue) == 0) - MOD_DEC_USE_COUNT; - } - if (info->xmit_cnt <= 0) { - info->IER &= ~UART_IER_THRI; - outb(info->IER, info->base + UART_IER); - } -} - static inline void mxser_check_modem_status(struct mxser_struct *info, int status) { @@ -1572,6 +1474,104 @@ static inline void mxser_check_modem_sta } } +static inline void mxser_transmit_chars(struct mxser_struct *info) +{ + int count, cnt; + + if (info->x_char) { + outb(info->x_char, info->base + UART_TX); + info->x_char = 0; + mxvar_log.txcnt[info->port]++; + return; + } + if ((info->xmit_cnt <= 0) || info->tty->stopped || + info->tty->hw_stopped) { + info->IER &= ~UART_IER_THRI; + outb(info->IER, info->base + UART_IER); + return; + } + cnt = info->xmit_cnt; + count = info->xmit_fifo_size; + do { + outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX); + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1); + if (--info->xmit_cnt <= 0) + break; + } while (--count > 0); + mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt); + + if (info->xmit_cnt < WAKEUP_CHARS) { + set_bit(MXSER_EVENT_TXLOW, &info->event); + MOD_INC_USE_COUNT; + if (schedule_task(&info->tqueue) == 0) + MOD_DEC_USE_COUNT; + } + if (info->xmit_cnt <= 0) { + info->IER &= ~UART_IER_THRI; + outb(info->IER, info->base + UART_IER); + } +} + +/* + * This is the serial driver's generic interrupt routine + */ +static void mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int status, i; + struct mxser_struct *info; + struct mxser_struct *port; + int max, irqbits, bits, msr; + int pass_counter = 0; + + port = 0; + for (i = 0; i < MXSER_BOARDS; i++) { + if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) { + port = dev_id; + break; + } + } + + if (i == MXSER_BOARDS) + return; + if (port == 0) + return; + max = mxser_numports[mxsercfg[i].board_type]; + + while (1) { + irqbits = inb(port->vector) & port->vectormask; + if (irqbits == port->vectormask) + break; + for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { + if (irqbits == port->vectormask) + break; + if (bits & irqbits) + continue; + info = port + i; + if (!info->tty || + (inb(info->base + UART_IIR) & UART_IIR_NO_INT)) + continue; + status = inb(info->base + UART_LSR) & info->read_status_mask; + if (status & UART_LSR_DR) + mxser_receive_chars(info, &status); + msr = inb(info->base + UART_MSR); + if (msr & UART_MSR_ANY_DELTA) + mxser_check_modem_status(info, msr); + if (status & UART_LSR_THRE) { +/* 8-2-99 by William + if ( info->x_char || (info->xmit_cnt > 0) ) + */ + mxser_transmit_chars(info); + } + } + if (pass_counter++ > MXSER_ISR_PASS_LIMIT) { +#if 0 + printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n"); +#endif + break; /* Prevent infinite loops */ + } + } +} + static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, struct mxser_struct *info) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/nwflash.c linux-2.4.28-pre3/drivers/char/nwflash.c --- linux-2.4.27/drivers/char/nwflash.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/nwflash.c 2004-09-10 19:37:23.000000000 +0000 @@ -159,7 +159,8 @@ static ssize_t flash_read(struct file *f if (ret == 0) { ret = count; *ppos = p + count; - } + } else + ret = -EFAULT; up(&nwflash_sem); } return ret; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/random.c linux-2.4.28-pre3/drivers/char/random.c --- linux-2.4.27/drivers/char/random.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/random.c 2004-09-10 19:32:28.000000000 +0000 @@ -750,6 +750,11 @@ static void add_timer_randomness(struct __u32 high; rdtsc(time, high); num ^= high; +#elif defined (__sparc_v9__) + unsigned long tick = tick_ops->get_tick(); + + time = (unsigned int) tick; + num ^= (tick >> 32UL); #else time = jiffies; #endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/synclinkmp.c linux-2.4.28-pre3/drivers/char/synclinkmp.c --- linux-2.4.27/drivers/char/synclinkmp.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/synclinkmp.c 2004-09-10 19:34:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * $Id: synclinkmp.c,v 3.22 2003/09/05 14:04:26 paulkf Exp $ + * $Id: synclinkmp.c,v 3.23 2004/08/24 19:49:48 paulkf Exp $ * * Device driver for Microgate SyncLink Multiport * high speed multiprotocol serial adapter. @@ -504,7 +504,7 @@ MODULE_PARM(maxframe,"1-" __MODULE_STRIN MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i"); static char *driver_name = "SyncLink MultiPort driver"; -static char *driver_version = "$Revision: 3.22 $"; +static char *driver_version = "$Revision: 3.23 $"; static int __devinit synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent); static void __devexit synclinkmp_remove_one(struct pci_dev *dev); @@ -681,7 +681,7 @@ static unsigned char tx_active_fifo_leve static unsigned char tx_negate_fifo_level = 32; // tx request FIFO negation level in bytes static u32 misc_ctrl_value = 0x007e4040; -static u32 lcr1_brdr_value = 0x0080002d; +static u32 lcr1_brdr_value = 0x00800029; static u32 read_ahead_count = 8; @@ -2036,16 +2036,15 @@ void isr_rxint(SLMP_INFO * info) { struct tty_struct *tty = info->tty; struct mgsl_icount *icount = &info->icount; - unsigned char status = read_reg(info, SR1); - unsigned char status2 = read_reg(info, SR2); + unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD); + unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN; /* clear status bits */ - if ( status & (FLGD + IDLD + CDCD + BRKD) ) - write_reg(info, SR1, - (unsigned char)(status & (FLGD + IDLD + CDCD + BRKD))); + if (status) + write_reg(info, SR1, status); - if ( status2 & OVRN ) - write_reg(info, SR2, (unsigned char)(status2 & OVRN)); + if (status2) + write_reg(info, SR2, status2); if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):%s isr_rxint status=%02X %02x\n", @@ -2182,15 +2181,22 @@ void isr_txeom(SLMP_INFO * info, unsigne printk("%s(%d):%s isr_txeom status=%02x\n", __FILE__,__LINE__,info->device_name,status); - /* disable and clear MSCI interrupts */ - info->ie1_value &= ~(IDLE + UDRN); - write_reg(info, IE1, info->ie1_value); - write_reg(info, SR1, (unsigned char)(UDRN + IDLE)); - write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */ write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */ write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ + if (status & UDRN) { + write_reg(info, CMD, TXRESET); + write_reg(info, CMD, TXENABLE); + } else + write_reg(info, CMD, TXBUFCLR); + + /* disable and clear tx interrupts */ + info->ie0_value &= ~TXRDYE; + info->ie1_value &= ~(IDLE + UDRN); + write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value)); + write_reg(info, SR1, (unsigned char)(UDRN + IDLE)); + if ( info->tx_active ) { if (info->params.mode != MGSL_MODE_ASYNC) { if (status & UDRN) @@ -2231,10 +2237,10 @@ void isr_txeom(SLMP_INFO * info, unsigne */ void isr_txint(SLMP_INFO * info) { - unsigned char status = read_reg(info, SR1); + unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS); /* clear status bits */ - write_reg(info, SR1, (unsigned char)(status & (UDRN + IDLE + CCTS))); + write_reg(info, SR1, status); if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):%s isr_txint status=%02x\n", @@ -2263,6 +2269,14 @@ void isr_txrdy(SLMP_INFO * info) printk("%s(%d):%s isr_txrdy() tx_count=%d\n", __FILE__,__LINE__,info->device_name,info->tx_count); + if (info->params.mode != MGSL_MODE_ASYNC) { + /* disable TXRDY IRQ, enable IDLE IRQ */ + info->ie0_value &= ~TXRDYE; + info->ie1_value |= IDLE; + write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value)); + return; + } + if (info->tty && (info->tty->stopped || info->tty->hw_stopped)) { tx_stop(info); return; @@ -2317,13 +2331,6 @@ void isr_rxdmaerror(SLMP_INFO * info) void isr_txdmaok(SLMP_INFO * info) { - /* BIT7 = EOT (end of transfer, used for async mode) - * BIT6 = EOM (end of message/frame, used for sync mode) - * - * We don't look at DMA status because only EOT is enabled - * and we always clear and disable all tx DMA IRQs. - */ -// unsigned char dma_status = read_reg(info,TXDMA + DSR) & 0xc0; unsigned char status_reg1 = read_reg(info, SR1); write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */ @@ -2334,19 +2341,10 @@ void isr_txdmaok(SLMP_INFO * info) printk("%s(%d):%s isr_txdmaok(), status=%02x\n", __FILE__,__LINE__,info->device_name,status_reg1); - /* If transmitter already idle, do end of frame processing, - * otherwise enable interrupt for tx IDLE. - */ - if (status_reg1 & IDLE) - isr_txeom(info, IDLE); - else { - /* disable and clear underrun IRQ, enable IDLE interrupt */ - info->ie1_value |= IDLE; - info->ie1_value &= ~UDRN; - write_reg(info, IE1, info->ie1_value); - - write_reg(info, SR1, UDRN); - } + /* program TXRDY as FIFO empty flag, enable TXRDY IRQ */ + write_reg16(info, TRC0, 0); + info->ie0_value |= TXRDYE; + write_reg(info, IE0, info->ie0_value); } void isr_txdmaerror(SLMP_INFO * info) @@ -3037,7 +3035,7 @@ static int wait_mgsl_event(SLMP_INFO * i unsigned char oldval = info->ie1_value; unsigned char newval = oldval + (mask & MgslEvent_ExitHuntMode ? FLGD:0) + - (mask & MgslEvent_IdleReceived ? IDLE:0); + (mask & MgslEvent_IdleReceived ? IDLD:0); if ( oldval != newval ) { info->ie1_value = newval; write_reg(info, IE1, info->ie1_value); @@ -3104,7 +3102,7 @@ static int wait_mgsl_event(SLMP_INFO * i spin_lock_irqsave(&info->lock,flags); if (!waitqueue_active(&info->event_wait_q)) { /* disable enable exit hunt mode/idle rcvd IRQs */ - info->ie1_value &= ~(FLGD|IDLE); + info->ie1_value &= ~(FLGD|IDLD); write_reg(info, IE1, info->ie1_value); } spin_unlock_irqrestore(&info->lock,flags); @@ -3554,9 +3552,10 @@ void free_tmp_rx_buf(SLMP_INFO *info) int claim_resources(SLMP_INFO *info) { - if (request_mem_region(info->phys_memory_base,0x40000,"synclinkmp") == NULL) { + if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) { printk( "%s(%d):%s mem addr conflict, Addr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_memory_base); + info->init_error = DiagStatus_AddressConflict; goto errout; } else @@ -3565,22 +3564,25 @@ int claim_resources(SLMP_INFO *info) if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) { printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_lcr_base); + info->init_error = DiagStatus_AddressConflict; goto errout; } else info->lcr_mem_requested = 1; - if (request_mem_region(info->phys_sca_base + info->sca_offset,512,"synclinkmp") == NULL) { + if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) { printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_sca_base); + info->init_error = DiagStatus_AddressConflict; goto errout; } else info->sca_base_requested = 1; - if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,16,"synclinkmp") == NULL) { + if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) { printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_statctrl_base); + info->init_error = DiagStatus_AddressConflict; goto errout; } else @@ -3590,33 +3592,41 @@ int claim_resources(SLMP_INFO *info) if (!info->memory_base) { printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + info->init_error = DiagStatus_CantAssignPciResources; goto errout; } - if ( !memory_test(info) ) { - printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - goto errout; - } - - info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset; + info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE); if (!info->lcr_base) { printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); + info->init_error = DiagStatus_CantAssignPciResources; goto errout; } + info->lcr_base += info->lcr_offset; - info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE) + info->sca_offset; + info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE); if (!info->sca_base) { printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_sca_base ); + info->init_error = DiagStatus_CantAssignPciResources; goto errout; } + info->sca_base += info->sca_offset; - info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE) + info->statctrl_offset; + info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE); if (!info->statctrl_base) { printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_statctrl_base ); + info->init_error = DiagStatus_CantAssignPciResources; + goto errout; + } + info->statctrl_base += info->statctrl_offset; + + if ( !memory_test(info) ) { + printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + info->init_error = DiagStatus_MemoryError; goto errout; } @@ -3639,7 +3649,7 @@ void release_resources(SLMP_INFO *info) } if ( info->shared_mem_requested ) { - release_mem_region(info->phys_memory_base,0x40000); + release_mem_region(info->phys_memory_base,SCA_MEM_SIZE); info->shared_mem_requested = 0; } if ( info->lcr_mem_requested ) { @@ -3647,11 +3657,11 @@ void release_resources(SLMP_INFO *info) info->lcr_mem_requested = 0; } if ( info->sca_base_requested ) { - release_mem_region(info->phys_sca_base + info->sca_offset,512); + release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE); info->sca_base_requested = 0; } if ( info->sca_statctrl_requested ) { - release_mem_region(info->phys_statctrl_base + info->statctrl_offset,16); + release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE); info->sca_statctrl_requested = 0; } @@ -3982,34 +3992,25 @@ static void __exit synclinkmp_exit(void) __FILE__,__LINE__,rc); restore_flags(flags); + /* reset devices */ info = synclinkmp_device_list; while(info) { -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->dosyncppp) - sppp_delete(info); -#endif reset_port(info); - if ( info->port_num == 0 ) { - if ( info->irq_requested ) { - free_irq(info->irq_level, info); - info->irq_requested = 0; - } - } info = info->next_device; } - /* port 0 of each adapter originally claimed - * all resources, release those now - */ + /* release devices */ info = synclinkmp_device_list; while(info) { +#ifdef CONFIG_SYNCLINK_SYNCPPP + if (info->dosyncppp) + sppp_delete(info); +#endif free_dma_bufs(info); free_tmp_rx_buf(info); if ( info->port_num == 0 ) { - spin_lock_irqsave(&info->lock,flags); - reset_adapter(info); - write_reg(info, LPR, 1); /* set low power mode */ - spin_unlock_irqrestore(&info->lock,flags); + if (info->sca_base) + write_reg(info, LPR, 1); /* set low power mode */ release_resources(info); } tmp = info; @@ -4229,6 +4230,9 @@ void tx_start(SLMP_INFO *info) } } + write_reg16(info, TRC0, + (unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level)); + write_reg(info, TXDMA + DSR, 0); /* disable DMA channel */ write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ @@ -4240,11 +4244,10 @@ void tx_start(SLMP_INFO *info) write_reg16(info, TXDMA + EDA, info->tx_buf_list_ex[info->last_tx_buf].phys_entry); - /* clear IDLE and UDRN status bit */ - info->ie1_value &= ~(IDLE + UDRN); - if (info->params.mode != MGSL_MODE_ASYNC) - info->ie1_value |= UDRN; /* HDLC, IRQ on underrun */ - write_reg(info, IE1, info->ie1_value); /* enable MSCI interrupts */ + /* enable underrun IRQ */ + info->ie1_value &= ~IDLE; + info->ie1_value |= UDRN; + write_reg(info, IE1, info->ie1_value); write_reg(info, SR1, (unsigned char)(IDLE + UDRN)); write_reg(info, TXDMA + DIR, 0x40); /* enable Tx DMA interrupts (EOM) */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/vc_screen.c linux-2.4.28-pre3/drivers/char/vc_screen.c --- linux-2.4.27/drivers/char/vc_screen.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/char/vc_screen.c 2004-09-10 19:33:32.000000000 +0000 @@ -136,10 +136,12 @@ vcs_read(struct file *file, char *buf, s if (!vc_cons_allocated(currcons)) goto unlock_out; - read = 0; - ret = 0; + ret = -EINVAL; if (pos != n) goto unlock_out; + + read = 0; + ret = 0; while (count) { char *con_buf0, *con_buf_start; long this_round, size; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/fc4/fc.c linux-2.4.28-pre3/drivers/fc4/fc.c --- linux-2.4.27/drivers/fc4/fc.c 2001-09-14 21:04:08.000000000 +0000 +++ linux-2.4.28-pre3/drivers/fc4/fc.c 2004-09-10 19:35:20.000000000 +0000 @@ -1155,3 +1155,5 @@ int fc_do_prli(fc_channel *fc, unsigned kfree(p); return status; } + +MODULE_LICENSE("GPL"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/cpqphp_ctrl.c linux-2.4.28-pre3/drivers/hotplug/cpqphp_ctrl.c --- linux-2.4.27/drivers/hotplug/cpqphp_ctrl.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/cpqphp_ctrl.c 2004-09-10 19:33:58.000000000 +0000 @@ -1726,7 +1726,14 @@ static int event_thread(void* data) // New name strcpy(current->comm, "phpd_event"); - + + /* avoid getting signals */ + spin_lock_irq(¤t->sigmask_lock); + flush_signals(current); + sigfillset(¤t->blocked); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + unlock_kernel(); while (1) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/ibmphp_res.c linux-2.4.28-pre3/drivers/hotplug/ibmphp_res.c --- linux-2.4.27/drivers/hotplug/ibmphp_res.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/ibmphp_res.c 2004-09-10 19:37:02.000000000 +0000 @@ -42,7 +42,7 @@ static int remove_ranges (struct bus_nod static int update_bridge_ranges (struct bus_node **); static int add_range (int type, struct range_node *, struct bus_node *); static void fix_resources (struct bus_node *); -static inline struct bus_node *find_bus_wprev (u8, struct bus_node **, u8); +static struct bus_node *find_bus_wprev (u8, struct bus_node **, u8); static LIST_HEAD(gbuses); LIST_HEAD(ibmphp_res_head); @@ -1757,7 +1757,7 @@ struct bus_node *ibmphp_find_res_bus (u8 return find_bus_wprev (bus_number, NULL, 0); } -static inline struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag) +static struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag) { struct bus_node *bus_cur; struct list_head *tmp; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehp.h linux-2.4.28-pre3/drivers/hotplug/pciehp.h --- linux-2.4.27/drivers/hotplug/pciehp.h 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/pciehp.h 2004-09-10 19:37:20.000000000 +0000 @@ -45,8 +45,6 @@ extern int pciehp_poll_mode; extern int pciehp_poll_time; extern int pciehp_debug; -extern int pciehp_msi_quirk; - /*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ #define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehp_ctrl.c linux-2.4.28-pre3/drivers/hotplug/pciehp_ctrl.c --- linux-2.4.27/drivers/hotplug/pciehp_ctrl.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/pciehp_ctrl.c 2004-09-10 19:32:47.000000000 +0000 @@ -1053,6 +1053,34 @@ static int is_bridge(struct pci_func * f hotplug controller logic */ +static void set_slot_off(struct controller *ctrl, struct slot * pslot) +{ + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* turn off slot, turn on Amber LED, turn off Green LED */ + if (pslot->hpc_ops->power_off_slot(pslot)) { + err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return; + } + wait_for_ctrl_irq (ctrl); + + pslot->hpc_ops->green_led_off(pslot); + + wait_for_ctrl_irq (ctrl); + + /* turn on Amber LED */ + if (pslot->hpc_ops->set_attention_status(pslot, 1)) { + err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return; + } + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); +} /** * board_added - Called after a board has been added to the system. @@ -1066,7 +1094,7 @@ static u32 board_added(struct pci_func * u8 hp_slot; int index; u32 temp_register = 0xFFFFFFFF; - u32 retval, rc = 0; + u32 rc = 0; struct pci_func *new_func = NULL; struct slot *p_slot; struct resource_lists res_lists; @@ -1082,8 +1110,10 @@ static u32 board_added(struct pci_func * /* Power on slot */ rc = p_slot->hpc_ops->power_on_slot(p_slot); - if (rc) + if (rc) { + up(&ctrl->crit_sect); return -1; + } /* Wait for the command to complete */ wait_for_ctrl_irq(ctrl); @@ -1105,10 +1135,11 @@ static u32 board_added(struct pci_func * dbg("%s: afterlong_delay\n", __FUNCTION__); dbg("%s: before check link status", __FUNCTION__); - /* Make this to check for link training status */ + /* Check link training status */ rc = p_slot->hpc_ops->check_lnk_status(ctrl); if (rc) { err("%s: Failed to check link status\n", __FUNCTION__); + set_slot_off(ctrl, p_slot); return -1; } @@ -1161,36 +1192,7 @@ static u32 board_added(struct pci_func * pciehp_resource_sort_and_combine(&(ctrl->bus_head)); if (rc) { - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - /* Turn off slot, turn on Amber LED, turn off Green LED */ - retval = p_slot->hpc_ops->power_off_slot(p_slot); - /* In PCI Express, just power off slot */ - if (retval) { - err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); - return retval; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq(ctrl); - - p_slot->hpc_ops->green_led_off(p_slot); - - /* Wait for the command to complete */ - wait_for_ctrl_irq(ctrl); - - /* Turn on Amber LED */ - retval = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (retval) { - err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); - return retval; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq(ctrl); - - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - + set_slot_off(ctrl, p_slot); return(rc); } pciehp_save_slot_config(ctrl, func); @@ -1220,42 +1222,12 @@ static u32 board_added(struct pci_func * /* Wait for the command to complete */ wait_for_ctrl_irq(ctrl); - /* Done with exclusive hardware access */ up(&ctrl->crit_sect); } else { - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - /* Turn off slot, turn on Amber LED, turn off Green LED */ - retval = p_slot->hpc_ops->power_off_slot(p_slot); - /* In PCI Express, just power off slot */ - if (retval) { - err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); - return retval; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq(ctrl); - - p_slot->hpc_ops->green_led_off(p_slot); - - /* Wait for the command to complete */ - wait_for_ctrl_irq(ctrl); - - /* Turn on Amber LED */ - retval = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (retval) { - err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); - return retval; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq(ctrl); - - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - - return(rc); + set_slot_off(ctrl, p_slot); + return -1; } return 0; } @@ -1323,6 +1295,7 @@ static u32 remove_board(struct pci_func rc = p_slot->hpc_ops->power_off_slot(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); return rc; } /* Wait for the command to complete */ @@ -1592,7 +1565,10 @@ static void interrupt_event_handler(stru down(&ctrl->crit_sect); p_slot->hpc_ops->set_attention_status(p_slot, 1); + wait_for_ctrl_irq(ctrl); + p_slot->hpc_ops->green_led_off(p_slot); + wait_for_ctrl_irq(ctrl); /* Done with exclusive hardware access */ up(&ctrl->crit_sect); @@ -1624,7 +1600,6 @@ void pciehp_pushbutton_thread (unsigned { struct slot *p_slot = (struct slot *) slot; u8 getstatus; - int rc; pushbutton_pending = 0; @@ -1638,23 +1613,7 @@ void pciehp_pushbutton_thread (unsigned p_slot->state = POWEROFF_STATE; dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); - if (pciehp_disable_slot(p_slot)) { - /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); - - /* Turn on the Attention LED */ - rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (rc) { - err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__); - return; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq (p_slot->ctrl); - - /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); - } + pciehp_disable_slot(p_slot); p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; @@ -1664,15 +1623,6 @@ void pciehp_pushbutton_thread (unsigned /* Wait for exclusive access to hardware */ down(&p_slot->ctrl->crit_sect); - /* Turn off the green LED */ - rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (rc) { - err("%s: Issue of Set Attn Indicator On command failed\n", __FUNCTION__); - return; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq (p_slot->ctrl); - p_slot->hpc_ops->green_led_off(p_slot); /* Wait for the command to complete */ @@ -1706,21 +1656,21 @@ int pciehp_enable_slot (struct slot *p_s if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } up(&p_slot->ctrl->crit_sect); @@ -1793,21 +1743,21 @@ int pciehp_disable_slot (struct slot *p_ if (ret || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } up(&p_slot->ctrl->crit_sect); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehp_hpc.c linux-2.4.28-pre3/drivers/hotplug/pciehp_hpc.c --- linux-2.4.27/drivers/hotplug/pciehp_hpc.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/pciehp_hpc.c 2004-09-10 19:34:15.000000000 +0000 @@ -346,10 +346,11 @@ static int hpc_check_lnk_status(struct c return retval; } - if ( (lnk_status & (LNK_TRN | LNK_TRN_ERR)) == 0x0C00) { + dbg("%s: lnk_status = %x\n", __FUNCTION__, lnk_status); + if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) || + !(lnk_status & NEG_LINK_WD)) { err("%s : Link Training Error occurs \n", __FUNCTION__); - retval = -1; - return retval; + return -1; } DBG_LEAVE_ROUTINE @@ -911,7 +912,6 @@ static void pcie_isr(int IRQ, void *dev_ err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return; } - /* dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); */ intr_detect = ( ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | CMD_COMPLETED ); @@ -932,8 +932,6 @@ static void pcie_isr(int IRQ, void *dev_ return; } - dbg("%s: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__); - dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word); @@ -941,14 +939,12 @@ static void pcie_isr(int IRQ, void *dev_ err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); return; } - dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); if (rc) { err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return; } - dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); /* Clear command complete interrupt caused by this write */ temp_word = 0x1f; @@ -957,7 +953,6 @@ static void pcie_isr(int IRQ, void *dev_ err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); return; } - dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); } if (intr_loc & CMD_COMPLETED) { @@ -995,8 +990,6 @@ static void pcie_isr(int IRQ, void *dev_ err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return; } - dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__); - dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word); @@ -1004,14 +997,12 @@ static void pcie_isr(int IRQ, void *dev_ err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); return; } - dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); if (rc) { err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return; } - dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); /* Clear command complete interrupt caused by this write */ temp_word = 0x1F; @@ -1020,7 +1011,6 @@ static void pcie_isr(int IRQ, void *dev_ err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); return; } - dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); } return; } @@ -1409,17 +1399,6 @@ int pcie_init(struct controller * ctrl, start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ } else { /* Installs the interrupt handler */ -#ifdef CONFIG_PCI_USE_VECTOR - if (!pciehp_msi_quirk) { - rc = pci_enable_msi(pdev); - if (rc) { - info("Can't get msi for the hotplug controller\n"); - info("Use INTx for the hotplug controller\n"); - dbg("%s: rc = %x\n", __FUNCTION__, rc); - } else - php_ctlr->irq = pdev->irq; - } -#endif rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl); dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); if (rc) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehp_pci.c linux-2.4.28-pre3/drivers/hotplug/pciehp_pci.c --- linux-2.4.27/drivers/hotplug/pciehp_pci.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/pciehp_pci.c 2004-09-10 19:35:56.000000000 +0000 @@ -117,9 +117,7 @@ static int configure_visit_pci_dev (stru temp_func->pci_dev->bus->number, temp_func->pci_dev->devfn); dbg("%s: PCI_SLOT_NAME=%s\n", __FUNCTION__, temp_func->pci_dev->slot_name); - //pci_enable_device(temp_func->pci_dev); - //dbg("%s: after calling pci_enable_device, irq = %x\n", - // __FUNCTION__, temp_func->pci_dev->irq); + pci_enable_device(temp_func->pci_dev); pci_proc_attach_device(temp_func->pci_dev); pci_announce_device_to_drivers(temp_func->pci_dev); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehprm_acpi.c linux-2.4.28-pre3/drivers/hotplug/pciehprm_acpi.c --- linux-2.4.27/drivers/hotplug/pciehprm_acpi.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/pciehprm_acpi.c 2004-09-10 19:36:44.000000000 +0000 @@ -217,6 +217,10 @@ static void acpi_get__hpp ( struct acpi_ } ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL); + if (!ab->_hpp) { + err ("acpi_pciehprm:%s alloc for _HPP failed\n", path_name); + goto free_and_return; + } memset(ab->_hpp, 0, sizeof(struct acpi__hpp)); ab->_hpp->cache_line_size = nui[0]; @@ -1392,7 +1396,7 @@ static int configure_existing_function( static int bind_pci_resources_to_slots ( struct controller *ctrl) { - struct pci_func *func; + struct pci_func *func, new_func; int busn = ctrl->slot_bus; int devn, funn; u32 vid; @@ -1411,11 +1415,19 @@ static int bind_pci_resources_to_slots ( if (vid != 0xFFFFFFFF) { dbg("%s: vid = %x\n", __FUNCTION__, vid); func = pciehp_slot_find(busn, devn, funn); - if (!func) - continue; - configure_existing_function(ctrl, func); + if (!func) { + memset(&new_func, 0, sizeof(struct pci_func)); + new_func.bus = busn; + new_func.device = devn; + new_func.function = funn; + new_func.is_a_board = 1; + configure_existing_function(ctrl, &new_func); + pciehprm_dump_func_res(&new_func); + } else { + configure_existing_function(ctrl, func); + pciehprm_dump_func_res(func); + } dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); - pciehprm_dump_func_res(func); } } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehprm_nonacpi.c linux-2.4.28-pre3/drivers/hotplug/pciehprm_nonacpi.c --- linux-2.4.27/drivers/hotplug/pciehprm_nonacpi.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/pciehprm_nonacpi.c 2004-09-10 19:32:27.000000000 +0000 @@ -281,7 +281,7 @@ static int pciehprm_delete_resource( static int bind_pci_resources_to_slots ( struct controller *ctrl) { - struct pci_func *func; + struct pci_func *func, new_func; int busn = ctrl->slot_bus; int devn, funn; u32 vid; @@ -301,11 +301,19 @@ static int bind_pci_resources_to_slots ( vid, busn, devn, funn); func = pciehp_slot_find(busn, devn, funn); dbg("%s: func = %p\n", __FUNCTION__,func); - if (!func) - continue; - configure_existing_function(ctrl, func); + if (!func) { + memset(&new_func, 0, sizeof(struct pci_func)); + new_func.bus = busn; + new_func.device = devn; + new_func.function = funn; + new_func.is_a_board = 1; + configure_existing_function(ctrl, &new_func); + phprm_dump_func_res(&new_func); + } else { + configure_existing_function(ctrl, func); + phprm_dump_func_res(func); + } dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); - phprm_dump_func_res(func); } } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchp.h linux-2.4.28-pre3/drivers/hotplug/shpchp.h --- linux-2.4.27/drivers/hotplug/shpchp.h 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/shpchp.h 2004-09-10 19:34:01.000000000 +0000 @@ -61,6 +61,7 @@ struct pci_func { u8 configured; u8 switch_save; u8 presence_save; + u8 pwr_save; u32 base_length[0x06]; u8 base_type[0x06]; u16 reserved2; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchp_ctrl.c linux-2.4.28-pre3/drivers/hotplug/shpchp_ctrl.c --- linux-2.4.27/drivers/hotplug/shpchp_ctrl.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/shpchp_ctrl.c 2004-09-10 19:37:00.000000000 +0000 @@ -137,6 +137,8 @@ u8 shpchp_handle_switch_change(u8 hp_slo p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + dbg("%s: Card present %x Power status %x\n", __FUNCTION__, + func->presence_save, func->pwr_save); if (getstatus) { /* @@ -145,6 +147,10 @@ u8 shpchp_handle_switch_change(u8 hp_slo info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); func->switch_save = 0; taskInfo->event_type = INT_SWITCH_OPEN; + if (func->pwr_save && func->presence_save) { + taskInfo->event_type = INT_POWER_FAULT; + err("Surprise Removal of card\n"); + } } else { /* * Switch closed @@ -1431,6 +1437,7 @@ static u32 board_added(struct pci_func * rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, adapter_speed); if (rc) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } @@ -1442,6 +1449,7 @@ static u32 board_added(struct pci_func * err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", __FUNCTION__); err("%s: Error code (%d)\n", __FUNCTION__, rc); + up(&ctrl->crit_sect); return WRONG_BUS_FREQUENCY; } /* Done with exclusive hardware access */ @@ -1592,7 +1600,8 @@ static u32 board_added(struct pci_func * func->status = 0; func->switch_save = 0x10; func->is_a_board = 0x01; - + func->pwr_save = 1; + /* Next, we will instantiate the linux pci_dev structures * (with appropriate driver notification, if already present) */ @@ -1785,6 +1794,7 @@ static u32 remove_board(struct pci_func func->function = 0; func->configured = 0; func->switch_save = 0x10; + func->pwr_save = 0; func->is_a_board = 0; } @@ -2038,7 +2048,6 @@ void shpchp_pushbutton_thread (unsigned { struct slot *p_slot = (struct slot *) slot; u8 getstatus; - int rc; pushbutton_pending = 0; @@ -2052,23 +2061,7 @@ void shpchp_pushbutton_thread (unsigned p_slot->state = POWEROFF_STATE; dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); - if (shpchp_disable_slot(p_slot)) { - /* Wait for exclusive access to hardware */ - down(&p_slot->ctrl->crit_sect); - - /* Turn on the Attention LED */ - rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (rc) { - err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__); - return; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq(p_slot->ctrl); - - /* Done with exclusive hardware access */ - up(&p_slot->ctrl->crit_sect); - } + shpchp_disable_slot(p_slot); p_slot->state = STATIC_STATE; } else { p_slot->state = POWERON_STATE; @@ -2078,15 +2071,6 @@ void shpchp_pushbutton_thread (unsigned /* Wait for exclusive access to hardware */ down(&p_slot->ctrl->crit_sect); - /* Turn off the green LED */ - rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); - if (rc) { - err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__); - return; - } - /* Wait for the command to complete */ - wait_for_ctrl_irq(p_slot->ctrl); - p_slot->hpc_ops->green_led_off(p_slot); /* Wait for the command to complete */ @@ -2120,19 +2104,19 @@ int shpchp_enable_slot (struct slot *p_s if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } up(&p_slot->ctrl->crit_sect); @@ -2150,6 +2134,8 @@ int shpchp_enable_slot (struct slot *p_s /* We have to save the presence info for these slots */ p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_power_status(p_slot, &(func->pwr_save)); + dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); func->switch_save = !getstatus? 0x10:0; @@ -2205,19 +2191,19 @@ int shpchp_disable_slot (struct slot *p_ if (ret || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); - return (0); + return (1); } up(&p_slot->ctrl->crit_sect); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchp_hpc.c linux-2.4.28-pre3/drivers/hotplug/shpchp_hpc.c --- linux-2.4.27/drivers/hotplug/shpchp_hpc.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/shpchp_hpc.c 2004-09-10 19:34:33.000000000 +0000 @@ -1547,15 +1547,6 @@ int shpc_init(struct controller * ctrl, start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ } else { /* Installs the interrupt handler */ -#ifdef CONFIG_PCI_USE_VECTOR - rc = pci_enable_msi(pdev); - if (rc) { - info("Can't get msi for the hotplug controller\n"); - info("Use INTx for the hotplug controller\n"); - dbg("%s: rc = %x\n", __FUNCTION__, rc); - } else - php_ctlr->irq = pdev->irq; -#endif rc = request_irq(php_ctlr->irq, shpc_isr, SA_SHIRQ, MY_NAME, (void *) ctrl); dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); @@ -1563,7 +1554,6 @@ int shpc_init(struct controller * ctrl, err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq); goto abort_free_ctlr; } - /* Execute OSHP method here */ } dbg("%s: Before adding HPC to HPC list\n", __FUNCTION__); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchp_pci.c linux-2.4.28-pre3/drivers/hotplug/shpchp_pci.c --- linux-2.4.27/drivers/hotplug/shpchp_pci.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/shpchp_pci.c 2004-09-10 19:33:11.000000000 +0000 @@ -481,6 +481,7 @@ int shpchp_save_config(struct controller new_slot->function = (u8) function; new_slot->is_a_board = 1; new_slot->switch_save = 0x10; + new_slot->pwr_save = 1; /* In case of unsupported board */ new_slot->status = DevError; new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchprm_acpi.c linux-2.4.28-pre3/drivers/hotplug/shpchprm_acpi.c --- linux-2.4.27/drivers/hotplug/shpchprm_acpi.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/shpchprm_acpi.c 2004-09-10 19:37:30.000000000 +0000 @@ -217,6 +217,10 @@ static void acpi_get__hpp ( struct acpi_ } ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL); + if (!ab->_hpp) { + err ("acpi_shpchprm:%s alloc for _HPP failed\n", path_name); + goto free_and_return; + } memset(ab->_hpp, 0, sizeof(struct acpi__hpp)); ab->_hpp->cache_line_size = nui[0]; @@ -1387,7 +1391,7 @@ static int configure_existing_function( static int bind_pci_resources_to_slots ( struct controller *ctrl) { - struct pci_func *func; + struct pci_func *func, new_func; int busn = ctrl->bus; int devn, funn; u32 vid; @@ -1402,11 +1406,19 @@ static int bind_pci_resources_to_slots ( if (vid != 0xFFFFFFFF) { func = shpchp_slot_find(busn, devn, funn); - if (!func) - continue; - configure_existing_function(ctrl, func); + if (!func) { + memset(&new_func, 0, sizeof(struct pci_func)); + new_func.bus = busn; + new_func.device = devn; + new_func.function = funn; + new_func.is_a_board = 1; + configure_existing_function(ctrl, &new_func); + shpchprm_dump_func_res(&new_func); + } else { + configure_existing_function(ctrl, func); + shpchprm_dump_func_res(func); + } dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); - shpchprm_dump_func_res(func); } } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchprm_nonacpi.c linux-2.4.28-pre3/drivers/hotplug/shpchprm_nonacpi.c --- linux-2.4.27/drivers/hotplug/shpchprm_nonacpi.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/hotplug/shpchprm_nonacpi.c 2004-09-10 19:35:00.000000000 +0000 @@ -213,7 +213,7 @@ static int configure_existing_function( static int bind_pci_resources_to_slots ( struct controller *ctrl) { - struct pci_func *func; + struct pci_func *func, new_func; int busn = ctrl->slot_bus; int devn, funn; u32 vid; @@ -230,11 +230,19 @@ static int bind_pci_resources_to_slots ( if (vid != 0xFFFFFFFF) { func = shpchp_slot_find(busn, devn, funn); - if (!func) - continue; - configure_existing_function(ctrl, func); + if (!func) { + memset(&new_func, 0, sizeof(struct pci_func)); + new_func.bus = busn; + new_func.device = devn; + new_func.function = funn; + new_func.is_a_board = 1; + configure_existing_function(ctrl, &new_func); + phprm_dump_func_res(&new_func); + } else { + configure_existing_function(ctrl, func); + phprm_dump_func_res(func); + } dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); - phprm_dump_func_res(func); } } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/Config.in linux-2.4.28-pre3/drivers/ide/Config.in --- linux-2.4.27/drivers/ide/Config.in 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/ide/Config.in 2004-09-10 19:36:49.000000000 +0000 @@ -12,6 +12,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; the dep_bool ' Use old disk-only driver on primary interface' CONFIG_BLK_DEV_HD_IDE $CONFIG_X86 define_bool CONFIG_BLK_DEV_HD $CONFIG_BLK_DEV_HD_IDE + dep_mbool ' Support for SATA (deprecated; conflicts with libata SATA driver)' CONFIG_BLK_DEV_IDE_SATA $CONFIG_BLK_DEV_IDE dep_tristate ' Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE dep_mbool ' Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE $CONFIG_BLK_DEV_IDEDISK dep_mbool ' Auto-Geometry Resizing support' CONFIG_IDEDISK_STROKE $CONFIG_BLK_DEV_IDEDISK diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/amd74xx.c linux-2.4.28-pre3/drivers/ide/pci/amd74xx.c --- linux-2.4.27/drivers/ide/pci/amd74xx.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/ide/pci/amd74xx.c 2004-09-10 19:35:20.000000000 +0000 @@ -70,11 +70,7 @@ static struct amd_ide_chip { { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, AMD_UDMA_133 }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA, 0x50, AMD_UDMA_133 }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA, 0x50, AMD_UDMA_133 }, - { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, 0x50, AMD_UDMA_133 }, { 0 } }; @@ -466,17 +462,17 @@ static struct pci_device_id amd74xx_pci_ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 }, +#ifdef CONFIG_BLK_DEV_IDE_SATA { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, +#endif { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 }, +#ifdef CONFIG_BLK_DEV_IDE_SATA { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 }, +#endif { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, { 0, }, }; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/amd74xx.h linux-2.4.28-pre3/drivers/ide/pci/amd74xx.h --- linux-2.4.27/drivers/ide/pci/amd74xx.h 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/ide/pci/amd74xx.h 2004-09-10 19:36:48.000000000 +0000 @@ -188,28 +188,6 @@ static ide_pci_device_t amd74xx_chipsets }, { /* 14 */ .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA, - .name = "NFORCE-CK804-SATA", - .init_chipset = init_chipset_amd74xx, - .init_hwif = init_hwif_amd74xx, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, - .bootable = ON_BOARD, - }, - { /* 15 */ - .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, - .name = "NFORCE-CK804-SATA2", - .init_chipset = init_chipset_amd74xx, - .init_hwif = init_hwif_amd74xx, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, - .bootable = ON_BOARD, - }, - { /* 16 */ - .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, .name = "NFORCE-MCP04", .init_chipset = init_chipset_amd74xx, @@ -219,28 +197,6 @@ static ide_pci_device_t amd74xx_chipsets .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, .bootable = ON_BOARD, }, - { /* 17 */ - .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA, - .name = "NFORCE-MCP04-SATA", - .init_chipset = init_chipset_amd74xx, - .init_hwif = init_hwif_amd74xx, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, - .bootable = ON_BOARD, - }, - { /* 18 */ - .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, - .name = "NFORCE-MCP04-SATA2", - .init_chipset = init_chipset_amd74xx, - .init_hwif = init_hwif_amd74xx, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, - .bootable = ON_BOARD, - }, { .vendor = 0, .device = 0, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/piix.c linux-2.4.28-pre3/drivers/ide/pci/piix.c --- linux-2.4.27/drivers/ide/pci/piix.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/ide/pci/piix.c 2004-09-10 19:36:56.000000000 +0000 @@ -49,9 +49,9 @@ * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, ®40); * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, ®42); * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, ®44); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, ®48); + * pci_read_config_byte(HWIF(drive)->pci_dev, 0x48, ®48); * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, ®4a); - * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, ®54); + * pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, ®54); * * Documentation * Publically available from Intel web site. Errata documentation @@ -433,15 +433,14 @@ static int piix_tune_chipset (ide_drive_ int w_flag = 0x10 << drive->dn; int u_speed = 0; int sitre; - u16 reg4042, reg44, reg48, reg4a, reg54; - u8 reg55; + u16 reg4042, reg4a; + u8 reg48, reg54, reg55; pci_read_config_word(dev, maslave, ®4042); sitre = (reg4042 & 0x4000) ? 1 : 0; - pci_read_config_word(dev, 0x44, ®44); - pci_read_config_word(dev, 0x48, ®48); + pci_read_config_byte(dev, 0x48, ®48); pci_read_config_word(dev, 0x4a, ®4a); - pci_read_config_word(dev, 0x54, ®54); + pci_read_config_byte(dev, 0x54, ®54); pci_read_config_byte(dev, 0x55, ®55); switch(speed) { @@ -463,30 +462,26 @@ static int piix_tune_chipset (ide_drive_ if (speed >= XFER_UDMA_0) { if (!(reg48 & u_flag)) - pci_write_config_word(dev, 0x48, reg48|u_flag); + pci_write_config_byte(dev, 0x48, reg48 | u_flag); if (speed == XFER_UDMA_5) { pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); } else { pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); } - if (!(reg4a & u_speed)) { - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - pci_write_config_word(dev, 0x4a, reg4a|u_speed); - } + if ((reg4a & a_speed) != u_speed) + pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); if (speed > XFER_UDMA_2) { - if (!(reg54 & v_flag)) { - pci_write_config_word(dev, 0x54, reg54|v_flag); - } - } else { - pci_write_config_word(dev, 0x54, reg54 & ~v_flag); - } + if (!(reg54 & v_flag)) + pci_write_config_byte(dev, 0x54, reg54 | v_flag); + } else + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); } else { if (reg48 & u_flag) - pci_write_config_word(dev, 0x48, reg48 & ~u_flag); + pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); if (reg4a & a_speed) pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); if (reg54 & v_flag) - pci_write_config_word(dev, 0x54, reg54 & ~v_flag); + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); if (reg55 & w_flag) pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); } @@ -882,7 +877,9 @@ static struct pci_device_id piix_pci_tbl { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17}, +#ifdef CONFIG_BLK_DEV_IDE_SATA { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18}, +#endif { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20}, { 0, }, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/sc1200.c linux-2.4.28-pre3/drivers/ide/pci/sc1200.c --- linux-2.4.27/drivers/ide/pci/sc1200.c 2003-06-13 14:51:33.000000000 +0000 +++ linux-2.4.28-pre3/drivers/ide/pci/sc1200.c 2004-09-10 19:35:31.000000000 +0000 @@ -418,7 +418,7 @@ printk("SC1200: save_state(%u)\n", state ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL); if (ss == NULL) return -ENOMEM; - (sc1200_saved_state_t *)hwif->config_data = ss; + hwif->config_data = (unsigned long)ss; } ss = (sc1200_saved_state_t *)hwif->config_data; // diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/siimage.c linux-2.4.28-pre3/drivers/ide/pci/siimage.c --- linux-2.4.27/drivers/ide/pci/siimage.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/ide/pci/siimage.c 2004-09-10 19:36:30.000000000 +0000 @@ -1194,8 +1194,10 @@ static int __devinit siimage_init_one(st static struct pci_device_id siimage_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#ifdef CONFIG_BLK_DEV_IDE_SATA { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, +#endif { 0, }, }; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/triflex.c linux-2.4.28-pre3/drivers/ide/pci/triflex.c --- linux-2.4.27/drivers/ide/pci/triflex.c 2003-06-13 14:51:33.000000000 +0000 +++ linux-2.4.28-pre3/drivers/ide/pci/triflex.c 2004-09-10 19:34:15.000000000 +0000 @@ -44,15 +44,17 @@ #include "ide_modes.h" #include "triflex.h" -static struct pci_dev *triflex_dev; +#ifdef CONFIG_PROC_FS +static u8 triflex_proc; -static int triflex_get_info(char *buf, char **addr, off_t offset, int count) -{ - char *p = buf; - int len; +#define TRIFLEX_MAX_DEVS 2 +static struct pci_dev *triflex_devs[TRIFLEX_MAX_DEVS]; +static unsigned int n_triflex_devs; - struct pci_dev *dev = triflex_dev; +static int triflex_info(char *buffer, struct pci_dev *dev) +{ unsigned long bibma = pci_resource_start(dev, 4); + char *p = buffer; u8 c0 = 0, c1 = 0; u32 pri_timing, sec_timing; @@ -87,11 +89,23 @@ static int triflex_get_info(char *buf, c p += sprintf(p, "DMA\n"); p += sprintf(p, "PIO\n"); + return p - buffer; +} + +static int triflex_get_info(char *buf, char **addr, off_t offset, int count) +{ + char *p = buf; + unsigned int i, len; + + for (i = 0; i < n_triflex_devs; i++) + buf += triflex_info(buf, triflex_devs[i]); + len = (p - buf) - offset; *addr = buf + offset; - + return len > count ? count : len; } +#endif static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed) { @@ -211,9 +225,13 @@ static unsigned int __init init_chipset_ const char *name) { #ifdef CONFIG_PROC_FS - ide_pci_register_host_proc(&triflex_proc); + triflex_devs[n_triflex_devs++] = dev; + if (!triflex_proc) { + triflex_proc = 1; + ide_pci_register_host_proc(&triflex_procs); + } #endif - return 0; + return 0; } static int __devinit triflex_init_one(struct pci_dev *dev, @@ -222,11 +240,10 @@ static int __devinit triflex_init_one(st ide_pci_device_t *d = &triflex_devices[id->driver_data]; if (dev->device != d->device) BUG(); - + ide_setup_pci_device(dev, d); - triflex_dev = dev; MOD_INC_USE_COUNT; - + return 0; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/triflex.h linux-2.4.28-pre3/drivers/ide/pci/triflex.h --- linux-2.4.27/drivers/ide/pci/triflex.h 2003-06-13 14:51:33.000000000 +0000 +++ linux-2.4.28-pre3/drivers/ide/pci/triflex.h 2004-09-10 19:35:32.000000000 +0000 @@ -14,7 +14,6 @@ static unsigned int __devinit init_chipset_triflex(struct pci_dev *, const char *); static void init_hwif_triflex(ide_hwif_t *); -static int triflex_get_info(char *, char **, off_t, int); static ide_pci_device_t triflex_devices[] __devinitdata = { { @@ -34,7 +33,9 @@ static ide_pci_device_t triflex_devices[ }; #ifdef CONFIG_PROC_FS -static ide_pci_host_proc_t triflex_proc __initdata = { +static int triflex_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t triflex_procs __initdata = { .name = "triflex", .set = 1, .get_info = triflex_get_info, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ieee1394/eth1394.c linux-2.4.28-pre3/drivers/ieee1394/eth1394.c --- linux-2.4.27/drivers/ieee1394/eth1394.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/ieee1394/eth1394.c 2004-09-10 19:36:19.000000000 +0000 @@ -149,6 +149,20 @@ MODULE_PARM_DESC(max_partial_datagrams, "(default = 25)."); static int max_partial_datagrams = 25; +static inline void purge_partial_datagram(struct list_head *old) +{ + struct partial_datagram *pd = list_entry(old, struct partial_datagram, list); + struct list_head *lh, *n; + + list_for_each_safe(lh, n, &pd->frag_info) { + struct fragment_info *fi = list_entry(lh, struct fragment_info, list); + list_del(lh); + kfree(fi); + } + list_del(old); + kfree_skb(pd->skb); + kfree(pd); +} static int ether1394_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, @@ -885,21 +899,6 @@ static inline int update_partial_datagra return 0; } -static inline void purge_partial_datagram(struct list_head *old) -{ - struct partial_datagram *pd = list_entry(old, struct partial_datagram, list); - struct list_head *lh, *n; - - list_for_each_safe(lh, n, &pd->frag_info) { - struct fragment_info *fi = list_entry(lh, struct fragment_info, list); - list_del(lh); - kfree(fi); - } - list_del(old); - kfree_skb(pd->skb); - kfree(pd); -} - static inline int is_datagram_complete(struct list_head *lh, int dg_size) { struct partial_datagram *pd = list_entry(lh, struct partial_datagram, list); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/divert/divert_procfs.c linux-2.4.28-pre3/drivers/isdn/divert/divert_procfs.c --- linux-2.4.27/drivers/isdn/divert/divert_procfs.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/divert/divert_procfs.c 2004-09-10 19:36:55.000000000 +0000 @@ -92,7 +92,7 @@ isdn_divert_read(struct file *file, char return (0); inf->usage_cnt--; /* new usage count */ - (struct divert_info **) file->private_data = &inf->next; /* next structure */ + file->private_data = &inf->next; /* next structure */ if ((len = strlen(inf->info_start)) <= count) { if (copy_to_user(buf, inf->info_start, len)) return -EFAULT; @@ -141,9 +141,9 @@ isdn_divert_open(struct inode *ino, stru cli(); if_used++; if (divert_info_head) - (struct divert_info **) filep->private_data = &(divert_info_tail->next); + filep->private_data = &(divert_info_tail->next); else - (struct divert_info **) filep->private_data = &divert_info_head; + filep->private_data = &divert_info_head; restore_flags(flags); /* start_divert(); */ unlock_kernel(); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/hisax/callc.c linux-2.4.28-pre3/drivers/isdn/hisax/callc.c --- linux-2.4.27/drivers/isdn/hisax/callc.c 2001-12-21 17:41:54.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/hisax/callc.c 2004-09-10 19:34:58.000000000 +0000 @@ -925,7 +925,7 @@ static void stat_redir_result(struct Isd ic.driver = cs->myid; ic.command = ISDN_STAT_REDIR; ic.arg = chan; - (ulong)(ic.parm.num[0]) = result; + ic.parm.num[0] = result; cs->iif.statcallb(&ic); } /* stat_redir_result */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/hisax/isar.c linux-2.4.28-pre3/drivers/isdn/hisax/isar.c --- linux-2.4.27/drivers/isdn/hisax/isar.c 2003-06-13 14:51:34.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/hisax/isar.c 2004-09-10 19:34:22.000000000 +0000 @@ -428,6 +428,21 @@ reterror: return(ret); } +static inline void +ll_deliver_faxstat(struct BCState *bcs, u_char status) +{ + isdn_ctrl ic; + struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata; + + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "HL->LL FAXIND %x", status); + ic.driver = bcs->cs->myid; + ic.command = ISDN_STAT_FAXIND; + ic.arg = chanp->chan; + ic.parm.aux.cmd = status; + bcs->cs->iif.statcallb(&ic); +} + extern void BChannel_bh(struct BCState *); #define B_LL_NOCARRIER 8 #define B_LL_CONNECT 9 @@ -962,21 +977,6 @@ isar_pump_statev_modem(struct BCState *b } } -static inline void -ll_deliver_faxstat(struct BCState *bcs, u_char status) -{ - isdn_ctrl ic; - struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata; - - if (bcs->cs->debug & L1_DEB_HSCX) - debugl1(bcs->cs, "HL->LL FAXIND %x", status); - ic.driver = bcs->cs->myid; - ic.command = ISDN_STAT_FAXIND; - ic.arg = chanp->chan; - ic.parm.aux.cmd = status; - bcs->cs->iif.statcallb(&ic); -} - static void isar_pump_statev_fax(struct BCState *bcs, u_char devt) { struct IsdnCardState *cs = bcs->cs; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/hisax/st5481.h linux-2.4.28-pre3/drivers/isdn/hisax/st5481.h --- linux-2.4.27/drivers/isdn/hisax/st5481.h 2003-06-13 14:51:34.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/hisax/st5481.h 2004-09-10 19:35:46.000000000 +0000 @@ -219,13 +219,13 @@ enum { #define L1_EVENT_COUNT (EV_TIMER3 + 1) #define ERR(format, arg...) \ -printk(KERN_ERR __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg) +printk(KERN_ERR "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg) #define WARN(format, arg...) \ -printk(KERN_WARNING __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg) +printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg) #define INFO(format, arg...) \ -printk(KERN_INFO __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg) +printk(KERN_INFO "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg) #include "isdnhdlc.h" #include "fsm.h" diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/hysdn/hysdn_procconf.c linux-2.4.28-pre3/drivers/isdn/hysdn/hysdn_procconf.c --- linux-2.4.27/drivers/isdn/hysdn/hysdn_procconf.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/hysdn/hysdn_procconf.c 2004-09-10 19:32:47.000000000 +0000 @@ -219,20 +219,25 @@ hysdn_conf_read(struct file *file, char if (off != &file->f_pos) /* fs error check */ return -ESPIPE; + if (!(file->f_mode & FMODE_READ)) + return -EPERM; + if (!(cp = file->private_data)) return (-EFAULT); /* should never happen */ + i = strlen(cp); /* get total string length */ - if (pos == (unsigned)pos && pos < i) { - /* still bytes to transfer */ - cp += pos; /* point to desired data offset */ - i -= pos; /* remaining length */ - if (i > count) - i = count; /* limit length to transfer */ - if (copy_to_user(buf, cp, i)) - return (-EFAULT); /* copy error */ - *off = pos + i; /* adjust offset */ - } else - return (0); + + if (pos != (unsigned)pos || pos >= i) + return 0; + + /* still bytes to transfer */ + cp += pos; /* point to desired data offset */ + i -= pos; /* remaining length */ + if (i > count) + i = count; /* limit length to transfer */ + if (copy_to_user(buf, cp, i)) + return (-EFAULT); /* copy error */ + *off = pos + i; /* adjust offset */ return (i); } /* hysdn_conf_read */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/callbacks.c linux-2.4.28-pre3/drivers/isdn/pcbit/callbacks.c --- linux-2.4.27/drivers/isdn/pcbit/callbacks.c 2001-09-30 19:26:06.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/pcbit/callbacks.c 2004-09-10 19:37:19.000000000 +0000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 Universidade de Lisboa * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) + * Written by Pedro Roque Marques (pedro_m@yahoo.com) * * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/callbacks.h linux-2.4.28-pre3/drivers/isdn/pcbit/callbacks.h --- linux-2.4.27/drivers/isdn/pcbit/callbacks.h 2001-09-30 19:26:06.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/pcbit/callbacks.h 2004-09-10 19:31:51.000000000 +0000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 Universidade de Lisboa * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) + * Written by Pedro Roque Marques (pedro_m@yahoo.com) * * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/capi.c linux-2.4.28-pre3/drivers/isdn/pcbit/capi.c --- linux-2.4.27/drivers/isdn/pcbit/capi.c 2001-09-30 19:26:06.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/pcbit/capi.c 2004-09-10 19:36:03.000000000 +0000 @@ -4,7 +4,7 @@ * * Copyright (C) 1996 Universidade de Lisboa * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) + * Written by Pedro Roque Marques (pedro_m@yahoo.com) * * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/capi.h linux-2.4.28-pre3/drivers/isdn/pcbit/capi.h --- linux-2.4.27/drivers/isdn/pcbit/capi.h 2002-08-03 00:39:44.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/pcbit/capi.h 2004-09-10 19:36:50.000000000 +0000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 Universidade de Lisboa * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) + * Written by Pedro Roque Marques (pedro_m@yahoo.com) * * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/drv.c linux-2.4.28-pre3/drivers/isdn/pcbit/drv.c --- linux-2.4.27/drivers/isdn/pcbit/drv.c 2002-11-28 23:53:13.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/pcbit/drv.c 2004-09-10 19:36:02.000000000 +0000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 Universidade de Lisboa * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) + * Written by Pedro Roque Marques (pedro_m@yahoo.com) * * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/edss1.c linux-2.4.28-pre3/drivers/isdn/pcbit/edss1.c --- linux-2.4.27/drivers/isdn/pcbit/edss1.c 2001-09-30 19:26:06.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/pcbit/edss1.c 2004-09-10 19:32:27.000000000 +0000 @@ -4,7 +4,7 @@ * * Copyright (C) 1996 Universidade de Lisboa * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) + * Written by Pedro Roque Marques (pedro_m@yahoo.com) * * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/edss1.h linux-2.4.28-pre3/drivers/isdn/pcbit/edss1.h --- linux-2.4.27/drivers/isdn/pcbit/edss1.h 2001-09-30 19:26:06.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/pcbit/edss1.h 2004-09-10 19:33:22.000000000 +0000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 Universidade de Lisboa * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) + * Written by Pedro Roque Marques (pedro_m@yahoo.com) * * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/layer2.c linux-2.4.28-pre3/drivers/isdn/pcbit/layer2.c --- linux-2.4.27/drivers/isdn/pcbit/layer2.c 2001-09-30 19:26:06.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/pcbit/layer2.c 2004-09-10 19:36:06.000000000 +0000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 Universidade de Lisboa * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) + * Written by Pedro Roque Marques (pedro_m@yahoo.com) * * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/layer2.h linux-2.4.28-pre3/drivers/isdn/pcbit/layer2.h --- linux-2.4.27/drivers/isdn/pcbit/layer2.h 2001-09-30 19:26:06.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/pcbit/layer2.h 2004-09-10 19:32:40.000000000 +0000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 Universidade de Lisboa * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) + * Written by Pedro Roque Marques (pedro_m@yahoo.com) * * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/module.c linux-2.4.28-pre3/drivers/isdn/pcbit/module.c --- linux-2.4.27/drivers/isdn/pcbit/module.c 2001-09-30 19:26:06.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/pcbit/module.c 2004-09-10 19:35:42.000000000 +0000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 Universidade de Lisboa * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) + * Written by Pedro Roque Marques (pedro_m@yahoo.com) * * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/pcbit.h linux-2.4.28-pre3/drivers/isdn/pcbit/pcbit.h --- linux-2.4.27/drivers/isdn/pcbit/pcbit.h 2001-09-30 19:26:06.000000000 +0000 +++ linux-2.4.28-pre3/drivers/isdn/pcbit/pcbit.h 2004-09-10 19:32:38.000000000 +0000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 Universidade de Lisboa * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) + * Written by Pedro Roque Marques (pedro_m@yahoo.com) * * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/md/lvm.c linux-2.4.28-pre3/drivers/md/lvm.c --- linux-2.4.27/drivers/md/lvm.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/md/lvm.c 2004-09-10 19:35:28.000000000 +0000 @@ -2689,6 +2689,10 @@ static int lvm_do_lv_status_byname(vg_t (&lv_status_byname_req.lv->lv_current_pe, &saved_ptr1, sizeof(void *)) != 0) return -EFAULT; + if (copy_to_user + (&lv_status_byname_req.lv->lv_block_exception, + &saved_ptr2, sizeof(void *)) != 0) + return -EFAULT; return 0; } } @@ -2743,6 +2747,10 @@ static int lvm_do_lv_status_byindex(vg_t (&lv_status_byindex_req.lv->lv_current_pe, &saved_ptr1, sizeof(void *)) != 0) return -EFAULT; + if (copy_to_user + (&lv_status_byindex_req.lv->lv_block_exception, &saved_ptr2, + sizeof(void *)) != 0) + return -EFAULT; return 0; } /* lvm_do_lv_status_byindex() */ @@ -2801,6 +2809,10 @@ static int lvm_do_lv_status_bydev(vg_t * (&lv_status_bydev_req.lv->lv_current_pe, &saved_ptr1, sizeof(void *)) != 0) return -EFAULT; + if (copy_to_user + (&lv_status_bydev_req.lv->lv_block_exception, &saved_ptr2, + sizeof(void *)) != 0) + return -EFAULT; return 0; } /* lvm_do_lv_status_bydev() */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/media/radio/radio-maestro.c linux-2.4.28-pre3/drivers/media/radio/radio-maestro.c --- linux-2.4.27/drivers/media/radio/radio-maestro.c 2001-09-30 19:26:06.000000000 +0000 +++ linux-2.4.28-pre3/drivers/media/radio/radio-maestro.c 2004-09-10 19:35:29.000000000 +0000 @@ -307,30 +307,6 @@ void __exit maestro_radio_exit(void) video_unregister_device(&maestro_radio); } -int __init maestro_radio_init(void) -{ - register __u16 found=0; - struct pci_dev *pcidev = NULL; - if(!pci_present()) - return -ENODEV; - while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS, - PCI_DEVICE_ID_ESS_ESS1968, - pcidev))) - found |= radio_install(pcidev); - while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS, - PCI_DEVICE_ID_ESS_ESS1978, - pcidev))) - found |= radio_install(pcidev); - if(!found) { - printk(KERN_INFO "radio-maestro: no devices found.\n"); - return -ENODEV; - } - return 0; -} - -module_init(maestro_radio_init); -module_exit(maestro_radio_exit); - inline static __u16 radio_power_on(struct radio_device *dev) { register __u16 io=dev->io; @@ -378,3 +354,27 @@ inline static __u16 radio_install(struct return 0; } +int __init maestro_radio_init(void) +{ + register __u16 found=0; + struct pci_dev *pcidev = NULL; + if(!pci_present()) + return -ENODEV; + while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS, + PCI_DEVICE_ID_ESS_ESS1968, + pcidev))) + found |= radio_install(pcidev); + while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS, + PCI_DEVICE_ID_ESS_ESS1978, + pcidev))) + found |= radio_install(pcidev); + if(!found) { + printk(KERN_INFO "radio-maestro: no devices found.\n"); + return -ENODEV; + } + return 0; +} + +module_init(maestro_radio_init); +module_exit(maestro_radio_exit); + diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/media/video/bttv-driver.c linux-2.4.28-pre3/drivers/media/video/bttv-driver.c --- linux-2.4.27/drivers/media/video/bttv-driver.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/media/video/bttv-driver.c 2004-09-10 19:36:12.000000000 +0000 @@ -558,7 +558,7 @@ static struct tvnorm tvnorms[] = { .sram = -1, },{ /* PAL-N */ - .Fsc 35468950, + .Fsc = 35468950, .swidth = 768, .sheight = 576, .totalwidth = 1135, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/media/video/w9966.c linux-2.4.28-pre3/drivers/media/video/w9966.c --- linux-2.4.27/drivers/media/video/w9966.c 2003-06-13 14:51:34.000000000 +0000 +++ linux-2.4.28-pre3/drivers/media/video/w9966.c 2004-09-10 19:33:19.000000000 +0000 @@ -691,6 +691,14 @@ static inline void w9966_i2c_setsda(stru udelay(W9966_I2C_UDELAY); } +// Get peripheral clock line +// Expects a claimed pdev. +static inline int w9966_i2c_getscl(struct w9966_dev* cam) +{ + const u8 pins = w9966_rreg(cam, 0x18); + return ((pins & W9966_I2C_R_CLOCK) > 0); +} + // Sets the clock line on the i2c bus. // Expects a claimed pdev. // 1 on success, else 0 @@ -723,14 +731,6 @@ static inline int w9966_i2c_getsda(struc return ((pins & W9966_I2C_R_DATA) > 0); } -// Get peripheral clock line -// Expects a claimed pdev. -static inline int w9966_i2c_getscl(struct w9966_dev* cam) -{ - const u8 pins = w9966_rreg(cam, 0x18); - return ((pins & W9966_I2C_R_CLOCK) > 0); -} - // Write a byte with ack to the i2c bus. // Expects a claimed pdev. // 1 on success, else 0 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/message/i2o/i2o_pci.c linux-2.4.28-pre3/drivers/message/i2o/i2o_pci.c --- linux-2.4.27/drivers/message/i2o/i2o_pci.c 2002-11-28 23:53:13.000000000 +0000 +++ linux-2.4.28-pre3/drivers/message/i2o/i2o_pci.c 2004-09-10 19:32:51.000000000 +0000 @@ -390,4 +390,3 @@ MODULE_PARM(dpt, "i"); MODULE_PARM_DESC(dpt, "Set this if you want to drive DPT cards normally handled by dpt_i2o"); module_init(i2o_pci_core_attach); module_exit(i2o_pci_core_detach); - \ No newline at end of file diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/mtd/chips/cfi_cmdset_0002.c linux-2.4.28-pre3/drivers/mtd/chips/cfi_cmdset_0002.c --- linux-2.4.27/drivers/mtd/chips/cfi_cmdset_0002.c 2003-06-13 14:51:34.000000000 +0000 +++ linux-2.4.28-pre3/drivers/mtd/chips/cfi_cmdset_0002.c 2004-09-10 19:34:24.000000000 +0000 @@ -461,7 +461,6 @@ static int do_write_oneword(struct map_i unsigned int dq6, dq5; struct cfi_private *cfi = map->fldrv_priv; DECLARE_WAITQUEUE(wait, current); - int ret = 0; retry: cfi_spin_lock(chip->mutex); @@ -554,7 +553,7 @@ static int do_write_oneword(struct map_i wake_up(&chip->wq); cfi_spin_unlock(chip->mutex); DISABLE_VPP(map); - ret = -EIO; + return -EIO; } } @@ -563,7 +562,7 @@ static int do_write_oneword(struct map_i wake_up(&chip->wq); cfi_spin_unlock(chip->mutex); - return ret; + return 0; } static int cfi_amdstd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/mtd/devices/doc1000.c linux-2.4.28-pre3/drivers/mtd/devices/doc1000.c --- linux-2.4.27/drivers/mtd/devices/doc1000.c 2003-06-13 14:51:34.000000000 +0000 +++ linux-2.4.28-pre3/drivers/mtd/devices/doc1000.c 2004-09-10 19:35:47.000000000 +0000 @@ -137,6 +137,119 @@ int flashcard_erase (struct mtd_info *mt return 0; } +static inline int suspend_erase(volatile u_char *addr) +{ + __u16 status; + u_long i = 0; + + writew(IF_ERASE_SUSPEND, addr); + writew(IF_READ_CSR, addr); + + do { + status = readw(addr); + if ((status & CSR_WR_READY) == CSR_WR_READY) + return 0; + i++; + } while(i < max_tries); + + printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status); + return -EIO; + +} + +static inline void resume_erase(volatile u_char *addr) +{ + __u16 status; + + writew(IF_READ_CSR, addr); + status = readw(addr); + + /* Only give resume signal if the erase is really suspended */ + if (status & CSR_ERA_SUSPEND) + writew(IF_CONFIRM, addr); +} + +static inline int byte_write (volatile u_char *addr, u_char byte) +{ + register u_char status; + register u_short i = 0; + + do { + status = readb(addr); + if (status & CSR_WR_READY) + { + writeb(IF_WRITE & 0xff, addr); + writeb(byte, addr); + return 0; + } + i++; + } while(i < max_tries); + + + printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status); + return -EIO; +} + +static inline int word_write (volatile u_char *addr, __u16 word) +{ + register u_short status; + register u_short i = 0; + + do { + status = readw(addr); + if ((status & CSR_WR_READY) == CSR_WR_READY) + { + writew(IF_WRITE, addr); + writew(word, addr); + return 0; + } + i++; + } while(i < max_tries); + + printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status); + return -EIO; +} + +static inline void reset_block(volatile u_char *addr) +{ + u_short i; + __u16 status; + + writew(IF_CLEAR_CSR, addr); + + for (i = 0; i < 100; i++) { + writew(IF_READ_CSR, addr); + status = readw(addr); + if (status != 0xffff) break; + udelay(1000); + } + + writew(IF_READ_CSR, addr); +} + +static inline int check_write(volatile u_char *addr) +{ + u_short status, i = 0; + + writew(IF_READ_CSR, addr); + + do { + status = readw(addr); + if (status & (CSR_WR_ERR | CSR_VPP_LOW)) + { + printk(KERN_NOTICE "flashcard: write failure at %p, status 0x%x\n", addr, status); + reset_block(addr); + return -EIO; + } + if ((status & CSR_WR_READY) == CSR_WR_READY) + return 0; + i++; + } while (i < max_tries); + + printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status); + return -EIO; +} + int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { @@ -281,47 +394,6 @@ int flashcard_write (struct mtd_info *mt /*====================================================================*/ -static inline int byte_write (volatile u_char *addr, u_char byte) -{ - register u_char status; - register u_short i = 0; - - do { - status = readb(addr); - if (status & CSR_WR_READY) - { - writeb(IF_WRITE & 0xff, addr); - writeb(byte, addr); - return 0; - } - i++; - } while(i < max_tries); - - - printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status); - return -EIO; -} - -static inline int word_write (volatile u_char *addr, __u16 word) -{ - register u_short status; - register u_short i = 0; - - do { - status = readw(addr); - if ((status & CSR_WR_READY) == CSR_WR_READY) - { - writew(IF_WRITE, addr); - writew(word, addr); - return 0; - } - i++; - } while(i < max_tries); - - printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status); - return -EIO; -} - static inline void block_erase (volatile u_char *addr) { writew(IF_BLOCK_ERASE, addr); @@ -350,79 +422,6 @@ static inline int check_erase(volatile u return 0; } -static inline int suspend_erase(volatile u_char *addr) -{ - __u16 status; - u_long i = 0; - - writew(IF_ERASE_SUSPEND, addr); - writew(IF_READ_CSR, addr); - - do { - status = readw(addr); - if ((status & CSR_WR_READY) == CSR_WR_READY) - return 0; - i++; - } while(i < max_tries); - - printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status); - return -EIO; - -} - -static inline void resume_erase(volatile u_char *addr) -{ - __u16 status; - - writew(IF_READ_CSR, addr); - status = readw(addr); - - /* Only give resume signal if the erase is really suspended */ - if (status & CSR_ERA_SUSPEND) - writew(IF_CONFIRM, addr); -} - -static inline void reset_block(volatile u_char *addr) -{ - u_short i; - __u16 status; - - writew(IF_CLEAR_CSR, addr); - - for (i = 0; i < 100; i++) { - writew(IF_READ_CSR, addr); - status = readw(addr); - if (status != 0xffff) break; - udelay(1000); - } - - writew(IF_READ_CSR, addr); -} - -static inline int check_write(volatile u_char *addr) -{ - u_short status, i = 0; - - writew(IF_READ_CSR, addr); - - do { - status = readw(addr); - if (status & (CSR_WR_ERR | CSR_VPP_LOW)) - { - printk(KERN_NOTICE "flashcard: write failure at %p, status 0x%x\n", addr, status); - reset_block(addr); - return -EIO; - } - if ((status & CSR_WR_READY) == CSR_WR_READY) - return 0; - i++; - } while (i < max_tries); - - printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status); - return -EIO; -} - - /*====================================================================*/ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/mtd/maps/amd76xrom.c linux-2.4.28-pre3/drivers/mtd/maps/amd76xrom.c --- linux-2.4.27/drivers/mtd/maps/amd76xrom.c 2003-06-13 14:51:34.000000000 +0000 +++ linux-2.4.28-pre3/drivers/mtd/maps/amd76xrom.c 2004-09-10 19:33:44.000000000 +0000 @@ -178,7 +178,7 @@ err_out_iounmap: iounmap((void *)(info->window_addr)); err_out_free_mmio_region: release_mem_region(window->start, window->size); -err_out_none: +//err_out_none: return -ENODEV; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/8139too.c linux-2.4.28-pre3/drivers/net/8139too.c --- linux-2.4.27/drivers/net/8139too.c 2004-08-07 23:26:04.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/8139too.c 2004-09-10 19:31:49.000000000 +0000 @@ -614,7 +614,7 @@ static int rtl8139_open (struct net_devi static int mdio_read (struct net_device *dev, int phy_id, int location); static void mdio_write (struct net_device *dev, int phy_id, int location, int val); -static inline void rtl8139_start_thread(struct net_device *dev); +static void rtl8139_start_thread(struct net_device *dev); static void rtl8139_tx_timeout (struct net_device *dev); static void rtl8139_init_ring (struct net_device *dev); static int rtl8139_start_xmit (struct sk_buff *skb, @@ -1626,7 +1626,7 @@ static int rtl8139_thread (void *data) complete_and_exit (&tp->thr_exited, 0); } -static inline void rtl8139_start_thread(struct net_device *dev) +static void rtl8139_start_thread(struct net_device *dev) { struct rtl8139_private *tp = dev->priv; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/dmfe.c linux-2.4.28-pre3/drivers/net/dmfe.c --- linux-2.4.27/drivers/net/dmfe.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/dmfe.c 2004-09-10 19:36:43.000000000 +0000 @@ -863,6 +863,20 @@ static void dmfe_free_tx_pkt(struct DEVI /* + * Calculate the CRC valude of the Rx packet + * flag = 1 : return the reverse CRC (for the received packet CRC) + * 0 : return the normal CRC (for Hash Table index) + */ + +static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag) +{ + u32 crc = ether_crc_le(Len, Data); + if (flag) crc = ~crc; + return crc; +} + + +/* * Receive the come packet and pass to upper layer */ @@ -1753,20 +1767,6 @@ static u16 phy_read_1bit(unsigned long i /* - * Calculate the CRC valude of the Rx packet - * flag = 1 : return the reverse CRC (for the received packet CRC) - * 0 : return the normal CRC (for Hash Table index) - */ - -static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag) -{ - u32 crc = ether_crc_le(Len, Data); - if (flag) crc = ~crc; - return crc; -} - - -/* * Parser SROM and media mode */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/e100/e100_main.c linux-2.4.28-pre3/drivers/net/e100/e100_main.c --- linux-2.4.27/drivers/net/e100/e100_main.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/e100/e100_main.c 2004-09-10 19:32:37.000000000 +0000 @@ -1073,6 +1073,116 @@ e100_change_mtu(struct net_device *dev, return 0; } +/** + * e100_prepare_xmit_buff - prepare a buffer for transmission + * @bdp: atapter's private data struct + * @skb: skb to send + * + * This routine prepare a buffer for transmission. It checks + * the message length for the appropiate size. It picks up a + * free tcb from the TCB pool and sets up the corresponding + * TBD's. If the number of fragments are more than the number + * of TBD/TCB it copies all the fragments in a coalesce buffer. + * It returns a pointer to the prepared TCB. + */ +static inline tcb_t * +e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb) +{ + tcb_t *tcb, *prev_tcb; + + tcb = bdp->tcb_pool.data; + tcb += TCB_TO_USE(bdp->tcb_pool); + + if (bdp->flags & USE_IPCB) { + tcb->tcbu.ipcb.ip_activation_high = IPCB_IP_ACTIVATION_DEFAULT; + tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCP_PACKET; + tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE; + } + + if(bdp->vlgrp && vlan_tx_tag_present(skb)) { + (tcb->tcbu).ipcb.ip_activation_high |= IPCB_INSERTVLAN_ENABLE; + (tcb->tcbu).ipcb.vlan = cpu_to_be16(vlan_tx_tag_get(skb)); + } + + tcb->tcb_hdr.cb_status = 0; + tcb->tcb_thrshld = bdp->tx_thld; + tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT); + + /* Set I (Interrupt) bit on every (TX_FRAME_CNT)th packet */ + if (!(++bdp->tx_count % TX_FRAME_CNT)) + tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_I_BIT); + else + /* Clear I bit on other packets */ + tcb->tcb_hdr.cb_cmd &= ~__constant_cpu_to_le16(CB_I_BIT); + + tcb->tcb_skb = skb; + + if (skb->ip_summed == CHECKSUM_HW) { + const struct iphdr *ip = skb->nh.iph; + + if ((ip->protocol == IPPROTO_TCP) || + (ip->protocol == IPPROTO_UDP)) { + + tcb->tcbu.ipcb.ip_activation_high |= + IPCB_HARDWAREPARSING_ENABLE; + tcb->tcbu.ipcb.ip_schedule |= + IPCB_TCPUDP_CHECKSUM_ENABLE; + + if (ip->protocol == IPPROTO_TCP) + tcb->tcbu.ipcb.ip_schedule |= IPCB_TCP_PACKET; + } + } + + if (!skb_shinfo(skb)->nr_frags) { + (tcb->tbd_ptr)->tbd_buf_addr = + cpu_to_le32(pci_map_single(bdp->pdev, skb->data, + skb->len, PCI_DMA_TODEVICE)); + (tcb->tbd_ptr)->tbd_buf_cnt = cpu_to_le16(skb->len); + tcb->tcb_tbd_num = 1; + tcb->tcb_tbd_ptr = tcb->tcb_tbd_dflt_ptr; + } else { + int i; + void *addr; + tbd_t *tbd_arr_ptr = &(tcb->tbd_ptr[1]); + skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; + + (tcb->tbd_ptr)->tbd_buf_addr = + cpu_to_le32(pci_map_single(bdp->pdev, skb->data, + skb_headlen(skb), + PCI_DMA_TODEVICE)); + (tcb->tbd_ptr)->tbd_buf_cnt = + cpu_to_le16(skb_headlen(skb)); + + for (i = 0; i < skb_shinfo(skb)->nr_frags; + i++, tbd_arr_ptr++, frag++) { + + addr = ((void *) page_address(frag->page) + + frag->page_offset); + + tbd_arr_ptr->tbd_buf_addr = + cpu_to_le32(pci_map_single(bdp->pdev, + addr, frag->size, + PCI_DMA_TODEVICE)); + tbd_arr_ptr->tbd_buf_cnt = cpu_to_le16(frag->size); + } + tcb->tcb_tbd_num = skb_shinfo(skb)->nr_frags + 1; + tcb->tcb_tbd_ptr = tcb->tcb_tbd_expand_ptr; + } + + /* clear the S-BIT on the previous tcb */ + prev_tcb = bdp->tcb_pool.data; + prev_tcb += PREV_TCB_USED(bdp->tcb_pool); + prev_tcb->tcb_hdr.cb_cmd &= __constant_cpu_to_le16((u16) ~CB_S_BIT); + + bdp->tcb_pool.tail = NEXT_TCB_TOUSE(bdp->tcb_pool.tail); + + wmb(); + + e100_start_cu(bdp, tcb); + + return tcb; +} + static int e100_xmit_frame(struct sk_buff *skb, struct net_device *dev) { @@ -1605,6 +1715,32 @@ e100_alloc_tcb_pool(struct e100_private return 1; } +/** + * e100_tx_skb_free - free TX skbs resources + * @bdp: atapter's private data struct + * @tcb: associated tcb of the freed skb + * + * This routine frees resources of TX skbs. + */ +static inline void +e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb) +{ + if (tcb->tcb_skb) { + int i; + tbd_t *tbd_arr = tcb->tbd_ptr; + int frags = skb_shinfo(tcb->tcb_skb)->nr_frags; + + for (i = 0; i <= frags; i++, tbd_arr++) { + pci_unmap_single(bdp->pdev, + le32_to_cpu(tbd_arr->tbd_buf_addr), + le16_to_cpu(tbd_arr->tbd_buf_cnt), + PCI_DMA_TODEVICE); + } + dev_kfree_skb_irq(tcb->tcb_skb); + tcb->tcb_skb = NULL; + } +} + void e100_free_tcb_pool(struct e100_private *bdp) { @@ -1910,32 +2046,6 @@ e100intr(int irq, void *dev_inst, struct } /** - * e100_tx_skb_free - free TX skbs resources - * @bdp: atapter's private data struct - * @tcb: associated tcb of the freed skb - * - * This routine frees resources of TX skbs. - */ -static inline void -e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb) -{ - if (tcb->tcb_skb) { - int i; - tbd_t *tbd_arr = tcb->tbd_ptr; - int frags = skb_shinfo(tcb->tcb_skb)->nr_frags; - - for (i = 0; i <= frags; i++, tbd_arr++) { - pci_unmap_single(bdp->pdev, - le32_to_cpu(tbd_arr->tbd_buf_addr), - le16_to_cpu(tbd_arr->tbd_buf_cnt), - PCI_DMA_TODEVICE); - } - dev_kfree_skb_irq(tcb->tcb_skb); - tcb->tcb_skb = NULL; - } -} - -/** * e100_tx_srv - service TX queues * @bdp: atapter's private data struct * @@ -2155,116 +2265,6 @@ e100_refresh_txthld(struct e100_private } /* end underrun check */ } -/** - * e100_prepare_xmit_buff - prepare a buffer for transmission - * @bdp: atapter's private data struct - * @skb: skb to send - * - * This routine prepare a buffer for transmission. It checks - * the message length for the appropiate size. It picks up a - * free tcb from the TCB pool and sets up the corresponding - * TBD's. If the number of fragments are more than the number - * of TBD/TCB it copies all the fragments in a coalesce buffer. - * It returns a pointer to the prepared TCB. - */ -static inline tcb_t * -e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb) -{ - tcb_t *tcb, *prev_tcb; - - tcb = bdp->tcb_pool.data; - tcb += TCB_TO_USE(bdp->tcb_pool); - - if (bdp->flags & USE_IPCB) { - tcb->tcbu.ipcb.ip_activation_high = IPCB_IP_ACTIVATION_DEFAULT; - tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCP_PACKET; - tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE; - } - - if(bdp->vlgrp && vlan_tx_tag_present(skb)) { - (tcb->tcbu).ipcb.ip_activation_high |= IPCB_INSERTVLAN_ENABLE; - (tcb->tcbu).ipcb.vlan = cpu_to_be16(vlan_tx_tag_get(skb)); - } - - tcb->tcb_hdr.cb_status = 0; - tcb->tcb_thrshld = bdp->tx_thld; - tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT); - - /* Set I (Interrupt) bit on every (TX_FRAME_CNT)th packet */ - if (!(++bdp->tx_count % TX_FRAME_CNT)) - tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_I_BIT); - else - /* Clear I bit on other packets */ - tcb->tcb_hdr.cb_cmd &= ~__constant_cpu_to_le16(CB_I_BIT); - - tcb->tcb_skb = skb; - - if (skb->ip_summed == CHECKSUM_HW) { - const struct iphdr *ip = skb->nh.iph; - - if ((ip->protocol == IPPROTO_TCP) || - (ip->protocol == IPPROTO_UDP)) { - - tcb->tcbu.ipcb.ip_activation_high |= - IPCB_HARDWAREPARSING_ENABLE; - tcb->tcbu.ipcb.ip_schedule |= - IPCB_TCPUDP_CHECKSUM_ENABLE; - - if (ip->protocol == IPPROTO_TCP) - tcb->tcbu.ipcb.ip_schedule |= IPCB_TCP_PACKET; - } - } - - if (!skb_shinfo(skb)->nr_frags) { - (tcb->tbd_ptr)->tbd_buf_addr = - cpu_to_le32(pci_map_single(bdp->pdev, skb->data, - skb->len, PCI_DMA_TODEVICE)); - (tcb->tbd_ptr)->tbd_buf_cnt = cpu_to_le16(skb->len); - tcb->tcb_tbd_num = 1; - tcb->tcb_tbd_ptr = tcb->tcb_tbd_dflt_ptr; - } else { - int i; - void *addr; - tbd_t *tbd_arr_ptr = &(tcb->tbd_ptr[1]); - skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; - - (tcb->tbd_ptr)->tbd_buf_addr = - cpu_to_le32(pci_map_single(bdp->pdev, skb->data, - skb_headlen(skb), - PCI_DMA_TODEVICE)); - (tcb->tbd_ptr)->tbd_buf_cnt = - cpu_to_le16(skb_headlen(skb)); - - for (i = 0; i < skb_shinfo(skb)->nr_frags; - i++, tbd_arr_ptr++, frag++) { - - addr = ((void *) page_address(frag->page) + - frag->page_offset); - - tbd_arr_ptr->tbd_buf_addr = - cpu_to_le32(pci_map_single(bdp->pdev, - addr, frag->size, - PCI_DMA_TODEVICE)); - tbd_arr_ptr->tbd_buf_cnt = cpu_to_le16(frag->size); - } - tcb->tcb_tbd_num = skb_shinfo(skb)->nr_frags + 1; - tcb->tcb_tbd_ptr = tcb->tcb_tbd_expand_ptr; - } - - /* clear the S-BIT on the previous tcb */ - prev_tcb = bdp->tcb_pool.data; - prev_tcb += PREV_TCB_USED(bdp->tcb_pool); - prev_tcb->tcb_hdr.cb_cmd &= __constant_cpu_to_le16((u16) ~CB_S_BIT); - - bdp->tcb_pool.tail = NEXT_TCB_TOUSE(bdp->tcb_pool.tail); - - wmb(); - - e100_start_cu(bdp, tcb); - - return tcb; -} - /* Changed for 82558 enhancement */ /** * e100_start_cu - start the adapter's CU diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/e1000/e1000_main.c linux-2.4.28-pre3/drivers/net/e1000/e1000_main.c --- linux-2.4.27/drivers/net/e1000/e1000_main.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/e1000/e1000_main.c 2004-09-10 19:34:20.000000000 +0000 @@ -248,6 +248,34 @@ e1000_exit_module(void) module_exit(e1000_exit_module); +/** + * e1000_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + **/ + +static inline void +e1000_irq_enable(struct e1000_adapter *adapter) +{ + if(atomic_dec_and_test(&adapter->irq_sem)) { + E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); + E1000_WRITE_FLUSH(&adapter->hw); + } +} + +/** + * e1000_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ + +static inline void +e1000_irq_disable(struct e1000_adapter *adapter) +{ + atomic_inc(&adapter->irq_sem); + E1000_WRITE_REG(&adapter->hw, IMC, ~0); + E1000_WRITE_FLUSH(&adapter->hw); + synchronize_irq(); +} + int e1000_up(struct e1000_adapter *adapter) { @@ -2055,34 +2083,6 @@ e1000_update_stats(struct e1000_adapter } /** - * e1000_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - **/ - -static inline void -e1000_irq_disable(struct e1000_adapter *adapter) -{ - atomic_inc(&adapter->irq_sem); - E1000_WRITE_REG(&adapter->hw, IMC, ~0); - E1000_WRITE_FLUSH(&adapter->hw); - synchronize_irq(); -} - -/** - * e1000_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - **/ - -static inline void -e1000_irq_enable(struct e1000_adapter *adapter) -{ - if(atomic_dec_and_test(&adapter->irq_sem)) { - E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); - E1000_WRITE_FLUSH(&adapter->hw); - } -} - -/** * e1000_intr - Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure @@ -2227,6 +2227,41 @@ e1000_clean_tx_irq(struct e1000_adapter } /** + * e1000_rx_checksum - Receive Checksum Offload for 82543 + * @adapter: board private structure + * @rx_desc: receive descriptor + * @sk_buff: socket buffer with received data + **/ + +static inline void +e1000_rx_checksum(struct e1000_adapter *adapter, + struct e1000_rx_desc *rx_desc, + struct sk_buff *skb) +{ + /* 82543 or newer only */ + if((adapter->hw.mac_type < e1000_82543) || + /* Ignore Checksum bit is set */ + (rx_desc->status & E1000_RXD_STAT_IXSM) || + /* TCP Checksum has not been calculated */ + (!(rx_desc->status & E1000_RXD_STAT_TCPCS))) { + skb->ip_summed = CHECKSUM_NONE; + return; + } + + /* At this point we know the hardware did the TCP checksum */ + /* now look at the TCP checksum error bit */ + if(rx_desc->errors & E1000_RXD_ERR_TCPE) { + /* let the stack verify checksum errors */ + skb->ip_summed = CHECKSUM_NONE; + adapter->hw_csum_err++; + } else { + /* TCP checksum is good */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + adapter->hw_csum_good++; + } +} + +/** * e1000_clean_rx_irq - Send received data up the network stack, * @adapter: board private structure **/ @@ -2581,41 +2616,6 @@ e1000_mii_ioctl(struct net_device *netde return E1000_SUCCESS; } -/** - * e1000_rx_checksum - Receive Checksum Offload for 82543 - * @adapter: board private structure - * @rx_desc: receive descriptor - * @sk_buff: socket buffer with received data - **/ - -static inline void -e1000_rx_checksum(struct e1000_adapter *adapter, - struct e1000_rx_desc *rx_desc, - struct sk_buff *skb) -{ - /* 82543 or newer only */ - if((adapter->hw.mac_type < e1000_82543) || - /* Ignore Checksum bit is set */ - (rx_desc->status & E1000_RXD_STAT_IXSM) || - /* TCP Checksum has not been calculated */ - (!(rx_desc->status & E1000_RXD_STAT_TCPCS))) { - skb->ip_summed = CHECKSUM_NONE; - return; - } - - /* At this point we know the hardware did the TCP checksum */ - /* now look at the TCP checksum error bit */ - if(rx_desc->errors & E1000_RXD_ERR_TCPE) { - /* let the stack verify checksum errors */ - skb->ip_summed = CHECKSUM_NONE; - adapter->hw_csum_err++; - } else { - /* TCP checksum is good */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - adapter->hw_csum_good++; - } -} - void e1000_pci_set_mwi(struct e1000_hw *hw) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/e1000/e1000_param.c linux-2.4.28-pre3/drivers/net/e1000/e1000_param.c --- linux-2.4.27/drivers/net/e1000/e1000_param.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/e1000/e1000_param.c 2004-09-10 19:32:44.000000000 +0000 @@ -212,7 +212,7 @@ E1000_PARAM(InterruptThrottleRate, "Inte #define MAX_TXABSDELAY 0xFFFF #define MIN_TXABSDELAY 0 -#define DEFAULT_ITR 1 +#define DEFAULT_ITR 8000 #define MAX_ITR 100000 #define MIN_ITR 100 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/eql.c linux-2.4.28-pre3/drivers/net/eql.c --- linux-2.4.27/drivers/net/eql.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/eql.c 2004-09-10 19:33:46.000000000 +0000 @@ -335,6 +335,152 @@ static int eql_ioctl(struct net_device * } +static inline int eql_number_slaves(slave_queue_t *queue) +{ + return queue->num_slaves; +} + + +static inline int eql_is_empty(slave_queue_t *queue) +{ + if (eql_number_slaves (queue) == 0) + return 1; + return 0; +} + +static inline int eql_is_full(slave_queue_t *queue) +{ + equalizer_t *eql = (equalizer_t *) queue->master_dev->priv; + + if (eql_number_slaves (queue) == eql->max_slaves) + return 1; + return 0; +} + +static inline slave_t *eql_first_slave(slave_queue_t *queue) +{ + return queue->head->next; +} + + +static inline slave_t *eql_next_slave(slave_queue_t *queue, slave_t *slave) +{ + return slave->next; +} + +static inline void eql_set_best_slave(slave_queue_t *queue, slave_t *slave) +{ + queue->best_slave = slave; +} + +static inline void eql_schedule_slaves(slave_queue_t *queue) +{ + struct net_device *master_dev = queue->master_dev; + slave_t *best_slave = 0; + slave_t *slave_corpse = 0; + +#ifdef EQL_DEBUG + if (eql_debug >= 100) + printk ("%s: schedule %d slaves\n", + master_dev->name, eql_number_slaves (queue)); +#endif + if ( eql_is_empty (queue) ) + { + /* + * No slaves to play with + */ + eql_set_best_slave (queue, (slave_t *) 0); + return; + } + else + { + /* + * Make a pass to set the best slave + */ + unsigned long best_load = (unsigned long) ULONG_MAX; + slave_t *slave = 0; + unsigned long flags; + int i; + + save_flags(flags); + cli (); + for (i = 1, slave = eql_first_slave (queue); + i <= eql_number_slaves (queue); + i++, slave = eql_next_slave (queue, slave)) + { + /* + * Go through the slave list once, updating best_slave + * whenever a new best_load is found, whenever a dead + * slave is found, it is marked to be pulled out of the + * queue + */ + + unsigned long slave_load; + unsigned long bytes_queued; + unsigned long priority_Bps; + + if (slave != 0) + { + bytes_queued = slave->bytes_queued; + priority_Bps = slave->priority_Bps; + if ( slave->dev != 0) + { + if ((slave->dev->flags & IFF_UP) == IFF_UP ) + { + slave_load = (ULONG_MAX - (ULONG_MAX / 2)) - + (priority_Bps) + bytes_queued * 8; + + if (slave_load < best_load) + { + best_load = slave_load; + best_slave = slave; + } + } + else /* we found a dead slave */ + { + /* + * We only bury one slave at a time, if more than + * one slave dies, we will bury him on the next + * reschedule. slaves don't die all at once that + * much anyway + */ + slave_corpse = slave; + } + } + } + } /* for */ + restore_flags(flags); + eql_set_best_slave (queue, best_slave); + } /* else */ + if (slave_corpse != 0) + { + printk ("eql: scheduler found dead slave, burying...\n"); + eql_delete_slave (eql_remove_slave (queue, slave_corpse)); + } + return; +} + + +static inline struct net_device *eql_best_slave_dev(slave_queue_t *queue) +{ + if (queue->best_slave != 0) + { + if (queue->best_slave->dev != 0) + return queue->best_slave->dev; + else + return 0; + } + else + return 0; +} + + +static inline slave_t *eql_best_slave(slave_queue_t *queue) +{ + return queue->best_slave; +} + + static int eql_slave_xmit(struct sk_buff *skb, struct net_device *dev) { equalizer_t *eql = (equalizer_t *) dev->priv; @@ -383,6 +529,28 @@ static struct net_device_stats * eql_get return eql->stats; } +static inline int eql_is_slave(struct net_device *dev) +{ + if (dev) + { + if ((dev->flags & IFF_SLAVE) == IFF_SLAVE) + return 1; + } + return 0; +} + + +static inline int eql_is_master(struct net_device *dev) +{ + if (dev) + { + if ((dev->flags & IFF_MASTER) == IFF_MASTER) + return 1; + } + return 0; +} + + /* * Private ioctl functions */ @@ -597,28 +765,6 @@ static int eql_s_master_cfg(struct net_d * Private device support functions */ -static inline int eql_is_slave(struct net_device *dev) -{ - if (dev) - { - if ((dev->flags & IFF_SLAVE) == IFF_SLAVE) - return 1; - } - return 0; -} - - -static inline int eql_is_master(struct net_device *dev) -{ - if (dev) - { - if ((dev->flags & IFF_MASTER) == IFF_MASTER) - return 1; - } - return 0; -} - - static slave_t *eql_new_slave(void) { slave_t *slave; @@ -650,27 +796,6 @@ static long slave_bps(slave_t *slave) #endif -static inline int eql_number_slaves(slave_queue_t *queue) -{ - return queue->num_slaves; -} - -static inline int eql_is_empty(slave_queue_t *queue) -{ - if (eql_number_slaves (queue) == 0) - return 1; - return 0; -} - -static inline int eql_is_full(slave_queue_t *queue) -{ - equalizer_t *eql = (equalizer_t *) queue->master_dev->priv; - - if (eql_number_slaves (queue) == eql->max_slaves) - return 1; - return 0; -} - static slave_queue_t *eql_new_slave_queue(struct net_device *dev) { slave_queue_t *queue; @@ -817,113 +942,6 @@ static int eql_remove_slave_dev(slave_qu } -static inline struct net_device *eql_best_slave_dev(slave_queue_t *queue) -{ - if (queue->best_slave != 0) - { - if (queue->best_slave->dev != 0) - return queue->best_slave->dev; - else - return 0; - } - else - return 0; -} - - -static inline slave_t *eql_best_slave(slave_queue_t *queue) -{ - return queue->best_slave; -} - -static inline void eql_schedule_slaves(slave_queue_t *queue) -{ - struct net_device *master_dev = queue->master_dev; - slave_t *best_slave = 0; - slave_t *slave_corpse = 0; - -#ifdef EQL_DEBUG - if (eql_debug >= 100) - printk ("%s: schedule %d slaves\n", - master_dev->name, eql_number_slaves (queue)); -#endif - if ( eql_is_empty (queue) ) - { - /* - * No slaves to play with - */ - eql_set_best_slave (queue, (slave_t *) 0); - return; - } - else - { - /* - * Make a pass to set the best slave - */ - unsigned long best_load = (unsigned long) ULONG_MAX; - slave_t *slave = 0; - unsigned long flags; - int i; - - save_flags(flags); - cli (); - for (i = 1, slave = eql_first_slave (queue); - i <= eql_number_slaves (queue); - i++, slave = eql_next_slave (queue, slave)) - { - /* - * Go through the slave list once, updating best_slave - * whenever a new best_load is found, whenever a dead - * slave is found, it is marked to be pulled out of the - * queue - */ - - unsigned long slave_load; - unsigned long bytes_queued; - unsigned long priority_Bps; - - if (slave != 0) - { - bytes_queued = slave->bytes_queued; - priority_Bps = slave->priority_Bps; - if ( slave->dev != 0) - { - if ((slave->dev->flags & IFF_UP) == IFF_UP ) - { - slave_load = (ULONG_MAX - (ULONG_MAX / 2)) - - (priority_Bps) + bytes_queued * 8; - - if (slave_load < best_load) - { - best_load = slave_load; - best_slave = slave; - } - } - else /* we found a dead slave */ - { - /* - * We only bury one slave at a time, if more than - * one slave dies, we will bury him on the next - * reschedule. slaves don't die all at once that - * much anyway - */ - slave_corpse = slave; - } - } - } - } /* for */ - restore_flags(flags); - eql_set_best_slave (queue, best_slave); - } /* else */ - if (slave_corpse != 0) - { - printk ("eql: scheduler found dead slave, burying...\n"); - eql_delete_slave (eql_remove_slave (queue, slave_corpse)); - } - return; -} - - static slave_t * eql_find_slave_dev(slave_queue_t *queue, struct net_device *dev) { slave_t *slave = 0; @@ -943,22 +961,6 @@ static slave_t * eql_find_slave_dev(slav } -static inline slave_t *eql_first_slave(slave_queue_t *queue) -{ - return queue->head->next; -} - - -static inline slave_t *eql_next_slave(slave_queue_t *queue, slave_t *slave) -{ - return slave->next; -} - -static inline void eql_set_best_slave(slave_queue_t *queue, slave_t *slave) -{ - queue->best_slave = slave; -} - static void eql_timer(unsigned long param) { equalizer_t *eql = (equalizer_t *) param; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/fc/iph5526.c linux-2.4.28-pre3/drivers/net/fc/iph5526.c --- linux-2.4.27/drivers/net/fc/iph5526.c 2003-06-13 14:51:34.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/fc/iph5526.c 2004-09-10 19:33:16.000000000 +0000 @@ -689,8 +689,8 @@ int index, no_of_entries = 0; prev_IMQ_index = current_IMQ_index; } } /*end of for loop*/ - return; LEAVE("tachyon_interrupt"); + return; } @@ -2933,7 +2933,7 @@ static void iph5526_timeout(struct net_d { struct fc_info *fi = (struct fc_info*)dev->priv; printk(KERN_WARNING "%s: timed out on send.\n", dev->name); - fi->fc_stats.rx_dropped++; + fi->fc_stats.tx_dropped++; dev->trans_start = jiffies; netif_wake_queue(dev); } @@ -2976,7 +2976,7 @@ static int iph5526_send_packet(struct sk fi->fc_stats.tx_packets++; } else - fi->fc_stats.rx_dropped++; + fi->fc_stats.tx_dropped++; dev->trans_start = jiffies; /* We free up the IP buffers in the OCI_interrupt handler. * status == 0 implies that the frame was not transmitted. So the @@ -3374,8 +3374,8 @@ u_int s_id; q = q->next; } DPRINTK1("Port Name does not match. Txing LOGO."); - return 0; LEAVE("validate_login"); + return 0; } static void add_to_address_cache(struct fc_info *fi, u_int *base_ptr) @@ -3758,8 +3758,10 @@ struct pci_dev *pdev = NULL; sprintf(fi->name, "fc%d", count); host = scsi_register(tmpt, sizeof(struct iph5526_hostdata)); - if(host==NULL) + if(host==NULL) { + kfree(fc[count]); return no_of_hosts; + } hostdata = (struct iph5526_hostdata *)host->hostdata; memset(hostdata, 0 , sizeof(struct iph5526_hostdata)); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/fealnx.c linux-2.4.28-pre3/drivers/net/fealnx.c --- linux-2.4.27/drivers/net/fealnx.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/fealnx.c 2004-09-10 19:35:57.000000000 +0000 @@ -1796,7 +1796,7 @@ static void set_rx_mode(struct net_devic unsigned long flags; spin_lock_irqsave(lp, flags); __set_rx_mode(dev); - spin_unlock_irqrestore(&lp, flags); + spin_unlock_irqrestore(lp, flags); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/hamachi.c linux-2.4.28-pre3/drivers/net/hamachi.c --- linux-2.4.27/drivers/net/hamachi.c 2003-06-13 14:51:34.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/hamachi.c 2004-09-10 19:37:19.000000000 +0000 @@ -1369,109 +1369,6 @@ static int hamachi_start_xmit(struct sk_ return 0; } -/* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -static void hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *rgs) -{ - struct net_device *dev = dev_instance; - struct hamachi_private *hmp; - long ioaddr, boguscnt = max_interrupt_work; - -#ifndef final_version /* Can never occur. */ - if (dev == NULL) { - printk (KERN_ERR "hamachi_interrupt(): irq %d for unknown device.\n", irq); - return; - } -#endif - - ioaddr = dev->base_addr; - hmp = dev->priv; - spin_lock(&hmp->lock); - - do { - u32 intr_status = readl(ioaddr + InterruptClear); - - if (hamachi_debug > 4) - printk(KERN_DEBUG "%s: Hamachi interrupt, status %4.4x.\n", - dev->name, intr_status); - - if (intr_status == 0) - break; - - if (intr_status & IntrRxDone) - hamachi_rx(dev); - - if (intr_status & IntrTxDone){ - /* This code should RARELY need to execute. After all, this is - * a gigabit link, it should consume packets as fast as we put - * them in AND we clear the Tx ring in hamachi_start_xmit(). - */ - if (hmp->tx_full){ - for (; hmp->cur_tx - hmp->dirty_tx > 0; hmp->dirty_tx++){ - int entry = hmp->dirty_tx % TX_RING_SIZE; - struct sk_buff *skb; - - if (hmp->tx_ring[entry].status_n_length & cpu_to_le32(DescOwn)) - break; - skb = hmp->tx_skbuff[entry]; - /* Free the original skb. */ - if (skb){ - pci_unmap_single(hmp->pci_dev, - hmp->tx_ring[entry].addr, - skb->len, - PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); - hmp->tx_skbuff[entry] = 0; - } - hmp->tx_ring[entry].status_n_length = 0; - if (entry >= TX_RING_SIZE-1) - hmp->tx_ring[TX_RING_SIZE-1].status_n_length |= - cpu_to_le32(DescEndRing); - hmp->stats.tx_packets++; - } - if (hmp->cur_tx - hmp->dirty_tx < TX_RING_SIZE - 4){ - /* The ring is no longer full */ - hmp->tx_full = 0; - netif_wake_queue(dev); - } - } else { - netif_wake_queue(dev); - } - } - - - /* Abnormal error summary/uncommon events handlers. */ - if (intr_status & - (IntrTxPCIFault | IntrTxPCIErr | IntrRxPCIFault | IntrRxPCIErr | - LinkChange | NegotiationChange | StatsMax)) - hamachi_error(dev, intr_status); - - if (--boguscnt < 0) { - printk(KERN_WARNING "%s: Too much work at interrupt, status=0x%4.4x.\n", - dev->name, intr_status); - break; - } - } while (1); - - if (hamachi_debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", - dev->name, readl(ioaddr + IntrStatus)); - -#ifndef final_version - /* Code that should never be run! Perhaps remove after testing.. */ - { - static int stopit = 10; - if (dev->start == 0 && --stopit < 0) { - printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n", - dev->name); - free_irq(irq, dev); - } - } -#endif - - spin_unlock(&hmp->lock); -} - /* This routine is logically part of the interrupt handler, but seperated for clarity and better register allocation. */ static int hamachi_rx(struct net_device *dev) @@ -1677,6 +1574,109 @@ static int hamachi_rx(struct net_device return 0; } +/* The interrupt handler does all of the Rx thread work and cleans up + after the Tx thread. */ +static void hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *rgs) +{ + struct net_device *dev = dev_instance; + struct hamachi_private *hmp; + long ioaddr, boguscnt = max_interrupt_work; + +#ifndef final_version /* Can never occur. */ + if (dev == NULL) { + printk (KERN_ERR "hamachi_interrupt(): irq %d for unknown device.\n", irq); + return; + } +#endif + + ioaddr = dev->base_addr; + hmp = dev->priv; + spin_lock(&hmp->lock); + + do { + u32 intr_status = readl(ioaddr + InterruptClear); + + if (hamachi_debug > 4) + printk(KERN_DEBUG "%s: Hamachi interrupt, status %4.4x.\n", + dev->name, intr_status); + + if (intr_status == 0) + break; + + if (intr_status & IntrRxDone) + hamachi_rx(dev); + + if (intr_status & IntrTxDone){ + /* This code should RARELY need to execute. After all, this is + * a gigabit link, it should consume packets as fast as we put + * them in AND we clear the Tx ring in hamachi_start_xmit(). + */ + if (hmp->tx_full){ + for (; hmp->cur_tx - hmp->dirty_tx > 0; hmp->dirty_tx++){ + int entry = hmp->dirty_tx % TX_RING_SIZE; + struct sk_buff *skb; + + if (hmp->tx_ring[entry].status_n_length & cpu_to_le32(DescOwn)) + break; + skb = hmp->tx_skbuff[entry]; + /* Free the original skb. */ + if (skb){ + pci_unmap_single(hmp->pci_dev, + hmp->tx_ring[entry].addr, + skb->len, + PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + hmp->tx_skbuff[entry] = 0; + } + hmp->tx_ring[entry].status_n_length = 0; + if (entry >= TX_RING_SIZE-1) + hmp->tx_ring[TX_RING_SIZE-1].status_n_length |= + cpu_to_le32(DescEndRing); + hmp->stats.tx_packets++; + } + if (hmp->cur_tx - hmp->dirty_tx < TX_RING_SIZE - 4){ + /* The ring is no longer full */ + hmp->tx_full = 0; + netif_wake_queue(dev); + } + } else { + netif_wake_queue(dev); + } + } + + + /* Abnormal error summary/uncommon events handlers. */ + if (intr_status & + (IntrTxPCIFault | IntrTxPCIErr | IntrRxPCIFault | IntrRxPCIErr | + LinkChange | NegotiationChange | StatsMax)) + hamachi_error(dev, intr_status); + + if (--boguscnt < 0) { + printk(KERN_WARNING "%s: Too much work at interrupt, status=0x%4.4x.\n", + dev->name, intr_status); + break; + } + } while (1); + + if (hamachi_debug > 3) + printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", + dev->name, readl(ioaddr + IntrStatus)); + +#ifndef final_version + /* Code that should never be run! Perhaps remove after testing.. */ + { + static int stopit = 10; + if (dev->start == 0 && --stopit < 0) { + printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n", + dev->name); + free_irq(irq, dev); + } + } +#endif + + spin_unlock(&hmp->lock); +} + /* This is more properly named "uncommon interrupt events", as it covers more than just errors. */ static void hamachi_error(struct net_device *dev, int intr_status) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/hamradio/dmascc.c linux-2.4.28-pre3/drivers/net/hamradio/dmascc.c --- linux-2.4.27/drivers/net/hamradio/dmascc.c 2002-02-25 19:37:59.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/hamradio/dmascc.c 2004-09-10 19:34:29.000000000 +0000 @@ -356,6 +356,12 @@ void __init dmascc_setup(char *str, int #endif +static inline unsigned char random(void) { + /* See "Numerical Recipes in C", second edition, p. 284 */ + rand = rand * 1664525L + 1013904223L; + return (unsigned char) (rand >> 24); +} + /* Initialization functions */ @@ -950,6 +956,34 @@ static int scc_set_mac_address(struct ne } +static inline void z8530_isr(struct scc_info *info) { + int is, i = 100; + + while ((is = read_scc(&info->priv[0], R3)) && i--) { + if (is & CHARxIP) { + rx_isr(&info->priv[0]); + } else if (is & CHATxIP) { + tx_isr(&info->priv[0]); + } else if (is & CHAEXT) { + es_isr(&info->priv[0]); + } else if (is & CHBRxIP) { + rx_isr(&info->priv[1]); + } else if (is & CHBTxIP) { + tx_isr(&info->priv[1]); + } else { + es_isr(&info->priv[1]); + } + write_scc(&info->priv[0], R0, RES_H_IUS); + i++; + } + if (i < 0) { + printk("dmascc: stuck in ISR with RR3=0x%02x.\n", is); + } + /* Ok, no interrupts pending from this 8530. The INT line should + be inactive now. */ +} + + static void scc_isr(int irq, void *dev_id, struct pt_regs * regs) { struct scc_info *info = dev_id; @@ -983,34 +1017,6 @@ static void scc_isr(int irq, void *dev_i } -static inline void z8530_isr(struct scc_info *info) { - int is, i = 100; - - while ((is = read_scc(&info->priv[0], R3)) && i--) { - if (is & CHARxIP) { - rx_isr(&info->priv[0]); - } else if (is & CHATxIP) { - tx_isr(&info->priv[0]); - } else if (is & CHAEXT) { - es_isr(&info->priv[0]); - } else if (is & CHBRxIP) { - rx_isr(&info->priv[1]); - } else if (is & CHBTxIP) { - tx_isr(&info->priv[1]); - } else { - es_isr(&info->priv[1]); - } - write_scc(&info->priv[0], R0, RES_H_IUS); - i++; - } - if (i < 0) { - printk("dmascc: stuck in ISR with RR3=0x%02x.\n", is); - } - /* Ok, no interrupts pending from this 8530. The INT line should - be inactive now. */ -} - - static void rx_isr(struct scc_priv *priv) { if (priv->param.dma >= 0) { /* Check special condition and perform error reset. See 2.4.7.5. */ @@ -1160,6 +1166,90 @@ static void tx_isr(struct scc_priv *priv } +static inline void tx_on(struct scc_priv *priv) { + int i, n; + unsigned long flags; + + if (priv->param.dma >= 0) { + n = (priv->chip == Z85230) ? 3 : 1; + /* Program DMA controller */ + flags = claim_dma_lock(); + set_dma_mode(priv->param.dma, DMA_MODE_WRITE); + set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n); + set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n); + release_dma_lock(flags); + /* Enable TX underrun interrupt */ + write_scc(priv, R15, TxUIE); + /* Configure DREQ */ + if (priv->type == TYPE_TWIN) + outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3, + priv->card_base + TWIN_DMA_CFG); + else + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB); + /* Write first byte(s) */ + save_flags(flags); + cli(); + for (i = 0; i < n; i++) + write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1); + enable_dma(priv->param.dma); + restore_flags(flags); + } else { + write_scc(priv, R15, TxUIE); + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB); + tx_isr(priv); + } + /* Reset EOM latch if we do not have the AUTOEOM feature */ + if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L); +} + + +static inline void rx_on(struct scc_priv *priv) { + unsigned long flags; + + /* Clear RX FIFO */ + while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv); + priv->rx_over = 0; + if (priv->param.dma >= 0) { + /* Program DMA controller */ + flags = claim_dma_lock(); + set_dma_mode(priv->param.dma, DMA_MODE_READ); + set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]); + set_dma_count(priv->param.dma, BUF_SIZE); + release_dma_lock(flags); + enable_dma(priv->param.dma); + /* Configure PackeTwin DMA */ + if (priv->type == TYPE_TWIN) { + outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3, + priv->card_base + TWIN_DMA_CFG); + } + /* Sp. cond. intr. only, ext int enable, RX DMA enable */ + write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx | + WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB); + } else { + /* Reset current frame */ + priv->rx_ptr = 0; + /* Intr. on all Rx characters and Sp. cond., ext int enable */ + write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT | + WT_FN_RDYFN); + } + write_scc(priv, R0, ERR_RES); + write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB); +} + + +static inline void rx_off(struct scc_priv *priv) { + /* Disable receiver */ + write_scc(priv, R3, Rx8); + /* Disable DREQ / RX interrupt */ + if (priv->param.dma >= 0 && priv->type == TYPE_TWIN) + outb(0, priv->card_base + TWIN_DMA_CFG); + else + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN); + /* Disable DMA */ + if (priv->param.dma >= 0) disable_dma(priv->param.dma); +} + + static void es_isr(struct scc_priv *priv) { int i, rr0, drr0, res; unsigned long flags; @@ -1301,90 +1391,6 @@ static void tm_isr(struct scc_priv *priv } -static inline void tx_on(struct scc_priv *priv) { - int i, n; - unsigned long flags; - - if (priv->param.dma >= 0) { - n = (priv->chip == Z85230) ? 3 : 1; - /* Program DMA controller */ - flags = claim_dma_lock(); - set_dma_mode(priv->param.dma, DMA_MODE_WRITE); - set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n); - set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n); - release_dma_lock(flags); - /* Enable TX underrun interrupt */ - write_scc(priv, R15, TxUIE); - /* Configure DREQ */ - if (priv->type == TYPE_TWIN) - outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3, - priv->card_base + TWIN_DMA_CFG); - else - write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB); - /* Write first byte(s) */ - save_flags(flags); - cli(); - for (i = 0; i < n; i++) - write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1); - enable_dma(priv->param.dma); - restore_flags(flags); - } else { - write_scc(priv, R15, TxUIE); - write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB); - tx_isr(priv); - } - /* Reset EOM latch if we do not have the AUTOEOM feature */ - if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L); -} - - -static inline void rx_on(struct scc_priv *priv) { - unsigned long flags; - - /* Clear RX FIFO */ - while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv); - priv->rx_over = 0; - if (priv->param.dma >= 0) { - /* Program DMA controller */ - flags = claim_dma_lock(); - set_dma_mode(priv->param.dma, DMA_MODE_READ); - set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]); - set_dma_count(priv->param.dma, BUF_SIZE); - release_dma_lock(flags); - enable_dma(priv->param.dma); - /* Configure PackeTwin DMA */ - if (priv->type == TYPE_TWIN) { - outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3, - priv->card_base + TWIN_DMA_CFG); - } - /* Sp. cond. intr. only, ext int enable, RX DMA enable */ - write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx | - WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB); - } else { - /* Reset current frame */ - priv->rx_ptr = 0; - /* Intr. on all Rx characters and Sp. cond., ext int enable */ - write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT | - WT_FN_RDYFN); - } - write_scc(priv, R0, ERR_RES); - write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB); -} - - -static inline void rx_off(struct scc_priv *priv) { - /* Disable receiver */ - write_scc(priv, R3, Rx8); - /* Disable DREQ / RX interrupt */ - if (priv->param.dma >= 0 && priv->type == TYPE_TWIN) - outb(0, priv->card_base + TWIN_DMA_CFG); - else - write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN); - /* Disable DMA */ - if (priv->param.dma >= 0) disable_dma(priv->param.dma); -} - - static void start_timer(struct scc_priv *priv, int t, int r15) { unsigned long flags; @@ -1404,10 +1410,3 @@ static void start_timer(struct scc_priv } } - -static inline unsigned char random(void) { - /* See "Numerical Recipes in C", second edition, p. 284 */ - rand = rand * 1664525L + 1013904223L; - return (unsigned char) (rand >> 24); -} - diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/irda/ma600.c linux-2.4.28-pre3/drivers/net/irda/ma600.c --- linux-2.4.27/drivers/net/irda/ma600.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/irda/ma600.c 2004-09-10 19:33:27.000000000 +0000 @@ -48,7 +48,7 @@ #undef IRDA_DEBUG #define IRDA_DEBUG(n, args...) (printk(KERN_DEBUG args)) - #undef ASSERT(expr, func) + #undef ASSERT #define ASSERT(expr, func) \ if(!(expr)) { \ printk( "Assertion failed! %s,%s,%s,line=%d\n",\ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/irda/nsc-ircc.c linux-2.4.28-pre3/drivers/net/irda/nsc-ircc.c --- linux-2.4.27/drivers/net/irda/nsc-ircc.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/irda/nsc-ircc.c 2004-09-10 19:31:52.000000000 +0000 @@ -6,8 +6,8 @@ * Status: Stable. * Author: Dag Brattli * Created at: Sat Nov 7 21:43:15 1998 - * Modified at: Wed Mar 1 11:29:34 2000 - * Modified by: Dag Brattli + * Modified at: Sat Aug 14 04:14:57 2004 + * Modified by: Maik Broemme * * Copyright (c) 1998-2000 Dag Brattli * Copyright (c) 1998 Lichen Wang, @@ -369,15 +369,22 @@ static int nsc_ircc_open(int i, chipio_t } MESSAGE("IrDA: Registered device %s\n", dev->name); - /* Check if user has supplied the dongle id or not */ + /* Check if user has supplied the dongle id and if it is in the range of available ids or not. */ if (!dongle_id) { dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); MESSAGE("%s, Found dongle: %s\n", driver_name, dongle_types[dongle_id]); } else { - MESSAGE("%s, Using dongle: %s\n", driver_name, - dongle_types[dongle_id]); + if (dongle_id < sizeof(dongle_types) / sizeof(dongle_types[0])) { + MESSAGE("%s, Using dongle: %s\n", driver_name, + dongle_types[dongle_id]); + } else { + MESSAGE("%s, dongle id %i out of range, start autodetect.\n", driver_name, dongle_id); + dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); + MESSAGE("%s, Found dongle: %s\n", driver_name, + dongle_types[dongle_id]); + } } self->io.dongle_id = dongle_id; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/ne2k-pci.c linux-2.4.28-pre3/drivers/net/ne2k-pci.c --- linux-2.4.27/drivers/net/ne2k-pci.c 2004-04-14 13:05:30.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/ne2k-pci.c 2004-09-10 19:33:14.000000000 +0000 @@ -505,8 +505,12 @@ static void ne2k_pci_block_input(struct insl(NE_BASE + NE_DATAPORT, buf, count>>2); if (count & 3) { buf += count & ~3; - if (count & 2) - *((u16*)buf)++ = le16_to_cpu(inw(NE_BASE + NE_DATAPORT)); + if (count & 2) { + u16 *b = (u16 *)buf; + + *b++ = le16_to_cpu(inw(NE_BASE + NE_DATAPORT)); + buf = (char *)b; + } if (count & 1) *buf = inb(NE_BASE + NE_DATAPORT); } @@ -566,8 +570,12 @@ static void ne2k_pci_block_output(struct outsl(NE_BASE + NE_DATAPORT, buf, count>>2); if (count & 3) { buf += count & ~3; - if (count & 2) - outw(cpu_to_le16(*((u16*)buf)++), NE_BASE + NE_DATAPORT); + if (count & 2) { + u16 *b = (u16 *)buf; + + outw(cpu_to_le16(*b++), NE_BASE + NE_DATAPORT); + buf = (char *)b; + } } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/ns83820.c linux-2.4.28-pre3/drivers/net/ns83820.c --- linux-2.4.27/drivers/net/ns83820.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/ns83820.c 2004-09-10 19:37:07.000000000 +0000 @@ -587,7 +587,7 @@ static inline int rx_refill(struct ns838 } static void FASTCALL(rx_refill_atomic(struct ns83820 *dev)); -static void rx_refill_atomic(struct ns83820 *dev) +static void fastcall rx_refill_atomic(struct ns83820 *dev) { rx_refill(dev, GFP_ATOMIC); } @@ -608,7 +608,7 @@ static inline void clear_rx_desc(struct } static void FASTCALL(phy_intr(struct ns83820 *dev)); -static void phy_intr(struct ns83820 *dev) +static void fastcall phy_intr(struct ns83820 *dev) { static char *speeds[] = { "10", "100", "1000", "1000(?)", "1000F" }; u32 cfg, new_cfg; @@ -793,7 +793,7 @@ static void ns83820_cleanup_rx(struct ns } static void FASTCALL(ns83820_rx_kick(struct ns83820 *dev)); -static void ns83820_rx_kick(struct ns83820 *dev) +static void fastcall ns83820_rx_kick(struct ns83820 *dev) { /*if (nr_rx_empty(dev) >= NR_RX_DESC/4)*/ { if (dev->rx_info.up) { @@ -814,7 +814,7 @@ static void ns83820_rx_kick(struct ns838 * */ static void FASTCALL(rx_irq(struct ns83820 *dev)); -static void rx_irq(struct ns83820 *dev) +static void fastcall rx_irq(struct ns83820 *dev) { struct rx_info *info = &dev->rx_info; unsigned next_rx; @@ -1585,6 +1585,7 @@ static void ns83820_run_bist(struct ns83 dprintk("%s: done %s in %d loops\n", dev->net_dev.name, name, loops); } +#ifdef PHY_CODE_IS_FINISHED static void ns83820_mii_write_bit(struct ns83820 *dev, int bit) { /* drive MDC low */ @@ -1757,6 +1758,7 @@ static void ns83820_probe_phy(struct ns8 dprintk("version: 0x%04x 0x%04x\n", a, b); } } +#endif static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_device_id *id) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/smc9194.c linux-2.4.28-pre3/drivers/net/smc9194.c --- linux-2.4.27/drivers/net/smc9194.c 2003-06-13 14:51:35.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/smc9194.c 2004-09-10 19:36:12.000000000 +0000 @@ -1132,131 +1132,6 @@ static void smc_timeout(struct net_devic netif_wake_queue(dev); } -/*-------------------------------------------------------------------- - . - . This is the main routine of the driver, to handle the device when - . it needs some attention. - . - . So: - . first, save state of the chipset - . branch off into routines to handle each case, and acknowledge - . each to the interrupt register - . and finally restore state. - . - ---------------------------------------------------------------------*/ - -static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs) -{ - struct net_device *dev = dev_id; - int ioaddr = dev->base_addr; - struct smc_local *lp = (struct smc_local *)dev->priv; - - byte status; - word card_stats; - byte mask; - int timeout; - /* state registers */ - word saved_bank; - word saved_pointer; - - - - PRINTK3((CARDNAME": SMC interrupt started \n")); - - saved_bank = inw( ioaddr + BANK_SELECT ); - - SMC_SELECT_BANK(2); - saved_pointer = inw( ioaddr + POINTER ); - - mask = inb( ioaddr + INT_MASK ); - /* clear all interrupts */ - outb( 0, ioaddr + INT_MASK ); - - - /* set a timeout value, so I don't stay here forever */ - timeout = 4; - - PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask )); - do { - /* read the status flag, and mask it */ - status = inb( ioaddr + INTERRUPT ) & mask; - if (!status ) - break; - - PRINTK3((KERN_WARNING CARDNAME - ": Handling interrupt status %x \n", status )); - - if (status & IM_RCV_INT) { - /* Got a packet(s). */ - PRINTK2((KERN_WARNING CARDNAME - ": Receive Interrupt\n")); - smc_rcv(dev); - } else if (status & IM_TX_INT ) { - PRINTK2((KERN_WARNING CARDNAME - ": TX ERROR handled\n")); - smc_tx(dev); - outb(IM_TX_INT, ioaddr + INTERRUPT ); - } else if (status & IM_TX_EMPTY_INT ) { - /* update stats */ - SMC_SELECT_BANK( 0 ); - card_stats = inw( ioaddr + COUNTER ); - /* single collisions */ - lp->stats.collisions += card_stats & 0xF; - card_stats >>= 4; - /* multiple collisions */ - lp->stats.collisions += card_stats & 0xF; - - /* these are for when linux supports these statistics */ - - SMC_SELECT_BANK( 2 ); - PRINTK2((KERN_WARNING CARDNAME - ": TX_BUFFER_EMPTY handled\n")); - outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT ); - mask &= ~IM_TX_EMPTY_INT; - lp->stats.tx_packets += lp->packets_waiting; - lp->packets_waiting = 0; - - } else if (status & IM_ALLOC_INT ) { - PRINTK2((KERN_DEBUG CARDNAME - ": Allocation interrupt \n")); - /* clear this interrupt so it doesn't happen again */ - mask &= ~IM_ALLOC_INT; - - smc_hardware_send_packet( dev ); - - /* enable xmit interrupts based on this */ - mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); - - /* and let the card send more packets to me */ - netif_wake_queue(dev); - - PRINTK2((CARDNAME": Handoff done successfully.\n")); - } else if (status & IM_RX_OVRN_INT ) { - lp->stats.rx_errors++; - lp->stats.rx_fifo_errors++; - outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT ); - } else if (status & IM_EPH_INT ) { - PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n")); - } else if (status & IM_ERCV_INT ) { - PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n")); - outb( IM_ERCV_INT, ioaddr + INTERRUPT ); - } - } while ( timeout -- ); - - - /* restore state register */ - SMC_SELECT_BANK( 2 ); - outb( mask, ioaddr + INT_MASK ); - - PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask )); - outw( saved_pointer, ioaddr + POINTER ); - - SMC_SELECT_BANK( saved_bank ); - - PRINTK3((CARDNAME ": Interrupt done\n")); - return; -} - /*------------------------------------------------------------- . . smc_rcv - receive a packet from the card @@ -1448,6 +1323,131 @@ static void smc_tx( struct net_device * return; } +/*-------------------------------------------------------------------- + . + . This is the main routine of the driver, to handle the device when + . it needs some attention. + . + . So: + . first, save state of the chipset + . branch off into routines to handle each case, and acknowledge + . each to the interrupt register + . and finally restore state. + . + ---------------------------------------------------------------------*/ + +static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs) +{ + struct net_device *dev = dev_id; + int ioaddr = dev->base_addr; + struct smc_local *lp = (struct smc_local *)dev->priv; + + byte status; + word card_stats; + byte mask; + int timeout; + /* state registers */ + word saved_bank; + word saved_pointer; + + + + PRINTK3((CARDNAME": SMC interrupt started \n")); + + saved_bank = inw( ioaddr + BANK_SELECT ); + + SMC_SELECT_BANK(2); + saved_pointer = inw( ioaddr + POINTER ); + + mask = inb( ioaddr + INT_MASK ); + /* clear all interrupts */ + outb( 0, ioaddr + INT_MASK ); + + + /* set a timeout value, so I don't stay here forever */ + timeout = 4; + + PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask )); + do { + /* read the status flag, and mask it */ + status = inb( ioaddr + INTERRUPT ) & mask; + if (!status ) + break; + + PRINTK3((KERN_WARNING CARDNAME + ": Handling interrupt status %x \n", status )); + + if (status & IM_RCV_INT) { + /* Got a packet(s). */ + PRINTK2((KERN_WARNING CARDNAME + ": Receive Interrupt\n")); + smc_rcv(dev); + } else if (status & IM_TX_INT ) { + PRINTK2((KERN_WARNING CARDNAME + ": TX ERROR handled\n")); + smc_tx(dev); + outb(IM_TX_INT, ioaddr + INTERRUPT ); + } else if (status & IM_TX_EMPTY_INT ) { + /* update stats */ + SMC_SELECT_BANK( 0 ); + card_stats = inw( ioaddr + COUNTER ); + /* single collisions */ + lp->stats.collisions += card_stats & 0xF; + card_stats >>= 4; + /* multiple collisions */ + lp->stats.collisions += card_stats & 0xF; + + /* these are for when linux supports these statistics */ + + SMC_SELECT_BANK( 2 ); + PRINTK2((KERN_WARNING CARDNAME + ": TX_BUFFER_EMPTY handled\n")); + outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT ); + mask &= ~IM_TX_EMPTY_INT; + lp->stats.tx_packets += lp->packets_waiting; + lp->packets_waiting = 0; + + } else if (status & IM_ALLOC_INT ) { + PRINTK2((KERN_DEBUG CARDNAME + ": Allocation interrupt \n")); + /* clear this interrupt so it doesn't happen again */ + mask &= ~IM_ALLOC_INT; + + smc_hardware_send_packet( dev ); + + /* enable xmit interrupts based on this */ + mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); + + /* and let the card send more packets to me */ + netif_wake_queue(dev); + + PRINTK2((CARDNAME": Handoff done successfully.\n")); + } else if (status & IM_RX_OVRN_INT ) { + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT ); + } else if (status & IM_EPH_INT ) { + PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n")); + } else if (status & IM_ERCV_INT ) { + PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n")); + outb( IM_ERCV_INT, ioaddr + INTERRUPT ); + } + } while ( timeout -- ); + + + /* restore state register */ + SMC_SELECT_BANK( 2 ); + outb( mask, ioaddr + INT_MASK ); + + PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask )); + outw( saved_pointer, ioaddr + POINTER ); + + SMC_SELECT_BANK( saved_bank ); + + PRINTK3((CARDNAME ": Interrupt done\n")); + return; +} + /*---------------------------------------------------- . smc_close . diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/sungem.c linux-2.4.28-pre3/drivers/net/sungem.c --- linux-2.4.27/drivers/net/sungem.c 2004-04-14 13:05:30.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/sungem.c 2004-09-10 19:37:02.000000000 +0000 @@ -2920,7 +2920,7 @@ static int __devinit gem_init_one(struct */ if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_GEM && - !pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff)) { + !pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL)) { pci_using_dac = 1; } else { err = pci_set_dma_mask(pdev, (u64) 0xffffffff); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/sungem.h linux-2.4.28-pre3/drivers/net/sungem.h --- linux-2.4.27/drivers/net/sungem.h 2002-08-03 00:39:44.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/sungem.h 2004-09-10 19:35:17.000000000 +0000 @@ -805,14 +805,14 @@ struct gem_txd { u64 buffer; }; -#define TXDCTRL_BUFSZ 0x0000000000007fff /* Buffer Size */ -#define TXDCTRL_CSTART 0x00000000001f8000 /* CSUM Start Offset */ -#define TXDCTRL_COFF 0x000000001fe00000 /* CSUM Stuff Offset */ -#define TXDCTRL_CENAB 0x0000000020000000 /* CSUM Enable */ -#define TXDCTRL_EOF 0x0000000040000000 /* End of Frame */ -#define TXDCTRL_SOF 0x0000000080000000 /* Start of Frame */ -#define TXDCTRL_INTME 0x0000000100000000 /* "Interrupt Me" */ -#define TXDCTRL_NOCRC 0x0000000200000000 /* No CRC Present */ +#define TXDCTRL_BUFSZ 0x0000000000007fffULL /* Buffer Size */ +#define TXDCTRL_CSTART 0x00000000001f8000ULL /* CSUM Start Offset */ +#define TXDCTRL_COFF 0x000000001fe00000ULL /* CSUM Stuff Offset */ +#define TXDCTRL_CENAB 0x0000000020000000ULL /* CSUM Enable */ +#define TXDCTRL_EOF 0x0000000040000000ULL /* End of Frame */ +#define TXDCTRL_SOF 0x0000000080000000ULL /* Start of Frame */ +#define TXDCTRL_INTME 0x0000000100000000ULL /* "Interrupt Me" */ +#define TXDCTRL_NOCRC 0x0000000200000000ULL /* No CRC Present */ /* GEM requires that RX descriptors are provided four at a time, * aligned. Also, the RX ring may not wrap around. This means that @@ -840,13 +840,13 @@ struct gem_rxd { u64 buffer; }; -#define RXDCTRL_TCPCSUM 0x000000000000ffff /* TCP Pseudo-CSUM */ -#define RXDCTRL_BUFSZ 0x000000007fff0000 /* Buffer Size */ -#define RXDCTRL_OWN 0x0000000080000000 /* GEM owns this entry */ -#define RXDCTRL_HASHVAL 0x0ffff00000000000 /* Hash Value */ -#define RXDCTRL_HPASS 0x1000000000000000 /* Passed Hash Filter */ -#define RXDCTRL_ALTMAC 0x2000000000000000 /* Matched ALT MAC */ -#define RXDCTRL_BAD 0x4000000000000000 /* Frame has bad CRC */ +#define RXDCTRL_TCPCSUM 0x000000000000ffffULL /* TCP Pseudo-CSUM */ +#define RXDCTRL_BUFSZ 0x000000007fff0000ULL /* Buffer Size */ +#define RXDCTRL_OWN 0x0000000080000000ULL /* GEM owns this entry */ +#define RXDCTRL_HASHVAL 0x0ffff00000000000ULL /* Hash Value */ +#define RXDCTRL_HPASS 0x1000000000000000ULL /* Passed Hash Filter */ +#define RXDCTRL_ALTMAC 0x2000000000000000ULL /* Matched ALT MAC */ +#define RXDCTRL_BAD 0x4000000000000000ULL /* Frame has bad CRC */ #define RXDCTRL_FRESH(gp) \ ((((RX_BUF_ALLOC_SIZE(gp) - RX_OFFSET) << 16) & RXDCTRL_BUFSZ) | \ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/tg3.c linux-2.4.28-pre3/drivers/net/tg3.c --- linux-2.4.27/drivers/net/tg3.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/tg3.c 2004-09-10 19:34:21.000000000 +0000 @@ -4,6 +4,9 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. + * + * Firmware is: + * Copyright (C) 2000-2003 Broadcom Corporation. */ #include @@ -56,8 +59,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.8" -#define DRV_MODULE_RELDATE "July 14, 2004" +#define DRV_MODULE_VERSION "3.9" +#define DRV_MODULE_RELDATE "August 30, 2004" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -441,9 +444,14 @@ static void tg3_switch_clocks(struct tg3 0x1f); tp->pci_clock_ctrl = clock_ctrl; - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && - (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { + if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) { + tw32_f(TG3PCI_CLOCK_CTRL, + clock_ctrl | CLOCK_CTRL_625_CORE); + udelay(40); + } + } else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { tw32_f(TG3PCI_CLOCK_CTRL, clock_ctrl | (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK)); @@ -979,7 +987,7 @@ static int tg3_set_power_state(struct tg tp->link_config.orig_autoneg = tp->link_config.autoneg; } - if (tp->phy_id != PHY_ID_SERDES) { + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { tp->link_config.speed = SPEED_10; tp->link_config.duplex = DUPLEX_HALF; tp->link_config.autoneg = AUTONEG_ENABLE; @@ -991,7 +999,7 @@ static int tg3_set_power_state(struct tg if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) { u32 mac_mode; - if (tp->phy_id != PHY_ID_SERDES) { + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); udelay(40); @@ -1486,6 +1494,18 @@ static int tg3_setup_copper_phy(struct t current_speed = SPEED_INVALID; current_duplex = DUPLEX_INVALID; + if (tp->tg3_flags2 & TG3_FLG2_CAPACITIVE_COUPLING) { + u32 val; + + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007); + tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); + if (!(val & (1 << 10))) { + val |= (1 << 10); + tg3_writephy(tp, MII_TG3_AUX_CTRL, val); + goto relink; + } + } + bmsr = 0; for (i = 0; i < 100; i++) { tg3_readphy(tp, MII_BMSR, &bmsr); @@ -1565,7 +1585,7 @@ static int tg3_setup_copper_phy(struct t tg3_setup_flow_control(tp, local_adv, remote_adv); } } - +relink: if (current_link_up == 0) { u32 tmp; @@ -1615,7 +1635,7 @@ static int tg3_setup_copper_phy(struct t tw32_f(MAC_MODE, tp->mac_mode); udelay(40); - if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) { + if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { /* Polled via timer. */ tw32_f(MAC_EVENT, 0); } else { @@ -1964,62 +1984,264 @@ static int tg3_fiber_aneg_smachine(struc static int fiber_autoneg(struct tg3 *tp, u32 *flags) { int res = 0; + struct tg3_fiber_aneginfo aninfo; + int status = ANEG_FAILED; + unsigned int tick; + u32 tmp; - if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) { - u32 dig_status; + tw32_f(MAC_TX_AUTO_NEG, 0); - dig_status = tr32(SG_DIG_STATUS); - *flags = 0; - if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE) - *flags |= MR_LP_ADV_ASYM_PAUSE; - if (dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE) - *flags |= MR_LP_ADV_SYM_PAUSE; - - if ((dig_status & SG_DIG_AUTONEG_COMPLETE) && - !(dig_status & (SG_DIG_AUTONEG_ERROR | - SG_DIG_PARTNER_FAULT_MASK))) - res = 1; - } else { - struct tg3_fiber_aneginfo aninfo; - int status = ANEG_FAILED; - unsigned int tick; - u32 tmp; + tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; + tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII); + udelay(40); - tw32_f(MAC_TX_AUTO_NEG, 0); + tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS); + udelay(40); - tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; - tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII); - udelay(40); + memset(&aninfo, 0, sizeof(aninfo)); + aninfo.flags |= MR_AN_ENABLE; + aninfo.state = ANEG_STATE_UNKNOWN; + aninfo.cur_time = 0; + tick = 0; + while (++tick < 195000) { + status = tg3_fiber_aneg_smachine(tp, &aninfo); + if (status == ANEG_DONE || status == ANEG_FAILED) + break; - tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS); - udelay(40); + udelay(1); + } - memset(&aninfo, 0, sizeof(aninfo)); - aninfo.flags |= MR_AN_ENABLE; - aninfo.state = ANEG_STATE_UNKNOWN; - aninfo.cur_time = 0; - tick = 0; - while (++tick < 195000) { - status = tg3_fiber_aneg_smachine(tp, &aninfo); - if (status == ANEG_DONE || status == ANEG_FAILED) - break; + tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); - udelay(1); + *flags = aninfo.flags; + + if (status == ANEG_DONE && + (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK | + MR_LP_ADV_FULL_DUPLEX))) + res = 1; + + return res; +} + +static void tg3_init_bcm8002(struct tg3 *tp) +{ + u32 mac_status = tr32(MAC_STATUS); + int i; + + /* Reset when initting first time or we have a link. */ + if ((tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) && + !(mac_status & MAC_STATUS_PCS_SYNCED)) + return; + + /* Set PLL lock range. */ + tg3_writephy(tp, 0x16, 0x8007); + + /* SW reset */ + tg3_writephy(tp, MII_BMCR, BMCR_RESET); + + /* Wait for reset to complete. */ + /* XXX schedule_timeout() ... */ + for (i = 0; i < 500; i++) + udelay(10); + + /* Config mode; select PMA/Ch 1 regs. */ + tg3_writephy(tp, 0x10, 0x8411); + + /* Enable auto-lock and comdet, select txclk for tx. */ + tg3_writephy(tp, 0x11, 0x0a10); + + tg3_writephy(tp, 0x18, 0x00a0); + tg3_writephy(tp, 0x16, 0x41ff); + + /* Assert and deassert POR. */ + tg3_writephy(tp, 0x13, 0x0400); + udelay(40); + tg3_writephy(tp, 0x13, 0x0000); + + tg3_writephy(tp, 0x11, 0x0a50); + udelay(40); + tg3_writephy(tp, 0x11, 0x0a10); + + /* Wait for signal to stabilize */ + /* XXX schedule_timeout() ... */ + for (i = 0; i < 15000; i++) + udelay(10); + + /* Deselect the channel register so we can read the PHYID + * later. + */ + tg3_writephy(tp, 0x10, 0x8011); +} + +static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) +{ + u32 sg_dig_ctrl, sg_dig_status; + u32 serdes_cfg, expected_sg_dig_ctrl; + int workaround, port_a; + int current_link_up; + + serdes_cfg = 0; + expected_sg_dig_ctrl = 0; + workaround = 0; + port_a = 1; + current_link_up = 0; + + if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 && + tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) { + workaround = 1; + if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) + port_a = 0; + + serdes_cfg = tr32(MAC_SERDES_CFG) & + ((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20)); + } + + sg_dig_ctrl = tr32(SG_DIG_CTRL); + + if (tp->link_config.autoneg != AUTONEG_ENABLE) { + if (sg_dig_ctrl & (1 << 31)) { + if (workaround) { + u32 val = serdes_cfg; + + if (port_a) + val |= 0xc010880; + else + val |= 0x4010880; + tw32_f(MAC_SERDES_CFG, val); + } + tw32_f(SG_DIG_CTRL, 0x01388400); } + if (mac_status & MAC_STATUS_PCS_SYNCED) { + tg3_setup_flow_control(tp, 0, 0); + current_link_up = 1; + } + goto out; + } - tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; - tw32_f(MAC_MODE, tp->mac_mode); - udelay(40); + /* Want auto-negotiation. */ + expected_sg_dig_ctrl = 0x81388400; + + /* Pause capability */ + expected_sg_dig_ctrl |= (1 << 11); - *flags = aninfo.flags; + /* Asymettric pause */ + expected_sg_dig_ctrl |= (1 << 12); - if (status == ANEG_DONE && - (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK | - MR_LP_ADV_FULL_DUPLEX))) - res = 1; + if (sg_dig_ctrl != expected_sg_dig_ctrl) { + if (workaround) + tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011880); + tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30)); + udelay(5); + tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl); + + tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED; + } else if (mac_status & (MAC_STATUS_PCS_SYNCED | + MAC_STATUS_SIGNAL_DET)) { + sg_dig_status = tr32(SG_DIG_STATUS); + + if ((sg_dig_status & (1 << 1)) && + (mac_status & MAC_STATUS_PCS_SYNCED)) { + u32 local_adv, remote_adv; + + local_adv = ADVERTISE_PAUSE_CAP; + remote_adv = 0; + if (sg_dig_status & (1 << 19)) + remote_adv |= LPA_PAUSE_CAP; + if (sg_dig_status & (1 << 20)) + remote_adv |= LPA_PAUSE_ASYM; + + tg3_setup_flow_control(tp, local_adv, remote_adv); + current_link_up = 1; + tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; + } else if (!(sg_dig_status & (1 << 1))) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) + tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; + else { + if (workaround) { + u32 val = serdes_cfg; + + if (port_a) + val |= 0xc010880; + else + val |= 0x4010880; + + tw32_f(MAC_SERDES_CFG, serdes_cfg); + } + + tw32_f(SG_DIG_CTRL, 0x01388400); + udelay(40); + + mac_status = tr32(MAC_STATUS); + if (mac_status & MAC_STATUS_PCS_SYNCED) { + tg3_setup_flow_control(tp, 0, 0); + current_link_up = 1; + } + } + } } - return res; +out: + return current_link_up; +} + +static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) +{ + int current_link_up = 0; + + if (!(mac_status & MAC_STATUS_PCS_SYNCED)) { + tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL; + goto out; + } + + if (tp->link_config.autoneg == AUTONEG_ENABLE) { + u32 flags; + int i; + + if (fiber_autoneg(tp, &flags)) { + u32 local_adv, remote_adv; + + local_adv = ADVERTISE_PAUSE_CAP; + remote_adv = 0; + if (flags & MR_LP_ADV_SYM_PAUSE) + remote_adv |= LPA_PAUSE_CAP; + if (flags & MR_LP_ADV_ASYM_PAUSE) + remote_adv |= LPA_PAUSE_ASYM; + + tg3_setup_flow_control(tp, local_adv, remote_adv); + + tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL; + current_link_up = 1; + } + for (i = 0; i < 30; i++) { + udelay(20); + tw32_f(MAC_STATUS, + (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED)); + udelay(40); + if ((tr32(MAC_STATUS) & + (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED)) == 0) + break; + } + + mac_status = tr32(MAC_STATUS); + if (current_link_up == 0 && + (mac_status & MAC_STATUS_PCS_SYNCED) && + !(mac_status & MAC_STATUS_RCVD_CFG)) + current_link_up = 1; + } else { + /* Forcing 1000FD link up. */ + current_link_up = 1; + tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL; + + tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS)); + udelay(40); + } + +out: + return current_link_up; } static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) @@ -2027,6 +2249,7 @@ static int tg3_setup_fiber_phy(struct tg u32 orig_pause_cfg; u16 orig_active_speed; u8 orig_active_duplex; + u32 mac_status; int current_link_up; int i; @@ -2036,118 +2259,43 @@ static int tg3_setup_fiber_phy(struct tg orig_active_speed = tp->link_config.active_speed; orig_active_duplex = tp->link_config.active_duplex; - tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); - tp->mac_mode |= MAC_MODE_PORT_MODE_TBI; - tw32_f(MAC_MODE, tp->mac_mode); - udelay(40); - - if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) { - /* Allow time for the hardware to auto-negotiate (195ms) */ - unsigned int tick = 0; - - while (++tick < 195000) { - if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE) - break; - udelay(1); + if (!(tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) && + netif_carrier_ok(tp->dev) && + (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) { + mac_status = tr32(MAC_STATUS); + mac_status &= (MAC_STATUS_PCS_SYNCED | + MAC_STATUS_SIGNAL_DET | + MAC_STATUS_CFG_CHANGED | + MAC_STATUS_RCVD_CFG); + if (mac_status == (MAC_STATUS_PCS_SYNCED | + MAC_STATUS_SIGNAL_DET)) { + tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED)); + return 0; } - if (tick >= 195000) - printk(KERN_INFO PFX "%s: HW autoneg failed !\n", - tp->dev->name); } - /* Reset when initting first time or we have a link. */ - if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || - (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) { - /* Set PLL lock range. */ - tg3_writephy(tp, 0x16, 0x8007); - - /* SW reset */ - tg3_writephy(tp, MII_BMCR, BMCR_RESET); - - /* Wait for reset to complete. */ - /* XXX schedule_timeout() ... */ - for (i = 0; i < 500; i++) - udelay(10); - - /* Config mode; select PMA/Ch 1 regs. */ - tg3_writephy(tp, 0x10, 0x8411); - - /* Enable auto-lock and comdet, select txclk for tx. */ - tg3_writephy(tp, 0x11, 0x0a10); - - tg3_writephy(tp, 0x18, 0x00a0); - tg3_writephy(tp, 0x16, 0x41ff); - - /* Assert and deassert POR. */ - tg3_writephy(tp, 0x13, 0x0400); - udelay(40); - tg3_writephy(tp, 0x13, 0x0000); + tw32_f(MAC_TX_AUTO_NEG, 0); - tg3_writephy(tp, 0x11, 0x0a50); - udelay(40); - tg3_writephy(tp, 0x11, 0x0a10); + tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); + tp->mac_mode |= MAC_MODE_PORT_MODE_TBI; + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); - /* Wait for signal to stabilize */ - /* XXX schedule_timeout() ... */ - for (i = 0; i < 15000; i++) - udelay(10); + if (tp->phy_id == PHY_ID_BCM8002) + tg3_init_bcm8002(tp); - /* Deselect the channel register so we can read the PHYID - * later. - */ - tg3_writephy(tp, 0x10, 0x8011); - } - - /* Enable link change interrupt unless serdes polling. */ - if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES)) - tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); - else - tw32_f(MAC_EVENT, 0); + /* Enable link change event even when serdes polling. */ + tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); udelay(40); current_link_up = 0; - if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) { - if (tp->link_config.autoneg == AUTONEG_ENABLE) { - u32 flags; - - if (fiber_autoneg(tp, &flags)) { - u32 local_adv, remote_adv; - - local_adv = ADVERTISE_PAUSE_CAP; - remote_adv = 0; - if (flags & MR_LP_ADV_SYM_PAUSE) - remote_adv |= LPA_PAUSE_CAP; - if (flags & MR_LP_ADV_ASYM_PAUSE) - remote_adv |= LPA_PAUSE_ASYM; + mac_status = tr32(MAC_STATUS); - tg3_setup_flow_control(tp, local_adv, remote_adv); - - tp->tg3_flags |= - TG3_FLAG_GOT_SERDES_FLOWCTL; - current_link_up = 1; - } - for (i = 0; i < 60; i++) { - udelay(20); - tw32_f(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)); - udelay(40); - if ((tr32(MAC_STATUS) & - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)) == 0) - break; - } - if (current_link_up == 0 && - (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) { - current_link_up = 1; - } - } else { - /* Forcing 1000FD link up. */ - current_link_up = 1; - tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL; - } - } else - tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL; + if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) + current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status); + else + current_link_up = tg3_setup_fiber_by_hand(tp, mac_status); tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; tw32_f(MAC_MODE, tp->mac_mode); @@ -2158,19 +2306,24 @@ static int tg3_setup_fiber_phy(struct tg (tp->hw_status->status & ~SD_STATUS_LINK_CHG)); for (i = 0; i < 100; i++) { - udelay(20); - tw32_f(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)); - udelay(40); - if ((tr32(MAC_STATUS) & - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)) == 0) + tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED)); + udelay(5); + if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED)) == 0) break; } - if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) + mac_status = tr32(MAC_STATUS); + if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) { current_link_up = 0; + if (tp->link_config.autoneg == AUTONEG_ENABLE) { + tw32_f(MAC_MODE, (tp->mac_mode | + MAC_MODE_SEND_CONFIGS)); + udelay(1); + tw32_f(MAC_MODE, tp->mac_mode); + } + } if (current_link_up == 1) { tp->link_config.active_speed = SPEED_1000; @@ -2202,15 +2355,6 @@ static int tg3_setup_fiber_phy(struct tg tg3_link_report(tp); } - if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) { - tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY); - udelay(40); - if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) { - tw32_f(MAC_MODE, tp->mac_mode); - udelay(40); - } - } - return 0; } @@ -2218,7 +2362,7 @@ static int tg3_setup_phy(struct tg3 *tp, { int err; - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { err = tg3_setup_fiber_phy(tp, force_reset); } else { err = tg3_setup_copper_phy(tp, force_reset); @@ -2736,11 +2880,11 @@ static void tg3_reset_task(void *_data) tg3_halt(tp); tg3_init_hw(tp); + tg3_netif_start(tp); + spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); - if (restart_timer) mod_timer(&tp->timer, jiffies + 1); } @@ -3100,9 +3244,10 @@ static int tg3_change_mtu(struct net_dev tg3_init_hw(tp); + tg3_netif_start(tp); + spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); return 0; } @@ -3593,6 +3738,8 @@ static void tg3_write_sig_legacy(struct } } +static void tg3_stop_fw(struct tg3 *); + /* tp->lock is held. */ static int tg3_chip_reset(struct tg3 *tp) { @@ -3695,6 +3842,11 @@ static int tg3_chip_reset(struct tg3 *tp tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); + if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) { + tg3_stop_fw(tp); + tw32(0x5000, 0x400); + } + tw32(GRC_MODE, tp->grc_mode); if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) { @@ -3711,7 +3863,7 @@ static int tg3_chip_reset(struct tg3 *tp tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); } - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_TBI; tw32_f(MAC_MODE, tp->mac_mode); } else @@ -5241,14 +5393,14 @@ static int tg3_reset_hw(struct tg3 *tp) tw32(MAC_LED_CTRL, tp->led_ctrl); tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { tw32_f(MAC_RX_MODE, RX_MODE_RESET); udelay(10); } tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { /* Set drive transmission level to 1.2V */ val = tr32(MAC_SERDES_CFG); @@ -5266,22 +5418,8 @@ static int tg3_reset_hw(struct tg3 *tp) tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && - tp->phy_id == PHY_ID_SERDES) { - /* Enable hardware link auto-negotiation */ - u32 digctrl, txctrl; - - digctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_CRC16_CLEAR_N | - SG_DIG_LOCAL_DUPLEX_STATUS | SG_DIG_LOCAL_LINK_STATUS | - (2 << SG_DIG_SPEED_STATUS_SHIFT) | SG_DIG_FIBER_MODE | - SG_DIG_GBIC_ENABLE; - - txctrl = tr32(MAC_SERDES_CFG); - tw32_f(MAC_SERDES_CFG, txctrl | MAC_SERDES_CFG_EDGE_SELECT); - tw32_f(SG_DIG_CTRL, digctrl | SG_DIG_SOFT_RESET); - tr32(SG_DIG_CTRL); - udelay(5); - tw32_f(SG_DIG_CTRL, digctrl); - + (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + /* Use hardware link auto-negotiation */ tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG; } @@ -5289,7 +5427,7 @@ static int tg3_reset_hw(struct tg3 *tp) if (err) return err; - if (tp->phy_id != PHY_ID_SERDES) { + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { u32 tmp; /* Clear CRC stats. */ @@ -5481,7 +5619,8 @@ static void tg3_timer(unsigned long __op need_setup = 1; } if (! netif_carrier_ok(tp->dev) && - (mac_stat & MAC_STATUS_PCS_SYNCED)) { + (mac_stat & (MAC_STATUS_PCS_SYNCED | + MAC_STATUS_SIGNAL_DET))) { need_setup = 1; } if (need_setup) { @@ -5877,7 +6016,7 @@ static unsigned long calc_crc_errors(str { struct tg3_hw_stats *hw_stats = tp->hw_stats; - if (tp->phy_id != PHY_ID_SERDES && + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { unsigned long flags; @@ -6308,7 +6447,7 @@ static int tg3_get_settings(struct net_d cmd->supported |= (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full); - if (tp->phy_id != PHY_ID_SERDES) + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) cmd->supported |= (SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_10baseT_Half | @@ -6337,7 +6476,7 @@ static int tg3_set_settings(struct net_d tp->link_config.phy_is_low_power) return -EAGAIN; - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { /* These are the only valid advertisement bits allowed. */ if (cmd->autoneg == AUTONEG_ENABLE && (cmd->advertising & ~(ADVERTISED_1000baseT_Half | @@ -6395,7 +6534,7 @@ static int tg3_set_wol(struct net_device if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; if ((wol->wolopts & WAKE_MAGIC) && - tp->phy_id == PHY_ID_SERDES && + tp->tg3_flags2 & TG3_FLG2_PHY_SERDES && !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP)) return -EINVAL; @@ -6491,10 +6630,9 @@ static int tg3_set_ringparam(struct net_ tg3_halt(tp); tg3_init_hw(tp); - netif_wake_queue(tp->dev); + tg3_netif_start(tp); spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); return 0; } @@ -6529,9 +6667,9 @@ static int tg3_set_pauseparam(struct net tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX; tg3_halt(tp); tg3_init_hw(tp); + tg3_netif_start(tp); spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); return 0; } @@ -6618,7 +6756,7 @@ static int tg3_ioctl(struct net_device * case SIOCGMIIREG: { u32 mii_regval; - if (tp->phy_id == PHY_ID_SERDES) + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) break; /* We have no PHY */ spin_lock_irq(&tp->lock); @@ -6631,7 +6769,7 @@ static int tg3_ioctl(struct net_device * } case SIOCSMIIREG: - if (tp->phy_id == PHY_ID_SERDES) + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) break; /* We have no PHY */ if (!capable(CAP_NET_ADMIN)) @@ -6868,10 +7006,10 @@ static struct subsys_tbl_ent subsys_id_t { PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */ { PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */ { PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */ - { PCI_VENDOR_ID_BROADCOM, 0x0003, PHY_ID_SERDES }, /* BCM95700A9 */ + { PCI_VENDOR_ID_BROADCOM, 0x0003, 0 }, /* BCM95700A9 */ { PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */ { PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */ - { PCI_VENDOR_ID_BROADCOM, 0x0007, PHY_ID_SERDES }, /* BCM95701A7 */ + { PCI_VENDOR_ID_BROADCOM, 0x0007, 0 }, /* BCM95701A7 */ { PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */ { PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */ { PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */ @@ -6880,7 +7018,7 @@ static struct subsys_tbl_ent subsys_id_t /* 3com boards. */ { PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */ { PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */ - { PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES }, /* 3C996SX */ + { PCI_VENDOR_ID_3COM, 0x1004, 0 }, /* 3C996SX */ { PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */ { PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */ @@ -6893,37 +7031,43 @@ static struct subsys_tbl_ent subsys_id_t /* Compaq boards. */ { PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */ { PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */ - { PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES }, /* CHANGELING */ + { PCI_VENDOR_ID_COMPAQ, 0x007d, 0 }, /* CHANGELING */ { PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */ { PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */ /* IBM boards. */ - { PCI_VENDOR_ID_IBM, 0x0281, PHY_ID_SERDES } /* IBM??? */ + { PCI_VENDOR_ID_IBM, 0x0281, 0 } /* IBM??? */ }; -static int __devinit tg3_phy_probe(struct tg3 *tp) +static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp) { - u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2; - u32 hw_phy_id, hw_phy_id_masked; - u32 val; - int i, eeprom_signature_found, err; + int i; - tp->phy_id = PHY_ID_INVALID; for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) { if ((subsys_id_to_phy_id[i].subsys_vendor == tp->pdev->subsystem_vendor) && (subsys_id_to_phy_id[i].subsys_devid == - tp->pdev->subsystem_device)) { - tp->phy_id = subsys_id_to_phy_id[i].phy_id; - break; - } + tp->pdev->subsystem_device)) + return &subsys_id_to_phy_id[i]; } + return NULL; +} + +static int __devinit tg3_phy_probe(struct tg3 *tp) +{ + u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2; + u32 hw_phy_id, hw_phy_id_masked; + u32 val; + int eeprom_signature_found, eeprom_phy_serdes, err; + tp->phy_id = PHY_ID_INVALID; eeprom_phy_id = PHY_ID_INVALID; + eeprom_phy_serdes = 0; eeprom_signature_found = 0; tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { u32 nic_cfg, led_cfg; + u32 nic_phy_id, cfg2; tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); tp->nic_sram_data_cfg = nic_cfg; @@ -6931,21 +7075,19 @@ static int __devinit tg3_phy_probe(struc eeprom_signature_found = 1; if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) == - NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) { - eeprom_phy_id = PHY_ID_SERDES; - } else { - u32 nic_phy_id; + NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) + eeprom_phy_serdes = 1; - tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id); - if (nic_phy_id != 0) { - u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK; - u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK; - - eeprom_phy_id = (id1 >> 16) << 10; - eeprom_phy_id |= (id2 & 0xfc00) << 16; - eeprom_phy_id |= (id2 & 0x03ff) << 0; - } - } + tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id); + if (nic_phy_id != 0) { + u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK; + u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK; + + eeprom_phy_id = (id1 >> 16) << 10; + eeprom_phy_id |= (id2 & 0xfc00) << 16; + eeprom_phy_id |= (id2 & 0x03ff) << 0; + } else + eeprom_phy_id = 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg); @@ -7007,6 +7149,10 @@ static int __devinit tg3_phy_probe(struc } if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL) tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP; + + tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &cfg2); + if (cfg2 & (1 << 17)) + tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING; } /* Reading the PHY ID register can conflict with ASF @@ -7033,20 +7179,31 @@ static int __devinit tg3_phy_probe(struc if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) { tp->phy_id = hw_phy_id; + if (hw_phy_id_masked == PHY_ID_BCM8002) + tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; } else { - /* phy_id currently holds the value found in the - * subsys_id_to_phy_id[] table or PHY_ID_INVALID - * if a match was not found there. - */ - if (tp->phy_id == PHY_ID_INVALID) { - if (!eeprom_signature_found || - !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK)) - return -ENODEV; + if (eeprom_signature_found) { tp->phy_id = eeprom_phy_id; + if (eeprom_phy_serdes) + tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + } else { + struct subsys_tbl_ent *p; + + /* No eeprom signature? Try the hardcoded + * subsys device table. + */ + p = lookup_by_subsys(tp); + if (!p) + return -ENODEV; + + tp->phy_id = p->phy_id; + if (!tp->phy_id || + tp->phy_id == PHY_ID_BCM8002) + tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; } } - if (tp->phy_id != PHY_ID_SERDES && + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { u32 bmsr, adv_reg, tg3_ctrl; @@ -7103,7 +7260,7 @@ skip_phy_reset: if (!eeprom_signature_found) tp->led_ctrl = LED_CTRL_MODE_PHY_1; - if (tp->phy_id == PHY_ID_SERDES) + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) tp->link_config.advertising = (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | @@ -7490,12 +7647,14 @@ static int __devinit tg3_get_invariants( grc_misc_cfg = tr32(GRC_MISC_CFG); grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK; + /* Broadcom's driver says that CIOBE multisplit has a bug */ +#if 0 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) { tp->tg3_flags |= TG3_FLAG_SPLIT_MODE; tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ; } - +#endif if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 || grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M)) @@ -7522,7 +7681,7 @@ static int __devinit tg3_get_invariants( tg3_read_partno(tp); - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT; } else { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) @@ -7545,13 +7704,13 @@ static int __devinit tg3_get_invariants( * upon subsystem IDs. */ if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && - tp->phy_id != PHY_ID_SERDES) { + !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT | TG3_FLAG_USE_LINKCHG_REG); } /* For all SERDES we poll the MAC status register. */ - if (tp->phy_id == PHY_ID_SERDES) + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) tp->tg3_flags |= TG3_FLAG_POLL_SERDES; else tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES; @@ -7987,8 +8146,8 @@ static char * __devinit tg3_phy_string(s case PHY_ID_BCM5704: return "5704"; case PHY_ID_BCM5705: return "5705"; case PHY_ID_BCM5750: return "5750"; - case PHY_ID_BCM8002: return "8002"; - case PHY_ID_SERDES: return "serdes"; + case PHY_ID_BCM8002: return "8002/serdes"; + case 0: return "serdes"; default: return "unknown"; }; } @@ -8363,11 +8522,11 @@ static int tg3_suspend(struct pci_dev *p tp->timer.expires = jiffies + tp->timer_offset; add_timer(&tp->timer); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - netif_device_attach(dev); tg3_netif_start(tp); + + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); } return err; @@ -8400,11 +8559,11 @@ static int tg3_resume(struct pci_dev *pd tg3_enable_ints(tp); + tg3_netif_start(tp); + spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); - return 0; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/tg3.h linux-2.4.28-pre3/drivers/net/tg3.h --- linux-2.4.27/drivers/net/tg3.h 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/tg3.h 2004-09-10 19:35:30.000000000 +0000 @@ -124,6 +124,7 @@ #define CHIPREV_ID_5705_A3 0x3003 #define CHIPREV_ID_5750_A0 0x4000 #define CHIPREV_ID_5750_A1 0x4001 +#define CHIPREV_ID_5750_A3 0x4003 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 @@ -2089,6 +2090,9 @@ struct tg3 { #define TG3_FLG2_PCI_EXPRESS 0x00000200 #define TG3_FLG2_ASF_NEW_HANDSHAKE 0x00000400 #define TG3_FLG2_HW_AUTONEG 0x00000800 +#define TG3_FLG2_PHY_JUST_INITTED 0x00001000 +#define TG3_FLG2_PHY_SERDES 0x00002000 +#define TG3_FLG2_CAPACITIVE_COUPLING 0x00004000 u32 split_mode_max_reqs; #define SPLIT_MODE_5704_MAX_REQ 3 @@ -2136,7 +2140,6 @@ struct tg3 { #define PHY_ID_BCM5705 0x600081a0 #define PHY_ID_BCM5750 0x60008180 #define PHY_ID_BCM8002 0x60010140 -#define PHY_ID_SERDES 0xfeedbee0 #define PHY_ID_INVALID 0xffffffff #define PHY_ID_REV_MASK 0x0000000f #define PHY_REV_BCM5401_B0 0x1 @@ -2159,7 +2162,7 @@ struct tg3 { (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ - (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES) + (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wan/dscc4.c linux-2.4.28-pre3/drivers/net/wan/dscc4.c --- linux-2.4.27/drivers/net/wan/dscc4.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wan/dscc4.c 2004-09-10 19:33:22.000000000 +0000 @@ -351,8 +351,8 @@ struct dscc4_dev_priv { #endif /* Functions prototypes */ -static inline void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *); -static inline void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *); +static void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *); +static void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *); static int dscc4_found1(struct pci_dev *, unsigned long ioaddr); static int dscc4_init_one(struct pci_dev *, const struct pci_device_id *ent); static int dscc4_open(struct net_device *); @@ -366,7 +366,6 @@ static void dscc4_tx_timeout(struct net_ static void dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs); static int dscc4_hdlc_attach(hdlc_device *, unsigned short, unsigned short); static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *); -static inline int dscc4_set_quartz(struct dscc4_dev_priv *, int); #ifdef DSCC4_POLLING static int dscc4_tx_poll(struct dscc4_dev_priv *, struct net_device *); #endif @@ -857,6 +856,18 @@ static void dscc4_init_registers(struct //scc_writel(0x00250008 & ~RxActivate, dpriv, dev, CCR2); } +static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz) +{ + int ret = 0; + + if ((hz < 0) || (hz > DSCC4_HZ_MAX)) + ret = -EOPNOTSUPP; + else + dpriv->pci_priv->xtal_hz = hz; + + return ret; +} + static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) { struct dscc4_pci_priv *ppriv; @@ -1325,18 +1336,6 @@ static int dscc4_ioctl(struct net_device return ret; } -static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz) -{ - int ret = 0; - - if ((hz < 0) || (hz > DSCC4_HZ_MAX)) - ret = -EOPNOTSUPP; - else - dpriv->pci_priv->xtal_hz = hz; - - return ret; -} - static int dscc4_match(struct thingie *p, int value) { int i; @@ -1512,7 +1511,7 @@ out: spin_unlock_irqrestore(&priv->lock, flags); } -static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv, +static void dscc4_tx_irq(struct dscc4_pci_priv *ppriv, struct dscc4_dev_priv *dpriv) { struct net_device *dev = hdlc_to_dev(&dpriv->hdlc); @@ -1681,7 +1680,7 @@ try: goto try; } -static inline void dscc4_rx_irq(struct dscc4_pci_priv *priv, +static void dscc4_rx_irq(struct dscc4_pci_priv *priv, struct dscc4_dev_priv *dpriv) { struct net_device *dev = hdlc_to_dev(&dpriv->hdlc); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wan/hd6457x.c linux-2.4.28-pre3/drivers/net/wan/hd6457x.c --- linux-2.4.27/drivers/net/wan/hd6457x.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wan/hd6457x.c 2004-09-10 19:33:06.000000000 +0000 @@ -452,8 +452,8 @@ static void sca_set_port(port_t *port) brv >>= 1; /* brv = 2^9 = 512 max in specs */ /* Baud Rate = CLOCK_BASE / TMC / 2^BR */ - tmc = CLOCK_BASE / (brv * port->settings.clock_rate); - }while(br > 1 && tmc <= 128); + tmc = CLOCK_BASE / brv / port->settings.clock_rate; + }while (br > 1 && tmc <= 128); if (tmc < 1) { tmc = 1; @@ -462,7 +462,7 @@ static void sca_set_port(port_t *port) } else if (tmc > 255) tmc = 256; /* tmc=0 means 256 - low baud rates */ - port->settings.clock_rate = CLOCK_BASE / (brv * tmc); + port->settings.clock_rate = CLOCK_BASE / brv / tmc; } else { br = 9; /* Minimum clock rate */ tmc = 256; /* 8bit = 0 */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wan/lmc/lmc_debug.c linux-2.4.28-pre3/drivers/net/wan/lmc/lmc_debug.c --- linux-2.4.27/drivers/net/wan/lmc/lmc_debug.c 2002-08-03 00:39:44.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wan/lmc/lmc_debug.c 2004-09-10 19:33:40.000000000 +0000 @@ -66,7 +66,7 @@ void lmcEventLog (u_int32_t EventNum, u_ #endif } -inline void lmc_trace(struct net_device *dev, char *msg){ +void lmc_trace(struct net_device *dev, char *msg){ #ifdef LMC_TRACE unsigned long j = jiffies + 3; /* Wait for 50 ms */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wan/lmc/lmc_debug.h linux-2.4.28-pre3/drivers/net/wan/lmc/lmc_debug.h --- linux-2.4.27/drivers/net/wan/lmc/lmc_debug.h 2000-04-21 23:08:45.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wan/lmc/lmc_debug.h 2004-09-10 19:32:00.000000000 +0000 @@ -47,6 +47,6 @@ extern u_int32_t lmcEventLogBuf[LMC_EVEN void lmcConsoleLog(char *type, unsigned char *ucData, int iLen); void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3); -inline void lmc_trace(struct net_device *dev, char *msg); +void lmc_trace(struct net_device *dev, char *msg); #endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wan/pc300_tty.c linux-2.4.28-pre3/drivers/net/wan/pc300_tty.c --- linux-2.4.27/drivers/net/wan/pc300_tty.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wan/pc300_tty.c 2004-09-10 19:34:06.000000000 +0000 @@ -702,7 +702,7 @@ static void cpc_tty_rx_task(void * data) if (cpc_tty->tty && (cpc_tty->tty->ldisc.receive_buf)) { CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name); - cpc_tty->tty->ldisc.receive_buf(cpc_tty->tty, buf->data, + cpc_tty->tty->ldisc.receive_buf(cpc_tty->tty, (const unsigned char *)buf->data, &flags, buf->size); } cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/Config.in linux-2.4.28-pre3/drivers/net/wireless/Config.in --- linux-2.4.27/drivers/net/wireless/Config.in 2004-04-14 13:05:30.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/Config.in 2004-09-10 19:33:35.000000000 +0000 @@ -27,6 +27,15 @@ if [ "$CONFIG_PCMCIA" != "n" ]; then dep_tristate ' Atmel at76c502/at76c504 PCMCIA cards' CONFIG_PCMCIA_ATMEL $CONFIG_FW_LOADER fi +# If PCI enabled, allow for prism54 driver. CONFIG_FW_LOADER required +comment 'Prism54 PCI/PCMCIA GT/Duette Driver - 802.11(a/b/g)' +dep_tristate 'Intersil Prism GT/Duette/Indigo PCI/PCMCIA' CONFIG_PRISM54 $CONFIG_EXPERIMENTAL $CONFIG_PCI $CONFIG_HOTPLUG +if [ "$CONFIG_PRISM54" != "n" ]; then + if [ "$CONFIG_FW_LOADER" != "y" ]; then + define_tristate CONFIG_FW_LOADER $CONFIG_PRISM54 + fi +fi + # yes, this works even when no drivers are selected if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" -o \ "$CONFIG_ALL_PPC" = "y" -o "$CONFIG_PCMCIA" != "n" ]; then diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/Makefile linux-2.4.28-pre3/drivers/net/wireless/Makefile --- linux-2.4.27/drivers/net/wireless/Makefile 2004-04-14 13:05:30.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/Makefile 2004-09-10 19:37:30.000000000 +0000 @@ -25,4 +25,9 @@ obj-$(CONFIG_AIRO) += airo.o obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o atmel.o +ifeq ($(CONFIG_PRISM54),y) +obj-$(CONFIG_PRISM54) += prism54/prism54.o +endif +subdir-$(CONFIG_PRISM54) += prism54 + include $(TOPDIR)/Rules.make diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/Makefile linux-2.4.28-pre3/drivers/net/wireless/prism54/Makefile --- linux-2.4.27/drivers/net/wireless/prism54/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/Makefile 2004-09-10 19:37:02.000000000 +0000 @@ -0,0 +1,12 @@ + +O_TARGET := prism54.o + +EXTRA_CFLAGS += -DPRISM54_COMPAT24 + +obj-y := isl_38xx.o islpci_dev.o islpci_eth.o \ + islpci_mgt.o islpci_hotplug.o isl_ioctl.o \ + oid_mgt.o + +obj-m += prism54.o + +include $(TOPDIR)/Rules.make diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/isl_38xx.c linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_38xx.c --- linux-2.4.27/drivers/net/wireless/prism54/isl_38xx.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_38xx.c 2004-09-10 19:37:25.000000000 +0000 @@ -0,0 +1,265 @@ +/* + * + * Copyright (C) 2002 Intersil Americas Inc. + * Copyright (C) 2003-2004 Luis R. Rodriguez _ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include + +#include +#include + +#include "prismcompat.h" +#include "isl_38xx.h" +#include "islpci_dev.h" +#include "islpci_mgt.h" + +/****************************************************************************** + Device Interface & Control functions +******************************************************************************/ + +/** + * isl38xx_disable_interrupts - disable all interrupts + * @device: pci memory base address + * + * Instructs the device to disable all interrupt reporting by asserting + * the IRQ line. New events may still show up in the interrupt identification + * register located at offset %ISL38XX_INT_IDENT_REG. + */ +void +isl38xx_disable_interrupts(void *device) +{ + isl38xx_w32_flush(device, 0x00000000, ISL38XX_INT_EN_REG); + udelay(ISL38XX_WRITEIO_DELAY); +} + +void +isl38xx_handle_sleep_request(isl38xx_control_block *control_block, + int *powerstate, void *device_base) +{ + /* device requests to go into sleep mode + * check whether the transmit queues for data and management are empty */ + if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ)) + /* data tx queue not empty */ + return; + + if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ)) + /* management tx queue not empty */ + return; + + /* check also whether received frames are pending */ + if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_DATA_LQ)) + /* data rx queue not empty */ + return; + + if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ)) + /* management rx queue not empty */ + return; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "Device going to sleep mode\n"); +#endif + + /* all queues are empty, allow the device to go into sleep mode */ + *powerstate = ISL38XX_PSM_POWERSAVE_STATE; + + /* assert the Sleep interrupt in the Device Interrupt Register */ + isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_SLEEP, + ISL38XX_DEV_INT_REG); + udelay(ISL38XX_WRITEIO_DELAY); +} + +void +isl38xx_handle_wakeup(isl38xx_control_block *control_block, + int *powerstate, void *device_base) +{ + /* device is in active state, update the powerstate flag */ + *powerstate = ISL38XX_PSM_ACTIVE_STATE; + + /* now check whether there are frames pending for the card */ + if (!isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ) + && !isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ)) + return; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_ANYTHING, "Wake up handler trigger the device\n"); +#endif + + /* either data or management transmit queue has a frame pending + * trigger the device by setting the Update bit in the Device Int reg */ + isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE, + ISL38XX_DEV_INT_REG); + udelay(ISL38XX_WRITEIO_DELAY); +} + +void +isl38xx_trigger_device(int asleep, void *device_base) +{ + struct timeval current_time; + u32 reg, counter = 0; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n"); +#endif + + /* check whether the device is in power save mode */ + if (asleep) { + /* device is in powersave, trigger the device for wakeup */ +#if VERBOSE > SHOW_ERROR_MESSAGES + do_gettimeofday(¤t_time); + DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n", + current_time.tv_sec, current_time.tv_usec); +#endif + + DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", + current_time.tv_sec, current_time.tv_usec, + readl(device_base + ISL38XX_CTRL_STAT_REG)); + udelay(ISL38XX_WRITEIO_DELAY); + + if (reg = readl(device_base + ISL38XX_INT_IDENT_REG), + reg == 0xabadface) { +#if VERBOSE > SHOW_ERROR_MESSAGES + do_gettimeofday(¤t_time); + DEBUG(SHOW_TRACING, + "%08li.%08li Device register abadface\n", + current_time.tv_sec, current_time.tv_usec); +#endif + /* read the Device Status Register until Sleepmode bit is set */ + while (reg = readl(device_base + ISL38XX_CTRL_STAT_REG), + (reg & ISL38XX_CTRL_STAT_SLEEPMODE) == 0) { + udelay(ISL38XX_WRITEIO_DELAY); + counter++; + } + + DEBUG(SHOW_TRACING, + "%08li.%08li Device register read %08x\n", + current_time.tv_sec, current_time.tv_usec, + readl(device_base + ISL38XX_CTRL_STAT_REG)); + udelay(ISL38XX_WRITEIO_DELAY); + +#if VERBOSE > SHOW_ERROR_MESSAGES + do_gettimeofday(¤t_time); + DEBUG(SHOW_TRACING, + "%08li.%08li Device asleep counter %i\n", + current_time.tv_sec, current_time.tv_usec, + counter); +#endif + } + /* assert the Wakeup interrupt in the Device Interrupt Register */ + isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_WAKEUP, + ISL38XX_DEV_INT_REG); + udelay(ISL38XX_WRITEIO_DELAY); + + /* perform another read on the Device Status Register */ + reg = readl(device_base + ISL38XX_CTRL_STAT_REG); + udelay(ISL38XX_WRITEIO_DELAY); + +#if VERBOSE > SHOW_ERROR_MESSAGES + do_gettimeofday(¤t_time); + DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", + current_time.tv_sec, current_time.tv_usec, reg); +#endif + } else { + /* device is (still) awake */ +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "Device is in active state\n"); +#endif + /* trigger the device by setting the Update bit in the Device Int reg */ + + isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE, + ISL38XX_DEV_INT_REG); + udelay(ISL38XX_WRITEIO_DELAY); + } +} + +void +isl38xx_interface_reset(void *device_base, dma_addr_t host_address) +{ + u32 reg; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_interface_reset \n"); +#endif + + /* load the address of the control block in the device */ + isl38xx_w32_flush(device_base, host_address, ISL38XX_CTRL_BLK_BASE_REG); + udelay(ISL38XX_WRITEIO_DELAY); + + /* set the reset bit in the Device Interrupt Register */ + isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_RESET, + ISL38XX_DEV_INT_REG); + udelay(ISL38XX_WRITEIO_DELAY); + + /* enable the interrupt for detecting initialization */ + + /* Note: Do not enable other interrupts here. We want the + * device to have come up first 100% before allowing any other + * interrupts. */ + reg = ISL38XX_INT_IDENT_INIT; + + isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG); + udelay(ISL38XX_WRITEIO_DELAY); /* allow complete full reset */ +} + +void +isl38xx_enable_common_interrupts(void *device_base) { + u32 reg; + reg = ( ISL38XX_INT_IDENT_UPDATE | + ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP); + isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG); + udelay(ISL38XX_WRITEIO_DELAY); +} + +int +isl38xx_in_queue(isl38xx_control_block *cb, int queue) +{ + const s32 delta = (le32_to_cpu(cb->driver_curr_frag[queue]) - + le32_to_cpu(cb->device_curr_frag[queue])); + + /* determine the amount of fragments in the queue depending on the type + * of the queue, either transmit or receive */ + + BUG_ON(delta < 0); /* driver ptr must be ahead of device ptr */ + + switch (queue) { + /* send queues */ + case ISL38XX_CB_TX_MGMTQ: + BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE); + case ISL38XX_CB_TX_DATA_LQ: + case ISL38XX_CB_TX_DATA_HQ: + BUG_ON(delta > ISL38XX_CB_TX_QSIZE); + return delta; + break; + + /* receive queues */ + case ISL38XX_CB_RX_MGMTQ: + BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE); + return ISL38XX_CB_MGMT_QSIZE - delta; + break; + + case ISL38XX_CB_RX_DATA_LQ: + case ISL38XX_CB_RX_DATA_HQ: + BUG_ON(delta > ISL38XX_CB_RX_QSIZE); + return ISL38XX_CB_RX_QSIZE - delta; + break; + } + BUG(); + return 0; +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/isl_38xx.h linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_38xx.h --- linux-2.4.27/drivers/net/wireless/prism54/isl_38xx.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_38xx.h 2004-09-10 19:36:20.000000000 +0000 @@ -0,0 +1,169 @@ +/* + * + * Copyright (C) 2002 Intersil Americas Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _ISL_38XX_H +#define _ISL_38XX_H + +#include +#include +#include + +#define ISL38XX_CB_RX_QSIZE 8 +#define ISL38XX_CB_TX_QSIZE 32 + +/* ISL38XX Access Point Specific definitions */ +#define ISL38XX_MAX_WDS_LINKS 8 + +/* ISL38xx Client Specific definitions */ +#define ISL38XX_PSM_ACTIVE_STATE 0 +#define ISL38XX_PSM_POWERSAVE_STATE 1 + +/* ISL38XX Host Interface Definitions */ +#define ISL38XX_PCI_MEM_SIZE 0x02000 +#define ISL38XX_MEMORY_WINDOW_SIZE 0x01000 +#define ISL38XX_DEV_FIRMWARE_ADDRES 0x20000 +#define ISL38XX_WRITEIO_DELAY 10 /* in us */ +#define ISL38XX_RESET_DELAY 50 /* in ms */ +#define ISL38XX_WAIT_CYCLE 10 /* in 10ms */ +#define ISL38XX_MAX_WAIT_CYCLES 10 + +/* PCI Memory Area */ +#define ISL38XX_HARDWARE_REG 0x0000 +#define ISL38XX_CARDBUS_CIS 0x0800 +#define ISL38XX_DIRECT_MEM_WIN 0x1000 + +/* Hardware registers */ +#define ISL38XX_DEV_INT_REG 0x0000 +#define ISL38XX_INT_IDENT_REG 0x0010 +#define ISL38XX_INT_ACK_REG 0x0014 +#define ISL38XX_INT_EN_REG 0x0018 +#define ISL38XX_GEN_PURP_COM_REG_1 0x0020 +#define ISL38XX_GEN_PURP_COM_REG_2 0x0024 +#define ISL38XX_CTRL_BLK_BASE_REG ISL38XX_GEN_PURP_COM_REG_1 +#define ISL38XX_DIR_MEM_BASE_REG 0x0030 +#define ISL38XX_CTRL_STAT_REG 0x0078 + +/* High end mobos queue up pci writes, the following + * is used to "read" from after a write to force flush */ +#define ISL38XX_PCI_POSTING_FLUSH ISL38XX_INT_EN_REG + +/** + * isl38xx_w32_flush - PCI iomem write helper + * @base: (host) memory base address of the device + * @val: 32bit value (host order) to write + * @offset: byte offset into @base to write value to + * + * This helper takes care of writing a 32bit datum to the + * specified offset into the device's pci memory space, and making sure + * the pci memory buffers get flushed by performing one harmless read + * from the %ISL38XX_PCI_POSTING_FLUSH offset. + */ +static inline void +isl38xx_w32_flush(void *base, u32 val, unsigned long offset) +{ + writel(val, base + offset); + (void) readl(base + ISL38XX_PCI_POSTING_FLUSH); +} + +/* Device Interrupt register bits */ +#define ISL38XX_DEV_INT_RESET 0x0001 +#define ISL38XX_DEV_INT_UPDATE 0x0002 +#define ISL38XX_DEV_INT_WAKEUP 0x0008 +#define ISL38XX_DEV_INT_SLEEP 0x0010 + +/* Interrupt Identification/Acknowledge/Enable register bits */ +#define ISL38XX_INT_IDENT_UPDATE 0x0002 +#define ISL38XX_INT_IDENT_INIT 0x0004 +#define ISL38XX_INT_IDENT_WAKEUP 0x0008 +#define ISL38XX_INT_IDENT_SLEEP 0x0010 +#define ISL38XX_INT_SOURCES 0x001E + +/* Control/Status register bits */ +#define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200 +#define ISL38XX_CTRL_STAT_CLKRUN 0x00800000 +#define ISL38XX_CTRL_STAT_RESET 0x10000000 +#define ISL38XX_CTRL_STAT_RAMBOOT 0x20000000 +#define ISL38XX_CTRL_STAT_STARTHALTED 0x40000000 +#define ISL38XX_CTRL_STAT_HOST_OVERRIDE 0x80000000 + +/* Control Block definitions */ +#define ISL38XX_CB_RX_DATA_LQ 0 +#define ISL38XX_CB_TX_DATA_LQ 1 +#define ISL38XX_CB_RX_DATA_HQ 2 +#define ISL38XX_CB_TX_DATA_HQ 3 +#define ISL38XX_CB_RX_MGMTQ 4 +#define ISL38XX_CB_TX_MGMTQ 5 +#define ISL38XX_CB_QCOUNT 6 +#define ISL38XX_CB_MGMT_QSIZE 4 +#define ISL38XX_MIN_QTHRESHOLD 4 /* fragments */ + +/* Memory Manager definitions */ +#define MGMT_FRAME_SIZE 1500 /* >= size struct obj_bsslist */ +#define MGMT_TX_FRAME_COUNT 24 /* max 4 + spare 4 + 8 init */ +#define MGMT_RX_FRAME_COUNT 24 /* 4*4 + spare 8 */ +#define MGMT_FRAME_COUNT (MGMT_TX_FRAME_COUNT + MGMT_RX_FRAME_COUNT) +#define CONTROL_BLOCK_SIZE 1024 /* should be enough */ +#define PSM_FRAME_SIZE 1536 +#define PSM_MINIMAL_STATION_COUNT 64 +#define PSM_FRAME_COUNT PSM_MINIMAL_STATION_COUNT +#define PSM_BUFFER_SIZE PSM_FRAME_SIZE * PSM_FRAME_COUNT +#define MAX_TRAP_RX_QUEUE 4 +#define HOST_MEM_BLOCK CONTROL_BLOCK_SIZE + PSM_BUFFER_SIZE + +/* Fragment package definitions */ +#define FRAGMENT_FLAG_MF 0x0001 +#define MAX_FRAGMENT_SIZE 1536 + +/* In monitor mode frames have a header. I don't know exactly how big those + * frame can be but I've never seen any frame bigger than 1584... : + */ +#define MAX_FRAGMENT_SIZE_RX 1600 + +typedef struct { + u32 address; /* physical address on host */ + u16 size; /* packet size */ + u16 flags; /* set of bit-wise flags */ +} isl38xx_fragment; + +struct isl38xx_cb { + u32 driver_curr_frag[ISL38XX_CB_QCOUNT]; + u32 device_curr_frag[ISL38XX_CB_QCOUNT]; + isl38xx_fragment rx_data_low[ISL38XX_CB_RX_QSIZE]; + isl38xx_fragment tx_data_low[ISL38XX_CB_TX_QSIZE]; + isl38xx_fragment rx_data_high[ISL38XX_CB_RX_QSIZE]; + isl38xx_fragment tx_data_high[ISL38XX_CB_TX_QSIZE]; + isl38xx_fragment rx_data_mgmt[ISL38XX_CB_MGMT_QSIZE]; + isl38xx_fragment tx_data_mgmt[ISL38XX_CB_MGMT_QSIZE]; +}; + +typedef struct isl38xx_cb isl38xx_control_block; + +/* determine number of entries currently in queue */ +int isl38xx_in_queue(isl38xx_control_block *cb, int queue); + +void isl38xx_disable_interrupts(void *); +void isl38xx_enable_common_interrupts(void *); + +void isl38xx_handle_sleep_request(isl38xx_control_block *, int *, + void *); +void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void *); +void isl38xx_trigger_device(int, void *); +void isl38xx_interface_reset(void *, dma_addr_t); + +#endif /* _ISL_38XX_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/isl_ioctl.c linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_ioctl.c --- linux-2.4.27/drivers/net/wireless/prism54/isl_ioctl.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_ioctl.c 2004-09-10 19:36:01.000000000 +0000 @@ -0,0 +1,2269 @@ +/* + * + * Copyright (C) 2002 Intersil Americas Inc. + * (C) 2003,2004 Aurelien Alleaume + * (C) 2003 Herbert Valerio Riedel + * (C) 2003 Luis R. Rodriguez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include + +#include + +#include "prismcompat.h" +#include "isl_ioctl.h" +#include "islpci_mgt.h" +#include "isl_oid.h" /* additional types and defs for isl38xx fw */ +#include "oid_mgt.h" + +#include /* New driver API */ + +static int init_mode = CARD_DEFAULT_IW_MODE; +static int init_channel = CARD_DEFAULT_CHANNEL; +static int init_wep = CARD_DEFAULT_WEP; +static int init_filter = CARD_DEFAULT_FILTER; +static int init_authen = CARD_DEFAULT_AUTHEN; +static int init_dot1x = CARD_DEFAULT_DOT1X; +static int init_conformance = CARD_DEFAULT_CONFORMANCE; +static int init_mlme = CARD_DEFAULT_MLME_MODE; + +module_param(init_mode, int, 0); +MODULE_PARM_DESC(init_mode, + "Set card mode:\n0: Auto\n1: Ad-Hoc\n2: Managed Client (Default)\n3: Master / Access Point\n4: Repeater (Not supported yet)\n5: Secondary (Not supported yet)\n6: Monitor"); + +module_param(init_channel, int, 0); +MODULE_PARM_DESC(init_channel, + "Check `iwpriv ethx channel` for available channels"); + +module_param(init_wep, int, 0); +module_param(init_filter, int, 0); + +module_param(init_authen, int, 0); +MODULE_PARM_DESC(init_authen, + "Authentication method. Can be of seven types:\n0 0x0000: None\n1 0x0001: DOT11_AUTH_OS (Default)\n2 0x0002: DOT11_AUTH_SK\n3 0x0003: DOT11_AUTH_BOTH"); + +module_param(init_dot1x, int, 0); +MODULE_PARM_DESC(init_dot1x, + "\n0: None/not set (Default)\n1: DOT11_DOT1X_AUTHENABLED\n2: DOT11_DOT1X_KEYTXENABLED"); + +module_param(init_mlme, int, 0); +MODULE_PARM_DESC(init_mlme, + "Sets the MAC layer management entity (MLME) mode of operation,\n0: DOT11_MLME_AUTO (Default)\n1: DOT11_MLME_INTERMEDIATE\n2: DOT11_MLME_EXTENDED"); + +/** + * prism54_mib_mode_helper - MIB change mode helper function + * @mib: the &struct islpci_mib object to modify + * @iw_mode: new mode (%IW_MODE_*) + * + * This is a helper function, hence it does not lock. Make sure + * caller deals with locking *if* necessary. This function sets the + * mode-dependent mib values and does the mapping of the Linux + * Wireless API modes to Device firmware modes. It also checks for + * correct valid Linux wireless modes. + */ +int +prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode) +{ + u32 config = INL_CONFIG_MANUALRUN; + u32 mode, bsstype; + + /* For now, just catch early the Repeater and Secondary modes here */ + if (iw_mode == IW_MODE_REPEAT || iw_mode == IW_MODE_SECOND) { + printk(KERN_DEBUG + "%s(): Sorry, Repeater mode and Secondary mode " + "are not yet supported by this driver.\n", __FUNCTION__); + return -EINVAL; + } + + priv->iw_mode = iw_mode; + + switch (iw_mode) { + case IW_MODE_AUTO: + mode = INL_MODE_CLIENT; + bsstype = DOT11_BSSTYPE_ANY; + break; + case IW_MODE_ADHOC: + mode = INL_MODE_CLIENT; + bsstype = DOT11_BSSTYPE_IBSS; + break; + case IW_MODE_INFRA: + mode = INL_MODE_CLIENT; + bsstype = DOT11_BSSTYPE_INFRA; + break; + case IW_MODE_MASTER: + mode = INL_MODE_AP; + bsstype = DOT11_BSSTYPE_INFRA; + break; + case IW_MODE_MONITOR: + mode = INL_MODE_PROMISCUOUS; + bsstype = DOT11_BSSTYPE_ANY; + config |= INL_CONFIG_RXANNEX; + break; + default: + return -EINVAL; + } + + if (init_wds) + config |= INL_CONFIG_WDS; + mgt_set(priv, DOT11_OID_BSSTYPE, &bsstype); + mgt_set(priv, OID_INL_CONFIG, &config); + mgt_set(priv, OID_INL_MODE, &mode); + + return 0; +} + +/** + * prism54_mib_init - fill MIB cache with defaults + * + * this function initializes the struct given as @mib with defaults, + * of which many are retrieved from the global module parameter + * variables. + */ + +void +prism54_mib_init(islpci_private *priv) +{ + u32 t; + struct obj_buffer psm_buffer = { + .size = PSM_BUFFER_SIZE, + .addr = priv->device_psm_buffer + }; + + mgt_set(priv, DOT11_OID_CHANNEL, &init_channel); + mgt_set(priv, DOT11_OID_AUTHENABLE, &init_authen); + mgt_set(priv, DOT11_OID_PRIVACYINVOKED, &init_wep); + + mgt_set(priv, DOT11_OID_PSMBUFFER, &psm_buffer); + mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &init_filter); + mgt_set(priv, DOT11_OID_DOT1XENABLE, &init_dot1x); + mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &init_mlme); + mgt_set(priv, OID_INL_DOT11D_CONFORMANCE, &init_conformance); + + t = 127; + mgt_set(priv, OID_INL_OUTPUTPOWER, &t); + + /* Important: we are setting a default wireless mode and we are + * forcing a valid one, so prism54_mib_mode_helper should just set + * mib values depending on what the wireless mode given is. No need + * for it save old values */ + if (init_mode > IW_MODE_MONITOR || init_mode < IW_MODE_AUTO) { + printk(KERN_DEBUG "%s(): You passed a non-valid init_mode. " + "Using default mode\n", __FUNCTION__); + init_mode = CARD_DEFAULT_IW_MODE; + } + /* This sets all of the mode-dependent values */ + prism54_mib_mode_helper(priv, init_mode); +} + +/* this will be executed outside of atomic context thanks to + * schedule_work(), thus we can as well use sleeping semaphore + * locking */ +void +prism54_update_stats(islpci_private *priv) +{ + char *data; + int j; + struct obj_bss bss, *bss2; + union oid_res_t r; + + if (down_interruptible(&priv->stats_sem)) + return; + +/* Noise floor. + * I'm not sure if the unit is dBm. + * Note : If we are not connected, this value seems to be irrelevant. */ + + mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); + priv->local_iwstatistics.qual.noise = r.u; + +/* Get the rssi of the link. To do this we need to retrieve a bss. */ + + /* First get the MAC address of the AP we are associated with. */ + mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r); + data = r.ptr; + + /* copy this MAC to the bss */ + memcpy(bss.address, data, 6); + kfree(data); + + /* now ask for the corresponding bss */ + j = mgt_get_request(priv, DOT11_OID_BSSFIND, 0, (void *) &bss, &r); + bss2 = r.ptr; + /* report the rssi and use it to calculate + * link quality through a signal-noise + * ratio */ + priv->local_iwstatistics.qual.level = bss2->rssi; + priv->local_iwstatistics.qual.qual = + bss2->rssi - priv->iwstatistics.qual.noise; + + kfree(bss2); + + /* report that the stats are new */ + priv->local_iwstatistics.qual.updated = 0x7; + +/* Rx : unable to decrypt the MPDU */ + mgt_get_request(priv, DOT11_OID_PRIVRXFAILED, 0, NULL, &r); + priv->local_iwstatistics.discard.code = r.u; + +/* Tx : Max MAC retries num reached */ + mgt_get_request(priv, DOT11_OID_MPDUTXFAILED, 0, NULL, &r); + priv->local_iwstatistics.discard.retries = r.u; + + up(&priv->stats_sem); + + return; +} + +struct iw_statistics * +prism54_get_wireless_stats(struct net_device *ndev) +{ + islpci_private *priv = netdev_priv(ndev); + + /* If the stats are being updated return old data */ + if (down_trylock(&priv->stats_sem) == 0) { + memcpy(&priv->iwstatistics, &priv->local_iwstatistics, + sizeof (struct iw_statistics)); + /* They won't be marked updated for the next time */ + priv->local_iwstatistics.qual.updated = 0; + up(&priv->stats_sem); + } else + priv->iwstatistics.qual.updated = 0; + + /* Update our wireless stats, but do not schedule to often + * (max 1 HZ) */ + if ((priv->stats_timestamp == 0) || + time_after(jiffies, priv->stats_timestamp + 1 * HZ)) { + schedule_work(&priv->stats_work); + priv->stats_timestamp = jiffies; + } + + return &priv->iwstatistics; +} + +static int +prism54_commit(struct net_device *ndev, struct iw_request_info *info, + char *cwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + + /* simply re-set the last set SSID, this should commit most stuff */ + + /* Commit in Monitor mode is not necessary, also setting essid + * in Monitor mode does not make sense and isn't allowed for this + * device's firmware */ + if (priv->iw_mode != IW_MODE_MONITOR) + return mgt_set_request(priv, DOT11_OID_SSID, 0, NULL); + return 0; +} + +static int +prism54_get_name(struct net_device *ndev, struct iw_request_info *info, + char *cwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + char *capabilities; + union oid_res_t r; + int rvalue; + + if (islpci_get_state(priv) < PRV_STATE_INIT) { + strncpy(cwrq, "NOT READY!", IFNAMSIZ); + return 0; + } + rvalue = mgt_get_request(priv, OID_INL_PHYCAPABILITIES, 0, NULL, &r); + + switch (r.u) { + case INL_PHYCAP_5000MHZ: + capabilities = "IEEE 802.11a/b/g"; + break; + case INL_PHYCAP_FAA: + capabilities = "IEEE 802.11b/g - FAA Support"; + break; + case INL_PHYCAP_2400MHZ: + default: + capabilities = "IEEE 802.11b/g"; /* Default */ + break; + } + strncpy(cwrq, capabilities, IFNAMSIZ); + return rvalue; +} + +static int +prism54_set_freq(struct net_device *ndev, struct iw_request_info *info, + struct iw_freq *fwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + int rvalue; + u32 c; + + if (fwrq->m < 1000) + /* we have a channel number */ + c = fwrq->m; + else + c = (fwrq->e == 1) ? channel_of_freq(fwrq->m / 100000) : 0; + + rvalue = c ? mgt_set_request(priv, DOT11_OID_CHANNEL, 0, &c) : -EINVAL; + + /* Call commit handler */ + return (rvalue ? rvalue : -EINPROGRESS); +} + +static int +prism54_get_freq(struct net_device *ndev, struct iw_request_info *info, + struct iw_freq *fwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + union oid_res_t r; + int rvalue; + + rvalue = mgt_get_request(priv, DOT11_OID_CHANNEL, 0, NULL, &r); + fwrq->i = r.u; + rvalue |= mgt_get_request(priv, DOT11_OID_FREQUENCY, 0, NULL, &r); + fwrq->m = r.u; + fwrq->e = 3; + + return rvalue; +} + +static int +prism54_set_mode(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + u32 mlmeautolevel = CARD_DEFAULT_MLME_MODE; + + /* Let's see if the user passed a valid Linux Wireless mode */ + if (*uwrq > IW_MODE_MONITOR || *uwrq < IW_MODE_AUTO) { + printk(KERN_DEBUG + "%s: %s() You passed a non-valid init_mode.\n", + priv->ndev->name, __FUNCTION__); + return -EINVAL; + } + + down_write(&priv->mib_sem); + + if (prism54_mib_mode_helper(priv, *uwrq)) { + up_write(&priv->mib_sem); + return -EOPNOTSUPP; + } + + /* the ACL code needs an intermediate mlmeautolevel. The wpa stuff an + * extended one. + */ + if ((*uwrq == IW_MODE_MASTER) && (priv->acl.policy != MAC_POLICY_OPEN)) + mlmeautolevel = DOT11_MLME_INTERMEDIATE; + if (priv->wpa) + mlmeautolevel = DOT11_MLME_EXTENDED; + + mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlmeautolevel); + + mgt_commit(priv); + priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) + ? priv->monitor_type : ARPHRD_ETHER; + up_write(&priv->mib_sem); + + return 0; +} + +/* Use mib cache */ +static int +prism54_get_mode(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + + BUG_ON((priv->iw_mode < IW_MODE_AUTO) || (priv->iw_mode > + IW_MODE_MONITOR)); + *uwrq = priv->iw_mode; + + return 0; +} + +/* we use DOT11_OID_EDTHRESHOLD. From what I guess the card will not try to + * emit data if (sensitivity > rssi - noise) (in dBm). + * prism54_set_sens does not seem to work. + */ + +static int +prism54_set_sens(struct net_device *ndev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + u32 sens; + + /* by default the card sets this to 20. */ + sens = vwrq->disabled ? 20 : vwrq->value; + + return mgt_set_request(priv, DOT11_OID_EDTHRESHOLD, 0, &sens); +} + +static int +prism54_get_sens(struct net_device *ndev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + union oid_res_t r; + int rvalue; + + rvalue = mgt_get_request(priv, DOT11_OID_EDTHRESHOLD, 0, NULL, &r); + + vwrq->value = r.u; + vwrq->disabled = (vwrq->value == 0); + vwrq->fixed = 1; + + return rvalue; +} + +static int +prism54_get_range(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + struct iw_range *range = (struct iw_range *) extra; + islpci_private *priv = netdev_priv(ndev); + u8 *data; + int i, m, rvalue; + struct obj_frequencies *freq; + union oid_res_t r; + + memset(range, 0, sizeof (struct iw_range)); + dwrq->length = sizeof (struct iw_range); + + /* set the wireless extension version number */ + range->we_version_source = SUPPORTED_WIRELESS_EXT; + range->we_version_compiled = WIRELESS_EXT; + + /* Now the encoding capabilities */ + range->num_encoding_sizes = 3; + /* 64(40) bits WEP */ + range->encoding_size[0] = 5; + /* 128(104) bits WEP */ + range->encoding_size[1] = 13; + /* 256 bits for WPA-PSK */ + range->encoding_size[2] = 32; + /* 4 keys are allowed */ + range->max_encoding_tokens = 4; + + /* we don't know the quality range... */ + range->max_qual.level = 0; + range->max_qual.noise = 0; + range->max_qual.qual = 0; + /* these value describe an average quality. Needs more tweaking... */ + range->avg_qual.level = -80; /* -80 dBm */ + range->avg_qual.noise = 0; /* don't know what to put here */ + range->avg_qual.qual = 0; + + range->sensitivity = 200; + + /* retry limit capabilities */ + range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; + range->retry_flags = IW_RETRY_LIMIT; + range->r_time_flags = IW_RETRY_LIFETIME; + + /* I don't know the range. Put stupid things here */ + range->min_retry = 1; + range->max_retry = 65535; + range->min_r_time = 1024; + range->max_r_time = 65535 * 1024; + + /* txpower is supported in dBm's */ + range->txpower_capa = IW_TXPOW_DBM; + + if (islpci_get_state(priv) < PRV_STATE_INIT) + return 0; + + /* Request the device for the supported frequencies + * not really relevant since some devices will report the 5 GHz band + * frequencies even if they don't support them. + */ + rvalue = + mgt_get_request(priv, DOT11_OID_SUPPORTEDFREQUENCIES, 0, NULL, &r); + freq = r.ptr; + + range->num_channels = freq->nr; + range->num_frequency = freq->nr; + + m = min(IW_MAX_FREQUENCIES, (int) freq->nr); + for (i = 0; i < m; i++) { + range->freq[i].m = freq->mhz[i]; + range->freq[i].e = 6; + range->freq[i].i = channel_of_freq(freq->mhz[i]); + } + kfree(freq); + + rvalue |= mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r); + data = r.ptr; + + /* We got an array of char. It is NULL terminated. */ + i = 0; + while ((i < IW_MAX_BITRATES) && (*data != 0)) { + /* the result must be in bps. The card gives us 500Kbps */ + range->bitrate[i] = *data * 500000; + i++; + data++; + } + range->num_bitrates = i; + kfree(r.ptr); + + return rvalue; +} + +/* Set AP address*/ + +static int +prism54_set_wap(struct net_device *ndev, struct iw_request_info *info, + struct sockaddr *awrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + char bssid[6]; + int rvalue; + + if (awrq->sa_family != ARPHRD_ETHER) + return -EINVAL; + + /* prepare the structure for the set object */ + memcpy(&bssid[0], awrq->sa_data, 6); + + /* set the bssid -- does this make sense when in AP mode? */ + rvalue = mgt_set_request(priv, DOT11_OID_BSSID, 0, &bssid); + + return (rvalue ? rvalue : -EINPROGRESS); /* Call commit handler */ +} + +/* get AP address*/ + +static int +prism54_get_wap(struct net_device *ndev, struct iw_request_info *info, + struct sockaddr *awrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + union oid_res_t r; + int rvalue; + + rvalue = mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r); + memcpy(awrq->sa_data, r.ptr, 6); + awrq->sa_family = ARPHRD_ETHER; + kfree(r.ptr); + + return rvalue; +} + +static int +prism54_set_scan(struct net_device *dev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + /* hehe the device does this automagicaly */ + return 0; +} + +/* a little helper that will translate our data into a card independent + * format that the Wireless Tools will understand. This was inspired by + * the "Aironet driver for 4500 and 4800 series cards" (GPL) + */ + +static char * +prism54_translate_bss(struct net_device *ndev, char *current_ev, + char *end_buf, struct obj_bss *bss, char noise) +{ + struct iw_event iwe; /* Temporary buffer */ + short cap; + islpci_private *priv = netdev_priv(ndev); + + /* The first entry must be the MAC address */ + memcpy(iwe.u.ap_addr.sa_data, bss->address, 6); + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + iwe.cmd = SIOCGIWAP; + current_ev = + iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); + + /* The following entries will be displayed in the same order we give them */ + + /* The ESSID. */ + iwe.u.data.length = bss->ssid.length; + iwe.u.data.flags = 1; + iwe.cmd = SIOCGIWESSID; + current_ev = iwe_stream_add_point(current_ev, end_buf, + &iwe, bss->ssid.octets); + + /* Capabilities */ +#define CAP_ESS 0x01 +#define CAP_IBSS 0x02 +#define CAP_CRYPT 0x10 + + /* Mode */ + cap = bss->capinfo; + iwe.u.mode = 0; + if (cap & CAP_ESS) + iwe.u.mode = IW_MODE_MASTER; + else if (cap & CAP_IBSS) + iwe.u.mode = IW_MODE_ADHOC; + iwe.cmd = SIOCGIWMODE; + if (iwe.u.mode) + current_ev = + iwe_stream_add_event(current_ev, end_buf, &iwe, + IW_EV_UINT_LEN); + + /* Encryption capability */ + if (cap & CAP_CRYPT) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + iwe.cmd = SIOCGIWENCODE; + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL); + + /* Add frequency. (short) bss->channel is the frequency in MHz */ + iwe.u.freq.m = channel_of_freq(bss->channel); + iwe.u.freq.e = 0; + iwe.cmd = SIOCGIWFREQ; + current_ev = + iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); + + /* Add quality statistics */ + iwe.u.qual.level = bss->rssi; + iwe.u.qual.noise = noise; + /* do a simple SNR for quality */ + iwe.u.qual.qual = bss->rssi - noise; + iwe.cmd = IWEVQUAL; + current_ev = + iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + + if (priv->wpa) { + u8 wpa_ie[MAX_WPA_IE_LEN]; + char *buf, *p; + size_t wpa_ie_len; + int i; + + wpa_ie_len = prism54_wpa_ie_get(priv, bss->address, wpa_ie); + if (wpa_ie_len > 0 && + (buf = kmalloc(wpa_ie_len * 2 + 10, GFP_ATOMIC))) { + p = buf; + p += sprintf(p, "wpa_ie="); + for (i = 0; i < wpa_ie_len; i++) { + p += sprintf(p, "%02x", wpa_ie[i]); + } + memset(&iwe, 0, sizeof (iwe)); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(current_ev, end_buf, + &iwe, buf); + kfree(buf); + } + } + return current_ev; +} + +int +prism54_get_scan(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + int i, rvalue; + struct obj_bsslist *bsslist; + u32 noise = 0; + char *current_ev = extra; + union oid_res_t r; + + if (islpci_get_state(priv) < PRV_STATE_INIT) { + /* device is not ready, fail gently */ + dwrq->length = 0; + return 0; + } + + /* first get the noise value. We will use it to report the link quality */ + rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); + noise = r.u; + + /* Ask the device for a list of known bss. We can report at most + * IW_MAX_AP=64 to the range struct. But the device won't repport anything + * if you change the value of IWMAX_BSS=24. + */ + rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); + bsslist = r.ptr; + + /* ok now, scan the list and translate its info */ + for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) + current_ev = prism54_translate_bss(ndev, current_ev, + extra + IW_SCAN_MAX_DATA, + &(bsslist->bsslist[i]), + noise); + kfree(bsslist); + dwrq->length = (current_ev - extra); + dwrq->flags = 0; /* todo */ + + return rvalue; +} + +static int +prism54_set_essid(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct obj_ssid essid; + + memset(essid.octets, 0, 33); + + /* Check if we were asked for `any' */ + if (dwrq->flags && dwrq->length) { + if (dwrq->length > min(33, IW_ESSID_MAX_SIZE + 1)) + return -E2BIG; + essid.length = dwrq->length - 1; + memcpy(essid.octets, extra, dwrq->length); + } else + essid.length = 0; + + if (priv->iw_mode != IW_MODE_MONITOR) + return mgt_set_request(priv, DOT11_OID_SSID, 0, &essid); + + /* If in monitor mode, just save to mib */ + mgt_set(priv, DOT11_OID_SSID, &essid); + return 0; + +} + +static int +prism54_get_essid(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct obj_ssid *essid; + union oid_res_t r; + int rvalue; + + rvalue = mgt_get_request(priv, DOT11_OID_SSID, 0, NULL, &r); + essid = r.ptr; + + if (essid->length) { + dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */ + /* if it is to big, trunk it */ + dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length + 1); + } else { + dwrq->flags = 0; + dwrq->length = 0; + } + essid->octets[essid->length] = '\0'; + memcpy(extra, essid->octets, dwrq->length); + kfree(essid); + + return rvalue; +} + +/* Provides no functionality, just completes the ioctl. In essence this is a + * just a cosmetic ioctl. + */ +static int +prism54_set_nick(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + + if (dwrq->length > IW_ESSID_MAX_SIZE) + return -E2BIG; + + down_write(&priv->mib_sem); + memset(priv->nickname, 0, sizeof (priv->nickname)); + memcpy(priv->nickname, extra, dwrq->length); + up_write(&priv->mib_sem); + + return 0; +} + +static int +prism54_get_nick(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + + dwrq->length = 0; + + down_read(&priv->mib_sem); + dwrq->length = strlen(priv->nickname) + 1; + memcpy(extra, priv->nickname, dwrq->length); + up_read(&priv->mib_sem); + + return 0; +} + +/* Set the allowed Bitrates */ + +static int +prism54_set_rate(struct net_device *ndev, + struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + + islpci_private *priv = netdev_priv(ndev); + u32 rate, profile; + char *data; + int ret, i; + union oid_res_t r; + + if (vwrq->value == -1) { + /* auto mode. No limit. */ + profile = 1; + return mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); + } + + ret = mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r); + if (ret) { + kfree(r.ptr); + return ret; + } + + rate = (u32) (vwrq->value / 500000); + data = r.ptr; + i = 0; + + while (data[i]) { + if (rate && (data[i] == rate)) { + break; + } + if (vwrq->value == i) { + break; + } + data[i] |= 0x80; + i++; + } + + if (!data[i]) { + kfree(r.ptr); + return -EINVAL; + } + + data[i] |= 0x80; + data[i + 1] = 0; + + /* Now, check if we want a fixed or auto value */ + if (vwrq->fixed) { + data[0] = data[i]; + data[1] = 0; + } + +/* + i = 0; + printk("prism54 rate: "); + while(data[i]) { + printk("%u ", data[i]); + i++; + } + printk("0\n"); +*/ + profile = -1; + ret = mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); + ret |= mgt_set_request(priv, DOT11_OID_EXTENDEDRATES, 0, data); + ret |= mgt_set_request(priv, DOT11_OID_RATES, 0, data); + + kfree(r.ptr); + + return ret; +} + +/* Get the current bit rate */ +static int +prism54_get_rate(struct net_device *ndev, + struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + int rvalue; + char *data; + union oid_res_t r; + + /* Get the current bit rate */ + if ((rvalue = mgt_get_request(priv, GEN_OID_LINKSTATE, 0, NULL, &r))) + return rvalue; + vwrq->value = r.u * 500000; + + /* request the device for the enabled rates */ + rvalue = mgt_get_request(priv, DOT11_OID_RATES, 0, NULL, &r); + if (rvalue) { + kfree(r.ptr); + return rvalue; + } + data = r.ptr; + vwrq->fixed = (data[0] != 0) && (data[1] == 0); + kfree(r.ptr); + + return 0; +} + +static int +prism54_set_rts(struct net_device *ndev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + + return mgt_set_request(priv, DOT11_OID_RTSTHRESH, 0, &vwrq->value); +} + +static int +prism54_get_rts(struct net_device *ndev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + union oid_res_t r; + int rvalue; + + /* get the rts threshold */ + rvalue = mgt_get_request(priv, DOT11_OID_RTSTHRESH, 0, NULL, &r); + vwrq->value = r.u; + + return rvalue; +} + +static int +prism54_set_frag(struct net_device *ndev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + + return mgt_set_request(priv, DOT11_OID_FRAGTHRESH, 0, &vwrq->value); +} + +static int +prism54_get_frag(struct net_device *ndev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + union oid_res_t r; + int rvalue; + + rvalue = mgt_get_request(priv, DOT11_OID_FRAGTHRESH, 0, NULL, &r); + vwrq->value = r.u; + + return rvalue; +} + +/* Here we have (min,max) = max retries for (small frames, big frames). Where + * big frame <=> bigger than the rts threshold + * small frame <=> smaller than the rts threshold + * This is not really the behavior expected by the wireless tool but it seems + * to be a common behavior in other drivers. + */ + +static int +prism54_set_retry(struct net_device *ndev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + u32 slimit = 0, llimit = 0; /* short and long limit */ + u32 lifetime = 0; + int rvalue = 0; + + if (vwrq->disabled) + /* we cannot disable this feature */ + return -EINVAL; + + if (vwrq->flags & IW_RETRY_LIMIT) { + if (vwrq->flags & IW_RETRY_MIN) + slimit = vwrq->value; + else if (vwrq->flags & IW_RETRY_MAX) + llimit = vwrq->value; + else { + /* we are asked to set both */ + slimit = vwrq->value; + llimit = vwrq->value; + } + } + if (vwrq->flags & IW_RETRY_LIFETIME) + /* Wireless tools use us unit while the device uses 1024 us unit */ + lifetime = vwrq->value / 1024; + + /* now set what is requested */ + if (slimit) + rvalue = + mgt_set_request(priv, DOT11_OID_SHORTRETRIES, 0, &slimit); + if (llimit) + rvalue |= + mgt_set_request(priv, DOT11_OID_LONGRETRIES, 0, &llimit); + if (lifetime) + rvalue |= + mgt_set_request(priv, DOT11_OID_MAXTXLIFETIME, 0, + &lifetime); + return rvalue; +} + +static int +prism54_get_retry(struct net_device *ndev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + union oid_res_t r; + int rvalue = 0; + vwrq->disabled = 0; /* It cannot be disabled */ + + if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + /* we are asked for the life time */ + rvalue = + mgt_get_request(priv, DOT11_OID_MAXTXLIFETIME, 0, NULL, &r); + vwrq->value = r.u * 1024; + vwrq->flags = IW_RETRY_LIFETIME; + } else if ((vwrq->flags & IW_RETRY_MAX)) { + /* we are asked for the long retry limit */ + rvalue |= + mgt_get_request(priv, DOT11_OID_LONGRETRIES, 0, NULL, &r); + vwrq->value = r.u; + vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; + } else { + /* default. get the short retry limit */ + rvalue |= + mgt_get_request(priv, DOT11_OID_SHORTRETRIES, 0, NULL, &r); + vwrq->value = r.u; + vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MIN; + } + + return rvalue; +} + +static int +prism54_set_encode(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + int rvalue = 0, force = 0; + int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; + union oid_res_t r; + + /* with the new API, it's impossible to get a NULL pointer. + * New version of iwconfig set the IW_ENCODE_NOKEY flag + * when no key is given, but older versions don't. */ + + if (dwrq->length > 0) { + /* we have a key to set */ + int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + int current_index; + struct obj_key key = { DOT11_PRIV_WEP, 0, "" }; + + /* get the current key index */ + rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); + current_index = r.u; + /* Verify that the key is not marked as invalid */ + if (!(dwrq->flags & IW_ENCODE_NOKEY)) { + key.length = dwrq->length > sizeof (key.key) ? + sizeof (key.key) : dwrq->length; + memcpy(key.key, extra, key.length); + if (key.length == 32) + /* we want WPA-PSK */ + key.type = DOT11_PRIV_TKIP; + if ((index < 0) || (index > 3)) + /* no index provided use the current one */ + index = current_index; + + /* now send the key to the card */ + rvalue |= + mgt_set_request(priv, DOT11_OID_DEFKEYX, index, + &key); + } + /* + * If a valid key is set, encryption should be enabled + * (user may turn it off later). + * This is also how "iwconfig ethX key on" works + */ + if ((index == current_index) && (key.length > 0)) + force = 1; + } else { + int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + if ((index >= 0) && (index <= 3)) { + /* we want to set the key index */ + rvalue |= + mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, + &index); + } else { + if (!dwrq->flags & IW_ENCODE_MODE) { + /* we cannot do anything. Complain. */ + return -EINVAL; + } + } + } + /* now read the flags */ + if (dwrq->flags & IW_ENCODE_DISABLED) { + /* Encoding disabled, + * authen = DOT11_AUTH_OS; + * invoke = 0; + * exunencrypt = 0; */ + } + if (dwrq->flags & IW_ENCODE_OPEN) + /* Encode but accept non-encoded packets. No auth */ + invoke = 1; + if ((dwrq->flags & IW_ENCODE_RESTRICTED) || force) { + /* Refuse non-encoded packets. Auth */ + authen = DOT11_AUTH_BOTH; + invoke = 1; + exunencrypt = 1; + } + /* do the change if requested */ + if ((dwrq->flags & IW_ENCODE_MODE) || force) { + rvalue |= + mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); + rvalue |= + mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke); + rvalue |= + mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, + &exunencrypt); + } + return rvalue; +} + +static int +prism54_get_encode(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct obj_key *key; + u32 devindex, index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + u32 authen = 0, invoke = 0, exunencrypt = 0; + int rvalue; + union oid_res_t r; + + /* first get the flags */ + rvalue = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); + authen = r.u; + rvalue |= mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); + invoke = r.u; + rvalue |= mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); + exunencrypt = r.u; + + if (invoke && (authen == DOT11_AUTH_BOTH) && exunencrypt) + dwrq->flags = IW_ENCODE_RESTRICTED; + else if ((authen == DOT11_AUTH_OS) && !exunencrypt) { + if (invoke) + dwrq->flags = IW_ENCODE_OPEN; + else + dwrq->flags = IW_ENCODE_DISABLED; + } else + /* The card should not work in this state */ + dwrq->flags = 0; + + /* get the current device key index */ + rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); + devindex = r.u; + /* Now get the key, return it */ + if ((index < 0) || (index > 3)) + /* no index provided, use the current one */ + index = devindex; + rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r); + key = r.ptr; + dwrq->length = key->length; + memcpy(extra, key->key, dwrq->length); + kfree(key); + /* return the used key index */ + dwrq->flags |= devindex + 1; + + return rvalue; +} + +static int +prism54_get_txpower(struct net_device *ndev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + union oid_res_t r; + int rvalue; + + rvalue = mgt_get_request(priv, OID_INL_OUTPUTPOWER, 0, NULL, &r); + /* intersil firmware operates in 0.25 dBm (1/4 dBm) */ + vwrq->value = (s32) r.u / 4; + vwrq->fixed = 1; + /* radio is not turned of + * btw: how is possible to turn off only the radio + */ + vwrq->disabled = 0; + + return rvalue; +} + +static int +prism54_set_txpower(struct net_device *ndev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + s32 u = vwrq->value; + + /* intersil firmware operates in 0.25 dBm (1/4) */ + u *= 4; + if (vwrq->disabled) { + /* don't know how to disable radio */ + printk(KERN_DEBUG + "%s: %s() disabling radio is not yet supported.\n", + priv->ndev->name, __FUNCTION__); + return -ENOTSUPP; + } else if (vwrq->fixed) + /* currently only fixed value is supported */ + return mgt_set_request(priv, OID_INL_OUTPUTPOWER, 0, &u); + else { + printk(KERN_DEBUG + "%s: %s() auto power will be implemented later.\n", + priv->ndev->name, __FUNCTION__); + return -ENOTSUPP; + } +} + +static int +prism54_reset(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) +{ + islpci_reset(netdev_priv(ndev), 0); + + return 0; +} + +static int +prism54_get_oid(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + union oid_res_t r; + int rvalue; + enum oid_num_t n = dwrq->flags; + + rvalue = mgt_get_request((islpci_private *) ndev->priv, n, 0, NULL, &r); + dwrq->length = mgt_response_to_str(n, &r, extra); + if ((isl_oid[n].flags & OID_FLAG_TYPE) != OID_TYPE_U32) + kfree(r.ptr); + return rvalue; +} + +static int +prism54_set_u32(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) +{ + u32 oid = uwrq[0], u = uwrq[1]; + + return mgt_set_request((islpci_private *) ndev->priv, oid, 0, &u); +} + +static int +prism54_set_raw(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + u32 oid = dwrq->flags; + + return mgt_set_request((islpci_private *) ndev->priv, oid, 0, extra); +} + +void +prism54_acl_init(struct islpci_acl *acl) +{ + sema_init(&acl->sem, 1); + INIT_LIST_HEAD(&acl->mac_list); + acl->size = 0; + acl->policy = MAC_POLICY_OPEN; +} + +static void +prism54_clear_mac(struct islpci_acl *acl) +{ + struct list_head *ptr, *next; + struct mac_entry *entry; + + if (down_interruptible(&acl->sem)) + return; + + if (acl->size == 0) { + up(&acl->sem); + return; + } + + for (ptr = acl->mac_list.next, next = ptr->next; + ptr != &acl->mac_list; ptr = next, next = ptr->next) { + entry = list_entry(ptr, struct mac_entry, _list); + list_del(ptr); + kfree(entry); + } + acl->size = 0; + up(&acl->sem); +} + +void +prism54_acl_clean(struct islpci_acl *acl) +{ + prism54_clear_mac(acl); +} + +static int +prism54_add_mac(struct net_device *ndev, struct iw_request_info *info, + struct sockaddr *awrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct islpci_acl *acl = &priv->acl; + struct mac_entry *entry; + struct sockaddr *addr = (struct sockaddr *) extra; + + if (addr->sa_family != ARPHRD_ETHER) + return -EOPNOTSUPP; + + entry = kmalloc(sizeof (struct mac_entry), GFP_KERNEL); + if (entry == NULL) + return -ENOMEM; + + memcpy(entry->addr, addr->sa_data, ETH_ALEN); + + if (down_interruptible(&acl->sem)) { + kfree(entry); + return -ERESTARTSYS; + } + list_add_tail(&entry->_list, &acl->mac_list); + acl->size++; + up(&acl->sem); + + return 0; +} + +static int +prism54_del_mac(struct net_device *ndev, struct iw_request_info *info, + struct sockaddr *awrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct islpci_acl *acl = &priv->acl; + struct mac_entry *entry; + struct list_head *ptr; + struct sockaddr *addr = (struct sockaddr *) extra; + + if (addr->sa_family != ARPHRD_ETHER) + return -EOPNOTSUPP; + + if (down_interruptible(&acl->sem)) + return -ERESTARTSYS; + for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { + entry = list_entry(ptr, struct mac_entry, _list); + + if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) { + list_del(ptr); + acl->size--; + kfree(entry); + up(&acl->sem); + return 0; + } + } + up(&acl->sem); + return -EINVAL; +} + +static int +prism54_get_mac(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct islpci_acl *acl = &priv->acl; + struct mac_entry *entry; + struct list_head *ptr; + struct sockaddr *dst = (struct sockaddr *) extra; + + dwrq->length = 0; + + if (down_interruptible(&acl->sem)) + return -ERESTARTSYS; + + for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { + entry = list_entry(ptr, struct mac_entry, _list); + + memcpy(dst->sa_data, entry->addr, ETH_ALEN); + dst->sa_family = ARPHRD_ETHER; + dwrq->length++; + dst++; + } + up(&acl->sem); + return 0; +} + +/* Setting policy also clears the MAC acl, even if we don't change the defaut + * policy + */ + +static int +prism54_set_policy(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct islpci_acl *acl = &priv->acl; + u32 mlmeautolevel; + + prism54_clear_mac(acl); + + if ((*uwrq < MAC_POLICY_OPEN) || (*uwrq > MAC_POLICY_REJECT)) + return -EINVAL; + + down_write(&priv->mib_sem); + + acl->policy = *uwrq; + + /* the ACL code needs an intermediate mlmeautolevel */ + if ((priv->iw_mode == IW_MODE_MASTER) && + (acl->policy != MAC_POLICY_OPEN)) + mlmeautolevel = DOT11_MLME_INTERMEDIATE; + else + mlmeautolevel = CARD_DEFAULT_MLME_MODE; + if (priv->wpa) + mlmeautolevel = DOT11_MLME_EXTENDED; + mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlmeautolevel); + /* restart the card with our new policy */ + mgt_commit(priv); + up_write(&priv->mib_sem); + + return 0; +} + +static int +prism54_get_policy(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct islpci_acl *acl = &priv->acl; + + *uwrq = acl->policy; + + return 0; +} + +/* Return 1 only if client should be accepted. */ + +static int +prism54_mac_accept(struct islpci_acl *acl, char *mac) +{ + struct list_head *ptr; + struct mac_entry *entry; + int res = 0; + + if (down_interruptible(&acl->sem)) + return -ERESTARTSYS; + + if (acl->policy == MAC_POLICY_OPEN) { + up(&acl->sem); + return 1; + } + + for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { + entry = list_entry(ptr, struct mac_entry, _list); + if (memcmp(entry->addr, mac, ETH_ALEN) == 0) { + res = 1; + break; + } + } + res = (acl->policy == MAC_POLICY_ACCEPT) ? !res : res; + up(&acl->sem); + + return res; +} + +static int +prism54_kick_all(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + struct obj_mlme *mlme; + int rvalue; + + mlme = kmalloc(sizeof (struct obj_mlme), GFP_KERNEL); + if (mlme == NULL) + return -ENOMEM; + + /* Tell the card to kick every client */ + mlme->id = 0; + rvalue = + mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme); + kfree(mlme); + + return rvalue; +} + +static int +prism54_kick_mac(struct net_device *ndev, struct iw_request_info *info, + struct sockaddr *awrq, char *extra) +{ + struct obj_mlme *mlme; + struct sockaddr *addr = (struct sockaddr *) extra; + int rvalue; + + if (addr->sa_family != ARPHRD_ETHER) + return -EOPNOTSUPP; + + mlme = kmalloc(sizeof (struct obj_mlme), GFP_KERNEL); + if (mlme == NULL) + return -ENOMEM; + + /* Tell the card to only kick the corresponding bastard */ + memcpy(mlme->address, addr->sa_data, ETH_ALEN); + mlme->id = -1; + rvalue = + mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme); + + kfree(mlme); + + return rvalue; +} + +/* Translate a TRAP oid into a wireless event. Called in islpci_mgt_receive. */ + +static void +format_event(islpci_private *priv, char *dest, const char *str, + const struct obj_mlme *mlme, u16 *length, int error) +{ + const u8 *a = mlme->address; + int n = snprintf(dest, IW_CUSTOM_MAX, + "%s %s %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X %s (%2.2X)", + str, + ((priv->iw_mode == IW_MODE_MASTER) ? "from" : "to"), + a[0], a[1], a[2], a[3], a[4], a[5], + (error ? (mlme->code ? " : REJECTED " : " : ACCEPTED ") + : ""), mlme->code); + BUG_ON(n > IW_CUSTOM_MAX); + *length = n; +} + +static void +send_formatted_event(islpci_private *priv, const char *str, + const struct obj_mlme *mlme, int error) +{ + union iwreq_data wrqu; + + wrqu.data.pointer = kmalloc(IW_CUSTOM_MAX, GFP_KERNEL); + if (!wrqu.data.pointer) + return; + wrqu.data.length = 0; + format_event(priv, wrqu.data.pointer, str, mlme, &wrqu.data.length, + error); + wireless_send_event(priv->ndev, IWEVCUSTOM, &wrqu, wrqu.data.pointer); + kfree(wrqu.data.pointer); +} + +static void +send_simple_event(islpci_private *priv, const char *str) +{ + union iwreq_data wrqu; + int n = strlen(str); + + wrqu.data.pointer = kmalloc(IW_CUSTOM_MAX, GFP_KERNEL); + if (!wrqu.data.pointer) + return; + BUG_ON(n > IW_CUSTOM_MAX); + wrqu.data.length = n; + strcpy(wrqu.data.pointer, str); + wireless_send_event(priv->ndev, IWEVCUSTOM, &wrqu, wrqu.data.pointer); + kfree(wrqu.data.pointer); +} + +static void +link_changed(struct net_device *ndev, u32 bitrate) +{ + islpci_private *priv = netdev_priv(ndev); + + if (bitrate) { + if (priv->iw_mode == IW_MODE_INFRA) { + union iwreq_data uwrq; + prism54_get_wap(ndev, NULL, (struct sockaddr *) &uwrq, + NULL); + wireless_send_event(ndev, SIOCGIWAP, &uwrq, NULL); + } else + send_simple_event(netdev_priv(ndev), + "Link established"); + } else + send_simple_event(netdev_priv(ndev), "Link lost"); +} + +/* Beacon/ProbeResp payload header */ +struct ieee80211_beacon_phdr { + u8 timestamp[8]; + u16 beacon_int; + u16 capab_info; +} __attribute__ ((packed)); + +#define WLAN_EID_GENERIC 0xdd +static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 }; + +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" + +void +prism54_wpa_ie_add(islpci_private *priv, u8 *bssid, + u8 *wpa_ie, size_t wpa_ie_len) +{ + struct list_head *ptr; + struct islpci_bss_wpa_ie *bss = NULL; + + if (wpa_ie_len > MAX_WPA_IE_LEN) + wpa_ie_len = MAX_WPA_IE_LEN; + + if (down_interruptible(&priv->wpa_sem)) + return; + + /* try to use existing entry */ + list_for_each(ptr, &priv->bss_wpa_list) { + bss = list_entry(ptr, struct islpci_bss_wpa_ie, list); + if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) { + list_move(&bss->list, &priv->bss_wpa_list); + break; + } + bss = NULL; + } + + if (bss == NULL) { + /* add a new BSS entry; if max number of entries is already + * reached, replace the least recently updated */ + if (priv->num_bss_wpa >= MAX_BSS_WPA_IE_COUNT) { + bss = list_entry(priv->bss_wpa_list.prev, + struct islpci_bss_wpa_ie, list); + list_del(&bss->list); + } else { + bss = kmalloc(sizeof (*bss), GFP_ATOMIC); + if (bss != NULL) { + priv->num_bss_wpa++; + memset(bss, 0, sizeof (*bss)); + } + } + if (bss != NULL) { + memcpy(bss->bssid, bssid, ETH_ALEN); + list_add(&bss->list, &priv->bss_wpa_list); + } + } + + if (bss != NULL) { + memcpy(bss->wpa_ie, wpa_ie, wpa_ie_len); + bss->wpa_ie_len = wpa_ie_len; + bss->last_update = jiffies; + } else { + printk(KERN_DEBUG "Failed to add BSS WPA entry for " MACSTR + "\n", MAC2STR(bssid)); + } + + /* expire old entries from WPA list */ + while (priv->num_bss_wpa > 0) { + bss = list_entry(priv->bss_wpa_list.prev, + struct islpci_bss_wpa_ie, list); + if (!time_after(jiffies, bss->last_update + 60 * HZ)) + break; + + list_del(&bss->list); + priv->num_bss_wpa--; + kfree(bss); + } + + up(&priv->wpa_sem); +} + +size_t +prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie) +{ + struct list_head *ptr; + struct islpci_bss_wpa_ie *bss = NULL; + size_t len = 0; + + if (down_interruptible(&priv->wpa_sem)) + return 0; + + list_for_each(ptr, &priv->bss_wpa_list) { + bss = list_entry(ptr, struct islpci_bss_wpa_ie, list); + if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) + break; + bss = NULL; + } + if (bss) { + len = bss->wpa_ie_len; + memcpy(wpa_ie, bss->wpa_ie, len); + } + up(&priv->wpa_sem); + + return len; +} + +void +prism54_wpa_ie_init(islpci_private *priv) +{ + INIT_LIST_HEAD(&priv->bss_wpa_list); + sema_init(&priv->wpa_sem, 1); +} + +void +prism54_wpa_ie_clean(islpci_private *priv) +{ + struct list_head *ptr, *n; + + list_for_each_safe(ptr, n, &priv->bss_wpa_list) { + struct islpci_bss_wpa_ie *bss; + bss = list_entry(ptr, struct islpci_bss_wpa_ie, list); + kfree(bss); + } +} + +static void +prism54_process_bss_data(islpci_private *priv, u32 oid, u8 *addr, + u8 *payload, size_t len) +{ + struct ieee80211_beacon_phdr *hdr; + u8 *pos, *end; + + if (!priv->wpa) + return; + + hdr = (struct ieee80211_beacon_phdr *) payload; + pos = (u8 *) (hdr + 1); + end = payload + len; + while (pos < end) { + if (pos + 2 + pos[1] > end) { + printk(KERN_DEBUG "Parsing Beacon/ProbeResp failed " + "for " MACSTR "\n", MAC2STR(addr)); + return; + } + if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 && + memcmp(pos + 2, wpa_oid, 4) == 0) { + prism54_wpa_ie_add(priv, addr, pos, pos[1] + 2); + return; + } + pos += 2 + pos[1]; + } +} + +static void +handle_request(islpci_private *priv, struct obj_mlme *mlme, enum oid_num_t oid) +{ + if (((mlme->state == DOT11_STATE_AUTHING) || + (mlme->state == DOT11_STATE_ASSOCING)) + && mgt_mlme_answer(priv)) { + /* Someone is requesting auth and we must respond. Just send back + * the trap with error code set accordingly. + */ + mlme->code = prism54_mac_accept(&priv->acl, + mlme->address) ? 0 : 1; + mgt_set_request(priv, oid, 0, mlme); + } +} + +int +prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, + char *data) +{ + struct obj_mlme *mlme = (struct obj_mlme *) data; + size_t len; + u8 *payload, *pos = (u8 *) (mlme + 1); + + len = pos[0] | (pos[1] << 8); /* little endian data length */ + payload = pos + 2; + + /* I think all trapable objects are listed here. + * Some oids have a EX version. The difference is that they are emitted + * in DOT11_MLME_EXTENDED mode (set with DOT11_OID_MLMEAUTOLEVEL) + * with more info. + * The few events already defined by the wireless tools are not really + * suited. We use the more flexible custom event facility. + */ + + /* I fear prism54_process_bss_data won't work with big endian data */ + if ((oid == DOT11_OID_BEACON) || (oid == DOT11_OID_PROBE)) + prism54_process_bss_data(priv, oid, mlme->address, + payload, len); + + mgt_le_to_cpu(isl_oid[oid].flags & OID_FLAG_TYPE, (void *) mlme); + + switch (oid) { + + case GEN_OID_LINKSTATE: + link_changed(priv->ndev, (u32) *data); + break; + + case DOT11_OID_MICFAILURE: + send_simple_event(priv, "Mic failure"); + break; + + case DOT11_OID_DEAUTHENTICATE: + send_formatted_event(priv, "DeAuthenticate request", mlme, 0); + break; + + case DOT11_OID_AUTHENTICATE: + handle_request(priv, mlme, oid); + send_formatted_event(priv, "Authenticate request", mlme, 1); + break; + + case DOT11_OID_DISASSOCIATE: + send_formatted_event(priv, "Disassociate request", mlme, 0); + break; + + case DOT11_OID_ASSOCIATE: + handle_request(priv, mlme, oid); + send_formatted_event(priv, "Associate request", mlme, 1); + break; + + case DOT11_OID_REASSOCIATE: + handle_request(priv, mlme, oid); + send_formatted_event(priv, "ReAssociate request", mlme, 1); + break; + + case DOT11_OID_BEACON: + send_formatted_event(priv, + "Received a beacon from an unkown AP", + mlme, 0); + break; + + case DOT11_OID_PROBE: + /* we received a probe from a client. */ + send_formatted_event(priv, "Received a probe from client", mlme, + 0); + break; + + /* Note : "mlme" is actually a "struct obj_mlmeex *" here, but this + * is backward compatible layout-wise with "struct obj_mlme". + */ + + case DOT11_OID_DEAUTHENTICATEEX: + send_formatted_event(priv, "DeAuthenticate request", mlme, 0); + break; + + case DOT11_OID_AUTHENTICATEEX: + handle_request(priv, mlme, oid); + send_formatted_event(priv, "Authenticate request", mlme, 1); + break; + + case DOT11_OID_DISASSOCIATEEX: + send_formatted_event(priv, "Disassociate request", mlme, 0); + break; + + case DOT11_OID_ASSOCIATEEX: + handle_request(priv, mlme, oid); + send_formatted_event(priv, "Associate request", mlme, 1); + break; + + case DOT11_OID_REASSOCIATEEX: + handle_request(priv, mlme, oid); + send_formatted_event(priv, "Reassociate request", mlme, 1); + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* + * Process a device trap. This is called via schedule_work(), outside of + * interrupt context, no locks held. + */ +void +prism54_process_trap(void *data) +{ + struct islpci_mgmtframe *frame = data; + struct net_device *ndev = frame->ndev; + enum oid_num_t n = mgt_oidtonum(frame->header->oid); + + if (n != OID_NUM_LAST) + prism54_process_trap_helper(netdev_priv(ndev), n, frame->data); + islpci_mgt_release(frame); +} + +int +prism54_set_mac_address(struct net_device *ndev, void *addr) +{ + islpci_private *priv = netdev_priv(ndev); + int ret; + + if (ndev->addr_len != 6) + return -EINVAL; + ret = mgt_set_request(priv, GEN_OID_MACADDRESS, 0, + &((struct sockaddr *) addr)->sa_data); + if (!ret) + memcpy(priv->ndev->dev_addr, + &((struct sockaddr *) addr)->sa_data, 6); + + return ret; +} + +int +prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + + down_write(&priv->mib_sem); + + priv->wpa = *uwrq; + if (priv->wpa) { + u32 l = DOT11_MLME_EXTENDED; + mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &l); + } + /* restart the card with new level. Needed ? */ + mgt_commit(priv); + up_write(&priv->mib_sem); + + return 0; +} + +int +prism54_get_wpa(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + *uwrq = priv->wpa; + return 0; +} + +int +prism54_set_prismhdr(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + priv->monitor_type = + (*uwrq ? ARPHRD_IEEE80211_PRISM : ARPHRD_IEEE80211); + if (priv->iw_mode == IW_MODE_MONITOR) + priv->ndev->type = priv->monitor_type; + + return 0; +} + +int +prism54_get_prismhdr(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + *uwrq = (priv->monitor_type == ARPHRD_IEEE80211_PRISM); + return 0; +} + +int +prism54_debug_oid(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + + priv->priv_oid = *uwrq; + printk("%s: oid 0x%08X\n", ndev->name, *uwrq); + + return 0; +} + +int +prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct islpci_mgmtframe *response = NULL; + int ret = -EIO; + + printk("%s: get_oid 0x%08X\n", ndev->name, priv->priv_oid); + data->length = 0; + + if (islpci_get_state(priv) >= PRV_STATE_INIT) { + ret = + islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, + priv->priv_oid, extra, 256, + &response); + printk("%s: ret: %i\n", ndev->name, ret); + if (ret || !response + || response->header->operation == PIMFOR_OP_ERROR) { + if (response) { + islpci_mgt_release(response); + } + printk("%s: EIO\n", ndev->name); + ret = -EIO; + } + if (!ret) { + data->length = response->header->length; + memcpy(extra, response->data, data->length); + islpci_mgt_release(response); + printk("%s: len: %i\n", ndev->name, data->length); + } + } + + return ret; +} + +int +prism54_debug_set_oid(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct islpci_mgmtframe *response = NULL; + int ret = 0, response_op = PIMFOR_OP_ERROR; + + printk("%s: set_oid 0x%08X\tlen: %d\n", ndev->name, priv->priv_oid, + data->length); + + if (islpci_get_state(priv) >= PRV_STATE_INIT) { + ret = + islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, + priv->priv_oid, extra, data->length, + &response); + printk("%s: ret: %i\n", ndev->name, ret); + if (ret || !response + || response->header->operation == PIMFOR_OP_ERROR) { + if (response) { + islpci_mgt_release(response); + } + printk("%s: EIO\n", ndev->name); + ret = -EIO; + } + if (!ret) { + response_op = response->header->operation; + printk("%s: response_op: %i\n", ndev->name, + response_op); + islpci_mgt_release(response); + } + } + + return (ret ? ret : -EINPROGRESS); +} + +static int +prism54_set_spy(struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + u32 u, oid = OID_INL_CONFIG; + + down_write(&priv->mib_sem); + mgt_get(priv, OID_INL_CONFIG, &u); + + if ((uwrq->data.length == 0) && (priv->spy_data.spy_number > 0)) + /* disable spy */ + u &= ~INL_CONFIG_RXANNEX; + else if ((uwrq->data.length > 0) && (priv->spy_data.spy_number == 0)) + /* enable spy */ + u |= INL_CONFIG_RXANNEX; + + mgt_set(priv, OID_INL_CONFIG, &u); + mgt_commit_list(priv, &oid, 1); + up_write(&priv->mib_sem); + + return iw_handler_set_spy(ndev, info, uwrq, extra); +} + +static const iw_handler prism54_handler[] = { + (iw_handler) prism54_commit, /* SIOCSIWCOMMIT */ + (iw_handler) prism54_get_name, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) prism54_set_freq, /* SIOCSIWFREQ */ + (iw_handler) prism54_get_freq, /* SIOCGIWFREQ */ + (iw_handler) prism54_set_mode, /* SIOCSIWMODE */ + (iw_handler) prism54_get_mode, /* SIOCGIWMODE */ + (iw_handler) prism54_set_sens, /* SIOCSIWSENS */ + (iw_handler) prism54_get_sens, /* SIOCGIWSENS */ + (iw_handler) NULL, /* SIOCSIWRANGE */ + (iw_handler) prism54_get_range, /* SIOCGIWRANGE */ + (iw_handler) NULL, /* SIOCSIWPRIV */ + (iw_handler) NULL, /* SIOCGIWPRIV */ + (iw_handler) NULL, /* SIOCSIWSTATS */ + (iw_handler) NULL, /* SIOCGIWSTATS */ + prism54_set_spy, /* SIOCSIWSPY */ + iw_handler_get_spy, /* SIOCGIWSPY */ + iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ + iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ + (iw_handler) prism54_set_wap, /* SIOCSIWAP */ + (iw_handler) prism54_get_wap, /* SIOCGIWAP */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCGIWAPLIST depreciated */ + (iw_handler) prism54_set_scan, /* SIOCSIWSCAN */ + (iw_handler) prism54_get_scan, /* SIOCGIWSCAN */ + (iw_handler) prism54_set_essid, /* SIOCSIWESSID */ + (iw_handler) prism54_get_essid, /* SIOCGIWESSID */ + (iw_handler) prism54_set_nick, /* SIOCSIWNICKN */ + (iw_handler) prism54_get_nick, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) prism54_set_rate, /* SIOCSIWRATE */ + (iw_handler) prism54_get_rate, /* SIOCGIWRATE */ + (iw_handler) prism54_set_rts, /* SIOCSIWRTS */ + (iw_handler) prism54_get_rts, /* SIOCGIWRTS */ + (iw_handler) prism54_set_frag, /* SIOCSIWFRAG */ + (iw_handler) prism54_get_frag, /* SIOCGIWFRAG */ + (iw_handler) prism54_set_txpower, /* SIOCSIWTXPOW */ + (iw_handler) prism54_get_txpower, /* SIOCGIWTXPOW */ + (iw_handler) prism54_set_retry, /* SIOCSIWRETRY */ + (iw_handler) prism54_get_retry, /* SIOCGIWRETRY */ + (iw_handler) prism54_set_encode, /* SIOCSIWENCODE */ + (iw_handler) prism54_get_encode, /* SIOCGIWENCODE */ + (iw_handler) NULL, /* SIOCSIWPOWER */ + (iw_handler) NULL, /* SIOCGIWPOWER */ +}; + +/* The low order bit identify a SET (0) or a GET (1) ioctl. */ + +#define PRISM54_RESET SIOCIWFIRSTPRIV +#define PRISM54_GET_POLICY SIOCIWFIRSTPRIV+1 +#define PRISM54_SET_POLICY SIOCIWFIRSTPRIV+2 +#define PRISM54_GET_MAC SIOCIWFIRSTPRIV+3 +#define PRISM54_ADD_MAC SIOCIWFIRSTPRIV+4 + +#define PRISM54_DEL_MAC SIOCIWFIRSTPRIV+6 + +#define PRISM54_KICK_MAC SIOCIWFIRSTPRIV+8 + +#define PRISM54_KICK_ALL SIOCIWFIRSTPRIV+10 + +#define PRISM54_GET_WPA SIOCIWFIRSTPRIV+11 +#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12 + +#define PRISM54_DBG_OID SIOCIWFIRSTPRIV+14 +#define PRISM54_DBG_GET_OID SIOCIWFIRSTPRIV+15 +#define PRISM54_DBG_SET_OID SIOCIWFIRSTPRIV+16 + +#define PRISM54_GET_OID SIOCIWFIRSTPRIV+17 +#define PRISM54_SET_OID_U32 SIOCIWFIRSTPRIV+18 +#define PRISM54_SET_OID_STR SIOCIWFIRSTPRIV+20 +#define PRISM54_SET_OID_ADDR SIOCIWFIRSTPRIV+22 + +#define PRISM54_GET_PRISMHDR SIOCIWFIRSTPRIV+23 +#define PRISM54_SET_PRISMHDR SIOCIWFIRSTPRIV+24 + +#define IWPRIV_SET_U32(n,x) { n, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_SET_SSID(n,x) { n, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_SET_ADDR(n,x) { n, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_GET(n,x) { n, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, "g_"x } + +#define IWPRIV_U32(n,x) IWPRIV_SET_U32(n,x), IWPRIV_GET(n,x) +#define IWPRIV_SSID(n,x) IWPRIV_SET_SSID(n,x), IWPRIV_GET(n,x) +#define IWPRIV_ADDR(n,x) IWPRIV_SET_ADDR(n,x), IWPRIV_GET(n,x) + +/* Note : limited to 128 private ioctls (wireless tools 26) */ + +static const struct iw_priv_args prism54_private_args[] = { +/*{ cmd, set_args, get_args, name } */ + {PRISM54_RESET, 0, 0, "reset"}, + {PRISM54_GET_PRISMHDR, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_prismhdr"}, + {PRISM54_SET_PRISMHDR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "set_prismhdr"}, + {PRISM54_GET_POLICY, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "getPolicy"}, + {PRISM54_SET_POLICY, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "setPolicy"}, + {PRISM54_GET_MAC, 0, IW_PRIV_TYPE_ADDR | 64, "getMac"}, + {PRISM54_ADD_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, + "addMac"}, + {PRISM54_DEL_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, + "delMac"}, + {PRISM54_KICK_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, + "kickMac"}, + {PRISM54_KICK_ALL, 0, 0, "kickAll"}, + {PRISM54_GET_WPA, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_wpa"}, + {PRISM54_SET_WPA, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "set_wpa"}, + {PRISM54_DBG_OID, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "dbg_oid"}, + {PRISM54_DBG_GET_OID, 0, IW_PRIV_TYPE_BYTE | 256, "dbg_get_oid"}, + {PRISM54_DBG_SET_OID, IW_PRIV_TYPE_BYTE | 256, 0, "dbg_set_oid"}, + /* --- sub-ioctls handlers --- */ + {PRISM54_GET_OID, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, ""}, + {PRISM54_SET_OID_U32, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, ""}, + {PRISM54_SET_OID_STR, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, ""}, + {PRISM54_SET_OID_ADDR, + IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, ""}, + /* --- sub-ioctls definitions --- */ + IWPRIV_ADDR(GEN_OID_MACADDRESS, "addr"), + IWPRIV_GET(GEN_OID_LINKSTATE, "linkstate"), + IWPRIV_U32(DOT11_OID_BSSTYPE, "bsstype"), + IWPRIV_ADDR(DOT11_OID_BSSID, "bssid"), + IWPRIV_U32(DOT11_OID_STATE, "state"), + IWPRIV_U32(DOT11_OID_AID, "aid"), + + IWPRIV_SSID(DOT11_OID_SSIDOVERRIDE, "ssidoverride"), + + IWPRIV_U32(DOT11_OID_MEDIUMLIMIT, "medlimit"), + IWPRIV_U32(DOT11_OID_BEACONPERIOD, "beacon"), + IWPRIV_U32(DOT11_OID_DTIMPERIOD, "dtimperiod"), + + IWPRIV_U32(DOT11_OID_AUTHENABLE, "authenable"), + IWPRIV_U32(DOT11_OID_PRIVACYINVOKED, "privinvok"), + IWPRIV_U32(DOT11_OID_EXUNENCRYPTED, "exunencrypt"), + + IWPRIV_U32(DOT11_OID_REKEYTHRESHOLD, "rekeythresh"), + + IWPRIV_U32(DOT11_OID_MAXTXLIFETIME, "maxtxlife"), + IWPRIV_U32(DOT11_OID_MAXRXLIFETIME, "maxrxlife"), + IWPRIV_U32(DOT11_OID_ALOFT_FIXEDRATE, "fixedrate"), + IWPRIV_U32(DOT11_OID_MAXFRAMEBURST, "frameburst"), + IWPRIV_U32(DOT11_OID_PSM, "psm"), + + IWPRIV_U32(DOT11_OID_BRIDGELOCAL, "bridge"), + IWPRIV_U32(DOT11_OID_CLIENTS, "clients"), + IWPRIV_U32(DOT11_OID_CLIENTSASSOCIATED, "clientassoc"), + IWPRIV_U32(DOT11_OID_DOT1XENABLE, "dot1xenable"), + IWPRIV_U32(DOT11_OID_ANTENNARX, "rxant"), + IWPRIV_U32(DOT11_OID_ANTENNATX, "txant"), + IWPRIV_U32(DOT11_OID_ANTENNADIVERSITY, "antdivers"), + IWPRIV_U32(DOT11_OID_EDTHRESHOLD, "edthresh"), + IWPRIV_U32(DOT11_OID_PREAMBLESETTINGS, "preamble"), + IWPRIV_GET(DOT11_OID_RATES, "rates"), + IWPRIV_U32(DOT11_OID_OUTPUTPOWER, ".11outpower"), + IWPRIV_GET(DOT11_OID_SUPPORTEDRATES, "supprates"), + IWPRIV_GET(DOT11_OID_SUPPORTEDFREQUENCIES, "suppfreq"), + + IWPRIV_U32(DOT11_OID_NOISEFLOOR, "noisefloor"), + IWPRIV_GET(DOT11_OID_FREQUENCYACTIVITY, "freqactivity"), + IWPRIV_U32(DOT11_OID_NONERPPROTECTION, "nonerpprotec"), + IWPRIV_U32(DOT11_OID_PROFILES, "profile"), + IWPRIV_GET(DOT11_OID_EXTENDEDRATES, "extrates"), + IWPRIV_U32(DOT11_OID_MLMEAUTOLEVEL, "mlmelevel"), + + IWPRIV_GET(DOT11_OID_BSSS, "bsss"), + IWPRIV_GET(DOT11_OID_BSSLIST, "bsslist"), + IWPRIV_U32(OID_INL_MODE, "mode"), + IWPRIV_U32(OID_INL_CONFIG, "config"), + IWPRIV_U32(OID_INL_DOT11D_CONFORMANCE, ".11dconform"), + IWPRIV_GET(OID_INL_PHYCAPABILITIES, "phycapa"), + IWPRIV_U32(OID_INL_OUTPUTPOWER, "outpower"), +}; + +static const iw_handler prism54_private_handler[] = { + (iw_handler) prism54_reset, + (iw_handler) prism54_get_policy, + (iw_handler) prism54_set_policy, + (iw_handler) prism54_get_mac, + (iw_handler) prism54_add_mac, + (iw_handler) NULL, + (iw_handler) prism54_del_mac, + (iw_handler) NULL, + (iw_handler) prism54_kick_mac, + (iw_handler) NULL, + (iw_handler) prism54_kick_all, + (iw_handler) prism54_get_wpa, + (iw_handler) prism54_set_wpa, + (iw_handler) NULL, + (iw_handler) prism54_debug_oid, + (iw_handler) prism54_debug_get_oid, + (iw_handler) prism54_debug_set_oid, + (iw_handler) prism54_get_oid, + (iw_handler) prism54_set_u32, + (iw_handler) NULL, + (iw_handler) prism54_set_raw, + (iw_handler) NULL, + (iw_handler) prism54_set_raw, + (iw_handler) prism54_get_prismhdr, + (iw_handler) prism54_set_prismhdr, +}; + +const struct iw_handler_def prism54_handler_def = { + .num_standard = sizeof (prism54_handler) / sizeof (iw_handler), + .num_private = sizeof (prism54_private_handler) / sizeof (iw_handler), + .num_private_args = + sizeof (prism54_private_args) / sizeof (struct iw_priv_args), + .standard = (iw_handler *) prism54_handler, + .private = (iw_handler *) prism54_private_handler, + .private_args = (struct iw_priv_args *) prism54_private_args, + .spy_offset = offsetof(islpci_private, spy_data), +}; + +/* For ioctls that don't work with the new API */ + +int +prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) +{ + + return -EOPNOTSUPP; +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/isl_ioctl.h linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_ioctl.h --- linux-2.4.27/drivers/net/wireless/prism54/isl_ioctl.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_ioctl.h 2004-09-10 19:36:06.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * + * Copyright (C) 2002 Intersil Americas Inc. + * (C) 2003 Aurelien Alleaume + * (C) 2003 Luis R. Rodriguez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _ISL_IOCTL_H +#define _ISL_IOCTL_H + +#include "islpci_mgt.h" +#include "islpci_dev.h" + +#include /* New driver API */ + +#define SUPPORTED_WIRELESS_EXT 16 + +void prism54_mib_init(islpci_private *); + +struct iw_statistics *prism54_get_wireless_stats(struct net_device *); +void prism54_update_stats(islpci_private *); + +void prism54_acl_init(struct islpci_acl *); +void prism54_acl_clean(struct islpci_acl *); + +void prism54_process_trap(void *); + +void prism54_wpa_ie_init(islpci_private *priv); +void prism54_wpa_ie_clean(islpci_private *priv); +void prism54_wpa_ie_add(islpci_private *priv, u8 *bssid, + u8 *wpa_ie, size_t wpa_ie_len); +size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie); + +int prism54_set_mac_address(struct net_device *, void *); + +int prism54_ioctl(struct net_device *, struct ifreq *, int); + +extern const struct iw_handler_def prism54_handler_def; + +#endif /* _ISL_IOCTL_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/isl_oid.h linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_oid.h --- linux-2.4.27/drivers/net/wireless/prism54/isl_oid.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_oid.h 2004-09-10 19:35:32.000000000 +0000 @@ -0,0 +1,498 @@ +/* + * + * + * Copyright (C) 2003 Herbert Valerio Riedel + * Copyright (C) 2004 Luis R. Rodriguez + * Copyright (C) 2004 Aurelien Alleaume + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#if !defined(_ISL_OID_H) +#define _ISL_OID_H + +/* + * MIB related constant and structure definitions for communicating + * with the device firmware + */ + +struct obj_ssid { + u8 length; + char octets[33]; +} __attribute__ ((packed)); + +struct obj_key { + u8 type; /* dot11_priv_t */ + u8 length; + char key[32]; +} __attribute__ ((packed)); + +struct obj_mlme { + u8 address[6]; + u16 id; + u16 state; + u16 code; +} __attribute__ ((packed)); + +struct obj_mlmeex { + u8 address[6]; + u16 id; + u16 state; + u16 code; + u16 size; + u8 data[0]; +} __attribute__ ((packed)); + +struct obj_buffer { + u32 size; + u32 addr; /* 32bit bus address */ +} __attribute__ ((packed)); + +struct obj_bss { + u8 address[6]; + int:16; /* padding */ + + char state; + char reserved; + short age; + + char quality; + char rssi; + + struct obj_ssid ssid; + short channel; + char beacon_period; + char dtim_period; + short capinfo; + short rates; + short basic_rates; + int:16; /* padding */ +} __attribute__ ((packed)); + +struct obj_bsslist { + u32 nr; + struct obj_bss bsslist[0]; +} __attribute__ ((packed)); + +struct obj_frequencies { + u16 nr; + u16 mhz[0]; +} __attribute__ ((packed)); + +/* + * in case everything's ok, the inlined function below will be + * optimized away by the compiler... + */ +static inline void +__bug_on_wrong_struct_sizes(void) +{ + BUG_ON(sizeof (struct obj_ssid) != 34); + BUG_ON(sizeof (struct obj_key) != 34); + BUG_ON(sizeof (struct obj_mlme) != 12); + BUG_ON(sizeof (struct obj_mlmeex) != 14); + BUG_ON(sizeof (struct obj_buffer) != 8); + BUG_ON(sizeof (struct obj_bss) != 60); + BUG_ON(sizeof (struct obj_bsslist) != 4); + BUG_ON(sizeof (struct obj_frequencies) != 2); +} + +enum dot11_state_t { + DOT11_STATE_NONE = 0, + DOT11_STATE_AUTHING = 1, + DOT11_STATE_AUTH = 2, + DOT11_STATE_ASSOCING = 3, + + DOT11_STATE_ASSOC = 5, + DOT11_STATE_IBSS = 6, + DOT11_STATE_WDS = 7 +}; + +enum dot11_bsstype_t { + DOT11_BSSTYPE_NONE = 0, + DOT11_BSSTYPE_INFRA = 1, + DOT11_BSSTYPE_IBSS = 2, + DOT11_BSSTYPE_ANY = 3 +}; + +enum dot11_auth_t { + DOT11_AUTH_NONE = 0, + DOT11_AUTH_OS = 1, + DOT11_AUTH_SK = 2, + DOT11_AUTH_BOTH = 3 +}; + +enum dot11_mlme_t { + DOT11_MLME_AUTO = 0, + DOT11_MLME_INTERMEDIATE = 1, + DOT11_MLME_EXTENDED = 2 +}; + +enum dot11_priv_t { + DOT11_PRIV_WEP = 0, + DOT11_PRIV_TKIP = 1 +}; + +/* Prism "Nitro" / Frameburst / "Packet Frame Grouping" + * Value is in microseconds. Represents the # microseconds + * the firmware will take to group frames before sending out then out + * together with a CSMA contention. Without this all frames are + * sent with a CSMA contention. + * Bibliography: + * http://www.hpl.hp.com/personal/Jean_Tourrilhes/Papers/Packet.Frame.Grouping.html + */ +enum dot11_maxframeburst_t { + /* Values for DOT11_OID_MAXFRAMEBURST */ + DOT11_MAXFRAMEBURST_OFF = 0, /* Card firmware default */ + DOT11_MAXFRAMEBURST_MIXED_SAFE = 650, /* 802.11 a,b,g safe */ + DOT11_MAXFRAMEBURST_IDEAL = 1300, /* Theoretical ideal level */ + DOT11_MAXFRAMEBURST_MAX = 5000, /* Use this as max, + * Note: firmware allows for greater values. This is a + * recommended max. I'll update this as I find + * out what the real MAX is. Also note that you don't necessarily + * get better results with a greater value here. + */ +}; + +/* Support for 802.11 long and short frame preambles. + * Long preamble uses 128-bit sync field, 8-bit CRC + * Short preamble uses 56-bit sync field, 16-bit CRC + * + * 802.11a -- not sure, both optionally ? + * 802.11b supports long and optionally short + * 802.11g supports both */ +enum dot11_preamblesettings_t { + DOT11_PREAMBLESETTING_LONG = 0, + /* Allows *only* long 802.11 preambles */ + DOT11_PREAMBLESETTING_SHORT = 1, + /* Allows *only* short 802.11 preambles */ + DOT11_PREAMBLESETTING_DYNAMIC = 2 + /* AutomatiGically set */ +}; + +/* Support for 802.11 slot timing (time between packets). + * + * Long uses 802.11a slot timing (9 usec ?) + * Short uses 802.11b slot timing (20 use ?) */ +enum dot11_slotsettings_t { + DOT11_SLOTSETTINGS_LONG = 0, + /* Allows *only* long 802.11b slot timing */ + DOT11_SLOTSETTINGS_SHORT = 1, + /* Allows *only* long 802.11a slot timing */ + DOT11_SLOTSETTINGS_DYNAMIC = 2 + /* AutomatiGically set */ +}; + +/* All you need to know, ERP is "Extended Rate PHY". + * An Extended Rate PHY (ERP) STA or AP shall support three different + * preamble and header formats: + * Long preamble (refer to above) + * Short preamble (refer to above) + * OFDM preamble ( ? ) + * + * I'm assuming here Protection tells the AP + * to be careful, a STA which cannot handle the long pre-amble + * has joined. + */ +enum do11_nonerpstatus_t { + DOT11_ERPSTAT_NONEPRESENT = 0, + DOT11_ERPSTAT_USEPROTECTION = 1 +}; + +/* (ERP is "Extended Rate PHY") Way to read NONERP is NON-ERP-* + * The key here is DOT11 NON ERP NEVER protects against + * NON ERP STA's. You *don't* want this unless + * you know what you are doing. It means you will only + * get Extended Rate capabilities */ +enum dot11_nonerpprotection_t { + DOT11_NONERP_NEVER = 0, + DOT11_NONERP_ALWAYS = 1, + DOT11_NONERP_DYNAMIC = 2 +}; + +/* Preset OID configuration for 802.11 modes + * Note: DOT11_OID_CW[MIN|MAX] hold the values of the + * DCS MIN|MAX backoff used */ +enum dot11_profile_t { /* And set/allowed values */ + /* Allowed values for DOT11_OID_PROFILES */ + DOT11_PROFILE_B_ONLY = 0, + /* DOT11_OID_RATES: 1, 2, 5.5, 11Mbps + * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_DYNAMIC + * DOT11_OID_CWMIN: 31 + * DOT11_OID_NONEPROTECTION: DOT11_NOERP_DYNAMIC + * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_LONG + */ + DOT11_PROFILE_MIXED_G_WIFI = 1, + /* DOT11_OID_RATES: 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54Mbs + * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_DYNAMIC + * DOT11_OID_CWMIN: 15 + * DOT11_OID_NONEPROTECTION: DOT11_NOERP_DYNAMIC + * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_DYNAMIC + */ + DOT11_PROFILE_MIXED_LONG = 2, /* "Long range" */ + /* Same as Profile MIXED_G_WIFI */ + DOT11_PROFILE_G_ONLY = 3, + /* Same as Profile MIXED_G_WIFI */ + DOT11_PROFILE_TEST = 4, + /* Same as Profile MIXED_G_WIFI except: + * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_SHORT + * DOT11_OID_NONEPROTECTION: DOT11_NOERP_NEVER + * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_SHORT + */ + DOT11_PROFILE_B_WIFI = 5, + /* Same as Profile B_ONLY */ + DOT11_PROFILE_A_ONLY = 6, + /* Same as Profile MIXED_G_WIFI except: + * DOT11_OID_RATES: 6, 9, 12, 18, 24, 36, 48, 54Mbs + */ + DOT11_PROFILE_MIXED_SHORT = 7 + /* Same as MIXED_G_WIFI */ +}; + + +/* The dot11d conformance level configures the 802.11d conformance levels. + * The following conformance levels exist:*/ +enum oid_inl_conformance_t { + OID_INL_CONFORMANCE_NONE = 0, /* Perform active scanning */ + OID_INL_CONFORMANCE_STRICT = 1, /* Strictly adhere to 802.11d */ + OID_INL_CONFORMANCE_FLEXIBLE = 2, /* Use passed 802.11d info to + * determine channel AND/OR just make assumption that active + * channels are valid channels */ +}; + +enum oid_inl_mode_t { + INL_MODE_NONE = -1, + INL_MODE_PROMISCUOUS = 0, + INL_MODE_CLIENT = 1, + INL_MODE_AP = 2, + INL_MODE_SNIFFER = 3 +}; + +enum oid_inl_config_t { + INL_CONFIG_NOTHING = 0x00, + INL_CONFIG_MANUALRUN = 0x01, + INL_CONFIG_FRAMETRAP = 0x02, + INL_CONFIG_RXANNEX = 0x04, + INL_CONFIG_TXANNEX = 0x08, + INL_CONFIG_WDS = 0x10 +}; + +enum oid_inl_phycap_t { + INL_PHYCAP_2400MHZ = 1, + INL_PHYCAP_5000MHZ = 2, + INL_PHYCAP_FAA = 0x80000000, /* Means card supports the FAA switch */ +}; + + +enum oid_num_t { + GEN_OID_MACADDRESS = 0, + GEN_OID_LINKSTATE, + GEN_OID_WATCHDOG, + GEN_OID_MIBOP, + GEN_OID_OPTIONS, + GEN_OID_LEDCONFIG, + + /* 802.11 */ + DOT11_OID_BSSTYPE, + DOT11_OID_BSSID, + DOT11_OID_SSID, + DOT11_OID_STATE, + DOT11_OID_AID, + DOT11_OID_COUNTRYSTRING, + DOT11_OID_SSIDOVERRIDE, + + DOT11_OID_MEDIUMLIMIT, + DOT11_OID_BEACONPERIOD, + DOT11_OID_DTIMPERIOD, + DOT11_OID_ATIMWINDOW, + DOT11_OID_LISTENINTERVAL, + DOT11_OID_CFPPERIOD, + DOT11_OID_CFPDURATION, + + DOT11_OID_AUTHENABLE, + DOT11_OID_PRIVACYINVOKED, + DOT11_OID_EXUNENCRYPTED, + DOT11_OID_DEFKEYID, + DOT11_OID_DEFKEYX, /* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */ + DOT11_OID_STAKEY, + DOT11_OID_REKEYTHRESHOLD, + DOT11_OID_STASC, + + DOT11_OID_PRIVTXREJECTED, + DOT11_OID_PRIVRXPLAIN, + DOT11_OID_PRIVRXFAILED, + DOT11_OID_PRIVRXNOKEY, + + DOT11_OID_RTSTHRESH, + DOT11_OID_FRAGTHRESH, + DOT11_OID_SHORTRETRIES, + DOT11_OID_LONGRETRIES, + DOT11_OID_MAXTXLIFETIME, + DOT11_OID_MAXRXLIFETIME, + DOT11_OID_AUTHRESPTIMEOUT, + DOT11_OID_ASSOCRESPTIMEOUT, + + DOT11_OID_ALOFT_TABLE, + DOT11_OID_ALOFT_CTRL_TABLE, + DOT11_OID_ALOFT_RETREAT, + DOT11_OID_ALOFT_PROGRESS, + DOT11_OID_ALOFT_FIXEDRATE, + DOT11_OID_ALOFT_RSSIGRAPH, + DOT11_OID_ALOFT_CONFIG, + + DOT11_OID_VDCFX, + DOT11_OID_MAXFRAMEBURST, + + DOT11_OID_PSM, + DOT11_OID_CAMTIMEOUT, + DOT11_OID_RECEIVEDTIMS, + DOT11_OID_ROAMPREFERENCE, + + DOT11_OID_BRIDGELOCAL, + DOT11_OID_CLIENTS, + DOT11_OID_CLIENTSASSOCIATED, + DOT11_OID_CLIENTX, /* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */ + + DOT11_OID_CLIENTFIND, + DOT11_OID_WDSLINKADD, + DOT11_OID_WDSLINKREMOVE, + DOT11_OID_EAPAUTHSTA, + DOT11_OID_EAPUNAUTHSTA, + DOT11_OID_DOT1XENABLE, + DOT11_OID_MICFAILURE, + DOT11_OID_REKEYINDICATE, + + DOT11_OID_MPDUTXSUCCESSFUL, + DOT11_OID_MPDUTXONERETRY, + DOT11_OID_MPDUTXMULTIPLERETRIES, + DOT11_OID_MPDUTXFAILED, + DOT11_OID_MPDURXSUCCESSFUL, + DOT11_OID_MPDURXDUPS, + DOT11_OID_RTSSUCCESSFUL, + DOT11_OID_RTSFAILED, + DOT11_OID_ACKFAILED, + DOT11_OID_FRAMERECEIVES, + DOT11_OID_FRAMEERRORS, + DOT11_OID_FRAMEABORTS, + DOT11_OID_FRAMEABORTSPHY, + + DOT11_OID_SLOTTIME, + DOT11_OID_CWMIN, /* MIN DCS backoff */ + DOT11_OID_CWMAX, /* MAX DCS backoff */ + DOT11_OID_ACKWINDOW, + DOT11_OID_ANTENNARX, + DOT11_OID_ANTENNATX, + DOT11_OID_ANTENNADIVERSITY, + DOT11_OID_CHANNEL, + DOT11_OID_EDTHRESHOLD, + DOT11_OID_PREAMBLESETTINGS, + DOT11_OID_RATES, + DOT11_OID_CCAMODESUPPORTED, + DOT11_OID_CCAMODE, + DOT11_OID_RSSIVECTOR, + DOT11_OID_OUTPUTPOWERTABLE, + DOT11_OID_OUTPUTPOWER, + DOT11_OID_SUPPORTEDRATES, + DOT11_OID_FREQUENCY, + DOT11_OID_SUPPORTEDFREQUENCIES, + DOT11_OID_NOISEFLOOR, + DOT11_OID_FREQUENCYACTIVITY, + DOT11_OID_IQCALIBRATIONTABLE, + DOT11_OID_NONERPPROTECTION, + DOT11_OID_SLOTSETTINGS, + DOT11_OID_NONERPTIMEOUT, + DOT11_OID_PROFILES, + DOT11_OID_EXTENDEDRATES, + + DOT11_OID_DEAUTHENTICATE, + DOT11_OID_AUTHENTICATE, + DOT11_OID_DISASSOCIATE, + DOT11_OID_ASSOCIATE, + DOT11_OID_SCAN, + DOT11_OID_BEACON, + DOT11_OID_PROBE, + DOT11_OID_DEAUTHENTICATEEX, + DOT11_OID_AUTHENTICATEEX, + DOT11_OID_DISASSOCIATEEX, + DOT11_OID_ASSOCIATEEX, + DOT11_OID_REASSOCIATE, + DOT11_OID_REASSOCIATEEX, + + DOT11_OID_NONERPSTATUS, + + DOT11_OID_STATIMEOUT, + DOT11_OID_MLMEAUTOLEVEL, + DOT11_OID_BSSTIMEOUT, + DOT11_OID_ATTACHMENT, + DOT11_OID_PSMBUFFER, + + DOT11_OID_BSSS, + DOT11_OID_BSSX, /*DOT11_OID_BSS1,...,DOT11_OID_BSS64 */ + DOT11_OID_BSSFIND, + DOT11_OID_BSSLIST, + + OID_INL_TUNNEL, + OID_INL_MEMADDR, + OID_INL_MEMORY, + OID_INL_MODE, + OID_INL_COMPONENT_NR, + OID_INL_VERSION, + OID_INL_INTERFACE_ID, + OID_INL_COMPONENT_ID, + OID_INL_CONFIG, + OID_INL_DOT11D_CONFORMANCE, + OID_INL_PHYCAPABILITIES, + OID_INL_OUTPUTPOWER, + + OID_NUM_LAST +}; + +#define OID_FLAG_CACHED 0x80 +#define OID_FLAG_TYPE 0x7f + +#define OID_TYPE_U32 0x01 +#define OID_TYPE_SSID 0x02 +#define OID_TYPE_KEY 0x03 +#define OID_TYPE_BUFFER 0x04 +#define OID_TYPE_BSS 0x05 +#define OID_TYPE_BSSLIST 0x06 +#define OID_TYPE_FREQUENCIES 0x07 +#define OID_TYPE_MLME 0x08 +#define OID_TYPE_MLMEEX 0x09 +#define OID_TYPE_ADDR 0x0A +#define OID_TYPE_RAW 0x0B + +/* OID_TYPE_MLMEEX is special because of a variable size field when sending. + * Not yet implemented (not used in driver anyway). + */ + +struct oid_t { + enum oid_num_t oid; + short range; /* to define a range of oid */ + short size; /* max size of the associated data */ + char flags; +}; + +union oid_res_t { + void *ptr; + u32 u; +}; + +#define IWMAX_BITRATES 20 +#define IWMAX_BSS 24 +#define IWMAX_FREQ 30 +#define PRIV_STR_SIZE 1024 + +#endif /* !defined(_ISL_OID_H) */ +/* EOF */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_dev.c linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_dev.c --- linux-2.4.27/drivers/net/wireless/prism54/islpci_dev.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_dev.c 2004-09-10 19:37:09.000000000 +0000 @@ -0,0 +1,940 @@ +/* + * + * Copyright (C) 2002 Intersil Americas Inc. + * Copyright (C) 2003 Herbert Valerio Riedel + * Copyright (C) 2003 Luis R. Rodriguez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "prismcompat.h" +#include "isl_38xx.h" +#include "isl_ioctl.h" +#include "islpci_dev.h" +#include "islpci_mgt.h" +#include "islpci_eth.h" +#include "oid_mgt.h" + +#define ISL3877_IMAGE_FILE "isl3877" +#define ISL3886_IMAGE_FILE "isl3886" +#define ISL3890_IMAGE_FILE "isl3890" + +static int prism54_bring_down(islpci_private *); +static int islpci_alloc_memory(islpci_private *); + +/* Temporary dummy MAC address to use until firmware is loaded. + * The idea there is that some tools (such as nameif) may query + * the MAC address before the netdev is 'open'. By using a valid + * OUI prefix, they can process the netdev properly. + * Of course, this is not the final/real MAC address. It doesn't + * matter, as you are suppose to be able to change it anytime via + * ndev->set_mac_address. Jean II */ +const unsigned char dummy_mac[6] = { 0x00, 0x30, 0xB4, 0x00, 0x00, 0x00 }; + +static int +isl_upload_firmware(islpci_private *priv) +{ + u32 reg, rc; + void *device_base = priv->device_base; + + /* clear the RAMBoot and the Reset bit */ + reg = readl(device_base + ISL38XX_CTRL_STAT_REG); + reg &= ~ISL38XX_CTRL_STAT_RESET; + reg &= ~ISL38XX_CTRL_STAT_RAMBOOT; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* set the Reset bit without reading the register ! */ + reg |= ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* clear the Reset bit */ + reg &= ~ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + + /* wait a while for the device to reboot */ + mdelay(50); + + { + const struct firmware *fw_entry = NULL; + long fw_len; + const u32 *fw_ptr; + + rc = request_firmware(&fw_entry, priv->firmware, PRISM_FW_PDEV); + if (rc) { + printk(KERN_ERR + "%s: request_firmware() failed for '%s'\n", + "prism54", priv->firmware); + return rc; + } + /* prepare the Direct Memory Base register */ + reg = ISL38XX_DEV_FIRMWARE_ADDRES; + + fw_ptr = (u32 *) fw_entry->data; + fw_len = fw_entry->size; + + if (fw_len % 4) { + printk(KERN_ERR + "%s: firmware '%s' size is not multiple of 32bit, aborting!\n", + "prism54", priv->firmware); + release_firmware(fw_entry); + return EILSEQ; /* Illegal byte sequence */; + } + + while (fw_len > 0) { + long _fw_len = + (fw_len > + ISL38XX_MEMORY_WINDOW_SIZE) ? + ISL38XX_MEMORY_WINDOW_SIZE : fw_len; + u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN; + + /* set the cards base address for writting the data */ + isl38xx_w32_flush(device_base, reg, + ISL38XX_DIR_MEM_BASE_REG); + wmb(); /* be paranoid */ + + /* increment the write address for next iteration */ + reg += _fw_len; + fw_len -= _fw_len; + + /* write the data to the Direct Memory Window 32bit-wise */ + /* memcpy_toio() doesn't guarantee 32bit writes :-| */ + while (_fw_len > 0) { + /* use non-swapping writel() */ + __raw_writel(*fw_ptr, dev_fw_ptr); + fw_ptr++, dev_fw_ptr++; + _fw_len -= 4; + } + + /* flush PCI posting */ + (void) readl(device_base + ISL38XX_PCI_POSTING_FLUSH); + wmb(); /* be paranoid again */ + + BUG_ON(_fw_len != 0); + } + + BUG_ON(fw_len != 0); + + release_firmware(fw_entry); + } + + /* now reset the device + * clear the Reset & ClkRun bit, set the RAMBoot bit */ + reg = readl(device_base + ISL38XX_CTRL_STAT_REG); + reg &= ~ISL38XX_CTRL_STAT_CLKRUN; + reg &= ~ISL38XX_CTRL_STAT_RESET; + reg |= ISL38XX_CTRL_STAT_RAMBOOT; + isl38xx_w32_flush(device_base, reg, ISL38XX_CTRL_STAT_REG); + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* set the reset bit latches the host override and RAMBoot bits + * into the device for operation when the reset bit is reset */ + reg |= ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + /* don't do flush PCI posting here! */ + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* clear the reset bit should start the whole circus */ + reg &= ~ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + /* don't do flush PCI posting here! */ + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + return 0; +} + +/****************************************************************************** + Device Interrupt Handler +******************************************************************************/ + +irqreturn_t +islpci_interrupt(int irq, void *config, struct pt_regs *regs) +{ + u32 reg; + islpci_private *priv = config; + struct net_device *ndev = priv->ndev; + void *device = priv->device_base; + int powerstate = ISL38XX_PSM_POWERSAVE_STATE; + + /* lock the interrupt handler */ + spin_lock(&priv->slock); + + /* received an interrupt request on a shared IRQ line + * first check whether the device is in sleep mode */ + reg = readl(device + ISL38XX_CTRL_STAT_REG); + if (reg & ISL38XX_CTRL_STAT_SLEEPMODE) + /* device is in sleep mode, IRQ was generated by someone else */ + { +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n"); +#endif + spin_unlock(&priv->slock); + return IRQ_NONE; + } + + + /* check whether there is any source of interrupt on the device */ + reg = readl(device + ISL38XX_INT_IDENT_REG); + + /* also check the contents of the Interrupt Enable Register, because this + * will filter out interrupt sources from other devices on the same irq ! */ + reg &= readl(device + ISL38XX_INT_EN_REG); + reg &= ISL38XX_INT_SOURCES; + + if (reg != 0) { + if (islpci_get_state(priv) != PRV_STATE_SLEEP) + powerstate = ISL38XX_PSM_ACTIVE_STATE; + + /* reset the request bits in the Identification register */ + isl38xx_w32_flush(device, reg, ISL38XX_INT_ACK_REG); + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_FUNCTION_CALLS, + "IRQ: Identification register 0x%p 0x%x \n", device, reg); +#endif + + /* check for each bit in the register separately */ + if (reg & ISL38XX_INT_IDENT_UPDATE) { +#if VERBOSE > SHOW_ERROR_MESSAGES + /* Queue has been updated */ + DEBUG(SHOW_TRACING, "IRQ: Update flag \n"); + + DEBUG(SHOW_QUEUE_INDEXES, + "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n", + le32_to_cpu(priv->control_block-> + driver_curr_frag[0]), + le32_to_cpu(priv->control_block-> + driver_curr_frag[1]), + le32_to_cpu(priv->control_block-> + driver_curr_frag[2]), + le32_to_cpu(priv->control_block-> + driver_curr_frag[3]), + le32_to_cpu(priv->control_block-> + driver_curr_frag[4]), + le32_to_cpu(priv->control_block-> + driver_curr_frag[5]) + ); + + DEBUG(SHOW_QUEUE_INDEXES, + "CB dev Qs: [%i][%i][%i][%i][%i][%i]\n", + le32_to_cpu(priv->control_block-> + device_curr_frag[0]), + le32_to_cpu(priv->control_block-> + device_curr_frag[1]), + le32_to_cpu(priv->control_block-> + device_curr_frag[2]), + le32_to_cpu(priv->control_block-> + device_curr_frag[3]), + le32_to_cpu(priv->control_block-> + device_curr_frag[4]), + le32_to_cpu(priv->control_block-> + device_curr_frag[5]) + ); +#endif + + /* cleanup the data low transmit queue */ + islpci_eth_cleanup_transmit(priv, priv->control_block); + + /* device is in active state, update the + * powerstate flag if necessary */ + powerstate = ISL38XX_PSM_ACTIVE_STATE; + + /* check all three queues in priority order + * call the PIMFOR receive function until the + * queue is empty */ + if (isl38xx_in_queue(priv->control_block, + ISL38XX_CB_RX_MGMTQ) != 0) { +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, + "Received frame in Management Queue\n"); +#endif + islpci_mgt_receive(ndev); + + islpci_mgt_cleanup_transmit(ndev); + + /* Refill slots in receive queue */ + islpci_mgmt_rx_fill(ndev); + + /* no need to trigger the device, next + islpci_mgt_transaction does it */ + } + + while (isl38xx_in_queue(priv->control_block, + ISL38XX_CB_RX_DATA_LQ) != 0) { +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, + "Received frame in Data Low Queue \n"); +#endif + islpci_eth_receive(priv); + } + + /* check whether the data transmit queues were full */ + if (priv->data_low_tx_full) { + /* check whether the transmit is not full anymore */ + if (ISL38XX_CB_TX_QSIZE - + isl38xx_in_queue(priv->control_block, + ISL38XX_CB_TX_DATA_LQ) >= + ISL38XX_MIN_QTHRESHOLD) { + /* nope, the driver is ready for more network frames */ + netif_wake_queue(priv->ndev); + + /* reset the full flag */ + priv->data_low_tx_full = 0; + } + } + } + + if (reg & ISL38XX_INT_IDENT_INIT) { + /* Device has been initialized */ +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, + "IRQ: Init flag, device initialized \n"); +#endif + wake_up(&priv->reset_done); + } + + if (reg & ISL38XX_INT_IDENT_SLEEP) { + /* Device intends to move to powersave state */ +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "IRQ: Sleep flag \n"); +#endif + isl38xx_handle_sleep_request(priv->control_block, + &powerstate, + priv->device_base); + } + + if (reg & ISL38XX_INT_IDENT_WAKEUP) { + /* Device has been woken up to active state */ +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "IRQ: Wakeup flag \n"); +#endif + + isl38xx_handle_wakeup(priv->control_block, + &powerstate, priv->device_base); + } + } else { +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n"); +#endif + spin_unlock(&priv->slock); + return IRQ_NONE; + } + + /* sleep -> ready */ + if (islpci_get_state(priv) == PRV_STATE_SLEEP + && powerstate == ISL38XX_PSM_ACTIVE_STATE) + islpci_set_state(priv, PRV_STATE_READY); + + /* !sleep -> sleep */ + if (islpci_get_state(priv) != PRV_STATE_SLEEP + && powerstate == ISL38XX_PSM_POWERSAVE_STATE) + islpci_set_state(priv, PRV_STATE_SLEEP); + + /* unlock the interrupt handler */ + spin_unlock(&priv->slock); + + return IRQ_HANDLED; +} + +/****************************************************************************** + Network Interface Control & Statistical functions +******************************************************************************/ +static int +islpci_open(struct net_device *ndev) +{ + u32 rc; + islpci_private *priv = netdev_priv(ndev); + + printk(KERN_DEBUG "%s: islpci_open()\n", ndev->name); + + /* reset data structures, upload firmware and reset device */ + rc = islpci_reset(priv,1); + if (rc) { + prism54_bring_down(priv); + return rc; /* Returns informative message */ + } + + netif_start_queue(ndev); +/* netif_mark_up( ndev ); */ + + return 0; +} + +static int +islpci_close(struct net_device *ndev) +{ + islpci_private *priv = netdev_priv(ndev); + + printk(KERN_DEBUG "%s: islpci_close ()\n", ndev->name); + + netif_stop_queue(ndev); + + return prism54_bring_down(priv); +} + +static int +prism54_bring_down(islpci_private *priv) +{ + void *device_base = priv->device_base; + u32 reg; + /* we are going to shutdown the device */ + islpci_set_state(priv, PRV_STATE_PREBOOT); + + /* disable all device interrupts in case they weren't */ + isl38xx_disable_interrupts(priv->device_base); + + /* For safety reasons, we may want to ensure that no DMA transfer is + * currently in progress by emptying the TX and RX queues. */ + + /* wait until interrupts have finished executing on other CPUs */ + prism54_synchronize_irq(priv->pdev->irq); + + reg = readl(device_base + ISL38XX_CTRL_STAT_REG); + reg &= ~(ISL38XX_CTRL_STAT_RESET | ISL38XX_CTRL_STAT_RAMBOOT); + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + reg |= ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* clear the Reset bit */ + reg &= ~ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + + /* wait a while for the device to reset */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(50*HZ/1000); + + return 0; +} + +static int +islpci_upload_fw(islpci_private *priv) +{ + islpci_state_t old_state; + u32 rc; + + old_state = islpci_set_state(priv, PRV_STATE_BOOT); + + printk(KERN_DEBUG "%s: uploading firmware...\n", priv->ndev->name); + + rc = isl_upload_firmware(priv); + if (rc) { + /* error uploading the firmware */ + printk(KERN_ERR "%s: could not upload firmware ('%s')\n", + priv->ndev->name, priv->firmware); + + islpci_set_state(priv, old_state); + return rc; + } + + printk(KERN_DEBUG + "%s: firmware uploaded done, now triggering reset...\n", + priv->ndev->name); + + islpci_set_state(priv, PRV_STATE_POSTBOOT); + + return 0; +} + +static int +islpci_reset_if(islpci_private *priv) +{ + long remaining; + int result = -ETIME; + int count; + + DEFINE_WAIT(wait); + prepare_to_wait(&priv->reset_done, &wait, TASK_UNINTERRUPTIBLE); + + /* now the last step is to reset the interface */ + isl38xx_interface_reset(priv->device_base, priv->device_host_address); + islpci_set_state(priv, PRV_STATE_PREINIT); + + for(count = 0; count < 2 && result; count++) { + /* The software reset acknowledge needs about 220 msec here. + * Be conservative and wait for up to one second. */ + + remaining = schedule_timeout(HZ); + + if(remaining > 0) { + result = 0; + break; + } + + /* If we're here it's because our IRQ hasn't yet gone through. + * Retry a bit more... + */ + printk(KERN_ERR "%s: device soft reset timed out\n", + priv->ndev->name); + + } + + finish_wait(&priv->reset_done, &wait); + + if(result) + return result; + + islpci_set_state(priv, PRV_STATE_INIT); + + /* Now that the device is 100% up, let's allow + * for the other interrupts -- + * NOTE: this is not *yet* true since we've only allowed the + * INIT interrupt on the IRQ line. We can perhaps poll + * the IRQ line until we know for sure the reset went through */ + isl38xx_enable_common_interrupts(priv->device_base); + + down_write(&priv->mib_sem); + mgt_commit(priv); + up_write(&priv->mib_sem); + + islpci_set_state(priv, PRV_STATE_READY); + + return 0; +} + +int +islpci_reset(islpci_private *priv, int reload_firmware) +{ + isl38xx_control_block *cb = /* volatile not needed */ + (isl38xx_control_block *) priv->control_block; + unsigned counter; + int rc; + + if (reload_firmware) + islpci_set_state(priv, PRV_STATE_PREBOOT); + else + islpci_set_state(priv, PRV_STATE_POSTBOOT); + + printk(KERN_DEBUG "%s: resetting device...\n", priv->ndev->name); + + /* disable all device interrupts in case they weren't */ + isl38xx_disable_interrupts(priv->device_base); + + /* flush all management queues */ + priv->index_mgmt_tx = 0; + priv->index_mgmt_rx = 0; + + /* clear the indexes in the frame pointer */ + for (counter = 0; counter < ISL38XX_CB_QCOUNT; counter++) { + cb->driver_curr_frag[counter] = cpu_to_le32(0); + cb->device_curr_frag[counter] = cpu_to_le32(0); + } + + /* reset the mgmt receive queue */ + for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) { + isl38xx_fragment *frag = &cb->rx_data_mgmt[counter]; + frag->size = cpu_to_le16(MGMT_FRAME_SIZE); + frag->flags = 0; + frag->address = cpu_to_le32(priv->mgmt_rx[counter].pci_addr); + } + + for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) { + cb->rx_data_low[counter].address = + cpu_to_le32((u32) priv->pci_map_rx_address[counter]); + } + + /* since the receive queues are filled with empty fragments, now we can + * set the corresponding indexes in the Control Block */ + priv->control_block->driver_curr_frag[ISL38XX_CB_RX_DATA_LQ] = + cpu_to_le32(ISL38XX_CB_RX_QSIZE); + priv->control_block->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = + cpu_to_le32(ISL38XX_CB_MGMT_QSIZE); + + /* reset the remaining real index registers and full flags */ + priv->free_data_rx = 0; + priv->free_data_tx = 0; + priv->data_low_tx_full = 0; + + if (reload_firmware) { /* Should we load the firmware ? */ + /* now that the data structures are cleaned up, upload + * firmware and reset interface */ + rc = islpci_upload_fw(priv); + if (rc) + return rc; + } + + /* finally reset interface */ + rc = islpci_reset_if(priv); + if (!rc) /* If successful */ + return rc; + + printk(KERN_DEBUG "prism54: Your card/socket may be faulty, or IRQ line too busy :(\n"); + return rc; + +} + +struct net_device_stats * +islpci_statistics(struct net_device *ndev) +{ + islpci_private *priv = netdev_priv(ndev); + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics \n"); +#endif + + return &priv->statistics; +} + +/****************************************************************************** + Network device configuration functions +******************************************************************************/ +static int +islpci_alloc_memory(islpci_private *priv) +{ + int counter; + +#if VERBOSE > SHOW_ERROR_MESSAGES + printk(KERN_DEBUG "islpci_alloc_memory\n"); +#endif + + /* remap the PCI device base address to accessable */ + if (!(priv->device_base = + ioremap(pci_resource_start(priv->pdev, 0), + ISL38XX_PCI_MEM_SIZE))) { + /* error in remapping the PCI device memory address range */ + printk(KERN_ERR "PCI memory remapping failed \n"); + return -1; + } + + /* memory layout for consistent DMA region: + * + * Area 1: Control Block for the device interface + * Area 2: Power Save Mode Buffer for temporary frame storage. Be aware that + * the number of supported stations in the AP determines the minimal + * size of the buffer ! + */ + + /* perform the allocation */ + priv->driver_mem_address = pci_alloc_consistent(priv->pdev, + HOST_MEM_BLOCK, + &priv-> + device_host_address); + + if (!priv->driver_mem_address) { + /* error allocating the block of PCI memory */ + printk(KERN_ERR "%s: could not allocate DMA memory, aborting!", + "prism54"); + return -1; + } + + /* assign the Control Block to the first address of the allocated area */ + priv->control_block = + (isl38xx_control_block *) priv->driver_mem_address; + + /* set the Power Save Buffer pointer directly behind the CB */ + priv->device_psm_buffer = + priv->device_host_address + CONTROL_BLOCK_SIZE; + + /* make sure all buffer pointers are initialized */ + for (counter = 0; counter < ISL38XX_CB_QCOUNT; counter++) { + priv->control_block->driver_curr_frag[counter] = cpu_to_le32(0); + priv->control_block->device_curr_frag[counter] = cpu_to_le32(0); + } + + priv->index_mgmt_rx = 0; + memset(priv->mgmt_rx, 0, sizeof(priv->mgmt_rx)); + memset(priv->mgmt_tx, 0, sizeof(priv->mgmt_tx)); + + /* allocate rx queue for management frames */ + if (islpci_mgmt_rx_fill(priv->ndev) < 0) + goto out_free; + + /* now get the data rx skb's */ + memset(priv->data_low_rx, 0, sizeof (priv->data_low_rx)); + memset(priv->pci_map_rx_address, 0, sizeof (priv->pci_map_rx_address)); + + for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) { + struct sk_buff *skb; + + /* allocate an sk_buff for received data frames storage + * each frame on receive size consists of 1 fragment + * include any required allignment operations */ + if (!(skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2))) { + /* error allocating an sk_buff structure elements */ + printk(KERN_ERR "Error allocating skb.\n"); + skb = NULL; + goto out_free; + } + skb_reserve(skb, (4 - (long) skb->data) & 0x03); + /* add the new allocated sk_buff to the buffer array */ + priv->data_low_rx[counter] = skb; + + /* map the allocated skb data area to pci */ + priv->pci_map_rx_address[counter] = + pci_map_single(priv->pdev, (void *) skb->data, + MAX_FRAGMENT_SIZE_RX + 2, + PCI_DMA_FROMDEVICE); + if (!priv->pci_map_rx_address[counter]) { + /* error mapping the buffer to device + accessable memory address */ + printk(KERN_ERR "failed to map skb DMA'able\n"); + goto out_free; + } + } + + prism54_acl_init(&priv->acl); + prism54_wpa_ie_init(priv); + if (mgt_init(priv)) + goto out_free; + + return 0; + out_free: + islpci_free_memory(priv); + return -1; +} + +int +islpci_free_memory(islpci_private *priv) +{ + int counter; + + if (priv->device_base) + iounmap(priv->device_base); + priv->device_base = NULL; + + /* free consistent DMA area... */ + if (priv->driver_mem_address) + pci_free_consistent(priv->pdev, HOST_MEM_BLOCK, + priv->driver_mem_address, + priv->device_host_address); + + /* clear some dangling pointers */ + priv->driver_mem_address = NULL; + priv->device_host_address = 0; + priv->device_psm_buffer = 0; + priv->control_block = NULL; + + /* clean up mgmt rx buffers */ + for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) { + struct islpci_membuf *buf = &priv->mgmt_rx[counter]; + if (buf->pci_addr) + pci_unmap_single(priv->pdev, buf->pci_addr, + buf->size, PCI_DMA_FROMDEVICE); + buf->pci_addr = 0; + if (buf->mem) + kfree(buf->mem); + buf->size = 0; + buf->mem = NULL; + } + + /* clean up data rx buffers */ + for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) { + if (priv->pci_map_rx_address[counter]) + pci_unmap_single(priv->pdev, + priv->pci_map_rx_address[counter], + MAX_FRAGMENT_SIZE_RX + 2, + PCI_DMA_FROMDEVICE); + priv->pci_map_rx_address[counter] = 0; + + if (priv->data_low_rx[counter]) + dev_kfree_skb(priv->data_low_rx[counter]); + priv->data_low_rx[counter] = NULL; + } + + /* Free the acces control list and the WPA list */ + prism54_acl_clean(&priv->acl); + prism54_wpa_ie_clean(priv); + mgt_clean(priv); + + return 0; +} + +#if 0 +static void +islpci_set_multicast_list(struct net_device *dev) +{ + /* put device into promisc mode and let network layer handle it */ +} +#endif + +struct net_device * +islpci_setup(struct pci_dev *pdev) +{ + islpci_private *priv; + struct net_device *ndev = alloc_etherdev(sizeof (islpci_private)); + + if (!ndev) + return ndev; + + SET_MODULE_OWNER(ndev); + pci_set_drvdata(pdev, ndev); +#if defined(SET_NETDEV_DEV) + SET_NETDEV_DEV(ndev, &pdev->dev); +#endif + + /* setup the structure members */ + ndev->base_addr = pci_resource_start(pdev, 0); + ndev->irq = pdev->irq; + + /* initialize the function pointers */ + ndev->open = &islpci_open; + ndev->stop = &islpci_close; + ndev->get_stats = &islpci_statistics; + ndev->get_wireless_stats = &prism54_get_wireless_stats; + ndev->do_ioctl = &prism54_ioctl; + ndev->wireless_handlers = + (struct iw_handler_def *) &prism54_handler_def; + + ndev->hard_start_xmit = &islpci_eth_transmit; + /* ndev->set_multicast_list = &islpci_set_multicast_list; */ + ndev->addr_len = ETH_ALEN; + ndev->set_mac_address = &prism54_set_mac_address; + /* Get a non-zero dummy MAC address for nameif. Jean II */ + memcpy(ndev->dev_addr, dummy_mac, 6); + +#ifdef HAVE_TX_TIMEOUT + ndev->watchdog_timeo = ISLPCI_TX_TIMEOUT; + ndev->tx_timeout = &islpci_eth_tx_timeout; +#endif + + /* allocate a private device structure to the network device */ + priv = netdev_priv(ndev); + priv->ndev = ndev; + priv->pdev = pdev; + priv->monitor_type = ARPHRD_IEEE80211; + priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ? + priv->monitor_type : ARPHRD_ETHER; + + /* save the start and end address of the PCI memory area */ + ndev->mem_start = (unsigned long) priv->device_base; + ndev->mem_end = ndev->mem_start + ISL38XX_PCI_MEM_SIZE; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "PCI Memory remapped to 0x%p\n", priv->device_base); +#endif + + init_waitqueue_head(&priv->reset_done); + + /* init the queue read locks, process wait counter */ + sema_init(&priv->mgmt_sem, 1); + priv->mgmt_received = NULL; + init_waitqueue_head(&priv->mgmt_wqueue); + sema_init(&priv->stats_sem, 1); + spin_lock_init(&priv->slock); + + /* init state machine with off#1 state */ + priv->state = PRV_STATE_OFF; + priv->state_off = 1; + + /* initialize workqueue's */ + INIT_WORK(&priv->stats_work, + (void (*)(void *)) prism54_update_stats, priv); + priv->stats_timestamp = 0; + + INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake, priv); + priv->reset_task_pending = 0; + + /* allocate various memory areas */ + if (islpci_alloc_memory(priv)) + goto do_free_netdev; + + /* select the firmware file depending on the device id */ + switch (pdev->device) { + case 0x3877: + strcpy(priv->firmware, ISL3877_IMAGE_FILE); + break; + + case 0x3886: + strcpy(priv->firmware, ISL3886_IMAGE_FILE); + break; + + default: + strcpy(priv->firmware, ISL3890_IMAGE_FILE); + break; + } + + if (register_netdev(ndev)) { + DEBUG(SHOW_ERROR_MESSAGES, + "ERROR: register_netdev() failed \n"); + goto do_islpci_free_memory; + } + + return ndev; + + do_islpci_free_memory: + islpci_free_memory(priv); + do_free_netdev: + pci_set_drvdata(pdev, NULL); + free_netdev(ndev); + priv = NULL; + return NULL; +} + +islpci_state_t +islpci_set_state(islpci_private *priv, islpci_state_t new_state) +{ + islpci_state_t old_state; + + /* lock */ + old_state = priv->state; + + /* this means either a race condition or some serious error in + * the driver code */ + switch (new_state) { + case PRV_STATE_OFF: + priv->state_off++; + default: + priv->state = new_state; + break; + + case PRV_STATE_PREBOOT: + /* there are actually many off-states, enumerated by + * state_off */ + if (old_state == PRV_STATE_OFF) + priv->state_off--; + + /* only if hw_unavailable is zero now it means we either + * were in off#1 state, or came here from + * somewhere else */ + if (!priv->state_off) + priv->state = new_state; + break; + }; +#if 0 + printk(KERN_DEBUG "%s: state transition %d -> %d (off#%d)\n", + priv->ndev->name, old_state, new_state, priv->state_off); +#endif + + /* invariants */ + BUG_ON(priv->state_off < 0); + BUG_ON(priv->state_off && (priv->state != PRV_STATE_OFF)); + BUG_ON(!priv->state_off && (priv->state == PRV_STATE_OFF)); + + /* unlock */ + return old_state; +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_dev.h linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_dev.h --- linux-2.4.27/drivers/net/wireless/prism54/islpci_dev.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_dev.h 2004-09-10 19:33:55.000000000 +0000 @@ -0,0 +1,215 @@ +/* + * + * Copyright (C) 2002 Intersil Americas Inc. + * Copyright (C) 2003 Herbert Valerio Riedel + * Copyright (C) 2003 Luis R. Rodriguez + * Copyright (C) 2003 Aurelien Alleaume + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _ISLPCI_DEV_H +#define _ISLPCI_DEV_H + +#include +#include +#include +#include +#include + +#include "isl_38xx.h" +#include "isl_oid.h" +#include "islpci_mgt.h" + +/* some states might not be superflous and may be removed when + design is finalized (hvr) */ +typedef enum { + PRV_STATE_OFF = 0, /* this means hw_unavailable is != 0 */ + PRV_STATE_PREBOOT, /* we are in a pre-boot state (empty RAM) */ + PRV_STATE_BOOT, /* boot state (fw upload, run fw) */ + PRV_STATE_POSTBOOT, /* after boot state, need reset now */ + PRV_STATE_PREINIT, /* pre-init state */ + PRV_STATE_INIT, /* init state (restore MIB backup to device) */ + PRV_STATE_READY, /* driver&device are in operational state */ + PRV_STATE_SLEEP /* device in sleep mode */ +} islpci_state_t; + +/* ACL using MAC address */ +struct mac_entry { + struct list_head _list; + char addr[ETH_ALEN]; +}; + +struct islpci_acl { + enum { MAC_POLICY_OPEN=0, MAC_POLICY_ACCEPT=1, MAC_POLICY_REJECT=2 } policy; + struct list_head mac_list; /* a list of mac_entry */ + int size; /* size of queue */ + struct semaphore sem; /* accessed in ioctls and trap_work */ +}; + +struct islpci_membuf { + int size; /* size of memory */ + void *mem; /* address of memory as seen by CPU */ + dma_addr_t pci_addr; /* address of memory as seen by device */ +}; + +#define MAX_BSS_WPA_IE_COUNT 64 +#define MAX_WPA_IE_LEN 64 +struct islpci_bss_wpa_ie { + struct list_head list; + unsigned long last_update; + u8 bssid[ETH_ALEN]; + u8 wpa_ie[MAX_WPA_IE_LEN]; + size_t wpa_ie_len; + +}; + +typedef struct { + spinlock_t slock; /* generic spinlock; */ + + u32 priv_oid; + + /* our mib cache */ + u32 iw_mode; + struct rw_semaphore mib_sem; + void **mib; + char nickname[IW_ESSID_MAX_SIZE+1]; + + /* Take care of the wireless stats */ + struct work_struct stats_work; + struct semaphore stats_sem; + /* remember when we last updated the stats */ + unsigned long stats_timestamp; + /* The first is accessed under semaphore locking. + * The second is the clean one we return to iwconfig. + */ + struct iw_statistics local_iwstatistics; + struct iw_statistics iwstatistics; + + struct iw_spy_data spy_data; /* iwspy support */ + + int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */ + + struct islpci_acl acl; + + /* PCI bus allocation & configuration members */ + struct pci_dev *pdev; /* PCI structure information */ + u32 pci_state[16]; /* used for suspend/resume */ + char firmware[33]; + + void *device_base; /* ioremapped device base address */ + + /* consistent DMA region */ + void *driver_mem_address; /* base DMA address */ + dma_addr_t device_host_address; /* base DMA address (bus address) */ + dma_addr_t device_psm_buffer; /* host memory for PSM buffering (bus address) */ + + /* our network_device structure */ + struct net_device *ndev; + + /* device queue interface members */ + struct isl38xx_cb *control_block; /* device control block + (== driver_mem_address!) */ + + /* Each queue has three indexes: + * free/index_mgmt/data_rx/tx (called index, see below), + * driver_curr_frag, and device_curr_frag (in the control block) + * All indexes are ever-increasing, but interpreted modulo the + * device queue size when used. + * index <= device_curr_frag <= driver_curr_frag at all times + * For rx queues, [index, device_curr_frag) contains fragments + * that the interrupt processing needs to handle (owned by driver). + * [device_curr_frag, driver_curr_frag) is the free space in the + * rx queue, waiting for data (owned by device). The driver + * increments driver_curr_frag to indicate to the device that more + * buffers are available. + * If device_curr_frag == driver_curr_frag, no more rx buffers are + * available, and the rx DMA engine of the device is halted. + * For tx queues, [index, device_curr_frag) contains fragments + * where tx is done; they need to be freed (owned by driver). + * [device_curr_frag, driver_curr_frag) contains the frames + * that are being transferred (owned by device). The driver + * increments driver_curr_frag to indicate that more tx work + * needs to be done. + */ + u32 index_mgmt_rx; /* real index mgmt rx queue */ + u32 index_mgmt_tx; /* read index mgmt tx queue */ + u32 free_data_rx; /* free pointer data rx queue */ + u32 free_data_tx; /* free pointer data tx queue */ + u32 data_low_tx_full; /* full detected flag */ + + /* frame memory buffers for the device queues */ + struct islpci_membuf mgmt_tx[ISL38XX_CB_MGMT_QSIZE]; + struct islpci_membuf mgmt_rx[ISL38XX_CB_MGMT_QSIZE]; + struct sk_buff *data_low_tx[ISL38XX_CB_TX_QSIZE]; + struct sk_buff *data_low_rx[ISL38XX_CB_RX_QSIZE]; + dma_addr_t pci_map_tx_address[ISL38XX_CB_TX_QSIZE]; + dma_addr_t pci_map_rx_address[ISL38XX_CB_RX_QSIZE]; + + /* driver network interface members */ + struct net_device_stats statistics; + + /* wait for a reset interrupt */ + wait_queue_head_t reset_done; + + /* used by islpci_mgt_transaction */ + struct semaphore mgmt_sem; /* serialize access to mailbox and wqueue */ + struct islpci_mgmtframe *mgmt_received; /* mbox for incoming frame */ + wait_queue_head_t mgmt_wqueue; /* waitqueue for mbox */ + + /* state machine */ + islpci_state_t state; + int state_off; /* enumeration of off-state, if 0 then + * we're not in any off-state */ + + /* WPA stuff */ + int wpa; /* WPA mode enabled */ + struct list_head bss_wpa_list; + int num_bss_wpa; + struct semaphore wpa_sem; + + struct work_struct reset_task; + int reset_task_pending; +} islpci_private; + +static inline islpci_state_t +islpci_get_state(islpci_private *priv) +{ + /* lock */ + return priv->state; + /* unlock */ +} + +islpci_state_t islpci_set_state(islpci_private *priv, islpci_state_t new_state); + +#define ISLPCI_TX_TIMEOUT (2*HZ) + +irqreturn_t islpci_interrupt(int, void *, struct pt_regs *); + +int prism54_post_setup(islpci_private *, int); +int islpci_reset(islpci_private *, int); + +static inline void +islpci_trigger(islpci_private *priv) +{ + isl38xx_trigger_device(islpci_get_state(priv) == PRV_STATE_SLEEP, + priv->device_base); +} + +struct net_device_stats *islpci_statistics(struct net_device *); + +int islpci_free_memory(islpci_private *); +struct net_device *islpci_setup(struct pci_dev *); +#endif /* _ISLPCI_DEV_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_eth.c linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_eth.c --- linux-2.4.27/drivers/net/wireless/prism54/islpci_eth.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_eth.c 2004-09-10 19:33:05.000000000 +0000 @@ -0,0 +1,518 @@ +/* + * + * Copyright (C) 2002 Intersil Americas Inc. + * Copyright (C) 2004 Aurelien Alleaume + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "prismcompat.h" +#include "isl_38xx.h" +#include "islpci_eth.h" +#include "islpci_mgt.h" +#include "oid_mgt.h" + +/****************************************************************************** + Network Interface functions +******************************************************************************/ +void +islpci_eth_cleanup_transmit(islpci_private *priv, + isl38xx_control_block *control_block) +{ + struct sk_buff *skb; + u32 index; + + /* compare the control block read pointer with the free pointer */ + while (priv->free_data_tx != + le32_to_cpu(control_block-> + device_curr_frag[ISL38XX_CB_TX_DATA_LQ])) { + /* read the index of the first fragment to be freed */ + index = priv->free_data_tx % ISL38XX_CB_TX_QSIZE; + + /* check for holes in the arrays caused by multi fragment frames + * searching for the last fragment of a frame */ + if (priv->pci_map_tx_address[index] != (dma_addr_t) NULL) { + /* entry is the last fragment of a frame + * free the skb structure and unmap pci memory */ + skb = priv->data_low_tx[index]; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, + "cleanup skb %p skb->data %p skb->len %u truesize %u\n ", + skb, skb->data, skb->len, skb->truesize); +#endif + + pci_unmap_single(priv->pdev, + priv->pci_map_tx_address[index], + skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + skb = NULL; + } + /* increment the free data low queue pointer */ + priv->free_data_tx++; + } +} + +int +islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) +{ + islpci_private *priv = netdev_priv(ndev); + isl38xx_control_block *cb = priv->control_block; + u32 index; + dma_addr_t pci_map_address; + int frame_size; + isl38xx_fragment *fragment; + int offset; + struct sk_buff *newskb; + int newskb_offset; + unsigned long flags; + unsigned char wds_mac[6]; + u32 curr_frag; + int err = 0; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit \n"); +#endif + + /* lock the driver code */ + spin_lock_irqsave(&priv->slock, flags); + + /* determine the amount of fragments needed to store the frame */ + + frame_size = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; + if (init_wds) + frame_size += 6; + + /* check whether the destination queue has enough fragments for the frame */ + curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ]); + if (unlikely(curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE)) { + printk(KERN_ERR "%s: transmit device queue full when awake\n", + ndev->name); + netif_stop_queue(ndev); + + /* trigger the device */ + isl38xx_w32_flush(priv->device_base, ISL38XX_DEV_INT_UPDATE, + ISL38XX_DEV_INT_REG); + udelay(ISL38XX_WRITEIO_DELAY); + + err = -EBUSY; + goto drop_free; + } + /* Check alignment and WDS frame formatting. The start of the packet should + * be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes + * and add WDS address information */ + if (likely(((long) skb->data & 0x03) | init_wds)) { + /* get the number of bytes to add and re-allign */ + offset = (4 - (long) skb->data) & 0x03; + offset += init_wds ? 6 : 0; + + /* check whether the current skb can be used */ + if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) { + unsigned char *src = skb->data; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "skb offset %i wds %i\n", offset, + init_wds); +#endif + + /* align the buffer on 4-byte boundary */ + skb_reserve(skb, (4 - (long) skb->data) & 0x03); + if (init_wds) { + /* wds requires an additional address field of 6 bytes */ + skb_put(skb, 6); +#ifdef ISLPCI_ETH_DEBUG + printk("islpci_eth_transmit:wds_mac\n"); +#endif + memmove(skb->data + 6, src, skb->len); + memcpy(skb->data, wds_mac, 6); + } else { + memmove(skb->data, src, skb->len); + } + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "memmove %p %p %i \n", skb->data, + src, skb->len); +#endif + } else { + newskb = + dev_alloc_skb(init_wds ? skb->len + 6 : skb->len); + if (unlikely(newskb == NULL)) { + printk(KERN_ERR "%s: Cannot allocate skb\n", + ndev->name); + err = -ENOMEM; + goto drop_free; + } + newskb_offset = (4 - (long) newskb->data) & 0x03; + + /* Check if newskb->data is aligned */ + if (newskb_offset) + skb_reserve(newskb, newskb_offset); + + skb_put(newskb, init_wds ? skb->len + 6 : skb->len); + if (init_wds) { + memcpy(newskb->data + 6, skb->data, skb->len); + memcpy(newskb->data, wds_mac, 6); +#ifdef ISLPCI_ETH_DEBUG + printk("islpci_eth_transmit:wds_mac\n"); +#endif + } else + memcpy(newskb->data, skb->data, skb->len); + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "memcpy %p %p %i wds %i\n", + newskb->data, skb->data, skb->len, init_wds); +#endif + + newskb->dev = skb->dev; + dev_kfree_skb(skb); + skb = newskb; + } + } + /* display the buffer contents for debugging */ +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_BUFFER_CONTENTS, "\ntx %p ", skb->data); + display_buffer((char *) skb->data, skb->len); +#endif + + /* map the skb buffer to pci memory for DMA operation */ + pci_map_address = pci_map_single(priv->pdev, + (void *) skb->data, skb->len, + PCI_DMA_TODEVICE); + if (unlikely(pci_map_address == 0)) { + printk(KERN_WARNING "%s: cannot map buffer to PCI\n", + ndev->name); + + err = -EIO; + goto drop_free; + } + /* Place the fragment in the control block structure. */ + index = curr_frag % ISL38XX_CB_TX_QSIZE; + fragment = &cb->tx_data_low[index]; + + priv->pci_map_tx_address[index] = pci_map_address; + /* store the skb address for future freeing */ + priv->data_low_tx[index] = skb; + /* set the proper fragment start address and size information */ + fragment->size = cpu_to_le16(frame_size); + fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */ + fragment->address = cpu_to_le32(pci_map_address); + curr_frag++; + + /* The fragment address in the control block must have been + * written before announcing the frame buffer to device. */ + wmb(); + cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ] = cpu_to_le32(curr_frag); + + if (curr_frag - priv->free_data_tx + ISL38XX_MIN_QTHRESHOLD + > ISL38XX_CB_TX_QSIZE) { + /* stop sends from upper layers */ + netif_stop_queue(ndev); + + /* set the full flag for the transmission queue */ + priv->data_low_tx_full = 1; + } + + /* trigger the device */ + islpci_trigger(priv); + + /* unlock the driver code */ + spin_unlock_irqrestore(&priv->slock, flags); + + /* set the transmission time */ + ndev->trans_start = jiffies; + priv->statistics.tx_packets++; + priv->statistics.tx_bytes += skb->len; + + return 0; + + drop_free: + /* free the skbuf structure before aborting */ + dev_kfree_skb(skb); + skb = NULL; + + priv->statistics.tx_dropped++; + spin_unlock_irqrestore(&priv->slock, flags); + return err; +} + +static inline int +islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb) +{ + /* The card reports full 802.11 packets but with a 20 bytes + * header and without the FCS. But there a is a bit that + * indicates if the packet is corrupted :-) */ + struct rfmon_header *hdr = (struct rfmon_header *) (*skb)->data; + if (hdr->flags & 0x01) + /* This one is bad. Drop it ! */ + return -1; + if (priv->ndev->type == ARPHRD_IEEE80211_PRISM) { + struct avs_80211_1_header *avs; + /* extract the relevant data from the header */ + u32 clock = le32_to_cpu(hdr->clock); + u8 rate = hdr->rate; + u16 freq = le16_to_cpu(hdr->freq); + u8 rssi = hdr->rssi; + + skb_pull(*skb, sizeof (struct rfmon_header)); + + if (skb_headroom(*skb) < sizeof (struct avs_80211_1_header)) { + struct sk_buff *newskb = skb_copy_expand(*skb, + sizeof (struct + avs_80211_1_header), + 0, GFP_ATOMIC); + if (newskb) { + dev_kfree_skb_irq(*skb); + *skb = newskb; + } else + return -1; + /* This behavior is not very subtile... */ + } + + /* make room for the new header and fill it. */ + avs = + (struct avs_80211_1_header *) skb_push(*skb, + sizeof (struct + avs_80211_1_header)); + + avs->version = cpu_to_be32(P80211CAPTURE_VERSION); + avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header)); + avs->mactime = cpu_to_be64(le64_to_cpu(clock)); + avs->hosttime = cpu_to_be64(jiffies); + avs->phytype = cpu_to_be32(6); /*OFDM: 6 for (g), 8 for (a) */ + avs->channel = cpu_to_be32(channel_of_freq(freq)); + avs->datarate = cpu_to_be32(rate * 5); + avs->antenna = cpu_to_be32(0); /*unknown */ + avs->priority = cpu_to_be32(0); /*unknown */ + avs->ssi_type = cpu_to_be32(3); /*2: dBm, 3: raw RSSI */ + avs->ssi_signal = cpu_to_be32(rssi & 0x7f); + avs->ssi_noise = cpu_to_be32(priv->local_iwstatistics.qual.noise); /*better than 'undefined', I assume */ + avs->preamble = cpu_to_be32(0); /*unknown */ + avs->encoding = cpu_to_be32(0); /*unknown */ + } else + skb_pull(*skb, sizeof (struct rfmon_header)); + + (*skb)->protocol = htons(ETH_P_802_2); + (*skb)->mac.raw = (*skb)->data; + (*skb)->pkt_type = PACKET_OTHERHOST; + + return 0; +} + +int +islpci_eth_receive(islpci_private *priv) +{ + struct net_device *ndev = priv->ndev; + isl38xx_control_block *control_block = priv->control_block; + struct sk_buff *skb; + u16 size; + u32 index, offset; + unsigned char *src; + int discard = 0; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive \n"); +#endif + + /* the device has written an Ethernet frame in the data area + * of the sk_buff without updating the structure, do it now */ + index = priv->free_data_rx % ISL38XX_CB_RX_QSIZE; + size = le16_to_cpu(control_block->rx_data_low[index].size); + skb = priv->data_low_rx[index]; + offset = ((unsigned long) + le32_to_cpu(control_block->rx_data_low[index].address) - + (unsigned long) skb->data) & 3; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, + "frq->addr %x skb->data %p skb->len %u offset %u truesize %u\n ", + control_block->rx_data_low[priv->free_data_rx].address, skb->data, + skb->len, offset, skb->truesize); +#endif + + /* delete the streaming DMA mapping before processing the skb */ + pci_unmap_single(priv->pdev, + priv->pci_map_rx_address[index], + MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE); + + /* update the skb structure and allign the buffer */ + skb_put(skb, size); + if (offset) { + /* shift the buffer allocation offset bytes to get the right frame */ + skb_pull(skb, 2); + skb_put(skb, 2); + } +#if VERBOSE > SHOW_ERROR_MESSAGES + /* display the buffer contents for debugging */ + DEBUG(SHOW_BUFFER_CONTENTS, "\nrx %p ", skb->data); + display_buffer((char *) skb->data, skb->len); +#endif + + /* check whether WDS is enabled and whether the data frame is a WDS frame */ + + if (init_wds) { + /* WDS enabled, check for the wds address on the first 6 bytes of the buffer */ + src = skb->data + 6; + memmove(skb->data, src, skb->len - 6); + skb_trim(skb, skb->len - 6); + } +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "Fragment size %i in skb at %p\n", size, skb); + DEBUG(SHOW_TRACING, "Skb data at %p, length %i\n", skb->data, skb->len); + + /* display the buffer contents for debugging */ + DEBUG(SHOW_BUFFER_CONTENTS, "\nrx %p ", skb->data); + display_buffer((char *) skb->data, skb->len); +#endif + + /* do some additional sk_buff and network layer parameters */ + skb->dev = ndev; + + /* take care of monitor mode and spy monitoring. */ + if (unlikely(priv->iw_mode == IW_MODE_MONITOR)) + discard = islpci_monitor_rx(priv, &skb); + else { + if (unlikely(skb->data[2 * ETH_ALEN] == 0)) { + /* The packet has a rx_annex. Read it for spy monitoring, Then + * remove it, while keeping the 2 leading MAC addr. + */ + struct iw_quality wstats; + struct rx_annex_header *annex = + (struct rx_annex_header *) skb->data; + wstats.level = annex->rfmon.rssi; + /* The noise value can be a bit outdated if nobody's + * reading wireless stats... */ + wstats.noise = priv->local_iwstatistics.qual.noise; + wstats.qual = wstats.level - wstats.noise; + wstats.updated = 0x07; + /* Update spy records */ + wireless_spy_update(ndev, annex->addr2, &wstats); + + memcpy(skb->data + sizeof (struct rfmon_header), + skb->data, 2 * ETH_ALEN); + skb_pull(skb, sizeof (struct rfmon_header)); + } + skb->protocol = eth_type_trans(skb, ndev); + } + skb->ip_summed = CHECKSUM_NONE; + priv->statistics.rx_packets++; + priv->statistics.rx_bytes += size; + + /* deliver the skb to the network layer */ +#ifdef ISLPCI_ETH_DEBUG + printk + ("islpci_eth_receive:netif_rx %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + skb->data[0], skb->data[1], skb->data[2], skb->data[3], + skb->data[4], skb->data[5]); +#endif + if (unlikely(discard)) { + dev_kfree_skb_irq(skb); + skb = NULL; + } else + netif_rx(skb); + + /* increment the read index for the rx data low queue */ + priv->free_data_rx++; + + /* add one or more sk_buff structures */ + while (index = + le32_to_cpu(control_block-> + driver_curr_frag[ISL38XX_CB_RX_DATA_LQ]), + index - priv->free_data_rx < ISL38XX_CB_RX_QSIZE) { + /* allocate an sk_buff for received data frames storage + * include any required allignment operations */ + skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2); + if (unlikely(skb == NULL)) { + /* error allocating an sk_buff structure elements */ + DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n"); + break; + } + skb_reserve(skb, (4 - (long) skb->data) & 0x03); + /* store the new skb structure pointer */ + index = index % ISL38XX_CB_RX_QSIZE; + priv->data_low_rx[index] = skb; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, + "new alloc skb %p skb->data %p skb->len %u index %u truesize %u\n ", + skb, skb->data, skb->len, index, skb->truesize); +#endif + + /* set the streaming DMA mapping for proper PCI bus operation */ + priv->pci_map_rx_address[index] = + pci_map_single(priv->pdev, (void *) skb->data, + MAX_FRAGMENT_SIZE_RX + 2, + PCI_DMA_FROMDEVICE); + if (unlikely(priv->pci_map_rx_address[index] == (dma_addr_t) NULL)) { + /* error mapping the buffer to device accessable memory address */ + DEBUG(SHOW_ERROR_MESSAGES, + "Error mapping DMA address\n"); + + /* free the skbuf structure before aborting */ + dev_kfree_skb_irq((struct sk_buff *) skb); + skb = NULL; + break; + } + /* update the fragment address */ + control_block->rx_data_low[index].address = cpu_to_le32((u32) + priv-> + pci_map_rx_address + [index]); + wmb(); + + /* increment the driver read pointer */ + add_le32p((u32 *) &control_block-> + driver_curr_frag[ISL38XX_CB_RX_DATA_LQ], 1); + } + + /* trigger the device */ + islpci_trigger(priv); + + return 0; +} + +void +islpci_do_reset_and_wake(void *data) +{ + islpci_private *priv = (islpci_private *) data; + islpci_reset(priv, 1); + netif_wake_queue(priv->ndev); + priv->reset_task_pending = 0; +} + +void +islpci_eth_tx_timeout(struct net_device *ndev) +{ + islpci_private *priv = netdev_priv(ndev); + struct net_device_stats *statistics = &priv->statistics; + + /* increment the transmit error counter */ + statistics->tx_errors++; + + if (!priv->reset_task_pending) { + priv->reset_task_pending = 1; + netif_stop_queue(ndev); + schedule_work(&priv->reset_task); + } + + return; +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_eth.h linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_eth.h --- linux-2.4.27/drivers/net/wireless/prism54/islpci_eth.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_eth.h 2004-09-10 19:35:30.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * + * Copyright (C) 2002 Intersil Americas Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _ISLPCI_ETH_H +#define _ISLPCI_ETH_H + +#include "isl_38xx.h" +#include "islpci_dev.h" + +struct rfmon_header { + u16 unk0; /* = 0x0000 */ + u16 length; /* = 0x1400 */ + u32 clock; /* 1MHz clock */ + u8 flags; + u8 unk1; + u8 rate; + u8 unk2; + u16 freq; + u16 unk3; + u8 rssi; + u8 padding[3]; +} __attribute__ ((packed)); + +struct rx_annex_header { + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + struct rfmon_header rfmon; +} __attribute__ ((packed)); + +/* wlan-ng (and hopefully others) AVS header, version one. Fields in + * network byte order. */ +#define P80211CAPTURE_VERSION 0x80211001 + +struct avs_80211_1_header { + uint32_t version; + uint32_t length; + uint64_t mactime; + uint64_t hosttime; + uint32_t phytype; + uint32_t channel; + uint32_t datarate; + uint32_t antenna; + uint32_t priority; + uint32_t ssi_type; + int32_t ssi_signal; + int32_t ssi_noise; + uint32_t preamble; + uint32_t encoding; +}; + +void islpci_eth_cleanup_transmit(islpci_private *, isl38xx_control_block *); +int islpci_eth_transmit(struct sk_buff *, struct net_device *); +int islpci_eth_receive(islpci_private *); +void islpci_eth_tx_timeout(struct net_device *); +void islpci_do_reset_and_wake(void *data); + +#endif /* _ISL_GEN_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_hotplug.c linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_hotplug.c --- linux-2.4.27/drivers/net/wireless/prism54/islpci_hotplug.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_hotplug.c 2004-09-10 19:33:21.000000000 +0000 @@ -0,0 +1,340 @@ +/* + * + * Copyright (C) 2002 Intersil Americas Inc. + * Copyright (C) 2003 Herbert Valerio Riedel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include /* For __init, __exit */ + +#include "prismcompat.h" +#include "islpci_dev.h" +#include "islpci_mgt.h" /* for pc_debug */ +#include "isl_oid.h" + +#define DRV_NAME "prism54" +#define DRV_VERSION "1.2" + +MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Development Team "); +MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter"); +MODULE_LICENSE("GPL"); + +static int init_pcitm = 0; +module_param(init_pcitm, int, 0); + +/* In this order: vendor, device, subvendor, subdevice, class, class_mask, + * driver_data + * If you have an update for this please contact prism54-devel@prism54.org + * The latest list can be found at http://prism54.org/supported_cards.php */ +static const struct pci_device_id prism54_id_tbl[] = { + /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ + { + 0x1260, 0x3890, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0 + }, + + /* 3COM 3CRWE154G72 Wireless LAN adapter */ + { + 0x10b7, 0x6001, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0 + }, + + /* Intersil PRISM Indigo Wireless LAN adapter */ + { + 0x1260, 0x3877, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0 + }, + + /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */ + { + 0x1260, 0x3886, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0 + }, + + /* End of list */ + {0,0,0,0,0,0,0} +}; + +/* register the device with the Hotplug facilities of the kernel */ +MODULE_DEVICE_TABLE(pci, prism54_id_tbl); + +static int prism54_probe(struct pci_dev *, const struct pci_device_id *); +static void prism54_remove(struct pci_dev *); +static int prism54_suspend(struct pci_dev *, u32 state); +static int prism54_resume(struct pci_dev *); + +static struct pci_driver prism54_driver = { + .name = DRV_NAME, + .id_table = prism54_id_tbl, + .probe = prism54_probe, + .remove = prism54_remove, + .suspend = prism54_suspend, + .resume = prism54_resume, + /* .enable_wake ; we don't support this yet */ +}; + +/****************************************************************************** + Module initialization functions +******************************************************************************/ + +int +prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct net_device *ndev; + u8 latency_tmr; + u32 mem_addr; + islpci_private *priv; + int rvalue; + + /* TRACE(DRV_NAME); */ + + + /* Enable the pci device */ + if (pci_enable_device(pdev)) { + printk(KERN_ERR "%s: pci_enable_device() failed.\n", DRV_NAME); + return -ENODEV; + } + + /* check whether the latency timer is set correctly */ + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_tmr); +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "latency timer: %x\n", latency_tmr); +#endif + if (latency_tmr < PCIDEVICE_LATENCY_TIMER_MIN) { + /* set the latency timer */ + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, + PCIDEVICE_LATENCY_TIMER_VAL); + } + + /* enable PCI DMA */ + if (pci_set_dma_mask(pdev, 0xffffffff)) { + printk(KERN_ERR "%s: 32-bit PCI DMA not supported", DRV_NAME); + goto do_pci_disable_device; + } + + /* 0x40 is the programmable timer to configure the response timeout (TRDY_TIMEOUT) + * 0x41 is the programmable timer to configure the retry timeout (RETRY_TIMEOUT) + * The RETRY_TIMEOUT is used to set the number of retries that the core, as a + * Master, will perform before abandoning a cycle. The default value for + * RETRY_TIMEOUT is 0x80, which far exceeds the PCI 2.1 requirement for new + * devices. A write of zero to the RETRY_TIMEOUT register disables this + * function to allow use with any non-compliant legacy devices that may + * execute more retries. + * + * Writing zero to both these two registers will disable both timeouts and + * *can* solve problems caused by devices that are slow to respond. + * Make this configurable - MSW + */ + if ( init_pcitm >= 0 ) { + pci_write_config_byte(pdev, 0x40, (u8)init_pcitm); + pci_write_config_byte(pdev, 0x41, (u8)init_pcitm); + } else { + printk(KERN_INFO "PCI TRDY/RETRY unchanged\n"); + } + + /* request the pci device I/O regions */ + rvalue = pci_request_regions(pdev, DRV_NAME); + if (rvalue) { + printk(KERN_ERR "%s: pci_request_regions failure (rc=%d)\n", + DRV_NAME, rvalue); + goto do_pci_disable_device; + } + + /* check if the memory window is indeed set */ + rvalue = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &mem_addr); + if (rvalue || !mem_addr) { + printk(KERN_ERR "%s: PCI device memory region not configured; fix your BIOS or CardBus bridge/drivers\n", + DRV_NAME); + goto do_pci_disable_device; + } + + /* enable PCI bus-mastering */ + DEBUG(SHOW_TRACING, "%s: pci_set_master(pdev)\n", DRV_NAME); + pci_set_master(pdev); + + /* enable MWI */ + pci_set_mwi(pdev); + + /* setup the network device interface and its structure */ + if (!(ndev = islpci_setup(pdev))) { + /* error configuring the driver as a network device */ + printk(KERN_ERR "%s: could not configure network device\n", + DRV_NAME); + goto do_pci_release_regions; + } + + priv = netdev_priv(ndev); + islpci_set_state(priv, PRV_STATE_PREBOOT); /* we are attempting to boot */ + + /* card is in unknown state yet, might have some interrupts pending */ + isl38xx_disable_interrupts(priv->device_base); + + /* request for the interrupt before uploading the firmware */ + rvalue = request_irq(pdev->irq, &islpci_interrupt, + SA_SHIRQ, ndev->name, priv); + + if (rvalue) { + /* error, could not hook the handler to the irq */ + printk(KERN_ERR "%s: could not install IRQ handler\n", + ndev->name); + goto do_unregister_netdev; + } + + /* firmware upload is triggered in islpci_open */ + + return 0; + + do_unregister_netdev: + unregister_netdev(ndev); + islpci_free_memory(priv); + pci_set_drvdata(pdev, NULL); + free_netdev(ndev); + priv = NULL; + do_pci_release_regions: + pci_release_regions(pdev); + do_pci_disable_device: + pci_disable_device(pdev); + return -EIO; +} + +/* set by cleanup_module */ +static volatile int __in_cleanup_module = 0; + +/* this one removes one(!!) instance only */ +void +prism54_remove(struct pci_dev *pdev) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + islpci_private *priv = ndev ? netdev_priv(ndev) : NULL; + BUG_ON(!priv); + + if (!__in_cleanup_module) { + printk(KERN_DEBUG "%s: hot unplug detected\n", ndev->name); + islpci_set_state(priv, PRV_STATE_OFF); + } + + printk(KERN_DEBUG "%s: removing device\n", ndev->name); + + unregister_netdev(ndev); + + /* free the interrupt request */ + + if (islpci_get_state(priv) != PRV_STATE_OFF) { + isl38xx_disable_interrupts(priv->device_base); + islpci_set_state(priv, PRV_STATE_OFF); + /* This bellow causes a lockup at rmmod time. It might be + * because some interrupts still linger after rmmod time, + * see bug #17 */ + /* pci_set_power_state(pdev, 3);*/ /* try to power-off */ + } + + free_irq(pdev->irq, priv); + + /* free the PCI memory and unmap the remapped page */ + islpci_free_memory(priv); + + pci_set_drvdata(pdev, NULL); + free_netdev(ndev); + priv = NULL; + + pci_release_regions(pdev); + + pci_disable_device(pdev); +} + +int +prism54_suspend(struct pci_dev *pdev, u32 state) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + islpci_private *priv = ndev ? netdev_priv(ndev) : NULL; + BUG_ON(!priv); + + printk(KERN_NOTICE "%s: got suspend request (state %d)\n", + ndev->name, state); + + pci_save_state(pdev, priv->pci_state); + + /* tell the device not to trigger interrupts for now... */ + isl38xx_disable_interrupts(priv->device_base); + + /* from now on assume the hardware was already powered down + and don't touch it anymore */ + islpci_set_state(priv, PRV_STATE_OFF); + + netif_stop_queue(ndev); + netif_device_detach(ndev); + + return 0; +} + +int +prism54_resume(struct pci_dev *pdev) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + islpci_private *priv = ndev ? netdev_priv(ndev) : NULL; + BUG_ON(!priv); + + printk(KERN_NOTICE "%s: got resume request\n", ndev->name); + + pci_restore_state(pdev, priv->pci_state); + + /* alright let's go into the PREBOOT state */ + islpci_reset(priv, 1); + + netif_device_attach(ndev); + netif_start_queue(ndev); + + return 0; +} + +static int __init +prism54_module_init(void) +{ + printk(KERN_INFO "Loaded %s driver, version %s\n", + DRV_NAME, DRV_VERSION); + + __bug_on_wrong_struct_sizes (); + + return pci_module_init(&prism54_driver); +} + +/* by the time prism54_module_exit() terminates, as a postcondition + * all instances will have been destroyed by calls to + * prism54_remove() */ +static void __exit +prism54_module_exit(void) +{ + __in_cleanup_module = 1; + + pci_unregister_driver(&prism54_driver); + + printk(KERN_INFO "Unloaded %s driver\n", DRV_NAME); + + __in_cleanup_module = 0; +} + +/* register entry points */ +module_init(prism54_module_init); +module_exit(prism54_module_exit); +/* EOF */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_mgt.c linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_mgt.c --- linux-2.4.27/drivers/net/wireless/prism54/islpci_mgt.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_mgt.c 2004-09-10 19:32:28.000000000 +0000 @@ -0,0 +1,510 @@ +/* + * + * Copyright (C) 2002 Intersil Americas Inc. + * Copyright 2004 Jens Maurer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "prismcompat.h" +#include "isl_38xx.h" +#include "islpci_mgt.h" +#include "isl_oid.h" /* additional types and defs for isl38xx fw */ +#include "isl_ioctl.h" + +#include + +/****************************************************************************** + Global variable definition section +******************************************************************************/ +int pc_debug = VERBOSE; +module_param(pc_debug, int, 0); + +/****************************************************************************** + Driver general functions +******************************************************************************/ +void +display_buffer(char *buffer, int length) +{ + if ((pc_debug & SHOW_BUFFER_CONTENTS) == 0) + return; + + while (length > 0) { + printk("[%02x]", *buffer & 255); + length--; + buffer++; + } + + printk("\n"); +} + +/***************************************************************************** + Queue handling for management frames +******************************************************************************/ + +/* + * Helper function to create a PIMFOR management frame header. + */ +static void +pimfor_encode_header(int operation, u32 oid, u32 length, pimfor_header_t *h) +{ + h->version = PIMFOR_VERSION; + h->operation = operation; + h->device_id = PIMFOR_DEV_ID_MHLI_MIB; + h->flags = 0; + h->oid = cpu_to_be32(oid); + h->length = cpu_to_be32(length); +} + +/* + * Helper function to analyze a PIMFOR management frame header. + */ +static pimfor_header_t * +pimfor_decode_header(void *data, int len) +{ + pimfor_header_t *h = data; + + while ((void *) h < data + len) { + if (h->flags & PIMFOR_FLAG_LITTLE_ENDIAN) { + le32_to_cpus(&h->oid); + le32_to_cpus(&h->length); + } else { + be32_to_cpus(&h->oid); + be32_to_cpus(&h->length); + } + if (h->oid != OID_INL_TUNNEL) + return h; + h++; + } + return NULL; +} + +/* + * Fill the receive queue for management frames with fresh buffers. + */ +int +islpci_mgmt_rx_fill(struct net_device *ndev) +{ + islpci_private *priv = netdev_priv(ndev); + isl38xx_control_block *cb = /* volatile not needed */ + (isl38xx_control_block *) priv->control_block; + u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]); + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgmt_rx_fill \n"); +#endif + + while (curr - priv->index_mgmt_rx < ISL38XX_CB_MGMT_QSIZE) { + u32 index = curr % ISL38XX_CB_MGMT_QSIZE; + struct islpci_membuf *buf = &priv->mgmt_rx[index]; + isl38xx_fragment *frag = &cb->rx_data_mgmt[index]; + + if (buf->mem == NULL) { + buf->mem = kmalloc(MGMT_FRAME_SIZE, GFP_ATOMIC); + if (!buf->mem) { + printk(KERN_WARNING + "Error allocating management frame.\n"); + return -ENOMEM; + } + buf->size = MGMT_FRAME_SIZE; + } + if (buf->pci_addr == 0) { + buf->pci_addr = pci_map_single(priv->pdev, buf->mem, + MGMT_FRAME_SIZE, + PCI_DMA_FROMDEVICE); + if (!buf->pci_addr) { + printk(KERN_WARNING + "Failed to make memory DMA'able\n."); + return -ENOMEM; + } + } + + /* be safe: always reset control block information */ + frag->size = cpu_to_le16(MGMT_FRAME_SIZE); + frag->flags = 0; + frag->address = cpu_to_le32(buf->pci_addr); + curr++; + + /* The fragment address in the control block must have + * been written before announcing the frame buffer to + * device */ + wmb(); + cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = cpu_to_le32(curr); + } + return 0; +} + +/* + * Create and transmit a management frame using "operation" and "oid", + * with arguments data/length. + * We either return an error and free the frame, or we return 0 and + * islpci_mgt_cleanup_transmit() frees the frame in the tx-done + * interrupt. + */ +static int +islpci_mgt_transmit(struct net_device *ndev, int operation, unsigned long oid, + void *data, int length) +{ + islpci_private *priv = netdev_priv(ndev); + isl38xx_control_block *cb = + (isl38xx_control_block *) priv->control_block; + void *p; + int err = -EINVAL; + unsigned long flags; + isl38xx_fragment *frag; + struct islpci_membuf buf; + u32 curr_frag; + int index; + int frag_len = length + PIMFOR_HEADER_SIZE; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_transmit\n"); +#endif + + if (frag_len > MGMT_FRAME_SIZE) { + printk(KERN_DEBUG "%s: mgmt frame too large %d\n", + ndev->name, frag_len); + goto error; + } + + err = -ENOMEM; + p = buf.mem = kmalloc(frag_len, GFP_KERNEL); + if (!buf.mem) { + printk(KERN_DEBUG "%s: cannot allocate mgmt frame\n", + ndev->name); + goto error; + } + buf.size = frag_len; + + /* create the header directly in the fragment data area */ + pimfor_encode_header(operation, oid, length, (pimfor_header_t *) p); + p += PIMFOR_HEADER_SIZE; + + if (data) + memcpy(p, data, length); + else + memset(p, 0, length); + +#if VERBOSE > SHOW_ERROR_MESSAGES + { + pimfor_header_t *h = buf.mem; + DEBUG(SHOW_PIMFOR_FRAMES, + "PIMFOR: op %i, oid 0x%08lx, device %i, flags 0x%x length 0x%x \n", + h->operation, oid, h->device_id, h->flags, length); + + /* display the buffer contents for debugging */ + display_buffer((char *) h, sizeof (pimfor_header_t)); + display_buffer(p, length); + } +#endif + + err = -ENOMEM; + buf.pci_addr = pci_map_single(priv->pdev, buf.mem, frag_len, + PCI_DMA_TODEVICE); + if (!buf.pci_addr) { + printk(KERN_WARNING "%s: cannot map PCI memory for mgmt\n", + ndev->name); + goto error_free; + } + + /* Protect the control block modifications against interrupts. */ + spin_lock_irqsave(&priv->slock, flags); + curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ]); + if (curr_frag - priv->index_mgmt_tx >= ISL38XX_CB_MGMT_QSIZE) { + printk(KERN_WARNING "%s: mgmt tx queue is still full\n", + ndev->name); + goto error_unlock; + } + + /* commit the frame to the tx device queue */ + index = curr_frag % ISL38XX_CB_MGMT_QSIZE; + priv->mgmt_tx[index] = buf; + frag = &cb->tx_data_mgmt[index]; + frag->size = cpu_to_le16(frag_len); + frag->flags = 0; /* for any other than the last fragment, set to 1 */ + frag->address = cpu_to_le32(buf.pci_addr); + + /* The fragment address in the control block must have + * been written before announcing the frame buffer to + * device */ + wmb(); + cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ] = cpu_to_le32(curr_frag + 1); + spin_unlock_irqrestore(&priv->slock, flags); + + /* trigger the device */ + islpci_trigger(priv); + return 0; + + error_unlock: + spin_unlock_irqrestore(&priv->slock, flags); + error_free: + kfree(buf.mem); + error: + return err; +} + +/* + * Receive a management frame from the device. + * This can be an arbitrary number of traps, and at most one response + * frame for a previous request sent via islpci_mgt_transmit(). + */ +int +islpci_mgt_receive(struct net_device *ndev) +{ + islpci_private *priv = netdev_priv(ndev); + isl38xx_control_block *cb = + (isl38xx_control_block *) priv->control_block; + u32 curr_frag; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive \n"); +#endif + + /* Only once per interrupt, determine fragment range to + * process. This avoids an endless loop (i.e. lockup) if + * frames come in faster than we can process them. */ + curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_RX_MGMTQ]); + barrier(); + + for (; priv->index_mgmt_rx < curr_frag; priv->index_mgmt_rx++) { + pimfor_header_t *header; + u32 index = priv->index_mgmt_rx % ISL38XX_CB_MGMT_QSIZE; + struct islpci_membuf *buf = &priv->mgmt_rx[index]; + u16 frag_len; + int size; + struct islpci_mgmtframe *frame; + + /* I have no idea (and no documentation) if flags != 0 + * is possible. Drop the frame, reuse the buffer. */ + if (le16_to_cpu(cb->rx_data_mgmt[index].flags) != 0) { + printk(KERN_WARNING "%s: unknown flags 0x%04x\n", + ndev->name, + le16_to_cpu(cb->rx_data_mgmt[index].flags)); + continue; + } + + /* The device only returns the size of the header(s) here. */ + frag_len = le16_to_cpu(cb->rx_data_mgmt[index].size); + + /* + * We appear to have no way to tell the device the + * size of a receive buffer. Thus, if this check + * triggers, we likely have kernel heap corruption. */ + if (frag_len > MGMT_FRAME_SIZE) { + printk(KERN_WARNING + "%s: Bogus packet size of %d (%#x).\n", + ndev->name, frag_len, frag_len); + frag_len = MGMT_FRAME_SIZE; + } + + /* Ensure the results of device DMA are visible to the CPU. */ + pci_dma_sync_single(priv->pdev, buf->pci_addr, + buf->size, PCI_DMA_FROMDEVICE); + + /* Perform endianess conversion for PIMFOR header in-place. */ + header = pimfor_decode_header(buf->mem, frag_len); + if (!header) { + printk(KERN_WARNING "%s: no PIMFOR header found\n", + ndev->name); + continue; + } + + /* The device ID from the PIMFOR packet received from + * the MVC is always 0. We forward a sensible device_id. + * Not that anyone upstream would care... */ + header->device_id = priv->ndev->ifindex; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_PIMFOR_FRAMES, + "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x \n", + header->operation, header->oid, header->device_id, + header->flags, header->length); + + /* display the buffer contents for debugging */ + display_buffer((char *) header, PIMFOR_HEADER_SIZE); + display_buffer((char *) header + PIMFOR_HEADER_SIZE, + header->length); +#endif + + /* nobody sends these */ + if (header->flags & PIMFOR_FLAG_APPLIC_ORIGIN) { + printk(KERN_DEBUG + "%s: errant PIMFOR application frame\n", + ndev->name); + continue; + } + + /* Determine frame size, skipping OID_INL_TUNNEL headers. */ + size = PIMFOR_HEADER_SIZE + header->length; + frame = kmalloc(sizeof (struct islpci_mgmtframe) + size, + GFP_ATOMIC); + if (!frame) { + printk(KERN_WARNING + "%s: Out of memory, cannot handle oid 0x%08x\n", + ndev->name, header->oid); + continue; + } + frame->ndev = ndev; + memcpy(&frame->buf, header, size); + frame->header = (pimfor_header_t *) frame->buf; + frame->data = frame->buf + PIMFOR_HEADER_SIZE; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_PIMFOR_FRAMES, + "frame: header: %p, data: %p, size: %d\n", + frame->header, frame->data, size); +#endif + + if (header->operation == PIMFOR_OP_TRAP) { +#if VERBOSE > SHOW_ERROR_MESSAGES + printk(KERN_DEBUG + "TRAP: oid 0x%x, device %i, flags 0x%x length %i\n", + header->oid, header->device_id, header->flags, + header->length); +#endif + + /* Create work to handle trap out of interrupt + * context. */ + INIT_WORK(&frame->ws, prism54_process_trap, frame); + schedule_work(&frame->ws); + + } else { + /* Signal the one waiting process that a response + * has been received. */ + if ((frame = xchg(&priv->mgmt_received, frame)) != NULL) { + printk(KERN_WARNING + "%s: mgmt response not collected\n", + ndev->name); + kfree(frame); + } +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "Wake up Mgmt Queue\n"); +#endif + wake_up(&priv->mgmt_wqueue); + } + + } + + return 0; +} + +/* + * Cleanup the transmit queue by freeing all frames handled by the device. + */ +void +islpci_mgt_cleanup_transmit(struct net_device *ndev) +{ + islpci_private *priv = netdev_priv(ndev); + isl38xx_control_block *cb = /* volatile not needed */ + (isl38xx_control_block *) priv->control_block; + u32 curr_frag; + +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_cleanup_transmit\n"); +#endif + + /* Only once per cleanup, determine fragment range to + * process. This avoids an endless loop (i.e. lockup) if + * the device became confused, incrementing device_curr_frag + * rapidly. */ + curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_TX_MGMTQ]); + barrier(); + + for (; priv->index_mgmt_tx < curr_frag; priv->index_mgmt_tx++) { + int index = priv->index_mgmt_tx % ISL38XX_CB_MGMT_QSIZE; + struct islpci_membuf *buf = &priv->mgmt_tx[index]; + pci_unmap_single(priv->pdev, buf->pci_addr, buf->size, + PCI_DMA_TODEVICE); + buf->pci_addr = 0; + kfree(buf->mem); + buf->mem = NULL; + buf->size = 0; + } +} + +/* + * Perform one request-response transaction to the device. + */ +int +islpci_mgt_transaction(struct net_device *ndev, + int operation, unsigned long oid, + void *senddata, int sendlen, + struct islpci_mgmtframe **recvframe) +{ + islpci_private *priv = netdev_priv(ndev); + const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000; + long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies; + int err; + DEFINE_WAIT(wait); + + *recvframe = NULL; + + if (down_interruptible(&priv->mgmt_sem)) + return -ERESTARTSYS; + + prepare_to_wait(&priv->mgmt_wqueue, &wait, TASK_UNINTERRUPTIBLE); + err = islpci_mgt_transmit(ndev, operation, oid, senddata, sendlen); + if (err) + goto out; + + err = -ETIMEDOUT; + while (timeout_left > 0) { + int timeleft; + struct islpci_mgmtframe *frame; + + timeleft = schedule_timeout(wait_cycle_jiffies); + frame = xchg(&priv->mgmt_received, NULL); + if (frame) { + if (frame->header->oid == oid) { + *recvframe = frame; + err = 0; + goto out; + } else { + printk(KERN_DEBUG + "%s: expecting oid 0x%x, received 0x%x.\n", + ndev->name, (unsigned int) oid, + frame->header->oid); + kfree(frame); + frame = NULL; + } + } + if (timeleft == 0) { + printk(KERN_DEBUG + "%s: timeout waiting for mgmt response %lu, " + "triggering device\n", + ndev->name, timeout_left); + islpci_trigger(priv); + } + timeout_left += timeleft - wait_cycle_jiffies; + } + printk(KERN_WARNING "%s: timeout waiting for mgmt response\n", + ndev->name); + + /* TODO: we should reset the device here */ + out: + finish_wait(&priv->mgmt_wqueue, &wait); + up(&priv->mgmt_sem); + return err; +} + diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_mgt.h linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_mgt.h --- linux-2.4.27/drivers/net/wireless/prism54/islpci_mgt.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_mgt.h 2004-09-10 19:36:59.000000000 +0000 @@ -0,0 +1,147 @@ +/* + * + * Copyright (C) 2002 Intersil Americas Inc. + * Copyright (C) 2003 Luis R. Rodriguez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _ISLPCI_MGT_H +#define _ISLPCI_MGT_H + +#include +#include + +/* + * Function definitions + */ + +#define K_DEBUG(f, m, args...) do { if(f & m) printk(KERN_DEBUG args); } while(0) +#define DEBUG(f, args...) K_DEBUG(f, pc_debug, args) + +#define TRACE(devname) K_DEBUG(SHOW_TRACING, VERBOSE, "%s: -> " __FUNCTION__ "()\n", devname) + +extern int pc_debug; +#define init_wds 0 /* help compiler optimize away dead code */ + + +/* General driver definitions */ +#define PCIDEVICE_LATENCY_TIMER_MIN 0x40 +#define PCIDEVICE_LATENCY_TIMER_VAL 0x50 + +/* Debugging verbose definitions */ +#define SHOW_NOTHING 0x00 /* overrules everything */ +#define SHOW_ANYTHING 0xFF +#define SHOW_ERROR_MESSAGES 0x01 +#define SHOW_TRAPS 0x02 +#define SHOW_FUNCTION_CALLS 0x04 +#define SHOW_TRACING 0x08 +#define SHOW_QUEUE_INDEXES 0x10 +#define SHOW_PIMFOR_FRAMES 0x20 +#define SHOW_BUFFER_CONTENTS 0x40 +#define VERBOSE 0x01 + +/* Default card definitions */ +#define CARD_DEFAULT_CHANNEL 6 +#define CARD_DEFAULT_MODE INL_MODE_CLIENT +#define CARD_DEFAULT_IW_MODE IW_MODE_INFRA +#define CARD_DEFAULT_BSSTYPE DOT11_BSSTYPE_INFRA +#define CARD_DEFAULT_CLIENT_SSID "" +#define CARD_DEFAULT_AP_SSID "default" +#define CARD_DEFAULT_KEY1 "default_key_1" +#define CARD_DEFAULT_KEY2 "default_key_2" +#define CARD_DEFAULT_KEY3 "default_key_3" +#define CARD_DEFAULT_KEY4 "default_key_4" +#define CARD_DEFAULT_WEP 0 +#define CARD_DEFAULT_FILTER 0 +#define CARD_DEFAULT_WDS 0 +#define CARD_DEFAULT_AUTHEN DOT11_AUTH_OS +#define CARD_DEFAULT_DOT1X 0 +#define CARD_DEFAULT_MLME_MODE DOT11_MLME_AUTO +#define CARD_DEFAULT_CONFORMANCE OID_INL_CONFORMANCE_NONE +#define CARD_DEFAULT_PROFILE DOT11_PROFILE_MIXED_G_WIFI +#define CARD_DEFAULT_MAXFRAMEBURST DOT11_MAXFRAMEBURST_MIXED_SAFE + +/* PIMFOR package definitions */ +#define PIMFOR_ETHERTYPE 0x8828 +#define PIMFOR_HEADER_SIZE 12 +#define PIMFOR_VERSION 1 +#define PIMFOR_OP_GET 0 +#define PIMFOR_OP_SET 1 +#define PIMFOR_OP_RESPONSE 2 +#define PIMFOR_OP_ERROR 3 +#define PIMFOR_OP_TRAP 4 +#define PIMFOR_OP_RESERVED 5 /* till 255 */ +#define PIMFOR_DEV_ID_MHLI_MIB 0 +#define PIMFOR_FLAG_APPLIC_ORIGIN 0x01 +#define PIMFOR_FLAG_LITTLE_ENDIAN 0x02 + +static inline void +add_le32p(u32 * le_number, u32 add) +{ + *le_number = cpu_to_le32(le32_to_cpup(le_number) + add); +} + +void display_buffer(char *, int); + +/* + * Type definition section + * + * the structure defines only the header allowing copyless + * frame handling + */ +typedef struct { + u8 version; + u8 operation; + u32 oid; + u8 device_id; + u8 flags; + u32 length; +} __attribute__ ((packed)) +pimfor_header_t; + +/* A received and interrupt-processed management frame, either for + * schedule_work(prism54_process_trap) or for priv->mgmt_received, + * processed by islpci_mgt_transaction(). */ +struct islpci_mgmtframe { + struct net_device *ndev; /* pointer to network device */ + pimfor_header_t *header; /* payload header, points into buf */ + void *data; /* payload ex header, points into buf */ + struct work_struct ws; /* argument for schedule_work() */ + char buf[0]; /* fragment buffer */ +}; + +int +islpci_mgt_receive(struct net_device *ndev); + +int +islpci_mgmt_rx_fill(struct net_device *ndev); + +void +islpci_mgt_cleanup_transmit(struct net_device *ndev); + +int +islpci_mgt_transaction(struct net_device *ndev, + int operation, unsigned long oid, + void *senddata, int sendlen, + struct islpci_mgmtframe **recvframe); + +static inline void +islpci_mgt_release(struct islpci_mgmtframe *frame) +{ + kfree(frame); +} + +#endif /* _ISLPCI_MGT_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/oid_mgt.c linux-2.4.28-pre3/drivers/net/wireless/prism54/oid_mgt.c --- linux-2.4.27/drivers/net/wireless/prism54/oid_mgt.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/oid_mgt.c 2004-09-10 19:34:09.000000000 +0000 @@ -0,0 +1,811 @@ +/* + * Copyright (C) 2003,2004 Aurelien Alleaume + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "prismcompat.h" +#include "islpci_dev.h" +#include "islpci_mgt.h" +#include "isl_oid.h" +#include "oid_mgt.h" +#include "isl_ioctl.h" + +/* to convert between channel and freq */ +const int frequency_list_bg[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; + +int +channel_of_freq(int f) +{ + int c = 0; + + if ((f >= 2412) && (f <= 2484)) { + while ((c < 14) && (f != frequency_list_bg[c])) + c++; + return (c >= 14) ? 0 : ++c; + } else if ((f >= (int) 5000) && (f <= (int) 6000)) { + return ( (f - 5000) / 5 ); + } else + return 0; +} + +#define OID_STRUCT(name,oid,s,t) [name] = {oid, 0, sizeof(s), t} +#define OID_STRUCT_C(name,oid,s,t) OID_STRUCT(name,oid,s,t | OID_FLAG_CACHED) +#define OID_U32(name,oid) OID_STRUCT(name,oid,u32,OID_TYPE_U32) +#define OID_U32_C(name,oid) OID_STRUCT_C(name,oid,u32,OID_TYPE_U32) +#define OID_STRUCT_MLME(name,oid) OID_STRUCT(name,oid,struct obj_mlme,OID_TYPE_MLME) +#define OID_STRUCT_MLMEEX(name,oid) OID_STRUCT(name,oid,struct obj_mlmeex,OID_TYPE_MLMEEX) + +#define OID_UNKNOWN(name,oid) OID_STRUCT(name,oid,0,0) + +struct oid_t isl_oid[] = { + OID_STRUCT(GEN_OID_MACADDRESS, 0x00000000, u8[6], OID_TYPE_ADDR), + OID_U32(GEN_OID_LINKSTATE, 0x00000001), + OID_UNKNOWN(GEN_OID_WATCHDOG, 0x00000002), + OID_UNKNOWN(GEN_OID_MIBOP, 0x00000003), + OID_UNKNOWN(GEN_OID_OPTIONS, 0x00000004), + OID_UNKNOWN(GEN_OID_LEDCONFIG, 0x00000005), + + /* 802.11 */ + OID_U32_C(DOT11_OID_BSSTYPE, 0x10000000), + OID_STRUCT_C(DOT11_OID_BSSID, 0x10000001, u8[6], OID_TYPE_RAW), + OID_STRUCT_C(DOT11_OID_SSID, 0x10000002, struct obj_ssid, + OID_TYPE_SSID), + OID_U32(DOT11_OID_STATE, 0x10000003), + OID_U32(DOT11_OID_AID, 0x10000004), + OID_STRUCT(DOT11_OID_COUNTRYSTRING, 0x10000005, u8[4], OID_TYPE_RAW), + OID_STRUCT_C(DOT11_OID_SSIDOVERRIDE, 0x10000006, struct obj_ssid, + OID_TYPE_SSID), + + OID_U32(DOT11_OID_MEDIUMLIMIT, 0x11000000), + OID_U32_C(DOT11_OID_BEACONPERIOD, 0x11000001), + OID_U32(DOT11_OID_DTIMPERIOD, 0x11000002), + OID_U32(DOT11_OID_ATIMWINDOW, 0x11000003), + OID_U32(DOT11_OID_LISTENINTERVAL, 0x11000004), + OID_U32(DOT11_OID_CFPPERIOD, 0x11000005), + OID_U32(DOT11_OID_CFPDURATION, 0x11000006), + + OID_U32_C(DOT11_OID_AUTHENABLE, 0x12000000), + OID_U32_C(DOT11_OID_PRIVACYINVOKED, 0x12000001), + OID_U32_C(DOT11_OID_EXUNENCRYPTED, 0x12000002), + OID_U32_C(DOT11_OID_DEFKEYID, 0x12000003), + [DOT11_OID_DEFKEYX] = {0x12000004, 3, sizeof (struct obj_key), + OID_FLAG_CACHED | OID_TYPE_KEY}, /* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */ + OID_UNKNOWN(DOT11_OID_STAKEY, 0x12000008), + OID_U32(DOT11_OID_REKEYTHRESHOLD, 0x12000009), + OID_UNKNOWN(DOT11_OID_STASC, 0x1200000a), + + OID_U32(DOT11_OID_PRIVTXREJECTED, 0x1a000000), + OID_U32(DOT11_OID_PRIVRXPLAIN, 0x1a000001), + OID_U32(DOT11_OID_PRIVRXFAILED, 0x1a000002), + OID_U32(DOT11_OID_PRIVRXNOKEY, 0x1a000003), + + OID_U32_C(DOT11_OID_RTSTHRESH, 0x13000000), + OID_U32_C(DOT11_OID_FRAGTHRESH, 0x13000001), + OID_U32_C(DOT11_OID_SHORTRETRIES, 0x13000002), + OID_U32_C(DOT11_OID_LONGRETRIES, 0x13000003), + OID_U32_C(DOT11_OID_MAXTXLIFETIME, 0x13000004), + OID_U32(DOT11_OID_MAXRXLIFETIME, 0x13000005), + OID_U32(DOT11_OID_AUTHRESPTIMEOUT, 0x13000006), + OID_U32(DOT11_OID_ASSOCRESPTIMEOUT, 0x13000007), + + OID_UNKNOWN(DOT11_OID_ALOFT_TABLE, 0x1d000000), + OID_UNKNOWN(DOT11_OID_ALOFT_CTRL_TABLE, 0x1d000001), + OID_UNKNOWN(DOT11_OID_ALOFT_RETREAT, 0x1d000002), + OID_UNKNOWN(DOT11_OID_ALOFT_PROGRESS, 0x1d000003), + OID_U32(DOT11_OID_ALOFT_FIXEDRATE, 0x1d000004), + OID_UNKNOWN(DOT11_OID_ALOFT_RSSIGRAPH, 0x1d000005), + OID_UNKNOWN(DOT11_OID_ALOFT_CONFIG, 0x1d000006), + + [DOT11_OID_VDCFX] = {0x1b000000, 7, 0, 0}, + OID_U32(DOT11_OID_MAXFRAMEBURST, 0x1b000008), + + OID_U32(DOT11_OID_PSM, 0x14000000), + OID_U32(DOT11_OID_CAMTIMEOUT, 0x14000001), + OID_U32(DOT11_OID_RECEIVEDTIMS, 0x14000002), + OID_U32(DOT11_OID_ROAMPREFERENCE, 0x14000003), + + OID_U32(DOT11_OID_BRIDGELOCAL, 0x15000000), + OID_U32(DOT11_OID_CLIENTS, 0x15000001), + OID_U32(DOT11_OID_CLIENTSASSOCIATED, 0x15000002), + [DOT11_OID_CLIENTX] = {0x15000003, 2006, 0, 0}, /* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */ + + OID_STRUCT(DOT11_OID_CLIENTFIND, 0x150007DB, u8[6], OID_TYPE_ADDR), + OID_STRUCT(DOT11_OID_WDSLINKADD, 0x150007DC, u8[6], OID_TYPE_ADDR), + OID_STRUCT(DOT11_OID_WDSLINKREMOVE, 0x150007DD, u8[6], OID_TYPE_ADDR), + OID_STRUCT(DOT11_OID_EAPAUTHSTA, 0x150007DE, u8[6], OID_TYPE_ADDR), + OID_STRUCT(DOT11_OID_EAPUNAUTHSTA, 0x150007DF, u8[6], OID_TYPE_ADDR), + OID_U32_C(DOT11_OID_DOT1XENABLE, 0x150007E0), + OID_UNKNOWN(DOT11_OID_MICFAILURE, 0x150007E1), + OID_UNKNOWN(DOT11_OID_REKEYINDICATE, 0x150007E2), + + OID_U32(DOT11_OID_MPDUTXSUCCESSFUL, 0x16000000), + OID_U32(DOT11_OID_MPDUTXONERETRY, 0x16000001), + OID_U32(DOT11_OID_MPDUTXMULTIPLERETRIES, 0x16000002), + OID_U32(DOT11_OID_MPDUTXFAILED, 0x16000003), + OID_U32(DOT11_OID_MPDURXSUCCESSFUL, 0x16000004), + OID_U32(DOT11_OID_MPDURXDUPS, 0x16000005), + OID_U32(DOT11_OID_RTSSUCCESSFUL, 0x16000006), + OID_U32(DOT11_OID_RTSFAILED, 0x16000007), + OID_U32(DOT11_OID_ACKFAILED, 0x16000008), + OID_U32(DOT11_OID_FRAMERECEIVES, 0x16000009), + OID_U32(DOT11_OID_FRAMEERRORS, 0x1600000A), + OID_U32(DOT11_OID_FRAMEABORTS, 0x1600000B), + OID_U32(DOT11_OID_FRAMEABORTSPHY, 0x1600000C), + + OID_U32(DOT11_OID_SLOTTIME, 0x17000000), + OID_U32(DOT11_OID_CWMIN, 0x17000001), + OID_U32(DOT11_OID_CWMAX, 0x17000002), + OID_U32(DOT11_OID_ACKWINDOW, 0x17000003), + OID_U32(DOT11_OID_ANTENNARX, 0x17000004), + OID_U32(DOT11_OID_ANTENNATX, 0x17000005), + OID_U32(DOT11_OID_ANTENNADIVERSITY, 0x17000006), + OID_U32_C(DOT11_OID_CHANNEL, 0x17000007), + OID_U32_C(DOT11_OID_EDTHRESHOLD, 0x17000008), + OID_U32(DOT11_OID_PREAMBLESETTINGS, 0x17000009), + OID_STRUCT(DOT11_OID_RATES, 0x1700000A, u8[IWMAX_BITRATES + 1], + OID_TYPE_RAW), + OID_U32(DOT11_OID_CCAMODESUPPORTED, 0x1700000B), + OID_U32(DOT11_OID_CCAMODE, 0x1700000C), + OID_UNKNOWN(DOT11_OID_RSSIVECTOR, 0x1700000D), + OID_UNKNOWN(DOT11_OID_OUTPUTPOWERTABLE, 0x1700000E), + OID_U32(DOT11_OID_OUTPUTPOWER, 0x1700000F), + OID_STRUCT(DOT11_OID_SUPPORTEDRATES, 0x17000010, + u8[IWMAX_BITRATES + 1], OID_TYPE_RAW), + OID_U32_C(DOT11_OID_FREQUENCY, 0x17000011), + [DOT11_OID_SUPPORTEDFREQUENCIES] = + {0x17000012, 0, sizeof (struct obj_frequencies) + + sizeof (u16) * IWMAX_FREQ, OID_TYPE_FREQUENCIES}, + + OID_U32(DOT11_OID_NOISEFLOOR, 0x17000013), + OID_STRUCT(DOT11_OID_FREQUENCYACTIVITY, 0x17000014, u8[IWMAX_FREQ + 1], + OID_TYPE_RAW), + OID_UNKNOWN(DOT11_OID_IQCALIBRATIONTABLE, 0x17000015), + OID_U32(DOT11_OID_NONERPPROTECTION, 0x17000016), + OID_U32(DOT11_OID_SLOTSETTINGS, 0x17000017), + OID_U32(DOT11_OID_NONERPTIMEOUT, 0x17000018), + OID_U32(DOT11_OID_PROFILES, 0x17000019), + OID_STRUCT(DOT11_OID_EXTENDEDRATES, 0x17000020, + u8[IWMAX_BITRATES + 1], OID_TYPE_RAW), + + OID_STRUCT_MLME(DOT11_OID_DEAUTHENTICATE, 0x18000000), + OID_STRUCT_MLME(DOT11_OID_AUTHENTICATE, 0x18000001), + OID_STRUCT_MLME(DOT11_OID_DISASSOCIATE, 0x18000002), + OID_STRUCT_MLME(DOT11_OID_ASSOCIATE, 0x18000003), + OID_UNKNOWN(DOT11_OID_SCAN, 0x18000004), + OID_STRUCT_MLMEEX(DOT11_OID_BEACON, 0x18000005), + OID_STRUCT_MLMEEX(DOT11_OID_PROBE, 0x18000006), + OID_STRUCT_MLMEEX(DOT11_OID_DEAUTHENTICATEEX, 0x18000007), + OID_STRUCT_MLMEEX(DOT11_OID_AUTHENTICATEEX, 0x18000008), + OID_STRUCT_MLMEEX(DOT11_OID_DISASSOCIATEEX, 0x18000009), + OID_STRUCT_MLMEEX(DOT11_OID_ASSOCIATEEX, 0x1800000A), + OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATE, 0x1800000B), + OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATEEX, 0x1800000C), + + OID_U32(DOT11_OID_NONERPSTATUS, 0x1E000000), + + OID_U32(DOT11_OID_STATIMEOUT, 0x19000000), + OID_U32_C(DOT11_OID_MLMEAUTOLEVEL, 0x19000001), + OID_U32(DOT11_OID_BSSTIMEOUT, 0x19000002), + OID_UNKNOWN(DOT11_OID_ATTACHMENT, 0x19000003), + OID_STRUCT_C(DOT11_OID_PSMBUFFER, 0x19000004, struct obj_buffer, + OID_TYPE_BUFFER), + + OID_U32(DOT11_OID_BSSS, 0x1C000000), + [DOT11_OID_BSSX] = {0x1C000001, 63, sizeof (struct obj_bss), + OID_TYPE_BSS}, /*DOT11_OID_BSS1,...,DOT11_OID_BSS64 */ + OID_STRUCT(DOT11_OID_BSSFIND, 0x1C000042, struct obj_bss, OID_TYPE_BSS), + [DOT11_OID_BSSLIST] = {0x1C000043, 0, sizeof (struct + obj_bsslist) + + sizeof (struct obj_bss[IWMAX_BSS]), + OID_TYPE_BSSLIST}, + + OID_UNKNOWN(OID_INL_TUNNEL, 0xFF020000), + OID_UNKNOWN(OID_INL_MEMADDR, 0xFF020001), + OID_UNKNOWN(OID_INL_MEMORY, 0xFF020002), + OID_U32_C(OID_INL_MODE, 0xFF020003), + OID_UNKNOWN(OID_INL_COMPONENT_NR, 0xFF020004), + OID_STRUCT(OID_INL_VERSION, 0xFF020005, u8[8], OID_TYPE_RAW), + OID_UNKNOWN(OID_INL_INTERFACE_ID, 0xFF020006), + OID_UNKNOWN(OID_INL_COMPONENT_ID, 0xFF020007), + OID_U32_C(OID_INL_CONFIG, 0xFF020008), + OID_U32_C(OID_INL_DOT11D_CONFORMANCE, 0xFF02000C), + OID_U32(OID_INL_PHYCAPABILITIES, 0xFF02000D), + OID_U32_C(OID_INL_OUTPUTPOWER, 0xFF02000F), + +}; + +int +mgt_init(islpci_private *priv) +{ + int i; + + priv->mib = kmalloc(OID_NUM_LAST * sizeof (void *), GFP_KERNEL); + if (!priv->mib) + return -ENOMEM; + + memset(priv->mib, 0, OID_NUM_LAST * sizeof (void *)); + + /* Alloc the cache */ + for (i = 0; i < OID_NUM_LAST; i++) { + if (isl_oid[i].flags & OID_FLAG_CACHED) { + priv->mib[i] = kmalloc(isl_oid[i].size * + (isl_oid[i].range + 1), + GFP_KERNEL); + if (!priv->mib[i]) + return -ENOMEM; + memset(priv->mib[i], 0, + isl_oid[i].size * (isl_oid[i].range + 1)); + } else + priv->mib[i] = NULL; + } + + init_rwsem(&priv->mib_sem); + prism54_mib_init(priv); + + return 0; +} + +void +mgt_clean(islpci_private *priv) +{ + int i; + + if (!priv->mib) + return; + for (i = 0; i < OID_NUM_LAST; i++) + if (priv->mib[i]) { + kfree(priv->mib[i]); + priv->mib[i] = NULL; + } + kfree(priv->mib); + priv->mib = NULL; +} + +void +mgt_le_to_cpu(int type, void *data) +{ + switch (type) { + case OID_TYPE_U32: + *(u32 *) data = le32_to_cpu(*(u32 *) data); + break; + case OID_TYPE_BUFFER:{ + struct obj_buffer *buff = data; + buff->size = le32_to_cpu(buff->size); + buff->addr = le32_to_cpu(buff->addr); + break; + } + case OID_TYPE_BSS:{ + struct obj_bss *bss = data; + bss->age = le16_to_cpu(bss->age); + bss->channel = le16_to_cpu(bss->channel); + bss->capinfo = le16_to_cpu(bss->capinfo); + bss->rates = le16_to_cpu(bss->rates); + bss->basic_rates = le16_to_cpu(bss->basic_rates); + break; + } + case OID_TYPE_BSSLIST:{ + struct obj_bsslist *list = data; + int i; + list->nr = le32_to_cpu(list->nr); + for (i = 0; i < list->nr; i++) + mgt_le_to_cpu(OID_TYPE_BSS, &list->bsslist[i]); + break; + } + case OID_TYPE_FREQUENCIES:{ + struct obj_frequencies *freq = data; + int i; + freq->nr = le16_to_cpu(freq->nr); + for (i = 0; i < freq->nr; i++) + freq->mhz[i] = le16_to_cpu(freq->mhz[i]); + break; + } + case OID_TYPE_MLME:{ + struct obj_mlme *mlme = data; + mlme->id = le16_to_cpu(mlme->id); + mlme->state = le16_to_cpu(mlme->state); + mlme->code = le16_to_cpu(mlme->code); + break; + } + case OID_TYPE_MLMEEX:{ + struct obj_mlmeex *mlme = data; + mlme->id = le16_to_cpu(mlme->id); + mlme->state = le16_to_cpu(mlme->state); + mlme->code = le16_to_cpu(mlme->code); + mlme->size = le16_to_cpu(mlme->size); + break; + } + case OID_TYPE_SSID: + case OID_TYPE_KEY: + case OID_TYPE_ADDR: + case OID_TYPE_RAW: + break; + default: + BUG(); + } +} + +static void +mgt_cpu_to_le(int type, void *data) +{ + switch (type) { + case OID_TYPE_U32: + *(u32 *) data = cpu_to_le32(*(u32 *) data); + break; + case OID_TYPE_BUFFER:{ + struct obj_buffer *buff = data; + buff->size = cpu_to_le32(buff->size); + buff->addr = cpu_to_le32(buff->addr); + break; + } + case OID_TYPE_BSS:{ + struct obj_bss *bss = data; + bss->age = cpu_to_le16(bss->age); + bss->channel = cpu_to_le16(bss->channel); + bss->capinfo = cpu_to_le16(bss->capinfo); + bss->rates = cpu_to_le16(bss->rates); + bss->basic_rates = cpu_to_le16(bss->basic_rates); + break; + } + case OID_TYPE_BSSLIST:{ + struct obj_bsslist *list = data; + int i; + list->nr = cpu_to_le32(list->nr); + for (i = 0; i < list->nr; i++) + mgt_cpu_to_le(OID_TYPE_BSS, &list->bsslist[i]); + break; + } + case OID_TYPE_FREQUENCIES:{ + struct obj_frequencies *freq = data; + int i; + freq->nr = cpu_to_le16(freq->nr); + for (i = 0; i < freq->nr; i++) + freq->mhz[i] = cpu_to_le16(freq->mhz[i]); + break; + } + case OID_TYPE_MLME:{ + struct obj_mlme *mlme = data; + mlme->id = cpu_to_le16(mlme->id); + mlme->state = cpu_to_le16(mlme->state); + mlme->code = cpu_to_le16(mlme->code); + break; + } + case OID_TYPE_MLMEEX:{ + struct obj_mlmeex *mlme = data; + mlme->id = cpu_to_le16(mlme->id); + mlme->state = cpu_to_le16(mlme->state); + mlme->code = cpu_to_le16(mlme->code); + mlme->size = cpu_to_le16(mlme->size); + break; + } + case OID_TYPE_SSID: + case OID_TYPE_KEY: + case OID_TYPE_ADDR: + case OID_TYPE_RAW: + break; + default: + BUG(); + } +} + +/* Note : data is modified during this function */ + +int +mgt_set_request(islpci_private *priv, enum oid_num_t n, int extra, void *data) +{ + int ret = 0; + struct islpci_mgmtframe *response = NULL; + int response_op = PIMFOR_OP_ERROR; + int dlen; + void *cache, *_data = data; + u32 oid; + + BUG_ON(OID_NUM_LAST <= n); + BUG_ON(extra > isl_oid[n].range); + + if (!priv->mib) + /* memory has been freed */ + return -1; + + dlen = isl_oid[n].size; + cache = priv->mib[n]; + cache += (cache ? extra * dlen : 0); + oid = isl_oid[n].oid + extra; + + if (_data == NULL) + /* we are requested to re-set a cached value */ + _data = cache; + else + mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, _data); + /* If we are going to write to the cache, we don't want anyone to read + * it -> acquire write lock. + * Else we could acquire a read lock to be sure we don't bother the + * commit process (which takes a write lock). But I'm not sure if it's + * needed. + */ + if (cache) + down_write(&priv->mib_sem); + + if (islpci_get_state(priv) >= PRV_STATE_READY) { + ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid, + _data, dlen, &response); + if (!ret) { + response_op = response->header->operation; + islpci_mgt_release(response); + } + if (ret || response_op == PIMFOR_OP_ERROR) + ret = -EIO; + } else if (!cache) + ret = -EIO; + + if (cache) { + if (!ret && data) + memcpy(cache, _data, dlen); + up_write(&priv->mib_sem); + } + + /* re-set given data to what it was */ + if (data) + mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, data); + + return ret; +} + +int +mgt_get_request(islpci_private *priv, enum oid_num_t n, int extra, void *data, + union oid_res_t *res) +{ + + int ret = -EIO; + int reslen = 0; + struct islpci_mgmtframe *response = NULL; + + int dlen; + void *cache, *_res = NULL; + u32 oid; + + BUG_ON(OID_NUM_LAST <= n); + BUG_ON(extra > isl_oid[n].range); + + res->ptr = NULL; + + if (!priv->mib) + /* memory has been freed */ + return -1; + + dlen = isl_oid[n].size; + cache = priv->mib[n]; + cache += cache ? extra * dlen : 0; + oid = isl_oid[n].oid + extra; + reslen = dlen; + + if (cache) + down_read(&priv->mib_sem); + + if (islpci_get_state(priv) >= PRV_STATE_READY) { + ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, + oid, data, dlen, &response); + if (ret || !response || + response->header->operation == PIMFOR_OP_ERROR) { + if (response) + islpci_mgt_release(response); + ret = -EIO; + } + if (!ret) { + _res = response->data; + reslen = response->header->length; + } + } else if (cache) { + _res = cache; + ret = 0; + } + if ((isl_oid[n].flags & OID_FLAG_TYPE) == OID_TYPE_U32) + res->u = ret ? 0 : le32_to_cpu(*(u32 *) _res); + else { + res->ptr = kmalloc(reslen, GFP_KERNEL); + BUG_ON(res->ptr == NULL); + if (ret) + memset(res->ptr, 0, reslen); + else { + memcpy(res->ptr, _res, reslen); + mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, + res->ptr); + } + } + if (cache) + up_read(&priv->mib_sem); + + if (response && !ret) + islpci_mgt_release(response); + + if (reslen > isl_oid[n].size) + printk(KERN_DEBUG + "mgt_get_request(0x%x): received data length was bigger " + "than expected (%d > %d). Memory is probably corrupted...", + oid, reslen, isl_oid[n].size); + + return ret; +} + +/* lock outside */ +int +mgt_commit_list(islpci_private *priv, enum oid_num_t *l, int n) +{ + int i, ret = 0; + struct islpci_mgmtframe *response; + + for (i = 0; i < n; i++) { + struct oid_t *t = &(isl_oid[l[i]]); + void *data = priv->mib[l[i]]; + int j = 0; + u32 oid = t->oid; + BUG_ON(data == NULL); + while (j <= t->range) { + response = NULL; + ret |= islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, + oid, data, t->size, + &response); + if (response) { + ret |= (response->header->operation == + PIMFOR_OP_ERROR); + islpci_mgt_release(response); + } + j++; + oid++; + data += t->size; + } + } + return ret; +} + +/* Lock outside */ + +void +mgt_set(islpci_private *priv, enum oid_num_t n, void *data) +{ + BUG_ON(OID_NUM_LAST <= n); + BUG_ON(priv->mib[n] == NULL); + + memcpy(priv->mib[n], data, isl_oid[n].size); + mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, priv->mib[n]); +} + +void +mgt_get(islpci_private *priv, enum oid_num_t n, void *res) +{ + BUG_ON(OID_NUM_LAST <= n); + BUG_ON(priv->mib[n] == NULL); + BUG_ON(res == NULL); + + memcpy(res, priv->mib[n], isl_oid[n].size); + mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, res); +} + +/* Commits the cache. Lock outside. */ + +static enum oid_num_t commit_part1[] = { + OID_INL_CONFIG, + OID_INL_MODE, + DOT11_OID_BSSTYPE, + DOT11_OID_CHANNEL, + DOT11_OID_MLMEAUTOLEVEL +}; + +static enum oid_num_t commit_part2[] = { + DOT11_OID_SSID, + DOT11_OID_PSMBUFFER, + DOT11_OID_AUTHENABLE, + DOT11_OID_PRIVACYINVOKED, + DOT11_OID_EXUNENCRYPTED, + DOT11_OID_DEFKEYX, /* MULTIPLE */ + DOT11_OID_DEFKEYID, + DOT11_OID_DOT1XENABLE, + OID_INL_DOT11D_CONFORMANCE, + /* Do not initialize this - fw < 1.0.4.3 rejects it + OID_INL_OUTPUTPOWER, + */ +}; + +/* update the MAC addr. */ +static int +mgt_update_addr(islpci_private *priv) +{ + struct islpci_mgmtframe *res = NULL; + int ret; + + ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, + isl_oid[GEN_OID_MACADDRESS].oid, NULL, + isl_oid[GEN_OID_MACADDRESS].size, &res); + + if ((ret == 0) && res && (res->header->operation != PIMFOR_OP_ERROR)) + memcpy(priv->ndev->dev_addr, res->data, 6); + else + ret = -EIO; + if (res) + islpci_mgt_release(res); + + return ret; +} + +void +mgt_commit(islpci_private *priv) +{ + int rvalue; + u32 u; + + if (islpci_get_state(priv) < PRV_STATE_INIT) + return; + + rvalue = mgt_commit_list(priv, commit_part1, + sizeof (commit_part1) / + sizeof (commit_part1[0])); + + if (priv->iw_mode != IW_MODE_MONITOR) + rvalue |= mgt_commit_list(priv, commit_part2, + sizeof (commit_part2) / + sizeof (commit_part2[0])); + + u = OID_INL_MODE; + rvalue |= mgt_commit_list(priv, &u, 1); + rvalue |= mgt_update_addr(priv); + + if (rvalue) { + /* some request have failed. The device might be in an + incoherent state. We should reset it ! */ + printk(KERN_DEBUG "%s: mgt_commit has failed. Restart the " + "device \n", priv->ndev->name); + } +} + +/* This will tell you if you are allowed to answer a mlme(ex) request .*/ + +int +mgt_mlme_answer(islpci_private *priv) +{ + u32 mlmeautolevel; + /* Acquire a read lock because if we are in a mode change, it's + * possible to answer true, while the card is leaving master to managed + * mode. Answering to a mlme in this situation could hang the card. + */ + down_read(&priv->mib_sem); + mlmeautolevel = + le32_to_cpu(*(u32 *) priv->mib[DOT11_OID_MLMEAUTOLEVEL]); + up_read(&priv->mib_sem); + + return ((priv->iw_mode == IW_MODE_MASTER) && + (mlmeautolevel >= DOT11_MLME_INTERMEDIATE)); +} + +enum oid_num_t +mgt_oidtonum(u32 oid) +{ + int i; + + for (i = 0; i < OID_NUM_LAST; i++) + if (isl_oid[i].oid == oid) + return i; + + printk(KERN_DEBUG "looking for an unknown oid 0x%x", oid); + + return OID_NUM_LAST; +} + +int +mgt_response_to_str(enum oid_num_t n, union oid_res_t *r, char *str) +{ + switch (isl_oid[n].flags & OID_FLAG_TYPE) { + case OID_TYPE_U32: + return snprintf(str, PRIV_STR_SIZE, "%u\n", r->u); + break; + case OID_TYPE_BUFFER:{ + struct obj_buffer *buff = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "size=%u\naddr=0x%X\n", buff->size, + buff->addr); + } + break; + case OID_TYPE_BSS:{ + struct obj_bss *bss = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "age=%u\nchannel=%u\n" + "capinfo=0x%X\nrates=0x%X\n" + "basic_rates=0x%X\n", bss->age, + bss->channel, bss->capinfo, + bss->rates, bss->basic_rates); + } + break; + case OID_TYPE_BSSLIST:{ + struct obj_bsslist *list = r->ptr; + int i, k; + k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr); + for (i = 0; i < list->nr; i++) + k += snprintf(str + k, PRIV_STR_SIZE - k, + "bss[%u] : \nage=%u\nchannel=%u\n" + "capinfo=0x%X\nrates=0x%X\n" + "basic_rates=0x%X\n", + i, list->bsslist[i].age, + list->bsslist[i].channel, + list->bsslist[i].capinfo, + list->bsslist[i].rates, + list->bsslist[i].basic_rates); + return k; + } + break; + case OID_TYPE_FREQUENCIES:{ + struct obj_frequencies *freq = r->ptr; + int i, t; + printk("nr : %u\n", freq->nr); + t = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", freq->nr); + for (i = 0; i < freq->nr; i++) + t += snprintf(str + t, PRIV_STR_SIZE - t, + "mhz[%u]=%u\n", i, freq->mhz[i]); + return t; + } + break; + case OID_TYPE_MLME:{ + struct obj_mlme *mlme = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "id=0x%X\nstate=0x%X\ncode=0x%X\n", + mlme->id, mlme->state, mlme->code); + } + break; + case OID_TYPE_MLMEEX:{ + struct obj_mlmeex *mlme = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "id=0x%X\nstate=0x%X\n" + "code=0x%X\nsize=0x%X\n", mlme->id, + mlme->state, mlme->code, mlme->size); + } + break; + case OID_TYPE_SSID:{ + struct obj_ssid *ssid = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "length=%u\noctets=%.*s\n", + ssid->length, ssid->length, + ssid->octets); + } + break; + case OID_TYPE_KEY:{ + struct obj_key *key = r->ptr; + int t, i; + t = snprintf(str, PRIV_STR_SIZE, + "type=0x%X\nlength=0x%X\nkey=0x", + key->type, key->length); + for (i = 0; i < key->length; i++) + t += snprintf(str + t, PRIV_STR_SIZE - t, + "%02X:", key->key[i]); + t += snprintf(str + t, PRIV_STR_SIZE - t, "\n"); + return t; + } + break; + case OID_TYPE_RAW: + case OID_TYPE_ADDR:{ + unsigned char *buff = r->ptr; + int t, i; + t = snprintf(str, PRIV_STR_SIZE, "hex data="); + for (i = 0; i < isl_oid[n].size; i++) + t += snprintf(str + t, PRIV_STR_SIZE - t, + "%02X:", buff[i]); + t += snprintf(str + t, PRIV_STR_SIZE - t, "\n"); + return t; + } + break; + default: + BUG(); + } + return 0; +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/oid_mgt.h linux-2.4.28-pre3/drivers/net/wireless/prism54/oid_mgt.h --- linux-2.4.27/drivers/net/wireless/prism54/oid_mgt.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/oid_mgt.h 2004-09-10 19:34:00.000000000 +0000 @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2003 Aurelien Alleaume + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#if !defined(_OID_MGT_H) +#define _OID_MGT_H + +#include "isl_oid.h" +#include "islpci_dev.h" + +extern struct oid_t isl_oid[]; + +int mgt_init(islpci_private *); + +void mgt_clean(islpci_private *); + +/* I don't know where to put these 3 */ +extern const int frequency_list_bg[]; +extern const int frequency_list_a[]; +int channel_of_freq(int); + +void mgt_le_to_cpu(int, void *); + +int mgt_set_request(islpci_private *, enum oid_num_t, int, void *); + +int mgt_get_request(islpci_private *, enum oid_num_t, int, void *, + union oid_res_t *); + +int mgt_commit_list(islpci_private *, enum oid_num_t *, int); + +void mgt_set(islpci_private *, enum oid_num_t, void *); + +void mgt_get(islpci_private *, enum oid_num_t, void *); + +void mgt_commit(islpci_private *); + +int mgt_mlme_answer(islpci_private *); + +enum oid_num_t mgt_oidtonum(u32 oid); + +int mgt_response_to_str(enum oid_num_t, union oid_res_t *, char *); + +#endif /* !defined(_OID_MGT_H) */ +/* EOF */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/prismcompat.h linux-2.4.28-pre3/drivers/net/wireless/prism54/prismcompat.h --- linux-2.4.27/drivers/net/wireless/prism54/prismcompat.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/prismcompat.h 2004-09-10 19:32:17.000000000 +0000 @@ -0,0 +1,46 @@ +/* + * (C) 2004 Margit Schubert-While + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * Compatibility header file to aid support of different kernel versions + */ + +#ifdef PRISM54_COMPAT24 +#include "prismcompat24.h" +#else /* PRISM54_COMPAT24 */ + +#ifndef _PRISM_COMPAT_H +#define _PRISM_COMPAT_H + +#include +#include +#include +#include +#include +#include + +#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE) +#error Firmware Loading is not configured in the kernel ! +#endif + +#define prism54_synchronize_irq(irq) synchronize_irq(irq) + +#define PRISM_FW_PDEV &priv->pdev->dev + +#endif /* _PRISM_COMPAT_H */ +#endif /* PRISM54_COMPAT24 */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/prismcompat24.h linux-2.4.28-pre3/drivers/net/wireless/prism54/prismcompat24.h --- linux-2.4.27/drivers/net/wireless/prism54/prismcompat24.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/net/wireless/prism54/prismcompat24.h 2004-09-10 19:33:15.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * (C) 2004 Margit Schubert-While + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * Compatibility header file to aid support of different kernel versions + */ + +#ifndef _PRISM_COMPAT_H +#define _PRISM_COMPAT_H + +#include +#include +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) +#define module_param(x, y, z) MODULE_PARM(x, "i") +#else +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) +#define free_netdev(x) kfree(x) +#define pci_name(x) x->slot_name +#define irqreturn_t void +#define IRQ_HANDLED +#define IRQ_NONE +#else +#include +#endif + +#define work_struct tq_struct +#define INIT_WORK INIT_TQUEUE +#define schedule_work schedule_task + +#if !defined(HAVE_NETDEV_PRIV) +#define netdev_priv(x) (x)->priv +#endif + +#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE) +#error Firmware Loading is not configured in the kernel ! +#endif + +#define prism54_synchronize_irq(irq) synchronize_irq() + +#define DEFINE_WAIT(y) DECLARE_WAITQUEUE(y, current) +#define prepare_to_wait(x, y, z) set_current_state(z); \ + add_wait_queue(x, y) +#define finish_wait(x, y) remove_wait_queue(x, y); \ + set_current_state(TASK_RUNNING) + +#define PRISM_FW_PDEV pci_name(priv->pdev) + +#endif /* _PRISM_COMPAT_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/parport/parport_pc.c linux-2.4.28-pre3/drivers/parport/parport_pc.c --- linux-2.4.27/drivers/parport/parport_pc.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/parport/parport_pc.c 2004-09-10 19:34:29.000000000 +0000 @@ -266,95 +266,6 @@ static void parport_pc_interrupt(int irq parport_generic_irq(irq, (struct parport *) dev_id, regs); } -void parport_pc_write_data(struct parport *p, unsigned char d) -{ - outb (d, DATA (p)); -} - -unsigned char parport_pc_read_data(struct parport *p) -{ - return inb (DATA (p)); -} - -void parport_pc_write_control(struct parport *p, unsigned char d) -{ - const unsigned char wm = (PARPORT_CONTROL_STROBE | - PARPORT_CONTROL_AUTOFD | - PARPORT_CONTROL_INIT | - PARPORT_CONTROL_SELECT); - - /* Take this out when drivers have adapted to the newer interface. */ - if (d & 0x20) { - printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n", - p->name, p->cad->name); - parport_pc_data_reverse (p); - } - - __parport_pc_frob_control (p, wm, d & wm); -} - -unsigned char parport_pc_read_control(struct parport *p) -{ - const unsigned char wm = (PARPORT_CONTROL_STROBE | - PARPORT_CONTROL_AUTOFD | - PARPORT_CONTROL_INIT | - PARPORT_CONTROL_SELECT); - const struct parport_pc_private *priv = p->physport->private_data; - return priv->ctr & wm; /* Use soft copy */ -} - -unsigned char parport_pc_frob_control (struct parport *p, unsigned char mask, - unsigned char val) -{ - const unsigned char wm = (PARPORT_CONTROL_STROBE | - PARPORT_CONTROL_AUTOFD | - PARPORT_CONTROL_INIT | - PARPORT_CONTROL_SELECT); - - /* Take this out when drivers have adapted to the newer interface. */ - if (mask & 0x20) { - printk (KERN_DEBUG "%s (%s): use data_%s for this!\n", - p->name, p->cad->name, - (val & 0x20) ? "reverse" : "forward"); - if (val & 0x20) - parport_pc_data_reverse (p); - else - parport_pc_data_forward (p); - } - - /* Restrict mask and val to control lines. */ - mask &= wm; - val &= wm; - - return __parport_pc_frob_control (p, mask, val); -} - -unsigned char parport_pc_read_status(struct parport *p) -{ - return inb (STATUS (p)); -} - -void parport_pc_disable_irq(struct parport *p) -{ - __parport_pc_frob_control (p, 0x10, 0); -} - -void parport_pc_enable_irq(struct parport *p) -{ - if (p->irq != PARPORT_IRQ_NONE) - __parport_pc_frob_control (p, 0x10, 0x10); -} - -void parport_pc_data_forward (struct parport *p) -{ - __parport_pc_frob_control (p, 0x20, 0); -} - -void parport_pc_data_reverse (struct parport *p) -{ - __parport_pc_frob_control (p, 0x20, 0x20); -} - void parport_pc_init_state(struct pardevice *dev, struct parport_state *s) { s->u.pc.ctr = 0xc; @@ -414,7 +325,8 @@ static size_t parport_pc_epp_read_data ( left -= 16; } else { /* grab single byte from the warp fifo */ - *((char *)buf)++ = inb (EPPDATA (port)); + *((char *)buf) = inb (EPPDATA (port)); + buf++; got++; left--; } @@ -441,7 +353,8 @@ static size_t parport_pc_epp_read_data ( return length; } for (; got < length; got++) { - *((char*)buf)++ = inb (EPPDATA(port)); + *((char*)buf) = inb (EPPDATA(port)); + buf++; if (inb (STATUS (port)) & 0x01) { /* EPP timeout */ clear_epp_timeout (port); @@ -470,7 +383,8 @@ static size_t parport_pc_epp_write_data return length; } for (; written < length; written++) { - outb (*((char*)buf)++, EPPDATA(port)); + outb (*((char*)buf), EPPDATA(port)); + buf++; if (inb (STATUS(port)) & 0x01) { clear_epp_timeout (port); break; @@ -494,7 +408,8 @@ static size_t parport_pc_epp_read_addr ( return length; } for (; got < length; got++) { - *((char*)buf)++ = inb (EPPADDR (port)); + *((char*)buf) = inb (EPPADDR (port)); + buf++; if (inb (STATUS (port)) & 0x01) { clear_epp_timeout (port); break; @@ -519,7 +434,8 @@ static size_t parport_pc_epp_write_addr return length; } for (; written < length; written++) { - outb (*((char*)buf)++, EPPADDR (port)); + outb (*((char*)buf), EPPADDR (port)); + buf++; if (inb (STATUS (port)) & 0x01) { clear_epp_timeout (port); break; @@ -2692,6 +2608,7 @@ enum parport_pc_pci_cards { syba_2p_epp, syba_1p_ecp, titan_010l, + titan_1284p1, titan_1284p2, avlab_1p, avlab_2p, @@ -2763,6 +2680,7 @@ static struct parport_pc_pci { /* syba_2p_epp AP138B */ { 2, { { 0, 0x078 }, { 0, 0x178 }, } }, /* syba_1p_ecp W83787 */ { 1, { { 0, 0x078 }, } }, /* titan_010l */ { 1, { { 3, -1 }, } }, + /* titan_1284p1 */ { 1, { { 0, 1 }, } }, /* titan_1284p2 */ { 2, { { 0, 1 }, { 2, 3 }, } }, /* avlab_1p */ { 1, { { 0, 1}, } }, /* avlab_2p */ { 2, { { 0, 1}, { 2, 3 },} }, @@ -2834,6 +2752,7 @@ static struct pci_device_id parport_pc_p PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_1p_ecp }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_010L, PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_010l }, + { 0x9710, 0x9805, 0x1000, 0x0010, 0, 0, titan_1284p1 }, { 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 }, /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ { 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, /* AFAVLAB_TK9902 */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pci/pci.c linux-2.4.28-pre3/drivers/pci/pci.c --- linux-2.4.27/drivers/pci/pci.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/pci/pci.c 2004-09-10 19:33:31.000000000 +0000 @@ -1238,6 +1238,8 @@ struct pci_bus * __devinit pci_add_new_b * Allocate a new bus, and inherit stuff from the parent.. */ child = pci_alloc_bus(); + if (!child) + return NULL; list_add_tail(&child->node, &parent->children); child->self = dev; @@ -1291,7 +1293,11 @@ static int __devinit pci_scan_bridge(str */ if (pass) return max; + child = pci_add_new_bus(bus, dev, 0); + if (!child) + return max; + child->primary = buses & 0xFF; child->secondary = (buses >> 8) & 0xFF; child->subordinate = (buses >> 16) & 0xFF; @@ -1316,6 +1322,9 @@ static int __devinit pci_scan_bridge(str pci_write_config_word(dev, PCI_STATUS, 0xffff); child = pci_add_new_bus(bus, dev, ++max); + if (!child) + return max; + buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) | ((unsigned int)(child->secondary) << 8) @@ -2214,7 +2223,6 @@ EXPORT_SYMBOL(pcibios_find_device); EXPORT_SYMBOL(isa_dma_bridge_buggy); EXPORT_SYMBOL(pci_pci_problems); -EXPORT_SYMBOL(pciehp_msi_quirk); /* Pool allocator */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pci/quirks.c linux-2.4.28-pre3/drivers/pci/quirks.c --- linux-2.4.27/drivers/pci/quirks.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/pci/quirks.c 2004-09-10 19:32:07.000000000 +0000 @@ -719,13 +719,6 @@ static void __init asus_hides_smbus_lpc( } } -int pciehp_msi_quirk; - -static void __devinit quirk_pciehp_msi(struct pci_dev *pdev) -{ - pciehp_msi_quirk = 1; -} - /* * The main table of quirks. */ @@ -815,8 +808,6 @@ static struct pci_fixup pci_fixups[] __i { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SMCH, quirk_pciehp_msi }, - { 0 } }; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pcmcia/bulkmem.c linux-2.4.28-pre3/drivers/pcmcia/bulkmem.c --- linux-2.4.27/drivers/pcmcia/bulkmem.c 2002-11-28 23:53:14.000000000 +0000 +++ linux-2.4.28-pre3/drivers/pcmcia/bulkmem.c 2004-09-10 19:37:29.000000000 +0000 @@ -301,7 +301,7 @@ int MTDHelperEntry(int func, void *a1, v { window_handle_t w; int ret = pcmcia_request_window(a1, a2, &w); - (window_handle_t *)a1 = w; + a1 = w; return ret; } break; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pcmcia/i82365.c linux-2.4.28-pre3/drivers/pcmcia/i82365.c --- linux-2.4.27/drivers/pcmcia/i82365.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/pcmcia/i82365.c 2004-09-10 19:36:43.000000000 +0000 @@ -63,7 +63,6 @@ #include "cirrus.h" #include "vg468.h" #include "ricoh.h" -#include "o2micro.h" #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pcmcia/o2micro.h linux-2.4.28-pre3/drivers/pcmcia/o2micro.h --- linux-2.4.27/drivers/pcmcia/o2micro.h 2002-11-28 23:53:14.000000000 +0000 +++ linux-2.4.28-pre3/drivers/pcmcia/o2micro.h 2004-09-10 19:36:30.000000000 +0000 @@ -120,4 +120,36 @@ #define O2_MODE_E_LED_OUT 0x08 #define O2_MODE_E_SKTA_ACTV 0x10 +static int o2micro_open(pci_socket_t *socket) +{ + /* + * 'reserved' register at 0x94/D4. chaning it to 0xCA (8 bit) enables + * read prefetching which for example makes the RME Hammerfall DSP + * working. for some bridges it is at 0x94, for others at 0xD4. it's + * ok to write to both registers on all O2 bridges. + * from Eric Still, 02Micro. + */ + if (PCI_FUNC(socket->dev->devfn) == 0) { + config_writeb(socket, 0x94, 0xCA); + config_writeb(socket, 0xD4, 0xCA); + } + + return 0; +} + +static struct pci_socket_ops o2micro_ops = { + o2micro_open, + yenta_close, + yenta_init, + yenta_suspend, + yenta_get_status, + yenta_get_socket, + yenta_set_socket, + yenta_get_io_map, + yenta_set_io_map, + yenta_get_mem_map, + yenta_set_mem_map, + yenta_proc_setup +}; + #endif /* _LINUX_O2MICRO_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pcmcia/ti113x.h linux-2.4.28-pre3/drivers/pcmcia/ti113x.h --- linux-2.4.27/drivers/pcmcia/ti113x.h 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/pcmcia/ti113x.h 2004-09-10 19:34:01.000000000 +0000 @@ -134,6 +134,10 @@ /* ExCA IO offset registers */ #define TI113X_IO_OFFSET(map) (0x36+((map)<<1)) +/* EnE test register */ +#define ENE_TEST_C9 0xc9 /* 8bit */ +#define ENE_TEST_C9_TLTENABLE 0x02 + #ifdef CONFIG_CARDBUS /* @@ -155,6 +159,17 @@ static int ti_open(pci_socket_t *socket) new = reg & ~I365_INTR_ENA; if (new != reg) exca_writeb(socket, I365_INTCTL, new); + + /* + * for EnE bridges only: clear testbit TLTEnable. this makes the + * RME Hammerfall DSP sound card working. + */ + if (socket->dev->vendor == PCI_VENDOR_ID_ENE) { + u8 test_c9 = config_readb(socket, ENE_TEST_C9); + test_c9 &= ~ENE_TEST_C9_TLTENABLE; + config_writeb(socket, ENE_TEST_C9, test_c9); + } + return 0; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pcmcia/yenta.c linux-2.4.28-pre3/drivers/pcmcia/yenta.c --- linux-2.4.27/drivers/pcmcia/yenta.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/pcmcia/yenta.c 2004-09-10 19:35:29.000000000 +0000 @@ -845,6 +845,7 @@ static void yenta_close(pci_socket_t *so #include "ti113x.h" #include "ricoh.h" +#include "o2micro.h" /* * Different cardbus controllers have slightly different @@ -880,6 +881,8 @@ static struct cardbus_override_struct { { PD(ENE,1410), &ti_ops }, { PD(ENE,1420), &ti_ops }, + { PCI_VENDOR_ID_O2, PCI_ANY_ID, &o2micro_ops }, + { PD(RICOH,RL5C465), &ricoh_ops }, { PD(RICOH,RL5C466), &ricoh_ops }, { PD(RICOH,RL5C475), &ricoh_ops }, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/Config.in linux-2.4.28-pre3/drivers/s390/Config.in --- linux-2.4.27/drivers/s390/Config.in 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/Config.in 2004-09-10 19:33:49.000000000 +0000 @@ -88,6 +88,23 @@ if [ "$CONFIG_NET" = "y" ]; then define_bool CONFIG_HOTPLUG y fi + if [ "$CONFIG_QDIO" != "n" -a "$CONFIG_CHANDEV" = "y" -a "$CONFIG_IP_MULTICAST" = "y" ]; then + dep_tristate 'Support for Gigabit Ethernet' CONFIG_QETH $CONFIG_QDIO + if [ "$CONFIG_QETH" != "n" ]; then + comment 'Gigabit Ethernet default settings' + if [ "$CONFIG_IPV6" = "y" -o "$CONFIG_IPV6" = "$CONFIG_QETH" ]; then + bool ' IPv6 support for qeth' CONFIG_QETH_IPV6 + else + define_bool CONFIG_QETH_IPV6 n + fi + if [ "$CONFIG_VLAN_8021Q" = "y" -o "$CONFIG_VLAN_8021Q" = "$CONFIG_QETH" ]; then + bool ' VLAN support for qeth' CONFIG_QETH_VLAN + else + define_bool CONFIG_QETH_VLAN n + fi + bool ' Performance statistics in /proc' CONFIG_QETH_PERF_STATS + fi + fi tristate 'CTC device support' CONFIG_CTC tristate 'IUCV device support (VM only)' CONFIG_IUCV fi diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/Makefile linux-2.4.28-pre3/drivers/s390/Makefile --- linux-2.4.27/drivers/s390/Makefile 2003-06-13 14:51:35.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/Makefile 2004-09-10 19:34:52.000000000 +0000 @@ -9,6 +9,8 @@ subdir-m := $(subdir-y) obj-y := s390io.o s390mach.o s390dyn.o ccwcache.o sysinfo.o export-objs += ccwcache.o s390dyn.o s390io.o +obj-$(CONFIG_QDIO) += qdio.o +export-objs += qdio.o obj-y += $(foreach dir,$(subdir-y),$(dir)/s390-$(dir).o) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/block/dasd.c linux-2.4.28-pre3/drivers/s390/block/dasd.c --- linux-2.4.27/drivers/s390/block/dasd.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/block/dasd.c 2004-09-10 19:34:38.000000000 +0000 @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.311 $ + * $Revision: 1.298.2.11 $ * * History of changes (starts July 2000) * 11/09/00 complete redesign after code review @@ -311,7 +311,7 @@ dasd_add_range (int from, int to, int fe /* and add the remaining subranges */ for (start = index = from, end = -EINVAL; index <= to; index++) { - if (dasd_devindex_from_devno(index) > 0) { + if (dasd_devindex_from_devno(index) >= 0) { /* current device is already in range */ MESSAGE (KERN_DEBUG, "dasd_add_range %04x-%04x: " @@ -3815,7 +3815,7 @@ dasd_oper_handler (int irq, devreg_t * d } if (device && - device->level >= DASD_STATE_READY) { + device->level >= DASD_STATE_NEW) { s390irq_spin_lock_irqsave (device->devinfo.irq, flags); DEV_MESSAGE (KERN_DEBUG, device, "%s", @@ -5188,6 +5188,7 @@ dasd_statistics_write (struct file *file "/proc/dasd/statistics: only 'set' and " "'reset' are supported verbs"); + vfree (buffer); return -EINVAL; } @@ -5243,6 +5244,7 @@ dasd_statistics_write (struct file *file #endif /* DASD_PROFILE */ + vfree (buffer); return user_len; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/block/dasd_3990_erp.c linux-2.4.28-pre3/drivers/s390/block/dasd_3990_erp.c --- linux-2.4.27/drivers/s390/block/dasd_3990_erp.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/block/dasd_3990_erp.c 2004-09-10 19:36:32.000000000 +0000 @@ -5,7 +5,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 * - * $Revision: 1.52 $ + * $Revision: 1.52.2.3 $ * * History of changes: * 05/14/01 fixed PL030160GTO (BUG() in erp_action_5) @@ -585,9 +585,8 @@ dasd_3990_erp_alternate_path (ccw_req_t ioinfo[irq]->opm); /* reset status to queued to handle the request again... */ - check_then_set (&erp->status, - CQR_STATUS_ERROR, - CQR_STATUS_QUEUED); + if (erp->status > CQR_STATUS_QUEUED) + erp->status = CQR_STATUS_QUEUED; erp->retries = 1; @@ -598,12 +597,10 @@ dasd_3990_erp_alternate_path (ccw_req_t "opm=%x) -> permanent error", erp->dstat->lpum, ioinfo[irq]->opm); - - /* post request with permanent error */ - check_then_set (&erp->status, - CQR_STATUS_ERROR, - CQR_STATUS_FAILED); + /* post request with permanent error */ + if (erp->status > CQR_STATUS_QUEUED) + erp->status = CQR_STATUS_FAILED; } } /* end dasd_3990_erp_alternate_path */ @@ -768,7 +765,6 @@ dasd_3990_erp_action_4 (ccw_req_t *erp, CQR_STATUS_QUEUED); } } - return erp; } /* end dasd_3990_erp_action_4 */ @@ -2386,7 +2382,7 @@ dasd_3990_erp_compound_code (ccw_req_t * switch (sense[28]) { case 0x17: /* issue a Diagnostic Control command with an - * Inhibit Write subcommand and controler modifier */ + * Inhibit Write subcommand and controler modifier */ erp = dasd_3990_erp_DCTL (erp, 0x20); break; @@ -2699,7 +2695,8 @@ dasd_3990_erp_add_erp (ccw_req_t *cqr) if (!erp) { if (cqr->retries <= 0) { DEV_MESSAGE (KERN_ERR, device, "%s", - "Unable to allocate ERP request (NO retries left)"); + "Unable to allocate ERP request " + "(NO retries left)"); check_then_set (&cqr->status, CQR_STATUS_ERROR, @@ -2709,7 +2706,8 @@ dasd_3990_erp_add_erp (ccw_req_t *cqr) } else { DEV_MESSAGE (KERN_ERR, device, - "Unable to allocate ERP request (%i retries left)", + "Unable to allocate ERP request " + "(%i retries left)", cqr->retries); if (!timer_pending(&device->timer)) { @@ -3169,8 +3167,9 @@ dasd_3990_erp_action (ccw_req_t *cqr) dasd_chanq_enq_head (&device->queue, erp); } else { - if ((erp->status == CQR_STATUS_FILLED ) || (erp != device->queue.head)) { - /* something strange happened - log the error and panic */ + if ((erp->status == CQR_STATUS_FILLED ) || + (erp != device->queue.head)) { + /* something strange happened - log error and panic */ /* print current erp_chain */ DEV_MESSAGE (KERN_DEBUG, device, "%s", "ERP chain at END of ERP-ACTION"); @@ -3188,7 +3187,8 @@ dasd_3990_erp_action (ccw_req_t *cqr) temp_erp->refers); } } - panic ("Problems with ERP chain!!! Please report to linux390@de.ibm.com"); + panic ("Problems with ERP chain!!! " + "Please report to linux390@de.ibm.com"); } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/char/ctrlchar.c linux-2.4.28-pre3/drivers/s390/char/ctrlchar.c --- linux-2.4.27/drivers/s390/char/ctrlchar.c 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/char/ctrlchar.c 2004-09-10 19:37:18.000000000 +0000 @@ -9,6 +9,7 @@ #include #include +#include #include #include #include diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/c7000.c linux-2.4.28-pre3/drivers/s390/net/c7000.c --- linux-2.4.27/drivers/s390/net/c7000.c 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/net/c7000.c 2004-09-10 19:33:46.000000000 +0000 @@ -3,6 +3,20 @@ Author: Bob Scardapane (UTS Global LLC). Version: 3. + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + To use this driver, run the LINUX command: insmod c7000 base0=0xYYYY lhost0=s1 uhost0=s2 lappl0=s3 uappl0=s4 dbg=x @@ -409,16 +423,7 @@ static char ifnames[MAX_C7000][8] = {"ci One device structure per controller. */ -/* RBH Try out the new code for 2.4.0 */ -#define NEWSTUFF - -#ifdef NEWSTUFF -#define STRUCT_NET_DEVICE struct net_device -#else -#define STRUCT_NET_DEVICE struct device -#endif - -STRUCT_NET_DEVICE c7000_devices[MAX_C7000]; +struct net_device c7000_devices[MAX_C7000]; /* Scratch variable filled in with controller name. @@ -432,6 +437,7 @@ static char *controller; MODULE_AUTHOR("Robert Scardapane (UTS Global)"); MODULE_DESCRIPTION("Network module for Cisco 7000 box."); +MODULE_LICENSE("GPL"); MODULE_PARM(base0, "1i"); MODULE_PARM_DESC(base0, "Base unit address for 1st C7000 box."); @@ -521,16 +527,12 @@ struct c7000_unit { ccw1_t ccws[5]; /* control ccws */ int devno; /* device number */ int irq; /* subchannel number */ - int IO_active; /* IO activity flag */ + unsigned long IO_active; /* IO activity flag */ int state; /* fsm state */ int retries; /* retry counter */ unsigned long flag_a; /* bh activity flag */ devstat_t devstat; /* device status */ -#ifdef NEWSTUFF wait_queue_head_t wait; /* sleep q head */ -#else - struct wait_queue *wait; /* sleep q pointer */ -#endif struct c7000_controller *cntlp; /* controller pointer */ struct c7000_buffer *free; /* free buffer anchor */ struct c7000_buffer *proc_head; /* proc head */ @@ -551,7 +553,7 @@ struct c7000_unit { struct c7000_controller { struct net_device_stats stats; /* statistics */ - STRUCT_NET_DEVICE *dev; /* -> device struct */ + struct net_device *dev; /* -> device struct */ unsigned int base_addr; /* base address */ char lappl[NAMLEN]; /* local appl */ char lhost[NAMLEN]; /* local host */ @@ -560,9 +562,7 @@ struct c7000_controller { unsigned char version; /* version = 2 */ unsigned char linkid; /* link id */ struct c7000_unit cunits[NUNITS]; /* embedded units */ -#ifdef NEWSTUFF - int tbusy; -#endif + unsigned long tbusy; }; /* @@ -579,62 +579,29 @@ struct c7000_rd_header { Set the device structure transmission busy flag. */ -#ifdef NEWSTUFF #define c7000_set_busy(dev) netif_stop_queue(dev) -#else -static __inline__ void -c7000_set_busy(STRUCT_NET_DEVICE *dev) -{ - dev->tbusy = 1; - eieio(); - return; -} -#endif /* Clear the device structure transmission busy flag. */ -#ifdef NEWSTUFF #define c7000_clear_busy(dev) netif_wake_queue(dev) -#else -static __inline__ void -c7000_clear_busy(STRUCT_NET_DEVICE *dev) -{ - dev->tbusy = 0; - eieio(); - return; -} -#endif /* Extract the device structure transmission busy flag. */ -#ifdef NEWSTUFF #define c7000_check_busy(dev) netif_queue_stopped(dev) -#else -static __inline__ int -c7000_check_busy(STRUCT_NET_DEVICE *dev) -{ - eieio(); - return(dev->tbusy); -} -#endif /* Set a bit in the device structure transmission busy flag. */ static __inline__ void -c7000_setbit_busy(int nr, STRUCT_NET_DEVICE *dev) +c7000_setbit_busy(int nr, struct net_device *dev) { -#ifdef NEWSTUFF netif_stop_queue(dev); test_and_set_bit(nr, &((struct c7000_controller *)dev->priv)->tbusy); -#else - set_bit(nr, (void *)&dev->tbusy); -#endif return; } @@ -643,14 +610,10 @@ c7000_setbit_busy(int nr, STRUCT_NET_DEV */ static __inline__ void -c7000_clearbit_busy(int nr, STRUCT_NET_DEVICE *dev) +c7000_clearbit_busy(int nr, struct net_device *dev) { -#ifdef NEWSTUFF clear_bit(nr, &((struct c7000_controller *)dev->priv)->tbusy); netif_wake_queue(dev); -#else - clear_bit(nr, (void *)&dev->tbusy); -#endif return; } @@ -659,14 +622,10 @@ c7000_clearbit_busy(int nr, STRUCT_NET_D */ static __inline__ int -c7000_ts_busy(int nr, STRUCT_NET_DEVICE *dev) +c7000_ts_busy(int nr, struct net_device *dev) { -#ifdef NEWSTUFF netif_stop_queue(dev); return test_and_set_bit(nr, &((struct c7000_controller *)dev->priv)->tbusy); -#else - return(test_and_set_bit(nr, (void *)&dev->tbusy)); -#endif } /* @@ -678,7 +637,7 @@ c7000_error(struct c7000_controller *ccp { int i; struct c7000_unit *cup; - STRUCT_NET_DEVICE *dev = ccp->dev; + struct net_device *dev = ccp->dev; for (i = 0; i < NUNITS; i++) { cup = &ccp->cunits[i]; @@ -686,12 +645,8 @@ c7000_error(struct c7000_controller *ccp } if (dev != NULL) -#ifdef NEWSTUFF /* RBH XXX Should we be doing this? */ dev->state &= ~__LINK_STATE_START; -#else - dev->flags &= ~IFF_RUNNING; -#endif CPrintk(0, "c7000: c7000_error: base unit 0x%x is down\n", ccp->base_addr); return; @@ -759,9 +714,9 @@ c7000_check_devices(int devno) static int c7000_haltio(struct c7000_unit *cup) { - __u32 parm; + unsigned long parm; __u8 flags = 0x00; - __u32 saveflags; + unsigned long saveflags; DECLARE_WAITQUEUE(wait, current); int rc; @@ -792,9 +747,9 @@ c7000_haltio(struct c7000_unit *cup) static int c7000_doio(struct c7000_unit *cup) { - __u32 parm; + unsigned long parm; __u8 flags = 0x00; - __u32 saveflags; + unsigned long saveflags; DECLARE_WAITQUEUE(wait, current); int rc; @@ -1013,7 +968,7 @@ c7000_bld_read_chpgm(struct c7000_unit * */ static int -c7000_alloc_buffers(STRUCT_NET_DEVICE *dev) +c7000_alloc_buffers(struct net_device *dev) { int i; int j; @@ -1030,9 +985,10 @@ c7000_alloc_buffers(STRUCT_NET_DEVICE *d bufptr = kmalloc(sizeof(struct c7000_buffer), GFP_KERNEL); data = kmalloc(C7000_BUFSIZE, GFP_KERNEL); - if (bufptr == NULL) - { - if(data) + if (bufptr == NULL || data == NULL) { + if (bufptr) + kfree(bufptr); + if (data) kfree(data); return(-1); } @@ -1088,7 +1044,7 @@ c7000_free_chain(struct c7000_buffer *bu */ static void -c7000_free_buffers(STRUCT_NET_DEVICE *dev) +c7000_free_buffers(struct net_device *dev) { int i; struct c7000_controller *ccp = (struct c7000_controller *) dev->priv; @@ -1328,12 +1284,12 @@ c7000_irq_bh(struct c7000_unit *cup) struct c7000_rd_header *head; struct sk_buff *skb; struct c7000_controller *ccp; - STRUCT_NET_DEVICE *dev; + struct net_device *dev; int rc; __u16 data_length; - __u32 parm; + unsigned long parm; __u8 flags = 0x00; - __u32 saveflags; + unsigned long saveflags; ccp = cup->cntlp; dev = ccp->dev; @@ -1385,6 +1341,7 @@ c7000_irq_bh(struct c7000_unit *cup) skb->ip_summed = CHECKSUM_UNNECESSARY; netif_rx(skb); ccp->stats.rx_packets++; + ccp->stats.rx_bytes += skb->len; } else { CPrintk(0, "c7000: c7000_irq_bh: can not allocate a skb for unit 0x%x\n", cup->devno); ccp->stats.rx_dropped++; @@ -1403,6 +1360,7 @@ c7000_irq_bh(struct c7000_unit *cup) Rechain the buffer on the running channel program. */ + buf->ccws[3].cda = buf->ccws[5].cda = (__u32)virt_to_phys(&buf->ccws[6]); if (pbuf != NULL) pbuf->ccws[3].cda = pbuf->ccws[5].cda = (__u32)virt_to_phys(&buf->ccws[0]); @@ -1422,7 +1380,7 @@ c7000_irq_bh(struct c7000_unit *cup) return; } - parm = (__u32)cup; + parm = (unsigned long)cup; cup->state = C7000_READ; if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) { @@ -1979,7 +1937,7 @@ c7000_get_conn(struct c7000_unit *cup) */ struct net_device_stats * -c7000_stats(STRUCT_NET_DEVICE *dev) +c7000_stats(struct net_device *dev) { struct c7000_controller *ccp = (struct c7000_controller *)dev->priv; @@ -1991,13 +1949,13 @@ c7000_stats(STRUCT_NET_DEVICE *dev) */ static int -c7000_open(STRUCT_NET_DEVICE *dev) +c7000_open(struct net_device *dev) { int i; struct c7000_controller *ccp = (struct c7000_controller *)dev->priv; struct c7000_unit *cup; int rc; - __u32 parm; + unsigned long parm; __u8 flags = 0x00; c7000_set_busy(dev); @@ -2025,16 +1983,11 @@ c7000_open(STRUCT_NET_DEVICE *dev) half routine. */ -#ifndef NEWSTUFF - cup->tq.next = NULL; -#endif cup->tq.sync = 0; cup->tq.routine = (void *)(void *)c7000_irq_bh; cup->tq.data = cup; cup->state = C7000_HALT; -#ifdef NEWSTUFF init_waitqueue_head(&cup->wait); -#endif CPrintk(1, "c7000: c7000_open: issuing halt to unit 0x%x\n", cup->devno); /* @@ -2154,7 +2107,7 @@ c7000_open(STRUCT_NET_DEVICE *dev) */ cup->state = C7000_READ; - parm = (__u32) cup; + parm = (unsigned long)cup; set_bit(0, (void *)&cup->IO_active); if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) { @@ -2165,11 +2118,7 @@ c7000_open(STRUCT_NET_DEVICE *dev) return(-EIO); } -#ifdef NEWSTUFF netif_start_queue(dev); -#else - dev->start = 1; -#endif CPrintk(0, "c7000: c7000_open: base unit 0x%lx is opened\n", dev->base_addr); c7000_clear_busy(dev); MOD_INC_USE_COUNT; /* increment module usage count */ @@ -2181,18 +2130,13 @@ c7000_open(STRUCT_NET_DEVICE *dev) */ static int -c7000_stop(STRUCT_NET_DEVICE *dev) +c7000_stop(struct net_device *dev) { int i; struct c7000_controller *ccp = (struct c7000_controller *)dev->priv; struct c7000_unit *cup; int rc; -#ifdef NEWSTUFF -/* nothing? */ -#else - dev->start = 0; -#endif c7000_set_busy(dev); /* @@ -2236,7 +2180,7 @@ c7000_stop(STRUCT_NET_DEVICE *dev) */ static int -c7000_config(STRUCT_NET_DEVICE *dev, struct ifmap *map) +c7000_config(struct net_device *dev, struct ifmap *map) { CPrintk(1, "c7000: c7000_config: entered for base unit 0x%lx\n", dev->base_addr); return(0); @@ -2247,12 +2191,12 @@ c7000_config(STRUCT_NET_DEVICE *dev, str */ static int -c7000_xmit(struct sk_buff *skb, STRUCT_NET_DEVICE *dev) +c7000_xmit(struct sk_buff *skb, struct net_device *dev) { struct c7000_controller *ccp = (struct c7000_controller *)dev->priv; struct c7000_unit *cup; - __u32 saveflags; - __u32 parm; + unsigned long saveflags; + unsigned long parm; __u8 flags = 0x00; struct c7000_buffer *buf, *pbuf; int rc; @@ -2350,7 +2294,7 @@ c7000_xmit(struct sk_buff *skb, STRUCT_N if (test_and_set_bit(0, (void *)&cup->IO_active) == 0) { CPrintk(1, "c7000: c7000_xmit: start IO for unit 0x%x\n", cup->devno); c7000_bld_wrt_chain(cup); - parm = (__u32) cup; + parm = (unsigned long)cup; cup->state = C7000_WRITE; if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) { @@ -2385,7 +2329,7 @@ c7000_xmit(struct sk_buff *skb, STRUCT_N */ static int -c7000_ioctl(STRUCT_NET_DEVICE *dev, struct ifreq *ifr, int cmd) +c7000_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { CPrintk(1, "c7000: c7000_ioctl: entered for base unit 0x%lx with cmd %d\n", dev->base_addr, cmd); return(0); @@ -2461,7 +2405,7 @@ static void c7000_retry_io(struct c7000_unit *cup) { int rc; - __u32 parm; + unsigned long parm; __u8 flags = 0x00; ccw1_t *ccwp; @@ -2472,7 +2416,7 @@ c7000_retry_io(struct c7000_unit *cup) } set_bit(0, (void *)&cup->IO_active); - parm = (__u32)cup; + parm = (unsigned long)cup; if (cup->state == C7000_READ || cup->state == C7000_WRITE) ccwp = &cup->proc_head->ccws[0]; @@ -2560,14 +2504,10 @@ c7000_proc_wintr(struct c7000_unit *cup) */ buf = c7000_dequeue_buffer(cup); + ccp->stats.tx_bytes += buf->len; + ccp->stats.tx_packets++; c7000_release_buffer(cup, buf); num_write++; - - /* - Update transmitted packets statistic. - */ - - ccp->stats.tx_packets++; } CPrintk(1, "c7000: c7000_proc_wintr: %d buffers written for unit 0x%x\n", num_write, cup->devno); @@ -2584,8 +2524,8 @@ c7000_intr(int irq, void *initparm, stru devstat_t *devstat = ((devstat_t *) initparm); struct c7000_unit *cup = NULL; struct c7000_controller *ccp = NULL; - STRUCT_NET_DEVICE *dev = NULL; - __u32 parm; + struct net_device *dev = NULL; + unsigned long parm; __u8 flags = 0x00; int rc; @@ -2618,14 +2558,14 @@ c7000_intr(int irq, void *initparm, stru ccp = cup->cntlp; if (ccp == NULL) { - CPrintk(0, "c7000: c7000_intr: c7000_cntlp pointer is NULL in c7000_unit structure 0x%x for unit 0x%x\n", (int)cup, cup->devno); + CPrintk(0, "c7000: c7000_intr: c7000_cntlp pointer is NULL in c7000_unit structure %p for unit 0x%x\n", cup, cup->devno); return; } dev = ccp->dev; if (dev == NULL) { - CPrintk(0, "c7000: c7000_intr: device pointer is NULL in c7000_controller structure 0x%x for unit 0x%x\n", (int)ccp, cup->devno); + CPrintk(0, "c7000: c7000_intr: device pointer is NULL in c7000_controller structure %p for unit 0x%x\n", ccp, cup->devno); return; } @@ -2777,7 +2717,7 @@ c7000_intr(int irq, void *initparm, stru if ((devstat->flag & DEVSTAT_FINAL_STATUS) && (cup->free != NULL)) { c7000_bld_read_chain(cup); - parm = (__u32)cup; + parm = (unsigned long)cup; set_bit(0, (void *)&cup->IO_active); if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) { @@ -2834,7 +2774,7 @@ c7000_intr(int irq, void *initparm, stru if (cup->proc_head != NULL) { c7000_bld_wrt_chain(cup); - parm = (__u32)cup; + parm = (unsigned long)cup; set_bit(0, (void *)&cup->IO_active); if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) { @@ -2932,7 +2872,7 @@ c7000_fill_name(char *dst, char *src) */ static int -c7000_init(STRUCT_NET_DEVICE *dev) +c7000_init(struct net_device *dev) { struct c7000_controller *ccp; int i; @@ -2970,7 +2910,7 @@ c7000_init(STRUCT_NET_DEVICE *dev) dev->addr_len = 0; dev->type = ARPHRD_SLIP; dev->tx_queue_len = C7000_TXQUEUE_LEN; - dev->flags = IFF_NOARP; + dev->flags = IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP; dev->open = c7000_open; dev->stop = c7000_stop; dev->set_config = c7000_config; @@ -2987,7 +2927,7 @@ c7000_init(STRUCT_NET_DEVICE *dev) return(-ENOMEM); } - CPrintk(1, "c7000: c7000_init: allocated a c7000_controller structure at address 0x%x\n", (int)ccp); + CPrintk(1, "c7000: c7000_init: allocated a c7000_controller structure at address %p\n", ccp); memset(ccp, '\0', sizeof(struct c7000_controller)); ccp->dev = dev; ccp->base_addr = dev->base_addr; @@ -3217,12 +3157,8 @@ init_module(void) Initialize the device structure. */ - memset(&c7000_devices[i], '\0', sizeof(STRUCT_NET_DEVICE)); -#ifdef NEWSTUFF + memset(&c7000_devices[i], '\0', sizeof(struct net_device)); strcpy(c7000_devices[i].name, ifnames[i]); -#else - c7000_devices[i].name = &ifnames[i][0]; -#endif c7000_devices[i].base_addr = bases[i]; c7000_devices[i].init = c7000_init; @@ -3278,7 +3214,7 @@ cleanup_module(void) free_irq(ccp->cunits[j].irq, &ccp->cunits[j].devstat); } - CPrintk(1, "c7000: clean_module: free a c7000_controller structure at address 0x%x\n", (int)ccp); + CPrintk(1, "c7000: clean_module: free a c7000_controller structure at address %p\n", ccp); kfree(ccp); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/ctcmain.c linux-2.4.28-pre3/drivers/s390/net/ctcmain.c --- linux-2.4.27/drivers/s390/net/ctcmain.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/net/ctcmain.c 2004-09-10 19:34:04.000000000 +0000 @@ -3096,7 +3096,7 @@ static ssize_t ctc_loglevel_read(struct privptr = (ctc_priv *)dev->priv; - if (!*sbus || pos == 0) + if (!*sbuf || pos == 0) sprintf(sbuf, "0x%02x\n", loglevel); l = strlen(sbuf); @@ -3169,7 +3169,7 @@ static ssize_t ctc_stat_read(struct file privptr = (ctc_priv *)dev->priv; - if (!*sbus || pos == 0) { + if (!*sbuf || pos == 0) { p += sprintf(p, "Device FSM state: %s\n", fsm_getstate_str(privptr->fsm)); p += sprintf(p, "RX channel FSM state: %s\n", diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/iucv.c linux-2.4.28-pre3/drivers/s390/net/iucv.c --- linux-2.4.27/drivers/s390/net/iucv.c 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/net/iucv.c 2004-09-10 19:32:31.000000000 +0000 @@ -1,5 +1,5 @@ /* - * $Id: iucv.c,v 1.41 2003/06/24 16:05:32 felfert Exp $ + * $Id: iucv.c,v 1.40.2.5 2004/06/29 07:37:33 braunu Exp $ * * IUCV network driver * @@ -29,7 +29,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.41 $ + * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.40.2.5 $ * */ @@ -320,7 +320,7 @@ iucv_dumpit(char *title, void *buf, int #define iucv_debug(lvl, fmt, args...) \ do { \ if (debuglevel >= lvl) \ - printk(KERN_DEBUG __FUNCTION__ ": " fmt "\n", ## args); \ + printk(KERN_DEBUG "%s: " fmt "\n", __FUNCTION__, ## args); \ } while (0) #else @@ -334,13 +334,15 @@ do { \ * Internal functions *******************************************************************************/ +static int iucv_retrieve_buffer(void); + /** * print start banner */ static void iucv_banner(void) { - char vbuf[] = "$Revision: 1.41 $"; + char vbuf[] = "$Revision: 1.40.2.5 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { @@ -418,6 +420,7 @@ iucv_init(void) static void iucv_exit(void) { + iucv_retrieve_buffer(); if (iucv_external_int_buffer) kfree(iucv_external_int_buffer); if (iucv_param_pool) @@ -438,17 +441,19 @@ iucv_exit(void) static __inline__ iucv_param * grab_param(void) { - iucv_param *ret; - int i = 0; + iucv_param *ptr; + static int hint = 0; + + ptr = iucv_param_pool + hint; + do { + ptr++; + if (ptr >= iucv_param_pool + PARAM_POOL_SIZE) + ptr = iucv_param_pool; + } while (atomic_compare_and_swap(0, 1, &ptr->in_use)); + hint = ptr - iucv_param_pool; - while (atomic_compare_and_swap(0, 1, &iucv_param_pool[i].in_use)) { - i++; - if (i >= PARAM_POOL_SIZE) - i = 0; - } - ret = &iucv_param_pool[i]; - memset(&ret->param, 0, sizeof(ret->param)); - return ret; + memset(&ptr->param, 0, sizeof(ptr->param)); + return ptr; } /** @@ -549,10 +554,8 @@ b2f0(__u32 code, void *parm) * - ENOMEM - storage allocation for a new pathid table failed */ static int -iucv_add_pathid(__u16 pathid, handler *handler) +__iucv_add_pathid(__u16 pathid, handler *handler) { - ulong flags; - iucv_debug(1, "entering"); iucv_debug(1, "handler is pointing to %p", handler); @@ -560,21 +563,30 @@ iucv_add_pathid(__u16 pathid, handler *h if (pathid > (max_connections - 1)) return -EINVAL; - spin_lock_irqsave (&iucv_lock, flags); if (iucv_pathid_table[pathid]) { - spin_unlock_irqrestore (&iucv_lock, flags); iucv_debug(1, "pathid entry is %p", iucv_pathid_table[pathid]); printk(KERN_WARNING "%s: Pathid being used, error.\n", __FUNCTION__); return -EINVAL; } iucv_pathid_table[pathid] = handler; - spin_unlock_irqrestore (&iucv_lock, flags); iucv_debug(1, "exiting"); return 0; } /* end of add_pathid function */ +static int +iucv_add_pathid(__u16 pathid, handler *handler) +{ + ulong flags; + int rc; + + spin_lock_irqsave (&iucv_lock, flags); + rc = __iucv_add_pathid(pathid, handler); + spin_unlock_irqrestore (&iucv_lock, flags); + return rc; +} + static void iucv_remove_pathid(__u16 pathid) { @@ -688,7 +700,6 @@ iucv_remove_handler(handler *handler) spin_lock_irqsave (&iucv_lock, flags); list_del(&handler->list); if (list_empty(&iucv_handler_table)) { - iucv_retrieve_buffer(); if (register_flag) { unregister_external_interrupt(0x4000, iucv_irq_handler); register_flag = 0; @@ -764,6 +775,7 @@ iucv_register_program (__u8 pgmname[16], if (iucv_pathid_table == NULL) { printk(KERN_WARNING "%s: iucv_pathid_table storage " "allocation failed\n", __FUNCTION__); + kfree(new_handler); return NULL; } memset (iucv_pathid_table, 0, max_connections * sizeof(handler *)); @@ -1002,6 +1014,8 @@ iucv_accept(__u16 pathid, __u16 msglim_r b2f0_result = b2f0(ACCEPT, parm); if (b2f0_result == 0) { + if (msglim) + *msglim = parm->ipmsglim; if (pgm_data) h->pgm_data = pgm_data; if (flags1_out) @@ -1133,11 +1147,15 @@ iucv_connect (__u16 *pathid, __u16 msgli iucv_setmask(~(AllInterrupts)); messagesDisabled = 1; + spin_lock_irqsave (&iucv_lock, flags); parm->ipflags1 = (__u8)flags1; b2f0_result = b2f0(CONNECT, parm); memcpy(&local_parm, parm, sizeof(local_parm)); release_param(parm); parm = &local_parm; + if (b2f0_result == 0) + add_pathid_result = __iucv_add_pathid(parm->ippathid, h); + spin_unlock_irqrestore (&iucv_lock, flags); if (b2f0_result) { iucv_setmask(~0); @@ -1145,7 +1163,6 @@ iucv_connect (__u16 *pathid, __u16 msgli return b2f0_result; } - add_pathid_result = iucv_add_pathid(parm->ippathid, h); *pathid = parm->ippathid; /* Enable everything again */ @@ -1884,6 +1901,7 @@ iucv_send_prmmsg (__u16 pathid, { iparml_dpl *parm; ulong b2f0_result; + iucv_param save_param; iucv_debug(2, "entering"); @@ -1896,7 +1914,13 @@ iucv_send_prmmsg (__u16 pathid, parm->ipflags1 = (IPRMDATA | IPNORPY | flags1); memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg)); + memcpy((void *)&save_param, (void *)parm, sizeof(iucv_param)); b2f0_result = b2f0(SEND, parm); + if (b2f0_result != 0) { + printk("b2f0 call returned %lx\n", b2f0_result); + iucv_dumpit("PL before:", &save_param, sizeof(iucv_param)); + iucv_dumpit("PL after:", parm, sizeof(iucv_param)); + } if ((b2f0_result == 0) && (msgid)) *msgid = parm->ipmsgid; @@ -2333,7 +2357,8 @@ iucv_do_int(iucv_GeneralInterrupt * int_ iucv_debug(2, "found a matching handler"); break; - } + } else + h = NULL; } spin_unlock_irqrestore (&iucv_lock, flags); if (h) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/netiucv.c linux-2.4.28-pre3/drivers/s390/net/netiucv.c --- linux-2.4.27/drivers/s390/net/netiucv.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/net/netiucv.c 2004-09-10 19:35:18.000000000 +0000 @@ -1,5 +1,5 @@ /* - * $Id: netiucv.c,v 1.23 2003/06/24 16:05:32 felfert Exp $ + * $Id: netiucv.c,v 1.21.8.6 2004/06/29 07:37:33 braunu Exp $ * * IUCV network driver * @@ -28,7 +28,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV network driver $Revision: 1.23 $ + * RELEASE-TAG: IUCV network driver $Revision: 1.21.8.6 $ * */ @@ -114,17 +114,13 @@ typedef struct iucv_connection_t { spinlock_t collect_lock; int collect_len; int max_buffsize; - int flags; fsm_timer timer; - int retry; fsm_instance *fsm; net_device *netdev; connection_profile prof; char userid[9]; } iucv_connection; -#define CONN_FLAGS_BUFSIZE_CHANGED 1 - /** * Linked list of all connection structs. */ @@ -435,6 +431,10 @@ netiucv_callback_txdone(iucv_MessageComp iucv_connection *conn = (iucv_connection *)pgm_data; iucv_event ev; +#ifdef DEBUG + printk(KERN_DEBUG "%s() called\n", __FUNCTION__); +#endif + ev.conn = conn; ev.data = (void *)eib; fsm_event(conn->fsm, CONN_EVENT_TXDONE, &ev); @@ -590,7 +590,7 @@ conn_action_rx(fsm_instance *fi, int eve iucv_MessagePending *eib = (iucv_MessagePending *)ev->data; netiucv_priv *privptr = (netiucv_priv *)conn->netdev->priv; - __u16 msglen = eib->ln1msg2.ipbfln1f; + __u32 msglen = eib->ln1msg2.ipbfln1f; int rc; #ifdef DEBUG @@ -613,6 +613,7 @@ conn_action_rx(fsm_instance *fi, int eve conn->rx_buff->data, msglen, NULL, NULL, NULL); if (rc != 0 || msglen < 5) { privptr->stats.rx_errors++; + printk(KERN_INFO "iucv_receive returned %08x\n", rc); return; } netiucv_unpack_skb(conn, conn->rx_buff); @@ -637,7 +638,6 @@ conn_action_txdone(fsm_instance *fi, int #ifdef DEBUG printk(KERN_DEBUG "%s() called\n", __FUNCTION__); #endif - fsm_deltimer(&conn->timer); if (conn && conn->netdev && conn->netdev->priv) privptr = (netiucv_priv *)conn->netdev->priv; conn->prof.tx_pending--; @@ -645,11 +645,12 @@ conn_action_txdone(fsm_instance *fi, int if ((skb = skb_dequeue(&conn->commit_queue))) { atomic_dec(&skb->users); dev_kfree_skb_any(skb); - } - if (privptr) { - privptr->stats.tx_packets++; - privptr->stats.tx_bytes += - (skb->len - NETIUCV_HDRLEN - NETIUCV_HDRLEN); + if (privptr) { + privptr->stats.tx_packets++; + privptr->stats.tx_bytes += + (skb->len - NETIUCV_HDRLEN + - NETIUCV_HDRLEN); + } } } conn->tx_buff->data = conn->tx_buff->tail = conn->tx_buff->head; @@ -677,8 +678,6 @@ conn_action_txdone(fsm_instance *fi, int memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN); - fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC, - CONN_EVENT_TIMER, conn); conn->prof.send_stamp = xtime; rc = iucv_send(conn->pathid, NULL, 0, 0, 0, 0, conn->tx_buff->data, conn->tx_buff->len); @@ -688,12 +687,11 @@ conn_action_txdone(fsm_instance *fi, int if (conn->prof.tx_pending > conn->prof.tx_max_pending) conn->prof.tx_max_pending = conn->prof.tx_pending; if (rc != 0) { - fsm_deltimer(&conn->timer); conn->prof.tx_pending--; fsm_newstate(fi, CONN_STATE_IDLE); if (privptr) privptr->stats.tx_errors += txpackets; - printk(KERN_DEBUG "iucv_send returned %08x\n", + printk(KERN_INFO "iucv_send returned %08x\n", rc); } else { if (privptr) { @@ -762,6 +760,7 @@ conn_action_connack(fsm_instance *fi, in #ifdef DEBUG printk(KERN_DEBUG "%s() called\n", __FUNCTION__); #endif + fsm_deltimer(&conn->timer); fsm_newstate(fi, CONN_STATE_IDLE); conn->pathid = eib->ippathid; netdev->tx_queue_len = eib->ipmsglim; @@ -769,6 +768,19 @@ conn_action_connack(fsm_instance *fi, in } static void +conn_action_conntimsev(fsm_instance *fi, int event, void *arg) +{ + iucv_connection *conn = (iucv_connection *)arg; + __u8 udata[16]; + + pr_debug("%s() called\n", __FUNCTION__); + + fsm_deltimer(&conn->timer); + iucv_sever(conn->pathid, udata); + fsm_newstate(fi, CONN_STATE_STARTWAIT); +} + +static void conn_action_connsever(fsm_instance *fi, int event, void *arg) { iucv_event *ev = (iucv_event *)arg; @@ -776,30 +788,17 @@ conn_action_connsever(fsm_instance *fi, // iucv_ConnectionSevered *eib = (iucv_ConnectionSevered *)ev->data; net_device *netdev = conn->netdev; netiucv_priv *privptr = (netiucv_priv *)netdev->priv; - int state = fsm_getstate(fi); + __u8 udata[16]; #ifdef DEBUG printk(KERN_DEBUG "%s() called\n", __FUNCTION__); #endif - switch (state) { - case CONN_STATE_SETUPWAIT: - printk(KERN_INFO "%s: Remote dropped connection\n", - netdev->name); - conn->handle = 0; - fsm_newstate(fi, CONN_STATE_STOPPED); - fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev); - break; - case CONN_STATE_IDLE: - case CONN_STATE_TX: - printk(KERN_INFO "%s: Remote dropped connection\n", - netdev->name); - if (conn->handle) - iucv_unregister_program(conn->handle); - conn->handle = 0; - fsm_newstate(fi, CONN_STATE_STOPPED); - fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev); - break; - } + fsm_deltimer(&conn->timer); + iucv_sever(conn->pathid, udata); + printk(KERN_INFO "%s: Remote dropped connection\n", + netdev->name); + fsm_newstate(fi, CONN_STATE_STARTWAIT); + fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev); } static void @@ -807,7 +806,7 @@ conn_action_start(fsm_instance *fi, int { iucv_event *ev = (iucv_event *)arg; iucv_connection *conn = ev->conn; - + __u16 msglimit; int rc; #ifdef DEBUG @@ -839,10 +838,13 @@ conn_action_start(fsm_instance *fi, int fsm_newstate(fi, CONN_STATE_SETUPWAIT); rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic, - conn->userid, iucv_host, 0, NULL, NULL, conn->handle, + conn->userid, iucv_host, 0, NULL, &msglimit, conn->handle, conn); switch (rc) { case 0: + conn->netdev->tx_queue_len = msglimit; + fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC, + CONN_EVENT_TIMER, conn); return; case 11: printk(KERN_NOTICE @@ -910,6 +912,7 @@ conn_action_stop(fsm_instance *fi, int e #ifdef DEBUG printk(KERN_DEBUG "%s() called\n", __FUNCTION__); #endif + fsm_deltimer(&conn->timer); fsm_newstate(fi, CONN_STATE_STOPPED); netiucv_purge_skb_queue(&conn->collect_queue); if (conn->handle) @@ -934,8 +937,8 @@ conn_action_inval(fsm_instance *fi, int static const fsm_node conn_fsm[] = { { CONN_STATE_INVALID, CONN_EVENT_START, conn_action_inval }, { CONN_STATE_STOPPED, CONN_EVENT_START, conn_action_start }, - { CONN_STATE_STARTWAIT, CONN_EVENT_START, conn_action_start }, + { CONN_STATE_STOPPED, CONN_EVENT_STOP, conn_action_stop }, { CONN_STATE_STARTWAIT, CONN_EVENT_STOP, conn_action_stop }, { CONN_STATE_SETUPWAIT, CONN_EVENT_STOP, conn_action_stop }, { CONN_STATE_IDLE, CONN_EVENT_STOP, conn_action_stop }, @@ -950,6 +953,7 @@ static const fsm_node conn_fsm[] = { { CONN_STATE_TX, CONN_EVENT_CONN_REQ, conn_action_connreject }, { CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_ACK, conn_action_connack }, + { CONN_STATE_SETUPWAIT, CONN_EVENT_TIMER, conn_action_conntimsev }, { CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_REJ, conn_action_connsever }, { CONN_STATE_IDLE, CONN_EVENT_CONN_REJ, conn_action_connsever }, @@ -1026,6 +1030,7 @@ static void dev_action_connup(fsm_instance *fi, int event, void *arg) { net_device *dev = (net_device *)arg; + netiucv_priv *privptr = (netiucv_priv *)dev->priv; #ifdef DEBUG printk(KERN_DEBUG "%s() called\n", __FUNCTION__); @@ -1034,8 +1039,8 @@ dev_action_connup(fsm_instance *fi, int case DEV_STATE_STARTWAIT: fsm_newstate(fi, DEV_STATE_RUNNING); printk(KERN_INFO - "%s: connected with remote side\n", - dev->name); + "%s: connected with remote side %s\n", + dev->name, privptr->conn->userid); break; case DEV_STATE_STOPWAIT: printk(KERN_INFO @@ -1056,9 +1061,6 @@ dev_action_connup(fsm_instance *fi, int static void dev_action_conndown(fsm_instance *fi, int event, void *arg) { - net_device *dev = (net_device *)arg; - netiucv_priv *privptr = dev->priv; - iucv_event ev; #ifdef DEBUG printk(KERN_DEBUG "%s() called\n", __FUNCTION__); @@ -1066,10 +1068,6 @@ dev_action_conndown(fsm_instance *fi, in switch (fsm_getstate(fi)) { case DEV_STATE_RUNNING: fsm_newstate(fi, DEV_STATE_STARTWAIT); - ev.conn = privptr->conn; - fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev); - break; - case DEV_STATE_STARTWAIT: break; case DEV_STATE_STOPWAIT: fsm_newstate(fi, DEV_STATE_STOPPED); @@ -1085,7 +1083,6 @@ static const fsm_node dev_fsm[] = { { DEV_STATE_STARTWAIT, DEV_EVENT_STOP, dev_action_stop }, { DEV_STATE_STARTWAIT, DEV_EVENT_CONUP, dev_action_connup }, - { DEV_STATE_STARTWAIT, DEV_EVENT_CONDOWN, dev_action_conndown }, { DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop }, { DEV_STATE_RUNNING, DEV_EVENT_CONDOWN, dev_action_conndown }, @@ -1141,6 +1138,7 @@ netiucv_transmit_skb(iucv_connection *co "%s: Could not allocate tx_skb\n", conn->netdev->name); rc = -ENOMEM; + return rc; } else { skb_reserve(nskb, NETIUCV_HDRLEN); memcpy(skb_put(nskb, skb->len), @@ -1156,10 +1154,7 @@ netiucv_transmit_skb(iucv_connection *co header.next = 0; memcpy(skb_put(nskb, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN); - conn->retry = 0; fsm_newstate(conn->fsm, CONN_STATE_TX); - fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC, - CONN_EVENT_TIMER, conn); conn->prof.send_stamp = xtime; rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */, @@ -1171,7 +1166,6 @@ netiucv_transmit_skb(iucv_connection *co conn->prof.tx_max_pending = conn->prof.tx_pending; if (rc != 0) { netiucv_priv *privptr; - fsm_deltimer(&conn->timer); fsm_newstate(conn->fsm, CONN_STATE_IDLE); conn->prof.tx_pending--; privptr = (netiucv_priv *)conn->netdev->priv; @@ -1276,7 +1270,6 @@ static int netiucv_tx(struct sk_buff *sk */ if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) { fsm_event(privptr->fsm, DEV_EVENT_START, dev); - dst_link_failure(skb); dev_kfree_skb(skb); privptr->stats.tx_dropped++; privptr->stats.tx_errors++; @@ -1390,7 +1383,7 @@ netiucv_buffer_close(struct inode *inode static ssize_t netiucv_buffer_write(struct file *file, const char *buf, size_t count, - loff_t *off) + loff_t *ppos) { unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino; net_device *dev; @@ -1401,7 +1394,7 @@ netiucv_buffer_write(struct file *file, if (!(dev = find_netdev_by_ino(ino))) return -ENODEV; - if (off != &file->f_pos) + if (ppos != &file->f_pos) return -ESPIPE; privptr = (netiucv_priv *)dev->priv; @@ -1427,13 +1420,12 @@ netiucv_buffer_write(struct file *file, privptr->conn->max_buffsize = bs1; if (!(dev->flags & IFF_RUNNING)) dev->mtu = bs1 - NETIUCV_HDRLEN - NETIUCV_HDRLEN; - privptr->conn->flags |= CONN_FLAGS_BUFSIZE_CHANGED; return count; } static ssize_t -netiucv_buffer_read(struct file *file, char *buf, size_t count, loff_t *off) +netiucv_buffer_read(struct file *file, char *buf, size_t count, loff_t *ppos) { unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino; char *sbuf = (char *)file->private_data; @@ -1446,7 +1438,7 @@ netiucv_buffer_read(struct file *file, c if (!(dev = find_netdev_by_ino(ino))) return -ENODEV; - if (off != &file->f_pos) + if (ppos != &file->f_pos) return -ESPIPE; privptr = (netiucv_priv *)dev->priv; @@ -1489,7 +1481,7 @@ netiucv_user_close(struct inode *inode, static ssize_t netiucv_user_write(struct file *file, const char *buf, size_t count, - loff_t *off) + loff_t *ppos) { unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino; net_device *dev; @@ -1501,7 +1493,7 @@ netiucv_user_write(struct file *file, co if (!(dev = find_netdev_by_ino(ino))) return -ENODEV; - if (off != &file->f_pos) + if (ppos != &file->f_pos) return -ESPIPE; privptr = (netiucv_priv *)dev->priv; @@ -1531,7 +1523,7 @@ netiucv_user_write(struct file *file, co } static ssize_t -netiucv_user_read(struct file *file, char *buf, size_t count, loff_t *off) +netiucv_user_read(struct file *file, char *buf, size_t count, loff_t *ppos) { unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino; char *sbuf = (char *)file->private_data; @@ -1544,7 +1536,7 @@ netiucv_user_read(struct file *file, cha if (!(dev = find_netdev_by_ino(ino))) return -ENODEV; - if (off != &file->f_pos) + if (ppos != &file->f_pos) return -ESPIPE; privptr = (netiucv_priv *)dev->priv; @@ -1589,7 +1581,7 @@ netiucv_stat_close(struct inode *inode, } static ssize_t -netiucv_stat_write(struct file *file, const char *buf, size_t count, loff_t *off) +netiucv_stat_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino; net_device *dev; @@ -1603,7 +1595,7 @@ netiucv_stat_write(struct file *file, co } static ssize_t -netiucv_stat_read(struct file *file, char *buf, size_t count, loff_t *off) +netiucv_stat_read(struct file *file, char *buf, size_t count, loff_t *ppos) { unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino; loff_t pos = *ppos; @@ -1616,7 +1608,7 @@ netiucv_stat_read(struct file *file, cha if (!(dev = find_netdev_by_ino(ino))) return -ENODEV; - if (off != &file->f_pos) + if (ppos != &file->f_pos) return -ESPIPE; privptr = (netiucv_priv *)dev->priv; @@ -1799,7 +1791,7 @@ netiucv_proc_destroy_main(void) proc_net_unregister(netiucv_dir.low_ino); #endif } -#endif MODULE +#endif /** * Create a device specific subdirectory in /proc/net/iucv/ with the @@ -2059,7 +2051,7 @@ netiucv_free_netdevice(net_device *dev) static void netiucv_banner(void) { - char vbuf[] = "$Revision: 1.23 $"; + char vbuf[] = "$Revision: 1.21.8.6 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/qeth.c linux-2.4.28-pre3/drivers/s390/net/qeth.c --- linux-2.4.27/drivers/s390/net/qeth.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/net/qeth.c 2004-09-10 19:34:31.000000000 +0000 @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth.c ($Revision: 1.337 $) + * linux/drivers/s390/net/qeth.c ($Revision: 1.337.4.24 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -28,9 +28,6 @@ */ /* - * The driver supports in general all QDIO driven network devices on the - * Hydra card. - * * For all devices, three channels must be available to the driver. One * channel is the read channel, one is the write channel and the third * one is the channel used to control QDIO. @@ -156,6 +153,7 @@ void volatile qeth_eyecatcher(void) #include #include #include +#include #include @@ -171,7 +169,7 @@ MODULE_PARM_DESC(qeth_sparebufs,"the num static int global_stay_in_mem=0; /****************** MODULE STUFF **********************************/ -#define VERSION_QETH_C "$Revision: 1.337 $" +#define VERSION_QETH_C "$Revision: 1.337.4.24 $" static const char *version="qeth S/390 OSA-Express driver (" \ VERSION_QETH_C "/" VERSION_QETH_H "/" VERSION_QETH_MPC_H QETH_VERSION_IPV6 QETH_VERSION_VLAN ")"; @@ -183,10 +181,8 @@ MODULE_LICENSE("GPL"); /******************** HERE WE GO ***********************************/ -#define PROCFILE_SLEEP_SEM_MAX_VALUE 0 -#define PROCFILE_IOCTL_SEM_MAX_VALUE 3 -static struct semaphore qeth_procfile_ioctl_lock; -static struct semaphore qeth_procfile_ioctl_sem; + + static qeth_card_t *firstcard=NULL; static sparebufs_t sparebufs[MAX_SPARE_BUFFERS]; @@ -224,9 +220,12 @@ typedef struct { /* thought I could get along without forward declarations... * just lazyness here */ static int qeth_reinit_thread(void*); -static void qeth_schedule_recovery(qeth_card_t *card); +static inline void qeth_schedule_recovery(qeth_card_t *card); +static int qeth_fake_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, + unsigned len); -inline static int QETH_IP_VERSION(struct sk_buff *skb) +static inline int QETH_IP_VERSION(struct sk_buff *skb) { switch (skb->protocol) { case ETH_P_IPV6: return 6; @@ -243,6 +242,21 @@ static inline int qeth_min(int a,int b) return b; } +/* + * This is our local skb_unshare, only with pskb_copy instead of skb_copy. + * We place our headers whare Ethernet MAC was, so we do not need + * full skb_copy. + */ +static inline struct sk_buff *qeth_pskb_unshare(struct sk_buff *skb, int pri) +{ + struct sk_buff *nskb; + if (!skb_cloned(skb)) + return skb; + nskb = skb_copy(skb, pri); + kfree_skb(skb); /* free our shared copy */ + return nskb; +} + static inline unsigned int qeth_get_millis(void) { __u64 time; @@ -291,7 +305,8 @@ static void qeth_wait_nonbusy(unsigned i set_task_state(current,TASK_RUNNING); } -static void qeth_get_mac_for_ipm(__u32 ipm,char *mac,struct net_device *dev) { +static inline void qeth_get_mac_for_ipm(__u32 ipm,char *mac, + struct net_device *dev) { if (dev->type==ARPHRD_IEEE802_TR) ip_tr_mc_map(ipm,mac); else @@ -403,7 +418,7 @@ static int inline my_spin_lock_nonbusy(q #define QETH_GET_ADDR(x) ((__u32)x) #endif /* CONFIG_ARCH_S390X */ -static int qeth_does_card_exist(qeth_card_t *card) +static inline int qeth_does_card_exist(qeth_card_t *card) { qeth_card_t *c=firstcard; int rc=0; @@ -718,7 +733,9 @@ static int qeth_set_config(struct net_de static int qeth_is_multicast_skb_at_all(struct sk_buff *skb,int version) { - int i; + int i=RTN_UNSPEC; + qeth_card_t *card = (qeth_card_t *)skb->dev->priv; + if (skb->dst && skb->dst->neighbour) { i=skb->dst->neighbour->type; return ((i==RTN_BROADCAST)|| @@ -731,13 +748,37 @@ static int qeth_is_multicast_skb_at_all( } else if (version==6) { return (skb->nh.raw[24]==0xff)?RTN_MULTICAST:0; } - return 0; + if (!memcmp(skb->nh.raw,skb->dev->broadcast,6)) { + i=RTN_BROADCAST; + } else { + __u16 hdr_mac; + hdr_mac=*((__u16*)skb->nh.raw); + /* tr multicast? */ + switch (card->link_type) { + case QETH_MPC_LINK_TYPE_HSTR: + case QETH_MPC_LINK_TYPE_LANE_TR: + if ( (hdr_mac==QETH_TR_MAC_NC) || + (hdr_mac==QETH_TR_MAC_C) ) + i = RTN_MULTICAST; + break; + /* eth or so multicast? */ + default: + if ( (hdr_mac==QETH_ETH_MAC_V4) || + (hdr_mac==QETH_ETH_MAC_V6) ) + i = RTN_MULTICAST; + } + } + return ((i==RTN_BROADCAST)|| + (i==RTN_MULTICAST)|| + (i==RTN_ANYCAST))?i:0; } static int qeth_get_prioqueue(qeth_card_t *card,struct sk_buff *skb, int multicast,int version) { - if (!version) return QETH_DEFAULT_QUEUE; + if (!version && + (card->type==QETH_CARD_TYPE_OSAE)) + return QETH_DEFAULT_QUEUE; switch (card->no_queues) { case 1: return 0; @@ -1046,7 +1087,7 @@ static int qeth_wait_for_event(atomic_t return retval; } -static int qeth_get_spare_buf(void) +static inline int qeth_get_spare_buf(void) { int i=0; char dbf_text[15]; @@ -1131,8 +1172,8 @@ static inline void qeth_clear_input_buff } } -static void qeth_queue_input_buffer(qeth_card_t *card,int bufno, - unsigned int under_int) +static inline void qeth_queue_input_buffer(qeth_card_t *card,int bufno, + unsigned int under_int) { int count=0,start=0,stop=0,pos; int result; @@ -1283,10 +1324,11 @@ static inline struct sk_buff *qeth_get_s return skb; } -static struct sk_buff *qeth_get_next_skb(qeth_card_t *card, - int *element_ptr,int *pos_in_el_ptr, - void **hdr_ptr, - qdio_buffer_t *buffer) +static inline struct sk_buff *qeth_get_next_skb(qeth_card_t *card, + int *element_ptr, + int *pos_in_el_ptr, + void **hdr_ptr, + qdio_buffer_t *buffer) { int length; char *data_ptr; @@ -1394,10 +1436,6 @@ static struct sk_buff *qeth_get_next_skb skb=qeth_get_skb(length+QETH_FAKE_LL_LEN); if (!skb) goto nomem; skb_pull(skb,QETH_FAKE_LL_LEN); - if (!skb) { - dev_kfree_skb_irq(skb); - goto nomem; - } } else { skb=qeth_get_skb(length); if (!skb) goto nomem; @@ -1472,8 +1510,8 @@ nomem: return NULL; } -static void qeth_transform_outbound_addrs(qeth_card_t *card, - qdio_buffer_t *buffer) +static inline void qeth_transform_outbound_addrs(qeth_card_t *card, + qdio_buffer_t *buffer) { int i; void *ptr; @@ -1485,7 +1523,8 @@ static void qeth_transform_outbound_addr } } } -static void qeth_get_linux_addrs_for_buffer(qeth_card_t *card,int buffer_no) +static inline void qeth_get_linux_addrs_for_buffer(qeth_card_t *card, + int buffer_no) { int i; void *ptr; @@ -1501,7 +1540,7 @@ static void qeth_get_linux_addrs_for_buf } } -static void qeth_read_in_buffer(qeth_card_t *card,int buffer_no) +static inline void qeth_read_in_buffer(qeth_card_t *card,int buffer_no) { struct sk_buff *skb; void *hdr_ptr; @@ -1643,7 +1682,7 @@ static void qeth_read_in_buffer(qeth_car } else { /* clear source MAC for security reasons */ memset(skb->mac.raw+ - QETH_FAKE_LL_DEST_MAC_POS,0, + QETH_FAKE_LL_SRC_MAC_POS,0, QETH_FAKE_LL_ADDR_LEN); } memcpy(skb->mac.raw+ @@ -1654,34 +1693,47 @@ static void qeth_read_in_buffer(qeth_car skb->mac.raw=skb->data; } - skb->ip_summed=card->options.checksum_type; if (card->options.checksum_type==HW_CHECKSUMMING) { /* do we have a checksummed packet? */ - if (*(__u8*)(hdr_ptr+11)& - QETH_EXT_HEADER_CSUM_TRANSP_REQ) { - /* skb->ip_summed is set already */ - /* vlan is not an issue here, it's still in + /* we only check for TCP/UDP checksums when the + * pseudo header was also checked sucessfully -- for + * the rest of the packets, it's not clear, whether + * the upper layer csum is alright. And they + * shouldn't occur too often anyway in real life */ + if ( (*(__u8*)(hdr_ptr+11)& + (QETH_EXT_HEADER_CSUM_HDR_REQ| + QETH_EXT_HEADER_CSUM_TRANSP_REQ)) == + (QETH_EXT_HEADER_CSUM_HDR_REQ| + QETH_EXT_HEADER_CSUM_TRANSP_REQ) ) { + /* csum does not need to be set + * inbound anyway + * + * vlan is not an issue here, it's still in * the QDIO header, not pushed in the - * skb yet */ + * skb yet * int ip_len=(skb->data[0]&0x0f)<<2; if (*(__u8*)(hdr_ptr+11)& QETH_EXT_HEADER_CSUM_TRANSP_FRAME_TYPE) { - /* get the UDP checksum */ + * get the UDP checksum * skb->csum=*(__u16*) (&skb->data[ip_len+ QETH_UDP_CSUM_OFFSET]); } else { - /* get the TCP checksum */ + * get the TCP checksum * skb->csum=*(__u16*) (&skb->data[ip_len+ QETH_TCP_CSUM_OFFSET]); } + */ + skb->ip_summed=CHECKSUM_UNNECESSARY; } else { /* make the stack check it */ - skb->ip_summed=SW_CHECKSUMMING; + skb->ip_summed=CHECKSUM_NONE; } + } else { + skb->ip_summed=card->options.checksum_type; } #ifdef QETH_VLAN @@ -1735,8 +1787,8 @@ static void qeth_read_in_buffer(qeth_car buffer_no]); } -static void qeth_fill_header(qeth_hdr_t *hdr,struct sk_buff *skb, - int version,int multicast) +static inline void qeth_fill_header(qeth_hdr_t *hdr,struct sk_buff *skb, + int version,int multicast) { #ifdef QETH_DBF_LIKE_HELL char dbf_text[15]; @@ -1750,14 +1802,17 @@ static void qeth_fill_header(qeth_hdr_t #ifdef QETH_VLAN /* before we're going to overwrite - this location with next hop ip - */ + * this location with next hop ip. + * v6 uses passthrough, v4 sets the tag in the QDIO header */ card = (qeth_card_t *)skb->dev->priv; if ((card->vlangrp != NULL) && - (version == 4) && vlan_tx_tag_present(skb)) { - hdr->ext_flags = QETH_EXT_HEADER_VLAN_FRAME; + if (version == 4) { + hdr->ext_flags = QETH_EXT_HEADER_VLAN_FRAME; + } else { + hdr->ext_flags = QETH_EXT_HEADER_INCLUDE_VLAN_TAG; + } hdr->vlan_id = vlan_tx_tag_get(skb); } #endif @@ -1820,7 +1875,13 @@ static void qeth_fill_header(qeth_hdr_t skb->dev->broadcast,6)) { /* broadcast? */ hdr->flags=QETH_CAST_BROADCAST|QETH_HEADER_PASSTHRU; } else { - hdr->flags=QETH_CAST_UNICAST|QETH_HEADER_PASSTHRU; + if (multicast==RTN_MULTICAST) { + hdr->flags=QETH_CAST_MULTICAST| + QETH_HEADER_PASSTHRU; + } else { + hdr->flags=QETH_CAST_UNICAST| + QETH_HEADER_PASSTHRU; + } } } #ifdef QETH_DBF_LIKE_HELL @@ -1836,7 +1897,7 @@ static void qeth_fill_header(qeth_hdr_t #endif /* QETH_DBF_LIKE_HELL */ } -static int inline qeth_fill_buffer(qdio_buffer_t *buffer,char *dataptr, +static inline int qeth_fill_buffer(qdio_buffer_t *buffer,char *dataptr, int length,int element) { int length_here; @@ -1891,8 +1952,8 @@ static int inline qeth_fill_buffer(qdio_ return element; } -static void qeth_flush_packed_packets(qeth_card_t *card,int queue, - int under_int) +static inline void qeth_flush_packed_packets(qeth_card_t *card,int queue, + int under_int) { qdio_buffer_t *buffer; int result; @@ -1951,8 +2012,23 @@ static void qeth_flush_packed_packets(qe * adapter honors it or not */ switch (card->send_state[queue]) { case SEND_STATE_DONT_PACK: + /* only request a PCI, if the fill level of the queue + * is close to the high watermark, so that we don't + * loose initiative during packing */ if (atomic_read(&card->outbound_used_buffers[queue]) last_pci_pos[queue]); + /* compensate queues that wrapped around */ + if (position_for_do_qdiooutbound_ringbuffer[queue]-> buffer[position_for_do_qdio].element[0].flags|=0x40; @@ -1966,13 +2042,13 @@ static void qeth_flush_packed_packets(qe * last_pci is the position of the last pci we've set * position_for_do_qdio is the position we will send out now * outbound_used_buffers is the number of buffers used (means - * all buffers hydra has, inclusive position_for_do_qdio) + * all buffers OSA has, inclusive position_for_do_qdio) * * we have to request a pci, if we have got the buffer of the * last_pci position back. * * position_for_do_qdio-outbound_used_buffers is the newest - * buffer that we got back from hydra + * buffer that we got back from OSA * * if this is greater or equal than the last_pci position, * we should request a pci, as no pci request is @@ -2055,8 +2131,8 @@ static inline int qeth_determine_send_er return ERROR_LINK_FAILURE; /* should never happen */ } -static void qeth_free_buffer(qeth_card_t *card,int queue,int bufno, - int qdio_error,int siga_error) +static inline void qeth_free_buffer(qeth_card_t *card,int queue,int bufno, + int qdio_error,int siga_error) { struct sk_buff *skb; int error; @@ -2139,7 +2215,8 @@ static void qeth_free_buffer(qeth_card_t case ERROR_LINK_FAILURE: case ERROR_KICK_THAT_PUPPY: QETH_DBF_TEXT4(0,trace,"endeglnd"); - dst_link_failure(skb); + card->stats->tx_dropped++; + card->stats->tx_errors++; atomic_dec(&skb->users); dev_kfree_skb_irq(skb); break; @@ -2164,7 +2241,7 @@ static void qeth_free_buffer(qeth_card_t card->send_retries[queue][bufno]=0; } -static void qeth_free_all_skbs(qeth_card_t *card) +static inline void qeth_free_all_skbs(qeth_card_t *card) { int q,b; @@ -2199,7 +2276,7 @@ static inline void qeth_flush_buffer(qet } #ifdef QETH_VLAN -void qeth_insert_ipv6_vlan_tag(struct sk_buff *__skb) +static inline void qeth_insert_ipv6_vlan_tag(struct sk_buff *__skb) { /* Move the mac addresses to the beginning of the new header. @@ -2230,9 +2307,9 @@ void qeth_insert_ipv6_vlan_tag(struct sk -static void qeth_send_packet_fast(qeth_card_t *card,struct sk_buff *skb, - struct net_device *dev, - int queue,int version,int multicast) +static inline void qeth_send_packet_fast(qeth_card_t *card,struct sk_buff *skb, + struct net_device *dev, + int queue,int version,int multicast) { qeth_ringbuffer_element_t *mybuffer; int position; @@ -2250,8 +2327,8 @@ static void qeth_send_packet_fast(qeth_c if ((version)&&(!card->realloc_message)) { card->realloc_message=1; PRINT_WARN("%s: not enough headroom in skb. " \ - "Try increasing the " \ - "add_hhlen parameter by %i.\n", + "Increasing the " \ + "add_hhlen parameter by %i may help.\n", card->dev_name, QETH_HEADER_SIZE-skb_headroom(skb)); } @@ -2327,9 +2404,11 @@ static void qeth_send_packet_fast(qeth_c /* no checks, if all elements are used, as then we would not be here (at most 127 buffers are enqueued) */ -static void qeth_send_packet_packed(qeth_card_t *card,struct sk_buff *skb, - struct net_device *dev, - int queue,int version,int multicast) +static inline void qeth_send_packet_packed(qeth_card_t *card, + struct sk_buff *skb, + struct net_device *dev, + int queue,int version, + int multicast) { qeth_ringbuffer_element_t *mybuffer; int elements_needed; @@ -2490,8 +2569,8 @@ static __inline__ int atomic_return_sub( return old_val; } -static int qeth_do_send_packet(qeth_card_t *card,struct sk_buff *skb, - struct net_device *dev) +static inline int qeth_do_send_packet(qeth_card_t *card,struct sk_buff *skb, + struct net_device *dev) { int queue,result=0; int multicast,version; @@ -2610,12 +2689,32 @@ static int qeth_hard_start_xmit(struct s qeth_card_t *card; char dbf_text[15]; int result; + unsigned long stackptr; card=(qeth_card_t*)(dev->priv); if (skb==NULL) return 0; +#ifdef CONFIG_ARCH_S390X + asm volatile ("lgr %0,15" : "=d" (stackptr)); +#else /* CONFIG_ARCH_S390X */ + asm volatile ("lr %0,15" : "=d" (stackptr)); +#endif /* CONFIG_ARCH_S390X */ + /* prevent stack overflows */ + /* normal and async stack is both 8k on s390 and 16k on s390x, + * so it doesn't matter whether we're in an interrupt */ + if ( (stackptr & STACK_PTR_MASK)< + (sizeof(struct task_struct) + WORST_CASE_STACK_USAGE) ) { + PRINT_ERR("delaying packet transmission " \ + "due to potential stack overflow\n"); + sprintf(dbf_text,"STOF%4x",card->irq0); + QETH_DBF_TEXT1(1,trace,dbf_text); + PRINT_ERR("Backtrace follows:\n"); + show_trace((unsigned long *)stackptr); + return -EBUSY; + } + #ifdef QETH_DBF_LIKE_HELL QETH_DBF_HEX4(0,data,skb->data,__max(QETH_DBF_DATA_LEN,skb->len)); #endif /* QETH_DBF_LIKE_HELL */ @@ -2624,7 +2723,8 @@ static int qeth_hard_start_xmit(struct s if (!card) { QETH_DBF_TEXT2(0,trace,"XMNSNOCD"); - dst_link_failure(skb); + card->stats->tx_dropped++; + card->stats->tx_errors++; dev_kfree_skb_irq(skb); return 0; } @@ -2637,11 +2737,29 @@ static int qeth_hard_start_xmit(struct s card->stats->tx_carrier_errors++; sprintf(dbf_text,"XMNS%4x",card->irq0); QETH_DBF_TEXT2(0,trace,dbf_text); - dst_link_failure(skb); + card->stats->tx_dropped++; + card->stats->tx_errors++; dev_kfree_skb_irq(skb); return 0; } + if (dev->hard_header == qeth_fake_header) { + /* + * in theory, if we run in undef-ed QETH_IPV6, we should + * always unshare, because we do skb_push, then overwrite + * that place with OSA header in qeth_send_packet_fast(). + * But it is only visible to one application - tcpdump. + * Nobody else cares if (fake) MAC header gets smashed. + * So, we only do it if fake_ll is in effect. + */ + if ((skb = qeth_pskb_unshare(skb, GFP_ATOMIC)) == NULL) { + card->stats->tx_dropped++; + dev_kfree_skb_irq(skb); + return 0; + } + skb_pull(skb, QETH_FAKE_LL_LEN); + } + result=qeth_do_send_packet(card,skb,dev); if (!result) @@ -2650,6 +2768,36 @@ static int qeth_hard_start_xmit(struct s return result; } +/* + * This function is needed to tell af_packet.c to process headers. + * It is not called from there, but only from the transmit path, + * when we do not need any actual header. + * + * N.B. Why do we insist on kludging here instead of fixing tcpdump? + * Because tcpdump is shared among gazillions of platforms, and + * there is a) no reliable way to identify qeth or its packets + * in pcap-linux.c (sll->sll_halen is the only hope); b) no easy + * way to pass this information from libpcap to tcpdump proper. + * + * XXX This fails with TR: traffic flows ok, but tcpdump remains confused. + */ +int qeth_fake_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, + unsigned len) +{ + unsigned char *hdr; + + hdr = skb_push(skb, QETH_FAKE_LL_LEN); + memcpy(hdr, "FAKELLFAKELL", ETH_ALEN*2); + if (type != ETH_P_802_3) + *(u16 *)(hdr + ETH_ALEN*2) = htons(type); + else + *(u16 *)(hdr + ETH_ALEN*2) = htons(len); + + /* XXX Maybe dev->hard_header_len here? Then skb_pull by same size. */ + return QETH_FAKE_LL_LEN; +} + static struct net_device_stats* qeth_get_stats(struct net_device *dev) { qeth_card_t *card; @@ -2803,23 +2951,19 @@ static int qeth_sleepon_ioctl(qeth_card_ return retval; } -static void qeth_wakeup_procfile(void) -{ - QETH_DBF_TEXT5(0,trace,"procwkup"); - if (atomic_read(&qeth_procfile_ioctl_sem.count)< - PROCFILE_SLEEP_SEM_MAX_VALUE) - up(&qeth_procfile_ioctl_sem); -} - - -static int qeth_sleepon_procfile(void) +static void qeth_snmp_notify(void) { - QETH_DBF_TEXT5(0,trace,"procslp"); - if (down_interruptible(&qeth_procfile_ioctl_sem)) { - up(&qeth_procfile_ioctl_sem); - return -ERESTARTSYS; + /*notify all registered processes */ + struct list_head *l; + struct qeth_notify_list *n_entry; + + QETH_DBF_TEXT5(0,trace,"snmpnoti"); + spin_lock(¬ify_lock); + list_for_each(l, ¬ify_list) { + n_entry = list_entry(l, struct qeth_notify_list, list); + send_sig(n_entry->signum, n_entry->task, 1); } - return 0; + spin_unlock(¬ify_lock); } static char* qeth_send_control_data(qeth_card_t *card,unsigned char *buffer, @@ -2889,17 +3033,19 @@ again: QETH_DBF_TEXT2(0,trace,"scd:doio"); sprintf(dbf_text,"%4x",(__s16)result); QETH_DBF_TEXT2(0,trace,dbf_text); + /* re-enable qeth_send_control_data again */ + atomic_set(&card->write_busy,0); return NULL; } if (intparam==IPA_IOCTL_STATE) { if (qeth_sleepon_ioctl(card,QETH_IPA_TIMEOUT)) { - QETH_DBF_TEXT2(0,trace,"scd:ioctime"); + QETH_DBF_TEXT2(0,trace,"scd:ioct"); /* re-enable qeth_send_control_data again */ atomic_set(&card->write_busy,0); return NULL; } - rec_buf=card->ipa_buf; + rec_buf=card->dma_stuff->recbuf; sprintf(dbf_text,"scro%4x",card->irq0); } else { if (qeth_sleepon(card,(setip)?QETH_IPA_TIMEOUT: @@ -2963,6 +3109,15 @@ static int qeth_send_ipa_cmd(qeth_card_t if ((ipa_cmd==IPA_CMD_SETADAPTERPARMS)&&(result==0)) { result=reply->data.setadapterparms.return_code; } + if ( (ipa_cmd==IPA_CMD_SETASSPARMS) && + (result==0) && + (reply->data.setassparms.assist_no== + IPA_INBOUND_CHECKSUM) && + (reply->data.setassparms.command_code== + IPA_CMD_ASS_START) ) { + card->csum_enable_mask= + reply->data.setassparms.data.flags_32bit; + } } return result; } @@ -3183,6 +3338,18 @@ static int qeth_ioctl_handle_snmp_data(q static int qeth_ioctl_handle_arp_data(qeth_card_t *card, arp_cmd_t *reply) { + if ( (reply->data.setassparms.command_code== + IPA_CMD_ASS_ARP_SET_NO_ENTRIES) || + (reply->data.setassparms.command_code== + IPA_CMD_ASS_ARP_ADD_ENTRY) || + (reply->data.setassparms.command_code== + IPA_CMD_ASS_ARP_REMOVE_ENTRY) ) { + if (reply->data.setassparms.return_code) { + return ARP_RETURNCODE_ERROR; + } else { + return ARP_RETURNCODE_LASTREPLY; + } + } if (reply->data.setassparms.seq_no == 1) { if (card->ioctl_buffersize <= (sizeof(__u16) + sizeof(int) + reply->data. @@ -3229,6 +3396,21 @@ static int qeth_ioctl_handle_arp_data(qe } return card->ioctl_returncode; } +static int qeth_is_arp_command(int cmd) +{ + switch (cmd) { + case IPA_CMD_ASS_ARP_SET_NO_ENTRIES: + case IPA_CMD_ASS_ARP_QUERY_CACHE: + case IPA_CMD_ASS_ARP_ADD_ENTRY: + case IPA_CMD_ASS_ARP_REMOVE_ENTRY: + case IPA_CMD_ASS_ARP_FLUSH_CACHE: + case IPA_CMD_ASS_ARP_QUERY_INFO: + case IPA_CMD_ASS_ARP_QUERY_STATS: + return 1; + default: + return 0; + } +} static int qeth_look_for_arp_data(qeth_card_t *card) { @@ -3245,9 +3427,7 @@ static int qeth_look_for_arp_data(qeth_c result=ARP_FLUSH; } else if ( (reply->command == IPA_CMD_SETASSPARMS) && (reply->data.setassparms.assist_no == IPA_ARP_PROCESSING) && - (reply->data.setassparms.command_code == - IPA_CMD_ASS_ARP_QUERY_INFO) && - (card->ioctl_returncode == ARP_RETURNCODE_SUCCESS)) { + (qeth_is_arp_command(reply->data.setassparms.command_code)) ) { result = qeth_ioctl_handle_arp_data(card,reply); } else if ( (reply->command == IPA_CMD_SETADAPTERPARMS) && (reply->data.setadapterparms.command_code == @@ -3305,8 +3485,9 @@ static int qeth_queryarp(qeth_card_t *ca result = IPA_REPLY_SUCCESS; memcpy(((char *)(card->ioctl_data_buffer)) + sizeof(__u16), &(card->number_of_entries),sizeof(int)); - copy_to_user(req->ifr_ifru.ifru_data, - card->ioctl_data_buffer,data_size); + if (copy_to_user(req->ifr_ifru.ifru_data, + card->ioctl_data_buffer,data_size)) + result =-EFAULT; } card->ioctl_buffer_pointer = NULL; vfree(card->ioctl_data_buffer); @@ -3373,16 +3554,14 @@ static int qeth_send_snmp_control(qeth_c result = IPA_REPLY_FAILED; goto snmp_out; } - if (result == ARP_RETURNCODE_ERROR ) { - copy_to_user(req->ifr_ifru.ifru_data+SNMP_REQUEST_DATA_OFFSET, - card->ioctl_data_buffer,card->ioctl_buffersize); + if (result == ARP_RETURNCODE_ERROR ) result = IPA_REPLY_FAILED; - } - else { - copy_to_user(req->ifr_ifru.ifru_data+SNMP_REQUEST_DATA_OFFSET, - card->ioctl_data_buffer,card->ioctl_buffersize); + else result = IPA_REPLY_SUCCESS; - } + + if (copy_to_user(req->ifr_ifru.ifru_data + SNMP_REQUEST_DATA_OFFSET, + card->ioctl_data_buffer, card->ioctl_buffersize)) + result = -EFAULT; snmp_out: card->number_of_entries = 0; card->ioctl_buffersize = 0; @@ -3571,6 +3750,11 @@ static int qeth_send_setdelipm(qeth_card (result==0xe00e)?"unsupported arp assist cmd": \ (result==0xe00f)?"arp assist not enabled": \ (result==0xe080)?"startlan disabled": \ + (result==0xf012)?"unicast IP address invalid": \ + (result==0xf013)?"multicast router limit reached": \ + (result==0xf014)?"stop assist not supported": \ + (result==0xf015)?"multicast assist not set": \ + (result==0xf080)?"VM: startlan disabled": \ (result==-1)?"IPA communication timeout": \ "unknown return code") @@ -3612,7 +3796,8 @@ retry: QETH_DBF_TEXT2(0,trace,dbf_text); } - if (((result==-1)||(result==0xe080))&&(retries--)) { + if ( ((result==-1)||(result==0xe080)||(result==0xf080))&& + (retries--) ) { sprintf(dbf_text,"sipr%4x",card->irq0); QETH_DBF_TEXT2(0,trace,dbf_text); if (ip_vers==4) { @@ -3771,8 +3956,8 @@ static void qeth_set_vipas(qeth_card_t * le is last entry */ char dbf_text[15]; int result; - __u8 netmask[16]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; + __u8 netmask[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; qeth_vipa_entry_t *priv_add_list=NULL; qeth_vipa_entry_t *priv_del_list=NULL; @@ -3790,6 +3975,7 @@ static void qeth_set_vipas(qeth_card_t * GFP_KERNEL); if (ne) { ne->version=e->version; + ne->flag=e->flag; memcpy(ne->ip,e->ip,16); ne->next=priv_add_list; priv_add_list=ne; @@ -3821,6 +4007,7 @@ static void qeth_set_vipas(qeth_card_t * GFP_KERNEL); if (ne) { ne->version=e->version; + ne->flag=e->flag; memcpy(ne->ip,e->ip,16); ne->next=priv_del_list; priv_del_list=ne; @@ -3852,7 +4039,7 @@ static void qeth_set_vipas(qeth_card_t * sprintf(dbf_text,"%4x%4x",card->irq0,result); QETH_DBF_TEXT2(0,trace,dbf_text); if (priv_add_list->version==4) { - PRINT_ERR("going to leave vipa/rxip %08x" \ + PRINT_ERR("going to leave vipa/rxip x%08x " \ "unset...\n", *((__u32*)&priv_add_list->ip[0])); sprintf(dbf_text,"%08x", @@ -4404,9 +4591,12 @@ static void qeth_clone_ifa6(struct inet6 } #endif /* QETH_IPV6 */ + + #define QETH_STANDARD_RETVALS \ ret_val=-EIO; \ if (result==IPA_REPLY_SUCCESS) ret_val=0; \ + if (result==-EFAULT) ret_val=-EFAULT; \ if (result==IPA_REPLY_FAILED) ret_val=-EIO; \ if (result==IPA_REPLY_OPNOTSUPP) ret_val=-EOPNOTSUPP @@ -4429,7 +4619,14 @@ static int qeth_do_ioctl(struct net_devi if ((cmdSIOCDEVPRIVATE+5)) return -EOPNOTSUPP; - copy_from_user(buff,rq->ifr_ifru.ifru_data,sizeof(buff)); + if (copy_from_user(buff,rq->ifr_ifru.ifru_data,sizeof(buff))) + return -EFAULT; + data=buff; + + if ((cmdSIOCDEVPRIVATE+5)) + return -EOPNOTSUPP; + if (copy_from_user(buff,rq->ifr_ifru.ifru_data,sizeof(buff))) + return -EFAULT; data=buff; if ( (!atomic_read(&card->is_registered))|| @@ -4438,9 +4635,14 @@ static int qeth_do_ioctl(struct net_devi if (atomic_read(&card->shutdown_phase)) return -ENODEV; - my_spin_lock(&card->ioctl_lock); + if (down_interruptible ( &card->ioctl_sem ) ) + return -ERESTARTSYS; + + if (atomic_read(&card->shutdown_phase)) { + ret_val=-ENODEV; + goto out; + } - if (atomic_read(&card->shutdown_phase)) return -ENODEV; if ( (!atomic_read(&card->is_registered))|| (!atomic_read(&card->is_hardsetup))|| (atomic_read(&card->is_gone)) ) { @@ -4486,7 +4688,7 @@ static int qeth_do_ioctl(struct net_devi ret_val=-EPERM; break; } - for (i=4;i<12;i++) if (data[i]) version=6; + for (i=12;i<24;i++) if (data[i]) version=6; result=qeth_send_setassparms(card,version,IPA_ARP_PROCESSING, IPA_CMD_ASS_ARP_REMOVE_ENTRY, (long)data,16); @@ -4503,17 +4705,26 @@ static int qeth_do_ioctl(struct net_devi QETH_STANDARD_RETVALS; break; case SIOCDEVPRIVATE+5: - result=qeth_send_snmp_control(card,rq,IPA_CMD_SETADAPTERPARMS, + result=qeth_send_snmp_control(card,rq, + IPA_CMD_SETADAPTERPARMS, IPA_SETADP_SET_SNMP_CONTROL, data,4); QETH_STANDARD_RETVALS; break; + case SIOCDEVPRIVATE+6: + if (!card->is_guest_lan && + (card->type == QETH_CARD_TYPE_OSAE)) + ret_val = 1; + else + ret_val = 0; + break; default: - return -EOPNOTSUPP; + ret_val=-EOPNOTSUPP; + goto out; } out: - my_spin_unlock(&card->ioctl_lock); + up (&card->ioctl_sem); sprintf(dbf_text,"ret=%4x",ret_val); QETH_DBF_TEXT2(0,trace,dbf_text); @@ -5240,13 +5451,17 @@ static int qeth_softsetup_card(qeth_card "failure -- please check the " \ "network, plug in the cable or " \ "enable the OSA port": + (result==0xf080)? + "startlan disabled (VM: LAN " \ + "is offline for functions " \ + "requiring LAN access.": "unknown return code"); sprintf(dbf_text,"stln%4x",result); QETH_DBF_TEXT2(0,trace,dbf_text); atomic_set(&card->is_softsetup,0); atomic_set(&card->is_startlaned,0); /* do not return an error */ - if (result==0xe080) { + if ((result==0xe080)||(result==0xf080)) { result=0; } goto out; @@ -5372,7 +5587,8 @@ static int qeth_softsetup_card(qeth_card QETH_DBF_TEXT2(0,trace,dbf_text); atomic_set(&card->is_softsetup,0); /* do not return an error */ - if (result==0xe080) { + if ((result==0xe080)|| + (result==0xf080)) { result=0; } goto out; @@ -5390,8 +5606,9 @@ static int qeth_softsetup_card(qeth_card goto out; } - sprintf(dbf_text,"%4x%4x",card->ipa6_supported, - card->ipa6_enabled); + sprintf(dbf_text,"%8x",card->ipa6_supported); + QETH_DBF_TEXT2(0,trace,dbf_text); + sprintf(dbf_text,"%8x",card->ipa6_enabled); QETH_DBF_TEXT2(0,trace,dbf_text); QETH_DBF_TEXT2(0,trace,"enaipv46"); result=qeth_send_setassparms_simple_with_data( @@ -5461,8 +5678,19 @@ static int qeth_softsetup_card(qeth_card goto go_on_filt; } card->dev->flags|=IFF_BROADCAST; - card->broadcast_capable=1; + card->broadcast_capable=BROADCAST_WITH_ECHO; + result=qeth_send_setassparms_simple_with_data( + card,IPA_FILTERING,IPA_CMD_ASS_ENABLE,1); + sprintf(dbf_text,"Flt3%4x",result); + QETH_DBF_TEXT2(0,trace,dbf_text); + QETH_DBF_TEXT2(0,setup,dbf_text); + if (!result) { + PRINT_INFO("Broadcast packets will not be " \ + "echoed back on %s.\n", + card->dev_name); + card->broadcast_capable=BROADCAST_WITHOUT_ECHO; + } } go_on_filt: if (card->options.checksum_type==HW_CHECKSUMMING) { @@ -5494,7 +5722,7 @@ go_on_filt: result=qeth_send_setassparms_simple_with_data( card,IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_ENABLE, - IPA_CHECKSUM_ENABLE_MASK); + card->csum_enable_mask); if (result) { PRINT_WARN("Could not enable inbound " \ "checksumming on %s: " \ @@ -5571,7 +5799,14 @@ go_on_checksum: #ifdef QETH_IPV6 if (atomic_read(&card->enable_routing_attempts6)) { - if (card->options.routing_type6) { + /* for OSAs that can't do v6 multicast routing, we don't try */ + if ( (card->type==QETH_CARD_TYPE_OSAE) && + ( (card->options.routing_type6&ROUTER_MASK) == + MULTICAST_ROUTER) && + (!qeth_is_supported6(IPA_OSA_MC_ROUTER_AVAIL)) ) { + atomic_set(&card->enable_routing_attempts6,0); + atomic_set(&card->rt6fld,0); + } else if (card->options.routing_type6) { sprintf(dbf_text,"strtg6%2x", card->options.routing_type6); QETH_DBF_TEXT2(0,trace,dbf_text); @@ -5753,9 +5988,12 @@ static void qeth_recover(void *data) sprintf(dbf_text,"PROB%4x",i); QETH_DBF_TEXT2(0,trace,dbf_text); - PRINT_WARN("recovery was scheduled on irq 0x%x (%s) with " \ - "problem 0x%x\n", - card->irq0,card->dev_name,i); + if (i!=PROBLEM_TX_TIMEOUT) { + PRINT_WARN("recovery was scheduled on irq 0x%x (%s) with " \ + "problem 0x%x\n", + card->irq0,card->dev_name,i); + } + switch (i) { case PROBLEM_RECEIVED_IDX_TERMINATE: if (atomic_read(&card->in_recovery)) @@ -5802,7 +6040,7 @@ static void qeth_recover(void *data) } } -static void qeth_schedule_recovery(qeth_card_t *card) +static inline void qeth_schedule_recovery(qeth_card_t *card) { if (card) { INIT_LIST_HEAD(&card->tqueue.list); @@ -5920,6 +6158,9 @@ static void qeth_qdio_output_handler(int card=(qeth_card_t *)card_ptr; if (status&QDIO_STATUS_LOOK_FOR_ERROR) { + sbalf15=(card->outbound_ringbuffer[queue]->buffer[ + (first_element+count-1)& + QDIO_MAX_BUFFERS_PER_Q].element[15].flags)&0xff; if (status&QDIO_STATUS_ACTIVATE_CHECK_CONDITION) { problem=PROBLEM_ACTIVATE_CHECK_CONDITION; PRINT_WARN("activate queues on irq 0x%x: " \ @@ -5937,9 +6178,29 @@ static void qeth_qdio_output_handler(int qeth_schedule_recovery(card); goto out; } - sbalf15=(card->outbound_ringbuffer[queue]->buffer[ - (first_element+count-1)& - QDIO_MAX_BUFFERS_PER_Q].element[15].flags)&0xff; + if ( (siga_error==0x01) || + (siga_error==(0x02|QDIO_SIGA_ERROR_B_BIT_SET)) || + (siga_error==0x03) ) { + sprintf(dbf_text,"BS%4x%2x",card->irq0,queue); + QETH_DBF_TEXT2(0,trace,dbf_text); + QETH_DBF_TEXT2(0,qerr,dbf_text); + QETH_DBF_TEXT2(1,setup,dbf_text); + sprintf(dbf_text,"%2x%2x%2x%2x", + first_element+count-1, + siga_error,qdio_error,sbalf15); + QETH_DBF_TEXT2(1,trace,dbf_text); + QETH_DBF_TEXT2(1,qerr,dbf_text); + PRINT_ERR("Outbound queue x%x on irq x%x (%s); " \ + "errs: siga: x%x, qdio: x%x, flags15: " \ + "x%x. The device will be taken down.\n", + queue,card->irq0,card->dev_name, + siga_error,qdio_error,sbalf15); + netif_stop_queue(card->dev); + qeth_set_dev_flag_norunning(card); + atomic_set(&card->problem,PROBLEM_BAD_SIGA_RESULT); + qeth_schedule_recovery(card); + goto out; + } PRINT_STUPID("outbound qdio transfer error on irq %04x, " \ "queue=%i. qdio_error=0x%x (more than one: %c)," \ " siga_error=0x%x (more than one: %c), " \ @@ -5988,7 +6249,7 @@ static void qeth_qdio_output_handler(int (&card->outbound_used_buffers[queue])<= LOW_WATERMARK_PACK); /* first_element is the last buffer that we got back - * from hydra */ + * from OSA */ if (switch_state||last_pci_hit) { *((__u16*)(&dbf_text2[6]))=card->irq0; QETH_DBF_HEX3(0,trace,dbf_text2,QETH_DBF_TRACE_LEN); @@ -6010,6 +6271,14 @@ static void qeth_qdio_output_handler(int if (switch_state) card->send_state[queue]= SEND_STATE_DONT_PACK; + + /* reset the last_pci position to avoid + * races, when we get close to packing again + * immediately (in order to never loose + * a PCI) */ + atomic_set(&card->last_pci_pos[queue], + (-2*QDIO_MAX_BUFFERS_PER_Q)); + netif_wake_queue(card->dev); atomic_set(&card->outbound_ringbuffer_lock[ queue],QETH_LOCK_UNLOCKED); @@ -6137,8 +6406,9 @@ recover: goto wakeup_out; } - if (!IS_IPA(card->dma_stuff->recbuf)|| - IS_IPA_REPLY(card->dma_stuff->recbuf)) { + if ( (!IS_IPA(card->dma_stuff->recbuf))|| + (IS_IPA(card->dma_stuff->recbuf)&& + IS_IPA_REPLY(card->dma_stuff->recbuf)) ) { /* setup or unknown data */ result = qeth_look_for_arp_data(card); switch (result) { @@ -6870,6 +7140,10 @@ static int qeth_idx_activate_read(qeth_c card->portname_required= ((!QETH_IDX_NO_PORTNAME_REQUIRED(card->dma_stuff->recbuf))&& (card->type==QETH_CARD_TYPE_OSAE)); + /* however, as the portname indication of OSA is wrong, we have to + * do this: */ + card->portname_required=(card->type==QETH_CARD_TYPE_OSAE); + memcpy(&temp,QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->recbuf),2); if (temp!=qeth_peer_func_level(card->func_level)) { @@ -7220,12 +7494,17 @@ static int qeth_ulp_setup(qeth_card_t *c static int qeth_qdio_establish(qeth_card_t *card) { int result; - char adapter_area[15]; + char *adapter_area; char dbf_text[15]; void **input_array,**output_array,**ptr; int i,j; qdio_initialize_t init_data; + adapter_area=vmalloc(QDIO_MAX_BUFFERS_PER_Q*sizeof(char)); + if (!adapter_area) return -ENOMEM; + + memset(adapter_area,0,QDIO_MAX_BUFFERS_PER_Q*sizeof(char)); + adapter_area[0]=_ascebc['P']; adapter_area[1]=_ascebc['C']; adapter_area[2]=_ascebc['I']; @@ -7235,7 +7514,10 @@ static int qeth_qdio_establish(qeth_card *((unsigned int*)(&adapter_area[12]))=PCI_TIMER_VALUE; input_array=vmalloc(QDIO_MAX_BUFFERS_PER_Q*sizeof(void*)); - if (!input_array) return -ENOMEM; + if (!input_array) { + vfree(adapter_area); + return -ENOMEM; + } ptr=input_array; for (j=0;jno_queues); if (!output_array) { vfree(input_array); + vfree(adapter_area); return -ENOMEM; } ptr=output_array; @@ -7285,6 +7568,7 @@ static int qeth_qdio_establish(qeth_card vfree(input_array); vfree(output_array); + vfree(adapter_area); sprintf(dbf_text,"qde=%4i",result); QETH_DBF_TEXT3(0,trace,dbf_text); @@ -7388,6 +7672,51 @@ static int qeth_verify_card(qeth_card_t return result; } +static void qeth_correct_routing_status(qeth_card_t *card) +{ + if (card->type==QETH_CARD_TYPE_IQD) { + /* if it's not a mc router, it's no router */ + if ( (card->options.routing_type4 == PRIMARY_ROUTER) || + (card->options.routing_type4 == SECONDARY_ROUTER) +#ifdef QETH_IPV6 + || + (card->options.routing_type6 == PRIMARY_ROUTER) || + (card->options.routing_type6 == SECONDARY_ROUTER) +#endif /* QETH_IPV6 */ + ) { + PRINT_WARN("routing not applicable, reset " \ + "routing status.\n"); + card->options.routing_type4=NO_ROUTER; +#ifdef QETH_IPV6 + card->options.routing_type6=NO_ROUTER; +#endif /* QETH_IPV6 */ + } + card->options.do_prio_queueing=NO_PRIO_QUEUEING; + } else { + /* if it's a mc router, it's no router */ + if ( (((!qeth_is_supported(IPA_OSA_MC_ROUTER_AVAIL))&& + card->options.routing_type4 == MULTICAST_ROUTER)) || + (card->options.routing_type4 == PRIMARY_CONNECTOR) || + (card->options.routing_type4 == SECONDARY_CONNECTOR) +#ifdef QETH_IPV6 + || + (((!qeth_is_supported(IPA_OSA_MC_ROUTER_AVAIL))&& + card->options.routing_type6 == MULTICAST_ROUTER)) || + (card->options.routing_type6 == PRIMARY_CONNECTOR) || + (card->options.routing_type6 == SECONDARY_CONNECTOR) +#endif /* QETH_IPV6 */ + ) { + PRINT_WARN("routing not applicable, reset " \ + "routing status. (Did you mean " \ + "primary_router or secondary_router?)\n"); + card->options.routing_type4=NO_ROUTER; +#ifdef QETH_IPV6 + card->options.routing_type6=NO_ROUTER; +#endif /* QETH_IPV6 */ + } + } +} + #ifdef QETH_IPV6 extern struct neigh_table arp_tbl; int (*qeth_old_arp_constructor)(struct neighbour *); @@ -7567,6 +7896,8 @@ static int qeth_init_dev(struct net_devi (!(qeth_get_additional_dev_flags(card->type)&IFF_NOARP))? (qeth_get_hard_header(card->link_type)? qeth_hard_header:NULL): +#else /* QETH_IPV6 */ + (card->options.fake_ll==FAKE_LL)?qeth_fake_header: #endif /* QETH_IPV6 */ NULL; dev->header_cache_update= @@ -7600,7 +7931,7 @@ static int qeth_init_dev(struct net_devi qeth_send_qipassist(card,4);*/ /* that was the old place. one id. we need to make sure, that - * hydra knows about us going to use the same id again, so we + * OSA knows about us going to use the same id again, so we * do that in hardsetup_card every time qeth_get_unique_id(card);*/ @@ -7650,8 +7981,9 @@ static int qeth_get_unitaddr(qeth_card_t card->unit_addr2 = prcd[31]; card->cula = prcd[63]; /* Don't build queues with diag98 for VM guest lan. */ - card->do_pfix = (MACHINE_HAS_PFIX) ? ((prcd[0x10]!=_ascebc['V']) || - (prcd[0x11]!=_ascebc['M'])):0; + card->is_guest_lan= ((prcd[0x10]==_ascebc['V']) && + (prcd[0x11]==_ascebc['M'])); + card->do_pfix = (MACHINE_HAS_PFIX) ? (!(card->is_guest_lan)):0; sprintf(dbf_text,"chpid:%02x",card->chpid); QETH_DBF_TEXT2(0,trace,dbf_text); @@ -8041,8 +8373,12 @@ static int qeth_hardsetup_card(qeth_card QETH_DBF_TEXT2(0,trace,dbf_text); } - sprintf(dbf_text,"%4x%4x",card->ipa_supported,card->ipa_enabled); + sprintf(dbf_text,"%8x",card->ipa_supported); QETH_DBF_TEXT2(0,trace,dbf_text); + sprintf(dbf_text,"%8x",card->ipa_enabled); + QETH_DBF_TEXT2(0,trace,dbf_text); + + qeth_correct_routing_status(card); qeth_get_unique_id(card); @@ -8094,7 +8430,8 @@ static int qeth_hardsetup_card(qeth_card "card%s%s%s\n" \ "with link type %s (portname: %s)\n", card->devno0,card->devno1,card->devno2, - qeth_get_cardname(card->type), + qeth_get_cardname(card->type, + card->is_guest_lan), (card->level[0])?" (level: ":"", (card->level[0])?card->level:"", (card->level[0])?")":"", @@ -8102,16 +8439,32 @@ static int qeth_hardsetup_card(qeth_card card->link_type), dbf_text); } else { - printk("qeth: Device 0x%X/0x%X/0x%X is a%s " \ - "card%s%s%s\nwith link type %s " \ - "(no portname needed by interface)\n", - card->devno0,card->devno1,card->devno2, - qeth_get_cardname(card->type), - (card->level[0])?" (level: ":"", - (card->level[0])?card->level:"", - (card->level[0])?")":"", - qeth_get_link_type_name(card->type, - card->link_type)); + if (card->options.portname[0]) { + printk("qeth: Device 0x%X/0x%X/0x%X is a%s " \ + "card%s%s%s\nwith link type %s " \ + "(no portname needed by interface)\n", + card->devno0,card->devno1,card->devno2, + qeth_get_cardname(card->type, + card->is_guest_lan), + (card->level[0])?" (level: ":"", + (card->level[0])?card->level:"", + (card->level[0])?")":"", + qeth_get_link_type_name(card->type, + card-> + link_type)); + } else { + printk("qeth: Device 0x%X/0x%X/0x%X is a%s " \ + "card%s%s%s\nwith link type %s\n", + card->devno0,card->devno1,card->devno2, + qeth_get_cardname(card->type, + card->is_guest_lan), + (card->level[0])?" (level: ":"", + (card->level[0])?card->level:"", + (card->level[0])?")":"", + qeth_get_link_type_name(card->type, + card-> + link_type)); + } } } @@ -8210,7 +8563,7 @@ static int qeth_reinit_thread(void *para atomic_set(&card->is_startlaned,0); /* show status in /proc/qeth */ atomic_set(&card->is_gone,1); - qeth_wakeup_procfile(); + qeth_snmp_notify(); } else { QETH_DBF_TEXT1(0,trace,"ri-sftst"); qeth_softsetup_card(card,QETH_LOCK_ALREADY_HELD); @@ -8223,7 +8576,7 @@ static int qeth_reinit_thread(void *para qeth_restore_dev_flag_state(card); atomic_set(&card->is_gone,0); netif_wake_queue(card->dev); - qeth_wakeup_procfile(); + qeth_snmp_notify(); } my_spin_unlock(&setup_lock); } @@ -8324,7 +8677,8 @@ static qeth_card_t *qeth_alloc_card(void spin_lock_init(&card->wait_q_lock); spin_lock_init(&card->softsetup_lock); spin_lock_init(&card->hardsetup_lock); - spin_lock_init(&card->ioctl_lock); + sema_init(&card->ioctl_sem, 1); + #ifdef QETH_VLAN spin_lock_init(&card->vlan_lock); card->vlangrp = NULL; @@ -8346,6 +8700,8 @@ static qeth_card_t *qeth_alloc_card(void card->ip_mc_new_state.ipm6_ifa=NULL; #endif /* QETH_IPV6 */ + card->csum_enable_mask=IPA_CHECKSUM_DEFAULT_ENABLE_MASK; + /* setup net_device stuff */ card->dev->priv=card; @@ -8819,7 +9175,7 @@ static void qeth_detach_handler(int irq, if ((card=qeth_get_card_by_irq(irq))) { qeth_remove_card(card,remove_method); } - qeth_wakeup_procfile(); + qeth_snmp_notify(); my_spin_unlock(&setup_lock); } @@ -8905,49 +9261,6 @@ static int qeth_get_bufcnt_from_memamnt( return cnt; } -static void qeth_correct_routing_status(qeth_card_t *card) -{ - if (card->type==QETH_CARD_TYPE_IQD) { - /* if it's not a mc router, it's no router */ - if ( (card->options.routing_type4 == PRIMARY_ROUTER) || - (card->options.routing_type4 == SECONDARY_ROUTER) -#ifdef QETH_IPV6 - || - (card->options.routing_type6 == PRIMARY_ROUTER) || - (card->options.routing_type6 == SECONDARY_ROUTER) -#endif /* QETH_IPV6 */ - ) { - PRINT_WARN("routing not applicable, reset " \ - "routing status.\n"); - card->options.routing_type4=NO_ROUTER; -#ifdef QETH_IPV6 - card->options.routing_type6=NO_ROUTER; -#endif /* QETH_IPV6 */ - } - card->options.do_prio_queueing=NO_PRIO_QUEUEING; - } else { - /* if it's a mc router, it's no router */ - if ( (card->options.routing_type4 == MULTICAST_ROUTER) || - (card->options.routing_type4 == PRIMARY_CONNECTOR) || - (card->options.routing_type4 == SECONDARY_CONNECTOR) -#ifdef QETH_IPV6 - || - (card->options.routing_type6 == MULTICAST_ROUTER) || - (card->options.routing_type6 == PRIMARY_CONNECTOR) || - (card->options.routing_type6 == SECONDARY_CONNECTOR) -#endif /* QETH_IPV6 */ - ) { - PRINT_WARN("routing not applicable, reset " \ - "routing status. (Did you mean " \ - "primary_router or secondary_router?)\n"); - card->options.routing_type4=NO_ROUTER; -#ifdef QETH_IPV6 - card->options.routing_type6=NO_ROUTER; -#endif /* QETH_IPV6 */ - } - } -} - static int qeth_attach_handler(int irq_to_scan,chandev_probeinfo *probeinfo) { int result = 0; @@ -9102,7 +9415,6 @@ correct_order: goto endloop; } - qeth_correct_routing_status(card); qeth_insert_card_into_list(card); QETH_DBF_TEXT3(0,trace,"request0"); @@ -9247,7 +9559,7 @@ static void qeth_chandev_msck_notfunc(st /* means, we prevent looping in * qeth_send_control_data */ atomic_set(&card->write_busy,0); - qeth_wakeup_procfile(); + qeth_snmp_notify(); } my_read_unlock(&list_lock); } @@ -9297,7 +9609,7 @@ struct net_device *qeth_chandev_init_net card->tqueue_sst.sync=0; schedule_task(&card->tqueue_sst); out: - qeth_wakeup_procfile(); + qeth_snmp_notify(); return dev; } @@ -9385,11 +9697,10 @@ static int qeth_ip_event(struct notifier sprintf(dbf_text,"ipevent"); QETH_DBF_TEXT3(0,trace,dbf_text); QETH_DBF_HEX3(0,trace,&event,sizeof(unsigned long)); - QETH_DBF_HEX3(0,trace,&dev,sizeof(void*)); - sprintf(dbf_text,"%08x",ifa->ifa_address); - QETH_DBF_TEXT3(0,trace,dbf_text); - sprintf(dbf_text,"%08x",ifa->ifa_mask); - QETH_DBF_TEXT3(0,trace,dbf_text); + sprintf(dbf_text,"%08x",ifa->ifa_address); + QETH_DBF_TEXT3(0,trace,dbf_text); + sprintf(dbf_text,"%08x",ifa->ifa_mask); + QETH_DBF_TEXT3(0,trace,dbf_text); #ifdef QETH_VLAN if (qeth_verify_dev(dev)==QETH_VERIFY_IS_VLAN_DEV) @@ -9418,10 +9729,9 @@ static int qeth_ip6_event(struct notifie sprintf(dbf_text,"ip6event"); QETH_DBF_TEXT3(0,trace,dbf_text); QETH_DBF_HEX3(0,trace,&event,sizeof(unsigned long)); - QETH_DBF_HEX3(0,trace,&dev,sizeof(void*)); - QETH_DBF_HEX3(0,trace,ifa->addr.s6_addr,QETH_DBF_TRACE_LEN); - QETH_DBF_HEX3(0,trace,ifa->addr.s6_addr+QETH_DBF_TRACE_LEN, - QETH_DBF_TRACE_LEN); + QETH_DBF_HEX3(0,trace,ifa->addr.s6_addr,QETH_DBF_TRACE_LEN); + QETH_DBF_HEX3(0,trace,ifa->addr.s6_addr+QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); #ifdef QETH_VLAN if (qeth_verify_dev(dev)==QETH_VERIFY_IS_VLAN_DEV) @@ -9438,8 +9748,63 @@ static int qeth_ip6_event(struct notifie return NOTIFY_DONE; } + +static int +qeth_multicast6_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + qeth_card_t *card; + struct ifmcaddr6 *mc = (struct ifmcaddr6 *) ptr; + struct net_device *dev = mc->idev->dev; + char dbf_text[15]; + + sprintf(dbf_text,"mc6event"); + QETH_DBF_TEXT3(0,trace,dbf_text); + QETH_DBF_HEX3(0,trace,&event,sizeof(unsigned long)); +#ifdef QETH_VLAN + if (qeth_verify_dev(dev)==QETH_VERIFY_IS_VLAN_DEV) + card = (qeth_card_t *)VLAN_DEV_INFO(dev)->real_dev->priv; + else +#endif + card=(qeth_card_t *)dev->priv; + if (qeth_does_card_exist(card)) { + QETH_DBF_HEX3(0,trace,&card,sizeof(void*)); + qeth_save_dev_flag_state(card); + qeth_start_softsetup_thread(card); + } + + return NOTIFY_DONE; +} + #endif /* QETH_IPV6 */ +static int +qeth_multicast_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + qeth_card_t *card; + struct ip_mc_list *mc = (struct ip_mc_list *) ptr; + struct net_device *dev = mc->interface->dev; + char dbf_text[15]; + + sprintf(dbf_text,"mc4event"); + QETH_DBF_TEXT3(0,trace,dbf_text); + QETH_DBF_HEX3(0,trace,&event,sizeof(unsigned long)); +#ifdef QETH_VLAN + if (qeth_verify_dev(dev)==QETH_VERIFY_IS_VLAN_DEV) + card = (qeth_card_t *)VLAN_DEV_INFO(dev)->real_dev->priv; + else +#endif + card=(qeth_card_t *)dev->priv; + if (qeth_does_card_exist(card)) { + QETH_DBF_HEX3(0,trace,&card,sizeof(void*)); + qeth_save_dev_flag_state(card); + qeth_start_softsetup_thread(card); + } + + return NOTIFY_DONE; +} + static int qeth_reboot_event(struct notifier_block *this, unsigned long event,void *ptr) { @@ -9533,9 +9898,11 @@ static int qeth_procfile_open(struct ino int size; tempinfo_t *info; + MOD_INC_USE_COUNT; info = (tempinfo_t *) vmalloc (sizeof (tempinfo_t)); if (info == NULL) { PRINT_WARN("No memory available for data\n"); + MOD_DEC_USE_COUNT; return -ENOMEM; } else { file->private_data = (void *) info; @@ -9556,6 +9923,7 @@ static int qeth_procfile_open(struct ino PRINT_WARN("No memory available for data\n"); vfree (info); rc=-ENOMEM; + MOD_DEC_USE_COUNT; goto out; } @@ -9583,23 +9951,23 @@ static int qeth_procfile_open(struct ino "by_ToS"); } + /* a '+' in the routing indicator means, that broadcast + * packets are not echoed back to the sender */ #ifdef QETH_IPV6 - if (atomic_read(&card->rt4fld) && - atomic_read(&card->rt6fld)) - strcpy(router_str, "no"); - else if (atomic_read(&card->rt4fld) || - atomic_read(&card->rt6fld)) - strcpy(router_str, "mix"); + if (atomic_read(&card->rt4fld) || + atomic_read(&card->rt6fld)) + strcpy(router_str, "FLD"); #else /* QETH_IPV6 */ if (atomic_read(&card->rt4fld)) - strcpy(router_str, "no"); + strcpy(router_str, "FLD"); #endif /* QETH_IPV6 */ else if ( ((card->options.routing_type4&ROUTER_MASK)== PRIMARY_ROUTER) #ifdef QETH_IPV6 && - ((card->options.routing_type6&ROUTER_MASK)== - PRIMARY_ROUTER) + ( ((card->options.routing_type6&ROUTER_MASK)== + PRIMARY_ROUTER)|| + (!qeth_is_supported(IPA_IPv6)) ) #endif /* QETH_IPV6 */ ) { strcpy(router_str,"pri"); @@ -9608,8 +9976,9 @@ static int qeth_procfile_open(struct ino SECONDARY_ROUTER) #ifdef QETH_IPV6 && - ((card->options.routing_type6&ROUTER_MASK)== - SECONDARY_ROUTER) + ( ((card->options.routing_type6&ROUTER_MASK)== + SECONDARY_ROUTER)|| + (!qeth_is_supported(IPA_IPv6)) ) #endif /* QETH_IPV6 */ ) { strcpy(router_str,"sec"); @@ -9618,38 +9987,51 @@ static int qeth_procfile_open(struct ino MULTICAST_ROUTER) #ifdef QETH_IPV6 && - ((card->options.routing_type6&ROUTER_MASK)== - MULTICAST_ROUTER) + ( ((card->options.routing_type6&ROUTER_MASK)== + MULTICAST_ROUTER)|| + (!qeth_is_supported(IPA_IPv6)) ) #endif /* QETH_IPV6 */ ) { - strcpy(router_str,"mc"); + if (card->broadcast_capable==BROADCAST_WITHOUT_ECHO) + strcpy(router_str,"mc+"); + else + strcpy(router_str,"mc"); } else if ( ((card->options.routing_type4&ROUTER_MASK)== PRIMARY_CONNECTOR) #ifdef QETH_IPV6 && - ((card->options.routing_type6&ROUTER_MASK)== - PRIMARY_CONNECTOR) + ( ((card->options.routing_type6&ROUTER_MASK)== + PRIMARY_CONNECTOR)|| + (!qeth_is_supported(IPA_IPv6)) ) #endif /* QETH_IPV6 */ ) { - strcpy(router_str,"p.c"); + if (card->broadcast_capable==BROADCAST_WITHOUT_ECHO) + strcpy(router_str,"p+c"); + else + strcpy(router_str,"p.c"); } else if ( ((card->options.routing_type4&ROUTER_MASK)== SECONDARY_CONNECTOR) #ifdef QETH_IPV6 && - ((card->options.routing_type6&ROUTER_MASK)== - SECONDARY_CONNECTOR) + ( ((card->options.routing_type6&ROUTER_MASK)== + SECONDARY_CONNECTOR)|| + (!qeth_is_supported(IPA_IPv6)) ) #endif /* QETH_IPV6 */ ) { - strcpy(router_str,"s.c"); + if (card->broadcast_capable==BROADCAST_WITHOUT_ECHO) + strcpy(router_str,"s+c"); + else + strcpy(router_str,"s.c"); } else if ( ((card->options.routing_type4&ROUTER_MASK)== NO_ROUTER) #ifdef QETH_IPV6 && - ((card->options.routing_type6&ROUTER_MASK)== - NO_ROUTER) + ( ((card->options.routing_type6&ROUTER_MASK)== + NO_ROUTER)|| + (!qeth_is_supported(IPA_IPv6)) ) #endif /* QETH_IPV6 */ ) { strcpy(router_str,"no"); @@ -9670,7 +10052,8 @@ static int qeth_procfile_open(struct ino card->chpid, card->dev_name, qeth_get_cardname_short - (card->type,card->link_type), + (card->type,card->link_type, + card->is_guest_lan), card->options.portno); } else if (!atomic_read(&card->is_startlaned)) { length+=sprintf(buffer+length, @@ -9680,7 +10063,8 @@ static int qeth_procfile_open(struct ino card->chpid, card->dev_name, qeth_get_cardname_short - (card->type,card->link_type), + (card->type,card->link_type, + card->is_guest_lan), card->options.portno); } else { length+=sprintf(buffer+length, @@ -9689,7 +10073,8 @@ static int qeth_procfile_open(struct ino card->devno0,card->devno1,card->devno2, card->chpid,card->dev_name, qeth_get_cardname_short - (card->type,card->link_type), + (card->type,card->link_type, + card->is_guest_lan), card->options.portno, checksum_str, queueing_str,router_str,bufsize_str, @@ -10174,6 +10559,7 @@ static int qeth_ipato_procfile_open(stru int size; char entry_type[5]; + MOD_INC_USE_COUNT; info = (tempinfo_t *) vmalloc (sizeof (tempinfo_t)); if (info == NULL) { PRINT_WARN("No memory available for data\n"); @@ -10327,13 +10713,25 @@ static ssize_t qeth_procfile_read(struct static int qeth_procfile_release(struct inode *inode,struct file *file) { tempinfo_t *p_info = (tempinfo_t *) file->private_data; + struct list_head *l,*n; + struct qeth_notify_list *n_entry; if (p_info) { if (p_info->data) vfree (p_info->data); vfree (p_info); } - +/*remove task-entry to notify from list */ + spin_lock(¬ify_lock); + list_for_each_safe(l, n, ¬ify_list) { + n_entry = list_entry(l, struct qeth_notify_list, list); + if (n_entry->task == current) { + list_del(&n_entry->list); + kfree(n_entry); + } + } + spin_unlock(¬ify_lock); + MOD_DEC_USE_COUNT; return 0; } @@ -10481,118 +10879,35 @@ out: return user_len; } -static int qeth_procfile_getinterfaces(unsigned long arg) +static int qeth_snmp_register(struct task_struct *p, unsigned long arg) { - qeth_card_t *card; + struct qeth_notify_list *n_entry; + struct list_head *l; + QETH_DBF_TEXT5(0,trace,"snmpreg"); - char parms[16]; - char *buffer; - char *buffer_pointer; - __u32 version,valid_fields,qeth_version,number_of_devices,if_index; - __u32 data_size,data_len; - unsigned long ioctl_flags; - int result=0; + /*check first if entry already exists*/ - /* the struct of version 0 is: -typedef struct dev_list -{ - char device_name[IFNAME_MAXLEN]; // OSA-Exp device name (e.g. eth0) - __u32 if_index; // interface index from kernel - __u32 flags; // device charateristics -} __attribute__((packed)) DEV_LIST; - -typedef struct osaexp_dev_ver0 -{ - __u32 version; // structure version - __u32 valid_fields; // bitmask of fields that are really filled - __u32 qeth_version; // qeth driver version - __u32 number_of_devices; // number of OSA Express devices - struct dev_list devices[0]; // list of OSA Express devices -} __attribute__((packed)) OSAEXP_DEV_VER0; - */ - - version = 0; - valid_fields = 0; - qeth_version = 0; - number_of_devices= 0; - - copy_from_user((void*)parms,(void*)arg,sizeof(parms)); - memcpy(&data_size,parms,sizeof(__u32)); - - if ( !(data_size > 0) ) - return -EFAULT; - if ( data_size > IOCTL_MAX_TRANSFER_SIZE ) - return -EFAULT; - if ( !access_ok(VERIFY_WRITE, (void *)arg, data_size) ) - return -EFAULT; - - my_read_lock(&list_lock); - card = firstcard; -#define IOCTL_USER_STRUCT_SIZE (DEV_NAME_LEN*sizeof(char)) + \ - sizeof(__u32) + sizeof(__u32) - while (card) { - if (card->type == QETH_CARD_TYPE_OSAE) - number_of_devices=number_of_devices + IOCTL_USER_STRUCT_SIZE; - card = card->next; - } -#undef IOCTL_USER_STRUCT_SIZE - if ((number_of_devices + 4*sizeof(__u32)) >= data_size) { - result=-ENOMEM; - goto out; - } + spin_lock(¬ify_lock); + list_for_each(l, ¬ify_list) { + n_entry = list_entry(l, struct qeth_notify_list, list); + if (n_entry->task == p) { + n_entry->signum = (int) arg; + goto reg_out; + } - number_of_devices=0; - card = firstcard; - buffer = (char *)vmalloc(data_size); - if (!buffer) { - result=-EFAULT; - goto out; } - buffer_pointer = ((char *)(buffer)) + (4*sizeof(__u32)) ; - while (card) { - if ((card->type == QETH_CARD_TYPE_OSAE)&& - (!atomic_read(&card->is_gone))&& - (atomic_read(&card->is_hardsetup))&& - (atomic_read(&card->is_registered))) { - - memcpy(buffer_pointer,card->dev_name,DEV_NAME_LEN); - buffer_pointer = buffer_pointer + DEV_NAME_LEN; - if_index=card->dev->ifindex; - memcpy(buffer_pointer,&if_index,sizeof(__u32)); - buffer_pointer = buffer_pointer + sizeof(__u32); - memcpy(buffer_pointer,&ioctl_flags,sizeof(__u32)); - buffer_pointer = buffer_pointer + sizeof(__u32); - number_of_devices=number_of_devices+1; - } - card = card->next; - } - - /* we copy the real size */ - data_len=buffer_pointer-buffer; - - buffer_pointer = buffer; - /* copy the header information at the beginning of the buffer */ - memcpy(buffer_pointer,&version,sizeof(__u32)); - memcpy(((char *)buffer_pointer)+sizeof(__u32),&valid_fields, - sizeof(__u32)); - memcpy(((char *)buffer_pointer)+(2*sizeof(__u32)),&qeth_version, - sizeof(__u32)); - memcpy(((char *)buffer_pointer)+(3*sizeof(__u32)),&number_of_devices, - sizeof(__u32)); - copy_to_user((char *)arg,buffer,data_len); - vfree(buffer); -out: - my_read_unlock(&list_lock); - return result; - -#undef PARMS_BUFFERLENGTH - -}; - -static int qeth_procfile_interfacechanges(unsigned long arg) -{ - return qeth_sleepon_procfile(); - + spin_unlock(¬ify_lock); + n_entry = (struct qeth_notify_list *) + kmalloc(sizeof(struct qeth_notify_list),GFP_KERNEL); + if (!n_entry) + return -ENOMEM; + n_entry->task = p; + n_entry->signum = (int) arg; + spin_lock(¬ify_lock); + list_add(&n_entry->list,¬ify_list); +reg_out: + spin_unlock(¬ify_lock); + return 0; } static int qeth_procfile_ioctl(struct inode *inode, struct file *file, @@ -10600,19 +10915,17 @@ static int qeth_procfile_ioctl(struct in { int result; - down_interruptible(&qeth_procfile_ioctl_lock); - switch (cmd) { - case QETH_IOCPROC_OSAEINTERFACES: - result = qeth_procfile_getinterfaces(arg); - break; - case QETH_IOCPROC_INTERFACECHANGES: - result = qeth_procfile_interfacechanges(arg); + switch (cmd) { + case QETH_IOCPROC_REGISTER: + if ( (arg > 0) && (arg < 32) ) + result = qeth_snmp_register(current,arg); + else + result = -EINVAL; break; default: result = -EOPNOTSUPP; } - up(&qeth_procfile_ioctl_lock); return result; }; @@ -10644,10 +10957,6 @@ static void qeth_add_procfs_entries(void S_IFREG|0644,&proc_root); if (qeth_proc_file) { qeth_proc_file->proc_fops = &qeth_procfile_fops; - sema_init(&qeth_procfile_ioctl_sem, - PROCFILE_SLEEP_SEM_MAX_VALUE); - sema_init(&qeth_procfile_ioctl_lock, - PROCFILE_IOCTL_SEM_MAX_VALUE); } else proc_file_registration=-1; if (proc_file_registration) @@ -10796,7 +11105,11 @@ static int __init qeth_init(void) global_stay_in_mem = chandev_persist(chandev_type_qeth); #endif /* MODULE */ - spin_lock_init(&setup_lock); +/*SNMP init stuff*/ + spin_lock_init(¬ify_lock); + INIT_LIST_HEAD(¬ify_list); + + spin_lock_init(&setup_lock); spin_lock_init(&ipato_list_lock); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/qeth.h linux-2.4.28-pre3/drivers/s390/net/qeth.h --- linux-2.4.27/drivers/s390/net/qeth.h 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/net/qeth.h 2004-09-10 19:33:57.000000000 +0000 @@ -15,7 +15,7 @@ #define QETH_NAME " qeth" -#define VERSION_QETH_H "$Revision: 1.113 $" +#define VERSION_QETH_H "$Revision: 1.113.4.8 $" /******************** CONFIG STUFF ***********************/ //#define QETH_DBF_LIKE_HELL @@ -47,7 +47,7 @@ /********************* TUNING STUFF **************************/ #define HIGH_WATERMARK_PACK 5 #define LOW_WATERMARK_PACK 2 -#define WATERMARK_FUZZ 2 +#define WATERMARK_FUZZ 1 #define QETH_MAX_INPUT_THRESHOLD 500 #define QETH_MAX_OUTPUT_THRESHOLD 300 /* ? */ @@ -85,6 +85,22 @@ #define QETH_HARDSETUP_CLEAR_LAPS 3 #define QETH_RECOVERY_HARDSETUP_RETRY 2 +/* the worst case stack usage is: + * qeth_hard_start_xmit + * do_QDIO + * qeth_qdio_output_handler + * do_QDIO + * qeth_qdio_output_handler + * (no more recursion as we have called netif_stop_queue) + */ +#ifdef CONFIG_ARCH_S390X +#define STACK_PTR_MASK 0x3fff +#define WORST_CASE_STACK_USAGE 1100 +#else /* CONFIG_ARCH_S390X */ +#define STACK_PTR_MASK 0x1fff +#define WORST_CASE_STACK_USAGE 800 +#endif /* CONFIG_ARCH_S390X */ + /************************* DEBUG FACILITY STUFF *********************/ #define QETH_DBF_HEX(ex,name,level,addr,len) \ @@ -253,6 +269,12 @@ #define QETH_HEADER_PASSTHRU 0x10 #define QETH_HEADER_IPV6 0x80 +#define QETH_ETH_MAC_V4 0x0100 /* like v4 */ +#define QETH_ETH_MAC_V6 0x3333 /* like v6 */ +/* tr mc mac is longer, but that will be enough to detect mc frames */ +#define QETH_TR_MAC_NC 0xc000 /* non-canonical */ +#define QETH_TR_MAC_C 0x0300 /* canonical */ + #define QETH_CAST_FLAGS 0x07 #define QETH_CAST_UNICAST 6 #define QETH_CAST_MULTICAST 4 @@ -529,7 +551,7 @@ typedef struct sparebufs_t { #define QETH_FAKE_LL_ADDR_LEN ETH_ALEN /* 6 */ #define QETH_FAKE_LL_DEST_MAC_POS 0 #define QETH_FAKE_LL_SRC_MAC_POS 6 -#define QETH_FAKE_LL_SRC_MAC_POS_IN_QDIO_HDR 6 +#define QETH_FAKE_LL_SRC_MAC_POS_IN_QDIO_HDR 18 #define QETH_FAKE_LL_PROT_POS 12 #define QETH_FAKE_LL_V4_ADDR_POS 16 #define QETH_FAKE_LL_V6_ADDR_POS 24 @@ -603,7 +625,7 @@ typedef struct sparebufs_t { #define MULTICAST_ROUTER 3 #define PRIMARY_CONNECTOR 4 #define SECONDARY_CONNECTOR 5 -#define ROUTER_MASK 0xf /* used to remove SET_ROUTING_FLAG +#define ROUTER_MASK 0xf /* used to remove RESET_ROUTING_FLAG from routing_type */ #define RESET_ROUTING_FLAG 0x10 /* used to indicate, that setting the routing type is desired */ @@ -629,6 +651,9 @@ typedef struct sparebufs_t { #define QETH_DONT_WAIT_FOR_LOCK 1 #define QETH_LOCK_ALREADY_HELD 2 +#define BROADCAST_WITH_ECHO 1 +#define BROADCAST_WITHOUT_ECHO 2 + #define PROBLEM_CARD_HAS_STARTLANED 1 #define PROBLEM_RECEIVED_IDX_TERMINATE 2 #define PROBLEM_ACTIVATE_CHECK_CONDITION 3 @@ -782,6 +807,7 @@ typedef struct qeth_card_t { /* pointe __u8 link_type; + int is_guest_lan; int do_pfix; /* to avoid doing diag98 for vm guest lan devices */ /* inbound buffer management */ @@ -852,7 +878,7 @@ typedef struct qeth_card_t { /* pointe /* prevents deadlocks :-O */ spinlock_t softsetup_lock; spinlock_t hardsetup_lock; - spinlock_t ioctl_lock; + struct semaphore ioctl_sem; atomic_t softsetup_thread_is_running; struct semaphore softsetup_thread_sem; struct tq_struct tqueue_sst; @@ -907,6 +933,8 @@ typedef struct qeth_card_t { /* pointe __u32 ipa6_enabled; __u32 adp_supported; + __u32 csum_enable_mask; + atomic_t startlan_attempts; atomic_t enable_routing_attempts4; atomic_t rt4fld; @@ -1004,6 +1032,15 @@ typedef struct mydevreg_t { struct mydevreg_t *prev; } mydevreg_t; +/*user process notification stuff */ +spinlock_t notify_lock; +struct list_head notify_list; +struct qeth_notify_list { + struct list_head list; + struct task_struct *task; + int signum; +}; + inline static int qeth_get_arphrd_type(int cardtype,int linktype) { switch (cardtype) { @@ -1011,7 +1048,7 @@ inline static int qeth_get_arphrd_type(i case QETH_MPC_LINK_TYPE_LANE_TR: /* fallthrough */ case QETH_MPC_LINK_TYPE_HSTR: - return ARPHRD_IEEE802; + return ARPHRD_IEEE802_TR; default: return ARPHRD_ETHER; } case QETH_CARD_TYPE_IQD: return ARPHRD_ETHER; @@ -1036,22 +1073,33 @@ inline static __u8 qeth_get_adapter_type } } -inline static const char *qeth_get_cardname(int cardtype) +inline static const char *qeth_get_cardname(int cardtype,int is_guest_lan) { - switch (cardtype) { - case QETH_CARD_TYPE_UNKNOWN: return "n unknown"; - case QETH_CARD_TYPE_OSAE: return "n OSD Express"; - case QETH_CARD_TYPE_IQD: return " HiperSockets"; - default: return " strange"; + if (is_guest_lan) { + switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: return "n unknown"; + case QETH_CARD_TYPE_OSAE: return " Guest LAN QDIO"; + case QETH_CARD_TYPE_IQD: return " Guest LAN Hiper"; + default: return " strange"; + } + } else { + switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: return "n unknown"; + case QETH_CARD_TYPE_OSAE: return "n OSD Express"; + case QETH_CARD_TYPE_IQD: return " HiperSockets"; + default: return " strange"; + } } } /* max length to be returned: 14 */ -inline static const char *qeth_get_cardname_short(int cardtype,__u8 link_type) +inline static const char *qeth_get_cardname_short(int cardtype,__u8 link_type,int is_guest_lan) { switch (cardtype) { case QETH_CARD_TYPE_UNKNOWN: return "unknown"; - case QETH_CARD_TYPE_OSAE: switch (link_type) { + case QETH_CARD_TYPE_OSAE: if (is_guest_lan) + return "GuestLAN QDIO"; + switch (link_type) { case QETH_MPC_LINK_TYPE_FAST_ETHERNET: return "OSD_100"; case QETH_MPC_LINK_TYPE_HSTR: @@ -1068,7 +1116,7 @@ inline static const char *qeth_get_cardn return "OSD_ATM_LANE"; default: return "OSD_Express"; } - case QETH_CARD_TYPE_IQD: return "HiperSockets"; + case QETH_CARD_TYPE_IQD: return (is_guest_lan)?"GuestLAN Hiper":"HiperSockets"; default: return " strange"; } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/qeth_mpc.h linux-2.4.28-pre3/drivers/s390/net/qeth_mpc.h --- linux-2.4.27/drivers/s390/net/qeth_mpc.h 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/net/qeth_mpc.h 2004-09-10 19:34:53.000000000 +0000 @@ -11,7 +11,7 @@ #ifndef __QETH_MPC_H__ #define __QETH_MPC_H__ -#define VERSION_QETH_MPC_H "$Revision: 1.42 $" +#define VERSION_QETH_MPC_H "$Revision: 1.42.4.4 $" #define QETH_IPA_TIMEOUT (card->ipa_timeout) #define QETH_MPC_TIMEOUT 2000 @@ -288,6 +288,7 @@ static unsigned char DM_ACT[]={ #define IPA_PASSTHRU 0x00001000L #define IPA_FULL_VLAN 0x00004000L #define IPA_SOURCE_MAC_AVAIL 0x00010000L +#define IPA_OSA_MC_ROUTER_AVAIL 0x00020000L #define IPA_SETADP_QUERY_COMMANDS_SUPPORTED 0x01 #define IPA_SETADP_ALTER_MAC_ADDRESS 0x02 @@ -331,7 +332,7 @@ static unsigned char DM_ACT[]={ #define IPA_CMD_ASS_ARP_QUERY_INFO 0x0104 #define IPA_CMD_ASS_ARP_QUERY_STATS 0x0204 -#define IPA_CHECKSUM_ENABLE_MASK 0x001f +#define IPA_CHECKSUM_DEFAULT_ENABLE_MASK 0x001a #define IPA_CMD_ASS_FILTER_SET_TYPES 0x0003 @@ -462,11 +463,10 @@ typedef struct ipa_cmd_t { } ipa_cmd_t __attribute__ ((packed)); #define QETH_IOC_MAGIC 0x22 -#define QETH_IOCPROC_OSAEINTERFACES _IOWR(QETH_IOC_MAGIC, 1, arg) -#define QETH_IOCPROC_INTERFACECHANGES _IOWR(QETH_IOC_MAGIC, 2, arg) +#define QETH_IOCPROC_REGISTER _IOWR(QETH_IOC_MAGIC, 1, int) #define SNMP_QUERY_CARD_INFO 0x00000002L -#define SNMP_REGISETER_MIB 0x00000004L +#define SNMP_REGISTER_MIB 0x00000004L #define SNMP_GET_OID 0x00000010L #define SNMP_SET_OID 0x00000011L #define SNMP_GET_NEXT_OID 0x00000012L diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/qdio.c linux-2.4.28-pre3/drivers/s390/qdio.c --- linux-2.4.27/drivers/s390/qdio.c 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/qdio.c 2004-09-10 19:33:49.000000000 +0000 @@ -57,7 +57,7 @@ void volatile qdio_eyecatcher(void) #include -#define VERSION_QDIO_C "$Revision: 1.145 $" +#define VERSION_QDIO_C "$Revision: 1.145.4.9 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher "); @@ -97,10 +97,12 @@ static struct { #endif /* QDIO_PERFORMANCE_STATS */ static int hydra_thinints=0; +static int omit_svs=0; static int indicator_used[INDICATORS_PER_CACHELINE]; static __u32 * volatile indicators; static __u32 volatile spare_indicator; +static atomic_t spare_indicator_usecount; static debug_info_t *qdio_dbf_setup=NULL; static debug_info_t *qdio_dbf_sbal=NULL; @@ -121,6 +123,7 @@ static rwlock_t irq_list_lock[QDIO_IRQ_B static struct semaphore init_sema; static qdio_chsc_area_t *chsc_area; +static spinlock_t chsc_area_lock=SPIN_LOCK_UNLOCKED; /* iQDIO stuff: */ static volatile qdio_q_t *tiq_list=NULL; /* volatile as it could change during a while loop */ @@ -198,7 +201,7 @@ static inline volatile __u64 qdio_get_mi } static inline unsigned long qdio_get_millis(void) { - return (unsigned long)(qdio_get_micros()>>12); + return (unsigned long)(qdio_get_micros()>>10); } static __inline__ int atomic_return_add (int i, atomic_t *v) @@ -518,8 +521,10 @@ static __u32 * volatile qdio_get_indicat if (found) return indicators+i; - else + else { + atomic_inc(&spare_indicator_usecount); return (__u32 * volatile) &spare_indicator; + } } /* locked by the locks in qdio_activate and qdio_cleanup */ @@ -531,6 +536,9 @@ static void qdio_put_indicator(__u32 *ad i=addr-indicators; indicator_used[i]=0; } + if (addr==&spare_indicator) { + atomic_dec(&spare_indicator_usecount); + } } static inline volatile void tiqdio_clear_summary_bit(__u32 *location) @@ -621,8 +629,8 @@ static inline int qdio_stop_polling(qdio set_slsb(&q->slsb.acc.val[(gsf+QDIO_MAX_BUFFERS_PER_Q-1)& (QDIO_MAX_BUFFERS_PER_Q-1)],SLSB_P_INPUT_NOT_INIT); /* we don't issue this SYNC_MEMORY, as we trust Rick T and - * moreover will not use the PROCESSING state, so q->polling - * was 0 + * moreover will not use the PROCESSING state under VM, + * so q->polling was 0 anyway. SYNC_MEMORY;*/ if (q->slsb.acc.val[gsf]==SLSB_P_INPUT_PRIMED) { /* set our summary bit again, as otherwise there is a @@ -655,6 +663,11 @@ static inline void qdio_unmark_q(qdio_q_ if ((q->is_thinint_q)&&(q->is_input_q)) { /* iQDIO */ spin_lock_irqsave(&ttiq_list_lock,flags); + /* in case cleanup has done this already and simultanously + * qdio_unmark_q is called from the interrupt handler, we've + * got to check this in this specific case again */ + if ((!q->list_prev)||(!q->list_next)) + goto out; if (q->list_next==q) { /* q was the only interesting q */ tiq_list=NULL; @@ -667,6 +680,7 @@ static inline void qdio_unmark_q(qdio_q_ q->list_next=NULL; q->list_prev=NULL; } +out: spin_unlock_irqrestore(&ttiq_list_lock,flags); } } @@ -710,7 +724,7 @@ static inline void qdio_translate_buffer (void*)q->sbal[bufno],SBAL_SIZE); } -inline static int qdio_get_outbound_buffer_frontier(qdio_q_t *q) +static inline int qdio_get_outbound_buffer_frontier(qdio_q_t *q) { int f,f_mod_no; volatile char *slsb; @@ -739,7 +753,7 @@ check_next: if (f==first_not_to_check) goto out; slsbyte=slsb[f_mod_no]; - /* the hydra has not fetched the output yet */ + /* the card has not fetched the output yet */ if (slsbyte==SLSB_CU_OUTPUT_PRIMED) { #ifdef QDIO_DBF_LIKE_HELL QDIO_DBF_TEXT5(0,trace,"outpprim"); @@ -747,7 +761,7 @@ check_next: goto out; } - /* the hydra got it */ + /* the card got it */ if (slsbyte==SLSB_P_OUTPUT_EMPTY) { atomic_dec(&q->number_of_buffers_used); f++; @@ -797,7 +811,7 @@ out: } /* all buffers are processed */ -inline static int qdio_is_outbound_q_done(qdio_q_t *q) +static inline int qdio_is_outbound_q_done(qdio_q_t *q) { int no_used; #ifdef QDIO_DBF_LIKE_HELL @@ -818,7 +832,7 @@ inline static int qdio_is_outbound_q_don return (no_used==0); } -inline static int qdio_has_outbound_q_moved(qdio_q_t *q) +static inline int qdio_has_outbound_q_moved(qdio_q_t *q) { int i; @@ -827,7 +841,6 @@ inline static int qdio_has_outbound_q_mo if ( (i!=GET_SAVED_FRONTIER(q)) || (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) { SAVE_FRONTIER(q,i); - SAVE_TIMESTAMP(q); #ifdef QDIO_DBF_LIKE_HELL QDIO_DBF_TEXT4(0,trace,"oqhasmvd"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); @@ -842,9 +855,10 @@ inline static int qdio_has_outbound_q_mo } } -inline static void qdio_kick_outbound_q(qdio_q_t *q) +static inline void qdio_kick_outbound_q(qdio_q_t *q) { int result; + char dbf_text[15]; #ifdef QDIO_DBF_LIKE_HELL QDIO_DBF_TEXT4(0,trace,"kickoutq"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); @@ -852,9 +866,66 @@ inline static void qdio_kick_outbound_q( if (!q->siga_out) return; + /* here's the story with cc=2 and busy bit set (thanks, Rick): + * VM's CP could present us cc=2 and busy bit set on SIGA-write + * during reconfiguration of their Guest LAN (only in HIPERS mode, + * QDIO mode is asynchronous -- cc=2 and busy bit there will take + * the queues down immediately; and not being under VM we have a + * problem on cc=2 and busy bit set right away). + * + * Therefore qdio_siga_output will try for a short time constantly, + * if such a condition occurs. If it doesn't change, it will + * increase the busy_siga_counter and save the timestamp, and + * schedule the queue for later processing (via mark_q, using the + * queue tasklet). __qdio_outbound_processing will check out the + * counter. If non-zero, it will call qdio_kick_outbound_q as often + * as the value of the counter. This will attempt further SIGA + * instructions. + * Every successful SIGA instruction will decrease the counter. + * After some time of no movement, qdio_kick_outbound_q will + * finally fail and reflect corresponding error codes to call + * the upper layer module and have it take the queues down. + * + * Note that this is a change from the original HiperSockets design + * (saying cc=2 and busy bit means take the queues down), but in + * these days Guest LAN didn't exist... excessive cc=2 with busy bit + * conditions will still take the queues down, but the threshold is + * higher due to the Guest LAN environment. + */ + result=qdio_siga_output(q); - if (result) { + switch (result) { + case 0: + /* went smooth this time, reset timestamp */ + QDIO_DBF_TEXT3(0,trace,"cc2reslv"); + sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no, + atomic_read(&q->busy_siga_counter)); + QDIO_DBF_TEXT3(0,trace,dbf_text); + q->timing.busy_start=0; + break; + case (2|QDIO_SIGA_ERROR_B_BIT_SET): + /* cc=2 and busy bit: */ + atomic_inc(&q->busy_siga_counter); + + /* if the last siga was successful, save + * timestamp here */ + if (!q->timing.busy_start) + q->timing.busy_start=NOW; + + /* if we're in time, don't touch error_status_flags + * and siga_error */ + if (NOW-q->timing.busy_startirq,q->q_no, + atomic_read(&q->busy_siga_counter)); + QDIO_DBF_TEXT3(0,trace,dbf_text); + /* else fallthrough and report error */ + default: + /* for plain cc=1, 2 or 3: */ if (q->siga_error) q->error_status_flags|= QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR; @@ -864,7 +935,7 @@ inline static void qdio_kick_outbound_q( } } -inline static void qdio_kick_outbound_handler(qdio_q_t *q) +static inline void qdio_kick_outbound_handler(qdio_q_t *q) { #ifdef QDIO_DBF_LIKE_HELL char dbf_text[15]; @@ -901,8 +972,9 @@ inline static void qdio_kick_outbound_ha q->error_status_flags=0; } -static void qdio_outbound_processing(qdio_q_t *q) +static inline void __qdio_outbound_processing(qdio_q_t *q) { + int siga_attempts; #ifdef QDIO_DBF_LIKE_HELL QDIO_DBF_TEXT4(0,trace,"qoutproc"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); @@ -926,6 +998,14 @@ static void qdio_outbound_processing(qdi o_p_nc++; #endif /* QDIO_PERFORMANCE_STATS */ + /* see comment in qdio_kick_outbound_q */ + siga_attempts=atomic_read(&q->busy_siga_counter); + while (siga_attempts) { + atomic_dec(&q->busy_siga_counter); + qdio_kick_outbound_q(q); + siga_attempts--; + } + #ifdef QDIO_PERFORMANCE_STATS perf_stats.tl_runs++; #endif /* QDIO_PERFORMANCE_STATS */ @@ -936,7 +1016,8 @@ static void qdio_outbound_processing(qdi if (q->is_iqdio_q) { /* for asynchronous queues, we better check, if the fill - * level is too high */ + * level is too high. for synchronous queues, the fill + * level will never be that high. */ if (atomic_read(&q->number_of_buffers_used)> IQDIO_FILL_LEVEL_TO_POLL) { qdio_mark_q(q); @@ -950,16 +1031,24 @@ static void qdio_outbound_processing(qdi qdio_release_q(q); } +static void qdio_outbound_processing(qdio_q_t *q) +{ + __qdio_outbound_processing(q); +} + /************************* INBOUND ROUTINES *******************************/ -inline static int qdio_get_inbound_buffer_frontier(qdio_q_t *q) +static inline int qdio_get_inbound_buffer_frontier(qdio_q_t *q) { int f,f_mod_no; volatile char *slsb; char slsbyte; int first_not_to_check; char dbf_text[15]; +#ifdef QDIO_USE_PROCESSING_STATE + int last_position=-1; +#endif /* QDIO_USE_PROCESSING_STATE */ #ifdef QDIO_DBF_LIKE_HELL QDIO_DBF_TEXT4(0,trace,"getibfro"); @@ -1002,8 +1091,14 @@ check_next: if (q->siga_sync) { set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT); } else { - set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_PROCESSING); + /* set the previous buffer to NOT_INIT. The current + * buffer will be set to PROCESSING at the end of + * this function to avoid further interrupts. */ + if (last_position>=0) + set_slsb(&slsb[last_position], + SLSB_P_INPUT_NOT_INIT); atomic_set(&q->polling,1); + last_position=f_mod_no; } #else /* QDIO_USE_PROCESSING_STATE */ set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT); @@ -1044,6 +1139,10 @@ check_next: f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1); atomic_dec(&q->number_of_buffers_used); +#ifdef QDIO_USE_PROCESSING_STATE + last_position=-1; +#endif /* QDIO_USE_PROCESSING_STATE */ + goto out; } @@ -1051,6 +1150,11 @@ check_next: out: q->first_to_check=f_mod_no; +#ifdef QDIO_USE_PROCESSING_STATE + if (last_position>=0) + set_slsb(&slsb[last_position],SLSB_P_INPUT_PROCESSING); +#endif /* QDIO_USE_PROCESSING_STATE */ + #ifdef QDIO_DBF_LIKE_HELL QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int)); #endif /* QDIO_DBF_LIKE_HELL */ @@ -1058,7 +1162,7 @@ out: return q->first_to_check; } -inline static int qdio_has_inbound_q_moved(qdio_q_t *q) +static inline int qdio_has_inbound_q_moved(qdio_q_t *q) { int i; @@ -1095,7 +1199,7 @@ inline static int qdio_has_inbound_q_mov } /* means, no more buffers to be filled */ -inline static int iqdio_is_inbound_q_done(qdio_q_t *q) +static inline int iqdio_is_inbound_q_done(qdio_q_t *q) { int no_used; #ifdef QDIO_DBF_LIKE_HELL @@ -1148,7 +1252,7 @@ inline static int iqdio_is_inbound_q_don return 0; } -inline static int qdio_is_inbound_q_done(qdio_q_t *q) +static inline int qdio_is_inbound_q_done(qdio_q_t *q) { int no_used; #ifdef QDIO_DBF_LIKE_HELL @@ -1157,7 +1261,7 @@ inline static int qdio_is_inbound_q_done no_used=atomic_read(&q->number_of_buffers_used); - /* we need that one for synchronization with Hydra, as Hydra + /* we need that one for synchronization with the OSA/FCP card, as it * does a kind of PCI avoidance */ SYNC_MEMORY; @@ -1204,7 +1308,7 @@ inline static int qdio_is_inbound_q_done } } -inline static void qdio_kick_inbound_handler(qdio_q_t *q) +static inline void qdio_kick_inbound_handler(qdio_q_t *q) { int count=0; int start,end,real_end,i; @@ -1250,7 +1354,8 @@ inline static void qdio_kick_inbound_han #endif /* QDIO_PERFORMANCE_STATS */ } -static inline void tiqdio_inbound_processing(qdio_q_t *q) +static inline void __tiqdio_inbound_processing(qdio_q_t *q, + int spare_ind_was_set) { qdio_irq_t *irq_ptr; qdio_q_t *oq; @@ -1282,8 +1387,18 @@ static inline void tiqdio_inbound_proces goto out; } - if (*(q->dev_st_chg_ind)) { - tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind); + /* we reset spare_ind_was_set, when the queue does not use the + * spare indicator */ + if (spare_ind_was_set) { + spare_ind_was_set==(q->dev_st_chg_ind==&spare_indicator); + } + + if ( (*(q->dev_st_chg_ind)) || (spare_ind_was_set) ) { + /* q->dev_st_chg_ind is the indicator, be it shared or not. + * only clear it, if indicator is non-shared */ + if (!spare_ind_was_set) { + tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind); + } if (q->hydra_gives_outbound_pcis) { if (!q->siga_sync_done_on_thinints) { @@ -1297,7 +1412,7 @@ static inline void tiqdio_inbound_proces } /* maybe we have to do work on our outbound queues... at least - * we have to check Hydra outbound-int-capable thinint-capable + * we have to check for outbound-int-capable thinint-capable * queues */ if (q->hydra_gives_outbound_pcis) { irq_ptr=(qdio_irq_t*)q->irq_ptr; @@ -1307,7 +1422,7 @@ static inline void tiqdio_inbound_proces perf_stats.tl_runs--; #endif /* QDIO_PERFORMANCE_STATS */ if (!qdio_is_outbound_q_done(oq)) { - qdio_outbound_processing(oq); + __qdio_outbound_processing(oq); } } } @@ -1330,7 +1445,12 @@ out: qdio_release_q(q); } -static void qdio_inbound_processing(qdio_q_t *q) +static void tiqdio_inbound_processing(qdio_q_t *q) +{ + __tiqdio_inbound_processing(q,atomic_read(&spare_indicator_usecount)); +} + +static inline void __qdio_inbound_processing(qdio_q_t *q) { int q_laps=0; @@ -1375,11 +1495,17 @@ again: qdio_release_q(q); } +static void qdio_inbound_processing(qdio_q_t *q) +{ + __qdio_inbound_processing(q); +} + /************************* MAIN ROUTINES *******************************/ static inline void tiqdio_inbound_checks(void) { qdio_q_t *q; + int spare_ind_was_set=0; #ifdef QDIO_USE_PROCESSING_STATE int q_laps=0; #endif /* QDIO_USE_PROCESSING_STATE */ @@ -1398,15 +1524,22 @@ static inline void tiqdio_inbound_checks again: #endif /* QDIO_USE_PROCESSING_STATE */ + /* when the spare indicator is used and set, save that and clear it */ + if ( (atomic_read(&spare_indicator_usecount)) && (spare_indicator) ) { + spare_ind_was_set=1; + tiqdio_clear_summary_bit((__u32*)&spare_indicator); + } + q=(qdio_q_t*)tiq_list; /* switch all active queues to processing state */ do { if (!q) break; - tiqdio_inbound_processing(q); + __tiqdio_inbound_processing(q,spare_ind_was_set); q=(qdio_q_t*)q->list_next; } while (q!=(qdio_q_t*)tiq_list); - /* switch off all queues' processing state */ + /* switch off all queues' processing state, see comments in + * qdio_get_inbound_buffer_frontier */ #ifdef QDIO_USE_PROCESSING_STATE q=(qdio_q_t*)tiq_list; do { @@ -1589,7 +1722,7 @@ next: kfree(irq_ptr->output_qs[i]); } - if (irq_ptr->qdr) kfree(irq_ptr->qdr); + kfree(irq_ptr->qdr); kfree(irq_ptr); } @@ -1758,6 +1891,10 @@ static int qdio_alloc_qs(qdio_irq_t *irq ((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing: &qdio_inbound_processing); + /* actually this is not used for inbound queues. yet. */ + atomic_set(&q->busy_siga_counter,0); + q->timing.busy_start=0; + /* for (j=0;jtiming.last_transfer_times[j]=(qdio_get_micros()/ QDIO_STATS_NUMBER)*j; @@ -1849,6 +1986,9 @@ static int qdio_alloc_qs(qdio_irq_t *irq q->tasklet.func=(void(*)(unsigned long)) &qdio_outbound_processing; + atomic_set(&q->busy_siga_counter,0); + q->timing.busy_start=0; + /* fill in slib */ if (i>0) irq_ptr->output_qs[i-1]->slib->nsliba= QDIO_PFIX_GET_ADDR(q->slib); @@ -1928,9 +2068,10 @@ static int tiqdio_thinint_handler(__u32 perf_stats.start_time_inbound=NOW; #endif /* QDIO_PERFORMANCE_STATS */ - /* VM will do the SVS for us - * issue SVS to benefit from iqdio interrupt avoidance (SVS clears AISOI)*/ - if (!MACHINE_IS_VM) { + /* SVS only when needed: + * issue SVS to benefit from iqdio interrupt avoidance + * (SVS clears AISOI)*/ + if (!omit_svs) { tiqdio_clear_global_summary(); } @@ -2014,7 +2155,7 @@ static void qdio_handler(int irq,devstat #ifdef QDIO_PERFORMANCE_STATS perf_stats.tl_runs--; #endif /* QDIO_PERFORMANCE_STATS */ - qdio_inbound_processing(q); + __qdio_inbound_processing(q); } } if (irq_ptr->hydra_gives_outbound_pcis) { @@ -2027,7 +2168,7 @@ static void qdio_handler(int irq,devstat if (!irq_ptr->sync_done_on_outb_pcis) { SYNC_MEMORY; } - qdio_outbound_processing(q); + __qdio_outbound_processing(q); } } } @@ -2206,6 +2347,9 @@ static int qdio_chsc(qdio_chsc_area_t *c static unsigned char qdio_check_siga_needs(int sch) { int resp_code,result; + unsigned long flags; + + spin_lock_irqsave(&chsc_area_lock,flags); memset(chsc_area,0,sizeof(qdio_chsc_area_t)); chsc_area->request_block.command_code1=0x0010; /* length */ @@ -2219,7 +2363,8 @@ static unsigned char qdio_check_siga_nee QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \ "SIGAs for sch x%x.\n", result,sch); - return -1; /* all flags set */ + result=-1; /* all flags set */ + goto out; } resp_code=chsc_area->request_block.operation_data_area. @@ -2228,7 +2373,8 @@ static unsigned char qdio_check_siga_nee QDIO_PRINT_WARN("response upon checking SIGA needs " \ "is 0x%x. Using all SIGAs for sch x%x.\n", resp_code,sch); - return -1; /* all flags set */ + result=-1; /* all flags set */ + goto out; } if ( (!(chsc_area->request_block.operation_data_area. @@ -2240,18 +2386,25 @@ static unsigned char qdio_check_siga_nee ) { QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \ "using all SIGAs.\n",sch); - return CHSC_FLAG_SIGA_INPUT_NECESSARY | + result=CHSC_FLAG_SIGA_INPUT_NECESSARY | CHSC_FLAG_SIGA_OUTPUT_NECESSARY | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */ + goto out; } - return chsc_area->request_block.operation_data_area. + result=chsc_area->request_block.operation_data_area. store_qdio_data_response.qdioac; +out: + spin_unlock_irqrestore(&chsc_area_lock,flags); + return result; } -static int qdio_check_for_hydra_thinints(void) +static void qdio_check_for_machine_features(void) { int i,result; + unsigned long flags; + + spin_lock_irqsave(&chsc_area_lock,flags); memset(chsc_area,0,sizeof(qdio_chsc_area_t)); chsc_area->request_block.command_code1=0x0010; @@ -2260,16 +2413,19 @@ static int qdio_check_for_hydra_thinints if (result) { QDIO_PRINT_WARN("CHSC returned cc %i. Won't use adapter " \ - "interrupts for any Hydra.\n",result); - return 0; + "interrupts for any QDIO device.\n",result); + result=0; + goto out; } i=chsc_area->request_block.operation_data_area. store_qdio_data_response.response_code; if (i!=1) { QDIO_PRINT_WARN("Was not able to determine general " \ - "characteristics of all Hydras aboard.\n"); - return 0; + "characteristics of all QDIO devices " \ + "aboard.\n"); + result=0; + goto out; } /* 4: request block @@ -2277,16 +2433,29 @@ static int qdio_check_for_hydra_thinints * 512: chsc char */ /* check for bit 67 */ if ( (*(((unsigned int*)(chsc_area))+4+2+2)&0x10000000)!=0x10000000) { - return 0; + hydra_thinints=0; } else { - return 1; + hydra_thinints=1; } + + /* check for bit 56: if aif time delay disablement fac installed, + * omit svs even under lpar (good point by rick again) */ + if ( (*(((unsigned int*)(chsc_area))+4+2+1)&0x00000080)!=0x00000080) { + omit_svs=1; + } else { + omit_svs=0; + } +out: + spin_unlock_irqrestore(&chsc_area_lock,flags); } /* the chsc_area is locked by the lock in qdio_activate */ static unsigned int tiqdio_check_chsc_availability(void) { int result; int i; + unsigned long flags; + + spin_lock_irqsave(&chsc_area_lock,flags); memset(chsc_area,0,sizeof(qdio_chsc_area_t)); chsc_area->request_block.command_code1=0x0010; @@ -2327,6 +2496,7 @@ static unsigned int tiqdio_check_chsc_av goto exit; } exit: + spin_unlock_irqrestore(&chsc_area_lock,flags); return result; } @@ -2337,6 +2507,7 @@ static unsigned int tiqdio_set_subchanne unsigned long real_addr_local_summary_bit; unsigned long real_addr_dev_st_chg_ind; void *ptr; + unsigned long flags; char dbf_text[15]; unsigned int resp_code; @@ -2354,6 +2525,8 @@ static unsigned int tiqdio_set_subchanne virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind); } + spin_lock_irqsave(&chsc_area_lock,flags); + memset(chsc_area,0,sizeof(qdio_chsc_area_t)); chsc_area->request_block.command_code1=0x0fe0; chsc_area->request_block.command_code2=0x0021; @@ -2377,7 +2550,8 @@ static unsigned int tiqdio_set_subchanne if (result) { QDIO_PRINT_WARN("could not set indicators on irq x%x, " \ "cc=%i.\n",irq_ptr->irq,result); - return -EIO; + result=-EIO; + goto out; } resp_code=chsc_area->response_block.response_code; @@ -2389,14 +2563,18 @@ static unsigned int tiqdio_set_subchanne QDIO_DBF_TEXT1(0,setup,dbf_text); ptr=&chsc_area->response_block; QDIO_DBF_HEX2(1,setup,&ptr,QDIO_DBF_SETUP_LEN); - return -EIO; + result=-EIO; + goto out; } QDIO_DBF_TEXT2(0,setup,"setscind"); QDIO_DBF_HEX2(0,setup,&real_addr_local_summary_bit, sizeof(unsigned long)); QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long)); - return 0; + result=0; +out: + spin_unlock_irqrestore(&chsc_area_lock,flags); + return result; } /* chsc_area would have to be locked if called from outside qdio_activate */ @@ -2406,10 +2584,13 @@ static unsigned int tiqdio_set_delay_tar unsigned int resp_code; int result; void *ptr; + unsigned long flags; char dbf_text[15]; if (!irq_ptr->is_thinint_irq) return -ENODEV; + spin_lock_irqsave(&chsc_area_lock,flags); + memset(chsc_area,0,sizeof(qdio_chsc_area_t)); chsc_area->request_block.command_code1=0x0fe0; chsc_area->request_block.command_code2=0x1027; @@ -2420,7 +2601,8 @@ static unsigned int tiqdio_set_delay_tar if (result) { QDIO_PRINT_WARN("could not set delay target on irq x%x, " \ "cc=%i. Continuing.\n",irq_ptr->irq,result); - return -EIO; + result=-EIO; + goto out; } resp_code=chsc_area->response_block.response_code; @@ -2435,7 +2617,10 @@ static unsigned int tiqdio_set_delay_tar } QDIO_DBF_TEXT2(0,trace,"delytrgt"); QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long)); - return 0; + result=0; +out: + spin_unlock_irqrestore(&chsc_area_lock,flags); + return result; } int qdio_cleanup(int irq,int how) @@ -2445,7 +2630,7 @@ int qdio_cleanup(int irq,int how) int do_an_irqrestore=0; unsigned long flags; int timeout; - char dbf_text[15]="12345678"; + char dbf_text[15]; result=0; sprintf(dbf_text,"qcln%4x",irq); @@ -2455,7 +2640,7 @@ int qdio_cleanup(int irq,int how) irq_ptr=qdio_get_irq_ptr(irq); if (!irq_ptr) return -ENODEV; - spin_lock(&irq_ptr->setting_up_lock); + down(&irq_ptr->setting_up_lock); /* mark all qs as uninteresting */ for (i=0;ino_input_qs;i++) { @@ -2527,7 +2712,7 @@ int qdio_cleanup(int irq,int how) if (do_an_irqrestore) s390irq_spin_unlock_irqrestore(irq,flags); - spin_unlock(&irq_ptr->setting_up_lock); + up(&irq_ptr->setting_up_lock); qdio_remove_irq_ptr(irq_ptr); qdio_release_irq_memory(irq_ptr); @@ -2574,16 +2759,15 @@ int qdio_initialize(qdio_initialize_t *i int result,result2; int found; unsigned long flags; - char dbf_text[20]; /* if a printf would print out more than 8 chars */ + char dbf_text[20]; /* if a printf printed out more than 8 chars */ - down_interruptible(&init_sema); + down(&init_sema); sprintf(dbf_text,"qini%4x",init_data->irq); QDIO_DBF_TEXT0(0,setup,dbf_text); QDIO_DBF_TEXT0(0,trace,dbf_text); sprintf(dbf_text,"qfmt:%x",init_data->q_format); QDIO_DBF_TEXT0(0,setup,dbf_text); - QDIO_DBF_TEXT0(0,setup,init_data->adapter_name); QDIO_DBF_HEX0(0,setup,init_data->adapter_name,8); sprintf(dbf_text,"qpff%4x",init_data->qib_param_field_format); QDIO_DBF_TEXT0(0,setup,dbf_text); @@ -2672,7 +2856,6 @@ int qdio_initialize(qdio_initialize_t *i irq_ptr->qdr=kmalloc(sizeof(qdr_t),GFP_DMA); if (!(irq_ptr->qdr)) { - kfree(irq_ptr->qdr); kfree(irq_ptr); QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n"); result=-ENOMEM; @@ -2736,12 +2919,12 @@ int qdio_initialize(qdio_initialize_t *i qdio_set_state(irq_ptr,QDIO_IRQ_STATE_INACTIVE); - irq_ptr->setting_up_lock=SPIN_LOCK_UNLOCKED; + sema_init(&irq_ptr->setting_up_lock,1); MOD_INC_USE_COUNT; QDIO_DBF_TEXT3(0,setup,"MOD_INC_"); - spin_lock(&irq_ptr->setting_up_lock); + down(&irq_ptr->setting_up_lock); qdio_insert_irq_ptr(irq_ptr); @@ -2867,10 +3050,10 @@ int qdio_initialize(qdio_initialize_t *i } result=tiqdio_set_subchannel_ind(irq_ptr,0); if (result) { - spin_unlock(&irq_ptr->setting_up_lock); + up(&irq_ptr->setting_up_lock); qdio_cleanup(irq_ptr->irq, QDIO_FLAG_CLEANUP_USING_CLEAR); - goto out2; + goto out; } tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET); } @@ -2906,9 +3089,9 @@ int qdio_initialize(qdio_initialize_t *i s390irq_spin_unlock_irqrestore(irq_ptr->irq,saveflags); if (result) { - spin_unlock(&irq_ptr->setting_up_lock); + up(&irq_ptr->setting_up_lock); qdio_cleanup(irq_ptr->irq,QDIO_FLAG_CLEANUP_USING_CLEAR); - goto out2; + goto out; } result=qdio_sleepon(&irq_ptr->interrupt_has_arrived, @@ -2918,9 +3101,9 @@ int qdio_initialize(qdio_initialize_t *i QDIO_PRINT_ERR("establish queues on irq %04x: timed out\n", irq_ptr->irq); QDIO_DBF_TEXT2(1,setup,"eq:timeo"); - spin_unlock(&irq_ptr->setting_up_lock); + up(&irq_ptr->setting_up_lock); qdio_cleanup(irq_ptr->irq,QDIO_FLAG_CLEANUP_USING_CLEAR); - goto out2; + goto out; } if (!(irq_ptr->io_result_dstat & DEV_STAT_DEV_END)) { @@ -2937,10 +3120,10 @@ int qdio_initialize(qdio_initialize_t *i irq_ptr->irq,irq_ptr->io_result_dstat, irq_ptr->io_result_cstat, irq_ptr->io_result_flags); - spin_unlock(&irq_ptr->setting_up_lock); + up(&irq_ptr->setting_up_lock); qdio_cleanup(irq_ptr->irq,QDIO_FLAG_CLEANUP_USING_CLEAR); result=-EIO; - goto out2; + goto out; } if (irq_ptr->io_result_dstat & ~(DEV_STAT_CHN_END|DEV_STAT_DEV_END)) { @@ -2958,18 +3141,19 @@ int qdio_initialize(qdio_initialize_t *i irq_ptr->io_result_cstat, irq_ptr->io_result_flags); result=-EIO; + up(&irq_ptr->setting_up_lock); goto out; } - if (MACHINE_IS_VM) irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq); - else { - irq_ptr->qdioac=CHSC_FLAG_SIGA_INPUT_NECESSARY - | CHSC_FLAG_SIGA_OUTPUT_NECESSARY; - } sprintf(dbf_text,"qdioac%2x",irq_ptr->qdioac); QDIO_DBF_TEXT2(0,setup,dbf_text); + /* if this gets set once, we're running under VM and can omit SVSes */ + if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY) { + omit_svs=1; + } + sprintf(dbf_text,"qib ac%2x",irq_ptr->qib.ac); QDIO_DBF_TEXT2(0,setup,dbf_text); @@ -3026,11 +3210,10 @@ int qdio_initialize(qdio_initialize_t *i qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ESTABLISHED); - out: if (irq_ptr) { - spin_unlock(&irq_ptr->setting_up_lock); + up(&irq_ptr->setting_up_lock); } - out2: + out: up(&init_sema); return result; @@ -3046,7 +3229,7 @@ int qdio_activate(int irq,int flags) irq_ptr=qdio_get_irq_ptr(irq); if (!irq_ptr) return -ENODEV; - spin_lock(&irq_ptr->setting_up_lock); + down(&irq_ptr->setting_up_lock); if (irq_ptr->state==QDIO_IRQ_STATE_INACTIVE) { result=-EBUSY; goto out; @@ -3141,14 +3324,15 @@ int qdio_activate(int irq,int flags) qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ACTIVE); out: - spin_unlock(&irq_ptr->setting_up_lock); + up(&irq_ptr->setting_up_lock); return result; } /* buffers filled forwards again to make Rick happy */ -static void qdio_do_qdio_fill_input(qdio_q_t *q,unsigned int qidx, - unsigned int count,qdio_buffer_t *buffers) +static inline void qdio_do_qdio_fill_input(qdio_q_t *q,unsigned int qidx, + unsigned int count, + qdio_buffer_t *buffers) { for (;;) { if (!q->is_0copy_sbals_q) { @@ -3281,7 +3465,7 @@ int do_QDIO(int irq,unsigned int callfla qdio_kick_outbound_q(q); } - qdio_outbound_processing(q); + __qdio_outbound_processing(q); } else { /* under VM, we do a SIGA sync * unconditionally */ @@ -3309,7 +3493,7 @@ int do_QDIO(int irq,unsigned int callfla * too long, the upper layer * module could do a lot of * traffic in that time */ - qdio_outbound_processing(q); + __qdio_outbound_processing(q); } } @@ -3349,7 +3533,7 @@ static int qdio_perf_procfile_read(char perf_stats.siga_ins); _OUTP_IT("Number of SIGA out's issued : %u\n", perf_stats.siga_outs); - _OUTP_IT("Number of PCI's caught : %u\n", + _OUTP_IT("Number of PCIs caught : %u\n", perf_stats.pcis); _OUTP_IT("Number of adapter interrupts caught : %u\n", perf_stats.thinints); @@ -3576,10 +3760,12 @@ int init_QDIO(void) qdio_add_procfs_entry(); - hydra_thinints=qdio_check_for_hydra_thinints(); + qdio_check_for_machine_features(); sprintf(dbf_text,"hydrati%1x",hydra_thinints); QDIO_DBF_TEXT0(0,setup,dbf_text); + sprintf(dbf_text,"omitsvs%1x",omit_svs); + QDIO_DBF_TEXT0(0,setup,dbf_text); tiqdio_register_thinints(); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/s390io.c linux-2.4.28-pre3/drivers/s390/s390io.c --- linux-2.4.27/drivers/s390/s390io.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/s390/s390io.c 2004-09-10 19:33:16.000000000 +0000 @@ -1,7 +1,7 @@ /* * drivers/s390/s390io.c * S/390 common I/O routines - * $Revision: 1.258 $ + * $Revision: 1.247.4.4 $ * * S390 version * Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH, @@ -3043,7 +3043,16 @@ s390_process_IRQ (unsigned int irq) if (!ioinfo[irq]->ui.flags.ready) return (ending_status); - memcpy (udp, &(ioinfo[irq]->devstat), sdevstat); + /* + * Special case: We got a deferred cc 3 on a basic sense. + * We have to notify the device driver of the former unit + * check, but must not confuse it by calling it with the status + * for the failed basic sense. + */ + if (ioinfo[irq]->ui.flags.w4sense) + ioinfo[irq]->ui.flags.w4sense = 0; + else + memcpy (udp, &(ioinfo[irq]->devstat), sdevstat); ioinfo[irq]->devstat.intparm = 0; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/sbus/char/bpp.c linux-2.4.28-pre3/drivers/sbus/char/bpp.c --- linux-2.4.27/drivers/sbus/char/bpp.c 2001-10-11 16:43:29.000000000 +0000 +++ linux-2.4.28-pre3/drivers/sbus/char/bpp.c 2004-09-10 19:32:08.000000000 +0000 @@ -1073,3 +1073,5 @@ static void __exit bpp_cleanup(void) module_init(bpp_init); module_exit(bpp_cleanup); + +MODULE_LICENSE("GPL"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/sbus/char/vfc_dev.c linux-2.4.28-pre3/drivers/sbus/char/vfc_dev.c --- linux-2.4.27/drivers/sbus/char/vfc_dev.c 2001-08-12 17:38:48.000000000 +0000 +++ linux-2.4.28-pre3/drivers/sbus/char/vfc_dev.c 2004-09-10 19:35:17.000000000 +0000 @@ -743,4 +743,4 @@ void cleanup_module(void) } #endif - +MODULE_LICENSE("GPL"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/53c7,8xx.c linux-2.4.28-pre3/drivers/scsi/53c7,8xx.c --- linux-2.4.27/drivers/scsi/53c7,8xx.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/53c7,8xx.c 2004-09-10 19:32:13.000000000 +0000 @@ -3926,7 +3926,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, restore_flags (flags); cmd->result = le32_to_cpu(0xffff); /* The NCR will overwrite message and status with valid data */ - cmd->host_scribble = (unsigned char *) tmp = create_cmd (cmd); + cmd->host_scribble = (unsigned char *) create_cmd (cmd); } cli(); /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/AM53C974.c linux-2.4.28-pre3/drivers/scsi/AM53C974.c --- linux-2.4.27/drivers/scsi/AM53C974.c 2001-09-30 19:26:07.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/AM53C974.c 2004-09-10 19:34:48.000000000 +0000 @@ -1027,6 +1027,78 @@ static void do_AM53C974_intr(int irq, vo spin_unlock_irqrestore(&io_request_lock, flags); } +/************************************************************************** +* Function : AM53C974_set_async(struct Scsi_Host *instance, int target) +* +* Purpose : put controller into async. mode +* +* Inputs : instance -- which AM53C974 +* target -- which SCSI target to deal with +* +* Returns : nothing +**************************************************************************/ +static __inline__ void AM53C974_set_async(struct Scsi_Host *instance, int target) +{ + AM53C974_local_declare(); + struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *) instance->hostdata; + AM53C974_setio(instance); + + AM53C974_write_8(STPREG, hostdata->sync_per[target]); + AM53C974_write_8(SOFREG, (DEF_SOF_RAD << 6) | (DEF_SOF_RAA << 4)); +} + +/************************************************************************** +* Function : AM53C974_set_sync(struct Scsi_Host *instance, int target) +* +* Purpose : put controller into sync. mode +* +* Inputs : instance -- which AM53C974 +* target -- which SCSI target to deal with +* +* Returns : nothing +**************************************************************************/ +static __inline__ void AM53C974_set_sync(struct Scsi_Host *instance, int target) +{ + AM53C974_local_declare(); + struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *) instance->hostdata; + AM53C974_setio(instance); + + AM53C974_write_8(STPREG, hostdata->sync_per[target]); + AM53C974_write_8(SOFREG, (SOFREG_SO & hostdata->sync_off[target]) | + (DEF_SOF_RAD << 6) | (DEF_SOF_RAA << 4)); +} + +/************************************************************************** +* Function : AM53C974_transfer_dma(struct Scsi_Host *instance, short dir, +* unsigned long length, char *data) +* +* Purpose : setup DMA transfer +* +* Inputs : instance -- which AM53C974 +* dir -- direction flag, 0: write to device, read from memory; +* 1: read from device, write to memory +* length -- number of bytes to transfer to from buffer +* data -- pointer to data buffer +* +* Returns : nothing +**************************************************************************/ +static __inline__ void AM53C974_transfer_dma(struct Scsi_Host *instance, short dir, + unsigned long length, char *data) +{ + AM53C974_local_declare(); + AM53C974_setio(instance); + + AM53C974_write_8(CMDREG, CMDREG_NOP); + AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D); /* idle command */ + AM53C974_write_8(STCLREG, (unsigned char) (length & 0xff)); + AM53C974_write_8(STCMREG, (unsigned char) ((length & 0xff00) >> 8)); + AM53C974_write_8(STCHREG, (unsigned char) ((length & 0xff0000) >> 16)); + AM53C974_write_32(DMASTC, length & 0xffffff); + AM53C974_write_32(DMASPA, virt_to_bus(data)); + AM53C974_write_8(CMDREG, CMDREG_IT | CMDREG_DMA); + AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D | DMACMD_START); +} + /************************************************************************ * Function : AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs) * * * @@ -1464,47 +1536,6 @@ static int AM53C974_sync_neg(struct Scsi return (0); } -/************************************************************************** -* Function : AM53C974_set_async(struct Scsi_Host *instance, int target) -* -* Purpose : put controller into async. mode -* -* Inputs : instance -- which AM53C974 -* target -- which SCSI target to deal with -* -* Returns : nothing -**************************************************************************/ -static __inline__ void AM53C974_set_async(struct Scsi_Host *instance, int target) -{ - AM53C974_local_declare(); - struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *) instance->hostdata; - AM53C974_setio(instance); - - AM53C974_write_8(STPREG, hostdata->sync_per[target]); - AM53C974_write_8(SOFREG, (DEF_SOF_RAD << 6) | (DEF_SOF_RAA << 4)); -} - -/************************************************************************** -* Function : AM53C974_set_sync(struct Scsi_Host *instance, int target) -* -* Purpose : put controller into sync. mode -* -* Inputs : instance -- which AM53C974 -* target -- which SCSI target to deal with -* -* Returns : nothing -**************************************************************************/ -static __inline__ void AM53C974_set_sync(struct Scsi_Host *instance, int target) -{ - AM53C974_local_declare(); - struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *) instance->hostdata; - AM53C974_setio(instance); - - AM53C974_write_8(STPREG, hostdata->sync_per[target]); - AM53C974_write_8(SOFREG, (SOFREG_SO & hostdata->sync_off[target]) | - (DEF_SOF_RAD << 6) | (DEF_SOF_RAA << 4)); -} - /*********************************************************************** * Function : AM53C974_information_transfer(struct Scsi_Host *instance, * * unsigned char statreg, unsigned char isreg, * @@ -2157,37 +2188,6 @@ static void AM53C974_intr_reselect(struc } /************************************************************************** -* Function : AM53C974_transfer_dma(struct Scsi_Host *instance, short dir, -* unsigned long length, char *data) -* -* Purpose : setup DMA transfer -* -* Inputs : instance -- which AM53C974 -* dir -- direction flag, 0: write to device, read from memory; -* 1: read from device, write to memory -* length -- number of bytes to transfer to from buffer -* data -- pointer to data buffer -* -* Returns : nothing -**************************************************************************/ -static __inline__ void AM53C974_transfer_dma(struct Scsi_Host *instance, short dir, - unsigned long length, char *data) -{ - AM53C974_local_declare(); - AM53C974_setio(instance); - - AM53C974_write_8(CMDREG, CMDREG_NOP); - AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D); /* idle command */ - AM53C974_write_8(STCLREG, (unsigned char) (length & 0xff)); - AM53C974_write_8(STCMREG, (unsigned char) ((length & 0xff00) >> 8)); - AM53C974_write_8(STCHREG, (unsigned char) ((length & 0xff0000) >> 16)); - AM53C974_write_32(DMASTC, length & 0xffffff); - AM53C974_write_32(DMASPA, virt_to_bus(data)); - AM53C974_write_8(CMDREG, CMDREG_IT | CMDREG_DMA); - AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D | DMACMD_START); -} - -/************************************************************************** * Function : AM53C974_dma_blast(struct Scsi_Host *instance, unsigned char dmastatus, * unsigned char statreg) * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/Config.in linux-2.4.28-pre3/drivers/scsi/Config.in --- linux-2.4.27/drivers/scsi/Config.in 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/Config.in 2004-09-10 19:34:24.000000000 +0000 @@ -70,6 +70,8 @@ dep_tristate 'AMI MegaRAID support' CONF dep_tristate 'AMI MegaRAID2 support' CONFIG_SCSI_MEGARAID2 $CONFIG_SCSI dep_mbool 'Serial ATA (SATA) support' CONFIG_SCSI_SATA $CONFIG_SCSI dep_tristate ' ServerWorks Frodo / Apple K2 SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SVW $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL +dep_tristate ' Intel PIIX/ICH SATA support' CONFIG_SCSI_ATA_PIIX $CONFIG_SCSI_SATA $CONFIG_PCI +dep_tristate ' NVIDIA SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_NV $CONFIG_SCSI_SATA $CONFIG_PCI dep_tristate ' Promise SATA TX2/TX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_PROMISE $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate ' Promise SATA SX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SX4 $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate ' Silicon Image SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SIL $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/Makefile linux-2.4.28-pre3/drivers/scsi/Makefile --- linux-2.4.27/drivers/scsi/Makefile 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/Makefile 2004-09-10 19:36:25.000000000 +0000 @@ -131,12 +131,14 @@ obj-$(CONFIG_SCSI_CPQFCTS) += cpqfc.o obj-$(CONFIG_SCSI_LASI700) += lasi700.o 53c700.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o +obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o obj-$(CONFIG_SCSI_SATA_SIS) += libata.o sata_sis.o obj-$(CONFIG_SCSI_SATA_SX4) += libata.o sata_sx4.o +obj-$(CONFIG_SCSI_SATA_NV) += libata.o sata_nv.o subdir-$(CONFIG_ARCH_ACORN) += ../acorn/scsi obj-$(CONFIG_ARCH_ACORN) += ../acorn/scsi/acorn-scsi.o diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/advansys.c linux-2.4.28-pre3/drivers/scsi/advansys.c --- linux-2.4.27/drivers/scsi/advansys.c 2004-04-14 13:05:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/advansys.c 2004-09-10 19:33:35.000000000 +0000 @@ -6118,8 +6118,8 @@ advansys_reset(Scsi_Cmnd *scp) } else { /* Append to 'done_scp' at the end with 'last_scp'. */ ASC_ASSERT(last_scp != NULL); - REQPNEXT(last_scp) = asc_dequeue_list(&boardp->active, - &new_last_scp, ASC_TID_ALL); + last_scp->host_scribble = (unsigned char *)asc_dequeue_list( + &boardp->active, &new_last_scp, ASC_TID_ALL); if (new_last_scp != NULL) { ASC_ASSERT(REQPNEXT(last_scp) != NULL); for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) { @@ -6141,8 +6141,8 @@ advansys_reset(Scsi_Cmnd *scp) } else { /* Append to 'done_scp' at the end with 'last_scp'. */ ASC_ASSERT(last_scp != NULL); - REQPNEXT(last_scp) = asc_dequeue_list(&boardp->waiting, - &new_last_scp, ASC_TID_ALL); + last_scp->host_scribble = (unsigned char *)asc_dequeue_list( + &boardp->waiting, &new_last_scp, ASC_TID_ALL); if (new_last_scp != NULL) { ASC_ASSERT(REQPNEXT(last_scp) != NULL); for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) { @@ -6394,8 +6394,8 @@ advansys_interrupt(int irq, void *dev_id ASC_TID_ALL); } else { ASC_ASSERT(last_scp != NULL); - REQPNEXT(last_scp) = asc_dequeue_list(&boardp->done, - &new_last_scp, ASC_TID_ALL); + last_scp->host_scribble = (unsigned char *)asc_dequeue_list( + &boardp->done, &new_last_scp, ASC_TID_ALL); if (new_last_scp != NULL) { ASC_ASSERT(REQPNEXT(last_scp) != NULL); last_scp = new_last_scp; @@ -6466,7 +6466,7 @@ asc_scsi_done_list(Scsi_Cmnd *scp) while (scp != NULL) { ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong) scp); tscp = REQPNEXT(scp); - REQPNEXT(scp) = NULL; + scp->host_scribble = NULL; ASC_STATS(scp->host, done); ASC_ASSERT(scp->scsi_done != NULL); scp->scsi_done(scp); @@ -7511,7 +7511,7 @@ asc_enqueue(asc_queue_t *ascq, REQP reqp tid = REQPTID(reqp); ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); if (flag == ASC_FRONT) { - REQPNEXT(reqp) = ascq->q_first[tid]; + reqp->host_scribble = (unsigned char *)ascq->q_first[tid]; ascq->q_first[tid] = reqp; /* If the queue was empty, set the last pointer. */ if (ascq->q_last[tid] == NULL) { @@ -7519,10 +7519,10 @@ asc_enqueue(asc_queue_t *ascq, REQP reqp } } else { /* ASC_BACK */ if (ascq->q_last[tid] != NULL) { - REQPNEXT(ascq->q_last[tid]) = reqp; + ascq->q_last[tid]->host_scribble = (unsigned char *)reqp; } ascq->q_last[tid] = reqp; - REQPNEXT(reqp) = NULL; + reqp->host_scribble = NULL; /* If the queue was empty, set the first pointer. */ if (ascq->q_first[tid] == NULL) { ascq->q_first[tid] = reqp; @@ -7643,7 +7643,7 @@ asc_dequeue_list(asc_queue_t *ascq, REQP lastp = ascq->q_last[i]; } else { ASC_ASSERT(lastp != NULL); - REQPNEXT(lastp) = ascq->q_first[i]; + lastp->host_scribble = (unsigned char *)ascq->q_first[i]; lastp = ascq->q_last[i]; } ascq->q_first[i] = ascq->q_last[i] = NULL; @@ -7721,8 +7721,8 @@ asc_rmqueue(asc_queue_t *ascq, REQP reqp currp; prevp = currp, currp = REQPNEXT(currp)) { if (currp == reqp) { ret = ASC_TRUE; - REQPNEXT(prevp) = REQPNEXT(currp); - REQPNEXT(reqp) = NULL; + prevp->host_scribble = (unsigned char *)REQPNEXT(currp); + reqp->host_scribble = NULL; if (ascq->q_last[tid] == reqp) { ascq->q_last[tid] = prevp; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/aic7xxx/aic79xx_osm.c linux-2.4.28-pre3/drivers/scsi/aic7xxx/aic79xx_osm.c --- linux-2.4.27/drivers/scsi/aic7xxx/aic79xx_osm.c 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/aic7xxx/aic79xx_osm.c 2004-09-10 19:32:30.000000000 +0000 @@ -2931,6 +2931,19 @@ out: ahd_unlock(ahd, &s); } +static __inline int +ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) +{ + u_long s; + int retval; + + ahd_lock(ahd, &s); + retval = ahd_linux_fallback(ahd, devinfo); + ahd_unlock(ahd, &s); + + return (retval); +} + static void ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, @@ -3567,19 +3580,6 @@ ahd_linux_dv_su(struct ahd_softc *ahd, s cmd->cmnd[4] = le | SSS_START; } -static __inline int -ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) -{ - u_long s; - int retval; - - ahd_lock(ahd, &s); - retval = ahd_linux_fallback(ahd, devinfo); - ahd_unlock(ahd, &s); - - return (retval); -} - static int ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/ata_piix.c linux-2.4.28-pre3/drivers/scsi/ata_piix.c --- linux-2.4.27/drivers/scsi/ata_piix.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/ata_piix.c 2004-09-10 19:37:11.000000000 +0000 @@ -0,0 +1,680 @@ +/* + + ata_piix.c - Intel PATA/SATA controllers + + Maintained by: Jeff Garzik + Please ALWAYS copy linux-ide@vger.kernel.org + on emails. + + + Copyright 2003-2004 Red Hat Inc + Copyright 2003-2004 Jeff Garzik + + + Copyright header from piix.c: + + Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer + Copyright (C) 1998-2000 Andre Hedrick + Copyright (C) 2003 Red Hat Inc + + May be copied or modified under the terms of the GNU General Public License + + */ + +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include +#include + +#define DRV_NAME "ata_piix" +#define DRV_VERSION "1.02" + +enum { + PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ + ICH5_PMR = 0x90, /* port mapping register */ + ICH5_PCS = 0x92, /* port control and status */ + + PIIX_FLAG_AHCI = (1 << 28), /* AHCI possible */ + PIIX_FLAG_CHECKINTR = (1 << 29), /* make sure PCI INTx enabled */ + PIIX_FLAG_COMBINED = (1 << 30), /* combined mode possible */ + + /* combined mode. if set, PATA is channel 0. + * if clear, PATA is channel 1. + */ + PIIX_COMB_PATA_P0 = (1 << 1), + PIIX_COMB = (1 << 2), /* combined mode enabled? */ + + PIIX_PORT_PRESENT = (1 << 0), + PIIX_PORT_ENABLED = (1 << 4), + + PIIX_80C_PRI = (1 << 5) | (1 << 4), + PIIX_80C_SEC = (1 << 7) | (1 << 6), + + ich5_pata = 0, + ich5_sata = 1, + piix4_pata = 2, + ich6_sata = 3, + ich6_sata_rm = 4, +}; + +static int piix_init_one (struct pci_dev *pdev, + const struct pci_device_id *ent); + +static void piix_pata_phy_reset(struct ata_port *ap); +static void piix_sata_phy_reset(struct ata_port *ap); +static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev); +static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev); + +static unsigned int in_module_init = 1; + +static struct pci_device_id piix_pci_tbl[] = { +#ifdef ATA_ENABLE_PATA + { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, + { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, + { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, +#endif + + /* NOTE: The following PCI ids must be kept in sync with the + * list in drivers/pci/quirks.c. + */ + + { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, + { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm }, + { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm }, + + { } /* terminate list */ +}; + +static struct pci_driver piix_pci_driver = { + .name = DRV_NAME, + .id_table = piix_pci_tbl, + .probe = piix_init_one, + .remove = ata_pci_remove_one, +}; + +static Scsi_Host_Template piix_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .detect = ata_scsi_detect, + .release = ata_scsi_release, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .use_new_eh_code = ATA_SHT_NEW_EH_CODE, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations piix_pata_ops = { + .port_disable = ata_port_disable, + .set_piomode = piix_set_piomode, + .set_dmamode = piix_set_dmamode, + + .tf_load = ata_tf_load_pio, + .tf_read = ata_tf_read_pio, + .check_status = ata_check_status_pio, + .exec_command = ata_exec_command_pio, + + .phy_reset = piix_pata_phy_reset, + + .bmdma_setup = ata_bmdma_setup_pio, + .bmdma_start = ata_bmdma_start_pio, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + + .eng_timeout = ata_eng_timeout, + + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, +}; + +static struct ata_port_operations piix_sata_ops = { + .port_disable = ata_port_disable, + + .tf_load = ata_tf_load_pio, + .tf_read = ata_tf_read_pio, + .check_status = ata_check_status_pio, + .exec_command = ata_exec_command_pio, + + .phy_reset = piix_sata_phy_reset, + + .bmdma_setup = ata_bmdma_setup_pio, + .bmdma_start = ata_bmdma_start_pio, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + + .eng_timeout = ata_eng_timeout, + + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, +}; + +static struct ata_port_info piix_port_info[] = { + /* ich5_pata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | + PIIX_FLAG_CHECKINTR, + .pio_mask = 0x1f, /* pio0-4 */ +#if 0 + .mwdma_mask = 0x06, /* mwdma1-2 */ +#else + .mwdma_mask = 0x00, /* mwdma broken */ +#endif + .udma_mask = ATA_UDMA_MASK_40C, /* FIXME: cbl det */ + .port_ops = &piix_pata_ops, + }, + + /* ich5_sata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | + PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &piix_sata_ops, + }, + + /* piix4_pata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .pio_mask = 0x1f, /* pio0-4 */ +#if 0 + .mwdma_mask = 0x06, /* mwdma1-2 */ +#else + .mwdma_mask = 0x00, /* mwdma broken */ +#endif + .udma_mask = ATA_UDMA_MASK_40C, /* FIXME: cbl det */ + .port_ops = &piix_pata_ops, + }, + + /* ich6_sata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | + PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR | + ATA_FLAG_SLAVE_POSS, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &piix_sata_ops, + }, + + /* ich6_sata_rm */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | + PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR | + ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &piix_sata_ops, + }, +}; + +static struct pci_bits piix_enable_bits[] = { + { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ + { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */ +}; + +MODULE_AUTHOR("Andre Hedrick, Alan Cox, Andrzej Krzysztofowicz, Jeff Garzik"); +MODULE_DESCRIPTION("SCSI low-level driver for Intel PIIX/ICH ATA controllers"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, piix_pci_tbl); + +/** + * piix_pata_cbl_detect - Probe host controller cable detect info + * @ap: Port for which cable detect info is desired + * + * Read 80c cable indicator from SATA PCI device's PCI config + * register. This register is normally set by firmware (BIOS). + * + * LOCKING: + * None (inherited from caller). + */ +static void piix_pata_cbl_detect(struct ata_port *ap) +{ + struct pci_dev *pdev = ap->host_set->pdev; + u8 tmp, mask; + + /* no 80c support in host controller? */ + if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0) + goto cbl40; + + /* check BIOS cable detect results */ + mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; + pci_read_config_byte(pdev, PIIX_IOCFG, &tmp); + if ((tmp & mask) == 0) + goto cbl40; + + ap->cbl = ATA_CBL_PATA80; + return; + +cbl40: + ap->cbl = ATA_CBL_PATA40; + ap->udma_mask &= ATA_UDMA_MASK_40C; +} + +/** + * piix_pata_phy_reset - Probe specified port on PATA host controller + * @ap: Port to probe + * + * Probe PATA phy. + * + * LOCKING: + * None (inherited from caller). + */ + +static void piix_pata_phy_reset(struct ata_port *ap) +{ + if (!pci_test_config_bits(ap->host_set->pdev, + &piix_enable_bits[ap->port_no])) { + ata_port_disable(ap); + printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); + return; + } + + piix_pata_cbl_detect(ap); + + ata_port_probe(ap); + + ata_bus_reset(ap); +} + +/** + * piix_sata_probe - Probe PCI device for present SATA devices + * @ap: Port associated with the PCI device we wish to probe + * + * Reads SATA PCI device's PCI config register Port Configuration + * and Status (PCS) to determine port and device availability. + * + * LOCKING: + * None (inherited from caller). + * + * RETURNS: + * Non-zero if device detected, zero otherwise. + */ +static int piix_sata_probe (struct ata_port *ap) +{ + struct pci_dev *pdev = ap->host_set->pdev; + int combined = (ap->flags & ATA_FLAG_SLAVE_POSS); + int orig_mask, mask, i; + u8 pcs; + + mask = (PIIX_PORT_PRESENT << ap->port_no) | + (PIIX_PORT_ENABLED << ap->port_no); + + pci_read_config_byte(pdev, ICH5_PCS, &pcs); + orig_mask = (int) pcs & 0xff; + + /* TODO: this is vaguely wrong for ICH6 combined mode, + * where only two of the four SATA ports are mapped + * onto a single ATA channel. It is also vaguely inaccurate + * for ICH5, which has only two ports. However, this is ok, + * as further device presence detection code will handle + * any false positives produced here. + */ + + for (i = 0; i < 4; i++) { + mask = (PIIX_PORT_PRESENT << i) | (PIIX_PORT_ENABLED << i); + + if ((orig_mask & mask) == mask) + if (combined || (i == ap->port_no)) + return 1; + } + + return 0; +} + +/** + * piix_sata_phy_reset - Probe specified port on SATA host controller + * @ap: Port to probe + * + * Probe SATA phy. + * + * LOCKING: + * None (inherited from caller). + */ + +static void piix_sata_phy_reset(struct ata_port *ap) +{ + if (!piix_sata_probe(ap)) { + ata_port_disable(ap); + printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id); + return; + } + + ap->cbl = ATA_CBL_SATA; + + ata_port_probe(ap); + + ata_bus_reset(ap); +} + +/** + * piix_set_piomode - Initialize host controller PATA PIO timings + * @ap: Port whose timings we are configuring + * @adev: um + * @pio: PIO mode, 0 - 4 + * + * Set PIO mode for device, in host controller PCI config space. + * + * LOCKING: + * None (inherited from caller). + */ + +static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) +{ + unsigned int pio = adev->pio_mode - XFER_PIO_0; + struct pci_dev *dev = ap->host_set->pdev; + unsigned int is_slave = (adev->devno != 0); + unsigned int master_port= ap->port_no ? 0x42 : 0x40; + unsigned int slave_port = 0x44; + u16 master_data; + u8 slave_data; + + static const /* ISP RTC */ + u8 timings[][2] = { { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; + + pci_read_config_word(dev, master_port, &master_data); + if (is_slave) { + master_data |= 0x4000; + /* enable PPE, IE and TIME */ + master_data |= 0x0070; + pci_read_config_byte(dev, slave_port, &slave_data); + slave_data &= (ap->port_no ? 0x0f : 0xf0); + slave_data |= + (timings[pio][0] << 2) | + (timings[pio][1] << (ap->port_no ? 4 : 0)); + } else { + master_data &= 0xccf8; + /* enable PPE, IE and TIME */ + master_data |= 0x0007; + master_data |= + (timings[pio][0] << 12) | + (timings[pio][1] << 8); + } + pci_write_config_word(dev, master_port, master_data); + if (is_slave) + pci_write_config_byte(dev, slave_port, slave_data); +} + +/** + * piix_set_dmamode - Initialize host controller PATA PIO timings + * @ap: Port whose timings we are configuring + * @adev: um + * @udma: udma mode, 0 - 6 + * + * Set UDMA mode for device, in host controller PCI config space. + * + * LOCKING: + * None (inherited from caller). + */ + +static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev) +{ + unsigned int udma = adev->dma_mode; /* FIXME: MWDMA too */ + struct pci_dev *dev = ap->host_set->pdev; + u8 maslave = ap->port_no ? 0x42 : 0x40; + u8 speed = udma; + unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno; + int a_speed = 3 << (drive_dn * 4); + int u_flag = 1 << drive_dn; + int v_flag = 0x01 << drive_dn; + int w_flag = 0x10 << drive_dn; + int u_speed = 0; + int sitre; + u16 reg4042, reg4a; + u8 reg48, reg54, reg55; + + pci_read_config_word(dev, maslave, ®4042); + DPRINTK("reg4042 = 0x%04x\n", reg4042); + sitre = (reg4042 & 0x4000) ? 1 : 0; + pci_read_config_byte(dev, 0x48, ®48); + pci_read_config_word(dev, 0x4a, ®4a); + pci_read_config_byte(dev, 0x54, ®54); + pci_read_config_byte(dev, 0x55, ®55); + + switch(speed) { + case XFER_UDMA_4: + case XFER_UDMA_2: u_speed = 2 << (drive_dn * 4); break; + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_3: + case XFER_UDMA_1: u_speed = 1 << (drive_dn * 4); break; + case XFER_UDMA_0: u_speed = 0 << (drive_dn * 4); break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: break; + default: + BUG(); + return; + } + + if (speed >= XFER_UDMA_0) { + if (!(reg48 & u_flag)) + pci_write_config_byte(dev, 0x48, reg48 | u_flag); + if (speed == XFER_UDMA_5) { + pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); + } else { + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + } + if ((reg4a & a_speed) != u_speed) + pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); + if (speed > XFER_UDMA_2) { + if (!(reg54 & v_flag)) + pci_write_config_byte(dev, 0x54, reg54 | v_flag); + } else + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); + } else { + if (reg48 & u_flag) + pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); + if (reg4a & a_speed) + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + if (reg54 & v_flag) + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); + if (reg55 & w_flag) + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + } +} + +/* move to PCI layer, integrate w/ MSI stuff */ +static void pci_enable_intx(struct pci_dev *pdev) +{ + u16 pci_command; + + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); + if (pci_command & PCI_COMMAND_INTX_DISABLE) { + pci_command &= ~PCI_COMMAND_INTX_DISABLE; + pci_write_config_word(pdev, PCI_COMMAND, pci_command); + } +} + +#define AHCI_PCI_BAR 5 +#define AHCI_GLOBAL_CTL 0x04 +#define AHCI_ENABLE (1 << 31) +static int piix_disable_ahci(struct pci_dev *pdev) +{ + void *mmio; + unsigned long addr; + u32 tmp; + int rc = 0; + + /* BUG: pci_enable_device has not yet been called. This + * works because this device is usually set up by BIOS. + */ + + addr = pci_resource_start(pdev, AHCI_PCI_BAR); + if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR)) + return 0; + + mmio = ioremap(addr, 64); + if (!mmio) + return -ENOMEM; + + tmp = readl(mmio + AHCI_GLOBAL_CTL); + if (tmp & AHCI_ENABLE) { + tmp &= ~AHCI_ENABLE; + writel(tmp, mmio + AHCI_GLOBAL_CTL); + + tmp = readl(mmio + AHCI_GLOBAL_CTL); + if (tmp & AHCI_ENABLE) + rc = -EIO; + } + + iounmap(mmio); + return rc; +} + +/** + * piix_init_one - Register PIIX ATA PCI device with kernel services + * @pdev: PCI device to register + * @ent: Entry in piix_pci_tbl matching with @pdev + * + * Called from kernel PCI layer. We probe for combined mode (sigh), + * and then hand over control to libata, for it to do the rest. + * + * LOCKING: + * Inherited from PCI layer (may sleep). + * + * RETURNS: + * Zero on success, or -ERRNO value. + */ + +static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + struct ata_port_info *port_info[2]; + unsigned int combined = 0, n_ports = 1; + unsigned int pata_chan = 0, sata_chan = 0; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + + /* no hotplugging support (FIXME) */ + if (!in_module_init) + return -ENODEV; + + port_info[0] = &piix_port_info[ent->driver_data]; + port_info[1] = NULL; + + if (port_info[0]->host_flags & PIIX_FLAG_AHCI) { + int rc = piix_disable_ahci(pdev); + if (rc) + return rc; + } + + if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) { + u8 tmp; + pci_read_config_byte(pdev, ICH5_PMR, &tmp); + + if (tmp & PIIX_COMB) { + combined = 1; + if (tmp & PIIX_COMB_PATA_P0) + sata_chan = 1; + else + pata_chan = 1; + } + } + + /* On ICH5, some BIOSen disable the interrupt using the + * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. + * On ICH6, this bit has the same effect, but only when + * MSI is disabled (and it is disabled, as we don't use + * message-signalled interrupts currently). + */ + if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR) + pci_enable_intx(pdev); + + if (combined) { + port_info[sata_chan] = &piix_port_info[ent->driver_data]; + port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS; + port_info[pata_chan] = &piix_port_info[ich5_pata]; + n_ports++; + + printk(KERN_ERR DRV_NAME ": combined mode not supported\n"); + return -ENODEV; + } + + return ata_pci_init_one(pdev, port_info, n_ports); +} + +/** + * piix_init - + * + * LOCKING: + * + * RETURNS: + * + */ + +static int __init piix_init(void) +{ + int rc; + + DPRINTK("pci_module_init\n"); + rc = pci_module_init(&piix_pci_driver); + if (rc) + return rc; + + in_module_init = 0; + + DPRINTK("scsi_register_host\n"); + rc = scsi_register_module(MODULE_SCSI_HA, &piix_sht); + if (rc) { + rc = -ENODEV; + goto err_out; + } + + DPRINTK("done\n"); + return 0; + +err_out: + pci_unregister_driver(&piix_pci_driver); + return rc; +} + +/** + * piix_exit - + * + * LOCKING: + * + */ + +static void __exit piix_exit(void) +{ + scsi_unregister_module(MODULE_SCSI_HA, &piix_sht); + pci_unregister_driver(&piix_pci_driver); +} + +module_init(piix_init); +module_exit(piix_exit); + diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/dpt_i2o.c linux-2.4.28-pre3/drivers/scsi/dpt_i2o.c --- linux-2.4.27/drivers/scsi/dpt_i2o.c 2003-06-13 14:51:36.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/dpt_i2o.c 2004-09-10 19:36:29.000000000 +0000 @@ -434,7 +434,7 @@ static int adpt_queue(Scsi_Cmnd * cmd, v cmd->scsi_done(cmd); return 0; } - (struct adpt_device*)(cmd->device->hostdata) = pDev; + cmd->device->hostdata = pDev; } pDev->pScsi_dev = cmd->device; @@ -2194,7 +2194,7 @@ static s32 adpt_scsi_register(adpt_hba* printk ("%s: scsi_register returned NULL\n",pHba->name); return -1; } - (adpt_hba*)(host->hostdata[0]) = pHba; + host->hostdata[0] = (unsigned long)pHba; pHba->host = host; host->irq = pHba->pDev->irq;; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/esp.c linux-2.4.28-pre3/drivers/scsi/esp.c --- linux-2.4.27/drivers/scsi/esp.c 2002-11-28 23:53:14.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/esp.c 2004-09-10 19:37:11.000000000 +0000 @@ -4368,4 +4368,4 @@ static Scsi_Host_Template driver_templat #include "scsi_module.c" -EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/fcal.c linux-2.4.28-pre3/drivers/scsi/fcal.c --- linux-2.4.27/drivers/scsi/fcal.c 2001-02-09 19:30:23.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/fcal.c 2004-09-10 19:32:17.000000000 +0000 @@ -300,4 +300,4 @@ static Scsi_Host_Template driver_templat #include "scsi_module.c" -EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/ips.c linux-2.4.28-pre3/drivers/scsi/ips.c --- linux-2.4.27/drivers/scsi/ips.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/ips.c 2004-09-10 19:31:55.000000000 +0000 @@ -133,6 +133,10 @@ /* 6.10.00 - Remove 1G Addressing Limitations */ /* 6.11.xx - Get VersionInfo buffer off the stack ! DDTS 60401 */ /* 6.11.xx - Make Logical Drive Info structure safe for DMA DDTS 60639 */ +/* 7.10.xx - Add highmem_io flag in SCSI Templete for 2.4 kernels */ +/* - Fix path/name for scsi_hosts.h include for 2.6 kernels */ +/* - Fix sort order of 7k */ +/* - Remove 3 unused "inline" functions */ /*****************************************************************************/ /* @@ -176,7 +180,13 @@ #include #include "scsi.h" + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) #include "hosts.h" +#else +#include +#endif + #include "ips.h" #include @@ -197,8 +207,8 @@ MODULE_PARM(ips, "s"); /* * DRIVER_VER */ -#define IPS_VERSION_HIGH "7.00" -#define IPS_VERSION_LOW ".15 " +#define IPS_VERSION_HIGH "7.10" +#define IPS_VERSION_LOW ".18 " #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__) #warning "This driver has only been tested on the x86/ia64/x86_64 platforms" @@ -277,9 +287,9 @@ static Scsi_Host_Template ips_driver_tem .use_clustering = ENABLE_CLUSTERING, #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) .use_new_eh_code = 1, -#ifdef RHEL3 - .vary_io = 1, #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + .highmem_io = 1, #endif }; @@ -477,21 +487,17 @@ static uint32_t ips_statupd_copperhead(i static uint32_t ips_statupd_copperhead_memio(ips_ha_t *); static uint32_t ips_statupd_morpheus(ips_ha_t *); static ips_scb_t *ips_getscb(ips_ha_t *); -static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *); -static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *); -static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *); -static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *); -static inline void ips_putq_copp_head(ips_copp_queue_t *, - ips_copp_wait_item_t *); -static inline void ips_putq_copp_tail(ips_copp_queue_t *, +static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *); +static void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *); +static void ips_putq_copp_tail(ips_copp_queue_t *, ips_copp_wait_item_t *); -static inline ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *); -static inline ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *); -static inline Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *); -static inline Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *); -static inline ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *, +static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *); +static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *); +static Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *); +static Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *); +static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *, ips_copp_wait_item_t *); -static inline ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *); +static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *); static int ips_is_passthru(Scsi_Cmnd *); static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int); @@ -1888,7 +1894,7 @@ ips_flash_bios(ips_ha_t * ha, ips_passth /* Fill in a single scb sg_list element from an address */ /* return a -1 if a breakup occurred */ /****************************************************************************/ -static inline int +static int ips_fill_scb_sg_single(ips_ha_t * ha, dma_addr_t busaddr, ips_scb_t * scb, int indx, unsigned int e_len) { @@ -2953,7 +2959,7 @@ ips_next(ips_ha_t * ha, int intr) /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline void +static void ips_putq_scb_head(ips_scb_queue_t * queue, ips_scb_t * item) { METHOD_TRACE("ips_putq_scb_head", 1); @@ -2972,38 +2978,6 @@ ips_putq_scb_head(ips_scb_queue_t * queu /****************************************************************************/ /* */ -/* Routine Name: ips_putq_scb_tail */ -/* */ -/* Routine Description: */ -/* */ -/* Add an item to the tail of the queue */ -/* */ -/* ASSUMED to be called from within the HA lock */ -/* */ -/****************************************************************************/ -static inline void -ips_putq_scb_tail(ips_scb_queue_t * queue, ips_scb_t * item) -{ - METHOD_TRACE("ips_putq_scb_tail", 1); - - if (!item) - return; - - item->q_next = NULL; - - if (queue->tail) - queue->tail->q_next = item; - - queue->tail = item; - - if (!queue->head) - queue->head = item; - - queue->count++; -} - -/****************************************************************************/ -/* */ /* Routine Name: ips_removeq_scb_head */ /* */ /* Routine Description: */ @@ -3013,7 +2987,7 @@ ips_putq_scb_tail(ips_scb_queue_t * queu /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline ips_scb_t * +static ips_scb_t * ips_removeq_scb_head(ips_scb_queue_t * queue) { ips_scb_t *item; @@ -3048,7 +3022,7 @@ ips_removeq_scb_head(ips_scb_queue_t * q /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline ips_scb_t * +static ips_scb_t * ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item) { ips_scb_t *p; @@ -3085,34 +3059,6 @@ ips_removeq_scb(ips_scb_queue_t * queue, /****************************************************************************/ /* */ -/* Routine Name: ips_putq_wait_head */ -/* */ -/* Routine Description: */ -/* */ -/* Add an item to the head of the queue */ -/* */ -/* ASSUMED to be called from within the HA lock */ -/* */ -/****************************************************************************/ -static inline void -ips_putq_wait_head(ips_wait_queue_t * queue, Scsi_Cmnd * item) -{ - METHOD_TRACE("ips_putq_wait_head", 1); - - if (!item) - return; - - item->host_scribble = (char *) queue->head; - queue->head = item; - - if (!queue->tail) - queue->tail = item; - - queue->count++; -} - -/****************************************************************************/ -/* */ /* Routine Name: ips_putq_wait_tail */ /* */ /* Routine Description: */ @@ -3122,7 +3068,7 @@ ips_putq_wait_head(ips_wait_queue_t * qu /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline void +static void ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item) { METHOD_TRACE("ips_putq_wait_tail", 1); @@ -3154,7 +3100,7 @@ ips_putq_wait_tail(ips_wait_queue_t * qu /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline Scsi_Cmnd * +static Scsi_Cmnd * ips_removeq_wait_head(ips_wait_queue_t * queue) { Scsi_Cmnd *item; @@ -3189,7 +3135,7 @@ ips_removeq_wait_head(ips_wait_queue_t * /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline Scsi_Cmnd * +static Scsi_Cmnd * ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item) { Scsi_Cmnd *p; @@ -3226,34 +3172,6 @@ ips_removeq_wait(ips_wait_queue_t * queu /****************************************************************************/ /* */ -/* Routine Name: ips_putq_copp_head */ -/* */ -/* Routine Description: */ -/* */ -/* Add an item to the head of the queue */ -/* */ -/* ASSUMED to be called from within the HA lock */ -/* */ -/****************************************************************************/ -static inline void -ips_putq_copp_head(ips_copp_queue_t * queue, ips_copp_wait_item_t * item) -{ - METHOD_TRACE("ips_putq_copp_head", 1); - - if (!item) - return; - - item->next = queue->head; - queue->head = item; - - if (!queue->tail) - queue->tail = item; - - queue->count++; -} - -/****************************************************************************/ -/* */ /* Routine Name: ips_putq_copp_tail */ /* */ /* Routine Description: */ @@ -3263,7 +3181,7 @@ ips_putq_copp_head(ips_copp_queue_t * qu /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline void +static void ips_putq_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item) { METHOD_TRACE("ips_putq_copp_tail", 1); @@ -3295,7 +3213,7 @@ ips_putq_copp_tail(ips_copp_queue_t * qu /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline ips_copp_wait_item_t * +static ips_copp_wait_item_t * ips_removeq_copp_head(ips_copp_queue_t * queue) { ips_copp_wait_item_t *item; @@ -3330,7 +3248,7 @@ ips_removeq_copp_head(ips_copp_queue_t * /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline ips_copp_wait_item_t * +static ips_copp_wait_item_t * ips_removeq_copp(ips_copp_queue_t * queue, ips_copp_wait_item_t * item) { ips_copp_wait_item_t *p; @@ -4014,7 +3932,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb->cmd.logical_info.reserved2 = 0; scb->cmd.logical_info.reserved3 = 0; scb->data_len = sizeof (IPS_LD_INFO); - scb->data_busaddr = ha->logical_drive_info_dma_addr; + scb->data_busaddr = ha->logical_drive_info_dma_addr; scb->flags = 0; scb->cmd.logical_info.buffer_addr = scb->data_busaddr; ret = IPS_SUCCESS; @@ -4340,7 +4258,7 @@ ips_online(ips_ha_t * ha, ips_scb_t * sc if ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1) { memset(ha->logical_drive_info, 0, sizeof (IPS_LD_INFO)); - return (0); + return (0); } if (ha->logical_drive_info->drive_info[scb->target_id].state != @@ -4579,7 +4497,7 @@ ips_free(ips_ha_t * ha) if (ha->logical_drive_info) { pci_free_consistent(ha->pcidev, sizeof (IPS_LD_INFO), - ha->logical_drive_info, + ha->logical_drive_info, ha->logical_drive_info_dma_addr); ha->logical_drive_info = NULL; } @@ -4773,7 +4691,7 @@ ips_getscb(ips_ha_t * ha) } ha->scb_freelist = scb->q_next; - scb->flags = 0; + scb->flags = 0; scb->q_next = NULL; ips_init_scb(ha, scb); @@ -6831,7 +6749,7 @@ ips_version_check(ips_ha_t * ha, int int METHOD_TRACE("ips_version_check", 1); - VersionInfo = ( IPS_VERSION_DATA * ) ha->ioctl_data; + VersionInfo = ( IPS_VERSION_DATA * ) ha->ioctl_data; memset(FirmwareVersion, 0, IPS_COMPAT_ID_LENGTH + 1); memset(BiosVersion, 0, IPS_COMPAT_ID_LENGTH + 1); @@ -6843,7 +6761,7 @@ ips_version_check(ips_ha_t * ha, int int rc = IPS_FAILURE; if (ha->subsys->param[4] & IPS_GET_VERSION_SUPPORT) { /* If Versioning is Supported */ /* Get the Version Info with a Get Version Command */ - memset( VersionInfo, 0, sizeof (IPS_VERSION_DATA)); + memset( VersionInfo, 0, sizeof (IPS_VERSION_DATA)); rc = ips_get_version_info(ha, ha->ioctl_busaddr, intr); if (rc == IPS_SUCCESS) memcpy(FirmwareVersion, VersionInfo->compatibilityId, @@ -6999,7 +6917,6 @@ ips_order_controllers(void) for (j = position; j < ips_num_controllers; j++) { switch (ips_ha[j]->ad_type) { case IPS_ADTYPE_SERVERAID6M: - case IPS_ADTYPE_SERVERAID7k: case IPS_ADTYPE_SERVERAID7M: if (nvram->adapter_order[i] == 'M') { ips_shift_controllers(position, @@ -7020,6 +6937,7 @@ ips_order_controllers(void) case IPS_ADTYPE_SERVERAID6I: case IPS_ADTYPE_SERVERAID5I2: case IPS_ADTYPE_SERVERAID5I1: + case IPS_ADTYPE_SERVERAID7k: if (nvram->adapter_order[i] == 'S') { ips_shift_controllers(position, j); @@ -7548,6 +7466,15 @@ ips_init_phase2(int index) MODULE_LICENSE("GPL"); #endif +#ifdef MODULE_DESCRIPTION +MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING); +#endif + +#ifdef MODULE_VERSION +MODULE_VERSION(IPS_VER_STRING); +#endif + + /* * Overrides for Emacs so that we almost follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/ips.h linux-2.4.28-pre3/drivers/scsi/ips.h --- linux-2.4.27/drivers/scsi/ips.h 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/ips.h 2004-09-10 19:33:19.000000000 +0000 @@ -95,14 +95,15 @@ #define scsi_set_pci_device(sh,dev) (0) #endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) - typedef void irqreturn_t; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + + #ifndef irqreturn_t + typedef void irqreturn_t; + #endif + #define IRQ_NONE #define IRQ_HANDLED #define IRQ_RETVAL(x) - #endif - - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #define IPS_REGISTER_HOSTS(SHT) scsi_register_module(MODULE_SCSI_HA,SHT) #define IPS_UNREGISTER_HOSTS(SHT) scsi_unregister_module(MODULE_SCSI_HA,SHT) #define IPS_ADD_HOST(shost,device) @@ -1213,13 +1214,13 @@ typedef struct { #define IPS_VER_MAJOR 7 #define IPS_VER_MAJOR_STRING "7" -#define IPS_VER_MINOR 00 -#define IPS_VER_MINOR_STRING "00" -#define IPS_VER_BUILD 15 -#define IPS_VER_BUILD_STRING "15" -#define IPS_VER_STRING "7.00.15" +#define IPS_VER_MINOR 10 +#define IPS_VER_MINOR_STRING "10" +#define IPS_VER_BUILD 18 +#define IPS_VER_BUILD_STRING "18" +#define IPS_VER_STRING "7.10.18" #define IPS_RELEASE_ID 0x00020000 -#define IPS_BUILD_IDENT 625 +#define IPS_BUILD_IDENT 731 #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved." #define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to 2004. All Rights Reserved." #define IPS_DELLCOPYRIGHT_STRING "(c) Copyright Dell 2004. All Rights Reserved." @@ -1230,32 +1231,35 @@ typedef struct { #define IPS_VER_SERVERAID2 "2.88.13" #define IPS_VER_NAVAJO "2.88.13" #define IPS_VER_SERVERAID3 "6.10.24" -#define IPS_VER_SERVERAID4H "7.00.15" -#define IPS_VER_SERVERAID4MLx "7.00.15" -#define IPS_VER_SARASOTA "7.00.15" -#define IPS_VER_MARCO "7.00.15" -#define IPS_VER_SEBRING "7.00.15" +#define IPS_VER_SERVERAID4H "7.10.11" +#define IPS_VER_SERVERAID4MLx "7.10.18" +#define IPS_VER_SARASOTA "7.10.18" +#define IPS_VER_MARCO "7.10.18" +#define IPS_VER_SEBRING "7.10.18" +#define IPS_VER_KEYWEST "7.10.18" /* Compatability IDs for various adapters */ #define IPS_COMPAT_UNKNOWN "" -#define IPS_COMPAT_CURRENT "SB610" +#define IPS_COMPAT_CURRENT "KW710" #define IPS_COMPAT_SERVERAID1 "2.25.01" #define IPS_COMPAT_SERVERAID2 "2.88.13" #define IPS_COMPAT_NAVAJO "2.88.13" #define IPS_COMPAT_KIOWA "2.88.13" #define IPS_COMPAT_SERVERAID3H "SB610" #define IPS_COMPAT_SERVERAID3L "SB610" -#define IPS_COMPAT_SERVERAID4H "SB610" -#define IPS_COMPAT_SERVERAID4M "SB610" -#define IPS_COMPAT_SERVERAID4L "SB610" -#define IPS_COMPAT_SERVERAID4Mx "SB610" -#define IPS_COMPAT_SERVERAID4Lx "SB610" -#define IPS_COMPAT_SARASOTA "SB610" -#define IPS_COMPAT_MARCO "SB610" -#define IPS_COMPAT_SEBRING "SB610" -#define IPS_COMPAT_BIOS "SB610" +#define IPS_COMPAT_SERVERAID4H "KW710" +#define IPS_COMPAT_SERVERAID4M "KW710" +#define IPS_COMPAT_SERVERAID4L "KW710" +#define IPS_COMPAT_SERVERAID4Mx "KW710" +#define IPS_COMPAT_SERVERAID4Lx "KW710" +#define IPS_COMPAT_SARASOTA "KW710" +#define IPS_COMPAT_MARCO "KW710" +#define IPS_COMPAT_SEBRING "KW710" +#define IPS_COMPAT_TAMPA "KW710" +#define IPS_COMPAT_KEYWEST "KW710" +#define IPS_COMPAT_BIOS "KW710" -#define IPS_COMPAT_MAX_ADAPTER_TYPE 16 +#define IPS_COMPAT_MAX_ADAPTER_TYPE 18 #define IPS_COMPAT_ID_LENGTH 8 #define IPS_DEFINE_COMPAT_TABLE(tablename) \ @@ -1275,7 +1279,9 @@ typedef struct { IPS_COMPAT_SARASOTA, /* one-channel variety of SARASOTA */ \ IPS_COMPAT_SARASOTA, /* two-channel variety of SARASOTA */ \ IPS_COMPAT_MARCO, \ - IPS_COMPAT_SEBRING \ + IPS_COMPAT_SEBRING, \ + IPS_COMPAT_TAMPA, \ + IPS_COMPAT_KEYWEST \ } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/libata-core.c linux-2.4.28-pre3/drivers/scsi/libata-core.c --- linux-2.4.27/drivers/scsi/libata-core.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/libata-core.c 2004-09-10 19:35:18.000000000 +0000 @@ -42,6 +42,7 @@ #include #include #include +#include #include "libata.h" @@ -49,13 +50,14 @@ static unsigned int ata_busy_sleep (stru unsigned long tmout_pat, unsigned long tmout); static void __ata_dev_select (struct ata_port *ap, unsigned int device); -static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat); -static void ata_host_set_pio(struct ata_port *ap); -static void ata_host_set_udma(struct ata_port *ap); -static void ata_dev_set_pio(struct ata_port *ap, unsigned int device); -static void ata_dev_set_udma(struct ata_port *ap, unsigned int device); static void ata_set_mode(struct ata_port *ap); -static int ata_qc_issue_prot(struct ata_queued_cmd *qc); +static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); +static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift); +static int fgb(u32 bitmap); +static int ata_choose_xfer_mode(struct ata_port *ap, + u8 *xfer_mode_out, + unsigned int *xfer_shift_out); +static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat); static unsigned int ata_unique_id = 1; static LIST_HEAD(ata_probe_list); @@ -65,37 +67,6 @@ MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Library module for ATA devices"); MODULE_LICENSE("GPL"); -static const char * thr_state_name[] = { - "THR_UNKNOWN", - "THR_PORT_RESET", - "THR_AWAIT_DEATH", - "THR_PROBE_FAILED", - "THR_IDLE", - "THR_PROBE_SUCCESS", - "THR_PROBE_START", -}; - -/** - * ata_thr_state_name - convert thread state enum to string - * @thr_state: thread state to be converted to string - * - * Converts the specified thread state id to a constant C string. - * - * LOCKING: - * None. - * - * RETURNS: - * The THR_xxx-prefixed string naming the specified thread - * state id, or the string "". - */ - -static const char *ata_thr_state_name(unsigned int thr_state) -{ - if (thr_state < ARRAY_SIZE(thr_state_name)) - return thr_state_name[thr_state]; - return ""; -} - /** * msleep - sleep for a number of milliseconds * @msecs: number of milliseconds to sleep @@ -113,6 +84,11 @@ static void msleep(unsigned long msecs) schedule_timeout(msecs_to_jiffies(msecs) + 1); } +void libata_msleep(unsigned long msecs) +{ + msleep(msecs); +} + /** * ata_tf_load_pio - send taskfile registers to host controller * @ap: Port to which output is sent @@ -574,7 +550,7 @@ static void ata_dev_set_protocol(struct dev->write_cmd = (cmd >> 8) & 0xff; } -static const char * udma_str[] = { +static const char * xfer_mode_str[] = { "UDMA/16", "UDMA/25", "UDMA/33", @@ -583,6 +559,14 @@ static const char * udma_str[] = { "UDMA/100", "UDMA/133", "UDMA7", + "MWDMA0", + "MWDMA1", + "MWDMA2", + "PIO0", + "PIO1", + "PIO2", + "PIO3", + "PIO4", }; /** @@ -600,16 +584,24 @@ static const char * udma_str[] = { * @udma_mask, or the constant C string "". */ -static const char *ata_udma_string(unsigned int udma_mask) +static const char *ata_mode_string(unsigned int mask) { int i; - for (i = 7; i >= 0; i--) { - if (udma_mask & (1 << i)) - return udma_str[i]; - } + for (i = 7; i >= 0; i--) + if (mask & (1 << i)) + goto out; + for (i = ATA_SHIFT_MWDMA + 2; i >= ATA_SHIFT_MWDMA; i--) + if (mask & (1 << i)) + goto out; + for (i = ATA_SHIFT_PIO + 4; i >= ATA_SHIFT_PIO; i--) + if (mask & (1 << i)) + goto out; return ""; + +out: + return xfer_mode_str[i]; } /** @@ -980,10 +972,14 @@ static void ata_dev_identify(struct ata_ { struct ata_device *dev = &ap->device[device]; unsigned int i; - u16 tmp, udma_modes; + u16 tmp; + unsigned long xfer_modes; u8 status; - struct ata_taskfile tf; unsigned int using_edd; + DECLARE_COMPLETION(wait); + struct ata_queued_cmd *qc; + unsigned long flags; + int rc; if (!ata_dev_present(dev)) { DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", @@ -1003,27 +999,34 @@ static void ata_dev_identify(struct ata_ ata_dev_select(ap, device, 1, 1); /* select device 0/1 */ -retry: - ata_tf_init(ap, &tf, device); - tf.ctl |= ATA_NIEN; - tf.protocol = ATA_PROT_PIO; + qc = ata_qc_new_init(ap, dev); + BUG_ON(qc == NULL); + ata_sg_init_one(qc, dev->id, sizeof(dev->id)); + qc->pci_dma_dir = PCI_DMA_FROMDEVICE; + qc->tf.protocol = ATA_PROT_PIO; + qc->nsect = 1; + +retry: if (dev->class == ATA_DEV_ATA) { - tf.command = ATA_CMD_ID_ATA; + qc->tf.command = ATA_CMD_ID_ATA; DPRINTK("do ATA identify\n"); } else { - tf.command = ATA_CMD_ID_ATAPI; + qc->tf.command = ATA_CMD_ID_ATAPI; DPRINTK("do ATAPI identify\n"); } - ata_tf_to_host(ap, &tf); + qc->waiting = &wait; + qc->complete_fn = ata_qc_complete_noop; - /* crazy ATAPI devices... */ - if (dev->class == ATA_DEV_ATAPI) - msleep(150); + spin_lock_irqsave(&ap->host_set->lock, flags); + rc = ata_qc_issue(qc); + spin_unlock_irqrestore(&ap->host_set->lock, flags); - if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) + if (rc) goto err_out; + else + wait_for_completion(&wait); status = ata_chk_status(ap); if (status & ATA_ERR) { @@ -1038,44 +1041,21 @@ retry: * ATA software reset (SRST, the default) does not appear * to have this problem. */ - if ((using_edd) && (tf.command == ATA_CMD_ID_ATA)) { + if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) { u8 err = ata_chk_err(ap); if (err & ATA_ABORTED) { dev->class = ATA_DEV_ATAPI; + qc->cursg = 0; + qc->cursg_ofs = 0; + qc->cursect = 0; + qc->nsect = 1; goto retry; } } goto err_out; } - /* make sure we have BSY=0, DRQ=1 */ - if ((status & ATA_DRQ) == 0) { - printk(KERN_WARNING "ata%u: dev %u (ATA%s?) not returning id page (0x%x)\n", - ap->id, device, - dev->class == ATA_DEV_ATA ? "" : "PI", - status); - goto err_out; - } - - /* read IDENTIFY [X] DEVICE page */ - if (ap->flags & ATA_FLAG_MMIO) { - for (i = 0; i < ATA_ID_WORDS; i++) - dev->id[i] = readw((void *)ap->ioaddr.data_addr); - } else - for (i = 0; i < ATA_ID_WORDS; i++) - dev->id[i] = inw(ap->ioaddr.data_addr); - - /* wait for host_idle */ - status = ata_wait_idle(ap); - if (status & (ATA_BUSY | ATA_DRQ)) { - printk(KERN_WARNING "ata%u: dev %u (ATA%s?) error after id page (0x%x)\n", - ap->id, device, - dev->class == ATA_DEV_ATA ? "" : "PI", - status); - goto err_out; - } - - ata_irq_on(ap); /* re-enable interrupts */ + swap_buf_le16(dev->id, ATA_ID_WORDS); /* print device capabilities */ printk(KERN_DEBUG "ata%u: dev %u cfg " @@ -1095,12 +1075,13 @@ retry: goto err_out_nosup; } - /* we require UDMA support */ - udma_modes = - tmp = dev->id[ATA_ID_UDMA_MODES]; - if ((tmp & 0xff) == 0) { - printk(KERN_DEBUG "ata%u: no udma\n", ap->id); - goto err_out_nosup; + /* quick-n-dirty find max transfer mode; for printk only */ + xfer_modes = dev->id[ATA_ID_UDMA_MODES]; + if (!xfer_modes) + xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA; + if (!xfer_modes) { + xfer_modes = (dev->id[ATA_ID_PIO_MODES]) << (ATA_SHIFT_PIO + 3); + xfer_modes |= (0x7 << ATA_SHIFT_PIO); } ata_dump_id(dev); @@ -1133,7 +1114,7 @@ retry: /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n", ap->id, device, - ata_udma_string(udma_modes), + ata_mode_string(xfer_modes), (unsigned long long)dev->n_sectors, dev->flags & ATA_DFLAG_LBA48 ? " lba48" : ""); } @@ -1143,15 +1124,18 @@ retry: if (ata_id_is_ata(dev)) /* sanity check */ goto err_out_nosup; - /* see if 16-byte commands supported */ - tmp = dev->id[0] & 0x3; - if (tmp == 1) - ap->host->max_cmd_len = 16; + rc = atapi_cdb_len(dev->id); + if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { + printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); + goto err_out_nosup; + } + ap->cdb_len = (unsigned int) rc; + ap->host->max_cmd_len = (unsigned char) ap->cdb_len; /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", ap->id, device, - ata_udma_string(udma_modes)); + ata_mode_string(xfer_modes)); } DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); @@ -1167,13 +1151,16 @@ err_out: } /** - * ata_port_reset - - * @ap: + * ata_bus_probe - Reset and probe ATA bus + * @ap: Bus to probe * * LOCKING: + * + * RETURNS: + * Zero on success, non-zero on error. */ -static void ata_port_reset(struct ata_port *ap) +static int ata_bus_probe(struct ata_port *ap) { unsigned int i, found = 0; @@ -1197,14 +1184,12 @@ static void ata_port_reset(struct ata_po if (ap->flags & ATA_FLAG_PORT_DISABLED) goto err_out_disable; - ap->thr_state = THR_PROBE_SUCCESS; - - return; + return 0; err_out_disable: ap->ops->port_disable(ap); err_out: - ap->thr_state = THR_PROBE_FAILED; + return -1; } /** @@ -1281,6 +1266,101 @@ void ata_port_disable(struct ata_port *a ap->flags |= ATA_FLAG_PORT_DISABLED; } +static struct { + unsigned int shift; + u8 base; +} xfer_mode_classes[] = { + { ATA_SHIFT_UDMA, XFER_UDMA_0 }, + { ATA_SHIFT_MWDMA, XFER_MW_DMA_0 }, + { ATA_SHIFT_PIO, XFER_PIO_0 }, +}; + +static inline u8 base_from_shift(unsigned int shift) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) + if (xfer_mode_classes[i].shift == shift) + return xfer_mode_classes[i].base; + + return 0xff; +} + +static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) +{ + int ofs, idx; + u8 base; + + if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) + return; + + if (dev->xfer_shift == ATA_SHIFT_PIO) + dev->flags |= ATA_DFLAG_PIO; + + ata_dev_set_xfermode(ap, dev); + + base = base_from_shift(dev->xfer_shift); + ofs = dev->xfer_mode - base; + idx = ofs + dev->xfer_shift; + WARN_ON(idx >= ARRAY_SIZE(xfer_mode_str)); + + DPRINTK("idx=%d xfer_shift=%u, xfer_mode=0x%x, base=0x%x, offset=%d\n", + idx, dev->xfer_shift, (int)dev->xfer_mode, (int)base, ofs); + + printk(KERN_INFO "ata%u: dev %u configured for %s\n", + ap->id, dev->devno, xfer_mode_str[idx]); +} + +static int ata_host_set_pio(struct ata_port *ap) +{ + unsigned int mask; + int x, i; + u8 base, xfer_mode; + + mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO); + x = fgb(mask); + if (x < 0) { + printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); + return -1; + } + + base = base_from_shift(ATA_SHIFT_PIO); + xfer_mode = base + x; + + DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n", + (int)base, (int)xfer_mode, mask, x); + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + if (ata_dev_present(dev)) { + dev->pio_mode = xfer_mode; + dev->xfer_mode = xfer_mode; + dev->xfer_shift = ATA_SHIFT_PIO; + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, dev); + } + } + + return 0; +} + +static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, + unsigned int xfer_shift) +{ + int i; + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + if (ata_dev_present(dev)) { + dev->dma_mode = xfer_mode; + dev->xfer_mode = xfer_mode; + dev->xfer_shift = xfer_shift; + if (ap->ops->set_dmamode) + ap->ops->set_dmamode(ap, dev); + } + } +} + /** * ata_set_mode - Program timings and issue SET FEATURES - XFER * @ap: port on which timings will be programmed @@ -1290,29 +1370,28 @@ void ata_port_disable(struct ata_port *a */ static void ata_set_mode(struct ata_port *ap) { - unsigned int force_pio, i; - - ata_host_set_pio(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) - return; + unsigned int i, xfer_shift; + u8 xfer_mode; + int rc; - ata_host_set_udma(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) - return; + /* step 1: always set host PIO timings */ + rc = ata_host_set_pio(ap); + if (rc) + goto err_out; -#ifdef ATA_FORCE_PIO - force_pio = 1; -#else - force_pio = 0; -#endif + /* step 2: choose the best data xfer mode */ + xfer_mode = xfer_shift = 0; + rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift); + if (rc) + goto err_out; - if (force_pio) { - ata_dev_set_pio(ap, 0); - ata_dev_set_pio(ap, 1); - } else { - ata_dev_set_udma(ap, 0); - ata_dev_set_udma(ap, 1); - } + /* step 3: if that xfer mode isn't PIO, set host DMA timings */ + if (xfer_shift != ATA_SHIFT_PIO) + ata_host_set_dma(ap, xfer_mode, xfer_shift); + + /* step 4: update devices' xfer mode */ + ata_dev_set_mode(ap, &ap->device[0]); + ata_dev_set_mode(ap, &ap->device[1]); if (ap->flags & ATA_FLAG_PORT_DISABLED) return; @@ -1324,6 +1403,11 @@ static void ata_set_mode(struct ata_port struct ata_device *dev = &ap->device[i]; ata_dev_set_protocol(dev); } + + return; + +err_out: + ata_port_disable(ap); } /** @@ -1585,116 +1669,102 @@ err_out: DPRINTK("EXIT\n"); } -/** - * ata_host_set_pio - - * @ap: - * - * LOCKING: - */ - -static void ata_host_set_pio(struct ata_port *ap) +static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift) { struct ata_device *master, *slave; - unsigned int pio, i; - u16 mask; + unsigned int mask; master = &ap->device[0]; slave = &ap->device[1]; assert (ata_dev_present(master) || ata_dev_present(slave)); - mask = ap->pio_mask; - if (ata_dev_present(master)) - mask &= (master->id[ATA_ID_PIO_MODES] & 0x03); - if (ata_dev_present(slave)) - mask &= (slave->id[ATA_ID_PIO_MODES] & 0x03); - - /* require pio mode 3 or 4 support for host and all devices */ - if (mask == 0) { - printk(KERN_WARNING "ata%u: no PIO3/4 support, ignoring\n", - ap->id); - goto err_out; + if (shift == ATA_SHIFT_UDMA) { + mask = ap->udma_mask; + if (ata_dev_present(master)) + mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff); + if (ata_dev_present(slave)) + mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff); + } + else if (shift == ATA_SHIFT_MWDMA) { + mask = ap->mwdma_mask; + if (ata_dev_present(master)) + mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07); + if (ata_dev_present(slave)) + mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07); + } + else if (shift == ATA_SHIFT_PIO) { + mask = ap->pio_mask; + if (ata_dev_present(master)) { + /* spec doesn't return explicit support for + * PIO0-2, so we fake it + */ + u16 tmp_mode = master->id[ATA_ID_PIO_MODES] & 0x03; + tmp_mode <<= 3; + tmp_mode |= 0x7; + mask &= tmp_mode; + } + if (ata_dev_present(slave)) { + /* spec doesn't return explicit support for + * PIO0-2, so we fake it + */ + u16 tmp_mode = slave->id[ATA_ID_PIO_MODES] & 0x03; + tmp_mode <<= 3; + tmp_mode |= 0x7; + mask &= tmp_mode; + } + } + else { + mask = 0xffffffff; /* shut up compiler warning */ + BUG(); } - pio = (mask & ATA_ID_PIO4) ? 4 : 3; - for (i = 0; i < ATA_MAX_DEVICES; i++) - if (ata_dev_present(&ap->device[i])) { - ap->device[i].pio_mode = (pio == 3) ? - XFER_PIO_3 : XFER_PIO_4; - if (ap->ops->set_piomode) - ap->ops->set_piomode(ap, &ap->device[i], pio); - } + return mask; +} - return; +/* find greatest bit */ +static int fgb(u32 bitmap) +{ + unsigned int i; + int x = -1; -err_out: - ap->ops->port_disable(ap); + for (i = 0; i < 32; i++) + if (bitmap & (1 << i)) + x = i; + + return x; } /** - * ata_host_set_udma - + * ata_choose_xfer_mode - * @ap: * * LOCKING: + * + * RETURNS: + * Zero on success, negative on error. */ -static void ata_host_set_udma(struct ata_port *ap) -{ - struct ata_device *master, *slave; - u16 mask; - unsigned int i, j; - int udma_mode = -1; - - master = &ap->device[0]; - slave = &ap->device[1]; - - assert (ata_dev_present(master) || ata_dev_present(slave)); - assert ((ap->flags & ATA_FLAG_PORT_DISABLED) == 0); - - DPRINTK("udma masks: host 0x%X, master 0x%X, slave 0x%X\n", - ap->udma_mask, - (!ata_dev_present(master)) ? 0xff : - (master->id[ATA_ID_UDMA_MODES] & 0xff), - (!ata_dev_present(slave)) ? 0xff : - (slave->id[ATA_ID_UDMA_MODES] & 0xff)); - - mask = ap->udma_mask; - if (ata_dev_present(master)) - mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff); - if (ata_dev_present(slave)) - mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff); - - i = XFER_UDMA_7; - while (i >= XFER_UDMA_0) { - j = i - XFER_UDMA_0; - DPRINTK("mask 0x%X i 0x%X j %u\n", mask, i, j); - if (mask & (1 << j)) { - udma_mode = i; - break; +static int ata_choose_xfer_mode(struct ata_port *ap, + u8 *xfer_mode_out, + unsigned int *xfer_shift_out) +{ + unsigned int mask, shift; + int x, i; + + for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) { + shift = xfer_mode_classes[i].shift; + mask = ata_get_mode_mask(ap, shift); + + x = fgb(mask); + if (x >= 0) { + *xfer_mode_out = xfer_mode_classes[i].base + x; + *xfer_shift_out = shift; + return 0; } - - i--; - } - - /* require udma for host and all attached devices */ - if (udma_mode < 0) { - printk(KERN_WARNING "ata%u: no UltraDMA support, ignoring\n", - ap->id); - goto err_out; } - for (i = 0; i < ATA_MAX_DEVICES; i++) - if (ata_dev_present(&ap->device[i])) { - ap->device[i].udma_mode = udma_mode; - if (ap->ops->set_udmamode) - ap->ops->set_udmamode(ap, &ap->device[i], - udma_mode); - } - - return; - -err_out: - ap->ops->port_disable(ap); + return -1; } /** @@ -1707,89 +1777,39 @@ err_out: static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) { - struct ata_taskfile tf; + DECLARE_COMPLETION(wait); + struct ata_queued_cmd *qc; + int rc; + unsigned long flags; /* set up set-features taskfile */ DPRINTK("set features - xfer mode\n"); - ata_tf_init(ap, &tf, dev->devno); - tf.ctl |= ATA_NIEN; - tf.command = ATA_CMD_SET_FEATURES; - tf.feature = SETFEATURES_XFER; - tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; - tf.protocol = ATA_PROT_NODATA; - if (dev->flags & ATA_DFLAG_PIO) - tf.nsect = dev->pio_mode; - else - tf.nsect = dev->udma_mode; - /* do bus reset */ - ata_tf_to_host(ap, &tf); + qc = ata_qc_new_init(ap, dev); + BUG_ON(qc == NULL); - /* crazy ATAPI devices... */ - if (dev->class == ATA_DEV_ATAPI) - msleep(150); + qc->tf.command = ATA_CMD_SET_FEATURES; + qc->tf.feature = SETFEATURES_XFER; + qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + qc->tf.protocol = ATA_PROT_NODATA; + qc->tf.nsect = dev->xfer_mode; - ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + qc->waiting = &wait; + qc->complete_fn = ata_qc_complete_noop; - ata_irq_on(ap); /* re-enable interrupts */ + spin_lock_irqsave(&ap->host_set->lock, flags); + rc = ata_qc_issue(qc); + spin_unlock_irqrestore(&ap->host_set->lock, flags); - ata_wait_idle(ap); + if (rc) + ata_port_disable(ap); + else + wait_for_completion(&wait); DPRINTK("EXIT\n"); } /** - * ata_dev_set_udma - Set ATA device's transfer mode to Ultra DMA - * @ap: Port associated with device @dev - * @device: Device whose mode will be set - * - * LOCKING: - */ - -static void ata_dev_set_udma(struct ata_port *ap, unsigned int device) -{ - struct ata_device *dev = &ap->device[device]; - - if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) - return; - - ata_dev_set_xfermode(ap, dev); - - assert((dev->udma_mode >= XFER_UDMA_0) && - (dev->udma_mode <= XFER_UDMA_7)); - printk(KERN_INFO "ata%u: dev %u configured for %s\n", - ap->id, device, - udma_str[dev->udma_mode - XFER_UDMA_0]); -} - -/** - * ata_dev_set_pio - Set ATA device's transfer mode to PIO - * @ap: Port associated with device @dev - * @device: Device whose mode will be set - * - * LOCKING: - */ - -static void ata_dev_set_pio(struct ata_port *ap, unsigned int device) -{ - struct ata_device *dev = &ap->device[device]; - - if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) - return; - - /* force PIO mode */ - dev->flags |= ATA_DFLAG_PIO; - - ata_dev_set_xfermode(ap, dev); - - assert((dev->pio_mode >= XFER_PIO_3) && - (dev->pio_mode <= XFER_PIO_4)); - printk(KERN_INFO "ata%u: dev %u configured for PIO%c\n", - ap->id, device, - dev->pio_mode == 3 ? '3' : '4'); -} - -/** * ata_sg_clean - * @qc: * @@ -1799,37 +1819,35 @@ static void ata_dev_set_pio(struct ata_p static void ata_sg_clean(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - struct scsi_cmnd *cmd = qc->scsicmd; struct scatterlist *sg = qc->sg; - int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + int dir = qc->pci_dma_dir; - assert(dir == SCSI_DATA_READ || dir == SCSI_DATA_WRITE); - assert(qc->flags & ATA_QCFLAG_SG); + assert(qc->flags & ATA_QCFLAG_DMAMAP); assert(sg != NULL); - if (!cmd->use_sg) + if (qc->flags & ATA_QCFLAG_SINGLE) assert(qc->n_elem == 1); DPRINTK("unmapping %u sg elements\n", qc->n_elem); - if (cmd->use_sg) + if (qc->flags & ATA_QCFLAG_SG) pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir); else pci_unmap_single(ap->host_set->pdev, sg_dma_address(&sg[0]), sg_dma_len(&sg[0]), dir); - qc->flags &= ~ATA_QCFLAG_SG; + qc->flags &= ~ATA_QCFLAG_DMAMAP; qc->sg = NULL; } /** - * ata_fill_sg - - * @qc: + * ata_fill_sg - Fill PCI IDE PRD table + * @qc: Metadata associated with taskfile to be transferred * * LOCKING: * */ -void ata_fill_sg(struct ata_queued_cmd *qc) +static void ata_fill_sg(struct ata_queued_cmd *qc) { struct scatterlist *sg = qc->sg; struct ata_port *ap = qc->ap; @@ -1840,7 +1858,7 @@ void ata_fill_sg(struct ata_queued_cmd * idx = 0; for (nelem = qc->n_elem; nelem; nelem--,sg++) { - u32 addr, boundary; + u32 addr, offset; u32 sg_len, len; /* determine if physical DMA addr spans 64K boundary. @@ -1851,10 +1869,10 @@ void ata_fill_sg(struct ata_queued_cmd * sg_len = sg_dma_len(sg); while (sg_len) { - boundary = (addr & ~0xffff) + (0xffff + 1); + offset = addr & 0xffff; len = sg_len; - if ((addr + sg_len) > boundary) - len = boundary - addr; + if ((offset + sg_len) > 0x10000) + len = 0x10000 - offset; ap->prd[idx].addr = cpu_to_le32(addr); ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff); @@ -1871,6 +1889,48 @@ void ata_fill_sg(struct ata_queued_cmd * } /** + * ata_qc_prep - Prepare taskfile for submission + * @qc: Metadata associated with taskfile to be prepared + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_qc_prep(struct ata_queued_cmd *qc) +{ + if (!(qc->flags & ATA_QCFLAG_DMAMAP)) + return; + + ata_fill_sg(qc); +} + +void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) +{ + struct scatterlist *sg; + + qc->flags |= ATA_QCFLAG_SINGLE; + + memset(&qc->sgent, 0, sizeof(qc->sgent)); + qc->sg = &qc->sgent; + qc->n_elem = 1; + qc->buf_virt = buf; + + sg = qc->sg; + sg->page = virt_to_page(buf); + sg->offset = (unsigned long) buf & ~PAGE_MASK; + sg_dma_len(sg) = buflen; + + WARN_ON(buflen > PAGE_SIZE); +} + +void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, + unsigned int n_elem) +{ + qc->flags |= ATA_QCFLAG_SG; + qc->sg = sg; + qc->n_elem = n_elem; +} + +/** * ata_sg_setup_one - * @qc: * @@ -1884,29 +1944,16 @@ void ata_fill_sg(struct ata_queued_cmd * static int ata_sg_setup_one(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - struct scsi_cmnd *cmd = qc->scsicmd; - int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + int dir = qc->pci_dma_dir; struct scatterlist *sg = qc->sg; - unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG); dma_addr_t dma_address; - assert(sg == &qc->sgent); - assert(qc->n_elem == 1); - - sg->address = cmd->request_buffer; - sg->page = virt_to_page(cmd->request_buffer); - sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK; - sg_dma_len(sg) = cmd->request_bufflen; - - if (!have_sg) - return 0; - - dma_address = pci_map_single(ap->host_set->pdev, cmd->request_buffer, - cmd->request_bufflen, dir); + dma_address = pci_map_single(ap->host_set->pdev, qc->buf_virt, + sg_dma_len(sg), dir); sg_dma_address(sg) = dma_address; - DPRINTK("mapped buffer of %d bytes for %s\n", cmd->request_bufflen, + DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg), qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); return 0; @@ -1926,24 +1973,19 @@ static int ata_sg_setup_one(struct ata_q static int ata_sg_setup(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - struct scsi_cmnd *cmd = qc->scsicmd; - struct scatterlist *sg; - int n_elem; - unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG); + struct scatterlist *sg = qc->sg; + int n_elem, dir; - VPRINTK("ENTER, ata%u, use_sg %d\n", ap->id, cmd->use_sg); - assert(cmd->use_sg > 0); + VPRINTK("ENTER, ata%u\n", ap->id); + assert(qc->flags & ATA_QCFLAG_SG); + + dir = qc->pci_dma_dir; + n_elem = pci_map_sg(ap->host_set->pdev, sg, qc->n_elem, dir); + if (n_elem < 1) + return -1; + + DPRINTK("%d sg elements mapped\n", n_elem); - sg = (struct scatterlist *)cmd->request_buffer; - if (have_sg) { - int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); - n_elem = pci_map_sg(ap->host_set->pdev, sg, cmd->use_sg, dir); - if (n_elem < 1) - return -1; - DPRINTK("%d sg elements mapped\n", n_elem); - } else { - n_elem = cmd->use_sg; - } qc->n_elem = n_elem; return 0; @@ -2028,7 +2070,7 @@ static void ata_pio_complete (struct ata } drv_stat = ata_wait_idle(ap); - if (drv_stat & (ATA_BUSY | ATA_DRQ)) { + if (!ata_ok(drv_stat)) { ap->pio_task_state = PIO_ST_ERR; return; } @@ -2043,6 +2085,128 @@ static void ata_pio_complete (struct ata ata_qc_complete(qc, drv_stat); } +void swap_buf_le16(u16 *buf, unsigned int buf_words) +{ +#ifdef __BIG_ENDIAN + unsigned int i; + + for (i = 0; i < buf_words; i++) + buf[i] = le16_to_cpu(buf[i]); +#endif /* __BIG_ENDIAN */ +} + +static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, + unsigned int buflen, int write_data) +{ + unsigned int i; + unsigned int words = buflen >> 1; + u16 *buf16 = (u16 *) buf; + void *mmio = (void *)ap->ioaddr.data_addr; + + if (write_data) { + for (i = 0; i < words; i++) + writew(le16_to_cpu(buf16[i]), mmio); + } else { + for (i = 0; i < words; i++) + buf16[i] = cpu_to_le16(readw(mmio)); + } +} + +static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, + unsigned int buflen, int write_data) +{ + unsigned int dwords = buflen >> 1; + + if (write_data) + outsw(ap->ioaddr.data_addr, buf, dwords); + else + insw(ap->ioaddr.data_addr, buf, dwords); +} + +static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, + unsigned int buflen, int do_write) +{ + if (ap->flags & ATA_FLAG_MMIO) + ata_mmio_data_xfer(ap, buf, buflen, do_write); + else + ata_pio_data_xfer(ap, buf, buflen, do_write); +} + +static void ata_pio_sector(struct ata_queued_cmd *qc) +{ + int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); + struct scatterlist *sg = qc->sg; + struct ata_port *ap = qc->ap; + struct page *page; + unsigned char *buf; + + if (qc->cursect == (qc->nsect - 1)) + ap->pio_task_state = PIO_ST_LAST; + + page = sg[qc->cursg].page; + buf = kmap(page) + + sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE); + + qc->cursect++; + qc->cursg_ofs++; + + if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) { + qc->cursg++; + qc->cursg_ofs = 0; + } + + DPRINTK("data %s, drv_stat 0x%X\n", + qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read", + status); + + /* do the actual data transfer */ + do_write = (qc->tf.flags & ATA_TFLAG_WRITE); + ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write); + + kunmap(page); +} + +static void atapi_pio_sector(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct ata_device *dev = qc->dev; + unsigned int i, ireason, bc_lo, bc_hi, bytes; + int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0; + + ap->ops->tf_read(ap, &qc->tf); + ireason = qc->tf.nsect; + bc_lo = qc->tf.lbam; + bc_hi = qc->tf.lbah; + bytes = (bc_hi << 8) | bc_lo; + + /* shall be cleared to zero, indicating xfer of data */ + if (ireason & (1 << 0)) + goto err_out; + + /* make sure transfer direction matches expected */ + i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0; + if (do_write != i_write) + goto err_out; + + /* make sure byte count is multiple of sector size; not + * required by standard (warning! warning!), but IDE driver + * does this to simplify things a bit. We are lazy, and + * follow suit. + */ + if (bytes & (ATA_SECT_SIZE - 1)) + goto err_out; + + for (i = 0; i < (bytes >> 9); i++) + ata_pio_sector(qc); + + return; + +err_out: + printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n", + ap->id, dev->devno); + ap->pio_task_state = PIO_ST_ERR; +} + /** * ata_pio_sector - * @ap: @@ -2050,12 +2214,9 @@ static void ata_pio_complete (struct ata * LOCKING: */ -static void ata_pio_sector(struct ata_port *ap) +static void ata_pio_block(struct ata_port *ap) { struct ata_queued_cmd *qc; - struct scatterlist *sg; - struct scsi_cmnd *cmd; - unsigned char *buf; u8 status; /* @@ -2086,36 +2247,29 @@ static void ata_pio_sector(struct ata_po qc = ata_qc_from_tag(ap, ap->active_tag); assert(qc != NULL); - cmd = qc->scsicmd; - sg = qc->sg; - - if (qc->cursect == (qc->nsect - 1)) - ap->pio_task_state = PIO_ST_LAST; + if (is_atapi_taskfile(&qc->tf)) + atapi_pio_sector(qc); + else + ata_pio_sector(qc); +} - buf = kmap(sg[qc->cursg].page) + - sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE); +static void ata_pio_error(struct ata_port *ap) +{ + struct ata_queued_cmd *qc; + u8 drv_stat; - qc->cursect++; - qc->cursg_ofs++; + qc = ata_qc_from_tag(ap, ap->active_tag); + assert(qc != NULL); - if (cmd->use_sg) - if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) { - qc->cursg++; - qc->cursg_ofs = 0; - } + drv_stat = ata_chk_status(ap); + printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n", + ap->id, drv_stat); - DPRINTK("data %s, drv_stat 0x%X\n", - qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read", - status); + ap->pio_task_state = PIO_ST_IDLE; - /* do the actual data transfer */ - /* FIXME: mmio-ize */ - if (qc->tf.flags & ATA_TFLAG_WRITE) - outsl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS); - else - insl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS); + ata_irq_on(ap); - kunmap(sg[qc->cursg].page); + ata_qc_complete(qc, drv_stat | ATA_ERR); } static void ata_pio_task(void *_data) @@ -2125,7 +2279,7 @@ static void ata_pio_task(void *_data) switch (ap->pio_task_state) { case PIO_ST: - ata_pio_sector(ap); + ata_pio_block(ap); break; case PIO_ST_LAST: @@ -2138,15 +2292,8 @@ static void ata_pio_task(void *_data) break; case PIO_ST_TMOUT: - printk(KERN_ERR "ata%d: FIXME: PIO_ST_TMOUT\n", /* FIXME */ - ap->id); - timeout = 11 * HZ; - break; - case PIO_ST_ERR: - printk(KERN_ERR "ata%d: FIXME: PIO_ST_ERR\n", /* FIXME */ - ap->id); - timeout = 11 * HZ; + ata_pio_error(ap); break; } @@ -2157,13 +2304,14 @@ static void ata_pio_task(void *_data) if ((ap->pio_task_state != PIO_ST_IDLE) && (ap->pio_task_state != PIO_ST_TMOUT) && - (ap->pio_task_state != PIO_ST_ERR)) + (ap->pio_task_state != PIO_ST_ERR)) { schedule_task(&ap->pio_task); + } } /** - * ata_eng_timeout - Handle timeout of queued command - * @ap: Port on which timed-out command is active + * ata_qc_timeout - Handle timeout of queued command + * @qc: Command that timed out * * Some part of the kernel (currently, only the SCSI layer) * has noticed that the active command on port @ap has not @@ -2177,23 +2325,15 @@ static void ata_pio_task(void *_data) * transaction completed successfully. * * LOCKING: - * Inherited from SCSI layer (none, can sleep) */ -void ata_eng_timeout(struct ata_port *ap) +static void ata_qc_timeout(struct ata_queued_cmd *qc) { - u8 host_stat, drv_stat; - struct ata_queued_cmd *qc; + struct ata_port *ap = qc->ap; + u8 host_stat = 0, drv_stat; DPRINTK("ENTER\n"); - qc = ata_qc_from_tag(ap, ap->active_tag); - if (!qc) { - printk(KERN_ERR "ata%u: BUG: timeout without command\n", - ap->id); - goto out; - } - /* hack alert! We cannot use the supplied completion * function from inside the ->eh_strategy_handler() thread. * libata is the only user of ->eh_strategy_handler() in @@ -2203,38 +2343,68 @@ void ata_eng_timeout(struct ata_port *ap qc->scsidone = scsi_finish_command; switch (qc->tf.protocol) { + case ATA_PROT_DMA: - if (ap->flags & ATA_FLAG_MMIO) { - void *mmio = (void *) ap->ioaddr.bmdma_addr; - host_stat = readb(mmio + ATA_DMA_STATUS); - } else - host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + case ATA_PROT_ATAPI_DMA: + host_stat = ata_bmdma_status(ap); - printk(KERN_ERR "ata%u: DMA timeout, stat 0x%x\n", - ap->id, host_stat); + /* before we do anything else, clear DMA-Start bit */ + ata_bmdma_stop(ap); - ata_dma_complete(qc, host_stat); - break; + /* fall through */ - case ATA_PROT_NODATA: - drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + default: + ata_altstatus(ap); + drv_stat = ata_chk_status(ap); + + /* ack bmdma irq events */ + ata_bmdma_ack_irq(ap); - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); + printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", + ap->id, qc->tf.command, drv_stat, host_stat); + /* complete taskfile transaction */ ata_qc_complete(qc, drv_stat); break; + } - default: - drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + DPRINTK("EXIT\n"); +} - printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); +/** + * ata_eng_timeout - Handle timeout of queued command + * @ap: Port on which timed-out command is active + * + * Some part of the kernel (currently, only the SCSI layer) + * has noticed that the active command on port @ap has not + * completed after a specified length of time. Handle this + * condition by disabling DMA (if necessary) and completing + * transactions, with error if necessary. + * + * This also handles the case of the "lost interrupt", where + * for some reason (possibly hardware bug, possibly driver bug) + * an interrupt was not delivered to the driver, even though the + * transaction completed successfully. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + */ - ata_qc_complete(qc, drv_stat); - break; +void ata_eng_timeout(struct ata_port *ap) +{ + struct ata_queued_cmd *qc; + + DPRINTK("ENTER\n"); + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (!qc) { + printk(KERN_ERR "ata%u: BUG: timeout without command\n", + ap->id); + goto out; } + ata_qc_timeout(qc); + out: DPRINTK("EXIT\n"); } @@ -2289,8 +2459,6 @@ struct ata_queued_cmd *ata_qc_new_init(s ata_tf_init(ap, &qc->tf, dev->devno); - if (likely((dev->flags & ATA_DFLAG_PIO) == 0)) - qc->flags |= ATA_QCFLAG_DMA; if (dev->flags & ATA_DFLAG_LBA48) qc->tf.flags |= ATA_TFLAG_LBA48; } @@ -2298,6 +2466,11 @@ struct ata_queued_cmd *ata_qc_new_init(s return qc; } +static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat) +{ + return 0; +} + /** * ata_qc_complete - Complete an active ATA command * @qc: Command to complete @@ -2310,29 +2483,25 @@ struct ata_queued_cmd *ata_qc_new_init(s void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) { struct ata_port *ap = qc->ap; - struct scsi_cmnd *cmd = qc->scsicmd; unsigned int tag, do_clear = 0; + int rc; assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ assert(qc->flags & ATA_QCFLAG_ACTIVE); - if (likely(qc->flags & ATA_QCFLAG_SG)) + if (likely(qc->flags & ATA_QCFLAG_DMAMAP)) ata_sg_clean(qc); - if (cmd) { - if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) { - if (is_atapi_taskfile(&qc->tf)) - cmd->result = SAM_STAT_CHECK_CONDITION; - else - ata_to_sense_error(qc); - } else { - cmd->result = SAM_STAT_GOOD; - } + /* call completion callback */ + rc = qc->complete_fn(qc, drv_stat); - qc->scsidone(cmd); - } + /* if callback indicates not to complete command (non-zero), + * return immediately + */ + if (rc != 0) + return; - qc->flags &= ~ATA_QCFLAG_ACTIVE; + qc->flags = 0; tag = qc->tag; if (likely(ata_tag_valid(tag))) { if (tag == ap->active_tag) @@ -2341,11 +2510,16 @@ void ata_qc_complete(struct ata_queued_c do_clear = 1; } - if (qc->waiting) - complete(qc->waiting); + if (qc->waiting) { + struct completion *waiting = qc->waiting; + qc->waiting = NULL; + complete(waiting); + } if (likely(do_clear)) clear_bit(tag, &ap->qactive); + + VPRINTK("EXIT\n"); } /** @@ -2367,25 +2541,21 @@ void ata_qc_complete(struct ata_queued_c int ata_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - struct scsi_cmnd *cmd = qc->scsicmd; if (qc->flags & ATA_QCFLAG_SG) { - /* set up SG table */ - if (cmd->use_sg) { - if (ata_sg_setup(qc)) - goto err_out; - } else { - if (ata_sg_setup_one(qc)) - goto err_out; - } - - ap->ops->fill_sg(qc); + if (ata_sg_setup(qc)) + goto err_out; + } else if (qc->flags & ATA_QCFLAG_SINGLE) { + if (ata_sg_setup_one(qc)) + goto err_out; } + ap->ops->qc_prep(qc); + qc->ap->active_tag = qc->tag; qc->flags |= ATA_QCFLAG_ACTIVE; - return ata_qc_issue_prot(qc); + return ap->ops->qc_issue(qc); err_out: return -1; @@ -2407,7 +2577,7 @@ err_out: * Zero on success, negative on error. */ -static int ata_qc_issue_prot(struct ata_queued_cmd *qc) +int ata_qc_issue_prot(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -2432,6 +2602,12 @@ static int ata_qc_issue_prot(struct ata_ break; case ATA_PROT_ATAPI: + ata_qc_set_polling(qc); + ata_tf_to_host_nolock(ap, &qc->tf); + schedule_task(&ap->packet_task); + break; + + case ATA_PROT_ATAPI_NODATA: ata_tf_to_host_nolock(ap, &qc->tf); schedule_task(&ap->packet_task); break; @@ -2443,6 +2619,7 @@ static int ata_qc_issue_prot(struct ata_ break; default: + WARN_ON(1); return -1; } @@ -2461,7 +2638,7 @@ void ata_bmdma_setup_mmio (struct ata_qu { struct ata_port *ap = qc->ap; unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); - u8 host_stat, dmactl; + u8 dmactl; void *mmio = (void *) ap->ioaddr.bmdma_addr; /* load PRD table addr. */ @@ -2475,10 +2652,6 @@ void ata_bmdma_setup_mmio (struct ata_qu dmactl |= ATA_DMA_WR; writeb(dmactl, mmio + ATA_DMA_CMD); - /* clear interrupt, error bits */ - host_stat = readb(mmio + ATA_DMA_STATUS); - writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, mmio + ATA_DMA_STATUS); - /* issue r/w command */ ap->ops->exec_command(ap, &qc->tf); } @@ -2526,7 +2699,7 @@ void ata_bmdma_setup_pio (struct ata_que { struct ata_port *ap = qc->ap; unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); - u8 host_stat, dmactl; + u8 dmactl; /* load PRD table addr. */ outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); @@ -2538,11 +2711,6 @@ void ata_bmdma_setup_pio (struct ata_que dmactl |= ATA_DMA_WR; outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - /* clear interrupt, error bits */ - host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, - ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - /* issue r/w command */ ap->ops->exec_command(ap, &qc->tf); } @@ -2566,48 +2734,9 @@ void ata_bmdma_start_pio (struct ata_que ap->ioaddr.bmdma_addr + ATA_DMA_CMD); } -/** - * ata_dma_complete - Complete an active ATA BMDMA command - * @qc: Command to complete - * @host_stat: BMDMA status register contents - * - * LOCKING: - */ - -static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat) +void ata_bmdma_irq_clear(struct ata_port *ap) { - struct ata_port *ap = qc->ap; - VPRINTK("ENTER\n"); - - if (ap->flags & ATA_FLAG_MMIO) { - void *mmio = (void *) ap->ioaddr.bmdma_addr; - - /* clear start/stop bit */ - writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START, - mmio + ATA_DMA_CMD); - - /* ack intr, err bits */ - writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, - mmio + ATA_DMA_STATUS); - } else { - /* clear start/stop bit */ - outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, - ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - - /* ack intr, err bits */ - outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, - ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - } - - - /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ - ata_altstatus(ap); /* dummy read */ - - DPRINTK("host %u, host_stat==0x%X, drv_stat==0x%X\n", - ap->id, (u32) host_stat, (u32) ata_chk_status(ap)); - - /* get drive status; clear intr; complete txn */ - ata_qc_complete(qc, ata_wait_idle(ap)); + ata_bmdma_ack_irq(ap); } /** @@ -2630,59 +2759,63 @@ inline unsigned int ata_host_intr (struc struct ata_queued_cmd *qc) { u8 status, host_stat; - unsigned int handled = 0; switch (qc->tf.protocol) { - /* BMDMA completion */ case ATA_PROT_DMA: case ATA_PROT_ATAPI_DMA: - if (ap->flags & ATA_FLAG_MMIO) { - void *mmio = (void *) ap->ioaddr.bmdma_addr; - host_stat = readb(mmio + ATA_DMA_STATUS); - } else - host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - VPRINTK("BUS_DMA (host_stat 0x%X)\n", host_stat); + case ATA_PROT_ATAPI: + /* check status of DMA engine */ + host_stat = ata_bmdma_status(ap); + VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat); - if (!(host_stat & ATA_DMA_INTR)) { - ap->stats.idle_irq++; - break; - } + /* if it's not our irq... */ + if (!(host_stat & ATA_DMA_INTR)) + goto idle_irq; - ata_dma_complete(qc, host_stat); - handled = 1; - break; + /* before we do anything else, clear DMA-Start bit */ + ata_bmdma_stop(ap); - /* command completion, but no data xfer */ - /* FIXME: a shared interrupt _will_ cause a non-data command - * to be completed prematurely, with an error. - * - * This doesn't matter right now, since we aren't sending - * non-data commands down this pipe except in development - * situations. - */ - case ATA_PROT_ATAPI: + /* fall through */ + + case ATA_PROT_ATAPI_NODATA: case ATA_PROT_NODATA: - status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); + /* check altstatus */ + status = ata_altstatus(ap); + if (status & ATA_BUSY) + goto idle_irq; + + /* check main status, clearing INTRQ */ + status = ata_chk_status(ap); + if (unlikely(status & ATA_BUSY)) + goto idle_irq; + DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n", + ap->id, qc->tf.protocol, status); + + /* ack bmdma irq events */ + ata_bmdma_ack_irq(ap); + + /* complete taskfile transaction */ ata_qc_complete(qc, status); - handled = 1; break; default: - ap->stats.idle_irq++; + goto idle_irq; + } + + return 1; /* irq handled */ + +idle_irq: + ap->stats.idle_irq++; #ifdef ATA_IRQ_TRAP - if ((ap->stats.idle_irq % 1000) == 0) { - handled = 1; - ata_irq_ack(ap, 0); /* debug trap */ - printk(KERN_WARNING "ata%d: irq trap\n", ap->id); - } -#endif - break; + if ((ap->stats.idle_irq % 1000) == 0) { + handled = 1; + ata_irq_ack(ap, 0); /* debug trap */ + printk(KERN_WARNING "ata%d: irq trap\n", ap->id); } - - return handled; +#endif + return 0; /* irq not handled */ } /** @@ -2716,7 +2849,7 @@ irqreturn_t ata_interrupt (int irq, void qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.ctl & ATA_NIEN))) - handled += ata_host_intr(ap, qc); + handled |= ata_host_intr(ap, qc); } } @@ -2726,62 +2859,6 @@ irqreturn_t ata_interrupt (int irq, void } /** - * ata_thread_iter - - * @ap: - * - * LOCKING: - * - * RETURNS: - * - */ - -static unsigned long ata_thread_iter(struct ata_port *ap) -{ - long timeout = 0; - - DPRINTK("ata%u: thr_state %s\n", - ap->id, ata_thr_state_name(ap->thr_state)); - - switch (ap->thr_state) { - case THR_UNKNOWN: - ap->thr_state = THR_PORT_RESET; - break; - - case THR_PROBE_START: - ap->thr_state = THR_PORT_RESET; - break; - - case THR_PORT_RESET: - ata_port_reset(ap); - break; - - case THR_PROBE_SUCCESS: - up(&ap->probe_sem); - ap->thr_state = THR_IDLE; - break; - - case THR_PROBE_FAILED: - up(&ap->probe_sem); - ap->thr_state = THR_AWAIT_DEATH; - break; - - case THR_AWAIT_DEATH: - case THR_IDLE: - timeout = -1; - break; - - default: - printk(KERN_DEBUG "ata%u: unknown thr state %s\n", - ap->id, ata_thr_state_name(ap->thr_state)); - break; - } - - DPRINTK("ata%u: new thr_state %s, returning %ld\n", - ap->id, ata_thr_state_name(ap->thr_state), timeout); - return timeout; -} - -/** * atapi_packet_task - Write CDB bytes to hardware * @_data: Port to which ATAPI device is attached. * @@ -2812,21 +2889,20 @@ static void atapi_packet_task(void *_dat /* make sure DRQ is set */ status = ata_chk_status(ap); - if ((status & ATA_DRQ) == 0) + if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) goto err_out; /* send SCSI cdb */ - /* FIXME: mmio-ize */ DPRINTK("send cdb\n"); - outsl(ap->ioaddr.data_addr, - qc->scsicmd->cmnd, ap->host->max_cmd_len / 4); + assert(ap->cdb_len >= 12); + ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); /* if we are DMA'ing, irq handler takes over from here */ if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) ap->ops->bmdma_start(qc); /* initiate bmdma */ /* non-data commands are also handled via irq */ - else if (qc->scsicmd->sc_data_direction == SCSI_DATA_NONE) { + else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) { /* do nothing */ } @@ -2862,23 +2938,6 @@ void ata_port_stop (struct ata_port *ap) pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); } -static void ata_probe_task(void *_data) -{ - struct ata_port *ap = _data; - long timeout; - - timeout = ata_thread_iter(ap); - if (timeout < 0) - return; - - if (timeout > 0) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(timeout); - } - - schedule_task(&ap->probe_task); -} - /** * ata_host_remove - Unregister SCSI host structure with upper layers * @ap: Port to unregister @@ -2931,24 +2990,20 @@ static void ata_host_init(struct ata_por ap->host_set = host_set; ap->port_no = port_no; ap->pio_mask = ent->pio_mask; + ap->mwdma_mask = ent->mwdma_mask; ap->udma_mask = ent->udma_mask; ap->flags |= ent->host_flags; ap->ops = ent->port_ops; - ap->thr_state = THR_PROBE_START; ap->cbl = ATA_CBL_NONE; - ap->device[0].flags = ATA_DFLAG_MASTER; ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; INIT_TQUEUE(&ap->packet_task, atapi_packet_task, ap); INIT_TQUEUE(&ap->pio_task, ata_pio_task, ap); - INIT_TQUEUE(&ap->probe_task, ata_probe_task, ap); for (i = 0; i < ATA_MAX_DEVICES; i++) ap->device[i].devno = i; - init_MUTEX_LOCKED(&ap->probe_sem); - #ifdef ATA_IRQ_TRAP ap->stats.unhandled_irq = 1; ap->stats.idle_irq = 1; @@ -3027,28 +3082,35 @@ int ata_device_add(struct ata_probe_ent host_set->irq = ent->irq; host_set->mmio_base = ent->mmio_base; host_set->private_data = ent->private_data; + host_set->ops = ent->port_ops; /* register each port bound to this device */ for (i = 0; i < ent->n_ports; i++) { struct ata_port *ap; + unsigned long xfer_mode_mask; ap = ata_host_add(ent, host_set, i); if (!ap) goto err_out; host_set->ports[i] = ap; + xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) | + (ap->mwdma_mask << ATA_SHIFT_MWDMA) | + (ap->pio_mask << ATA_SHIFT_PIO); /* print per-port info to dmesg */ printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX " "bmdma 0x%lX irq %lu\n", ap->id, ap->flags & ATA_FLAG_SATA ? 'S' : 'P', - ata_udma_string(ent->udma_mask), + ata_mode_string(xfer_mode_mask), ap->ioaddr.cmd_addr, ap->ioaddr.ctl_addr, ap->ioaddr.bmdma_addr, ent->irq); + ata_chk_status(ap); + host_set->ops->irq_clear(ap); count++; } @@ -3066,16 +3128,22 @@ int ata_device_add(struct ata_probe_ent DPRINTK("probe begin\n"); for (i = 0; i < count; i++) { struct ata_port *ap; + int rc; ap = host_set->ports[i]; DPRINTK("ata%u: probe begin\n", ap->id); - schedule_task(&ap->probe_task); /* start probe */ - - DPRINTK("ata%u: probe-wait begin\n", ap->id); - down(&ap->probe_sem); /* wait for end */ + rc = ata_bus_probe(ap); + DPRINTK("ata%u: probe end\n", ap->id); - DPRINTK("ata%u: probe-wait end\n", ap->id); + if (rc) { + /* FIXME: do something useful here? + * Current libata behavior will + * tear down everything when + * the module is removed + * or the h/w is unplugged. + */ + } } pci_set_drvdata(pdev, host_set); @@ -3276,6 +3344,7 @@ int ata_pci_init_one (struct pci_dev *pd probe_ent->sht = port0->sht; probe_ent->host_flags = port0->host_flags; probe_ent->pio_mask = port0->pio_mask; + probe_ent->mwdma_mask = port0->mwdma_mask; probe_ent->udma_mask = port0->udma_mask; probe_ent->port_ops = port0->port_ops; @@ -3298,6 +3367,7 @@ int ata_pci_init_one (struct pci_dev *pd probe_ent2->sht = port1->sht; probe_ent2->host_flags = port1->host_flags; probe_ent2->pio_mask = port1->pio_mask; + probe_ent2->mwdma_mask = port1->mwdma_mask; probe_ent2->udma_mask = port1->udma_mask; probe_ent2->port_ops = port1->port_ops; } else { @@ -3383,10 +3453,10 @@ void ata_pci_remove_one (struct pci_dev /* FIXME: handle 'rc' failure? */ free_irq(host_set->irq, host_set); + if (host_set->ops->host_stop) + host_set->ops->host_stop(host_set); if (host_set->mmio_base) iounmap(host_set->mmio_base); - if (host_set->ports[0]->ops->host_stop) - host_set->ports[0]->ops->host_stop(host_set); pci_release_regions(pdev); @@ -3492,7 +3562,10 @@ EXPORT_SYMBOL_GPL(pci_test_config_bits); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_std_ports); EXPORT_SYMBOL_GPL(ata_device_add); +EXPORT_SYMBOL_GPL(ata_sg_init); +EXPORT_SYMBOL_GPL(ata_sg_init_one); EXPORT_SYMBOL_GPL(ata_qc_complete); +EXPORT_SYMBOL_GPL(ata_qc_issue_prot); EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_tf_load_pio); EXPORT_SYMBOL_GPL(ata_tf_load_mmio); @@ -3507,21 +3580,24 @@ EXPORT_SYMBOL_GPL(ata_exec_command_mmio) EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_stop); EXPORT_SYMBOL_GPL(ata_interrupt); -EXPORT_SYMBOL_GPL(ata_fill_sg); +EXPORT_SYMBOL_GPL(ata_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio); EXPORT_SYMBOL_GPL(ata_bmdma_start_pio); EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio); EXPORT_SYMBOL_GPL(ata_bmdma_start_mmio); +EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_pci_init_one); EXPORT_SYMBOL_GPL(ata_pci_remove_one); +EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_detect); EXPORT_SYMBOL_GPL(ata_add_to_probe_list); +EXPORT_SYMBOL_GPL(libata_msleep); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_dev_id_string); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/libata-scsi.c linux-2.4.28-pre3/drivers/scsi/libata-scsi.c --- linux-2.4.27/drivers/scsi/libata-scsi.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/libata-scsi.c 2004-09-10 19:32:40.000000000 +0000 @@ -31,6 +31,7 @@ #include #include "sd.h" #include +#include #include "libata.h" @@ -38,13 +39,15 @@ typedef unsigned int (*ata_xlat_func_t)( static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); +static struct ata_device * +ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev); /** * ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd. * @disk: SCSI device for which BIOS geometry is to be determined - * @dev: device major/minor - * @ip: location to which geometry will be output + * @bdev: device major/minor + * @geom: location to which geometry will be output * * Generic bios head/sector/cylinder calculator * used by sd. Most BIOSes nowadays expect a XXX/255/16 (CHS) @@ -58,16 +61,53 @@ static void ata_scsi_simulate(struct ata * Zero. */ int ata_std_bios_param(Disk * disk, /* SCSI disk */ - kdev_t dev, /* Device major, minor */ - int *ip /* Heads, sectors, cylinders in that order */ ) + kdev_t bdev, /* Device major, minor */ + int *geom /* Heads, sectors, cylinders in that order */ ) { - ip[0] = 255; - ip[1] = 63; - ip[2] = disk->capacity / (ip[0] * ip[1]); + geom[0] = 255; + geom[1] = 63; + geom[2] = disk->capacity / (geom[0] * geom[1]); return 0; } +int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) +{ + struct ata_port *ap; + struct ata_device *dev; + int val = -EINVAL, rc = -EINVAL; + + ap = (struct ata_port *) &scsidev->host->hostdata[0]; + if (!ap) + goto out; + + dev = ata_scsi_find_dev(ap, scsidev); + if (!dev) { + rc = -ENODEV; + goto out; + } + + switch (cmd) { + case ATA_IOC_GET_IO32: + val = 0; + if (copy_to_user(arg, &val, 1)) + return -EFAULT; + return 0; + + case ATA_IOC_SET_IO32: + val = (unsigned long) arg; + if (val != 0) + return -EINVAL; + return 0; + + default: + rc = -EOPNOTSUPP; + break; + } + +out: + return rc; +} /** * ata_scsi_qc_new - acquire new ata_queued_cmd reference @@ -121,34 +161,158 @@ struct ata_queued_cmd *ata_scsi_qc_new(s * ata_to_sense_error - convert ATA error to SCSI error * @qc: Command that we are erroring out * - * Converts an ATA error into a SCSI error. - * - * Right now, this routine is laughably primitive. We - * don't even examine what ATA told us, we just look at - * the command data direction, and return a fatal SCSI - * sense error based on that. + * Converts an ATA error into a SCSI error. While we are at it + * we decode and dump the ATA error for the user so that they + * have some idea what really happened at the non make-believe + * layer. * * LOCKING: * spin_lock_irqsave(host_set lock) */ -void ata_to_sense_error(struct ata_queued_cmd *qc) +void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat) { struct scsi_cmnd *cmd = qc->scsicmd; + u8 err = 0; + unsigned char *sb = cmd->sense_buffer; + /* Based on the 3ware driver translation table */ + static unsigned char sense_table[][4] = { + /* BBD|ECC|ID|MAR */ + {0xd1, ABORTED_COMMAND, 0x00, 0x00}, // Device busy Aborted command + /* BBD|ECC|ID */ + {0xd0, ABORTED_COMMAND, 0x00, 0x00}, // Device busy Aborted command + /* ECC|MC|MARK */ + {0x61, HARDWARE_ERROR, 0x00, 0x00}, // Device fault Hardware error + /* ICRC|ABRT */ /* NB: ICRC & !ABRT is BBD */ + {0x84, ABORTED_COMMAND, 0x47, 0x00}, // Data CRC error SCSI parity error + /* MC|ID|ABRT|TRK0|MARK */ + {0x37, NOT_READY, 0x04, 0x00}, // Unit offline Not ready + /* MCR|MARK */ + {0x09, NOT_READY, 0x04, 0x00}, // Unrecovered disk error Not ready + /* Bad address mark */ + {0x01, MEDIUM_ERROR, 0x13, 0x00}, // Address mark not found Address mark not found for data field + /* TRK0 */ + {0x02, HARDWARE_ERROR, 0x00, 0x00}, // Track 0 not found Hardware error + /* Abort & !ICRC */ + {0x04, ABORTED_COMMAND, 0x00, 0x00}, // Aborted command Aborted command + /* Media change request */ + {0x08, NOT_READY, 0x04, 0x00}, // Media change request FIXME: faking offline + /* SRV */ + {0x10, ABORTED_COMMAND, 0x14, 0x00}, // ID not found Recorded entity not found + /* Media change */ + {0x08, NOT_READY, 0x04, 0x00}, // Media change FIXME: faking offline + /* ECC */ + {0x40, MEDIUM_ERROR, 0x11, 0x04}, // Uncorrectable ECC error Unrecovered read error + /* BBD - block marked bad */ + {0x80, MEDIUM_ERROR, 0x11, 0x04}, // Block marked bad Medium error, unrecovered read error + {0xFF, 0xFF, 0xFF, 0xFF}, // END mark + }; + static unsigned char stat_table[][4] = { + /* Must be first because BUSY means no other bits valid */ + {0x80, ABORTED_COMMAND, 0x47, 0x00}, // Busy, fake parity for now + {0x20, HARDWARE_ERROR, 0x00, 0x00}, // Device fault + {0x08, ABORTED_COMMAND, 0x47, 0x00}, // Timed out in xfer, fake parity for now + {0x04, RECOVERED_ERROR, 0x11, 0x00}, // Recovered ECC error Medium error, recovered + {0xFF, 0xFF, 0xFF, 0xFF}, // END mark + }; + int i = 0; cmd->result = SAM_STAT_CHECK_CONDITION; - - cmd->sense_buffer[0] = 0x70; - cmd->sense_buffer[2] = MEDIUM_ERROR; - cmd->sense_buffer[7] = 14 - 8; /* addnl. sense len. FIXME: correct? */ - + + /* + * Is this an error we can process/parse + */ + + if(drv_stat & ATA_ERR) + /* Read the err bits */ + err = ata_chk_err(qc->ap); + + /* Display the ATA level error info */ + + printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat); + if(drv_stat & 0x80) + { + printk("Busy "); + err = 0; /* Data is not valid in this case */ + } + else { + if(drv_stat & 0x40) printk("DriveReady "); + if(drv_stat & 0x20) printk("DeviceFault "); + if(drv_stat & 0x10) printk("SeekComplete "); + if(drv_stat & 0x08) printk("DataRequest "); + if(drv_stat & 0x04) printk("CorrectedError "); + if(drv_stat & 0x02) printk("Index "); + if(drv_stat & 0x01) printk("Error "); + } + printk("}\n"); + + if(err) + { + printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err); + if(err & 0x04) printk("DriveStatusError "); + if(err & 0x80) + { + if(err & 0x04) + printk("BadCRC "); + else + printk("Sector "); + } + if(err & 0x40) printk("UncorrectableError "); + if(err & 0x10) printk("SectorIdNotFound "); + if(err & 0x02) printk("TrackZeroNotFound "); + if(err & 0x01) printk("AddrMarkNotFound "); + printk("}\n"); + + /* Should we dump sector info here too ?? */ + } + + + /* Look for err */ + while(sense_table[i][0] != 0xFF) + { + /* Look for best matches first */ + if((sense_table[i][0] & err) == sense_table[i][0]) + { + sb[0] = 0x70; + sb[2] = sense_table[i][1]; + sb[7] = 0x0a; + sb[12] = sense_table[i][2]; + sb[13] = sense_table[i][3]; + return; + } + i++; + } + /* No immediate match */ + if(err) + printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err); + + /* Fall back to interpreting status bits */ + while(stat_table[i][0] != 0xFF) + { + if(stat_table[i][0] & drv_stat) + { + sb[0] = 0x70; + sb[2] = stat_table[i][1]; + sb[7] = 0x0a; + sb[12] = stat_table[i][2]; + sb[13] = stat_table[i][3]; + return; + } + i++; + } + /* No error ?? */ + printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat); /* additional-sense-code[-qualifier] */ + + sb[0] = 0x70; + sb[2] = MEDIUM_ERROR; + sb[7] = 0x0A; if (cmd->sc_data_direction == SCSI_DATA_READ) { - cmd->sense_buffer[12] = 0x11; /* "unrecovered read error" */ - cmd->sense_buffer[13] = 0x04; + sb[12] = 0x11; /* "unrecovered read error" */ + sb[13] = 0x04; } else { - cmd->sense_buffer[12] = 0x0C; /* "write error - */ - cmd->sense_buffer[13] = 0x02; /* auto-reallocation failed" */ + sb[12] = 0x0C; /* "write error - */ + sb[13] = 0x02; /* auto-reallocation failed" */ } } @@ -174,11 +338,137 @@ int ata_scsi_error(struct Scsi_Host *hos ap = (struct ata_port *) &host->hostdata[0]; ap->ops->eng_timeout(ap); + host->in_recovery = 0; + + /* TODO: this is per-command; when queueing is supported + * this code will either change or move to a more + * appropriate place + */ + host->host_failed--; + DPRINTK("EXIT\n"); return 0; } /** + * ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command + * @qc: Storage for translated ATA taskfile + * @scsicmd: SCSI command to translate (ignored) + * + * Sets up an ATA taskfile to issue FLUSH CACHE or + * FLUSH CACHE EXT. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Zero on success, non-zero on error. + */ + +static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) +{ + struct ata_taskfile *tf = &qc->tf; + + tf->flags |= ATA_TFLAG_DEVICE; + tf->protocol = ATA_PROT_NODATA; + + if ((tf->flags & ATA_TFLAG_LBA48) && + (ata_id_has_flush_ext(qc->dev))) + tf->command = ATA_CMD_FLUSH_EXT; + else + tf->command = ATA_CMD_FLUSH; + + return 0; +} + +/** + * ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one + * @qc: Storage for translated ATA taskfile + * @scsicmd: SCSI command to translate + * + * Converts SCSI VERIFY command to an ATA READ VERIFY command. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Zero on success, non-zero on error. + */ + +static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) +{ + struct ata_taskfile *tf = &qc->tf; + unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48; + u64 dev_sectors = qc->dev->n_sectors; + u64 sect = 0; + u32 n_sect = 0; + + tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf->protocol = ATA_PROT_NODATA; + tf->device |= ATA_LBA; + + if (scsicmd[0] == VERIFY) { + sect |= ((u64)scsicmd[2]) << 24; + sect |= ((u64)scsicmd[3]) << 16; + sect |= ((u64)scsicmd[4]) << 8; + sect |= ((u64)scsicmd[5]); + + n_sect |= ((u32)scsicmd[7]) << 8; + n_sect |= ((u32)scsicmd[8]); + } + + else if (scsicmd[0] == VERIFY_16) { + sect |= ((u64)scsicmd[2]) << 56; + sect |= ((u64)scsicmd[3]) << 48; + sect |= ((u64)scsicmd[4]) << 40; + sect |= ((u64)scsicmd[5]) << 32; + sect |= ((u64)scsicmd[6]) << 24; + sect |= ((u64)scsicmd[7]) << 16; + sect |= ((u64)scsicmd[8]) << 8; + sect |= ((u64)scsicmd[9]); + + n_sect |= ((u32)scsicmd[10]) << 24; + n_sect |= ((u32)scsicmd[11]) << 16; + n_sect |= ((u32)scsicmd[12]) << 8; + n_sect |= ((u32)scsicmd[13]); + } + + else + return 1; + + if (!n_sect) + return 1; + if (sect >= dev_sectors) + return 1; + if ((sect + n_sect) > dev_sectors) + return 1; + if (lba48) { + if (n_sect > (64 * 1024)) + return 1; + } else { + if (n_sect > 256) + return 1; + } + + if (lba48) { + tf->hob_nsect = (n_sect >> 8) & 0xff; + + tf->hob_lbah = (sect >> 40) & 0xff; + tf->hob_lbam = (sect >> 32) & 0xff; + tf->hob_lbal = (sect >> 24) & 0xff; + } else + tf->device |= (sect >> 24) & 0xf; + + tf->nsect = n_sect & 0xff; + + tf->hob_lbah = (sect >> 16) & 0xff; + tf->hob_lbam = (sect >> 8) & 0xff; + tf->hob_lbal = sect & 0xff; + + return 0; +} + +/** * ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one * @qc: Storage for translated ATA taskfile * @scsicmd: SCSI command to translate @@ -204,10 +494,6 @@ static unsigned int ata_scsi_rw_xlat(str unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; - tf->hob_nsect = 0; - tf->hob_lbal = 0; - tf->hob_lbam = 0; - tf->hob_lbah = 0; tf->protocol = qc->dev->xfer_protocol; tf->device |= ATA_LBA; @@ -295,6 +581,20 @@ static unsigned int ata_scsi_rw_xlat(str return 1; } +static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + + if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) + ata_to_sense_error(qc, drv_stat); + else + cmd->result = SAM_STAT_GOOD; + + qc->scsidone(cmd); + + return 0; +} + /** * ata_scsi_translate - Translate then issue SCSI command to ATA device * @ap: ATA port to which the command is addressed @@ -328,6 +628,7 @@ static void ata_scsi_translate(struct at if (!qc) return; + /* data is present; dma-map it */ if (cmd->sc_data_direction == SCSI_DATA_READ || cmd->sc_data_direction == SCSI_DATA_WRITE) { if (unlikely(cmd->request_bufflen < 1)) { @@ -336,9 +637,17 @@ static void ata_scsi_translate(struct at goto err_out; } - qc->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */ + if (cmd->use_sg) + ata_sg_init(qc, cmd->request_buffer, cmd->use_sg); + else + ata_sg_init_one(qc, cmd->request_buffer, + cmd->request_bufflen); + + qc->pci_dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); } + qc->complete_fn = ata_scsi_qc_complete; + if (xlat_func(qc, scsicmd)) goto err_out; @@ -467,7 +776,7 @@ unsigned int ata_scsiop_inq_std(struct a 0, 0x5, /* claim SPC-3 version compatibility */ 2, - 96 - 4 + 95 - 4 }; /* set scsi removeable (RMB) bit per ata bit */ @@ -478,7 +787,7 @@ unsigned int ata_scsiop_inq_std(struct a memcpy(rbuf, hdr, sizeof(hdr)); - if (buflen > 36) { + if (buflen > 35) { memcpy(&rbuf[8], "ATA ", 8); ata_dev_id_string(dev, &rbuf[16], ATA_ID_PROD_OFS, 16); ata_dev_id_string(dev, &rbuf[32], ATA_ID_FW_REV_OFS, 4); @@ -897,6 +1206,31 @@ void ata_scsi_badcmd(struct scsi_cmnd *c done(cmd); } +static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + + if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) + cmd->result = SAM_STAT_CHECK_CONDITION; + else { + u8 *scsicmd = cmd->cmnd; + + if (scsicmd[0] == INQUIRY) { + u8 *buf = NULL; + unsigned int buflen; + + buflen = ata_scsi_rbuf_get(cmd, &buf); + buf[2] = 0x5; + buf[3] = (buf[3] & 0xf0) | 2; + ata_scsi_rbuf_put(cmd); + } + cmd->result = SAM_STAT_GOOD; + } + + qc->scsidone(cmd); + + return 0; +} /** * atapi_xlat - Initialize PACKET taskfile * @qc: command structure to be initialized @@ -912,6 +1246,13 @@ void ata_scsi_badcmd(struct scsi_cmnd *c static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) { struct scsi_cmnd *cmd = qc->scsicmd; + struct ata_device *dev = qc->dev; + int using_pio = (dev->flags & ATA_DFLAG_PIO); + int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE); + + memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len); + + qc->complete_fn = atapi_qc_complete; qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; if (cmd->sc_data_direction == SCSI_DATA_WRITE) { @@ -921,19 +1262,18 @@ static unsigned int atapi_xlat(struct at qc->tf.command = ATA_CMD_PACKET; - /* no data - interrupt-driven */ - if (cmd->sc_data_direction == SCSI_DATA_NONE) - qc->tf.protocol = ATA_PROT_ATAPI; - - /* PIO data xfer - polling */ - else if ((qc->flags & ATA_QCFLAG_DMA) == 0) { - ata_qc_set_polling(qc); - qc->tf.protocol = ATA_PROT_ATAPI; + /* no data, or PIO data xfer */ + if (using_pio || nodata) { + if (nodata) + qc->tf.protocol = ATA_PROT_ATAPI_NODATA; + else + qc->tf.protocol = ATA_PROT_ATAPI; qc->tf.lbam = (8 * 1024) & 0xff; qc->tf.lbah = (8 * 1024) >> 8; + } - /* DMA data xfer - interrupt-driven */ - } else { + /* DMA data xfer */ + else { qc->tf.protocol = ATA_PROT_ATAPI_DMA; qc->tf.feature |= ATAPI_PKT_DMA; @@ -964,19 +1304,19 @@ static unsigned int atapi_xlat(struct at * Associated ATA device, or %NULL if not found. */ -static inline struct ata_device * -ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd) +static struct ata_device * +ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev) { struct ata_device *dev; /* skip commands not addressed to targets we simulate */ - if (likely(cmd->target < ATA_MAX_DEVICES)) - dev = &ap->device[cmd->target]; + if (likely(scsidev->id < ATA_MAX_DEVICES)) + dev = &ap->device[scsidev->id]; else return NULL; - if (unlikely((cmd->channel != 0) || - (cmd->lun != 0))) + if (unlikely((scsidev->channel != 0) || + (scsidev->lun != 0))) return NULL; if (unlikely(!ata_dev_present(dev))) @@ -992,6 +1332,7 @@ ata_scsi_find_dev(struct ata_port *ap, s /** * ata_get_xlat_func - check if SCSI to ATA translation is possible + * @dev: ATA device * @cmd: SCSI command opcode to consider * * Look up the SCSI command given, and determine whether the @@ -1001,7 +1342,7 @@ ata_scsi_find_dev(struct ata_port *ap, s * Pointer to translation function if possible, %NULL if not. */ -static inline ata_xlat_func_t ata_get_xlat_func(u8 cmd) +static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) { switch (cmd) { case READ_6: @@ -1012,6 +1353,15 @@ static inline ata_xlat_func_t ata_get_xl case WRITE_10: case WRITE_16: return ata_scsi_rw_xlat; + + case SYNCHRONIZE_CACHE: + if (ata_try_flush_cache(dev)) + return ata_scsi_flush_xlat; + break; + + case VERIFY: + case VERIFY_16: + return ata_scsi_verify_xlat; } return NULL; @@ -1029,11 +1379,12 @@ static inline void ata_scsi_dump_cdb(str struct scsi_cmnd *cmd) { #ifdef ATA_DEBUG + struct scsi_device *scsidev = cmd->device; u8 *scsicmd = cmd->cmnd; DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", ap->id, - cmd->channel, cmd->target, cmd->lun, + scsidev->channel, scsidev->id, scsidev->lun, scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3], scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7], scsicmd[8]); @@ -1063,17 +1414,18 @@ int ata_scsi_queuecmd(struct scsi_cmnd * { struct ata_port *ap; struct ata_device *dev; + struct scsi_device *scsidev = cmd->device; /* Note: spin_lock_irqsave is held by caller... */ spin_unlock(&io_request_lock); - ap = (struct ata_port *) &cmd->host->hostdata[0]; + ap = (struct ata_port *) &scsidev->host->hostdata[0]; spin_lock(&ap->host_set->lock); ata_scsi_dump_cdb(ap, cmd); - dev = ata_scsi_find_dev(ap, cmd); + dev = ata_scsi_find_dev(ap, scsidev); if (unlikely(!dev)) { cmd->result = (DID_BAD_TARGET << 16); done(cmd); @@ -1081,7 +1433,8 @@ int ata_scsi_queuecmd(struct scsi_cmnd * } if (dev->class == ATA_DEV_ATA) { - ata_xlat_func_t xlat_func = ata_get_xlat_func(cmd->cmnd[0]); + ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, + cmd->cmnd[0]); if (xlat_func) ata_scsi_translate(ap, dev, cmd, done, xlat_func); @@ -1124,7 +1477,7 @@ static void ata_scsi_simulate(struct ata switch(scsicmd[0]) { /* no-op's, complete with success */ - case SYNCHRONIZE_CACHE: /* FIXME: temporary */ + case SYNCHRONIZE_CACHE: case REZERO_UNIT: case SEEK_6: case SEEK_10: diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/libata.h linux-2.4.28-pre3/drivers/scsi/libata.h --- linux-2.4.27/drivers/scsi/libata.h 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/libata.h 2004-09-10 19:33:19.000000000 +0000 @@ -35,7 +35,6 @@ struct ata_scsi_args { void (*done)(struct scsi_cmnd *); }; - /* libata-core.c */ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_device *dev); @@ -43,10 +42,11 @@ extern int ata_qc_issue(struct ata_queue extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf); +extern void swap_buf_le16(u16 *buf, unsigned int buf_words); /* libata-scsi.c */ -extern void ata_to_sense_error(struct ata_queued_cmd *qc); +extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat); extern int ata_scsi_error(struct Scsi_Host *host); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/megaraid.c linux-2.4.28-pre3/drivers/scsi/megaraid.c --- linux-2.4.27/drivers/scsi/megaraid.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/megaraid.c 2004-09-10 19:31:51.000000000 +0000 @@ -3471,6 +3471,24 @@ int megaraid_detect (Scsi_Host_Template return count; } +static inline void mega_freeSgList (mega_host_config * megaCfg) +{ + int i; + + for (i = 0; i < megaCfg->max_cmds; i++) { + if (megaCfg->scbList[i].sgList) + pci_free_consistent (megaCfg->dev, + sizeof (mega_64sglist) * + MAX_SGLIST, + megaCfg->scbList[i].sgList, + megaCfg->scbList[i]. + dma_sghandle64); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) /* 0x020400 */ + kfree (megaCfg->scbList[i].sgList); /* free sgList */ +#endif + } +} + /*--------------------------------------------------------------------- * Release the controller's resources *---------------------------------------------------------------------*/ @@ -3880,24 +3898,6 @@ static void mega_swap_hosts (struct Scsi return; } -static inline void mega_freeSgList (mega_host_config * megaCfg) -{ - int i; - - for (i = 0; i < megaCfg->max_cmds; i++) { - if (megaCfg->scbList[i].sgList) - pci_free_consistent (megaCfg->dev, - sizeof (mega_64sglist) * - MAX_SGLIST, - megaCfg->scbList[i].sgList, - megaCfg->scbList[i]. - dma_sghandle64); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) /* 0x020400 */ - kfree (megaCfg->scbList[i].sgList); /* free sgList */ -#endif - } -} - /*---------------------------------------------- * Get information about the card/driver *----------------------------------------------*/ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/megaraid2.c linux-2.4.28-pre3/drivers/scsi/megaraid2.c --- linux-2.4.27/drivers/scsi/megaraid2.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/megaraid2.c 2004-09-10 19:33:15.000000000 +0000 @@ -936,6 +936,19 @@ mega_query_adapter(adapter_t *adapter) } +/** + * mega_runpendq() + * @adapter - pointer to our soft state + * + * Runs through the list of pending requests. + */ +static inline void +mega_runpendq(adapter_t *adapter) +{ + if(!list_empty(&adapter->pending_list)) + __mega_runpendq(adapter); +} + /* * megaraid_queue() * @scmd - Issue this scsi command @@ -986,6 +999,98 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*d /** + * mega_allocate_scb() + * @adapter - pointer to our soft state + * @cmd - scsi command from the mid-layer + * + * Allocate a SCB structure. This is the central structure for controller + * commands. + */ +static inline scb_t * +mega_allocate_scb(adapter_t *adapter, Scsi_Cmnd *cmd) +{ + struct list_head *head = &adapter->free_list; + scb_t *scb; + + /* Unlink command from Free List */ + if( !list_empty(head) ) { + + scb = list_entry(head->next, scb_t, list); + + list_del_init(head->next); + + scb->state = SCB_ACTIVE; + scb->cmd = cmd; + scb->dma_type = MEGA_DMA_TYPE_NONE; + + return scb; + } + + return NULL; +} + + +/** + * mega_get_ldrv_num() + * @adapter - pointer to our soft state + * @cmd - scsi mid layer command + * @channel - channel on the controller + * + * Calculate the logical drive number based on the information in scsi command + * and the channel number. + */ +static inline int +mega_get_ldrv_num(adapter_t *adapter, Scsi_Cmnd *cmd, int channel) +{ + int tgt; + int ldrv_num; + + tgt = cmd->target; + + if ( tgt > adapter->this_id ) + tgt--; /* we do not get inquires for initiator id */ + + ldrv_num = (channel * 15) + tgt; + + + /* + * If we have a logical drive with boot enabled, project it first + */ + if( adapter->boot_ldrv_enabled ) { + if( ldrv_num == 0 ) { + ldrv_num = adapter->boot_ldrv; + } + else { + if( ldrv_num <= adapter->boot_ldrv ) { + ldrv_num--; + } + } + } + + /* + * If "delete logical drive" feature is enabled on this controller. + * Do only if at least one delete logical drive operation was done. + * + * Also, after logical drive deletion, instead of logical drive number, + * the value returned should be 0x80+logical drive id. + * + * These is valid only for IO commands. + */ + + if (adapter->support_random_del && adapter->read_ldidmap ) + switch (cmd->cmnd[0]) { + case READ_6: /* fall through */ + case WRITE_6: /* fall through */ + case READ_10: /* fall through */ + case WRITE_10: + ldrv_num += 0x80; + } + + return ldrv_num; +} + + +/** * mega_build_cmd() * @adapter - pointer to our soft state * @cmd - Prepare using this scsi command @@ -1566,51 +1671,6 @@ mega_prepare_extpassthru(adapter_t *adap } -/** - * mega_allocate_scb() - * @adapter - pointer to our soft state - * @cmd - scsi command from the mid-layer - * - * Allocate a SCB structure. This is the central structure for controller - * commands. - */ -static inline scb_t * -mega_allocate_scb(adapter_t *adapter, Scsi_Cmnd *cmd) -{ - struct list_head *head = &adapter->free_list; - scb_t *scb; - - /* Unlink command from Free List */ - if( !list_empty(head) ) { - - scb = list_entry(head->next, scb_t, list); - - list_del_init(head->next); - - scb->state = SCB_ACTIVE; - scb->cmd = cmd; - scb->dma_type = MEGA_DMA_TYPE_NONE; - - return scb; - } - - return NULL; -} - - -/** - * mega_runpendq() - * @adapter - pointer to our soft state - * - * Runs through the list of pending requests. - */ -static inline void -mega_runpendq(adapter_t *adapter) -{ - if(!list_empty(&adapter->pending_list)) - __mega_runpendq(adapter); -} - static void __mega_runpendq(adapter_t *adapter) { @@ -1642,7 +1702,7 @@ __mega_runpendq(adapter_t *adapter) * busy. We also take the scb from the pending list if the mailbox is * available. */ -static inline int +static int issue_scb(adapter_t *adapter, scb_t *scb) { volatile mbox64_t *mbox64 = adapter->mbox64; @@ -1705,6 +1765,17 @@ issue_scb(adapter_t *adapter, scb_t *scb } +/* + * Wait until the controller's mailbox is available + */ +static inline int +mega_busywait_mbox (adapter_t *adapter) +{ + if (adapter->mbox->busy) + return __mega_busywait_mbox(adapter); + return 0; +} + /** * issue_scb_block() * @adapter - pointer to our soft state @@ -1807,38 +1878,6 @@ bug_blocked_mailbox: /** - * megaraid_isr_iomapped() - * @irq - irq - * @devp - pointer to our soft state - * @regs - unused - * - * Interrupt service routine for io-mapped controllers. - * Find out if our device is interrupting. If yes, acknowledge the interrupt - * and service the completed commands. - */ -static void -megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs) -{ - adapter_t *adapter = devp; - unsigned long flags; - - - spin_lock_irqsave(adapter->host_lock, flags); - - megaraid_iombox_ack_sequence(adapter); - - /* Loop through any pending requests */ - if( atomic_read(&adapter->quiescent ) == 0) { - mega_runpendq(adapter); - } - - spin_unlock_irqrestore(adapter->host_lock, flags); - - return; -} - - -/** * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs * @adapter - controller's soft state * @@ -1901,38 +1940,6 @@ megaraid_iombox_ack_sequence(adapter_t * /** - * megaraid_isr_memmapped() - * @irq - irq - * @devp - pointer to our soft state - * @regs - unused - * - * Interrupt service routine for memory-mapped controllers. - * Find out if our device is interrupting. If yes, acknowledge the interrupt - * and service the completed commands. - */ -static void -megaraid_isr_memmapped(int irq, void *devp, struct pt_regs *regs) -{ - adapter_t *adapter = devp; - unsigned long flags; - - - spin_lock_irqsave(adapter->host_lock, flags); - - megaraid_memmbox_ack_sequence(adapter); - - /* Loop through any pending requests */ - if(atomic_read(&adapter->quiescent) == 0) { - mega_runpendq(adapter); - } - - spin_unlock_irqrestore(adapter->host_lock, flags); - - return; -} - - -/** * megaraid_memmbox_ack_sequence - interrupt ack sequence for memory mapped HBAs * @adapter - controller's soft state * @@ -2000,6 +2007,70 @@ megaraid_memmbox_ack_sequence(adapter_t /** + * megaraid_isr_iomapped() + * @irq - irq + * @devp - pointer to our soft state + * @regs - unused + * + * Interrupt service routine for io-mapped controllers. + * Find out if our device is interrupting. If yes, acknowledge the interrupt + * and service the completed commands. + */ +static void +megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs) +{ + adapter_t *adapter = devp; + unsigned long flags; + + + spin_lock_irqsave(adapter->host_lock, flags); + + megaraid_iombox_ack_sequence(adapter); + + /* Loop through any pending requests */ + if( atomic_read(&adapter->quiescent ) == 0) { + mega_runpendq(adapter); + } + + spin_unlock_irqrestore(adapter->host_lock, flags); + + return; +} + + +/** + * megaraid_isr_memmapped() + * @irq - irq + * @devp - pointer to our soft state + * @regs - unused + * + * Interrupt service routine for memory-mapped controllers. + * Find out if our device is interrupting. If yes, acknowledge the interrupt + * and service the completed commands. + */ +static void +megaraid_isr_memmapped(int irq, void *devp, struct pt_regs *regs) +{ + adapter_t *adapter = devp; + unsigned long flags; + + + spin_lock_irqsave(adapter->host_lock, flags); + + megaraid_memmbox_ack_sequence(adapter); + + /* Loop through any pending requests */ + if(atomic_read(&adapter->quiescent) == 0) { + mega_runpendq(adapter); + } + + spin_unlock_irqrestore(adapter->host_lock, flags); + + return; +} + + +/** * mega_cmd_done() * @adapter - pointer to our soft state * @completed - array of ids of completed commands @@ -2008,7 +2079,7 @@ megaraid_memmbox_ack_sequence(adapter_t * * Complete the comamnds and call the scsi mid-layer callback hooks. */ -static inline void +static void mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status) { mega_ext_passthru *epthru = NULL; @@ -2311,17 +2382,6 @@ mega_free_scb(adapter_t *adapter, scb_t } -/* - * Wait until the controller's mailbox is available - */ -static inline int -mega_busywait_mbox (adapter_t *adapter) -{ - if (adapter->mbox->busy) - return __mega_busywait_mbox(adapter); - return 0; -} - static int __mega_busywait_mbox (adapter_t *adapter) { @@ -2476,6 +2536,44 @@ mega_8_to_40ld(mraid_inquiry *inquiry, m } +static inline void +mega_free_sgl(adapter_t *adapter) +{ + scb_t *scb; + int i; + + for(i = 0; i < adapter->max_cmds; i++) { + + scb = &adapter->scb_list[i]; + + if( scb->sgl64 ) { + pci_free_consistent(adapter->dev, + sizeof(mega_sgl64) * adapter->sglen, + scb->sgl64, + scb->sgl_dma_addr); + + scb->sgl64 = NULL; + } + + if( scb->pthru ) { + pci_free_consistent(adapter->dev, sizeof(mega_passthru), + scb->pthru, scb->pthru_dma_addr); + + scb->pthru = NULL; + } + + if( scb->epthru ) { + pci_free_consistent(adapter->dev, + sizeof(mega_ext_passthru), + scb->epthru, scb->epthru_dma_addr); + + scb->epthru = NULL; + } + + } +} + + /* * Release the controller's resources */ @@ -2605,44 +2703,6 @@ megaraid_release(struct Scsi_Host *host) return 0; } -static inline void -mega_free_sgl(adapter_t *adapter) -{ - scb_t *scb; - int i; - - for(i = 0; i < adapter->max_cmds; i++) { - - scb = &adapter->scb_list[i]; - - if( scb->sgl64 ) { - pci_free_consistent(adapter->dev, - sizeof(mega_sgl64) * adapter->sglen, - scb->sgl64, - scb->sgl_dma_addr); - - scb->sgl64 = NULL; - } - - if( scb->pthru ) { - pci_free_consistent(adapter->dev, sizeof(mega_passthru), - scb->pthru, scb->pthru_dma_addr); - - scb->pthru = NULL; - } - - if( scb->epthru ) { - pci_free_consistent(adapter->dev, - sizeof(mega_ext_passthru), - scb->epthru, scb->epthru_dma_addr); - - scb->epthru = NULL; - } - - } -} - - /* * Get information about the card/driver */ @@ -2860,6 +2920,27 @@ megaraid_reset(Scsi_Cmnd *cmd) } +/** + * mega_allocate_inquiry() + * @dma_handle - handle returned for dma address + * @pdev - handle to pci device + * + * allocates memory for inquiry structure + */ +static inline caddr_t +mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev) +{ + return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle); +} + + +static inline void +mega_free_inquiry(caddr_t inquiry, dma_addr_t dma_handle, struct pci_dev *pdev) +{ + pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle); +} + + #ifdef CONFIG_PROC_FS /* Following code handles /proc fs */ @@ -5069,66 +5150,6 @@ mega_support_cluster(adapter_t *adapter) /** - * mega_get_ldrv_num() - * @adapter - pointer to our soft state - * @cmd - scsi mid layer command - * @channel - channel on the controller - * - * Calculate the logical drive number based on the information in scsi command - * and the channel number. - */ -static inline int -mega_get_ldrv_num(adapter_t *adapter, Scsi_Cmnd *cmd, int channel) -{ - int tgt; - int ldrv_num; - - tgt = cmd->target; - - if ( tgt > adapter->this_id ) - tgt--; /* we do not get inquires for initiator id */ - - ldrv_num = (channel * 15) + tgt; - - - /* - * If we have a logical drive with boot enabled, project it first - */ - if( adapter->boot_ldrv_enabled ) { - if( ldrv_num == 0 ) { - ldrv_num = adapter->boot_ldrv; - } - else { - if( ldrv_num <= adapter->boot_ldrv ) { - ldrv_num--; - } - } - } - - /* - * If "delete logical drive" feature is enabled on this controller. - * Do only if at least one delete logical drive operation was done. - * - * Also, after logical drive deletion, instead of logical drive number, - * the value returned should be 0x80+logical drive id. - * - * These is valid only for IO commands. - */ - - if (adapter->support_random_del && adapter->read_ldidmap ) - switch (cmd->cmnd[0]) { - case READ_6: /* fall through */ - case WRITE_6: /* fall through */ - case READ_10: /* fall through */ - case WRITE_10: - ldrv_num += 0x80; - } - - return ldrv_num; -} - - -/** * mega_reorder_hosts() * * Hack: reorder the scsi hosts in mid-layer so that the controller with the @@ -5342,27 +5363,6 @@ mega_adapinq(adapter_t *adapter, dma_add } -/** - * mega_allocate_inquiry() - * @dma_handle - handle returned for dma address - * @pdev - handle to pci device - * - * allocates memory for inquiry structure - */ -static inline caddr_t -mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev) -{ - return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle); -} - - -static inline void -mega_free_inquiry(caddr_t inquiry, dma_addr_t dma_handle, struct pci_dev *pdev) -{ - pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle); -} - - /** mega_internal_dev_inquiry() * @adapter - pointer to our soft state * @ch - channel for this device diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/megaraid2.h linux-2.4.28-pre3/drivers/scsi/megaraid2.h --- linux-2.4.27/drivers/scsi/megaraid2.h 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/megaraid2.h 2004-09-10 19:31:58.000000000 +0000 @@ -1091,14 +1091,12 @@ const char *megaraid_info (struct Scsi_H static int megaraid_detect(Scsi_Host_Template *); static void mega_find_card(Scsi_Host_Template *, u16, u16); static int mega_query_adapter(adapter_t *); -static inline int issue_scb(adapter_t *, scb_t *); +static int issue_scb(adapter_t *, scb_t *); static int mega_setup_mailbox(adapter_t *); static int megaraid_queue (Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); static scb_t * mega_build_cmd(adapter_t *, Scsi_Cmnd *, int *); -static inline scb_t *mega_allocate_scb(adapter_t *, Scsi_Cmnd *); static void __mega_runpendq(adapter_t *); -static inline void mega_runpendq(adapter_t *); static int issue_scb_block(adapter_t *, u_char *); static void megaraid_isr_memmapped(int, void *, struct pt_regs *); @@ -1115,9 +1113,8 @@ static int megaraid_reset(Scsi_Cmnd *); static int mega_build_sglist (adapter_t *adapter, scb_t *scb, u32 *buffer, u32 *length); -static inline int mega_busywait_mbox (adapter_t *); static int __mega_busywait_mbox (adapter_t *); -static inline void mega_cmd_done(adapter_t *, u8 [], int, int); +static void mega_cmd_done(adapter_t *, u8 [], int, int); static inline void mega_free_sgl (adapter_t *adapter); static void mega_8_to_40ld (mraid_inquiry *inquiry, mega_inquiry3 *enquiry3, mega_product_info *); @@ -1167,8 +1164,6 @@ static int proc_rdrv(adapter_t *, char * static int mega_adapinq(adapter_t *, dma_addr_t); static int mega_internal_dev_inquiry(adapter_t *, u8, u8, dma_addr_t); -static inline caddr_t mega_allocate_inquiry(dma_addr_t *, struct pci_dev *); -static inline void mega_free_inquiry(caddr_t, dma_addr_t, struct pci_dev *); static int mega_print_inquiry(char *, char *); #endif @@ -1179,7 +1174,6 @@ static mega_ext_passthru* mega_prepare_e scb_t *, Scsi_Cmnd *, int, int); static void mega_enum_raid_scsi(adapter_t *); static void mega_get_boot_drv(adapter_t *); -static inline int mega_get_ldrv_num(adapter_t *, Scsi_Cmnd *, int); static int mega_support_random_del(adapter_t *); static int mega_del_logdrv(adapter_t *, int); static int mega_do_del_logdrv(adapter_t *, int); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/nsp32.c linux-2.4.28-pre3/drivers/scsi/nsp32.c --- linux-2.4.27/drivers/scsi/nsp32.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/nsp32.c 2004-09-10 19:35:18.000000000 +0000 @@ -3365,6 +3365,48 @@ static int nsp32_prom_read(nsp32_hw_data return val; } +static inline void nsp32_prom_set(nsp32_hw_data *data, int bit, int val) +{ + unsigned int base = data->BaseAddress; + int tmp; + + tmp = nsp32_index_read1(base, SERIAL_ROM_CTL); + + if (val == 0) { + tmp &= ~bit; + } else { + tmp |= bit; + } + + nsp32_index_write1(base, SERIAL_ROM_CTL, tmp); + + udelay(10); +} + +static inline int nsp32_prom_get(nsp32_hw_data *data, int bit) +{ + unsigned int base = data->BaseAddress; + int tmp, ret; + + if (bit != SROM_DATA) { + nsp32_msg(KERN_ERR, "return value is not appropriate"); + return 0; + } + + + tmp = nsp32_index_read1(base, SERIAL_ROM_CTL) & bit; + + if (tmp == 0) { + ret = 0; + } else { + ret = 1; + } + + udelay(10); + + return ret; +} + static void nsp32_prom_start (nsp32_hw_data *data) { /* start condition */ @@ -3410,49 +3452,6 @@ static int nsp32_prom_read_bit(nsp32_hw_ return val; } -static inline void nsp32_prom_set(nsp32_hw_data *data, int bit, int val) -{ - unsigned int base = data->BaseAddress; - int tmp; - - tmp = nsp32_index_read1(base, SERIAL_ROM_CTL); - - if (val == 0) { - tmp &= ~bit; - } else { - tmp |= bit; - } - - nsp32_index_write1(base, SERIAL_ROM_CTL, tmp); - - udelay(10); -} - -static inline int nsp32_prom_get(nsp32_hw_data *data, int bit) -{ - unsigned int base = data->BaseAddress; - int tmp, ret; - - if (bit != SROM_DATA) { - nsp32_msg(KERN_ERR, "return value is not appropriate"); - return 0; - } - - - tmp = nsp32_index_read1(base, SERIAL_ROM_CTL) & bit; - - if (tmp == 0) { - ret = 0; - } else { - ret = 1; - } - - udelay(10); - - return ret; -} - - /************************************************************************** * Power Management */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/pluto.c linux-2.4.28-pre3/drivers/scsi/pluto.c --- linux-2.4.27/drivers/scsi/pluto.c 2001-02-09 19:30:23.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/pluto.c 2004-09-10 19:33:54.000000000 +0000 @@ -339,4 +339,4 @@ static Scsi_Host_Template driver_templat #include "scsi_module.c" -EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/qla1280.c linux-2.4.28-pre3/drivers/scsi/qla1280.c --- linux-2.4.27/drivers/scsi/qla1280.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/qla1280.c 2004-09-10 19:37:20.000000000 +0000 @@ -875,6 +875,41 @@ static int qla1280_read_nvram(struct scs } + /* + * qla2100_enable_intrs + * qla2100_disable_intrs + * + * Input: + * ha = adapter block pointer. + * + * Returns: + * None + */ +static inline void +qla1280_enable_intrs(struct scsi_qla_host *ha) +{ + struct device_reg *reg; + + reg = ha->iobase; + /* enable risc and host interrupts */ + WRT_REG_WORD(®->ictrl, (ISP_EN_INT | ISP_EN_RISC)); + RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */ + ha->flags.ints_enabled = 1; +} + +static inline void +qla1280_disable_intrs(struct scsi_qla_host *ha) +{ + struct device_reg *reg; + + reg = ha->iobase; + /* disable risc and host interrupts */ + WRT_REG_WORD(®->ictrl, 0); + RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */ + ha->flags.ints_enabled = 0; +} + + /************************************************************************** * qla1280_do_device_init * This routine will register the device with the SCSI subsystem, @@ -2049,40 +2084,6 @@ qla1280_mem_free(struct scsi_qla_host *h /* QLogic ISP1280 Hardware Support Functions. */ /****************************************************************************/ - /* - * qla2100_enable_intrs - * qla2100_disable_intrs - * - * Input: - * ha = adapter block pointer. - * - * Returns: - * None - */ -static inline void -qla1280_enable_intrs(struct scsi_qla_host *ha) -{ - struct device_reg *reg; - - reg = ha->iobase; - /* enable risc and host interrupts */ - WRT_REG_WORD(®->ictrl, (ISP_EN_INT | ISP_EN_RISC)); - RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */ - ha->flags.ints_enabled = 1; -} - -static inline void -qla1280_disable_intrs(struct scsi_qla_host *ha) -{ - struct device_reg *reg; - - reg = ha->iobase; - /* disable risc and host interrupts */ - WRT_REG_WORD(®->ictrl, 0); - RD_REG_WORD(®->ictrl); /* PCI Posted Write flush */ - ha->flags.ints_enabled = 0; -} - /* * qla1280_initialize_adapter * Initialize board. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/qlogicfc.c linux-2.4.28-pre3/drivers/scsi/qlogicfc.c --- linux-2.4.27/drivers/scsi/qlogicfc.c 2004-04-14 13:05:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/qlogicfc.c 2004-09-10 19:36:03.000000000 +0000 @@ -722,7 +722,7 @@ int isp2x00_detect(Scsi_Host_Template * continue; /* Try to configure DMA attributes. */ - if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff) && + if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) && pci_set_dma_mask(pdev, (u64) 0xffffffff)) continue; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/qlogicpti.c linux-2.4.28-pre3/drivers/scsi/qlogicpti.c --- linux-2.4.27/drivers/scsi/qlogicpti.c 2004-04-14 13:05:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/qlogicpti.c 2004-09-10 19:35:48.000000000 +0000 @@ -1533,4 +1533,4 @@ static Scsi_Host_Template driver_templat #include "scsi_module.c" -EXPORT_NO_SYMBOLS; +MODULE_LICENSE("GPL"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_nv.c linux-2.4.28-pre3/drivers/scsi/sata_nv.c --- linux-2.4.27/drivers/scsi/sata_nv.c 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/sata_nv.c 2004-09-10 19:37:06.000000000 +0000 @@ -0,0 +1,556 @@ +/* + * sata_nv.c - NVIDIA nForce SATA + * + * Copyright 2004 NVIDIA Corp. All rights reserved. + * Copyright 2004 Andrew Chew + * + * The contents of this file are subject to the Open + * Software License version 1.1 that can be found at + * http://www.opensource.org/licenses/osl-1.1.txt and is included herein + * by reference. + * + * Alternatively, the contents of this file may be used under the terms + * of the GNU General Public License version 2 (the "GPL") as distributed + * in the kernel source COPYING file, in which case the provisions of + * the GPL are applicable instead of the above. If you wish to allow + * the use of your version of this file only under the terms of the + * GPL and not to allow others to use your version of this file under + * the OSL, indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by the GPL. + * If you do not delete the provisions above, a recipient may use your + * version of this file under either the OSL or the GPL. + * + * 0.03 + * - Fixed a bug where the hotplug handlers for non-CK804/MCP04 were using + * mmio_base, which is only set for the CK804/MCP04 case. + * + * 0.02 + * - Added support for CK804 SATA controller. + * + * 0.01 + * - Initial revision. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include +#include + +#define DRV_NAME "sata_nv" +#define DRV_VERSION "0.03" + +#define NV_PORTS 2 +#define NV_PIO_MASK 0x1f +#define NV_MWDMA_MASK 0x07 +#define NV_UDMA_MASK 0x7f +#define NV_PORT0_BMDMA_REG_OFFSET 0x00 +#define NV_PORT1_BMDMA_REG_OFFSET 0x08 +#define NV_PORT0_SCR_REG_OFFSET 0x00 +#define NV_PORT1_SCR_REG_OFFSET 0x40 + +#define NV_INT_STATUS 0x10 +#define NV_INT_STATUS_CK804 0x440 +#define NV_INT_STATUS_PDEV_INT 0x01 +#define NV_INT_STATUS_PDEV_PM 0x02 +#define NV_INT_STATUS_PDEV_ADDED 0x04 +#define NV_INT_STATUS_PDEV_REMOVED 0x08 +#define NV_INT_STATUS_SDEV_INT 0x10 +#define NV_INT_STATUS_SDEV_PM 0x20 +#define NV_INT_STATUS_SDEV_ADDED 0x40 +#define NV_INT_STATUS_SDEV_REMOVED 0x80 +#define NV_INT_STATUS_PDEV_HOTPLUG (NV_INT_STATUS_PDEV_ADDED | \ + NV_INT_STATUS_PDEV_REMOVED) +#define NV_INT_STATUS_SDEV_HOTPLUG (NV_INT_STATUS_SDEV_ADDED | \ + NV_INT_STATUS_SDEV_REMOVED) +#define NV_INT_STATUS_HOTPLUG (NV_INT_STATUS_PDEV_HOTPLUG | \ + NV_INT_STATUS_SDEV_HOTPLUG) + +#define NV_INT_ENABLE 0x11 +#define NV_INT_ENABLE_CK804 0x441 +#define NV_INT_ENABLE_PDEV_MASK 0x01 +#define NV_INT_ENABLE_PDEV_PM 0x02 +#define NV_INT_ENABLE_PDEV_ADDED 0x04 +#define NV_INT_ENABLE_PDEV_REMOVED 0x08 +#define NV_INT_ENABLE_SDEV_MASK 0x10 +#define NV_INT_ENABLE_SDEV_PM 0x20 +#define NV_INT_ENABLE_SDEV_ADDED 0x40 +#define NV_INT_ENABLE_SDEV_REMOVED 0x80 +#define NV_INT_ENABLE_PDEV_HOTPLUG (NV_INT_ENABLE_PDEV_ADDED | \ + NV_INT_ENABLE_PDEV_REMOVED) +#define NV_INT_ENABLE_SDEV_HOTPLUG (NV_INT_ENABLE_SDEV_ADDED | \ + NV_INT_ENABLE_SDEV_REMOVED) +#define NV_INT_ENABLE_HOTPLUG (NV_INT_ENABLE_PDEV_HOTPLUG | \ + NV_INT_ENABLE_SDEV_HOTPLUG) + +#define NV_INT_CONFIG 0x12 +#define NV_INT_CONFIG_METHD 0x01 // 0 = INT, 1 = SMI + +// For PCI config register 20 +#define NV_MCP_SATA_CFG_20 0x50 +#define NV_MCP_SATA_CFG_20_SATA_SPACE_EN 0x04 + +static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs); +static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); +static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); +static void nv_host_stop (struct ata_host_set *host_set); +static void nv_enable_hotplug(struct ata_probe_ent *probe_ent); +static void nv_disable_hotplug(struct ata_host_set *host_set); +static void nv_check_hotplug(struct ata_host_set *host_set); +static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent); +static void nv_disable_hotplug_ck804(struct ata_host_set *host_set); +static void nv_check_hotplug_ck804(struct ata_host_set *host_set); + +enum nv_host_type +{ + NFORCE2, + NFORCE3, + CK804 +}; + +static struct pci_device_id nv_pci_tbl[] = { + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE2 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 }, + { 0, } /* terminate list */ +}; + +#define NV_HOST_FLAGS_SCR_MMIO 0x00000001 + +struct nv_host_desc +{ + enum nv_host_type host_type; + unsigned long host_flags; + void (*enable_hotplug)(struct ata_probe_ent *probe_ent); + void (*disable_hotplug)(struct ata_host_set *host_set); + void (*check_hotplug)(struct ata_host_set *host_set); + +}; +static struct nv_host_desc nv_device_tbl[] = { + { + .host_type = NFORCE2, + .host_flags = 0x00000000, + .enable_hotplug = nv_enable_hotplug, + .disable_hotplug= nv_disable_hotplug, + .check_hotplug = nv_check_hotplug, + }, + { + .host_type = NFORCE3, + .host_flags = 0x00000000, + .enable_hotplug = nv_enable_hotplug, + .disable_hotplug= nv_disable_hotplug, + .check_hotplug = nv_check_hotplug, + }, + { .host_type = CK804, + .host_flags = NV_HOST_FLAGS_SCR_MMIO, + .enable_hotplug = nv_enable_hotplug_ck804, + .disable_hotplug= nv_disable_hotplug_ck804, + .check_hotplug = nv_check_hotplug_ck804, + }, +}; + +struct nv_host +{ + struct nv_host_desc *host_desc; +}; + +static struct pci_driver nv_pci_driver = { + .name = DRV_NAME, + .id_table = nv_pci_tbl, + .probe = nv_init_one, + .remove = ata_pci_remove_one, +}; + +static Scsi_Host_Template nv_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .detect = ata_scsi_detect, + .release = ata_scsi_release, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .use_new_eh_code = ATA_SHT_NEW_EH_CODE, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations nv_ops = { + .port_disable = ata_port_disable, + .tf_load = ata_tf_load_pio, + .tf_read = ata_tf_read_pio, + .exec_command = ata_exec_command_pio, + .check_status = ata_check_status_pio, + .phy_reset = sata_phy_reset, + .bmdma_setup = ata_bmdma_setup_pio, + .bmdma_start = ata_bmdma_start_pio, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, + .irq_handler = nv_interrupt, + .irq_clear = ata_bmdma_irq_clear, + .scr_read = nv_scr_read, + .scr_write = nv_scr_write, + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = nv_host_stop, +}; + +MODULE_AUTHOR("NVIDIA"); +MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, nv_pci_tbl); + +irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + struct nv_host *host = host_set->private_data; + unsigned int i; + unsigned int handled = 0; + unsigned long flags; + + spin_lock_irqsave(&host_set->lock, flags); + + for (i = 0; i < host_set->n_ports; i++) { + struct ata_port *ap; + + ap = host_set->ports[i]; + if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { + struct ata_queued_cmd *qc; + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc && (!(qc->tf.ctl & ATA_NIEN))) + handled += ata_host_intr(ap, qc); + } + + } + + if (host->host_desc->check_hotplug) + host->host_desc->check_hotplug(host_set); + + spin_unlock_irqrestore(&host_set->lock, flags); + + return IRQ_RETVAL(handled); +} + +static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg) +{ + struct ata_host_set *host_set = ap->host_set; + struct nv_host *host = host_set->private_data; + + if (sc_reg > SCR_CONTROL) + return 0xffffffffU; + + if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) + return readl(ap->ioaddr.scr_addr + (sc_reg * 4)); + else + return inl(ap->ioaddr.scr_addr + (sc_reg * 4)); +} + +static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) +{ + struct ata_host_set *host_set = ap->host_set; + struct nv_host *host = host_set->private_data; + + if (sc_reg > SCR_CONTROL) + return; + + if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) + writel(val, ap->ioaddr.scr_addr + (sc_reg * 4)); + else + outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)); +} + +static void nv_host_stop (struct ata_host_set *host_set) +{ + struct nv_host *host = host_set->private_data; + + // Disable hotplug event interrupts. + if (host->host_desc->disable_hotplug) + host->host_desc->disable_hotplug(host_set); + + kfree(host); +} + +static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version = 0; + struct nv_host *host; + struct ata_probe_ent *probe_ent = NULL; + int rc; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (!probe_ent) { + rc = -ENOMEM; + goto err_out_regions; + } + + host = kmalloc(sizeof(struct nv_host), GFP_KERNEL); + if (!host) { + rc = -ENOMEM; + goto err_out_free_ent; + } + + host->host_desc = &nv_device_tbl[ent->driver_data]; + + memset(probe_ent, 0, sizeof(*probe_ent)); + INIT_LIST_HEAD(&probe_ent->node); + + probe_ent->pdev = pdev; + probe_ent->sht = &nv_sht; + probe_ent->host_flags = ATA_FLAG_SATA | + ATA_FLAG_SATA_RESET | + ATA_FLAG_SRST | + ATA_FLAG_NO_LEGACY; + + probe_ent->port_ops = &nv_ops; + probe_ent->n_ports = NV_PORTS; + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + probe_ent->pio_mask = NV_PIO_MASK; + probe_ent->mwdma_mask = NV_MWDMA_MASK; + probe_ent->udma_mask = NV_UDMA_MASK; + + probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); + ata_std_ports(&probe_ent->port[0]); + probe_ent->port[0].altstatus_addr = + probe_ent->port[0].ctl_addr = + pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; + probe_ent->port[0].bmdma_addr = + pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET; + + probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); + ata_std_ports(&probe_ent->port[1]); + probe_ent->port[1].altstatus_addr = + probe_ent->port[1].ctl_addr = + pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; + probe_ent->port[1].bmdma_addr = + pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET; + + probe_ent->private_data = host; + + if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) { + unsigned long base; + + probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5), + pci_resource_len(pdev, 5)); + if (probe_ent->mmio_base == NULL) + goto err_out_iounmap; + + base = (unsigned long)probe_ent->mmio_base; + + probe_ent->port[0].scr_addr = + base + NV_PORT0_SCR_REG_OFFSET; + probe_ent->port[1].scr_addr = + base + NV_PORT1_SCR_REG_OFFSET; + } else { + + probe_ent->port[0].scr_addr = + pci_resource_start(pdev, 5) | NV_PORT0_SCR_REG_OFFSET; + probe_ent->port[1].scr_addr = + pci_resource_start(pdev, 5) | NV_PORT1_SCR_REG_OFFSET; + } + + pci_set_master(pdev); + + // Enable hotplug event interrupts. + if (host->host_desc->enable_hotplug) + host->host_desc->enable_hotplug(probe_ent); + + ata_add_to_probe_list(probe_ent); + + return 0; + +err_out_iounmap: + if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) + iounmap(probe_ent->mmio_base); + +err_out_free_ent: + kfree(probe_ent); + +err_out_regions: + pci_release_regions(pdev); + +err_out: + pci_disable_device(pdev); + return rc; +} + +static void nv_enable_hotplug(struct ata_probe_ent *probe_ent) +{ + u8 intr_mask; + + outb(NV_INT_STATUS_HOTPLUG, + probe_ent->port[0].scr_addr + NV_INT_STATUS); + + intr_mask = inb(probe_ent->port[0].scr_addr + NV_INT_ENABLE); + intr_mask |= NV_INT_ENABLE_HOTPLUG; + + outb(intr_mask, probe_ent->port[0].scr_addr + NV_INT_ENABLE); +} + +static void nv_disable_hotplug(struct ata_host_set *host_set) +{ + u8 intr_mask; + + intr_mask = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); + + intr_mask &= ~(NV_INT_ENABLE_HOTPLUG); + + outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); +} + +static void nv_check_hotplug(struct ata_host_set *host_set) +{ + u8 intr_status; + + intr_status = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); + + // Clear interrupt status. + outb(0xff, host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); + + if (intr_status & NV_INT_STATUS_HOTPLUG) { + if (intr_status & NV_INT_STATUS_PDEV_ADDED) + printk(KERN_WARNING "nv_sata: " + "Primary device added\n"); + + if (intr_status & NV_INT_STATUS_PDEV_REMOVED) + printk(KERN_WARNING "nv_sata: " + "Primary device removed\n"); + + if (intr_status & NV_INT_STATUS_SDEV_ADDED) + printk(KERN_WARNING "nv_sata: " + "Secondary device added\n"); + + if (intr_status & NV_INT_STATUS_SDEV_REMOVED) + printk(KERN_WARNING "nv_sata: " + "Secondary device removed\n"); + } +} + +static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) +{ + u8 intr_mask; + u8 regval; + + pci_read_config_byte(probe_ent->pdev, NV_MCP_SATA_CFG_20, ®val); + regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; + pci_write_config_byte(probe_ent->pdev, NV_MCP_SATA_CFG_20, regval); + + writeb(NV_INT_STATUS_HOTPLUG, probe_ent->mmio_base + NV_INT_STATUS_CK804); + + intr_mask = readb(probe_ent->mmio_base + NV_INT_ENABLE_CK804); + intr_mask |= NV_INT_ENABLE_HOTPLUG; + + writeb(intr_mask, probe_ent->mmio_base + NV_INT_ENABLE_CK804); +} + +static void nv_disable_hotplug_ck804(struct ata_host_set *host_set) +{ + u8 intr_mask; + u8 regval; + + intr_mask = readb(host_set->mmio_base + NV_INT_ENABLE_CK804); + + intr_mask &= ~(NV_INT_ENABLE_HOTPLUG); + + writeb(intr_mask, host_set->mmio_base + NV_INT_ENABLE_CK804); + + pci_read_config_byte(host_set->pdev, NV_MCP_SATA_CFG_20, ®val); + regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN; + pci_write_config_byte(host_set->pdev, NV_MCP_SATA_CFG_20, regval); +} + +static void nv_check_hotplug_ck804(struct ata_host_set *host_set) +{ + u8 intr_status; + + intr_status = readb(host_set->mmio_base + NV_INT_STATUS_CK804); + + // Clear interrupt status. + writeb(0xff, host_set->mmio_base + NV_INT_STATUS_CK804); + + if (intr_status & NV_INT_STATUS_HOTPLUG) { + if (intr_status & NV_INT_STATUS_PDEV_ADDED) + printk(KERN_WARNING "nv_sata: " + "Primary device added\n"); + + if (intr_status & NV_INT_STATUS_PDEV_REMOVED) + printk(KERN_WARNING "nv_sata: " + "Primary device removed\n"); + + if (intr_status & NV_INT_STATUS_SDEV_ADDED) + printk(KERN_WARNING "nv_sata: " + "Secondary device added\n"); + + if (intr_status & NV_INT_STATUS_SDEV_REMOVED) + printk(KERN_WARNING "nv_sata: " + "Secondary device removed\n"); + } +} + +static int __init nv_init(void) +{ + int rc; + + rc = pci_module_init(&nv_pci_driver); + if (rc) + return rc; + + rc = scsi_register_module(MODULE_SCSI_HA, &nv_sht); + if (rc) { + pci_unregister_driver(&nv_pci_driver); + /* TODO: does scsi_register_module return errno val? */ + return -ENODEV; + } + + return 0; +} + +static void __exit nv_exit(void) +{ + scsi_unregister_module(MODULE_SCSI_HA, &nv_sht); + pci_unregister_driver(&nv_pci_driver); +} + +module_init(nv_init); +module_exit(nv_exit); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_promise.c linux-2.4.28-pre3/drivers/scsi/sata_promise.c --- linux-2.4.27/drivers/scsi/sata_promise.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/sata_promise.c 2004-09-10 19:31:55.000000000 +0000 @@ -42,6 +42,7 @@ #define DRV_NAME "sata_promise" #define DRV_VERSION "1.00" +#define msleep libata_msleep /* 2.4-specific */ enum { PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ @@ -74,24 +75,23 @@ struct pdc_port_priv { static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static void pdc_dma_setup(struct ata_queued_cmd *qc); -static void pdc_dma_start(struct ata_queued_cmd *qc); static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static void pdc_eng_timeout(struct ata_port *ap); static int pdc_port_start(struct ata_port *ap); static void pdc_port_stop(struct ata_port *ap); static void pdc_phy_reset(struct ata_port *ap); -static void pdc_fill_sg(struct ata_queued_cmd *qc); +static void pdc_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); -static inline void pdc_dma_complete (struct ata_port *ap, - struct ata_queued_cmd *qc, int have_err); +static void pdc_irq_clear(struct ata_port *ap); +static int pdc_qc_issue_prot(struct ata_queued_cmd *qc); static Scsi_Host_Template pdc_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .detect = ata_scsi_detect, .release = ata_scsi_release, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -113,11 +113,11 @@ static struct ata_port_operations pdc_sa .check_status = ata_check_status_mmio, .exec_command = pdc_exec_command_mmio, .phy_reset = pdc_phy_reset, - .bmdma_setup = pdc_dma_setup, - .bmdma_start = pdc_dma_start, - .fill_sg = pdc_fill_sg, + .qc_prep = pdc_qc_prep, + .qc_issue = pdc_qc_issue_prot, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc_interrupt, + .irq_clear = pdc_irq_clear, .scr_read = pdc_sata_scr_read, .scr_write = pdc_sata_scr_write, .port_start = pdc_port_start, @@ -130,7 +130,8 @@ static struct ata_port_info pdc_port_inf .sht = &pdc_sata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO, - .pio_mask = 0x03, /* pio3-4 */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_sata_ops, }, @@ -140,7 +141,8 @@ static struct ata_port_info pdc_port_inf .sht = &pdc_sata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO, - .pio_mask = 0x03, /* pio3-4 */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_sata_ops, }, @@ -262,33 +264,33 @@ static void pdc_sata_scr_write (struct a writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4)); } -static void pdc_fill_sg(struct ata_queued_cmd *qc) +static void pdc_qc_prep(struct ata_queued_cmd *qc) { struct pdc_port_priv *pp = qc->ap->private_data; unsigned int i; VPRINTK("ENTER\n"); - ata_fill_sg(qc); - - i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma, qc->dev->devno, pp->pkt); + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + ata_qc_prep(qc); + /* fall through */ - if (qc->tf.flags & ATA_TFLAG_LBA48) - i = pdc_prep_lba48(&qc->tf, pp->pkt, i); - else - i = pdc_prep_lba28(&qc->tf, pp->pkt, i); + case ATA_PROT_NODATA: + i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma, + qc->dev->devno, pp->pkt); - pdc_pkt_footer(&qc->tf, pp->pkt, i); -} + if (qc->tf.flags & ATA_TFLAG_LBA48) + i = pdc_prep_lba48(&qc->tf, pp->pkt, i); + else + i = pdc_prep_lba28(&qc->tf, pp->pkt, i); -static inline void pdc_dma_complete (struct ata_port *ap, - struct ata_queued_cmd *qc, - int have_err) -{ - u8 err_bit = have_err ? ATA_ERR : 0; + pdc_pkt_footer(&qc->tf, pp->pkt, i); + break; - /* get drive status; clear intr; complete txn */ - ata_qc_complete(qc, ata_wait_idle(ap) | err_bit); + default: + break; + } } static void pdc_eng_timeout(struct ata_port *ap) @@ -315,17 +317,9 @@ static void pdc_eng_timeout(struct ata_p switch (qc->tf.protocol) { case ATA_PROT_DMA: - printk(KERN_ERR "ata%u: DMA timeout\n", ap->id); - ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR); - break; - case ATA_PROT_NODATA: - drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); - - ata_qc_complete(qc, drv_stat); + printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR); break; default: @@ -358,13 +352,8 @@ static inline unsigned int pdc_host_intr switch (qc->tf.protocol) { case ATA_PROT_DMA: - pdc_dma_complete(ap, qc, have_err); - handled = 1; - break; - - case ATA_PROT_NODATA: /* command completion, but no data xfer */ - status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); + case ATA_PROT_NODATA: + status = ata_wait_idle(ap); if (have_err) status |= ATA_ERR; ata_qc_complete(qc, status); @@ -379,6 +368,14 @@ static inline unsigned int pdc_host_intr return handled; } +static void pdc_irq_clear(struct ata_port *ap) +{ + struct ata_host_set *host_set = ap->host_set; + void *mmio = host_set->mmio_base; + + readl(mmio + PDC_INT_SEQMASK); +} + static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; @@ -432,13 +429,7 @@ static irqreturn_t pdc_interrupt (int ir return IRQ_RETVAL(handled); } -static void pdc_dma_setup(struct ata_queued_cmd *qc) -{ - /* nothing for now. later, we will call standard - * code in libata-core for ATAPI here */ -} - -static void pdc_dma_start(struct ata_queued_cmd *qc) +static inline void pdc_packet_start(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct pdc_port_priv *pp = ap->private_data; @@ -456,17 +447,38 @@ static void pdc_dma_start(struct ata_que readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */ } +static int pdc_qc_issue_prot(struct ata_queued_cmd *qc) +{ + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + case ATA_PROT_NODATA: + pdc_packet_start(qc); + return 0; + + case ATA_PROT_ATAPI_DMA: + BUG(); + break; + + default: + break; + } + + return ata_qc_issue_prot(qc); +} + static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) { - if (tf->protocol != ATA_PROT_DMA) - ata_tf_load_mmio(ap, tf); + WARN_ON (tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); + ata_tf_load_mmio(ap, tf); } static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) { - if (tf->protocol != ATA_PROT_DMA) - ata_exec_command_mmio(ap, tf); + WARN_ON (tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); + ata_exec_command_mmio(ap, tf); } @@ -519,8 +531,7 @@ static void pdc_host_init(unsigned int c writel(tmp, mmio + PDC_TBG_MODE); readl(mmio + PDC_TBG_MODE); /* flush */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(10) + 1); + msleep(10); /* adjust slew rate control register. */ tmp = readl(mmio + PDC_SLEW_CTL); @@ -578,6 +589,7 @@ static int pdc_sata_init_one (struct pci probe_ent->sht = pdc_port_info[board_idx].sht; probe_ent->host_flags = pdc_port_info[board_idx].host_flags; probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; + probe_ent->mwdma_mask = pdc_port_info[board_idx].mwdma_mask; probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask; probe_ent->port_ops = pdc_port_info[board_idx].port_ops; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_sil.c linux-2.4.28-pre3/drivers/scsi/sata_sil.c --- linux-2.4.27/drivers/scsi/sata_sil.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/sata_sil.c 2004-09-10 19:35:04.000000000 +0000 @@ -6,7 +6,7 @@ * on emails. * * Copyright 2003 Red Hat, Inc. - * Copyright 2003 Benjamin Herrenschmidt + * Copyright 2003 Benjamin Herrenschmidt * * The contents of this file are subject to the Open * Software License version 1.1 that can be found at @@ -86,6 +86,7 @@ struct sil_drivelist { { "ST360015AS", SIL_QUIRK_MOD15WRITE }, { "ST380023AS", SIL_QUIRK_MOD15WRITE }, { "ST3120023AS", SIL_QUIRK_MOD15WRITE }, + { "ST3160023AS", SIL_QUIRK_MOD15WRITE }, { "ST340014ASL", SIL_QUIRK_MOD15WRITE }, { "ST360014ASL", SIL_QUIRK_MOD15WRITE }, { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, @@ -107,6 +108,7 @@ static Scsi_Host_Template sil_sht = { .name = DRV_NAME, .detect = ata_scsi_detect, .release = ata_scsi_release, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -132,9 +134,11 @@ static struct ata_port_operations sil_op .post_set_mode = sil_post_set_mode, .bmdma_setup = ata_bmdma_setup_mmio, .bmdma_start = ata_bmdma_start_mmio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, .scr_read = sil_scr_read, .scr_write = sil_scr_write, .port_start = ata_port_start, @@ -147,7 +151,8 @@ static struct ata_port_info sil_port_inf .sht = &sil_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO, - .pio_mask = 0x03, /* pio3-4 */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil_ops, }, /* sil_3114 */ @@ -155,7 +160,8 @@ static struct ata_port_info sil_port_inf .sht = &sil_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO, - .pio_mask = 0x03, /* pio3-4 */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil_ops, }, @@ -303,6 +309,7 @@ static void sil_dev_config(struct ata_po ap->id, dev->devno); ap->host->max_sectors = 15; ap->host->hostt->max_sectors = 15; + dev->flags |= ATA_DFLAG_LOCK_SECTORS; return; } @@ -357,6 +364,7 @@ static int sil_init_one (struct pci_dev probe_ent->sht = sil_port_info[ent->driver_data].sht; probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2; probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask; + probe_ent->mwdma_mask = sil_port_info[ent->driver_data].mwdma_mask; probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask; probe_ent->irq = pdev->irq; probe_ent->irq_flags = SA_SHIRQ; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_sis.c linux-2.4.28-pre3/drivers/scsi/sata_sis.c --- linux-2.4.27/drivers/scsi/sata_sis.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/sata_sis.c 2004-09-10 19:34:29.000000000 +0000 @@ -78,6 +78,7 @@ static Scsi_Host_Template sis_sht = { .name = DRV_NAME, .detect = ata_scsi_detect, .release = ata_scsi_release, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -101,9 +102,11 @@ static struct ata_port_operations sis_op .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup_pio, .bmdma_start = ata_bmdma_start_pio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, .scr_read = sis_scr_read, .scr_write = sis_scr_write, .port_start = ata_port_start, @@ -226,7 +229,8 @@ static int sis_init_one (struct pci_dev probe_ent->host_flags |= SIS_FLAG_CFGSCR; } - probe_ent->pio_mask = 0x03; + probe_ent->pio_mask = 0x1f; + probe_ent->mwdma_mask = 0x7; probe_ent->udma_mask = 0x7f; probe_ent->port_ops = &sis_ops; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_svw.c linux-2.4.28-pre3/drivers/scsi/sata_svw.c --- linux-2.4.27/drivers/scsi/sata_svw.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/sata_svw.c 2004-09-10 19:35:43.000000000 +0000 @@ -207,6 +207,7 @@ static Scsi_Host_Template k2_sata_sht = .name = DRV_NAME, .detect = ata_scsi_detect, .release = ata_scsi_release, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -234,9 +235,11 @@ static struct ata_port_operations k2_sat .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup_mmio, .bmdma_start = ata_bmdma_start_mmio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, .scr_read = k2_sata_scr_read, .scr_write = k2_sata_scr_write, .port_start = ata_port_start, @@ -339,6 +342,7 @@ static int k2_sata_init_one (struct pci_ * if we don't fill these */ probe_ent->pio_mask = 0x1f; + probe_ent->mwdma_mask = 0x7; probe_ent->udma_mask = 0x7f; /* We have 4 ports per PCI function */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_sx4.c linux-2.4.28-pre3/drivers/scsi/sata_sx4.c --- linux-2.4.27/drivers/scsi/sata_sx4.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/sata_sx4.c 2004-09-10 19:34:46.000000000 +0000 @@ -146,19 +146,15 @@ struct pdc_host_priv { static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static void pdc20621_dma_setup(struct ata_queued_cmd *qc); -static void pdc20621_dma_start(struct ata_queued_cmd *qc); static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static void pdc_eng_timeout(struct ata_port *ap); static void pdc_20621_phy_reset (struct ata_port *ap); static int pdc_port_start(struct ata_port *ap); static void pdc_port_stop(struct ata_port *ap); -static void pdc20621_fill_sg(struct ata_queued_cmd *qc); +static void pdc20621_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc20621_host_stop(struct ata_host_set *host_set); -static inline void pdc_dma_complete (struct ata_port *ap, - struct ata_queued_cmd *qc, int have_err); static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe); static int pdc20621_detect_dimm(struct ata_probe_ent *pe); static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, @@ -171,6 +167,8 @@ static void pdc20621_get_from_dimm(struc #endif static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, u32 offset, u32 size); +static void pdc20621_irq_clear(struct ata_port *ap); +static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); static Scsi_Host_Template pdc_sata_sht = { @@ -178,6 +176,7 @@ static Scsi_Host_Template pdc_sata_sht = .name = DRV_NAME, .detect = ata_scsi_detect, .release = ata_scsi_release, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -199,11 +198,11 @@ static struct ata_port_operations pdc_20 .check_status = ata_check_status_mmio, .exec_command = pdc_exec_command_mmio, .phy_reset = pdc_20621_phy_reset, - .bmdma_setup = pdc20621_dma_setup, - .bmdma_start = pdc20621_dma_start, - .fill_sg = pdc20621_fill_sg, + .qc_prep = pdc20621_qc_prep, + .qc_issue = pdc20621_qc_issue_prot, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc20621_interrupt, + .irq_clear = pdc20621_irq_clear, .port_start = pdc_port_start, .port_stop = pdc_port_stop, .host_stop = pdc20621_host_stop, @@ -215,7 +214,8 @@ static struct ata_port_info pdc_port_inf .sht = &pdc_sata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO, - .pio_mask = 0x03, /* pio3-4 */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_20621_ops, }, @@ -375,7 +375,10 @@ static inline unsigned int pdc20621_ata_ /* dimm dma S/G, and next-pkt */ dw = i >> 2; - buf32[dw] = cpu_to_le32(dimm_sg); + if (tf->protocol == ATA_PROT_NODATA) + buf32[dw] = 0; + else + buf32[dw] = cpu_to_le32(dimm_sg); buf32[dw + 1] = 0; i += 8; @@ -435,7 +438,7 @@ static inline void pdc20621_host_pkt(str buf32[dw + 3]); } -static void pdc20621_fill_sg(struct ata_queued_cmd *qc) +static void pdc20621_dma_prep(struct ata_queued_cmd *qc) { struct scatterlist *sg = qc->sg; struct ata_port *ap = qc->ap; @@ -447,6 +450,8 @@ static void pdc20621_fill_sg(struct ata_ unsigned int i, last, idx, total_len = 0, sgt_len; u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; + assert(qc->flags & ATA_QCFLAG_DMAMAP); + VPRINTK("ata%u: ENTER\n", ap->id); /* hard-code chip #0 */ @@ -496,6 +501,56 @@ static void pdc20621_fill_sg(struct ata_ VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len); } +static void pdc20621_nodata_prep(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct pdc_port_priv *pp = ap->private_data; + void *mmio = ap->host_set->mmio_base; + struct pdc_host_priv *hpriv = ap->host_set->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + unsigned int portno = ap->port_no; + unsigned int i; + + VPRINTK("ata%u: ENTER\n", ap->id); + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno); + + if (qc->tf.flags & ATA_TFLAG_LBA48) + i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i); + else + i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i); + + pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i); + + /* copy three S/G tables and two packets to DIMM MMIO window */ + memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP), + &pp->dimm_buf, PDC_DIMM_HEADER_SZ); + + /* force host FIFO dump */ + writel(0x00000001, mmio + PDC_20621_GENERAL_CTL); + + readl(dimm_mmio); /* MMIO PCI posting flush */ + + VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len); +} + +static void pdc20621_qc_prep(struct ata_queued_cmd *qc) +{ + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + pdc20621_dma_prep(qc); + break; + case ATA_PROT_NODATA: + pdc20621_nodata_prep(qc); + break; + default: + break; + } +} + static void __pdc20621_push_hdma(struct ata_queued_cmd *qc, unsigned int seq, u32 pkt_ofs) @@ -571,13 +626,7 @@ static void pdc20621_dump_hdma(struct at static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { } #endif /* ATA_VERBOSE_DEBUG */ -static void pdc20621_dma_setup(struct ata_queued_cmd *qc) -{ - /* nothing for now. later, we will call standard - * code in libata-core for ATAPI here */ -} - -static void pdc20621_dma_start(struct ata_queued_cmd *qc) +static void pdc20621_packet_start(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct ata_host_set *host_set = ap->host_set; @@ -585,24 +634,21 @@ static void pdc20621_dma_start(struct at void *mmio = host_set->mmio_base; unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); u8 seq = (u8) (port_no + 1); - unsigned int doing_hdma = 0, port_ofs; + unsigned int port_ofs; /* hard-code chip #0 */ mmio += PDC_CHIP0_OFS; VPRINTK("ata%u: ENTER\n", ap->id); + wmb(); /* flush PRD, pkt writes */ + port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no); /* if writing, we (1) DMA to DIMM, then (2) do ATA command */ - if (rw) { - doing_hdma = 1; + if (rw && qc->tf.protocol == ATA_PROT_DMA) { seq += 4; - } - wmb(); /* flush PRD, pkt writes */ - - if (doing_hdma) { pdc20621_dump_hdma(qc); pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT); VPRINTK("queued ofs 0x%x (%u), seq %u\n", @@ -623,6 +669,25 @@ static void pdc20621_dma_start(struct at } } +static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc) +{ + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + case ATA_PROT_NODATA: + pdc20621_packet_start(qc); + return 0; + + case ATA_PROT_ATAPI_DMA: + BUG(); + break; + + default: + break; + } + + return ata_qc_issue_prot(qc); +} + static inline unsigned int pdc20621_host_intr( struct ata_port *ap, struct ata_queued_cmd *qc, unsigned int doing_hdma, @@ -643,7 +708,8 @@ static inline unsigned int pdc20621_host if (doing_hdma) { VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id, readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - pdc_dma_complete(ap, qc, 0); + /* get drive status; clear intr; complete txn */ + ata_qc_complete(qc, ata_wait_idle(ap)); pdc20621_pop_hdma(qc); } @@ -680,7 +746,8 @@ static inline unsigned int pdc20621_host else { VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id, readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - pdc_dma_complete(ap, qc, 0); + /* get drive status; clear intr; complete txn */ + ata_qc_complete(qc, ata_wait_idle(ap)); pdc20621_pop_hdma(qc); } handled = 1; @@ -700,6 +767,16 @@ static inline unsigned int pdc20621_host return handled; } +static void pdc20621_irq_clear(struct ata_port *ap) +{ + struct ata_host_set *host_set = ap->host_set; + void *mmio = host_set->mmio_base; + + mmio += PDC_CHIP0_OFS; + + readl(mmio + PDC_20621_SEQMASK); +} + static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; @@ -764,16 +841,6 @@ static irqreturn_t pdc20621_interrupt (i return IRQ_RETVAL(handled); } -static inline void pdc_dma_complete (struct ata_port *ap, - struct ata_queued_cmd *qc, - int have_err) -{ - u8 err_bit = have_err ? ATA_ERR : 0; - - /* get drive status; clear intr; complete txn */ - ata_qc_complete(qc, ata_wait_idle(ap) | err_bit); -} - static void pdc_eng_timeout(struct ata_port *ap) { u8 drv_stat; @@ -798,17 +865,9 @@ static void pdc_eng_timeout(struct ata_p switch (qc->tf.protocol) { case ATA_PROT_DMA: - printk(KERN_ERR "ata%u: DMA timeout\n", ap->id); - ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR); - break; - case ATA_PROT_NODATA: - drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); - - ata_qc_complete(qc, drv_stat); + printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR); break; default: @@ -827,15 +886,17 @@ out: static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) { - if (tf->protocol != ATA_PROT_DMA) - ata_tf_load_mmio(ap, tf); + WARN_ON (tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); + ata_tf_load_mmio(ap, tf); } static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) { - if (tf->protocol != ATA_PROT_DMA) - ata_exec_command_mmio(ap, tf); + WARN_ON (tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); + ata_exec_command_mmio(ap, tf); } @@ -1366,6 +1427,7 @@ static int pdc_sata_init_one (struct pci probe_ent->sht = pdc_port_info[board_idx].sht; probe_ent->host_flags = pdc_port_info[board_idx].host_flags; probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; + probe_ent->mwdma_mask = pdc_port_info[board_idx].mwdma_mask; probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask; probe_ent->port_ops = pdc_port_info[board_idx].port_ops; @@ -1376,21 +1438,11 @@ static int pdc_sata_init_one (struct pci probe_ent->private_data = hpriv; base += PDC_CHIP0_OFS; + probe_ent->n_ports = 4; pdc_sata_setup_port(&probe_ent->port[0], base + 0x200); pdc_sata_setup_port(&probe_ent->port[1], base + 0x280); - - /* notice 4-port boards */ - switch (board_idx) { - case board_20621: - probe_ent->n_ports = 4; - - pdc_sata_setup_port(&probe_ent->port[2], base + 0x300); - pdc_sata_setup_port(&probe_ent->port[3], base + 0x380); - break; - default: - BUG(); - break; - } + pdc_sata_setup_port(&probe_ent->port[2], base + 0x300); + pdc_sata_setup_port(&probe_ent->port[3], base + 0x380); pci_set_master(pdev); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_via.c linux-2.4.28-pre3/drivers/scsi/sata_via.c --- linux-2.4.27/drivers/scsi/sata_via.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/sata_via.c 2004-09-10 19:36:58.000000000 +0000 @@ -83,6 +83,7 @@ static Scsi_Host_Template svia_sht = { .name = DRV_NAME, .detect = ata_scsi_detect, .release = ata_scsi_release, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -109,10 +110,13 @@ static struct ata_port_operations svia_s .bmdma_setup = ata_bmdma_setup_pio, .bmdma_start = ata_bmdma_start_pio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, .scr_read = svia_scr_read, .scr_write = svia_scr_write, @@ -209,6 +213,7 @@ static int svia_init_one (struct pci_dev probe_ent->irq = pdev->irq; probe_ent->irq_flags = SA_SHIRQ; probe_ent->pio_mask = 0x1f; + probe_ent->mwdma_mask = 0x07; probe_ent->udma_mask = 0x7f; probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_vsc.c linux-2.4.28-pre3/drivers/scsi/sata_vsc.c --- linux-2.4.27/drivers/scsi/sata_vsc.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/sata_vsc.c 2004-09-10 19:35:22.000000000 +0000 @@ -192,6 +192,7 @@ static Scsi_Host_Template vsc_sata_sht = .name = DRV_NAME, .detect = ata_scsi_detect, .release = ata_scsi_release, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -216,9 +217,11 @@ static struct ata_port_operations vsc_sa .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup_mmio, .bmdma_start = ata_bmdma_start_mmio, - .fill_sg = ata_fill_sg, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, .irq_handler = vsc_sata_interrupt, + .irq_clear = ata_bmdma_irq_clear, .scr_read = vsc_sata_scr_read, .scr_write = vsc_sata_scr_write, .port_start = ata_port_start, @@ -316,6 +319,7 @@ static int __devinit vsc_sata_init_one ( * if we don't fill these */ probe_ent->pio_mask = 0x1f; + probe_ent->mwdma_mask = 0x07; probe_ent->udma_mask = 0x7f; /* We have 4 ports per PCI function */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/scsi_debug.c linux-2.4.28-pre3/drivers/scsi/scsi_debug.c --- linux-2.4.27/drivers/scsi/scsi_debug.c 2002-11-28 23:53:14.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/scsi_debug.c 2004-09-10 19:35:30.000000000 +0000 @@ -48,7 +48,7 @@ #include "scsi_debug.h" -static const char * scsi_debug_version_str = "Version: 0.61 (20020815)"; +static const char * scsi_debug_version_str = "Version: 0.63 (20040831)"; #ifndef SCSI_CMD_READ_16 @@ -73,7 +73,7 @@ static const char * scsi_debug_version_s #define SCSI_DEBUG_OPT_MEDIUM_ERR 2 #define SCSI_DEBUG_OPT_EVERY_NTH 4 -#define OPT_MEDIUM_ERR_ADDR 0x1234 +#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's 4660 in decimal */ static int scsi_debug_num_devs = DEF_NR_FAKE_DEVS; static int scsi_debug_opts = DEF_OPTS; @@ -124,7 +124,7 @@ static struct sdebug_queued_cmd queued_a static unsigned char * fake_storep; /* ramdisk storage */ -static unsigned char broken_buff[SDEBUG_SENSE_LEN]; +static unsigned char spare_buff[SDEBUG_SENSE_LEN]; static int num_aborts = 0; static int num_dev_resets = 0; @@ -193,8 +193,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * else buff = (unsigned char *) SCpnt->request_buffer; if (NULL == buff) { - printk(KERN_WARNING "scsi_debug:qc: buff was NULL??\n"); - buff = broken_buff; /* just point at dummy */ + buff = spare_buff; /* just point at dummy */ bufflen = SDEBUG_SENSE_LEN; } @@ -370,7 +369,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * if ((errsts = check_reset(SCpnt, devip))) break; mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14); - errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); + errsts = (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); break; } return schedule_resp(SCpnt, devip, done, errsts, scsi_debug_delay); @@ -390,7 +389,7 @@ static int check_reset(Scsi_Cmnd * SCpnt if (devip->reset) { devip->reset = 0; mk_sense_buffer(devip, UNIT_ATTENTION, 0x29, 0, 14); - return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); + return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); } return 0; } @@ -451,7 +450,7 @@ static int resp_inquiry(unsigned char * arr[0] = pq_pdt; if (0x2 & cmd[1]) { /* CMDDT bit set */ mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); - return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); + return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); } else if (0x1 & cmd[1]) { /* EVPD bit set */ int dev_id_num, len; char dev_id_str[6]; @@ -476,7 +475,7 @@ static int resp_inquiry(unsigned char * } else { /* Illegal request, invalid field in cdb */ mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); - return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); + return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); } memcpy(buff, arr, min_len); return 0; @@ -589,7 +588,7 @@ static int resp_mode_sense(unsigned char memset(arr, 0, SDEBUG_MAX_MSENSE_SZ); if (0x3 == pcontrol) { /* Saving values not supported */ mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x39, 0, 14); - return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); + return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); } dev_spec = DEV_READONLY(target) ? 0x80 : 0x0; if (msense_6) { @@ -631,7 +630,7 @@ static int resp_mode_sense(unsigned char break; default: mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); - return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); + return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); } if (msense_6) arr[0] = offset - 1; @@ -655,14 +654,14 @@ static int resp_read(Scsi_Cmnd * SCpnt, if (upper_blk || (block + num > CAPACITY)) { mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); - return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); + return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); } if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && - (block >= OPT_MEDIUM_ERR_ADDR) && - (block < (OPT_MEDIUM_ERR_ADDR + num))) { + (block <= OPT_MEDIUM_ERR_ADDR) && + ((block + num) > OPT_MEDIUM_ERR_ADDR)) { mk_sense_buffer(devip, MEDIUM_ERROR, 0x11, 0, 14); /* claim unrecoverable read error */ - return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); + return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); } read_lock_irqsave(&atomic_rw, iflags); sgcount = 0; @@ -704,7 +703,7 @@ static int resp_write(Scsi_Cmnd * SCpnt, if (upper_blk || (block + num > CAPACITY)) { mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); - return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); + return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); } write_lock_irqsave(&atomic_rw, iflags); @@ -744,7 +743,7 @@ static int resp_report_luns(unsigned cha alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); if ((alloc_len < 16) || (select_report > 2)) { mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); - return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1); + return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); } if (bufflen > 3) { memset(buff, 0, bufflen); @@ -773,8 +772,10 @@ static void timer_intr_handler(unsigned return; } sqcp->in_use = 0; - if (sqcp->done_funct) + if (sqcp->done_funct) { + sqcp->a_cmnd->result = sqcp->scsi_result; sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */ + } sqcp->done_funct = NULL; spin_unlock_irqrestore(&queued_arr_lock, iflags); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/scsi_error.c linux-2.4.28-pre3/drivers/scsi/scsi_error.c --- linux-2.4.27/drivers/scsi/scsi_error.c 2004-04-14 13:05:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/scsi_error.c 2004-09-10 19:31:58.000000000 +0000 @@ -664,7 +664,10 @@ STATIC void scsi_send_eh_cmnd(Scsi_Cmnd SCpnt->eh_state = SUCCESS; break; case NEEDS_RETRY: - goto retry; + if ((++SCpnt->retries) < SCpnt->allowed) + goto retry; + SCpnt->eh_state = SUCCESS; + break; case FAILED: default: SCpnt->eh_state = FAILED; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/scsi_merge.c linux-2.4.28-pre3/drivers/scsi/scsi_merge.c --- linux-2.4.27/drivers/scsi/scsi_merge.c 2002-11-28 23:53:14.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/scsi_merge.c 2004-09-10 19:36:55.000000000 +0000 @@ -418,7 +418,7 @@ __inline static int __scsi_back_merge_fn return 0; if (!BH_PHYS_4G(req->bhtail, bh)) - return 0; + goto new_end_segment; if (use_clustering) { /* @@ -477,7 +477,7 @@ __inline static int __scsi_front_merge_f return 0; if (!BH_PHYS_4G(bh, req->bh)) - return 0; + goto new_start_segment; if (use_clustering) { /* @@ -640,7 +640,7 @@ __inline static int __scsi_merge_request return 0; if (!BH_PHYS_4G(req->bhtail, next->bh)) - return 0; + goto dont_combine; /* * The main question is whether the two segments at the boundaries diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/scsi_scan.c linux-2.4.28-pre3/drivers/scsi/scsi_scan.c --- linux-2.4.27/drivers/scsi/scsi_scan.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/scsi_scan.c 2004-09-10 19:36:19.000000000 +0000 @@ -157,6 +157,7 @@ static struct dev_info device_list[] = {"TOSHIBA","CDROM","*", BLIST_ISROM}, {"TOSHIBA","CD-ROM","*", BLIST_ISROM}, {"MegaRAID", "LD", "*", BLIST_FORCELUN}, + {"3PARdata", "VV", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // 3PARdata InServ Virtual Volume {"DGC", "RAID", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // Dell PV 650F (tgt @ LUN 0) {"DGC", "DISK", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // Dell PV 650F (no tgt @ LUN 0) {"DELL", "PV660F", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, @@ -189,6 +190,7 @@ static struct dev_info device_list[] = {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"IOI", "Media Bay", "*", BLIST_FORCELUN}, {"HITACHI", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HITACHI XP Arrays */ {"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HITACHI 9960 */ {"WINSYS","FLASHDISK G6", "*", BLIST_SPARSELUN}, @@ -208,6 +210,7 @@ static struct dev_info device_list[] = {"SMSC", "USB 2 HS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"NEC", "iStorage", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN}, + {"Xyratex", "4200", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* * Must be at end of list... diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/scsiiom.c linux-2.4.28-pre3/drivers/scsi/scsiiom.c --- linux-2.4.27/drivers/scsi/scsiiom.c 2000-12-31 19:06:00.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/scsiiom.c 2004-09-10 19:32:17.000000000 +0000 @@ -211,6 +211,24 @@ dc390_dma_intr (PACB pACB) }; #endif +static void __inline__ +dc390_InvalidCmd( PACB pACB ) +{ + if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) ) + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); +} + +#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD) + +/* abort command */ +static void __inline__ +dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB ) +{ + pSRB->MsgOutBuf[0] = ABORT; + pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; + pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_; +} + void __inline__ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs) { @@ -569,8 +587,6 @@ dc390_printMsg (UCHAR *MsgBuf, UCHAR len }; #endif -#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD) - /* reject_msg */ static void __inline__ dc390_MsgIn_reject (PACB pACB, PSRB pSRB) @@ -580,15 +596,6 @@ dc390_MsgIn_reject (PACB pACB, PSRB pSRB DEBUG0 (printk (KERN_INFO "DC390: Reject message\n");) } -/* abort command */ -static void __inline__ -dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB ) -{ - pSRB->MsgOutBuf[0] = ABORT; - pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; - pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_; -} - static PSRB dc390_MsgIn_QTag (PACB pACB, PDCB pDCB, UCHAR tag) { @@ -1355,6 +1362,47 @@ dc390_add_dev (PACB pACB, PDCB pDCB, PSC }; +static void __inline__ +dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + PSCSICMD pcmd; + + REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\ + pSRB->pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN);) + + pSRB->SRBFlag |= AUTO_REQSENSE; + //pSRB->Segment0[0] = (UINT) pSRB->CmdBlock[0]; + //pSRB->Segment0[1] = (UINT) pSRB->CmdBlock[4]; + //pSRB->Segment1[0] = ((UINT)(pSRB->pcmd->cmd_len) << 8) + pSRB->SGcount; + //pSRB->Segment1[1] = pSRB->TotalXferredLen; + pSRB->SavedSGCount = pSRB->SGcount; + pSRB->SavedTotXLen = pSRB->TotalXferredLen; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */ + + pcmd = pSRB->pcmd; + + pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer); + pSRB->Segmentx.length = sizeof(pcmd->sense_buffer); + pSRB->pSegmentList = &pSRB->Segmentx; + pSRB->SGcount = 1; + pSRB->SGIndex = 0; + + //pSRB->CmdBlock[0] = REQUEST_SENSE; + //pSRB->CmdBlock[1] = pDCB->TargetLUN << 5; + //(USHORT) pSRB->CmdBlock[2] = 0; + //(USHORT) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer); + //pSRB->ScsiCmdLen = 6; + + pSRB->TotalXferredLen = 0; + pSRB->SGToBeXferLen = 0; + if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) { + dc390_Going_to_Waiting ( pDCB, pSRB ); + dc390_waiting_timer (pACB, HZ/5); + } +} + + void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ) { @@ -1738,53 +1786,3 @@ dc390_ScsiRstDetect( PACB pACB ) return; } - -static void __inline__ -dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ) -{ - PSCSICMD pcmd; - - REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\ - pSRB->pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN);) - - pSRB->SRBFlag |= AUTO_REQSENSE; - //pSRB->Segment0[0] = (UINT) pSRB->CmdBlock[0]; - //pSRB->Segment0[1] = (UINT) pSRB->CmdBlock[4]; - //pSRB->Segment1[0] = ((UINT)(pSRB->pcmd->cmd_len) << 8) + pSRB->SGcount; - //pSRB->Segment1[1] = pSRB->TotalXferredLen; - pSRB->SavedSGCount = pSRB->SGcount; - pSRB->SavedTotXLen = pSRB->TotalXferredLen; - pSRB->AdaptStatus = 0; - pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */ - - pcmd = pSRB->pcmd; - - pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer); - pSRB->Segmentx.length = sizeof(pcmd->sense_buffer); - pSRB->pSegmentList = &pSRB->Segmentx; - pSRB->SGcount = 1; - pSRB->SGIndex = 0; - - //pSRB->CmdBlock[0] = REQUEST_SENSE; - //pSRB->CmdBlock[1] = pDCB->TargetLUN << 5; - //(USHORT) pSRB->CmdBlock[2] = 0; - //(USHORT) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer); - //pSRB->ScsiCmdLen = 6; - - pSRB->TotalXferredLen = 0; - pSRB->SGToBeXferLen = 0; - if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) { - dc390_Going_to_Waiting ( pDCB, pSRB ); - dc390_waiting_timer (pACB, HZ/5); - } -} - - - -static void __inline__ -dc390_InvalidCmd( PACB pACB ) -{ - if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) ) - DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); -} - diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/seagate.c linux-2.4.28-pre3/drivers/scsi/seagate.c --- linux-2.4.27/drivers/scsi/seagate.c 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/seagate.c 2004-09-10 19:34:33.000000000 +0000 @@ -698,7 +698,7 @@ int seagate_st0x_queue_command (Scsi_Cmn done_fn = done; current_target = SCpnt->target; current_lun = SCpnt->lun; - (const void *) current_cmnd = SCpnt->cmnd; + current_cmnd = SCpnt->cmnd; current_data = (unsigned char *) SCpnt->request_buffer; current_bufflen = SCpnt->request_bufflen; SCint = SCpnt; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sg.c linux-2.4.28-pre3/drivers/scsi/sg.c --- linux-2.4.27/drivers/scsi/sg.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/sg.c 2004-09-10 19:34:39.000000000 +0000 @@ -742,6 +742,16 @@ static int sg_common_write(Sg_fd * sfp, return 0; } +static inline unsigned sg_jif_to_ms(int jifs) +{ + if (jifs <= 0) + return 0U; + else { + unsigned int j = (unsigned int)jifs; + return (j < (UINT_MAX / 1000)) ? ((j * 1000) / HZ) : ((j / HZ) * 1000); + } +} + static int sg_ioctl(struct inode * inode, struct file * filp, unsigned int cmd_in, unsigned long arg) { @@ -1640,6 +1650,24 @@ static int sg_build_sgat(Sg_scatter_hold return mx_sc_elems; /* number of scat_gath elements allocated */ } +static inline int sg_alloc_kiovec(int nr, struct kiobuf **bufp, int *szp) +{ +#if SG_NEW_KIOVEC + return alloc_kiovec_sz(nr, bufp, szp); +#else + return alloc_kiovec(nr, bufp); +#endif +} + +static inline void sg_free_kiovec(int nr, struct kiobuf **bufp, int *szp) +{ +#if SG_NEW_KIOVEC + free_kiovec_sz(nr, bufp, szp); +#else + free_kiovec(nr, bufp); +#endif +} + static void sg_unmap_and(Sg_scatter_hold * schp, int free_also) { #ifdef SG_ALLOW_DIO_CODE @@ -2568,15 +2596,6 @@ static char * sg_malloc(const Sg_fd * sf return resp; } -static inline int sg_alloc_kiovec(int nr, struct kiobuf **bufp, int *szp) -{ -#if SG_NEW_KIOVEC - return alloc_kiovec_sz(nr, bufp, szp); -#else - return alloc_kiovec(nr, bufp); -#endif -} - static void sg_low_free(char * buff, int size, int mem_src) { if (! buff) return; @@ -2620,15 +2639,6 @@ static void sg_free(char * buff, int siz sg_low_free(buff, size, mem_src); } -static inline void sg_free_kiovec(int nr, struct kiobuf **bufp, int *szp) -{ -#if SG_NEW_KIOVEC - free_kiovec_sz(nr, bufp, szp); -#else - free_kiovec(nr, bufp); -#endif -} - static int sg_ms_to_jif(unsigned int msecs) { if ((UINT_MAX / 2U) < msecs) @@ -2638,16 +2648,6 @@ static int sg_ms_to_jif(unsigned int mse : (((int)msecs / 1000) * HZ); } -static inline unsigned sg_jif_to_ms(int jifs) -{ - if (jifs <= 0) - return 0U; - else { - unsigned int j = (unsigned int)jifs; - return (j < (UINT_MAX / 1000)) ? ((j * 1000) / HZ) : ((j / HZ) * 1000); - } -} - static unsigned char allow_ops[] = {TEST_UNIT_READY, REQUEST_SENSE, INQUIRY, READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12, MODE_SENSE, MODE_SENSE_10, LOG_SENSE}; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sim710.c linux-2.4.28-pre3/drivers/scsi/sim710.c --- linux-2.4.27/drivers/scsi/sim710.c 2002-08-03 00:39:44.000000000 +0000 +++ linux-2.4.28-pre3/drivers/scsi/sim710.c 2004-09-10 19:36:28.000000000 +0000 @@ -921,172 +921,6 @@ handle_script_int(struct Scsi_Host * hos } -/* A quick wrapper for sim710_intr_handle to grab the spin lock */ - -static void -do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - sim710_intr_handle(irq, dev_id, regs); - spin_unlock_irqrestore(&io_request_lock, flags); -} - - -/* A "high" level interrupt handler */ - -static void -sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs) -{ - struct Scsi_Host * host = (struct Scsi_Host *)dev_id; - struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0]; - Scsi_Cmnd * cmd; - unsigned char istat, dstat; - unsigned char sstat0; - u32 scratch, dsps, resume_offset = 0; - - istat = NCR_read8(ISTAT_REG); - if (!(istat & (ISTAT_SIP|ISTAT_DIP))) - return; - else { - sim710_intrs++; - dsps = NCR_read32(DSPS_REG); - hostdata->state = STATE_HALTED; - sstat0 = dstat = 0; - scratch = NCR_read32(SCRATCH_REG); - if (istat & ISTAT_SIP) { - sstat0 = NCR_read8(SSTAT0_REG); - } - if (istat & ISTAT_DIP) { - udelay(10); /* Some comment somewhere about 10cycles - * between accesses to sstat0 and dstat ??? */ - dstat = NCR_read8(DSTAT_REG); - } - DEB(DEB_INTS, printk("scsi%d: Int %d, istat %02x, sstat0 %02x " - "dstat %02x, dsp [%04x], scratch %02x\n", - host->host_no, sim710_intrs, istat, sstat0, dstat, - (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script, - scratch)); - if (scratch & 0x100) { - u8 *p = hostdata->msgin_buf; - - DEB(DEB_INTS, printk(" msgin_buf: %02x %02x %02x %02x\n", - p[0], p[1], p[2], p[3])); - } - if ((dstat & DSTAT_SIR) && dsps == A_int_reselected) { - /* Reselected. Identify the target from LCRC_REG, and - * update current command. If we were trying to select - * a device, then that command needs to go back on the - * issue_queue for later. - */ - unsigned char lcrc = NCR_read8(LCRC_REG_10); - int id = 0; - - if (!(lcrc & 0x7f)) { - printk("scsi%d: Reselected with LCRC = %02x\n", - host->host_no, lcrc); - cmd = NULL; - } - else { - while (!(lcrc & 1)) { - id++; - lcrc >>= 1; - } - DEB(DEB_DISC, printk("scsi%d: Reselected by ID %d\n", - host->host_no, id)); - if (hostdata->running) { - /* Clear SIGP */ - (void)NCR_read8(CTEST2_REG_700); - - DEB(DEB_DISC, printk("scsi%d: Select of %d interrupted " - "by reselect from %d (%p)\n", - host->host_no, hostdata->running->target, - id, hostdata->target[id].cur_cmd)); - cmd = hostdata->running; - hostdata->target[cmd->target].cur_cmd = NULL; - cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue; - hostdata->issue_queue = cmd; - } - cmd = hostdata->running = hostdata->target[id].cur_cmd; - } - } - else - cmd = hostdata->running; - - if (!cmd) { - printk("scsi%d: No active command!\n", host->host_no); - printk("scsi%d: Int %d, istat %02x, sstat0 %02x " - "dstat %02x, dsp [%04x], scratch %02x, dsps %08x\n", - host->host_no, sim710_intrs, istat, sstat0, dstat, - (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script, - NCR_read32(SCRATCH_REG), dsps); - /* resume_offset is zero, which will cause a host reset */ - } - else if (sstat0 & SSTAT0_700_STO) { - DEB(DEB_TOUT, printk("scsi%d: Selection timeout\n", host->host_no)); - cmd->result = DID_NO_CONNECT << 16; - SCSI_DONE(cmd); - hostdata->target[cmd->target].cur_cmd = NULL; - resume_offset = Ent_reselect; - } - else if (sstat0 & (SSTAT0_SGE|SSTAT0_UDC|SSTAT0_RST|SSTAT0_PAR)) { - printk("scsi%d: Serious error, sstat0 = %02x\n", host->host_no, - sstat0); - sim710_errors++; - /* resume_offset is zero, which will cause a host reset */ - } - else if (dstat & (DSTAT_BF|DSTAT_ABRT|DSTAT_SSI|DSTAT_WTD)) { - printk("scsi%d: Serious error, dstat = %02x\n", host->host_no, - dstat); - sim710_errors++; - /* resume_offset is zero, which will cause a host reset */ - } - else if (dstat & DSTAT_SIR) - resume_offset = handle_script_int(host, cmd); - else if (sstat0 & SSTAT0_MA) - resume_offset = handle_phase_mismatch(host, cmd); - else if (dstat & DSTAT_IID) { - /* This can be due to a quick reselect while doing a WAIT - * DISCONNECT. - */ - resume_offset = handle_idd(host, cmd); - } - else { - sim710_errors++; - printk("scsi%d: Spurious interrupt!\n", host->host_no); - /* resume_offset is zero, which will cause a host reset */ - } - } - - if (resume_offset) { - if (resume_offset == Ent_reselect) { - hostdata->running = NULL; - hostdata->state = STATE_IDLE; - } - else - hostdata->state = STATE_BUSY; - DEB(DEB_RESUME, printk("scsi%d: Resuming at script[0x%x]\n", - host->host_no, resume_offset/4)); -#ifdef DEBUG_LIMIT_INTS - if (sim710_intrs < DEBUG_LIMIT_INTS) -#endif - { - NCR_write32(SCRATCH_REG, 0); - NCR_write32(DSP_REG, virt_to_bus(hostdata->script+resume_offset/4)); - } - if (resume_offset == Ent_reselect) - run_process_issue_queue(hostdata); - } - else { - printk("scsi%d: Failed to handle interrupt. Failing commands " - "and resetting SCSI bus and chip\n", host->host_no); - mdelay(1000); /* Give chance to read screen!! */ - full_reset(host); - } -} - - static void run_command (struct sim710_hostdata *hostdata, Scsi_Cmnd *cmd) { @@ -1284,6 +1118,172 @@ process_issue_queue (struct sim710_hostd } +/* A quick wrapper for sim710_intr_handle to grab the spin lock */ + +static void +do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + sim710_intr_handle(irq, dev_id, regs); + spin_unlock_irqrestore(&io_request_lock, flags); +} + + +/* A "high" level interrupt handler */ + +static void +sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs) +{ + struct Scsi_Host * host = (struct Scsi_Host *)dev_id; + struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0]; + Scsi_Cmnd * cmd; + unsigned char istat, dstat; + unsigned char sstat0; + u32 scratch, dsps, resume_offset = 0; + + istat = NCR_read8(ISTAT_REG); + if (!(istat & (ISTAT_SIP|ISTAT_DIP))) + return; + else { + sim710_intrs++; + dsps = NCR_read32(DSPS_REG); + hostdata->state = STATE_HALTED; + sstat0 = dstat = 0; + scratch = NCR_read32(SCRATCH_REG); + if (istat & ISTAT_SIP) { + sstat0 = NCR_read8(SSTAT0_REG); + } + if (istat & ISTAT_DIP) { + udelay(10); /* Some comment somewhere about 10cycles + * between accesses to sstat0 and dstat ??? */ + dstat = NCR_read8(DSTAT_REG); + } + DEB(DEB_INTS, printk("scsi%d: Int %d, istat %02x, sstat0 %02x " + "dstat %02x, dsp [%04x], scratch %02x\n", + host->host_no, sim710_intrs, istat, sstat0, dstat, + (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script, + scratch)); + if (scratch & 0x100) { + u8 *p = hostdata->msgin_buf; + + DEB(DEB_INTS, printk(" msgin_buf: %02x %02x %02x %02x\n", + p[0], p[1], p[2], p[3])); + } + if ((dstat & DSTAT_SIR) && dsps == A_int_reselected) { + /* Reselected. Identify the target from LCRC_REG, and + * update current command. If we were trying to select + * a device, then that command needs to go back on the + * issue_queue for later. + */ + unsigned char lcrc = NCR_read8(LCRC_REG_10); + int id = 0; + + if (!(lcrc & 0x7f)) { + printk("scsi%d: Reselected with LCRC = %02x\n", + host->host_no, lcrc); + cmd = NULL; + } + else { + while (!(lcrc & 1)) { + id++; + lcrc >>= 1; + } + DEB(DEB_DISC, printk("scsi%d: Reselected by ID %d\n", + host->host_no, id)); + if (hostdata->running) { + /* Clear SIGP */ + (void)NCR_read8(CTEST2_REG_700); + + DEB(DEB_DISC, printk("scsi%d: Select of %d interrupted " + "by reselect from %d (%p)\n", + host->host_no, hostdata->running->target, + id, hostdata->target[id].cur_cmd)); + cmd = hostdata->running; + hostdata->target[cmd->target].cur_cmd = NULL; + cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue; + hostdata->issue_queue = cmd; + } + cmd = hostdata->running = hostdata->target[id].cur_cmd; + } + } + else + cmd = hostdata->running; + + if (!cmd) { + printk("scsi%d: No active command!\n", host->host_no); + printk("scsi%d: Int %d, istat %02x, sstat0 %02x " + "dstat %02x, dsp [%04x], scratch %02x, dsps %08x\n", + host->host_no, sim710_intrs, istat, sstat0, dstat, + (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script, + NCR_read32(SCRATCH_REG), dsps); + /* resume_offset is zero, which will cause a host reset */ + } + else if (sstat0 & SSTAT0_700_STO) { + DEB(DEB_TOUT, printk("scsi%d: Selection timeout\n", host->host_no)); + cmd->result = DID_NO_CONNECT << 16; + SCSI_DONE(cmd); + hostdata->target[cmd->target].cur_cmd = NULL; + resume_offset = Ent_reselect; + } + else if (sstat0 & (SSTAT0_SGE|SSTAT0_UDC|SSTAT0_RST|SSTAT0_PAR)) { + printk("scsi%d: Serious error, sstat0 = %02x\n", host->host_no, + sstat0); + sim710_errors++; + /* resume_offset is zero, which will cause a host reset */ + } + else if (dstat & (DSTAT_BF|DSTAT_ABRT|DSTAT_SSI|DSTAT_WTD)) { + printk("scsi%d: Serious error, dstat = %02x\n", host->host_no, + dstat); + sim710_errors++; + /* resume_offset is zero, which will cause a host reset */ + } + else if (dstat & DSTAT_SIR) + resume_offset = handle_script_int(host, cmd); + else if (sstat0 & SSTAT0_MA) + resume_offset = handle_phase_mismatch(host, cmd); + else if (dstat & DSTAT_IID) { + /* This can be due to a quick reselect while doing a WAIT + * DISCONNECT. + */ + resume_offset = handle_idd(host, cmd); + } + else { + sim710_errors++; + printk("scsi%d: Spurious interrupt!\n", host->host_no); + /* resume_offset is zero, which will cause a host reset */ + } + } + + if (resume_offset) { + if (resume_offset == Ent_reselect) { + hostdata->running = NULL; + hostdata->state = STATE_IDLE; + } + else + hostdata->state = STATE_BUSY; + DEB(DEB_RESUME, printk("scsi%d: Resuming at script[0x%x]\n", + host->host_no, resume_offset/4)); +#ifdef DEBUG_LIMIT_INTS + if (sim710_intrs < DEBUG_LIMIT_INTS) +#endif + { + NCR_write32(SCRATCH_REG, 0); + NCR_write32(DSP_REG, virt_to_bus(hostdata->script+resume_offset/4)); + } + if (resume_offset == Ent_reselect) + run_process_issue_queue(hostdata); + } + else { + printk("scsi%d: Failed to handle interrupt. Failing commands " + "and resetting SCSI bus and chip\n", host->host_no); + mdelay(1000); /* Give chance to read screen!! */ + full_reset(host); + } +} + + int sim710_queuecommand(Scsi_Cmnd * cmd, void (*done)(Scsi_Cmnd *)) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/sound/ac97_codec.c linux-2.4.28-pre3/drivers/sound/ac97_codec.c --- linux-2.4.27/drivers/sound/ac97_codec.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/sound/ac97_codec.c 2004-09-10 19:32:44.000000000 +0000 @@ -30,6 +30,9 @@ ************************************************************************** * * History + * Feb 25, 2004 Liam Girdwood + * Added support for codecs that require a warm reset to power up. + * Support for WM9713 * May 02, 2003 Liam Girdwood * Removed non existant WM9700 * Added support for WM9705, WM9708, WM9709, WM9710, WM9711 @@ -71,6 +74,7 @@ static int wolfson_init03(struct ac97_co static int wolfson_init04(struct ac97_codec * codec); static int wolfson_init05(struct ac97_codec * codec); static int wolfson_init11(struct ac97_codec * codec); +static int wolfson_init13(struct ac97_codec * codec); static int tritech_init(struct ac97_codec * codec); static int tritech_maestro_init(struct ac97_codec * codec); static int sigmatel_9708_init(struct ac97_codec *codec); @@ -107,6 +111,7 @@ static struct ac97_ops wolfson_ops03 = { static struct ac97_ops wolfson_ops04 = { wolfson_init04, NULL, NULL }; static struct ac97_ops wolfson_ops05 = { wolfson_init05, NULL, NULL }; static struct ac97_ops wolfson_ops11 = { wolfson_init11, NULL, NULL }; +static struct ac97_ops wolfson_ops13 = { wolfson_init13, NULL, NULL }; static struct ac97_ops tritech_ops = { tritech_init, NULL, NULL }; static struct ac97_ops tritech_m_ops = { tritech_maestro_init, NULL, NULL }; static struct ac97_ops sigmatel_9708_ops = { sigmatel_9708_init, NULL, NULL }; @@ -150,6 +155,7 @@ static const struct { {0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops}, {0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops}, {0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops}, + {0x43585430, "CXT48", &default_ops, AC97_DELUDED_MODEM }, {0x43585442, "CXT66", &default_ops, AC97_DELUDED_MODEM }, {0x44543031, "Diamond Technology DT0893", &default_ops}, {0x45838308, "ESS Allegro ES1988", &null_ops}, @@ -168,6 +174,7 @@ static const struct { {0x574D4C05, "Wolfson WM9705/WM9710", &wolfson_ops05}, {0x574D4C09, "Wolfson WM9709", &null_ops}, {0x574D4C12, "Wolfson WM9711/9712", &wolfson_ops11}, + {0x574D4C13, "Wolfson WM9713", &wolfson_ops13, AC97_DEFAULT_POWER_OFF}, {0x83847600, "SigmaTel STAC????", &null_ops}, {0x83847604, "SigmaTel STAC9701/3/4/5", &null_ops}, {0x83847605, "SigmaTel STAC9704", &null_ops}, @@ -793,6 +800,9 @@ EXPORT_SYMBOL(ac97_release_codec); * Currently codec_wait is used to wait for AC97 codec * reset to complete. * + * Some codecs will power down when a register reset is + * performed. We now check for such codecs. + * * Returns 1 (true) on success, or 0 (false) on failure. */ @@ -805,35 +815,18 @@ int ac97_probe_codec(struct ac97_codec * u16 f; struct list_head *l; struct ac97_driver *d; - - /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should - * be read zero. - * - * FIXME: is the following comment outdated? -jgarzik - * Probing of AC97 in this way is not reliable, it is not even SAFE !! - */ - codec->codec_write(codec, AC97_RESET, 0L); - /* also according to spec, we wait for codec-ready state */ + /* wait for codec-ready state */ if (codec->codec_wait) codec->codec_wait(codec); else udelay(10); - - if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) { - printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n", - (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary") - : (codec->id&1 ? "Secondary": "Primary")); - return 0; - } - - /* probe for Modem Codec */ - codec->modem = ac97_check_modem(codec); - codec->name = NULL; - codec->codec_ops = &default_ops; - + + /* will the codec power down if register reset ? */ id1 = codec->codec_read(codec, AC97_VENDOR_ID1); id2 = codec->codec_read(codec, AC97_VENDOR_ID2); + codec->name = NULL; + codec->codec_ops = &null_ops; for (i = 0; i < ARRAY_SIZE(ac97_codec_ids); i++) { if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) { codec->type = ac97_codec_ids[i].id; @@ -843,11 +836,35 @@ int ac97_probe_codec(struct ac97_codec * break; } } - codec->model = (id1 << 16) | id2; + if ((codec->flags & AC97_DEFAULT_POWER_OFF) == 0) { + /* reset codec and wait for the ready bit before we continue */ + codec->codec_write(codec, AC97_RESET, 0L); + if (codec->codec_wait) + codec->codec_wait(codec); + else + udelay(10); + } + /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should + * be read zero. + * + * FIXME: is the following comment outdated? -jgarzik + * Probing of AC97 in this way is not reliable, it is not even SAFE !! + */ + if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) { + printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n", + (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary") + : (codec->id&1 ? "Secondary": "Primary")); + return 0; + } + + /* probe for Modem Codec */ + codec->modem = ac97_check_modem(codec); + + /* enable SPDIF */ f = codec->codec_read(codec, AC97_EXTENDED_STATUS); - if(f & 4) + if((codec->codec_ops == &null_ops) && (f & 4)) codec->codec_ops = &default_digital_ops; /* A device which thinks its a modem but isnt */ @@ -916,11 +933,6 @@ static int ac97_init_mixer(struct ac97_c codec->recmask_io = ac97_recmask_io; codec->mixer_ioctl = ac97_mixer_ioctl; - /* codec specific initialization for 4-6 channel output or secondary codec stuff */ - if (codec->codec_ops->init != NULL) { - codec->codec_ops->init(codec); - } - /* initialize mixer channel volumes */ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { struct mixer_defaults *md = &mixer_defaults[i]; @@ -930,6 +942,11 @@ static int ac97_init_mixer(struct ac97_c continue; ac97_set_mixer(codec, md->mixer, md->value); } + + /* codec specific initialization for 4-6 channel output or secondary codec stuff */ + if (codec->codec_ops->init != NULL) { + codec->codec_ops->init(codec); + } /* * Volume is MUTE only on this device. We have to initialise @@ -1085,6 +1102,19 @@ static int wolfson_init11(struct ac97_co return 0; } +/* WM9713 */ +static int wolfson_init13(struct ac97_codec * codec) +{ + codec->codec_write(codec, AC97_RECORD_GAIN, 0x00a0); + codec->codec_write(codec, AC97_POWER_CONTROL, 0x0000); + codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0xDA00); + codec->codec_write(codec, AC97_EXTEND_MODEM_STAT, 0x3810); + codec->codec_write(codec, AC97_PHONE_VOL, 0x0808); + codec->codec_write(codec, AC97_PCBEEP_VOL, 0x0808); + + return 0; +} + static int tritech_init(struct ac97_codec * codec) { codec->codec_write(codec, 0x26, 0x0300); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/sound/i810_audio.c linux-2.4.28-pre3/drivers/sound/i810_audio.c --- linux-2.4.27/drivers/sound/i810_audio.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/sound/i810_audio.c 2004-09-10 19:36:12.000000000 +0000 @@ -304,6 +304,14 @@ static struct pci_device_id i810_pci_tbl PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP2S_AUDIO, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_AUDIO, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP04_AUDIO, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768}, {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AUDIO, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/devices.c linux-2.4.28-pre3/drivers/usb/devices.c --- linux-2.4.27/drivers/usb/devices.c 2002-11-28 23:53:14.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/devices.c 2004-09-10 19:34:31.000000000 +0000 @@ -387,22 +387,31 @@ static char *usb_dump_desc(char *start, if (start > end) return start; - + + /* + * Grab device's exclusive_access mutex to prevent its driver or + * devio from using this device while we are accessing it. + */ + down (&dev->exclusive_access); + start = usb_dump_device_descriptor(start, end, &dev->descriptor); if (start > end) - return start; - + goto out; + start = usb_dump_device_strings (start, end, dev); for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { if (start > end) - return start; + goto out; start = usb_dump_config(dev->speed, start, end, dev->config + i, /* active ? */ (dev->config + i) == dev->actconfig); } + +out: + up (&dev->exclusive_access); return start; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/devio.c linux-2.4.28-pre3/drivers/usb/devio.c --- linux-2.4.27/drivers/usb/devio.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/devio.c 2004-09-10 19:34:52.000000000 +0000 @@ -1158,6 +1158,13 @@ static int usbdev_ioctl(struct inode *in up_read(&ps->devsem); return -ENODEV; } + + /* + * grab device's exclusive_access mutex to prevent its driver from + * using this device while it is being accessed by us. + */ + down(&ps->dev->exclusive_access); + switch (cmd) { case USBDEVFS_CONTROL: ret = proc_control(ps, (void *)arg); @@ -1237,6 +1244,7 @@ static int usbdev_ioctl(struct inode *in ret = proc_ioctl(ps, (void *) arg); break; } + up(&ps->dev->exclusive_access); up_read(&ps->devsem); if (ret >= 0) inode->i_atime = CURRENT_TIME; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/gadget/net2280.c linux-2.4.28-pre3/drivers/usb/gadget/net2280.c --- linux-2.4.27/drivers/usb/gadget/net2280.c 2004-04-14 13:05:32.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/gadget/net2280.c 2004-09-10 19:33:30.000000000 +0000 @@ -537,7 +537,10 @@ write_fifo (struct net2280_ep *ep, struc } /* write just one packet at a time */ - count = min (ep->ep.maxpacket, total); + count = ep->ep.maxpacket; + if (count > total) /* min() cannot be used on a bitfield */ + count = total; + VDEBUG (ep->dev, "write %s fifo (IN) %d bytes%s req %p\n", ep->ep.name, count, (count != ep->ep.maxpacket) ? " (short)" : "", @@ -2191,7 +2194,8 @@ static void handle_ep_small (struct net2 unsigned len; len = req->req.length - req->req.actual; - len = min (ep->ep.maxpacket, len); + if (len > ep->ep.maxpacket) + len = ep->ep.maxpacket; req->req.actual += len; /* if we wrote it all, we're usually done */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/hid-core.c linux-2.4.28-pre3/drivers/usb/hid-core.c --- linux-2.4.27/drivers/usb/hid-core.c 2004-04-14 13:05:32.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/hid-core.c 2004-09-10 19:35:22.000000000 +0000 @@ -620,14 +620,16 @@ static __u8 *fetch_item(__u8 *start, __u case 2: if ((end - start) >= 2) { - item->data.u16 = le16_to_cpu( get_unaligned(((__u16*)start)++)); + item->data.u16 = le16_to_cpu(get_unaligned((__u16*)start)); + start = (__u8 *)((__u16 *)start + 1); return start; } case 3: item->size++; if ((end - start) >= 4) { - item->data.u32 = le32_to_cpu( get_unaligned(((__u32*)start)++)); + item->data.u32 = le32_to_cpu(get_unaligned((__u32*)start)); + start = (__u8 *)((__u32 *)start + 1); return start; } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/host/ehci-hcd.c linux-2.4.28-pre3/drivers/usb/host/ehci-hcd.c --- linux-2.4.27/drivers/usb/host/ehci-hcd.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/host/ehci-hcd.c 2004-09-10 19:34:48.000000000 +0000 @@ -303,7 +303,8 @@ static int bios_handoff (struct ehci_hcd if (cap & (1 << 16)) { ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n", where, cap); - return 1; + pci_write_config_dword (ehci->hcd.pdev, where, 0); + return 0; } ehci_dbg (ehci, "BIOS handoff succeeded\n"); } @@ -547,7 +548,8 @@ static void ehci_stop (struct usb_hcd *h /* root hub is shut down separately (first, when possible) */ spin_lock_irq (&ehci->lock); - ehci_work (ehci, NULL); + if (ehci->async) + ehci_work (ehci, NULL); spin_unlock_irq (&ehci->lock); ehci_mem_cleanup (ehci); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/host/hc_sl811.c linux-2.4.28-pre3/drivers/usb/host/hc_sl811.c --- linux-2.4.27/drivers/usb/host/hc_sl811.c 2003-11-28 18:26:20.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/host/hc_sl811.c 2004-09-10 19:37:01.000000000 +0000 @@ -117,9 +117,6 @@ static int urb_debug = 0; -#include "hc_simple.c" -#include "hc_sl811_rh.c" - /* Include hardware and board depens */ #include @@ -601,6 +598,9 @@ static inline int hc_parse_trans (hci_t return 0; } +#include "hc_simple.c" +#include "hc_sl811_rh.c" + /************************************************************************ * Function Name : hc_start_int * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/host/usb-uhci.c linux-2.4.28-pre3/drivers/usb/host/usb-uhci.c --- linux-2.4.27/drivers/usb/host/usb-uhci.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/host/usb-uhci.c 2004-09-10 19:34:36.000000000 +0000 @@ -2746,13 +2746,8 @@ _static void uhci_interrupt (int irq, vo dbg("interrupt"); if (status != 1) { - // Avoid too much error messages at a time - if (time_after(jiffies, s->last_error_time + ERROR_SUPPRESSION_TIME)) { - warn("interrupt, status %x, frame# %i", status, - UHCI_GET_CURRENT_FRAME(s)); - s->last_error_time = jiffies; - } - + dbg("status %x, frame# %i", status, UHCI_GET_CURRENT_FRAME(s)); + // remove host controller halted state if ((status&0x20) && (s->running)) { err("Host controller halted, trying to restart."); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/host/usb-uhci.h linux-2.4.28-pre3/drivers/usb/host/usb-uhci.h --- linux-2.4.27/drivers/usb/host/usb-uhci.h 2003-06-13 14:51:36.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/host/usb-uhci.h 2004-09-10 19:35:32.000000000 +0000 @@ -218,7 +218,6 @@ typedef struct uhci { int timeout_urbs; struct pci_dev *uhci_pci; struct pci_pool *desc_pool; - long last_error_time; // last error output in uhci_interrupt() } uhci_t, *puhci_t; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/kaweth.c linux-2.4.28-pre3/drivers/usb/kaweth.c --- linux-2.4.27/drivers/usb/kaweth.c 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/kaweth.c 2004-09-10 19:36:01.000000000 +0000 @@ -735,7 +735,7 @@ static int kaweth_start_xmit(struct sk_b } } - private_header = __skb_push(skb, 2); + private_header = (u16 *)__skb_push(skb, 2); *private_header = cpu_to_le16(skb->len-2); kaweth->tx_skb = skb; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/ov511.c linux-2.4.28-pre3/drivers/usb/ov511.c --- linux-2.4.27/drivers/usb/ov511.c 2003-06-13 14:51:36.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/ov511.c 2004-09-10 19:33:43.000000000 +0000 @@ -334,8 +334,8 @@ static struct symbolic_list urb_errlist[ **********************************************************************/ static void ov51x_clear_snapshot(struct usb_ov511 *); -static inline int sensor_get_picture(struct usb_ov511 *, - struct video_picture *); +static int sensor_get_picture(struct usb_ov511 *, + struct video_picture *); #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) static int sensor_get_exposure(struct usb_ov511 *, unsigned char *); static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int, @@ -2014,7 +2014,7 @@ sensor_set_picture(struct usb_ov511 *ov, return 0; } -static inline int +static int sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p) { int rc; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/se401.c linux-2.4.28-pre3/drivers/usb/se401.c --- linux-2.4.27/drivers/usb/se401.c 2002-11-28 23:53:14.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/se401.c 2004-09-10 19:33:38.000000000 +0000 @@ -986,6 +986,44 @@ static int se401_newframe(struct usb_se4 return 0; } +static inline void usb_se401_remove_disconnected (struct usb_se401 *se401) +{ + int i; + + se401->dev = NULL; + se401->frame[0].grabstate = FRAME_ERROR; + se401->frame[1].grabstate = FRAME_ERROR; + + se401->streaming = 0; + + wake_up_interruptible(&se401->wq); + + for (i=0; iurb[i]) { + se401->urb[i]->next = NULL; + usb_unlink_urb(se401->urb[i]); + usb_free_urb(se401->urb[i]); + se401->urb[i] = NULL; + kfree(se401->sbuf[i].data); + } + for (i=0; iscratch[i].data) { + kfree(se401->scratch[i].data); + } + if (se401->inturb) { + usb_unlink_urb(se401->inturb); + usb_free_urb(se401->inturb); + } + info("%s disconnected", se401->camera_name); + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) + destroy_proc_se401_cam(se401); +#endif + + /* Free the memory */ + kfree(se401->width); + kfree(se401->height); + kfree(se401); +} + /**************************************************************************** * @@ -1531,44 +1569,6 @@ static void se401_disconnect(struct usb_ unlock_kernel(); } -static inline void usb_se401_remove_disconnected (struct usb_se401 *se401) -{ - int i; - - se401->dev = NULL; - se401->frame[0].grabstate = FRAME_ERROR; - se401->frame[1].grabstate = FRAME_ERROR; - - se401->streaming = 0; - - wake_up_interruptible(&se401->wq); - - for (i=0; iurb[i]) { - se401->urb[i]->next = NULL; - usb_unlink_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - kfree(se401->sbuf[i].data); - } - for (i=0; iscratch[i].data) { - kfree(se401->scratch[i].data); - } - if (se401->inturb) { - usb_unlink_urb(se401->inturb); - usb_free_urb(se401->inturb); - } - info("%s disconnected", se401->camera_name); - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) - destroy_proc_se401_cam(se401); -#endif - - /* Free the memory */ - kfree(se401->width); - kfree(se401->height); - kfree(se401); -} - static struct usb_driver se401_driver = { name: "se401", id_table: device_table, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/storage/scsiglue.c linux-2.4.28-pre3/drivers/usb/storage/scsiglue.c --- linux-2.4.27/drivers/usb/storage/scsiglue.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/storage/scsiglue.c 2004-09-10 19:34:53.000000000 +0000 @@ -127,7 +127,7 @@ static int release(struct Scsi_Host *psh wait_for_completion(&(us->notify)); /* remove the pointer to the data structure we were using */ - (struct us_data*)psh->hostdata[0] = NULL; + psh->hostdata[0] = (unsigned long)NULL; /* we always have a successful release */ return 0; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/storage/sddr09.c linux-2.4.28-pre3/drivers/usb/storage/sddr09.c --- linux-2.4.27/drivers/usb/storage/sddr09.c 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/storage/sddr09.c 2004-09-10 19:36:27.000000000 +0000 @@ -444,6 +444,7 @@ sddr09_test_unit_ready(struct us_data *u * byte 0: opcode: 03 * byte 4: data length */ +#if 0 static int sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) { unsigned char command[12] = { @@ -465,7 +466,7 @@ sddr09_request_sense(struct us_data *us, return result; } - +#endif /* * Read Command: 12 bytes. * byte 0: opcode: E8 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/storage/transport.c linux-2.4.28-pre3/drivers/usb/storage/transport.c --- linux-2.4.27/drivers/usb/storage/transport.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/storage/transport.c 2004-09-10 19:34:09.000000000 +0000 @@ -627,8 +627,17 @@ void usb_stor_invoke_transport(Scsi_Cmnd int need_auto_sense; int result; + /* + * Grab device's exclusive_access mutex to prevent libusb/usbfs from + * sending out a command in the middle of ours (if libusb sends a + * get_descriptor or something on pipe 0 after our CBW and before + * our CSW, and then we get a stall, we have trouble). + */ + down(&(us->pusb_dev->exclusive_access)); + /* send the command to the transport layer */ result = us->transport(srb, us); + up(&(us->pusb_dev->exclusive_access)); /* if the command gets aborted by the higher layers, we need to * short-circuit all other processing @@ -748,7 +757,9 @@ void usb_stor_invoke_transport(Scsi_Cmnd srb->use_sg = 0; /* issue the auto-sense command */ + down(&(us->pusb_dev->exclusive_access)); temp_result = us->transport(us->srb, us); + up(&(us->pusb_dev->exclusive_access)); /* let's clean up right away */ srb->request_buffer = old_request_buffer; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/storage/unusual_devs.h linux-2.4.28-pre3/drivers/usb/storage/unusual_devs.h --- linux-2.4.27/drivers/usb/storage/unusual_devs.h 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/storage/unusual_devs.h 2004-09-10 19:36:15.000000000 +0000 @@ -430,6 +430,13 @@ UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x US_FL_SINGLE_LUN ), #endif +/* Reported by Darsen Lu */ +UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, + "SigmaTel", + "USBMSC Audio Player", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Submitted by Benny Sjostrand */ UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001, "Minolta", @@ -679,7 +686,7 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xf UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001, "Minds@Work", "Digital Wallet", - US_SC_SCSI, US_PR_CB, NULL, + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_MODE_XLATE ), UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/storage/usb.c linux-2.4.28-pre3/drivers/usb/storage/usb.c --- linux-2.4.27/drivers/usb/storage/usb.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/storage/usb.c 2004-09-10 19:33:26.000000000 +0000 @@ -994,7 +994,7 @@ static void * storage_probe(struct usb_d * the host controller thread in us_detect. But how else are * we to do it? */ - (struct us_data *)ss->htmplt.proc_dir = ss; + ss->htmplt.proc_dir = (void *)ss; /* Just before we start our control thread, initialize * the device if it needs initialization */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/usb.c linux-2.4.28-pre3/drivers/usb/usb.c --- linux-2.4.27/drivers/usb/usb.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/usb.c 2004-09-10 19:34:58.000000000 +0000 @@ -989,6 +989,7 @@ struct usb_device *usb_alloc_dev(struct INIT_LIST_HEAD(&dev->filelist); init_MUTEX(&dev->serialize); + init_MUTEX(&dev->exclusive_access); dev->bus->op->allocate(dev); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/w9968cf.c linux-2.4.28-pre3/drivers/usb/w9968cf.c --- linux-2.4.27/drivers/usb/w9968cf.c 2004-04-14 13:05:37.000000000 +0000 +++ linux-2.4.28-pre3/drivers/usb/w9968cf.c 2004-09-10 19:34:07.000000000 +0000 @@ -446,8 +446,8 @@ static inline unsigned long w9968cf_get_ /* High-level CMOS sensor control functions */ static int w9968cf_sensor_set_control(struct w9968cf_device*,int cid,int val); static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val); -static inline int w9968cf_sensor_cmd(struct w9968cf_device*, - unsigned int cmd, void *arg); +static int w9968cf_sensor_cmd(struct w9968cf_device*, + unsigned int cmd, void *arg); static int w9968cf_sensor_init(struct w9968cf_device*); static int w9968cf_sensor_update_settings(struct w9968cf_device*); static int w9968cf_sensor_get_picture(struct w9968cf_device*); @@ -463,7 +463,7 @@ static int w9968cf_init_chip(struct w996 static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture); static int w9968cf_set_window(struct w9968cf_device*, struct video_window); static inline u16 w9968cf_valid_palette(u16 palette); -static inline u16 w9968cf_valid_depth(u16 palette); +static u16 w9968cf_valid_depth(u16 palette); static inline u8 w9968cf_need_decompression(u16 palette); static int w9968cf_postprocess_frame(struct w9968cf_device*, struct w9968cf_frame_t*); @@ -2214,7 +2214,7 @@ static inline u16 w9968cf_valid_palette( Return the depth corresponding to the given palette. Palette _must_ be supported ! --------------------------------------------------------------------------*/ -static inline u16 w9968cf_valid_depth(u16 palette) +static u16 w9968cf_valid_depth(u16 palette) { u8 i=0; while (w9968cf_formatlist[i].palette != palette) @@ -2433,7 +2433,7 @@ w9968cf_sensor_get_control(struct w9968c } -static inline int +static int w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg) { struct i2c_client* c = cam->sensor_client; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/video/fbcon.c linux-2.4.28-pre3/drivers/video/fbcon.c --- linux-2.4.27/drivers/video/fbcon.c 2003-08-25 11:44:42.000000000 +0000 +++ linux-2.4.28-pre3/drivers/video/fbcon.c 2004-09-10 19:35:55.000000000 +0000 @@ -1877,7 +1877,10 @@ static inline int fbcon_set_font(int uni font length must be multiple of 256, at least. And 256 is multiple of 4 */ k = 0; - while (p > new_data) k += *--(u32 *)p; + while (p > new_data) { + p = (u8 *)((u32 *)p - 1); + k += *(u32 *) p; + } FNTSUM(new_data) = k; /* Check if the same font is on some other console already */ for (i = 0; i < MAX_NR_CONSOLES; i++) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/video/matrox/matroxfb_g450.c linux-2.4.28-pre3/drivers/video/matrox/matroxfb_g450.c --- linux-2.4.27/drivers/video/matrox/matroxfb_g450.c 2003-06-13 14:51:37.000000000 +0000 +++ linux-2.4.28-pre3/drivers/video/matrox/matroxfb_g450.c 2004-09-10 19:36:29.000000000 +0000 @@ -558,7 +558,7 @@ static int matroxfb_g450_program(void* m } static int matroxfb_g450_verify_mode(void* md, u_int32_t arg) { - MINFO_FROM(md); +// MINFO_FROM(md); switch (arg) { case MATROXFB_OUTPUT_MODE_PAL: diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/video/pm3fb.c linux-2.4.28-pre3/drivers/video/pm3fb.c --- linux-2.4.27/drivers/video/pm3fb.c 2004-04-14 13:05:38.000000000 +0000 +++ linux-2.4.28-pre3/drivers/video/pm3fb.c 2004-09-10 19:35:12.000000000 +0000 @@ -3838,11 +3838,9 @@ void cleanup_module(void) (unsigned char *) -1) { pm3fb_unmapIO(l_fb_info); #if (defined KERNEL_2_4) || (defined KERNEL_2_5) - release_mem_region(l_fb_info->p_fb, - l_fb_info-> - fb_size); - release_mem_region(l_fb_info-> - pIOBase, + release_mem_region((u_long)l_fb_info->p_fb, + l_fb_info->fb_size); + release_mem_region((u_long)l_fb_info->pIOBase, PM3_REGS_SIZE); #endif /* KERNEL_2_4 or KERNEL_2_5 */ } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/video/riva/fbdev.c linux-2.4.28-pre3/drivers/video/riva/fbdev.c --- linux-2.4.27/drivers/video/riva/fbdev.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/drivers/video/riva/fbdev.c 2004-09-10 19:35:58.000000000 +0000 @@ -117,7 +117,7 @@ static void rivafb_blank(int blank, struct fb_info *info); extern void riva_setup_accel(struct rivafb_info *rinfo); -extern inline void wait_for_idle(struct rivafb_info *rinfo); +extern void wait_for_idle(struct rivafb_info *rinfo); @@ -2221,7 +2221,6 @@ err_out_free_base1: release_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size); err_out_free_base0: release_mem_region(rinfo->ctrl_base_phys, rinfo->base0_region_size); -err_out_kfree: kfree(rinfo); err_out: return -ENODEV; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/video/sstfb.c linux-2.4.28-pre3/drivers/video/sstfb.c --- linux-2.4.27/drivers/video/sstfb.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/drivers/video/sstfb.c 2004-09-10 19:35:34.000000000 +0000 @@ -968,7 +968,6 @@ static int sstfb_ioctl(struct inode *ino struct fb_info *info) { #define sst_info ((struct sstfb_info *) info) - int i; u_long p; u32 tmp, val; u32 fbiinit0; @@ -980,12 +979,14 @@ static int sstfb_ioctl(struct inode *ino #if (SST_DEBUG_VAR >0) /* tmp ioctl : dumps fb_display[0-5] */ - case _IO('F', 0xdb): /* 0x46db */ + case _IO('F', 0xdb): /* 0x46db */ { + int i; f_dprintk("dumping fb_display[0-5].var\n"); for (i = 0 ; i< 6 ; i++) { print_var(&fb_display[i].var, "var(%d)", i); } return 0; + } #endif /* (SST_DEBUG_VAR >0) */ /* fills the lfb up to given count of pixels */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/Config.in linux-2.4.28-pre3/fs/Config.in --- linux-2.4.27/fs/Config.in 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/fs/Config.in 2004-09-10 19:35:42.000000000 +0000 @@ -121,7 +121,7 @@ if [ "$CONFIG_NET" = "y" ]; then dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET dep_mbool ' Provide NFSv3 server support' CONFIG_NFSD_V3 $CONFIG_NFSD - dep_mbool ' Provide NFS server over TCP support (EXPERIMENTAL)' CONFIG_NFSD_TCP $CONFIG_NFSD $CONFIG_EXPERIMENTAL + dep_mbool ' Provide NFS server over TCP support' CONFIG_NFSD_TCP $CONFIG_NFSD if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then define_tristate CONFIG_SUNRPC y diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/affs/super.c linux-2.4.28-pre3/fs/affs/super.c --- linux-2.4.27/fs/affs/super.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/fs/affs/super.c 2004-09-10 19:35:52.000000000 +0000 @@ -130,7 +130,7 @@ parse_options(char *options, uid_t *uid, printk("AFFS: Argument for set[ug]id option missing\n"); return 0; } else { - (f ? *uid : *gid) = simple_strtoul(value,&value,0); + *(f ? uid : gid) = simple_strtoul(value,&value,0); if (*value) { printk("AFFS: Bad set[ug]id argument\n"); return 0; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/befs/btree.c linux-2.4.28-pre3/fs/befs/btree.c --- linux-2.4.27/fs/befs/btree.c 2003-06-13 14:51:37.000000000 +0000 +++ linux-2.4.28-pre3/fs/befs/btree.c 2004-09-10 19:37:12.000000000 +0000 @@ -85,7 +85,7 @@ typedef struct { } befs_btree_node; /* local constants */ -const static befs_off_t befs_bt_inval = 0xffffffffffffffff; +const static befs_off_t befs_bt_inval = 0xffffffffffffffffULL; /* local functions */ static int befs_btree_seekleaf(struct super_block *sb, befs_data_stream * ds, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/befs/linuxvfs.c linux-2.4.28-pre3/fs/befs/linuxvfs.c --- linux-2.4.27/fs/befs/linuxvfs.c 2003-06-13 14:51:37.000000000 +0000 +++ linux-2.4.28-pre3/fs/befs/linuxvfs.c 2004-09-10 19:37:29.000000000 +0000 @@ -55,13 +55,6 @@ static int befs_remount(struct super_blo static int befs_statfs(struct super_block *, struct statfs *); static int parse_options(char *, befs_mount_options *); -static ssize_t befs_listxattr(struct dentry *dentry, char *buffer, size_t size); -static ssize_t befs_getxattr(struct dentry *dentry, const char *name, - void *buffer, size_t size); -static int befs_setxattr(struct dentry *dentry, const char *name, void *value, - size_t size, int flags); -static int befs_removexattr(struct dentry *dentry, const char *name); - /* slab cache for befs_inode_info objects */ static kmem_cache_t *befs_inode_cachep; @@ -584,11 +577,11 @@ befs_utf2nls(struct super_block *sb, con } } result[o] = '\0'; + *out_len = o; befs_debug(sb, "<--- utf2nls()"); return o; - *out_len = o; conv_err: befs_error(sb, "Name using charecter set %s contains a charecter that " @@ -675,35 +668,6 @@ befs_nls2utf(struct super_block *sb, con return -EILSEQ; } -/****Xattr****/ - -static ssize_t -befs_listxattr(struct dentry *dentry, char *buffer, size_t size) -{ - printk(KERN_ERR "befs_listxattr called\n"); - return 0; -} - -static ssize_t -befs_getxattr(struct dentry *dentry, const char *name, - void *buffer, size_t size) -{ - return 0; -} - -static int -befs_setxattr(struct dentry *dentry, const char *name, - void *value, size_t size, int flags) -{ - return 0; -} - -static int -befs_removexattr(struct dentry *dentry, const char *name) -{ - return 0; -} - /****Superblock****/ static int diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/buffer.c linux-2.4.28-pre3/fs/buffer.c --- linux-2.4.27/fs/buffer.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/fs/buffer.c 2004-09-10 19:35:21.000000000 +0000 @@ -160,7 +160,7 @@ static inline void write_buffer(struct b ll_rw_block(WRITE, 1, &bh); } -void unlock_buffer(struct buffer_head *bh) +void fastcall unlock_buffer(struct buffer_head *bh) { clear_bit(BH_Wait_IO, &bh->b_state); clear_bit(BH_Launder, &bh->b_state); @@ -371,6 +371,7 @@ int sync_buffers(kdev_t dev, int wait) } return err; } +EXPORT_SYMBOL(sync_buffers); int fsync_super(struct super_block *sb) { @@ -649,7 +650,7 @@ struct buffer_head * get_hash_table(kdev return bh; } -void buffer_insert_list(struct buffer_head *bh, struct list_head *list) +void fastcall buffer_insert_list(struct buffer_head *bh, struct list_head *list) { spin_lock(&lru_list_lock); if (buffer_attached(bh)) @@ -1092,7 +1093,7 @@ void balance_dirty(void) } EXPORT_SYMBOL(balance_dirty); -inline void __mark_dirty(struct buffer_head *bh) +inline void fastcall __mark_dirty(struct buffer_head *bh) { bh->b_flushtime = jiffies + bdf_prm.b_un.age_buffer; refile_buffer(bh); @@ -1100,13 +1101,13 @@ inline void __mark_dirty(struct buffer_h /* atomic version, the user must call balance_dirty() by hand as soon as it become possible to block */ -void __mark_buffer_dirty(struct buffer_head *bh) +void fastcall __mark_buffer_dirty(struct buffer_head *bh) { if (!atomic_set_buffer_dirty(bh)) __mark_dirty(bh); } -void mark_buffer_dirty(struct buffer_head *bh) +void fastcall mark_buffer_dirty(struct buffer_head *bh) { if (!atomic_set_buffer_dirty(bh)) { if (block_dump) @@ -1122,7 +1123,7 @@ void set_buffer_flushtime(struct buffer_ } EXPORT_SYMBOL(set_buffer_flushtime); -inline int get_buffer_flushtime(void) +int get_buffer_flushtime(void) { return bdf_prm.b_un.interval; } @@ -1260,8 +1261,9 @@ struct buffer_head * get_unused_buffer_h /* * If we need an async buffer, use the reserved buffer heads. + * Non-PF_MEMALLOC tasks can just loop in create_buffers(). */ - if (async) { + if (async && (current->flags & PF_MEMALLOC)) { spin_lock(&unused_list_lock); if (unused_list) { bh = unused_list; @@ -2730,7 +2732,7 @@ static int sync_page_buffers(struct buff * obtain a reference to a buffer head within a page. So we must * lock out all of these paths to cleanly toss the page. */ -int try_to_free_buffers(struct page * page, unsigned int gfp_mask) +int fastcall try_to_free_buffers(struct page * page, unsigned int gfp_mask) { struct buffer_head * tmp, * bh = page->buffers; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/ext3/super.c linux-2.4.28-pre3/fs/ext3/super.c --- linux-2.4.27/fs/ext3/super.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/fs/ext3/super.c 2004-09-10 19:36:45.000000000 +0000 @@ -1302,6 +1302,7 @@ static journal_t *ext3_get_journal(struc if (!journal) { printk(KERN_ERR "EXT3-fs: Could not load journal inode\n"); iput(journal_inode); + return NULL; } ext3_init_journal_params(EXT3_SB(sb), journal); return journal; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/file_table.c linux-2.4.28-pre3/fs/file_table.c --- linux-2.4.27/fs/file_table.c 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/fs/file_table.c 2004-09-10 19:32:15.000000000 +0000 @@ -97,7 +97,7 @@ int init_private_file(struct file *filp, return 0; } -void fput(struct file * file) +void fastcall fput(struct file * file) { struct dentry * dentry = file->f_dentry; struct vfsmount * mnt = file->f_vfsmnt; @@ -126,7 +126,7 @@ void fput(struct file * file) } } -struct file * fget(unsigned int fd) +struct file fastcall *fget(unsigned int fd) { struct file * file; struct files_struct *files = current->files; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/freevxfs/vxfs_extern.h linux-2.4.28-pre3/fs/freevxfs/vxfs_extern.h --- linux-2.4.27/fs/freevxfs/vxfs_extern.h 2002-02-25 19:38:08.000000000 +0000 +++ linux-2.4.28-pre3/fs/freevxfs/vxfs_extern.h 2004-09-10 19:37:01.000000000 +0000 @@ -72,7 +72,7 @@ extern int vxfs_read_olt(struct super_ /* vxfs_subr.c */ extern struct page * vxfs_get_page(struct address_space *, u_long); -extern __inline__ void vxfs_put_page(struct page *); +extern void vxfs_put_page(struct page *); extern struct buffer_head * vxfs_bread(struct inode *, int); #endif /* _VXFS_EXTERN_H_ */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/freevxfs/vxfs_subr.c linux-2.4.28-pre3/fs/freevxfs/vxfs_subr.c --- linux-2.4.27/fs/freevxfs/vxfs_subr.c 2002-02-25 19:38:08.000000000 +0000 +++ linux-2.4.28-pre3/fs/freevxfs/vxfs_subr.c 2004-09-10 19:33:37.000000000 +0000 @@ -50,6 +50,12 @@ struct address_space_operations vxfs_aop .sync_page = block_sync_page, }; +__inline__ void +vxfs_put_page(struct page *pp) +{ + kunmap(pp); + page_cache_release(pp); +} /** * vxfs_get_page - read a page into memory. @@ -88,13 +94,6 @@ fail: return ERR_PTR(-EIO); } -__inline__ void -vxfs_put_page(struct page *pp) -{ - kunmap(pp); - page_cache_release(pp); -} - /** * vxfs_bread - read buffer for a give inode,block tuple * @ip: inode diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/hfs/file_hdr.c linux-2.4.28-pre3/fs/hfs/file_hdr.c --- linux-2.4.27/fs/hfs/file_hdr.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/fs/hfs/file_hdr.c 2004-09-10 19:35:42.000000000 +0000 @@ -241,7 +241,9 @@ static struct hfs_hdr_layout *dup_layout if (HFS_NEW(new)) { memcpy(new, old, sizeof(*new)); for (lcv = 0; lcv < new->entries; ++lcv) { - (char *)(new->order[lcv]) += (char *)new - (char *)old; + new->order[lcv] = (struct hfs_hdr_descr *) + ((char *)(new->order[lcv]) + + ((char *)new - (char *)old)); } } return new; @@ -640,18 +642,19 @@ static hfs_rwret_t hdr_write(struct file int left, lcv, written = 0; struct hdr_hdr meta; int built_meta = 0; - off_t pos; + loff_t pos; if (!S_ISREG(inode->i_mode)) { hfs_warn("hfs_hdr_write: mode = %07o\n", inode->i_mode); return -EINVAL; } + + pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos; + if (count <= 0 || pos != (unsigned)pos) { return 0; } - pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos; - if (!HFS_I(inode)->layout) { HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/intermezzo/cache.c linux-2.4.28-pre3/fs/intermezzo/cache.c --- linux-2.4.27/fs/intermezzo/cache.c 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/fs/intermezzo/cache.c 2004-09-10 19:34:18.000000000 +0000 @@ -78,6 +78,14 @@ inline void presto_cache_init_hash(void) } } +int izo_ioctl_packlen(struct izo_ioctl_data *data) +{ + int len = sizeof(struct izo_ioctl_data); + len += size_round(data->ioc_inllen1); + len += size_round(data->ioc_inllen2); + return len; +} + /* map a device to a cache */ struct presto_cache *presto_cache_find(kdev_t dev) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/intermezzo/sysctl.c linux-2.4.28-pre3/fs/intermezzo/sysctl.c --- linux-2.4.27/fs/intermezzo/sysctl.c 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/fs/intermezzo/sysctl.c 2004-09-10 19:32:55.000000000 +0000 @@ -290,6 +290,8 @@ int /* __init */ init_intermezzo_sysctl( * happens once per reboot. */ for(i = 0; i < total_dev; i++) { + void *p; + /* entry for this /proc/sys/intermezzo/intermezzo"i" */ ctl_table *psdev = &presto_table[i + PRESTO_PRIMARY_CTLCNT]; /* entries for the individual "files" in this "directory" */ @@ -302,7 +304,8 @@ int /* __init */ init_intermezzo_sysctl( /* the psdev has to point to psdev_entries, and fix the number */ psdev->ctl_name = psdev->ctl_name + i + 1; /* sorry */ - PRESTO_ALLOC((void*)psdev->procname, PROCNAME_SIZE); + PRESTO_ALLOC(p, PROCNAME_SIZE); + psdev->procname = p; if (!psdev->procname) { PRESTO_FREE(dev_ctl_table, sizeof(ctl_table) * total_entries); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/jbd/journal.c linux-2.4.28-pre3/fs/jbd/journal.c --- linux-2.4.27/fs/jbd/journal.c 2004-04-14 13:05:40.000000000 +0000 +++ linux-2.4.28-pre3/fs/jbd/journal.c 2004-09-10 19:32:54.000000000 +0000 @@ -1581,7 +1581,7 @@ void journal_ack_err (journal_t *journal * journal_datalist_lock spinlock: most callers will need those anyway * in order to probe the buffer's journaling state safely. */ -void __jbd_unexpected_dirty_buffer(char *function, int line, +void __jbd_unexpected_dirty_buffer(const char *function, int line, struct journal_head *jh) { struct buffer_head *bh = jh2bh(jh); @@ -1646,7 +1646,7 @@ void shrink_journal_memory(void) * Simple support for retying memory allocations. Introduced to help to * debug different VM deadlock avoidance strategies. */ -void * __jbd_kmalloc (char *where, size_t size, int flags, int retry) +void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry) { void *p; static unsigned long last_warning; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/jfs/jfs_metapage.c linux-2.4.28-pre3/fs/jfs/jfs_metapage.c --- linux-2.4.27/fs/jfs/jfs_metapage.c 2004-08-07 23:26:05.000000000 +0000 +++ linux-2.4.28-pre3/fs/jfs/jfs_metapage.c 2004-09-10 19:35:59.000000000 +0000 @@ -606,6 +606,7 @@ again: if (page) { block_flushpage(page, 0); UnlockPage(page); + page_cache_release(page); } } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/jfs/jfs_mount.c linux-2.4.28-pre3/fs/jfs/jfs_mount.c --- linux-2.4.27/fs/jfs/jfs_mount.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/fs/jfs/jfs_mount.c 2004-09-10 19:33:35.000000000 +0000 @@ -197,9 +197,6 @@ int jfs_mount(struct super_block *sb) /* * unwind on error */ -//errout42: /* close fileset inode allocation map */ - diUnmount(ipimap, 1); - errout41: /* close fileset inode allocation map inode */ diFreeSpecial(ipimap); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/namei.c linux-2.4.28-pre3/fs/namei.c --- linux-2.4.27/fs/namei.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/namei.c 2004-09-10 19:33:55.000000000 +0000 @@ -447,7 +447,7 @@ static inline void follow_dotdot(struct * * We expect 'base' to be positive and a directory. */ -int link_path_walk(const char * name, struct nameidata *nd) +int fastcall link_path_walk(const char * name, struct nameidata *nd) { struct dentry *dentry; struct inode *inode; @@ -653,7 +653,7 @@ return_err: return err; } -int path_walk(const char * name, struct nameidata *nd) +int fastcall path_walk(const char * name, struct nameidata *nd) { current->total_link_count = 0; return link_path_walk(name, nd); @@ -741,7 +741,7 @@ walk_init_root(const char *name, struct } /* SMP-safe */ -int path_lookup(const char *path, unsigned flags, struct nameidata *nd) +int fastcall path_lookup(const char *path, unsigned flags, struct nameidata *nd) { int error = 0; if (path_init(path, flags, nd)) @@ -751,7 +751,7 @@ int path_lookup(const char *path, unsign /* SMP-safe */ -int path_init(const char *name, unsigned int flags, struct nameidata *nd) +int fastcall path_init(const char *name, unsigned int flags, struct nameidata *nd) { nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->flags = flags; @@ -847,7 +847,7 @@ access: * that namei follows links, while lnamei does not. * SMP-safe */ -int __user_walk(const char *name, unsigned flags, struct nameidata *nd) +int fastcall __user_walk(const char *name, unsigned flags, struct nameidata *nd) { char *tmp; int err; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/ncpfs/ncplib_kernel.h linux-2.4.28-pre3/fs/ncpfs/ncplib_kernel.h --- linux-2.4.27/fs/ncpfs/ncplib_kernel.h 2001-02-09 19:29:44.000000000 +0000 +++ linux-2.4.28-pre3/fs/ncpfs/ncplib_kernel.h 2004-09-10 19:33:28.000000000 +0000 @@ -131,7 +131,7 @@ int ncp__vol2io(unsigned char *, unsigne #endif /* CONFIG_NCPFS_NLS */ -inline int +int ncp_strnicmp(struct nls_table *, const unsigned char *, const unsigned char *, int); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/nfsd/nfs3xdr.c linux-2.4.28-pre3/fs/nfsd/nfs3xdr.c --- linux-2.4.27/fs/nfsd/nfs3xdr.c 2003-06-13 14:51:37.000000000 +0000 +++ linux-2.4.28-pre3/fs/nfsd/nfs3xdr.c 2004-09-10 19:31:49.000000000 +0000 @@ -273,7 +273,7 @@ xdr_argsize_check(struct svc_rqst *rqstp { struct svc_buf *buf = &rqstp->rq_argbuf; - return p - buf->base <= buf->buflen; + return p >= buf->base && p <= buf->base + buf->buflen ; } static inline int diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/nfsd/vfs.c linux-2.4.28-pre3/fs/nfsd/vfs.c --- linux-2.4.27/fs/nfsd/vfs.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/fs/nfsd/vfs.c 2004-09-10 19:34:10.000000000 +0000 @@ -586,6 +586,22 @@ found: return ra; } +/* copied from fs/read_write.c */ +static inline loff_t llseek(struct file *file, loff_t offset, int origin) +{ + loff_t (*fn)(struct file *, loff_t, int); + loff_t retval; + + fn = default_llseek; + if (file->f_op && file->f_op->llseek) + fn = file->f_op->llseek; + lock_kernel(); + retval = fn(file, offset, origin); + unlock_kernel(); + return retval; +} + + /* * Read data from a file. count must contain the requested read count * on entry. On return, *count contains the number of bytes actually read. @@ -621,7 +637,7 @@ nfsd_read(struct svc_rqst *rqstp, struct file.f_ralen = ra->p_ralen; file.f_rawin = ra->p_rawin; } - file.f_pos = offset; + llseek(&file, offset, 0); oldfs = get_fs(); set_fs(KERNEL_DS); err = file.f_op->read(&file, buf, *count, &file.f_pos); @@ -706,7 +722,8 @@ nfsd_write(struct svc_rqst *rqstp, struc if (stable && !EX_WGATHER(exp)) file.f_flags |= O_SYNC; - file.f_pos = offset; /* set write offset */ + + llseek(&file, offset, 0); /* Write the data. */ oldfs = get_fs(); set_fs(KERNEL_DS); @@ -1398,10 +1415,12 @@ nfsd_readdir(struct svc_rqst *rqstp, str err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file); if (err) goto out; - if (offset > ~(u32) 0) - goto out_close; - file.f_pos = offset; + offset = llseek(&file, offset, 0); + if (offset < 0) { + err = nfserrno((int)offset); + goto out_close; + } /* Set up the readdir context */ memset(&cd, 0, sizeof(cd)); @@ -1429,11 +1448,13 @@ nfsd_readdir(struct svc_rqst *rqstp, str /* If we didn't fill the buffer completely, we're at EOF */ eof = !cd.eob; + + offset = llseek(&file, 0LL, 1); if (cd.offset) { if (rqstp->rq_vers == 3) - (void)xdr_encode_hyper(cd.offset, file.f_pos); + (void)xdr_encode_hyper(cd.offset, offset); else - *cd.offset = htonl(file.f_pos); + *cd.offset = htonl(offset); } p = cd.buffer; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/ntfs/fs.c linux-2.4.28-pre3/fs/ntfs/fs.c --- linux-2.4.27/fs/ntfs/fs.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/fs/ntfs/fs.c 2004-09-10 19:33:01.000000000 +0000 @@ -1045,7 +1045,7 @@ struct super_block *ntfs_read_super(stru } ntfs_debug(DEBUG_OTHER, "$Mft at cluster 0x%lx\n", vol->mft_lcn); brelse(bh); - NTFS_SB(vol) = sb; + vol->sb = sb; if (vol->cluster_size > PAGE_SIZE) { ntfs_error("Partition cluster size is not supported yet (it " "is > max kernel blocksize).\n"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/ntfs/util.c linux-2.4.28-pre3/fs/ntfs/util.c --- linux-2.4.27/fs/ntfs/util.c 2001-08-13 23:40:19.000000000 +0000 +++ linux-2.4.28-pre3/fs/ntfs/util.c 2004-09-10 19:31:52.000000000 +0000 @@ -165,13 +165,13 @@ int ntfs_decodeuni(ntfs_volume *vol, cha void ntfs_put(ntfs_io *dest, void *src, ntfs_size_t n) { ntfs_memcpy(dest->param, src, n); - ((char*)dest->param) += n; + dest->param = (char*)dest->param + n; } void ntfs_get(void* dest, ntfs_io *src, ntfs_size_t n) { ntfs_memcpy(dest, src->param, n); - ((char*)src->param) += n; + src->param = (char*)src->param + n; } void *ntfs_calloc(int size) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/partitions/ibm.c linux-2.4.28-pre3/fs/partitions/ibm.c --- linux-2.4.27/fs/partitions/ibm.c 2002-08-03 00:39:45.000000000 +0000 +++ linux-2.4.28-pre3/fs/partitions/ibm.c 2004-09-10 19:37:14.000000000 +0000 @@ -9,6 +9,7 @@ * 07/10/00 Fixed detection of CMS formatted disks * 02/13/00 VTOC partition support added * 12/27/01 fixed PL030593 (CMS reserved minidisk not detected on 64 bit) + * 07/24/03 no longer using contents of freed page for CMS label recognition (BZ3611) */ #include @@ -141,7 +142,7 @@ ibm_partition(struct gendisk *hd, struct /* * VM style CMS1 labeled disk */ - int *label = (int *) data; + int *label = (int *) vlabel; if (label[13] != 0) { printk("CMS1/%8s(MDSK):", name); @@ -158,7 +159,8 @@ ibm_partition(struct gendisk *hd, struct add_gd_partition(hd, first_part_minor, offset*(blocksize >> 9), size-offset*(blocksize >> 9)); - } else if (strncmp(type, "VOL1", 4) == 0) { + } else if ((strncmp(type, "VOL1", 4) == 0) && + (!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) { /* * New style VOL1 labeled disk */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/partitions/ldm.h linux-2.4.28-pre3/fs/partitions/ldm.h --- linux-2.4.27/fs/partitions/ldm.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/fs/partitions/ldm.h 2004-09-10 19:33:39.000000000 +0000 @@ -38,8 +38,8 @@ struct parsed_partitions; /* Magic numbers in CPU format. */ #define MAGIC_VMDB 0x564D4442 /* VMDB */ #define MAGIC_VBLK 0x56424C4B /* VBLK */ -#define MAGIC_PRIVHEAD 0x5052495648454144 /* PRIVHEAD */ -#define MAGIC_TOCBLOCK 0x544F43424C4F434B /* TOCBLOCK */ +#define MAGIC_PRIVHEAD 0x5052495648454144ULL /* PRIVHEAD */ +#define MAGIC_TOCBLOCK 0x544F43424C4F434BULL /* TOCBLOCK */ /* The defined vblk types. */ #define VBLK_VOL5 0x51 /* Volume, version 5 */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/readdir.c linux-2.4.28-pre3/fs/readdir.c --- linux-2.4.27/fs/readdir.c 2004-02-18 13:36:31.000000000 +0000 +++ linux-2.4.28-pre3/fs/readdir.c 2004-09-10 19:34:46.000000000 +0000 @@ -264,7 +264,7 @@ static int filldir(void * __buf, const c put_user(reclen, &dirent->d_reclen); copy_to_user(dirent->d_name, name, namlen); put_user(0, dirent->d_name + namlen); - ((char *) dirent) += reclen; + dirent = (void *)dirent + reclen; buf->current_dir = dirent; buf->count -= reclen; return 0; @@ -347,7 +347,7 @@ static int filldir64(void * __buf, const copy_to_user(dirent, &d, NAME_OFFSET(&d)); copy_to_user(dirent->d_name, name, namlen); put_user(0, dirent->d_name + namlen); - ((char *) dirent) += reclen; + dirent = (void *)dirent + reclen; buf->current_dir = dirent; buf->count -= reclen; return 0; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_aops.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_aops.c --- linux-2.4.27/fs/xfs/linux-2.4/xfs_aops.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_aops.c 2004-09-10 19:37:07.000000000 +0000 @@ -209,6 +209,7 @@ xfs_map_at_offset( sector_shift = block_bits - BBSHIFT; bn = iomapp->iomap_bn >> sector_shift; bn += delta; + BUG_ON(!bn && !(iomapp->iomap_flags & IOMAP_REALTIME)); ASSERT((bn << sector_shift) >= iomapp->iomap_bn); lock_buffer(bh); @@ -887,7 +888,7 @@ linvfs_get_block_core( bn = iomap.iomap_bn >> (inode->i_blkbits - BBSHIFT); bn += delta; - + BUG_ON(!bn && !(iomap.iomap_flags & IOMAP_REALTIME)); bh_result->b_blocknr = bn; set_buffer_mapped(bh_result); } @@ -911,10 +912,10 @@ linvfs_get_block_core( } if (iomap.iomap_flags & IOMAP_DELAY) { - if (unlikely(direct)) - BUG(); + BUG_ON(direct); if (create) { set_buffer_mapped(bh_result); + set_buffer_uptodate(bh_result); } set_buffer_delay(bh_result); } @@ -934,17 +935,6 @@ linvfs_get_block( } STATIC int -linvfs_get_block_sync( - struct inode *inode, - long iblock, - struct buffer_head *bh_result, - int create) -{ - return linvfs_get_block_core(inode, iblock, bh_result, - create, 0, BMAPI_SYNC|BMAPI_WRITE); -} - -STATIC int linvfs_get_block_direct( struct inode *inode, long iblock, @@ -1155,13 +1145,7 @@ linvfs_prepare_write( unsigned int from, unsigned int to) { - if (file && (file->f_flags & O_SYNC)) { - return block_prepare_write(page, from, to, - linvfs_get_block_sync); - } else { - return block_prepare_write(page, from, to, - linvfs_get_block); - } + return block_prepare_write(page, from, to, linvfs_get_block); } /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_buf.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_buf.c --- linux-2.4.27/fs/xfs/linux-2.4/xfs_buf.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_buf.c 2004-09-10 19:32:47.000000000 +0000 @@ -767,11 +767,8 @@ pagebuf_get( /* allocate a buffer */ pb = _pagebuf_find(target, ioff, isize, flags, new_pb); if (pb == new_pb) { error = _pagebuf_lookup_pages(pb, flags); - if (unlikely(error)) { - printk(KERN_WARNING - "pagebuf_get: failed to lookup pages\n"); + if (error) goto no_buffer; - } } else { pagebuf_deallocate(new_pb); if (unlikely(pb == NULL)) @@ -1445,6 +1442,7 @@ xfs_free_buftarg( xfs_flush_buftarg(btp, 1); if (external) xfs_blkdev_put(btp->pbr_bdev); + iput(btp->pbr_mapping->host); kmem_free(btp, sizeof(*btp)); } @@ -1458,7 +1456,7 @@ xfs_incore_relse( truncate_inode_pages(btp->pbr_mapping, 0LL); } -void +int xfs_setsize_buftarg( xfs_buftarg_t *btp, unsigned int blocksize, @@ -1472,7 +1470,40 @@ xfs_setsize_buftarg( printk(KERN_WARNING "XFS: Cannot set_blocksize to %u on device 0x%x\n", sectorsize, kdev_t_to_nr(btp->pbr_kdev)); + return EINVAL; } + return 0; +} + +STATIC int +xfs_mapping_buftarg( + xfs_buftarg_t *btp, + struct block_device *bdev) +{ + kdev_t kdev; + struct inode *inode; + struct address_space *mapping; + static struct address_space_operations mapping_aops = { + .sync_page = block_sync_page, + }; + + kdev = to_kdev_t(bdev->bd_dev); + inode = new_inode(bdev->bd_inode->i_sb); + if (!inode) { + printk(KERN_WARNING + "XFS: Cannot allocate mapping inode for device %s\n", + XFS_BUFTARG_NAME(btp)); + return ENOMEM; + } + inode->i_mode = S_IFBLK; + inode->i_dev = kdev; + inode->i_rdev = kdev; + inode->i_bdev = bdev; + mapping = &inode->i_data; + mapping->a_ops = &mapping_aops; + mapping->gfp_mask = GFP_KERNEL; + btp->pbr_mapping = mapping; + return 0; } xfs_buftarg_t * @@ -1480,16 +1511,14 @@ xfs_alloc_buftarg( struct block_device *bdev) { xfs_buftarg_t *btp; + kdev_t kdev; btp = kmem_zalloc(sizeof(*btp), KM_SLEEP); + kdev = to_kdev_t(bdev->bd_dev); btp->pbr_dev = bdev->bd_dev; - btp->pbr_kdev = to_kdev_t(btp->pbr_dev); + btp->pbr_kdev = kdev; btp->pbr_bdev = bdev; - btp->pbr_mapping = bdev->bd_inode->i_mapping; - xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, - get_hardsect_size(btp->pbr_kdev)); - switch (MAJOR(btp->pbr_dev)) { case MD_MAJOR: case EVMS_MAJOR: @@ -1499,8 +1528,15 @@ xfs_alloc_buftarg( btp->pbr_flags = PBR_SECTOR_ONLY; break; } - + if (xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, get_hardsect_size(kdev))) + goto error; + if (xfs_mapping_buftarg(btp, bdev)) + goto error; return btp; + +error: + kmem_free(btp, sizeof(*btp)); + return NULL; } /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_buf.h linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_buf.h --- linux-2.4.27/fs/xfs/linux-2.4/xfs_buf.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_buf.h 2004-09-10 19:36:31.000000000 +0000 @@ -617,7 +617,7 @@ static inline int xfs_bdwrite(void *mp, extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *); extern void xfs_free_buftarg(xfs_buftarg_t *, int); -extern void xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); +extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); extern void xfs_incore_relse(xfs_buftarg_t *, int, int); extern int xfs_flush_buftarg(xfs_buftarg_t *, int); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_ioctl.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_ioctl.c --- linux-2.4.27/fs/xfs/linux-2.4/xfs_ioctl.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_ioctl.c 2004-09-10 19:36:44.000000000 +0000 @@ -71,14 +71,6 @@ #include /* - * ioctl commands that are used by Linux filesystems - */ -#define XFS_IOC_GETXFLAGS _IOR('f', 1, long) -#define XFS_IOC_SETXFLAGS _IOW('f', 2, long) -#define XFS_IOC_GETVERSION _IOR('v', 1, long) - - -/* * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to * a file or fs handle. * @@ -827,13 +819,23 @@ xfs_ioctl( case XFS_IOC_FREEZE: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - xfs_fs_freeze(mp); + + if (vp->v_vfsp->vfs_frozen == SB_UNFROZEN) { + freeze_bdev(mp->m_ddev_targp->pbr_bdev); + if (mp->m_rtdev_targp) + freeze_bdev(mp->m_rtdev_targp->pbr_bdev); + } return 0; case XFS_IOC_THAW: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - xfs_fs_thaw(mp); + + if (vp->v_vfsp->vfs_frozen != SB_UNFROZEN) { + thaw_bdev(mp->m_ddev_targp->pbr_bdev, inode->i_sb); + if (mp->m_rtdev_targp) + thaw_bdev(mp->m_ddev_targp->pbr_bdev, NULL); + } return 0; case XFS_IOC_GOINGDOWN: { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_linux.h linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_linux.h --- linux-2.4.27/fs/xfs/linux-2.4/xfs_linux.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_linux.h 2004-09-10 19:35:59.000000000 +0000 @@ -35,6 +35,9 @@ #include #include +#undef __user +#define __user + /* * Some types are conditional depending on the target system. * XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_lrw.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_lrw.c --- linux-2.4.27/fs/xfs/linux-2.4/xfs_lrw.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_lrw.c 2004-09-10 19:32:18.000000000 +0000 @@ -604,7 +604,7 @@ xfs_write( io = &xip->i_iocore; mp = io->io_mount; - xfs_check_frozen(mp, bdp, XFS_FREEZE_WRITE); + fs_check_frozen(vp->v_vfsp, SB_FREEZE_WRITE); if (XFS_FORCED_SHUTDOWN(xip->i_mount)) { return -EIO; @@ -619,8 +619,6 @@ xfs_write( iolock = XFS_IOLOCK_SHARED; locktype = VRWLOCK_WRITE_DIRECT; } else { - if (io->io_flags & XFS_IOCORE_RT) - return XFS_ERROR(-EINVAL); iolock = XFS_IOLOCK_EXCL; locktype = VRWLOCK_WRITE; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_super.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_super.c --- linux-2.4.27/fs/xfs/linux-2.4/xfs_super.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_super.c 2004-09-10 19:35:59.000000000 +0000 @@ -568,32 +568,73 @@ linvfs_remount( return -error; } +struct super_block *freeze_bdev(struct block_device *bdev) +{ + struct super_block *sb; + struct vfs *vfsp; + int error; + + sb = get_super(to_kdev_t(bdev->bd_dev)); + if (sb && !(sb->s_flags & MS_RDONLY)) { + vfsp = LINVFS_GET_VFS(sb); + + /* Stop new writers */ + vfsp->vfs_frozen = SB_FREEZE_WRITE; + wmb(); + + /* Flush the refcache */ + VFS_SYNC(vfsp, SYNC_REFCACHE|SYNC_WAIT, NULL, error); + + /* Flush delalloc and delwri data */ + VFS_SYNC(vfsp, SYNC_DELWRI|SYNC_WAIT, NULL, error); + + /* Pause transaction subsystem */ + vfsp->vfs_frozen = SB_FREEZE_TRANS; + wmb(); + + /* Flush any remaining inodes into buffers */ + VFS_SYNC(vfsp, SYNC_ATTR|SYNC_WAIT, NULL, error); + + /* Push all buffers out to disk */ + sync_buffers(sb->s_dev, 1); + + /* Push the superblock and write an unmount record */ + VFS_FREEZE(vfsp); + } + + sync_buffers(to_kdev_t(bdev->bd_dev), 1); + return sb; /* thaw_bdev releases sb->s_umount */ +} + +void thaw_bdev(struct block_device *bdev, struct super_block *sb) +{ + if (sb) { + struct vfs *vfsp = LINVFS_GET_VFS(sb); + + BUG_ON(sb->s_bdev != bdev); + + vfsp->vfs_frozen = SB_UNFROZEN; + wmb(); + wake_up(&vfsp->vfs_wait_unfrozen); + + drop_super(sb); + } +} + STATIC void linvfs_freeze_fs( struct super_block *sb) { - vfs_t *vfsp = LINVFS_GET_VFS(sb); - vnode_t *vp; - int error; - if (sb->s_flags & MS_RDONLY) return; - VFS_ROOT(vfsp, &vp, error); - VOP_IOCTL(vp, LINVFS_GET_IP(vp), NULL, 0, XFS_IOC_FREEZE, 0, error); - VN_RELE(vp); + freeze_bdev(sb->s_bdev); } STATIC void linvfs_unfreeze_fs( struct super_block *sb) { - vfs_t *vfsp = LINVFS_GET_VFS(sb); - vnode_t *vp; - int error; - - VFS_ROOT(vfsp, &vp, error); - VOP_IOCTL(vp, LINVFS_GET_IP(vp), NULL, 0, XFS_IOC_THAW, 0, error); - VN_RELE(vp); + thaw_bdev(sb->s_bdev, sb); } STATIC int diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_super.h linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_super.h --- linux-2.4.27/fs/xfs/linux-2.4/xfs_super.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_super.h 2004-09-10 19:34:20.000000000 +0000 @@ -136,5 +136,7 @@ extern void xfs_blkdev_put(struct block_ /* matching a 2.6 kernel export, thus no xfs_ prefix */ extern struct dentry *d_alloc_anon(struct inode *inode); +extern struct super_block *freeze_bdev(struct block_device *bdev); +extern void thaw_bdev(struct block_device *bdev, struct super_block *sb); #endif /* __XFS_SUPER_H__ */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_vfs.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_vfs.c --- linux-2.4.27/fs/xfs/linux-2.4/xfs_vfs.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_vfs.c 2004-09-10 19:33:27.000000000 +0000 @@ -243,6 +243,18 @@ vfs_force_shutdown( ((*bhvtovfsops(next)->vfs_force_shutdown)(next, fl, file, line)); } +void +vfs_freeze( + struct bhv_desc *bdp) +{ + struct bhv_desc *next = bdp; + + ASSERT(next); + while (! (bhvtovfsops(next))->vfs_freeze) + next = BHV_NEXT(next); + ((*bhvtovfsops(next)->vfs_freeze)(next)); +} + vfs_t * vfs_allocate( void ) { @@ -251,6 +263,7 @@ vfs_allocate( void ) vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP); bhv_head_init(VFS_BHVHEAD(vfsp), "vfs"); init_waitqueue_head(&vfsp->vfs_wait_sync_task); + init_waitqueue_head(&vfsp->vfs_wait_unfrozen); return vfsp; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_vfs.h linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_vfs.h --- linux-2.4.27/fs/xfs/linux-2.4/xfs_vfs.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_vfs.h 2004-09-10 19:35:55.000000000 +0000 @@ -53,6 +53,8 @@ typedef struct vfs { struct super_block *vfs_super; /* Linux superblock structure */ struct task_struct *vfs_sync_task; wait_queue_head_t vfs_wait_sync_task; + int vfs_frozen; + wait_queue_head_t vfs_wait_unfrozen; } vfs_t; #define vfs_fbhv vfs_bh.bh_first /* 1st on vfs behavior chain */ @@ -114,6 +116,7 @@ typedef int (*vfs_quotactl_t)(bhv_desc_t typedef void (*vfs_init_vnode_t)(bhv_desc_t *, struct vnode *, bhv_desc_t *, int); typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int); +typedef void (*vfs_freeze_t)(bhv_desc_t *); typedef struct inode * (*vfs_get_inode_t)(bhv_desc_t *, xfs_ino_t, int); typedef struct vfsops { @@ -132,6 +135,7 @@ typedef struct vfsops { vfs_get_inode_t vfs_get_inode; /* bhv specific iget */ vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */ vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */ + vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */ } vfsops_t; /* @@ -152,6 +156,7 @@ typedef struct vfsops { #define VFS_GET_INODE(v, ino, fl) ( vfs_get_inode(VHEAD(v), ino,fl) ) #define VFS_INIT_VNODE(v, vp,b,ul) ( vfs_init_vnode(VHEAD(v), vp,b,ul) ) #define VFS_FORCE_SHUTDOWN(v, fl,f,l) ( vfs_force_shutdown(VHEAD(v), fl,f,l) ) +#define VFS_FREEZE(v) ( vfs_freeze(VHEAD(v)) ) /* * PVFS's. Operates on behavior descriptor pointers. @@ -170,6 +175,7 @@ typedef struct vfsops { #define PVFS_GET_INODE(b, ino,fl) ( vfs_get_inode(b, ino,fl) ) #define PVFS_INIT_VNODE(b, vp,b2,ul) ( vfs_init_vnode(b, vp,b2,ul) ) #define PVFS_FORCE_SHUTDOWN(b, fl,f,l) ( vfs_force_shutdown(b, fl,f,l) ) +#define PVFS_FREEZE(b) ( vfs_freeze(b) ) extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *); extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int); @@ -185,6 +191,7 @@ extern int vfs_quotactl(bhv_desc_t *, in extern struct inode *vfs_get_inode(bhv_desc_t *, xfs_ino_t, int); extern void vfs_init_vnode(bhv_desc_t *, struct vnode *, bhv_desc_t *, int); extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int); +extern void vfs_freeze(bhv_desc_t *); typedef struct bhv_vfsops { struct vfsops bhv_common; @@ -205,4 +212,14 @@ extern void bhv_insert_all_vfsops(struct extern void bhv_remove_all_vfsops(struct vfs *, int); extern void bhv_remove_vfsops(struct vfs *, int); +enum { + SB_UNFROZEN = 0, + SB_FREEZE_WRITE = 1, + SB_FREEZE_TRANS = 2, +}; + +#define fs_frozen(vfsp) ((vfsp)->vfs_frozen) +#define fs_check_frozen(vfsp, level) \ + wait_event((vfsp)->vfs_wait_unfrozen, ((vfsp)->vfs_frozen < (level))) + #endif /* __XFS_VFS_H__ */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_dquot.c linux-2.4.28-pre3/fs/xfs/quota/xfs_dquot.c --- linux-2.4.27/fs/xfs/quota/xfs_dquot.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/quota/xfs_dquot.c 2004-09-10 19:32:18.000000000 +0000 @@ -145,7 +145,7 @@ xfs_qm_dqinit( dqp->q_res_icount = 0; dqp->q_res_rtbcount = 0; dqp->q_pincount = 0; - dqp->q_hash = 0; + dqp->q_hash = NULL; ASSERT(dqp->dq_flnext == dqp->dq_flprev); #ifdef XFS_DQUOT_TRACE @@ -187,9 +187,9 @@ xfs_qm_dqdestroy( */ STATIC void xfs_qm_dqinit_core( - xfs_dqid_t id, - uint type, - xfs_dqblk_t *d) + xfs_dqid_t id, + uint type, + xfs_dqblk_t *d) { /* * Caller has zero'd the entire dquot 'chunk' already. @@ -250,6 +250,36 @@ __xfs_dqtrace_entry( /* + * If default limits are in force, push them into the dquot now. + * We overwrite the dquot limits only if they are zero and this + * is not the root dquot. + */ +void +xfs_qm_adjust_dqlimits( + xfs_mount_t *mp, + xfs_disk_dquot_t *d) +{ + xfs_quotainfo_t *q = mp->m_quotainfo; + + ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT)); + + if (q->qi_bsoftlimit && INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT)) + INT_SET(d->d_blk_softlimit, ARCH_CONVERT, q->qi_bsoftlimit); + if (q->qi_bhardlimit && INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT)) + INT_SET(d->d_blk_hardlimit, ARCH_CONVERT, q->qi_bhardlimit); + if (q->qi_isoftlimit && INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT)) + INT_SET(d->d_ino_softlimit, ARCH_CONVERT, q->qi_isoftlimit); + if (q->qi_ihardlimit && INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT)) + INT_SET(d->d_ino_hardlimit, ARCH_CONVERT, q->qi_ihardlimit); + if (q->qi_rtbsoftlimit && + INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT)) + INT_SET(d->d_rtb_softlimit, ARCH_CONVERT, q->qi_rtbsoftlimit); + if (q->qi_rtbhardlimit && + INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT)) + INT_SET(d->d_rtb_hardlimit, ARCH_CONVERT, q->qi_rtbhardlimit); +} + +/* * Check the limits and timers of a dquot and start or reset timers * if necessary. * This gets called even when quota enforcement is OFF, which makes our @@ -265,53 +295,81 @@ xfs_qm_adjust_dqtimers( xfs_mount_t *mp, xfs_disk_dquot_t *d) { - /* - * The dquot had better be locked. We are modifying it here. - */ - - /* - * root's limits are not real limits. - */ - if (INT_ISZERO(d->d_id, ARCH_CONVERT)) - return; + ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT)); #ifdef QUOTADEBUG if (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)) - ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)); + ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <= + INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)); if (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)) - ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)); + ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <= + INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)); + if (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)) + ASSERT(INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) <= + INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)); #endif if (INT_ISZERO(d->d_btimer, ARCH_CONVERT)) { if ((INT_GET(d->d_blk_softlimit, ARCH_CONVERT) && - (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) || + (INT_GET(d->d_bcount, ARCH_CONVERT) >= + INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) || (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT) && - (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) { - INT_SET(d->d_btimer, ARCH_CONVERT, get_seconds() + XFS_QI_BTIMELIMIT(mp)); + (INT_GET(d->d_bcount, ARCH_CONVERT) >= + INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) { + INT_SET(d->d_btimer, ARCH_CONVERT, + get_seconds() + XFS_QI_BTIMELIMIT(mp)); } } else { if ((INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) || - (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) && + (INT_GET(d->d_bcount, ARCH_CONVERT) < + INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) && (INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT) || - (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) { + (INT_GET(d->d_bcount, ARCH_CONVERT) < + INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) { INT_ZERO(d->d_btimer, ARCH_CONVERT); } } if (INT_ISZERO(d->d_itimer, ARCH_CONVERT)) { if ((INT_GET(d->d_ino_softlimit, ARCH_CONVERT) && - (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) || + (INT_GET(d->d_icount, ARCH_CONVERT) >= + INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) || (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT) && - (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) { - INT_SET(d->d_itimer, ARCH_CONVERT, get_seconds() + XFS_QI_ITIMELIMIT(mp)); + (INT_GET(d->d_icount, ARCH_CONVERT) >= + INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) { + INT_SET(d->d_itimer, ARCH_CONVERT, + get_seconds() + XFS_QI_ITIMELIMIT(mp)); } } else { if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT) || - (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) && + (INT_GET(d->d_icount, ARCH_CONVERT) < + INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) && (INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT) || - (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) { + (INT_GET(d->d_icount, ARCH_CONVERT) < + INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) { INT_ZERO(d->d_itimer, ARCH_CONVERT); } } + + if (INT_ISZERO(d->d_rtbtimer, ARCH_CONVERT)) { + if ((INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) && + (INT_GET(d->d_rtbcount, ARCH_CONVERT) >= + INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) || + (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT) && + (INT_GET(d->d_rtbcount, ARCH_CONVERT) >= + INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) { + INT_SET(d->d_rtbtimer, ARCH_CONVERT, + get_seconds() + XFS_QI_RTBTIMELIMIT(mp)); + } + } else { + if ((INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT) || + (INT_GET(d->d_rtbcount, ARCH_CONVERT) < + INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) && + (INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT) || + (INT_GET(d->d_rtbcount, ARCH_CONVERT) < + INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) { + INT_ZERO(d->d_rtbtimer, ARCH_CONVERT); + } + } } /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_dquot.h linux-2.4.28-pre3/fs/xfs/quota/xfs_dquot.h --- linux-2.4.27/fs/xfs/quota/xfs_dquot.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/quota/xfs_dquot.h 2004-09-10 19:33:21.000000000 +0000 @@ -209,6 +209,8 @@ extern int xfs_qm_dqflock_nowait(xfs_dq extern void xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp); extern void xfs_qm_adjust_dqtimers(xfs_mount_t *, xfs_disk_dquot_t *); +extern void xfs_qm_adjust_dqlimits(xfs_mount_t *, + xfs_disk_dquot_t *); extern int xfs_qm_dqwarn(xfs_disk_dquot_t *, uint); extern int xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *, xfs_dqid_t, uint, uint, xfs_dquot_t **); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_qm.c linux-2.4.28-pre3/fs/xfs/quota/xfs_qm.c --- linux-2.4.27/fs/xfs/quota/xfs_qm.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/quota/xfs_qm.c 2004-09-10 19:33:48.000000000 +0000 @@ -229,11 +229,8 @@ xfs_qm_hold_quotafs_ref( */ XFS_QM_LOCK(xfs_Gqm); - if (xfs_Gqm == NULL) { - if ((xfs_Gqm = xfs_Gqm_init()) == NULL) { - return (XFS_ERROR(EINVAL)); - } - } + if (xfs_Gqm == NULL) + xfs_Gqm = xfs_Gqm_init(); /* * We can keep a list of all filesystems with quotas mounted for * debugging and statistical purposes, but ... @@ -1216,22 +1213,46 @@ xfs_qm_init_quotainfo( XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN, &dqp); if (! error) { + xfs_disk_dquot_t *ddqp = &dqp->q_core; + /* * The warnings and timers set the grace period given to * a user or group before he or she can not perform any * more writing. If it is zero, a default is used. */ - qinf->qi_btimelimit = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT) ? - INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT) : XFS_QM_BTIMELIMIT; - qinf->qi_itimelimit = INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT) ? - INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT) : XFS_QM_ITIMELIMIT; - qinf->qi_rtbtimelimit = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT) ? - INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT) : XFS_QM_RTBTIMELIMIT; - qinf->qi_bwarnlimit = INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) ? - INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) : XFS_QM_BWARNLIMIT; - qinf->qi_iwarnlimit = INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) ? - INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) : XFS_QM_IWARNLIMIT; - + qinf->qi_btimelimit = + INT_GET(ddqp->d_btimer, ARCH_CONVERT) ? + INT_GET(ddqp->d_btimer, ARCH_CONVERT) : + XFS_QM_BTIMELIMIT; + qinf->qi_itimelimit = + INT_GET(ddqp->d_itimer, ARCH_CONVERT) ? + INT_GET(ddqp->d_itimer, ARCH_CONVERT) : + XFS_QM_ITIMELIMIT; + qinf->qi_rtbtimelimit = + INT_GET(ddqp->d_rtbtimer, ARCH_CONVERT) ? + INT_GET(ddqp->d_rtbtimer, ARCH_CONVERT) : + XFS_QM_RTBTIMELIMIT; + qinf->qi_bwarnlimit = + INT_GET(ddqp->d_bwarns, ARCH_CONVERT) ? + INT_GET(ddqp->d_bwarns, ARCH_CONVERT) : + XFS_QM_BWARNLIMIT; + qinf->qi_iwarnlimit = + INT_GET(ddqp->d_iwarns, ARCH_CONVERT) ? + INT_GET(ddqp->d_iwarns, ARCH_CONVERT) : + XFS_QM_IWARNLIMIT; + qinf->qi_bhardlimit = + INT_GET(ddqp->d_blk_hardlimit, ARCH_CONVERT); + qinf->qi_bsoftlimit = + INT_GET(ddqp->d_blk_softlimit, ARCH_CONVERT); + qinf->qi_ihardlimit = + INT_GET(ddqp->d_ino_hardlimit, ARCH_CONVERT); + qinf->qi_isoftlimit = + INT_GET(ddqp->d_ino_softlimit, ARCH_CONVERT); + qinf->qi_rtbhardlimit = + INT_GET(ddqp->d_rtb_hardlimit, ARCH_CONVERT); + qinf->qi_rtbsoftlimit = + INT_GET(ddqp->d_rtb_softlimit, ARCH_CONVERT); + /* * We sent the XFS_QMOPT_DQSUSER flag to dqget because * we don't want this dquot cached. We haven't done a @@ -1691,10 +1712,12 @@ xfs_qm_quotacheck_dqadjust( } /* - * Adjust the timers since we just changed usages + * Set default limits, adjust timers (since we changed usages) */ - if (! XFS_IS_SUSER_DQUOT(dqp)) + if (! XFS_IS_SUSER_DQUOT(dqp)) { + xfs_qm_adjust_dqlimits(dqp->q_mount, &dqp->q_core); xfs_qm_adjust_dqtimers(dqp->q_mount, &dqp->q_core); + } dqp->dq_flags |= XFS_DQ_DIRTY; } @@ -1735,7 +1758,7 @@ STATIC int xfs_qm_dqusage_adjust( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t ino, /* inode number to get data for */ - void *buffer, /* not used */ + void __user *buffer, /* not used */ int ubsize, /* not used */ void *private_data, /* not used */ xfs_daddr_t bno, /* starting block of inode cluster */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_qm.h linux-2.4.28-pre3/fs/xfs/quota/xfs_qm.h --- linux-2.4.27/fs/xfs/quota/xfs_qm.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/quota/xfs_qm.h 2004-09-10 19:34:45.000000000 +0000 @@ -136,9 +136,14 @@ typedef struct xfs_quotainfo { xfs_qwarncnt_t qi_bwarnlimit; /* limit for num warnings */ xfs_qwarncnt_t qi_iwarnlimit; /* limit for num warnings */ mutex_t qi_quotaofflock;/* to serialize quotaoff */ - /* Some useful precalculated constants */ xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */ uint qi_dqperchunk; /* # ondisk dqs in above chunk */ + xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */ + xfs_qcnt_t qi_bsoftlimit; /* default data blk soft limit */ + xfs_qcnt_t qi_ihardlimit; /* default inode count hard limit */ + xfs_qcnt_t qi_isoftlimit; /* default inode count soft limit */ + xfs_qcnt_t qi_rtbhardlimit;/* default realtime blk hard limit */ + xfs_qcnt_t qi_rtbsoftlimit;/* default realtime blk soft limit */ } xfs_quotainfo_t; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_qm_stats.c linux-2.4.28-pre3/fs/xfs/quota/xfs_qm_stats.c --- linux-2.4.27/fs/xfs/quota/xfs_qm_stats.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/quota/xfs_qm_stats.c 2004-09-10 19:33:14.000000000 +0000 @@ -137,8 +137,8 @@ xfs_qm_read_stats( void xfs_qm_init_procfs(void) { - create_proc_read_entry("fs/xfs/xqmstat", 0, 0, xfs_qm_read_stats, NULL); - create_proc_read_entry("fs/xfs/xqm", 0, 0, xfs_qm_read_xfsquota, NULL); + create_proc_read_entry("fs/xfs/xqmstat", 0, NULL, xfs_qm_read_stats, NULL); + create_proc_read_entry("fs/xfs/xqm", 0, NULL, xfs_qm_read_xfsquota, NULL); } void diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_qm_syscalls.c linux-2.4.28-pre3/fs/xfs/quota/xfs_qm_syscalls.c --- linux-2.4.27/fs/xfs/quota/xfs_qm_syscalls.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/quota/xfs_qm_syscalls.c 2004-09-10 19:34:03.000000000 +0000 @@ -648,8 +648,11 @@ xfs_qm_scall_setqlim( if (hard == 0 || hard >= soft) { INT_SET(ddq->d_blk_hardlimit, ARCH_CONVERT, hard); INT_SET(ddq->d_blk_softlimit, ARCH_CONVERT, soft); - } - else { + if (id == 0) { + mp->m_quotainfo->qi_bhardlimit = hard; + mp->m_quotainfo->qi_bsoftlimit = soft; + } + } else { qdprintk("blkhard %Ld < blksoft %Ld\n", hard, soft); } hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ? @@ -661,40 +664,49 @@ xfs_qm_scall_setqlim( if (hard == 0 || hard >= soft) { INT_SET(ddq->d_rtb_hardlimit, ARCH_CONVERT, hard); INT_SET(ddq->d_rtb_softlimit, ARCH_CONVERT, soft); - } - else + if (id == 0) { + mp->m_quotainfo->qi_rtbhardlimit = hard; + mp->m_quotainfo->qi_rtbsoftlimit = soft; + } + } else { qdprintk("rtbhard %Ld < rtbsoft %Ld\n", hard, soft); + } hard = (newlim->d_fieldmask & FS_DQ_IHARD) ? (xfs_qcnt_t) newlim->d_ino_hardlimit : - INT_GET(ddq->d_ino_hardlimit, ARCH_CONVERT); + INT_GET(ddq->d_ino_hardlimit, ARCH_CONVERT); soft = (newlim->d_fieldmask & FS_DQ_ISOFT) ? (xfs_qcnt_t) newlim->d_ino_softlimit : - INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT); + INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT); if (hard == 0 || hard >= soft) { INT_SET(ddq->d_ino_hardlimit, ARCH_CONVERT, hard); INT_SET(ddq->d_ino_softlimit, ARCH_CONVERT, soft); - } - else + if (id == 0) { + mp->m_quotainfo->qi_ihardlimit = hard; + mp->m_quotainfo->qi_isoftlimit = soft; + } + } else { qdprintk("ihard %Ld < isoft %Ld\n", hard, soft); + } if (id == 0) { /* * Timelimits for the super user set the relative time * the other users can be over quota for this file system. - * If it is zero a default is used. + * If it is zero a default is used. Ditto for the default + * soft and hard limit values (already done, above). */ if (newlim->d_fieldmask & FS_DQ_BTIMER) { mp->m_quotainfo->qi_btimelimit = newlim->d_btimer; - INT_SET(dqp->q_core.d_btimer, ARCH_CONVERT, newlim->d_btimer); + INT_SET(ddq->d_btimer, ARCH_CONVERT, newlim->d_btimer); } if (newlim->d_fieldmask & FS_DQ_ITIMER) { mp->m_quotainfo->qi_itimelimit = newlim->d_itimer; - INT_SET(dqp->q_core.d_itimer, ARCH_CONVERT, newlim->d_itimer); + INT_SET(ddq->d_itimer, ARCH_CONVERT, newlim->d_itimer); } if (newlim->d_fieldmask & FS_DQ_RTBTIMER) { mp->m_quotainfo->qi_rtbtimelimit = newlim->d_rtbtimer; - INT_SET(dqp->q_core.d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer); + INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer); } } else /* if (XFS_IS_QUOTA_ENFORCED(mp)) */ { /* @@ -1114,7 +1126,7 @@ mutex_t qcheck_lock; cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \ for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \ dqp = (xfs_dqtest_t *)dqp->NXT) { \ - cmn_err(CE_DEBUG, " %d\. \"%d (%s)\" bcnt = %d, icnt = %d", \ + cmn_err(CE_DEBUG, " %d. \"%d (%s)\" bcnt = %d, icnt = %d", \ ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp), \ dqp->d_bcount, dqp->d_icount); } \ } @@ -1299,7 +1311,7 @@ STATIC int xfs_qm_internalqcheck_adjust( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t ino, /* inode number to get data for */ - void *buffer, /* not used */ + void __user *buffer, /* not used */ int ubsize, /* not used */ void *private_data, /* not used */ xfs_daddr_t bno, /* starting block of inode cluster */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_trans_dquot.c linux-2.4.28-pre3/fs/xfs/quota/xfs_trans_dquot.c --- linux-2.4.27/fs/xfs/quota/xfs_trans_dquot.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/quota/xfs_trans_dquot.c 2004-09-10 19:37:20.000000000 +0000 @@ -452,9 +452,13 @@ xfs_trans_apply_dquot_deltas( INT_MOD(d->d_rtbcount, ARCH_CONVERT, (xfs_qcnt_t)totalrtbdelta); /* + * Get any default limits in use. * Start/reset the timer(s) if needed. */ - xfs_qm_adjust_dqtimers(tp->t_mountp, d); + if (!INT_ISZERO(d->d_id, ARCH_CONVERT)) { + xfs_qm_adjust_dqlimits(tp->t_mountp, d); + xfs_qm_adjust_dqtimers(tp->t_mountp, d); + } dqp->dq_flags |= XFS_DQ_DIRTY; /* @@ -625,6 +629,7 @@ xfs_trans_unreserve_and_mod_dquots( STATIC int xfs_trans_dqresv( xfs_trans_t *tp, + xfs_mount_t *mp, xfs_dquot_t *dqp, long nblks, long ninos, @@ -635,6 +640,7 @@ xfs_trans_dqresv( xfs_qcnt_t softlimit; time_t btimer; xfs_qcnt_t *resbcountp; + xfs_quotainfo_t *q = mp->m_quotainfo; if (! (flags & XFS_QMOPT_DQLOCK)) { xfs_dqlock(dqp); @@ -642,13 +648,21 @@ xfs_trans_dqresv( ASSERT(XFS_DQ_IS_LOCKED(dqp)); if (flags & XFS_TRANS_DQ_RES_BLKS) { hardlimit = INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT); + if (!hardlimit) + hardlimit = q->qi_bhardlimit; softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT); + if (!softlimit) + softlimit = q->qi_bsoftlimit; btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT); resbcountp = &dqp->q_res_bcount; } else { ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS); hardlimit = INT_GET(dqp->q_core.d_rtb_hardlimit, ARCH_CONVERT); + if (!hardlimit) + hardlimit = q->qi_rtbhardlimit; softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT); + if (!softlimit) + softlimit = q->qi_rtbsoftlimit; btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT); resbcountp = &dqp->q_res_rtbcount; } @@ -689,14 +703,18 @@ xfs_trans_dqresv( } } if (ninos > 0) { - if (INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT) > 0ULL && - INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= - INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT)) { + hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT); + if (!hardlimit) + hardlimit = q->qi_ihardlimit; + softlimit = INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT); + if (!softlimit) + softlimit = q->qi_isoftlimit; + if (hardlimit > 0ULL && + INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= hardlimit) { error = EDQUOT; goto error_return; - } else if (INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) > 0ULL && - INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= - INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) { + } else if (softlimit > 0ULL && + INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= softlimit) { /* * If timer or warnings has expired, * return EDQUOT @@ -786,19 +804,20 @@ xfs_trans_reserve_quota_bydquots( resvd = 0; if (udqp) { - if (xfs_trans_dqresv(tp, udqp, nblks, ninos, flags)) + if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags)) return (EDQUOT); resvd = 1; } if (gdqp) { - if (xfs_trans_dqresv(tp, gdqp, nblks, ninos, flags)) { + if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) { /* * can't do it, so backout previous reservation */ if (resvd) { - xfs_trans_dqresv(tp, udqp, -nblks, -ninos, - flags); + flags |= XFS_QMOPT_FORCE_RES; + xfs_trans_dqresv(tp, mp, udqp, + -nblks, -ninos, flags); } return (EDQUOT); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/support/ktrace.c linux-2.4.28-pre3/fs/xfs/support/ktrace.c --- linux-2.4.27/fs/xfs/support/ktrace.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/support/ktrace.c 2004-09-10 19:33:53.000000000 +0000 @@ -30,14 +30,7 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ -#include -#include - -#include -#include "kmem.h" -#include "spin.h" -#include "debug.h" -#include "ktrace.h" +#include static kmem_zone_t *ktrace_hdr_zone; static kmem_zone_t *ktrace_ent_zone; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/support/move.c linux-2.4.28-pre3/fs/xfs/support/move.c --- linux-2.4.27/fs/xfs/support/move.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/support/move.c 2004-09-10 19:34:29.000000000 +0000 @@ -30,13 +30,7 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ -#include -#include -#include - -#include -#include "debug.h" -#include "move.h" +#include /* Read from kernel buffer at src to user/kernel buffer defined * by the uio structure. Advance the pointer in the uio struct diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_acl.h linux-2.4.28-pre3/fs/xfs/xfs_acl.h --- linux-2.4.27/fs/xfs/xfs_acl.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_acl.h 2004-09-10 19:31:51.000000000 +0000 @@ -95,7 +95,7 @@ extern int xfs_acl_vremove(struct vnode #define _ACL_XFS_IACCESS(i,m,c) (XFS_IFORK_Q(i) ? xfs_acl_iaccess(i,m,c) : -1) #define _ACL_ALLOC(a) ((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP)) -#define _ACL_FREE(a) ((a)? kmem_zone_free(xfs_acl_zone, (a)) : 0) +#define _ACL_FREE(a) ((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0) #else #define xfs_acl_zone_init(zone,name) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_alloc.c linux-2.4.28-pre3/fs/xfs/xfs_alloc.c --- linux-2.4.27/fs/xfs/xfs_alloc.c 2004-04-14 13:05:40.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_alloc.c 2004-09-10 19:32:31.000000000 +0000 @@ -665,7 +665,7 @@ xfs_alloc_ag_vextent_exact( * Allocate/initialize a cursor for the by-number freespace btree. */ bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_BNO, 0, 0); + args->agno, XFS_BTNUM_BNO, NULL, 0); /* * Lookup bno and minlen in the btree (minlen is irrelevant, really). * Look for the closest free block <= bno, it must contain bno @@ -721,7 +721,7 @@ xfs_alloc_ag_vextent_exact( * Allocate/initialize a cursor for the by-size btree. */ cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_CNT, 0, 0); + args->agno, XFS_BTNUM_CNT, NULL, 0); ASSERT(args->agbno + args->len <= INT_GET(XFS_BUF_TO_AGF(args->agbp)->agf_length, ARCH_CONVERT)); @@ -788,7 +788,7 @@ xfs_alloc_ag_vextent_near( * Get a cursor for the by-size btree. */ cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_CNT, 0, 0); + args->agno, XFS_BTNUM_CNT, NULL, 0); ltlen = 0; bno_cur_lt = bno_cur_gt = NULL; /* @@ -916,7 +916,7 @@ xfs_alloc_ag_vextent_near( * Set up a cursor for the by-bno tree. */ bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp, - args->agbp, args->agno, XFS_BTNUM_BNO, 0, 0); + args->agbp, args->agno, XFS_BTNUM_BNO, NULL, 0); /* * Fix up the btree entries. */ @@ -944,7 +944,7 @@ xfs_alloc_ag_vextent_near( * Allocate and initialize the cursor for the leftward search. */ bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_BNO, 0, 0); + args->agno, XFS_BTNUM_BNO, NULL, 0); /* * Lookup <= bno to find the leftward search's starting point. */ @@ -956,7 +956,7 @@ xfs_alloc_ag_vextent_near( * search. */ bno_cur_gt = bno_cur_lt; - bno_cur_lt = 0; + bno_cur_lt = NULL; } /* * Found something. Duplicate the cursor for the rightward search. @@ -1301,7 +1301,7 @@ xfs_alloc_ag_vextent_size( * Allocate and initialize a cursor for the by-size btree. */ cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_CNT, 0, 0); + args->agno, XFS_BTNUM_CNT, NULL, 0); bno_cur = NULL; /* * Look for an entry >= maxlen+alignment-1 blocks. @@ -1406,7 +1406,7 @@ xfs_alloc_ag_vextent_size( * Allocate and initialize a cursor for the by-block tree. */ bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_BNO, 0, 0); + args->agno, XFS_BTNUM_BNO, NULL, 0); if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, rbno, rlen, XFSA_FIXUP_CNT_OK))) goto error0; @@ -1553,7 +1553,7 @@ xfs_free_ag_extent( /* * Allocate and initialize a cursor for the by-block btree. */ - bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, 0, + bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, NULL, 0); cnt_cur = NULL; /* @@ -1613,7 +1613,7 @@ xfs_free_ag_extent( /* * Now allocate and initialize a cursor for the by-size tree. */ - cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, 0, + cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, NULL, 0); /* * Have both left and right contiguous neighbors. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_alloc_btree.c linux-2.4.28-pre3/fs/xfs/xfs_alloc_btree.c --- linux-2.4.27/fs/xfs/xfs_alloc_btree.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_alloc_btree.c 2004-09-10 19:32:06.000000000 +0000 @@ -263,7 +263,7 @@ xfs_alloc_delrec( /* * Update the cursor so there's one fewer level. */ - xfs_btree_setbuf(cur, level, 0); + xfs_btree_setbuf(cur, level, NULL); cur->bc_nlevels--; } else if (level > 0 && (error = xfs_alloc_decrement(cur, level, &i))) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_attr.c linux-2.4.28-pre3/fs/xfs/xfs_attr.c --- linux-2.4.27/fs/xfs/xfs_attr.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_attr.c 2004-09-10 19:35:24.000000000 +0000 @@ -104,7 +104,6 @@ STATIC int xfs_attr_rmtval_set(xfs_da_ar STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args); #define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */ -#define ATTR_RMTVALUE_TRANSBLKS 8 /* max # of blks in a transaction */ #if defined(XFS_ATTR_TRACE) ktrace_t *xfs_attr_trace_buf; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_bmap.c linux-2.4.28-pre3/fs/xfs/xfs_bmap.c --- linux-2.4.27/fs/xfs/xfs_bmap.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_bmap.c 2004-09-10 19:36:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -203,8 +203,6 @@ STATIC void xfs_bmap_check_extents( xfs_inode_t *ip, /* incore inode pointer */ int whichfork); /* data or attr fork */ -#else -#define xfs_bmap_check_extents(ip,w) #endif /* @@ -3429,6 +3427,20 @@ xfs_bmap_do_search_extents( int high; /* high index of binary search */ int low; /* low index of binary search */ + /* + * Initialize the extent entry structure to catch access to + * uninitialized br_startblock field. + */ + got.br_startoff = 0xffa5a5a5a5a5a5a5LL; + got.br_blockcount = 0xa55a5a5a5a5a5a5aLL; + got.br_state = XFS_EXT_INVALID; + +#if XFS_BIG_BLKNOS + got.br_startblock = 0xffffa5a5a5a5a5a5LL; +#else + got.br_startblock = 0xffffa5a5; +#endif + if (lastx != NULLEXTNUM && lastx < nextents) ep = base + lastx; else @@ -3527,6 +3539,8 @@ xfs_bmap_search_extents( xfs_bmbt_rec_t *base; /* base of extent list */ xfs_extnum_t lastx; /* last extent index used */ xfs_extnum_t nextents; /* extent list size */ + xfs_bmbt_rec_t *ep; /* extent list entry pointer */ + int rt; /* realtime flag */ XFS_STATS_INC(xs_look_exlist); ifp = XFS_IFORK_PTR(ip, whichfork); @@ -3534,8 +3548,18 @@ xfs_bmap_search_extents( nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); base = &ifp->if_u1.if_extents[0]; - return xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp, + ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp, lastxp, gotp, prevp); + rt = ip->i_d.di_flags & XFS_DIFLAG_REALTIME; + if(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM)) { + cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld " + "start_block : %llx start_off : %llx blkcnt : %llx " + "extent-state : %x \n", + (ip->i_mount)->m_fsname,(long long)ip->i_ino, + gotp->br_startblock, gotp->br_startoff, + gotp->br_blockcount,gotp->br_state); + } + return ep; } @@ -4689,8 +4713,41 @@ xfs_bmapi( } break; } + + /* + * Split changing sb for alen and indlen since + * they could be coming from different places. + */ + if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) { + xfs_extlen_t extsz; + xfs_extlen_t ralen; + if (!(extsz = ip->i_d.di_extsize)) + extsz = mp->m_sb.sb_rextsize; + ralen = roundup(alen, extsz); + ralen = ralen / mp->m_sb.sb_rextsize; + if (xfs_mod_incore_sb(mp, + XFS_SBS_FREXTENTS, + -(ralen), rsvd)) { + if (XFS_IS_QUOTA_ON(ip->i_mount)) + XFS_TRANS_UNRESERVE_BLKQUOTA( + mp, NULL, ip, + (long)alen); + break; + } + } else { + if (xfs_mod_incore_sb(mp, + XFS_SBS_FDBLOCKS, + -(alen), rsvd)) { + if (XFS_IS_QUOTA_ON(ip->i_mount)) + XFS_TRANS_UNRESERVE_BLKQUOTA( + mp, NULL, ip, + (long)alen); + break; + } + } + if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, - -(alen + indlen), rsvd)) { + -(indlen), rsvd)) { XFS_TRANS_UNRESERVE_BLKQUOTA( mp, NULL, ip, (long)alen); break; @@ -5445,7 +5502,7 @@ int /* error code */ xfs_getbmap( bhv_desc_t *bdp, /* XFS behavior descriptor*/ struct getbmap *bmv, /* user bmap structure */ - void *ap, /* pointer to user's array */ + void __user *ap, /* pointer to user's array */ int interface) /* interface flags */ { __int64_t bmvend; /* last block requested */ @@ -5634,8 +5691,10 @@ xfs_getbmap( (__int64_t)(bmvend - bmv->bmv_offset)); bmv->bmv_entries++; ap = (interface & BMV_IF_EXTENDED) ? - (void *)((struct getbmapx *)ap + 1) : - (void *)((struct getbmap *)ap + 1); + (void __user *) + ((struct getbmapx __user *)ap + 1) : + (void __user *) + ((struct getbmap __user *)ap + 1); } } } while (nmap && nexleft && bmv->bmv_length); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_bmap.h linux-2.4.28-pre3/fs/xfs/xfs_bmap.h --- linux-2.4.27/fs/xfs/xfs_bmap.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_bmap.h 2004-09-10 19:32:46.000000000 +0000 @@ -328,7 +328,7 @@ int /* error code */ xfs_getbmap( bhv_desc_t *bdp, /* XFS behavior descriptor*/ struct getbmap *bmv, /* user bmap structure */ - void *ap, /* pointer to user's array */ + void __user *ap, /* pointer to user's array */ int iflags); /* interface flags */ /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_bmap_btree.c linux-2.4.28-pre3/fs/xfs/xfs_bmap_btree.c --- linux-2.4.27/fs/xfs/xfs_bmap_btree.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_bmap_btree.c 2004-09-10 19:31:58.000000000 +0000 @@ -1953,7 +1953,7 @@ xfs_bmbt_get_block( *bpp = cur->bc_bufs[level]; rval = XFS_BUF_TO_BMBT_BLOCK(*bpp); } else { - *bpp = 0; + *bpp = NULL; ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); rval = ifp->if_broot; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_bmap_btree.h linux-2.4.28-pre3/fs/xfs/xfs_bmap_btree.h --- linux-2.4.27/fs/xfs/xfs_bmap_btree.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_bmap_btree.h 2004-09-10 19:35:41.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000,2002-2004 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -153,7 +153,7 @@ typedef enum { */ typedef enum { XFS_EXT_NORM, XFS_EXT_UNWRITTEN, - XFS_EXT_DMAPI_OFFLINE + XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID } xfs_exntst_t; /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_buf_item.c linux-2.4.28-pre3/fs/xfs/xfs_buf_item.c --- linux-2.4.27/fs/xfs/xfs_buf_item.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_buf_item.c 2004-09-10 19:32:38.000000000 +0000 @@ -55,8 +55,6 @@ #include "xfs_error.h" -#define ROUNDUPNBWORD(x) (((x) + (NBWORD - 1)) & ~(NBWORD - 1)) - kmem_zone_t *xfs_buf_item_zone; #ifdef XFS_TRANS_DEBUG diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_da_btree.c linux-2.4.28-pre3/fs/xfs/xfs_da_btree.c --- linux-2.4.27/fs/xfs/xfs_da_btree.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_da_btree.c 2004-09-10 19:36:39.000000000 +0000 @@ -2092,7 +2092,7 @@ xfs_da_do_buf( int caller, inst_t *ra) { - xfs_buf_t *bp = 0; + xfs_buf_t *bp = NULL; xfs_buf_t **bplist; int error=0; int i; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_dfrag.c linux-2.4.28-pre3/fs/xfs/xfs_dfrag.c --- linux-2.4.27/fs/xfs/xfs_dfrag.c 2004-04-14 13:05:40.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_dfrag.c 2004-09-10 19:31:49.000000000 +0000 @@ -65,7 +65,7 @@ */ int xfs_swapext( - xfs_swapext_t *sxp) + xfs_swapext_t __user *sxp) { xfs_swapext_t sx; xfs_inode_t *ip=NULL, *tip=NULL, *ips[2]; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_dfrag.h linux-2.4.28-pre3/fs/xfs/xfs_dfrag.h --- linux-2.4.27/fs/xfs/xfs_dfrag.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_dfrag.h 2004-09-10 19:34:10.000000000 +0000 @@ -60,7 +60,7 @@ typedef struct xfs_swapext /* * Syscall interface for xfs_swapext */ -int xfs_swapext(struct xfs_swapext *sx); +int xfs_swapext(struct xfs_swapext __user *sx); #endif /* __KERNEL__ */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_dinode.h linux-2.4.28-pre3/fs/xfs/xfs_dinode.h --- linux-2.4.27/fs/xfs/xfs_dinode.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_dinode.h 2004-09-10 19:35:22.000000000 +0000 @@ -456,6 +456,7 @@ xfs_dinode_t *xfs_buf_to_dinode(struct x #define XFS_DIFLAG_SYNC_BIT 5 /* inode is written synchronously */ #define XFS_DIFLAG_NOATIME_BIT 6 /* do not update atime */ #define XFS_DIFLAG_NODUMP_BIT 7 /* do not dump */ +#define XFS_DIFLAG_RTINHERIT_BIT 8 /* create with realtime bit set */ #define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT) #define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT) #define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT) @@ -464,5 +465,11 @@ xfs_dinode_t *xfs_buf_to_dinode(struct x #define XFS_DIFLAG_SYNC (1 << XFS_DIFLAG_SYNC_BIT) #define XFS_DIFLAG_NOATIME (1 << XFS_DIFLAG_NOATIME_BIT) #define XFS_DIFLAG_NODUMP (1 << XFS_DIFLAG_NODUMP_BIT) +#define XFS_DIFLAG_RTINHERIT (1 << XFS_DIFLAG_RTINHERIT_BIT) + +#define XFS_DIFLAG_ANY \ + (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \ + XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \ + XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT) #endif /* __XFS_DINODE_H__ */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_dir2_trace.c linux-2.4.28-pre3/fs/xfs/xfs_dir2_trace.c --- linux-2.4.27/fs/xfs/xfs_dir2_trace.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_dir2_trace.c 2004-09-10 19:37:25.000000000 +0000 @@ -211,7 +211,7 @@ xfs_dir2_trace_args_s( (void *)((unsigned long)(args->inumber >> 32)), (void *)((unsigned long)(args->inumber & 0xFFFFFFFF)), (void *)args->dp, (void *)args->trans, - (void *)(unsigned long)args->justcheck, (void *)(long)s, 0); + (void *)(unsigned long)args->justcheck, (void *)(long)s, NULL); } void diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_fs.h linux-2.4.28-pre3/fs/xfs/xfs_fs.h --- linux-2.4.27/fs/xfs/xfs_fs.h 2004-04-14 13:05:40.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_fs.h 2004-09-10 19:34:35.000000000 +0000 @@ -76,6 +76,7 @@ struct fsxattr { #define XFS_XFLAG_SYNC 0x00000020 /* all writes synchronous */ #define XFS_XFLAG_NOATIME 0x00000040 /* do not update access time */ #define XFS_XFLAG_NODUMP 0x00000080 /* do not include in backups */ +#define XFS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */ #define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ /* @@ -164,7 +165,7 @@ typedef struct xfs_flock64 { __s64 l_start; __s64 l_len; /* len == 0 means until end of file */ __s32 l_sysid; - pid_t l_pid; + __u32 l_pid; __s32 l_pad[4]; /* reserve area */ } xfs_flock64_t; @@ -313,10 +314,10 @@ typedef struct xfs_bstat { * The user-level BulkStat Request interface structure. */ typedef struct xfs_fsop_bulkreq { - __u64 *lastip; /* last inode # pointer */ + __u64 __user *lastip; /* last inode # pointer */ __s32 icount; /* count of entries in buffer */ - void *ubuffer; /* user buffer for inode desc. */ - __s32 *ocount; /* output count pointer */ + void __user *ubuffer;/* user buffer for inode desc. */ + __s32 __user *ocount; /* output count pointer */ } xfs_fsop_bulkreq_t; @@ -344,12 +345,12 @@ typedef struct xfs_error_injection { */ typedef struct xfs_fsop_handlereq { __u32 fd; /* fd for FD_TO_HANDLE */ - void *path; /* user pathname */ + void __user *path; /* user pathname */ __u32 oflags; /* open flags */ - void *ihandle; /* user supplied handle */ + void __user *ihandle;/* user supplied handle */ __u32 ihandlen; /* user supplied length */ - void *ohandle; /* user buffer for handle */ - __u32 *ohandlen; /* user buffer length */ + void __user *ohandle;/* user buffer for handle */ + __u32 __user *ohandlen;/* user buffer length */ } xfs_fsop_handlereq_t; /* @@ -360,35 +361,35 @@ typedef struct xfs_fsop_handlereq { */ typedef struct xfs_fsop_setdm_handlereq { - struct xfs_fsop_handlereq hreq; /* handle interface structure */ - struct fsdmidata *data; /* DMAPI data to set */ + struct xfs_fsop_handlereq hreq; /* handle information */ + struct fsdmidata __user *data; /* DMAPI data */ } xfs_fsop_setdm_handlereq_t; typedef struct xfs_attrlist_cursor { - __u32 opaque[4]; + __u32 opaque[4]; } xfs_attrlist_cursor_t; typedef struct xfs_fsop_attrlist_handlereq { - struct xfs_fsop_handlereq hreq; /* handle interface structure */ - struct xfs_attrlist_cursor pos; /* opaque cookie, list offset */ - __u32 flags; /* flags, use ROOT/USER names */ - __u32 buflen; /* length of buffer supplied */ - void *buffer; /* attrlist data to return */ + struct xfs_fsop_handlereq hreq; /* handle interface structure */ + struct xfs_attrlist_cursor pos; /* opaque cookie, list offset */ + __u32 flags; /* which namespace to use */ + __u32 buflen; /* length of buffer supplied */ + void __user *buffer; /* returned names */ } xfs_fsop_attrlist_handlereq_t; typedef struct xfs_attr_multiop { - __u32 am_opcode; - __s32 am_error; - void *am_attrname; - void *am_attrvalue; - __u32 am_length; - __u32 am_flags; + __u32 am_opcode; + __s32 am_error; + void __user *am_attrname; + void __user *am_attrvalue; + __u32 am_length; + __u32 am_flags; } xfs_attr_multiop_t; typedef struct xfs_fsop_attrmulti_handlereq { - struct xfs_fsop_handlereq hreq; /* handle interface structure */ - __u32 opcount; /* count of following multiop */ - struct xfs_attr_multiop *ops; /* attr_multi data to get/set */ + struct xfs_fsop_handlereq hreq; /* handle interface structure */ + __u32 opcount;/* count of following multiop */ + struct xfs_attr_multiop __user *ops; /* attr_multi data */ } xfs_fsop_attrmulti_handlereq_t; /* @@ -445,6 +446,13 @@ typedef struct xfs_handle { #define XFS_FSOP_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */ /* + * ioctl commands that are used by Linux filesystems + */ +#define XFS_IOC_GETXFLAGS _IOR('f', 1, long) +#define XFS_IOC_SETXFLAGS _IOW('f', 2, long) +#define XFS_IOC_GETVERSION _IOR('v', 1, long) + +/* * ioctl commands that replace IRIX fcntl()'s * For 'documentation' purposed more than anything else, * the "cmd #" field reflects the IRIX fcntl number. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_fsops.c linux-2.4.28-pre3/fs/xfs/xfs_fsops.c --- linux-2.4.27/fs/xfs/xfs_fsops.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_fsops.c 2004-09-10 19:34:52.000000000 +0000 @@ -142,6 +142,7 @@ xfs_growfs_data_private( int dpct; int error; xfs_agnumber_t nagcount; + xfs_agnumber_t nagimax = 0; xfs_rfsblock_t nb, nb_mod; xfs_rfsblock_t new; xfs_rfsblock_t nfree; @@ -183,7 +184,7 @@ xfs_growfs_data_private( memset(&mp->m_perag[oagcount], 0, (nagcount - oagcount) * sizeof(xfs_perag_t)); mp->m_flags |= XFS_MOUNT_32BITINODES; - xfs_initialize_perag(mp, nagcount); + nagimax = xfs_initialize_perag(mp, nagcount); up_write(&mp->m_peraglock); } tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); @@ -372,6 +373,9 @@ xfs_growfs_data_private( if (error) { return error; } + /* New allocation groups fully initialized, so update mount struct */ + if (nagimax) + mp->m_maxagi = nagimax; if (mp->m_sb.sb_imax_pct) { __uint64_t icount = mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct; do_div(icount, 100); @@ -507,9 +511,9 @@ xfs_reserve_blocks( __uint64_t *inval, xfs_fsop_resblks_t *outval) { - __uint64_t lcounter, delta; - __uint64_t request; - unsigned long s; + __int64_t lcounter, delta; + __uint64_t request; + unsigned long s; /* If inval is null, report current values and return */ @@ -536,8 +540,7 @@ xfs_reserve_blocks( mp->m_resblks = request; } else { delta = request - mp->m_resblks; - lcounter = mp->m_sb.sb_fdblocks; - lcounter -= delta; + lcounter = mp->m_sb.sb_fdblocks - delta; if (lcounter < 0) { /* We can't satisfy the request, just get what we can */ mp->m_resblks += mp->m_sb.sb_fdblocks; @@ -583,63 +586,22 @@ xfs_fs_log_dummy(xfs_mount_t *mp) } int -xfs_fs_freeze( - xfs_mount_t *mp) -{ - vfs_t *vfsp; - /*REFERENCED*/ - int error; - - vfsp = XFS_MTOVFS(mp); - - /* Stop new writers */ - xfs_start_freeze(mp, XFS_FREEZE_WRITE); - - /* Flush the refcache */ - xfs_refcache_purge_mp(mp); - - /* Flush delalloc and delwri data */ - VFS_SYNC(vfsp, SYNC_DELWRI|SYNC_WAIT, NULL, error); - - /* Pause transaction subsystem */ - xfs_start_freeze(mp, XFS_FREEZE_TRANS); - - /* Flush any remaining inodes into buffers */ - VFS_SYNC(vfsp, SYNC_ATTR|SYNC_WAIT, NULL, error); - - /* Push all buffers out to disk */ - xfs_binval(mp->m_ddev_targp); - if (mp->m_rtdev_targp) { - xfs_binval(mp->m_rtdev_targp); - } - - /* Push the superblock and write an unmount record */ - xfs_log_unmount_write(mp); - xfs_unmountfs_writesb(mp); - - return 0; -} - -int -xfs_fs_thaw( - xfs_mount_t *mp) -{ - xfs_finish_freeze(mp); - return 0; -} - -int xfs_fs_goingdown( xfs_mount_t *mp, __uint32_t inflags) { - switch (inflags) - { - case XFS_FSOP_GOING_FLAGS_DEFAULT: - xfs_fs_freeze(mp); - xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); - xfs_fs_thaw(mp); + switch (inflags) { + case XFS_FSOP_GOING_FLAGS_DEFAULT: { + struct vfs *vfsp = XFS_MTOVFS(mp); + struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev); + + if (sb) { + xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); + thaw_bdev(sb->s_bdev, sb); + } + break; + } case XFS_FSOP_GOING_FLAGS_LOGFLUSH: xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); break; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_fsops.h linux-2.4.28-pre3/fs/xfs/xfs_fsops.h --- linux-2.4.27/fs/xfs/xfs_fsops.h 2004-04-14 13:05:40.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_fsops.h 2004-09-10 19:32:41.000000000 +0000 @@ -60,14 +60,6 @@ xfs_reserve_blocks( xfs_fsop_resblks_t *outval); int -xfs_fs_freeze( - xfs_mount_t *mp); - -int -xfs_fs_thaw( - xfs_mount_t *mp); - -int xfs_fs_goingdown( xfs_mount_t *mp, __uint32_t inflags); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_inode.c linux-2.4.28-pre3/fs/xfs/xfs_inode.c --- linux-2.4.27/fs/xfs/xfs_inode.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_inode.c 2004-09-10 19:37:09.000000000 +0000 @@ -860,25 +860,28 @@ xfs_dic2xflags( xfs_arch_t arch) { __uint16_t di_flags; - uint flags = 0; + uint flags; di_flags = INT_GET(dic->di_flags, arch); - if (di_flags & XFS_DIFLAG_REALTIME) - flags |= XFS_XFLAG_REALTIME; - if (di_flags & XFS_DIFLAG_PREALLOC) - flags |= XFS_XFLAG_PREALLOC; - if (di_flags & XFS_DIFLAG_IMMUTABLE) - flags |= XFS_XFLAG_IMMUTABLE; - if (di_flags & XFS_DIFLAG_APPEND) - flags |= XFS_XFLAG_APPEND; - if (di_flags & XFS_DIFLAG_SYNC) - flags |= XFS_XFLAG_SYNC; - if (di_flags & XFS_DIFLAG_NOATIME) - flags |= XFS_XFLAG_NOATIME; - if (di_flags & XFS_DIFLAG_NODUMP) - flags |= XFS_XFLAG_NODUMP; - if (XFS_CFORK_Q_ARCH(dic, arch)) - flags |= XFS_XFLAG_HASATTR; + flags = XFS_CFORK_Q_ARCH(dic, arch) ? XFS_XFLAG_HASATTR : 0; + if (di_flags & XFS_DIFLAG_ANY) { + if (di_flags & XFS_DIFLAG_REALTIME) + flags |= XFS_XFLAG_REALTIME; + if (di_flags & XFS_DIFLAG_PREALLOC) + flags |= XFS_XFLAG_PREALLOC; + if (di_flags & XFS_DIFLAG_IMMUTABLE) + flags |= XFS_XFLAG_IMMUTABLE; + if (di_flags & XFS_DIFLAG_APPEND) + flags |= XFS_XFLAG_APPEND; + if (di_flags & XFS_DIFLAG_SYNC) + flags |= XFS_XFLAG_SYNC; + if (di_flags & XFS_DIFLAG_NOATIME) + flags |= XFS_XFLAG_NOATIME; + if (di_flags & XFS_DIFLAG_NODUMP) + flags |= XFS_XFLAG_NODUMP; + if (di_flags & XFS_DIFLAG_RTINHERIT) + flags |= XFS_XFLAG_RTINHERIT; + } return flags; } @@ -1236,8 +1239,15 @@ xfs_ialloc( break; case S_IFREG: case S_IFDIR: - if (pip->i_d.di_flags & - (XFS_DIFLAG_NOATIME|XFS_DIFLAG_NODUMP|XFS_DIFLAG_SYNC)) { + if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) { + if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) { + if ((mode & S_IFMT) == S_IFDIR) { + ip->i_d.di_flags |= XFS_DIFLAG_RTINHERIT; + } else { + ip->i_d.di_flags |= XFS_DIFLAG_REALTIME; + ip->i_iocore.io_flags |= XFS_IOCORE_RT; + } + } if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) && xfs_inherit_noatime) ip->i_d.di_flags |= XFS_DIFLAG_NOATIME; @@ -1248,6 +1258,7 @@ xfs_ialloc( xfs_inherit_sync) ip->i_d.di_flags |= XFS_DIFLAG_SYNC; } + /* FALLTHROUGH */ case S_IFLNK: ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS; ip->i_df.if_flags = XFS_IFEXTENTS; @@ -3579,6 +3590,7 @@ corrupt_out: return XFS_ERROR(EFSCORRUPTED); } + /* * Flush all inactive inodes in mp. Return true if no user references * were found, false otherwise. @@ -3634,7 +3646,6 @@ xfs_iflush_all( continue; } if (!(flag & XFS_FLUSH_ALL)) { - ASSERT(0); busy = 1; done = 1; break; @@ -3851,6 +3862,6 @@ xfs_ilock_trace(xfs_inode_t *ip, int loc (void *)ra, /* caller of ilock */ (void *)(unsigned long)current_cpu(), (void *)(unsigned long)current_pid(), - 0,0,0,0,0,0,0,0,0,0); + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); } #endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_iomap.c linux-2.4.28-pre3/fs/xfs/xfs_iomap.c --- linux-2.4.27/fs/xfs/xfs_iomap.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_iomap.c 2004-09-10 19:32:40.000000000 +0000 @@ -165,20 +165,24 @@ xfs_imap_to_bmap( nisize = io->io_new_size; for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) { - iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ? - mp->m_rtdev_targp : mp->m_ddev_targp; iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff); iomapp->iomap_delta = offset - iomapp->iomap_offset; iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount); iomapp->iomap_flags = flags; + if (io->io_flags & XFS_IOCORE_RT) { + iomapp->iomap_flags |= IOMAP_REALTIME; + iomapp->iomap_target = mp->m_rtdev_targp; + } else { + iomapp->iomap_target = mp->m_ddev_targp; + } start_block = imap->br_startblock; if (start_block == HOLESTARTBLOCK) { iomapp->iomap_bn = IOMAP_DADDR_NULL; - iomapp->iomap_flags = IOMAP_HOLE; + iomapp->iomap_flags |= IOMAP_HOLE; } else if (start_block == DELAYSTARTBLOCK) { iomapp->iomap_bn = IOMAP_DADDR_NULL; - iomapp->iomap_flags = IOMAP_DELAY; + iomapp->iomap_flags |= IOMAP_DELAY; } else { iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block); if (ISUNWRITTEN(imap)) @@ -512,6 +516,15 @@ xfs_iomap_write_direct( *ret_imap = imap[0]; *nmaps = 1; + if ( !(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock) { + cmn_err(CE_PANIC,"Access to block zero: fs <%s> inode: %lld " + "start_block : %llx start_off : %llx blkcnt : %llx " + "extent-state : %x \n", + (ip->i_mount)->m_fsname, + (long long)ip->i_ino, + ret_imap->br_startblock, ret_imap->br_startoff, + ret_imap->br_blockcount,ret_imap->br_state); + } return 0; error0: /* Cancel bmap, unlock inode, and cancel trans */ @@ -572,8 +585,10 @@ retry: * out to the file system's write iosize. We clean up any extra * space left over when the file is closed in xfs_inactive(). * - * We don't bother with this for sync writes, because we need - * to minimize the amount we write for good performance. + * For sync writes, we are flushing delayed allocate space to + * try to make additional space available for allocation near + * the filesystem full boundary - preallocation hurts in that + * situation, of course. */ if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) { xfs_off_t aligned_offset; @@ -598,6 +613,20 @@ retry: return error; } for (n = 0; n < nimaps; n++) { + if ( !(io->io_flags & XFS_IOCORE_RT) && + !imap[n].br_startblock) { + cmn_err(CE_PANIC,"Access to block " + "zero: fs <%s> inode: %lld " + "start_block : %llx start_off " + ": %llx blkcnt : %llx " + "extent-state : %x \n", + (ip->i_mount)->m_fsname, + (long long)ip->i_ino, + imap[n].br_startblock, + imap[n].br_startoff, + imap[n].br_blockcount, + imap[n].br_state); + } if ((imap[n].br_startblock != HOLESTARTBLOCK) && (imap[n].br_startblock != DELAYSTARTBLOCK)) { goto write_map; @@ -621,7 +650,8 @@ write_map: * request to a stripe width boundary if the file size is >= * stripe width and we are allocating past the allocation eof. */ - if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC) + if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_swidth + && (mp->m_flags & XFS_MOUNT_SWALLOC) && (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)) && aeof) { int eof; xfs_fileoff_t new_last_fsb; @@ -639,8 +669,8 @@ write_map: * if the file size is >= stripe unit size, and we are allocating past * the allocation eof. */ - } else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)) - && aeof) { + } else if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_dalign && + (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)) && aeof) { int eof; xfs_fileoff_t new_last_fsb; new_last_fsb = roundup_64(last_fsb, mp->m_dalign); @@ -651,8 +681,22 @@ write_map: if (eof) { last_fsb = new_last_fsb; } - } + /* + * Round up the allocation request to a real-time extent boundary + * if the file is on the real-time subvolume. + */ + } else if (io->io_flags & XFS_IOCORE_RT && aeof) { + int eof; + xfs_fileoff_t new_last_fsb; + new_last_fsb = roundup_64(last_fsb, mp->m_sb.sb_rextsize); + error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof); + if (error) { + return error; + } + if (eof) + last_fsb = new_last_fsb; + } error = xfs_bmapi(NULL, ip, offset_fsb, (xfs_filblks_t)(last_fsb - offset_fsb), XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | @@ -680,6 +724,15 @@ write_map: *ret_imap = imap[0]; *nmaps = 1; + if ( !(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock) { + cmn_err(CE_PANIC,"Access to block zero: fs <%s> inode: %lld " + "start_block : %llx start_off : %llx blkcnt : %llx " + "extent-state : %x \n", + (ip->i_mount)->m_fsname, + (long long)ip->i_ino, + ret_imap->br_startblock, ret_imap->br_startoff, + ret_imap->br_blockcount,ret_imap->br_state); + } return 0; } @@ -697,6 +750,7 @@ xfs_iomap_write_allocate( int *retmap) { xfs_mount_t *mp = ip->i_mount; + xfs_iocore_t *io = &ip->i_iocore; xfs_fileoff_t offset_fsb, last_block; xfs_fileoff_t end_fsb, map_start_fsb; xfs_fsblock_t first_block; @@ -802,6 +856,18 @@ xfs_iomap_write_allocate( */ for (i = 0; i < nimaps; i++) { + if ( !(io->io_flags & XFS_IOCORE_RT) && + !imap[i].br_startblock) { + cmn_err(CE_PANIC,"Access to block zero: " + "fs <%s> inode: %lld " + "start_block : %llx start_off : %llx " + "blkcnt : %llx extent-state : %x \n", + (ip->i_mount)->m_fsname, + (long long)ip->i_ino, + imap[i].br_startblock, + imap[i].br_startoff, + imap[i].br_blockcount,imap[i].br_state); + } if ((map->br_startoff >= imap[i].br_startoff) && (map->br_startoff < (imap[i].br_startoff + imap[i].br_blockcount))) { @@ -837,6 +903,7 @@ xfs_iomap_write_unwritten( size_t count) { xfs_mount_t *mp = ip->i_mount; + xfs_iocore_t *io = &ip->i_iocore; xfs_trans_t *tp; xfs_fileoff_t offset_fsb; xfs_filblks_t count_fsb; @@ -853,7 +920,8 @@ xfs_iomap_write_unwritten( &ip->i_iocore, offset, count); offset_fsb = XFS_B_TO_FSBT(mp, offset); - count_fsb = XFS_B_TO_FSB(mp, count); + count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); + count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb); do { nres = XFS_DIOSTRAT_SPACE_RES(mp, 0); @@ -898,6 +966,16 @@ xfs_iomap_write_unwritten( xfs_iunlock(ip, XFS_ILOCK_EXCL); if (error) goto error0; + + if ( !(io->io_flags & XFS_IOCORE_RT) && !imap.br_startblock) { + cmn_err(CE_PANIC,"Access to block zero: fs <%s> " + "inode: %lld start_block : %llx start_off : " + "%llx blkcnt : %llx extent-state : %x \n", + (ip->i_mount)->m_fsname, + (long long)ip->i_ino, + imap.br_startblock,imap.br_startoff, + imap.br_blockcount,imap.br_state); + } if ((numblks_fsb = imap.br_blockcount) == 0) { /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_iomap.h linux-2.4.28-pre3/fs/xfs/xfs_iomap.h --- linux-2.4.27/fs/xfs/xfs_iomap.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_iomap.h 2004-09-10 19:34:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2003,2004 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -42,6 +42,7 @@ typedef enum { /* iomap_flags values IOMAP_EOF = 0x01, /* mapping contains EOF */ IOMAP_HOLE = 0x02, /* mapping covers a hole */ IOMAP_DELAY = 0x04, /* mapping covers delalloc region */ + IOMAP_REALTIME = 0x10, /* mapping on the realtime device */ IOMAP_UNWRITTEN = 0x20, /* mapping covers allocated */ /* but uninitialized file data */ IOMAP_NEW = 0x40 /* just allocate */ @@ -57,7 +58,7 @@ typedef enum { BMAPI_IGNSTATE = (1 << 4), /* ignore unwritten state on read */ BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */ BMAPI_MMAP = (1 << 6), /* allocate for mmap write */ - BMAPI_SYNC = (1 << 7), /* sync write */ + BMAPI_SYNC = (1 << 7), /* sync write to flush delalloc space */ BMAPI_TRYLOCK = (1 << 8), /* non-blocking request */ BMAPI_DEVICE = (1 << 9), /* we only want to know the device */ } bmapi_flags_t; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_itable.c linux-2.4.28-pre3/fs/xfs/xfs_itable.c --- linux-2.4.27/fs/xfs/xfs_itable.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_itable.c 2004-09-10 19:36:46.000000000 +0000 @@ -68,7 +68,7 @@ int /* error status */ xfs_bulkstat_one( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t ino, /* inode number to get data for */ - void *buffer, /* buffer to place output in */ + void __user *buffer, /* buffer to place output in */ int ubsize, /* size of buffer */ void *private_data, /* my private data */ xfs_daddr_t bno, /* starting bno of inode cluster */ @@ -231,7 +231,7 @@ xfs_bulkstat( bulkstat_one_pf formatter, /* func that'd fill a single buf */ void *private_data,/* private data for formatter */ size_t statstruct_size, /* sizeof struct filling */ - xfs_caddr_t ubuffer, /* buffer with inode stats */ + char __user *ubuffer, /* buffer with inode stats */ int flags, /* defined in xfs_itable.h */ int *done) /* 1 if there're more stats to get */ { @@ -265,7 +265,7 @@ xfs_bulkstat( int tmp; /* result value from btree calls */ int ubcount; /* size of user's buffer */ int ubleft; /* bytes left in user's buffer */ - xfs_caddr_t ubufp; /* current pointer into user's buffer */ + char __user *ubufp; /* pointer into user's buffer */ int ubelem; /* spaces used in user's buffer */ int ubused; /* bytes used by formatter */ xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */ @@ -633,7 +633,7 @@ int /* error status */ xfs_bulkstat_single( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t *lastinop, /* inode to return */ - xfs_caddr_t buffer, /* buffer with inode stats */ + char __user *buffer, /* buffer with inode stats */ int *done) /* 1 if there're more stats to get */ { int count; /* count value for bulkstat call */ @@ -682,7 +682,7 @@ xfs_inumbers( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t *lastino, /* last inode returned */ int *count, /* size of buffer/count returned */ - xfs_caddr_t ubuffer) /* buffer with inode descriptions */ + xfs_inogrp_t __user *ubuffer)/* buffer with inode descriptions */ { xfs_buf_t *agbp; xfs_agino_t agino; @@ -766,7 +766,7 @@ xfs_inumbers( error = XFS_ERROR(EFAULT); break; } - ubuffer += bufidx * sizeof(*buffer); + ubuffer += bufidx; *count += bufidx; bufidx = 0; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_itable.h linux-2.4.28-pre3/fs/xfs/xfs_itable.h --- linux-2.4.27/fs/xfs/xfs_itable.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_itable.h 2004-09-10 19:36:12.000000000 +0000 @@ -40,7 +40,7 @@ */ typedef int (*bulkstat_one_pf)(struct xfs_mount *mp, xfs_ino_t ino, - void *buffer, + void __user *buffer, int ubsize, void *private_data, xfs_daddr_t bno, @@ -73,7 +73,7 @@ xfs_bulkstat( bulkstat_one_pf formatter, /* func that'd fill a single buf */ void *private_data, /* private data for formatter */ size_t statstruct_size,/* sizeof struct that we're filling */ - xfs_caddr_t ubuffer, /* buffer with inode stats */ + char __user *ubuffer,/* buffer with inode stats */ int flags, /* flag to control access method */ int *done); /* 1 if there're more stats to get */ @@ -81,14 +81,14 @@ int xfs_bulkstat_single( xfs_mount_t *mp, xfs_ino_t *lastinop, - xfs_caddr_t buffer, + char __user *buffer, int *done); int xfs_bulkstat_one( xfs_mount_t *mp, xfs_ino_t ino, - void *buffer, + void __user *buffer, int ubsize, void *private_data, xfs_daddr_t bno, @@ -101,6 +101,6 @@ xfs_inumbers( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t *last, /* last inode returned */ int *count, /* size of buffer/count returned */ - xfs_caddr_t buffer);/* buffer with inode descriptions */ + xfs_inogrp_t __user *buffer);/* buffer with inode info */ #endif /* __XFS_ITABLE_H__ */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_log.c linux-2.4.28-pre3/fs/xfs/xfs_log.c --- linux-2.4.27/fs/xfs/xfs_log.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_log.c 2004-09-10 19:36:10.000000000 +0000 @@ -122,7 +122,6 @@ STATIC void xlog_ticket_put(xlog_t *log /* local debug functions */ #if defined(DEBUG) && !defined(XLOG_NOLOG) STATIC void xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr); -STATIC void xlog_verify_disk_cycle_no(xlog_t *log, xlog_in_core_t *iclog); STATIC void xlog_verify_grant_head(xlog_t *log, int equals); STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog, int count, boolean_t syncing); @@ -130,7 +129,6 @@ STATIC void xlog_verify_tail_lsn(xlog_t xfs_lsn_t tail_lsn); #else #define xlog_verify_dest_ptr(a,b) -#define xlog_verify_disk_cycle_no(a,b) #define xlog_verify_grant_head(a,b) #define xlog_verify_iclog(a,b,c,d) #define xlog_verify_tail_lsn(a,b,c) @@ -356,13 +354,13 @@ xfs_log_notify(xfs_mount_t *mp, /* mo if (!xlog_debug && xlog_target == log->l_targ) return 0; #endif - cb->cb_next = 0; + cb->cb_next = NULL; spl = LOG_LOCK(log); abortflg = (iclog->ic_state & XLOG_STATE_IOERROR); if (!abortflg) { ASSERT_ALWAYS((iclog->ic_state == XLOG_STATE_ACTIVE) || (iclog->ic_state == XLOG_STATE_WANT_SYNC)); - cb->cb_next = 0; + cb->cb_next = NULL; *(iclog->ic_callback_tail) = cb; iclog->ic_callback_tail = &(cb->cb_next); } @@ -564,7 +562,7 @@ xfs_log_unmount_write(xfs_mount_t *mp) xlog_in_core_t *first_iclog; #endif xfs_log_iovec_t reg[1]; - xfs_log_ticket_t tic = 0; + xfs_log_ticket_t tic = NULL; xfs_lsn_t lsn; int error; SPLDECL(s); @@ -813,7 +811,7 @@ xfs_log_need_covered(xfs_mount_t *mp) xlog_t *log = mp->m_log; vfs_t *vfsp = XFS_MTOVFS(mp); - if (mp->m_frozen || XFS_FORCED_SHUTDOWN(mp) || + if (fs_frozen(vfsp) || XFS_FORCED_SHUTDOWN(mp) || (vfsp->vfs_flag & VFS_RDONLY)) return 0; @@ -1277,7 +1275,7 @@ xlog_commit_record(xfs_mount_t *mp, int error; xfs_log_iovec_t reg[1]; - reg[0].i_addr = 0; + reg[0].i_addr = NULL; reg[0].i_len = 0; ASSERT_ALWAYS(iclog); @@ -1413,9 +1411,13 @@ xlog_sync(xlog_t *log, xlog_pack_data(log, iclog); /* put cycle number in every block */ /* real byte length */ - INT_SET(iclog->ic_header.h_len, - ARCH_CONVERT, - iclog->ic_offset + iclog->ic_roundoff); + if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) { + INT_SET(iclog->ic_header.h_len, + ARCH_CONVERT, + iclog->ic_offset + iclog->ic_roundoff); + } else { + INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset); + } /* put ops count in correct order */ ops = iclog->ic_header.h_num_logops; @@ -1857,7 +1859,7 @@ xlog_state_clean_log(xlog_t *log) if (iclog->ic_state == XLOG_STATE_DIRTY) { iclog->ic_state = XLOG_STATE_ACTIVE; iclog->ic_offset = 0; - iclog->ic_callback = 0; /* don't need to free */ + iclog->ic_callback = NULL; /* don't need to free */ /* * If the number of ops in this iclog indicate it just * contains the dummy transaction, we can @@ -2080,7 +2082,7 @@ xlog_state_do_callback( while (cb != 0) { iclog->ic_callback_tail = &(iclog->ic_callback); - iclog->ic_callback = 0; + iclog->ic_callback = NULL; LOG_UNLOCK(log, s); /* perform callbacks in the order given */ @@ -3098,7 +3100,7 @@ xlog_state_ticket_alloc(xlog_t *log) log->l_ticket_cnt++; log->l_ticket_tcnt++; } - t_list->t_next = 0; + t_list->t_next = NULL; log->l_tail = t_list; LOG_UNLOCK(log, s); } /* xlog_state_ticket_alloc */ @@ -3126,7 +3128,7 @@ xlog_ticket_put(xlog_t *log, /* no need to clear fields */ #else /* When we debug, it is easier if tickets are cycled */ - ticket->t_next = 0; + ticket->t_next = NULL; if (log->l_tail != 0) { log->l_tail->t_next = ticket; } else { @@ -3242,33 +3244,6 @@ xlog_verify_dest_ptr(xlog_t *log, xlog_panic("xlog_verify_dest_ptr: invalid ptr"); } /* xlog_verify_dest_ptr */ - -#ifdef DEBUG -/* check split LR write */ -STATIC void -xlog_verify_disk_cycle_no(xlog_t *log, - xlog_in_core_t *iclog) -{ - xfs_buf_t *bp; - uint cycle_no; - xfs_caddr_t ptr; - xfs_daddr_t i; - - if (BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT) < 10) { - cycle_no = CYCLE_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT); - bp = xlog_get_bp(log, 1); - ASSERT(bp); - for (i = 0; i < BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT); i++) { - xlog_bread(log, i, 1, bp); - ptr = xlog_align(log, i, 1, bp); - if (GET_CYCLE(ptr, ARCH_CONVERT) != cycle_no) - xlog_warn("XFS: xlog_verify_disk_cycle_no: bad cycle no"); - } - xlog_put_bp(bp); - } -} /* xlog_verify_disk_cycle_no */ -#endif - STATIC void xlog_verify_grant_head(xlog_t *log, int equals) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_log_recover.c linux-2.4.28-pre3/fs/xfs/xfs_log_recover.c --- linux-2.4.27/fs/xfs/xfs_log_recover.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_log_recover.c 2004-09-10 19:36:45.000000000 +0000 @@ -2047,12 +2047,11 @@ xfs_qm_dqcheck( errs++; } - if (! errs) { + if (! errs && !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) { if (INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT) && INT_GET(ddq->d_bcount, ARCH_CONVERT) >= INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT)) { - if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT) && - !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) { + if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT)) { if (flags & XFS_QMOPT_DOWARN) cmn_err(CE_ALERT, "%s : Dquot ID 0x%x (0x%p) " @@ -2065,8 +2064,7 @@ xfs_qm_dqcheck( if (INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT) && INT_GET(ddq->d_icount, ARCH_CONVERT) >= INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT)) { - if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT) && - !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) { + if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT)) { if (flags & XFS_QMOPT_DOWARN) cmn_err(CE_ALERT, "%s : Dquot ID 0x%x (0x%p) " @@ -2076,6 +2074,19 @@ xfs_qm_dqcheck( errs++; } } + if (INT_GET(ddq->d_rtb_softlimit, ARCH_CONVERT) && + INT_GET(ddq->d_rtbcount, ARCH_CONVERT) >= + INT_GET(ddq->d_rtb_softlimit, ARCH_CONVERT)) { + if (INT_ISZERO(ddq->d_rtbtimer, ARCH_CONVERT)) { + if (flags & XFS_QMOPT_DOWARN) + cmn_err(CE_ALERT, + "%s : Dquot ID 0x%x (0x%p) " + "RTBLK TIMER NOT STARTED", + str, (int) + INT_GET(ddq->d_id, ARCH_CONVERT), ddq); + errs++; + } + } } if (!errs || !(flags & XFS_QMOPT_DQREPAIR)) @@ -2319,7 +2330,7 @@ xlog_recover_do_inode_trans( * invalidate the buffer when we write it out below. */ imap.im_blkno = 0; - xfs_imap(log->l_mp, 0, ino, &imap, 0); + xfs_imap(log->l_mp, NULL, ino, &imap, 0); } /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_mount.c linux-2.4.28-pre3/fs/xfs/xfs_mount.c --- linux-2.4.27/fs/xfs/xfs_mount.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_mount.c 2004-09-10 19:35:59.000000000 +0000 @@ -140,9 +140,6 @@ xfs_mount_init(void) */ xfs_trans_ail_init(mp); - /* Init freeze sync structures */ - spinlock_init(&mp->m_freeze_lock, "xfs_freeze"); - init_sv(&mp->m_wait_unfreeze, SV_DEFAULT, "xfs_freeze", 0); atomic_set(&mp->m_active_trans, 0); return mp; @@ -192,8 +189,6 @@ xfs_mount_free( VFS_REMOVEBHV(vfsp, &mp->m_bhv); } - spinlock_destroy(&mp->m_freeze_lock); - sv_destroy(&mp->m_wait_unfreeze); kmem_free(mp, sizeof(xfs_mount_t)); } @@ -283,17 +278,22 @@ xfs_mount_validate_sb( return XFS_ERROR(EFSCORRUPTED); } -#if !XFS_BIG_BLKNOS + ASSERT(PAGE_SHIFT >= sbp->sb_blocklog); + ASSERT(sbp->sb_blocklog >= BBSHIFT); + +#if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */ + if (unlikely( + (sbp->sb_dblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX || + (sbp->sb_rblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX)) { +#else /* Limited by UINT_MAX of sectors */ if (unlikely( - (sbp->sb_dblocks << (__uint64_t)(sbp->sb_blocklog - BBSHIFT)) - > UINT_MAX || - (sbp->sb_rblocks << (__uint64_t)(sbp->sb_blocklog - BBSHIFT)) - > UINT_MAX)) { + (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX || + (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) { +#endif cmn_err(CE_WARN, "XFS: File system is too large to be mounted on this system."); return XFS_ERROR(E2BIG); } -#endif if (unlikely(sbp->sb_inprogress)) { cmn_err(CE_WARN, "XFS: file system busy"); @@ -318,10 +318,10 @@ xfs_mount_validate_sb( return 0; } -void -xfs_initialize_perag(xfs_mount_t *mp, int agcount) +xfs_agnumber_t +xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount) { - int index, max_metadata; + xfs_agnumber_t index, max_metadata; xfs_perag_t *pag; xfs_agino_t agino; xfs_ino_t ino; @@ -377,7 +377,7 @@ xfs_initialize_perag(xfs_mount_t *mp, in pag->pagi_inodeok = 1; } } - mp->m_maxagi = index; + return index; } /* @@ -638,9 +638,8 @@ xfs_mountfs( xfs_buf_t *bp; xfs_sb_t *sbp = &(mp->m_sb); xfs_inode_t *rip; - vnode_t *rvp = 0; + vnode_t *rvp = NULL; int readio_log, writeio_log; - vmap_t vmap; xfs_daddr_t d; __uint64_t ret64; __int64_t update_flags; @@ -952,7 +951,7 @@ xfs_mountfs( mp->m_perag = kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP); - xfs_initialize_perag(mp, sbp->sb_agcount); + mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount); /* * log's mount-time initialization. Perform 1st part recovery if needed @@ -984,7 +983,6 @@ xfs_mountfs( ASSERT(rip != NULL); rvp = XFS_ITOV(rip); - VMAP(rvp, vmap); if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) { cmn_err(CE_WARN, "XFS: corrupted root inode"); @@ -1048,7 +1046,6 @@ xfs_mountfs( * Free up the root inode. */ VN_RELE(rvp); - vn_purge(rvp, &vmap); error3: xfs_log_unmount_dealloc(mp); error2: @@ -1582,59 +1579,3 @@ xfs_mount_log_sbunit( xfs_mod_sb(tp, fields); xfs_trans_commit(tp, 0, NULL); } - -/* Functions to lock access out of the filesystem for forced - * shutdown or snapshot. - */ - -void -xfs_start_freeze( - xfs_mount_t *mp, - int level) -{ - unsigned long s = mutex_spinlock(&mp->m_freeze_lock); - - mp->m_frozen = level; - mutex_spinunlock(&mp->m_freeze_lock, s); - - if (level == XFS_FREEZE_TRANS) { - while (atomic_read(&mp->m_active_trans) > 0) - delay(100); - } -} - -void -xfs_finish_freeze( - xfs_mount_t *mp) -{ - unsigned long s = mutex_spinlock(&mp->m_freeze_lock); - - if (mp->m_frozen) { - mp->m_frozen = 0; - sv_broadcast(&mp->m_wait_unfreeze); - } - - mutex_spinunlock(&mp->m_freeze_lock, s); -} - -void -xfs_check_frozen( - xfs_mount_t *mp, - bhv_desc_t *bdp, - int level) -{ - unsigned long s; - - if (mp->m_frozen) { - s = mutex_spinlock(&mp->m_freeze_lock); - - if (mp->m_frozen < level) { - mutex_spinunlock(&mp->m_freeze_lock, s); - } else { - sv_wait(&mp->m_wait_unfreeze, 0, &mp->m_freeze_lock, s); - } - } - - if (level == XFS_FREEZE_TRANS) - atomic_inc(&mp->m_active_trans); -} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_mount.h linux-2.4.28-pre3/fs/xfs/xfs_mount.h --- linux-2.4.27/fs/xfs/xfs_mount.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_mount.h 2004-09-10 19:32:45.000000000 +0000 @@ -382,10 +382,6 @@ typedef struct xfs_mount { struct xfs_dmops m_dm_ops; /* vector of DMI ops */ struct xfs_qmops m_qm_ops; /* vector of XQM ops */ struct xfs_ioops m_io_ops; /* vector of I/O ops */ - lock_t m_freeze_lock; /* Lock for m_frozen */ - uint m_frozen; /* FS frozen for shutdown or - * snapshot */ - sv_t m_wait_unfreeze;/* waiting to unfreeze */ atomic_t m_active_trans; /* number trans frozen */ } xfs_mount_t; @@ -555,20 +551,10 @@ extern int xfs_readsb(xfs_mount_t *mp); extern void xfs_freesb(xfs_mount_t *); extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); extern int xfs_syncsub(xfs_mount_t *, int, int, int *); -extern void xfs_initialize_perag(xfs_mount_t *, int); +extern xfs_agnumber_t xfs_initialize_perag(xfs_mount_t *, xfs_agnumber_t); extern void xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t, __int64_t); -/* - * Flags for freeze operations. - */ -#define XFS_FREEZE_WRITE 1 -#define XFS_FREEZE_TRANS 2 - -extern void xfs_start_freeze(xfs_mount_t *, int); -extern void xfs_finish_freeze(xfs_mount_t *); -extern void xfs_check_frozen(xfs_mount_t *, bhv_desc_t *, int); - extern struct vfsops xfs_vfsops; extern struct vnodeops xfs_vnodeops; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_quota.h linux-2.4.28-pre3/fs/xfs/xfs_quota.h --- linux-2.4.27/fs/xfs/xfs_quota.h 2004-04-14 13:05:40.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_quota.h 2004-09-10 19:34:52.000000000 +0000 @@ -309,23 +309,27 @@ typedef struct xfs_dqtrxops { } xfs_dqtrxops_t; #define XFS_DQTRXOP(mp, tp, op, args...) \ - ((mp)->m_qm_ops.xfs_dqtrxops ? \ - ((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0) + ((mp)->m_qm_ops.xfs_dqtrxops ? \ + ((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0) + +#define XFS_DQTRXOP_VOID(mp, tp, op, args...) \ + ((mp)->m_qm_ops.xfs_dqtrxops ? \ + ((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : (void)0) #define XFS_TRANS_DUP_DQINFO(mp, otp, ntp) \ - XFS_DQTRXOP(mp, otp, qo_dup_dqinfo, ntp) + XFS_DQTRXOP_VOID(mp, otp, qo_dup_dqinfo, ntp) #define XFS_TRANS_FREE_DQINFO(mp, tp) \ - XFS_DQTRXOP(mp, tp, qo_free_dqinfo) + XFS_DQTRXOP_VOID(mp, tp, qo_free_dqinfo) #define XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, field, delta) \ - XFS_DQTRXOP(mp, tp, qo_mod_dquot_byino, ip, field, delta) + XFS_DQTRXOP_VOID(mp, tp, qo_mod_dquot_byino, ip, field, delta) #define XFS_TRANS_APPLY_DQUOT_DELTAS(mp, tp) \ - XFS_DQTRXOP(mp, tp, qo_apply_dquot_deltas) + XFS_DQTRXOP_VOID(mp, tp, qo_apply_dquot_deltas) #define XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, fl) \ XFS_DQTRXOP(mp, tp, qo_reserve_quota_nblks, mp, ip, nblks, ninos, fl) #define XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, fl) \ XFS_DQTRXOP(mp, tp, qo_reserve_quota_bydquots, mp, ud, gd, nb, ni, fl) #define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \ - XFS_DQTRXOP(mp, tp, qo_unreserve_and_mod_dquots) + XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots) #define XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, nblks) \ XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_rtalloc.c linux-2.4.28-pre3/fs/xfs/xfs_rtalloc.c --- linux-2.4.27/fs/xfs/xfs_rtalloc.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_rtalloc.c 2004-09-10 19:33:27.000000000 +0000 @@ -2353,13 +2353,7 @@ xfs_rtmount_inodes( ASSERT(sbp->sb_rsumino != NULLFSINO); error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, &mp->m_rsumip, 0); if (error) { - vnode_t *rbmvp; /* vnode for bitmap file */ - vmap_t vmap; /* vmap to delete vnode */ - - rbmvp = XFS_ITOV(mp->m_rbmip); - VMAP(rbmvp, vmap); - VN_RELE(rbmvp); - vn_purge(rbmvp, &vmap); + VN_RELE(XFS_ITOV(mp->m_rbmip)); return error; } ASSERT(mp->m_rsumip != NULL); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_sb.h linux-2.4.28-pre3/fs/xfs/xfs_sb.h --- linux-2.4.27/fs/xfs/xfs_sb.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_sb.h 2004-09-10 19:35:32.000000000 +0000 @@ -250,9 +250,9 @@ int xfs_sb_good_version(xfs_sb_t *sbp); ((((sbp)->sb_versionnum >= XFS_SB_VERSION_1) && \ ((sbp)->sb_versionnum <= XFS_SB_VERSION_3)) || \ ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ - !(((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) && \ - ((sbp)->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \ - ((sbp)->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS)) + !(((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) || \ + (((sbp)->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \ + ((sbp)->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS))) #ifdef __KERNEL__ #define XFS_SB_GOOD_VERSION(sbp) \ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_trans.c linux-2.4.28-pre3/fs/xfs/xfs_trans.c --- linux-2.4.27/fs/xfs/xfs_trans.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_trans.c 2004-09-10 19:35:22.000000000 +0000 @@ -131,7 +131,9 @@ xfs_trans_alloc( xfs_mount_t *mp, uint type) { - xfs_check_frozen(mp, NULL, XFS_FREEZE_TRANS); + fs_check_frozen(XFS_MTOVFS(mp), SB_FREEZE_TRANS); + atomic_inc(&mp->m_active_trans); + return (_xfs_trans_alloc(mp, type)); } @@ -489,6 +491,9 @@ xfs_trans_apply_sb_deltas( if (tp->t_frextents_delta != 0) { INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_frextents_delta); } + if (tp->t_res_frextents_delta != 0) { + INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_res_frextents_delta); + } if (tp->t_dblocks_delta != 0) { INT_MOD(sbp->sb_dblocks, ARCH_CONVERT, tp->t_dblocks_delta); whole = 1; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_trans_item.c linux-2.4.28-pre3/fs/xfs/xfs_trans_item.c --- linux-2.4.27/fs/xfs/xfs_trans_item.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_trans_item.c 2004-09-10 19:36:44.000000000 +0000 @@ -290,7 +290,7 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs } ASSERT(0); /* NOTREACHED */ - return 0; /* keep gcc quite */ + return NULL; /* keep gcc quite */ } /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_types.h linux-2.4.28-pre3/fs/xfs/xfs_types.h --- linux-2.4.27/fs/xfs/xfs_types.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_types.h 2004-09-10 19:34:49.000000000 +0000 @@ -58,7 +58,7 @@ typedef enum { B_FALSE,B_TRUE } boolean_ typedef __int64_t prid_t; /* project ID */ typedef __uint32_t inst_t; /* an instruction */ -typedef __u64 xfs_off_t; +typedef __s64 xfs_off_t; /* type */ typedef __u64 xfs_ino_t; /* type */ typedef __s64 xfs_daddr_t; /* type */ typedef char * xfs_caddr_t; /* type */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_vfsops.c linux-2.4.28-pre3/fs/xfs/xfs_vfsops.c --- linux-2.4.27/fs/xfs/xfs_vfsops.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_vfsops.c 2004-09-10 19:35:35.000000000 +0000 @@ -431,6 +431,16 @@ xfs_mount( logdev = rtdev = NULL; /* + * Setup xfs_mount function vectors from available behaviors + */ + p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM); + mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub; + p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM); + mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub; + p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO); + mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs; + + /* * Open real time and log devices - order is important. */ if (args->logname[0]) { @@ -455,68 +465,73 @@ xfs_mount( } /* - * Setup xfs_mount function vectors from available behaviors - */ - p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM); - mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub; - p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM); - mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub; - p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO); - mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs; - - /* * Setup xfs_mount buffer target pointers */ + error = ENOMEM; mp->m_ddev_targp = xfs_alloc_buftarg(ddev); - if (rtdev) + if (!mp->m_ddev_targp) { + xfs_blkdev_put(logdev); + xfs_blkdev_put(rtdev); + return error; + } + if (rtdev) { mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev); + if (!mp->m_rtdev_targp) + goto error0; + } mp->m_logdev_targp = (logdev && logdev != ddev) ? xfs_alloc_buftarg(logdev) : mp->m_ddev_targp; + if (!mp->m_logdev_targp) + goto error0; /* * Setup flags based on mount(2) options and then the superblock */ error = xfs_start_flags(vfsp, args, mp); if (error) - goto error; + goto error1; error = xfs_readsb(mp); if (error) - goto error; + goto error1; error = xfs_finish_flags(vfsp, args, mp); - if (error) { - xfs_freesb(mp); - goto error; - } + if (error) + goto error2; /* * Setup xfs_mount buffer target pointers based on superblock */ - xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize, - mp->m_sb.sb_sectsize); - if (logdev && logdev != ddev) { + error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize, + mp->m_sb.sb_sectsize); + if (!error && logdev && logdev != ddev) { unsigned int log_sector_size = BBSIZE; if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb)) log_sector_size = mp->m_sb.sb_logsectsize; - xfs_setsize_buftarg(mp->m_logdev_targp, mp->m_sb.sb_blocksize, - log_sector_size); - } - if (rtdev) - xfs_setsize_buftarg(mp->m_rtdev_targp, mp->m_sb.sb_blocksize, - mp->m_sb.sb_blocksize); + error = xfs_setsize_buftarg(mp->m_logdev_targp, + mp->m_sb.sb_blocksize, + log_sector_size); + } + if (!error && rtdev) + error = xfs_setsize_buftarg(mp->m_rtdev_targp, + mp->m_sb.sb_blocksize, + mp->m_sb.sb_sectsize); + if (error) + goto error2; - if (!(error = XFS_IOINIT(vfsp, args, flags))) + error = XFS_IOINIT(vfsp, args, flags); + if (!error) return 0; - - error: +error2: + if (mp->m_sb_bp) + xfs_freesb(mp); +error1: xfs_binval(mp->m_ddev_targp); - if (logdev != NULL && logdev != ddev) { + if (logdev && logdev != ddev) xfs_binval(mp->m_logdev_targp); - } - if (rtdev != NULL) { + if (rtdev) xfs_binval(mp->m_rtdev_targp); - } - xfs_unmountfs_close(mp, NULL); +error0: + xfs_unmountfs_close(mp, credp); return error; } @@ -1508,7 +1523,10 @@ xfs_syncsub( * eventually kicked out of the cache. */ if (flags & SYNC_REFCACHE) { - xfs_refcache_purge_some(mp); + if (flags & SYNC_WAIT) + xfs_refcache_purge_mp(mp); + else + xfs_refcache_purge_some(mp); } /* @@ -1866,6 +1884,20 @@ xfs_showargs( return 0; } +STATIC void +xfs_freeze( + bhv_desc_t *bdp) +{ + xfs_mount_t *mp = XFS_BHVTOM(bdp); + + while (atomic_read(&mp->m_active_trans) > 0) + delay(100); + + /* Push the superblock and write an unmount record */ + xfs_log_unmount_write(mp); + xfs_unmountfs_writesb(mp); +} + vfsops_t xfs_vfsops = { BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS), @@ -1883,4 +1915,5 @@ vfsops_t xfs_vfsops = { .vfs_get_inode = xfs_get_inode, .vfs_init_vnode = xfs_initialize_vnode, .vfs_force_shutdown = xfs_do_force_shutdown, + .vfs_freeze = xfs_freeze, }; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_vnodeops.c linux-2.4.28-pre3/fs/xfs/xfs_vnodeops.c --- linux-2.4.27/fs/xfs/xfs_vnodeops.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/fs/xfs/xfs_vnodeops.c 2004-09-10 19:35:38.000000000 +0000 @@ -283,7 +283,7 @@ xfs_getattr( /* * xfs_setattr */ -STATIC int +int xfs_setattr( bhv_desc_t *bdp, vattr_t *vap, @@ -305,6 +305,7 @@ xfs_setattr( int mandlock_before, mandlock_after; struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; int file_owner; + int need_iolock = (flags & ATTR_DMI) == 0; vp = BHV_TO_VNODE(bdp); vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); @@ -406,7 +407,8 @@ xfs_setattr( goto error_return; } } - lock_flags |= XFS_IOLOCK_EXCL; + if (need_iolock) + lock_flags |= XFS_IOLOCK_EXCL; } xfs_ilock(ip, lock_flags); @@ -678,7 +680,8 @@ xfs_setattr( XFS_TRANS_PERM_LOG_RES, XFS_ITRUNCATE_LOG_COUNT))) { xfs_trans_cancel(tp, 0); - xfs_iunlock(ip, XFS_IOLOCK_EXCL); + if (need_iolock) + xfs_iunlock(ip, XFS_IOLOCK_EXCL); return code; } commit_flags = XFS_TRANS_RELEASE_LOG_RES; @@ -823,10 +826,15 @@ xfs_setattr( mp->m_sb.sb_blocklog; } if (mask & XFS_AT_XFLAGS) { - ip->i_d.di_flags = 0; - if (vap->va_xflags & XFS_XFLAG_REALTIME) { + /* can't set PREALLOC this way, just preserve it */ + ip->i_d.di_flags = + (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC); + if (vap->va_xflags & XFS_XFLAG_REALTIME && + (ip->i_d.di_mode & S_IFMT) == S_IFREG) { ip->i_d.di_flags |= XFS_DIFLAG_REALTIME; ip->i_iocore.io_flags |= XFS_IOCORE_RT; + } else { + ip->i_iocore.io_flags &= ~XFS_IOCORE_RT; } if (vap->va_xflags & XFS_XFLAG_IMMUTABLE) ip->i_d.di_flags |= XFS_DIFLAG_IMMUTABLE; @@ -838,7 +846,9 @@ xfs_setattr( ip->i_d.di_flags |= XFS_DIFLAG_NOATIME; if (vap->va_xflags & XFS_XFLAG_NODUMP) ip->i_d.di_flags |= XFS_DIFLAG_NODUMP; - /* can't set PREALLOC this way, just ignore it */ + if ((vap->va_xflags & XFS_XFLAG_RTINHERIT) && + (ip->i_d.di_mode & S_IFMT) == S_IFDIR) + ip->i_d.di_flags |= XFS_DIFLAG_RTINHERIT; } xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); timeflags |= XFS_ICHGTIME_CHG; @@ -1822,8 +1832,6 @@ xfs_lookup( } -#define XFS_CREATE_NEW_MAXTRIES 10000 - /* * xfs_create (create a new file). */ @@ -4292,6 +4300,7 @@ xfs_free_file_space( int rt; xfs_fileoff_t startoffset_fsb; xfs_trans_t *tp; + int need_iolock = (attr_flags & ATTR_DMI) == 0; vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); mp = ip->i_mount; @@ -4319,7 +4328,8 @@ xfs_free_file_space( return(error); } - xfs_ilock(ip, XFS_IOLOCK_EXCL); + if (need_iolock) + xfs_ilock(ip, XFS_IOLOCK_EXCL); rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog), (__uint8_t)NBPP); ilen = len + (offset & (rounding - 1)); @@ -4338,7 +4348,7 @@ xfs_free_file_space( error = xfs_bmapi(NULL, ip, startoffset_fsb, 1, 0, NULL, 0, &imap, &nimap, NULL); if (error) - return error; + goto out_unlock_iolock; ASSERT(nimap == 0 || nimap == 1); if (nimap && imap.br_startblock != HOLESTARTBLOCK) { xfs_daddr_t block; @@ -4353,7 +4363,7 @@ xfs_free_file_space( error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, 1, 0, NULL, 0, &imap, &nimap, NULL); if (error) - return error; + goto out_unlock_iolock; ASSERT(nimap == 0 || nimap == 1); if (nimap && imap.br_startblock != HOLESTARTBLOCK) { ASSERT(imap.br_startblock != DELAYSTARTBLOCK); @@ -4442,14 +4452,17 @@ xfs_free_file_space( xfs_iunlock(ip, XFS_ILOCK_EXCL); } - xfs_iunlock(ip, XFS_IOLOCK_EXCL); + out_unlock_iolock: + if (need_iolock) + xfs_iunlock(ip, XFS_IOLOCK_EXCL); return error; error0: xfs_bmap_cancel(&free_list); error1: xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); - xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); + xfs_iunlock(ip, need_iolock ? (XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL) : + XFS_ILOCK_EXCL); return error; } @@ -4606,20 +4619,21 @@ xfs_change_file_space( xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_ihold(tp, ip); - ip->i_d.di_mode &= ~S_ISUID; - - /* - * Note that we don't have to worry about mandatory - * file locking being disabled here because we only - * clear the S_ISGID bit if the Group execute bit is - * on, but if it was on then mandatory locking wouldn't - * have been enabled. - */ - if (ip->i_d.di_mode & S_IXGRP) - ip->i_d.di_mode &= ~S_ISGID; + if ((attr_flags & ATTR_DMI) == 0) { + ip->i_d.di_mode &= ~S_ISUID; - xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + /* + * Note that we don't have to worry about mandatory + * file locking being disabled here because we only + * clear the S_ISGID bit if the Group execute bit is + * on, but if it was on then mandatory locking wouldn't + * have been enabled. + */ + if (ip->i_d.di_mode & S_IXGRP) + ip->i_d.di_mode &= ~S_ISGID; + xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + } if (setprealloc) ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; else if (clrprealloc) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-i386/apic.h linux-2.4.28-pre3/include/asm-i386/apic.h --- linux-2.4.27/include/asm-i386/apic.h 2002-08-03 00:39:45.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-i386/apic.h 2004-09-10 19:37:14.000000000 +0000 @@ -77,7 +77,7 @@ extern void init_apic_mappings (void); extern void smp_local_timer_interrupt (struct pt_regs * regs); extern void setup_APIC_clocks (void); extern void setup_apic_nmi_watchdog (void); -extern inline void nmi_watchdog_tick (struct pt_regs * regs); +extern void nmi_watchdog_tick (struct pt_regs * regs); extern int APIC_init_uniprocessor (void); extern void disable_APIC_timer(void); extern void enable_APIC_timer(void); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-i386/rwsem.h linux-2.4.28-pre3/include/asm-i386/rwsem.h --- linux-2.4.27/include/asm-i386/rwsem.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-i386/rwsem.h 2004-09-10 19:34:24.000000000 +0000 @@ -113,8 +113,8 @@ LOCK_PREFIX " incl (%%eax)\n\t" /* " jmp 1b\n" LOCK_SECTION_END "# ending down_read\n\t" - : "+m"(sem->count) - : "a"(sem) + : "=m"(sem->count) + : "a"(sem), "m"(sem->count) : "memory", "cc"); } @@ -151,8 +151,8 @@ static inline void __down_write(struct r tmp = RWSEM_ACTIVE_WRITE_BIAS; __asm__ __volatile__( "# beginning down_write\n\t" -LOCK_PREFIX " xadd %0,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */ - " testl %0,%0\n\t" /* was the count 0 before? */ +LOCK_PREFIX " xadd %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */ + " testl %%edx,%%edx\n\t" /* was the count 0 before? */ " jnz 2f\n\t" /* jump if we weren't granted the lock */ "1:\n\t" LOCK_SECTION_START("") @@ -163,8 +163,8 @@ LOCK_PREFIX " xadd %0,(%%eax)\n\t" " jmp 1b\n" LOCK_SECTION_END "# ending down_write" - : "+d"(tmp), "+m"(sem->count) - : "a"(sem) + : "=m"(sem->count), "=d"(tmp) + : "a"(sem), "1"(tmp), "m"(sem->count) : "memory", "cc"); } @@ -202,8 +202,8 @@ LOCK_PREFIX " xadd %%edx,(%%eax)\n " jmp 1b\n" LOCK_SECTION_END "# ending __up_read\n" - : "+m"(sem->count), "+d"(tmp) - : "a"(sem) + : "=m"(sem->count), "=d"(tmp) + : "a"(sem), "1"(tmp), "m"(sem->count) : "memory", "cc"); } @@ -228,8 +228,8 @@ LOCK_PREFIX " xaddl %%edx,(%%eax)\n " jmp 1b\n" LOCK_SECTION_END "# ending __up_write\n" - : "+m"(sem->count) - : "a"(sem), "i"(-RWSEM_ACTIVE_WRITE_BIAS) + : "=m"(sem->count) + : "a"(sem), "i"(-RWSEM_ACTIVE_WRITE_BIAS), "m"(sem->count) : "memory", "cc", "edx"); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-i386/smp.h linux-2.4.28-pre3/include/asm-i386/smp.h --- linux-2.4.27/include/asm-i386/smp.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-i386/smp.h 2004-09-10 19:32:11.000000000 +0000 @@ -39,7 +39,7 @@ extern int cpu_sibling_map[]; extern void smp_flush_tlb(void); extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs); -extern void smp_send_reschedule(int cpu); +extern void fastcall smp_send_reschedule(int cpu); extern void smp_invalidate_rcv(void); /* Process an NMI */ extern void (*mtrr_hook) (void); extern void zap_low_mappings (void); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-i386/smpboot.h linux-2.4.28-pre3/include/asm-i386/smpboot.h --- linux-2.4.27/include/asm-i386/smpboot.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-i386/smpboot.h 2004-09-10 19:36:56.000000000 +0000 @@ -130,8 +130,8 @@ static inline int target_cpus(void) cpu = (cpu+1)%smp_num_cpus; return cpu_to_physical_apicid(cpu); default: + return cpu_online_map; } - return cpu_online_map; } #else #define target_cpus() (cpu_online_map) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-i386/unistd.h linux-2.4.28-pre3/include/asm-i386/unistd.h --- linux-2.4.27/include/asm-i386/unistd.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-i386/unistd.h 2004-09-10 19:35:39.000000000 +0000 @@ -372,7 +372,7 @@ static inline _syscall1(int,dup,int,fd) static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) static inline _syscall3(int,open,const char *,file,int,flag,int,mode) static inline _syscall1(int,close,int,fd) -static inline _syscall1(int,_exit,int,exitcode) +static inline _syscall1(void,_exit,int,exitcode) static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) static inline _syscall1(int,delete_module,const char *,name) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-ppc/unistd.h linux-2.4.28-pre3/include/asm-ppc/unistd.h --- linux-2.4.27/include/asm-ppc/unistd.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-ppc/unistd.h 2004-09-10 19:33:01.000000000 +0000 @@ -382,7 +382,7 @@ static inline _syscall1(int,dup,int,fd) static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) static inline _syscall3(int,open,const char *,file,int,flag,int,mode) static inline _syscall1(int,close,int,fd) -static inline _syscall1(int,_exit,int,exitcode) +static inline _syscall1(void,_exit,int,exitcode) static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) static inline _syscall1(int,delete_module,const char *,name) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/kmap_types.h linux-2.4.28-pre3/include/asm-s390/kmap_types.h --- linux-2.4.27/include/asm-s390/kmap_types.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390/kmap_types.h 2004-09-10 19:33:03.000000000 +0000 @@ -0,0 +1,16 @@ +#ifndef _ASM_KMAP_TYPES_H +#define _ASM_KMAP_TYPES_H + +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BH_IRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_TYPE_NR +}; + +#endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/lowcore.h linux-2.4.28-pre3/include/asm-s390/lowcore.h --- linux-2.4.27/include/asm-s390/lowcore.h 2002-08-03 00:39:45.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390/lowcore.h 2004-09-10 19:34:47.000000000 +0000 @@ -47,6 +47,7 @@ #define __LC_IPLDEV 0xC7C #define __LC_JIFFY_TIMER 0xC80 +#define __LC_INT_CLOCK 0xC88 #define __LC_PANIC_MAGIC 0xE00 @@ -165,8 +166,9 @@ struct _lowcore /* SMP info area: defined by DJB */ __u64 jiffy_timer; /* 0xc80 */ - atomic_t ext_call_fast; /* 0xc88 */ - __u8 pad11[0xe00-0xc8c]; /* 0xc8c */ + __u64 int_clock; /* 0xc88 */ + atomic_t ext_call_fast; /* 0xc90 */ + __u8 pad11[0xe00-0xc94]; /* 0xc94 */ /* 0xe00 is used as indicator for dump tools */ /* whether the kernel died with panic() or not */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/pgtable.h linux-2.4.28-pre3/include/asm-s390/pgtable.h --- linux-2.4.27/include/asm-s390/pgtable.h 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390/pgtable.h 2004-09-10 19:36:19.000000000 +0000 @@ -426,9 +426,12 @@ static inline pte_t mk_pte_phys(unsigned __pte; \ }) -#define arch_set_page_uptodate(__page) \ +#define SetPageUptodate(_page) \ do { \ - asm volatile ("sske %0,%1" : : "d" (get_storage_key()), \ + struct page *__page = (_page); \ + if (!test_and_set_bit(PG_uptodate, &__page->flags)) \ + asm volatile ("sske %0,%1" \ + : : "d" (get_storage_key()), \ "a" (__pa((__page-mem_map) << PAGE_SHIFT)));\ } while (0) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/processor.h linux-2.4.28-pre3/include/asm-s390/processor.h --- linux-2.4.27/include/asm-s390/processor.h 2003-06-13 14:51:38.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390/processor.h 2004-09-10 19:34:46.000000000 +0000 @@ -50,6 +50,8 @@ struct cpuinfo_S390 extern void print_cpu_info(struct cpuinfo_S390 *); +extern void show_trace(unsigned long* esp); + /* Lazy FPU handling on uni-processor */ extern struct task_struct *last_task_used_math; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/qdio.h linux-2.4.28-pre3/include/asm-s390/qdio.h --- linux-2.4.27/include/asm-s390/qdio.h 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390/qdio.h 2004-09-10 19:36:38.000000000 +0000 @@ -11,7 +11,7 @@ #ifndef __QDIO_H__ #define __QDIO_H__ -#define VERSION_QDIO_H "$Revision: 1.66 $" +#define VERSION_QDIO_H "$Revision: 1.66.4.4 $" /* note, that most of the typedef's are from ingo. */ @@ -42,11 +42,18 @@ #define QDIO_MAX_ELEMENTS_PER_BUFFER 16 #define SBAL_SIZE 256 -#define IQDIO_FILL_LEVEL_TO_POLL (QDIO_MAX_BUFFERS_PER_Q*4/3) +/* unfortunately this can't be (QDIO_MAX_BUFFERS_PER_Q*4/3) or so -- as + * we never know, whether we'll get initiative again, e.g. to give the + * transmit skb's back to the stack, however the stack may be waiting for + * them... therefore we define 4 as threshold to start polling (which + * will stop as soon as the asynchronous queue catches up) + * btw, this only applies to the asynchronous HiperSockets queue */ +#define IQDIO_FILL_LEVEL_TO_POLL 4 #define TIQDIO_THININT_ISC 3 #define TIQDIO_DELAY_TARGET 0 -#define QDIO_BUSY_BIT_PATIENCE 2000 /* in microsecs */ +#define QDIO_BUSY_BIT_PATIENCE 100 /* in microsecs */ +#define QDIO_BUSY_BIT_GIVE_UP 10000000 /* 10 seconds */ #define IQDIO_GLOBAL_LAPS 2 /* GLOBAL_LAPS are not used as we */ #define IQDIO_GLOBAL_LAPS_INT 1 /* dont global summary */ #define IQDIO_LOCAL_LAPS 4 @@ -612,6 +619,8 @@ typedef struct _slsb { typedef struct qdio_q_t { volatile slsb_t slsb; + char unused[QDIO_MAX_BUFFERS_PER_Q]; + __u32 * volatile dev_st_chg_ind; int is_input_q; @@ -697,7 +706,9 @@ typedef struct qdio_q_t { int last_transfer_index; */ __u64 last_transfer_time; + __u64 busy_start; } timing; + atomic_t busy_siga_counter; unsigned int queue_type; } __attribute__ ((aligned(256))) qdio_q_t; @@ -713,7 +724,7 @@ typedef struct qdio_irq_t { unsigned int sync_done_on_outb_pcis; unsigned int state; - spinlock_t setting_up_lock; + struct semaphore setting_up_lock; unsigned int no_input_qs; unsigned int no_output_qs; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/sigp.h linux-2.4.28-pre3/include/asm-s390/sigp.h --- linux-2.4.27/include/asm-s390/sigp.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390/sigp.h 2004-09-10 19:34:58.000000000 +0000 @@ -106,7 +106,7 @@ signal_processor_p(__u32 parameter,__u16 * Signal processor with parameter and return status */ extern __inline__ sigp_ccode -signal_processor_ps(__u32 *statusptr, __u32 parameter, +signal_processor_ps(unsigned long *statusptr, __u32 parameter, __u16 cpu_addr, sigp_order_code order_code) { sigp_ccode ccode; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/smp.h linux-2.4.28-pre3/include/asm-s390/smp.h --- linux-2.4.27/include/asm-s390/smp.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390/smp.h 2004-09-10 19:34:54.000000000 +0000 @@ -26,6 +26,9 @@ typedef struct __u16 cpu; } sigp_info; +extern int smp_call_function_on(void (*func) (void *info), void *info, + int nonatomic, int wait, int cpu); + extern unsigned long cpu_online_map; #define NO_PROC_ID 0xFF /* No processor magic marker */ @@ -46,23 +49,28 @@ extern unsigned long cpu_online_map; extern __inline__ int cpu_logical_map(int cpu) { - return cpu; + return cpu; } extern __inline__ int cpu_number_map(int cpu) { - return cpu; + return cpu; } extern __inline__ __u16 hard_smp_processor_id(void) { - __u16 cpu_address; + __u16 cpu_address; - __asm__ ("stap %0\n" : "=m" (cpu_address)); - return cpu_address; + __asm__ ("stap %0\n" : "=m" (cpu_address)); + return cpu_address; } #define cpu_logical_map(cpu) (cpu) #endif + +#ifndef CONFIG_SMP +#define smp_call_function_on(func,info,nonatomic,wait,cpu) ({ 0; }) +#endif + #endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/kmap_types.h linux-2.4.28-pre3/include/asm-s390x/kmap_types.h --- linux-2.4.27/include/asm-s390x/kmap_types.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390x/kmap_types.h 2004-09-10 19:32:00.000000000 +0000 @@ -0,0 +1,16 @@ +#ifndef _ASM_KMAP_TYPES_H +#define _ASM_KMAP_TYPES_H + +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BH_IRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_TYPE_NR +}; + +#endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/lowcore.h linux-2.4.28-pre3/include/asm-s390x/lowcore.h --- linux-2.4.27/include/asm-s390x/lowcore.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390x/lowcore.h 2004-09-10 19:36:12.000000000 +0000 @@ -48,6 +48,7 @@ #define __LC_IPLDEV 0xDB8 #define __LC_JIFFY_TIMER 0xDC0 +#define __LC_INT_CLOCK 0xDC8 #define __LC_PANIC_MAGIC 0xE00 @@ -164,8 +165,9 @@ struct _lowcore /* SMP info area: defined by DJB */ __u64 jiffy_timer; /* 0xdc0 */ - __u64 ext_call_fast; /* 0xdc8 */ - __u8 pad12[0xe00-0xdd0]; /* 0xdd0 */ + __u64 int_clock; /* 0xdc8 */ + __u64 ext_call_fast; /* 0xdd0 */ + __u8 pad12[0xe00-0xdd8]; /* 0xdd8 */ /* 0xe00 is used as indicator for dump tools */ /* whether the kernel died with panic() or not */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/pgtable.h linux-2.4.28-pre3/include/asm-s390x/pgtable.h --- linux-2.4.27/include/asm-s390x/pgtable.h 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390x/pgtable.h 2004-09-10 19:34:20.000000000 +0000 @@ -484,9 +484,11 @@ extern inline pte_t mk_pte_phys(unsigned __pte; \ }) -#define arch_set_page_uptodate(__page) \ +#define SetPageUptodate(_page) \ do { \ - asm volatile ("sske %0,%1" : : "d" (0), \ + struct page *__page = (_page); \ + if (!test_and_set_bit(PG_uptodate, &__page->flags)) \ + asm volatile ("sske %0,%1" : : "d" (0), \ "a" (__pa((__page-mem_map) << PAGE_SHIFT)));\ } while (0) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/processor.h linux-2.4.28-pre3/include/asm-s390x/processor.h --- linux-2.4.27/include/asm-s390x/processor.h 2003-06-13 14:51:38.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390x/processor.h 2004-09-10 19:36:29.000000000 +0000 @@ -52,6 +52,8 @@ struct cpuinfo_S390 extern void print_cpu_info(struct cpuinfo_S390 *); +extern void show_trace(unsigned long* esp); + /* Lazy FPU handling on uni-processor */ extern struct task_struct *last_task_used_math; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/qdio.h linux-2.4.28-pre3/include/asm-s390x/qdio.h --- linux-2.4.27/include/asm-s390x/qdio.h 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390x/qdio.h 2004-09-10 19:34:58.000000000 +0000 @@ -11,7 +11,7 @@ #ifndef __QDIO_H__ #define __QDIO_H__ -#define VERSION_QDIO_H "$Revision: 1.57 $" +#define VERSION_QDIO_H "$Revision: 1.57.4.4 $" /* note, that most of the typedef's are from ingo. */ @@ -42,11 +42,18 @@ #define QDIO_MAX_ELEMENTS_PER_BUFFER 16 #define SBAL_SIZE 256 -#define IQDIO_FILL_LEVEL_TO_POLL (QDIO_MAX_BUFFERS_PER_Q*4/3) +/* unfortunately this can't be (QDIO_MAX_BUFFERS_PER_Q*4/3) or so -- as + * we never know, whether we'll get initiative again, e.g. to give the + * transmit skb's back to the stack, however the stack may be waiting for + * them... therefore we define 4 as threshold to start polling (which + * will stop as soon as the asynchronous queue catches up) + * btw, this only applies to the asynchronous HiperSockets queue */ +#define IQDIO_FILL_LEVEL_TO_POLL 4 #define TIQDIO_THININT_ISC 3 #define TIQDIO_DELAY_TARGET 0 -#define QDIO_BUSY_BIT_PATIENCE 2000 /* in microsecs */ +#define QDIO_BUSY_BIT_PATIENCE 100 /* in microsecs */ +#define QDIO_BUSY_BIT_GIVE_UP 10000000 /* 10 seconds */ #define IQDIO_GLOBAL_LAPS 2 /* GLOBAL_LAPS are not used as we */ #define IQDIO_GLOBAL_LAPS_INT 1 /* dont global summary */ #define IQDIO_LOCAL_LAPS 4 @@ -612,6 +619,8 @@ typedef struct _slsb { typedef struct qdio_q_t { volatile slsb_t slsb; + char unused[QDIO_MAX_BUFFERS_PER_Q]; + __u32 * volatile dev_st_chg_ind; int is_input_q; @@ -697,7 +706,9 @@ typedef struct qdio_q_t { int last_transfer_index; */ __u64 last_transfer_time; + __u64 busy_start; } timing; + atomic_t busy_siga_counter; unsigned int queue_type; } __attribute__ ((aligned(256))) qdio_q_t; @@ -713,7 +724,7 @@ typedef struct qdio_irq_t { unsigned int sync_done_on_outb_pcis; unsigned int state; - spinlock_t setting_up_lock; + struct semaphore setting_up_lock; unsigned int no_input_qs; unsigned int no_output_qs; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/siginfo.h linux-2.4.28-pre3/include/asm-s390x/siginfo.h --- linux-2.4.27/include/asm-s390x/siginfo.h 2002-08-03 00:39:45.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390x/siginfo.h 2004-09-10 19:36:45.000000000 +0000 @@ -19,7 +19,7 @@ typedef union sigval { } sigval_t; #define SI_MAX_SIZE 128 -#define SI_PAD_SIZE ((SI_MAX_SIZE/sizeof(int)) - 3) +#define SI_PAD_SIZE ((SI_MAX_SIZE/sizeof(int)) - 4) typedef struct siginfo { int si_signo; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/sigp.h linux-2.4.28-pre3/include/asm-s390x/sigp.h --- linux-2.4.27/include/asm-s390x/sigp.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390x/sigp.h 2004-09-10 19:34:24.000000000 +0000 @@ -107,7 +107,7 @@ signal_processor_p(__u64 parameter,__u16 * Signal processor with parameter and return status */ extern __inline__ sigp_ccode -signal_processor_ps(__u32 *statusptr, __u64 parameter, +signal_processor_ps(unsigned long *statusptr, __u64 parameter, __u16 cpu_addr, sigp_order_code order_code) { sigp_ccode ccode; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/smp.h linux-2.4.28-pre3/include/asm-s390x/smp.h --- linux-2.4.27/include/asm-s390x/smp.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-s390x/smp.h 2004-09-10 19:34:49.000000000 +0000 @@ -26,6 +26,9 @@ typedef struct __u16 cpu; } sigp_info; +extern int smp_call_function_on(void (*func) (void *info), void *info, + int nonatomic, int wait, int cpu); + extern unsigned long cpu_online_map; #define NO_PROC_ID 0xFF /* No processor magic marker */ @@ -65,4 +68,9 @@ extern __inline__ __u16 hard_smp_process #define cpu_logical_map(cpu) (cpu) #endif + +#ifndef CONFIG_SMP +#define smp_call_function_on(func,info,nonatomic,wait,cpu) ({ 0; }) +#endif + #endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc/sigcontext.h linux-2.4.28-pre3/include/asm-sparc/sigcontext.h --- linux-2.4.27/include/asm-sparc/sigcontext.h 1999-09-08 18:14:32.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-sparc/sigcontext.h 2004-09-10 19:33:19.000000000 +0000 @@ -57,20 +57,6 @@ typedef struct { } si_fpqueue [16]; } __siginfo_fpu_t; -#ifdef __KERNEL__ - -/* This magic should be in g_upper[0] for all upper parts - to be valid. - This is generated by sparc64 only, but for 32bit processes, - so we define it here as well. */ -#define SIGINFO_EXTRA_V8PLUS_MAGIC 0x130e269 -typedef struct { - unsigned int g_upper[8]; - unsigned int o_upper[8]; -} siginfo_extra_v8plus_t; - -#endif - #endif /* !(__ASSEMBLY__) */ #endif /* !(__SPARC_SIGCONTEXT_H) */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/asi.h linux-2.4.28-pre3/include/asm-sparc64/asi.h --- linux-2.4.27/include/asm-sparc64/asi.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-sparc64/asi.h 2004-09-10 19:33:16.000000000 +0000 @@ -8,125 +8,138 @@ */ /* V9 Architecture mandary ASIs. */ -#define ASI_N 0x04 /* Nucleus */ -#define ASI_NL 0x0c /* Nucleus, little endian */ -#define ASI_AIUP 0x10 /* Primary, user */ -#define ASI_AIUS 0x11 /* Secondary, user */ -#define ASI_AIUPL 0x18 /* Primary, user, little endian */ -#define ASI_AIUSL 0x19 /* Secondary, user, little endian */ -#define ASI_P 0x80 /* Primary, implicit */ -#define ASI_S 0x81 /* Secondary, implicit */ -#define ASI_PNF 0x82 /* Primary, no fault */ -#define ASI_SNF 0x83 /* Secondary, no fault */ -#define ASI_PL 0x88 /* Primary, implicit, little endian */ -#define ASI_SL 0x89 /* Secondary, implicit, little endian */ -#define ASI_PNFL 0x8a /* Primary, no fault, little endian */ -#define ASI_SNFL 0x8b /* Secondary, no fault, little endian */ +#define ASI_N 0x04 /* Nucleus */ +#define ASI_NL 0x0c /* Nucleus, little endian */ +#define ASI_AIUP 0x10 /* Primary, user */ +#define ASI_AIUS 0x11 /* Secondary, user */ +#define ASI_AIUPL 0x18 /* Primary, user, little endian */ +#define ASI_AIUSL 0x19 /* Secondary, user, little endian */ +#define ASI_P 0x80 /* Primary, implicit */ +#define ASI_S 0x81 /* Secondary, implicit */ +#define ASI_PNF 0x82 /* Primary, no fault */ +#define ASI_SNF 0x83 /* Secondary, no fault */ +#define ASI_PL 0x88 /* Primary, implicit, l-endian */ +#define ASI_SL 0x89 /* Secondary, implicit, l-endian */ +#define ASI_PNFL 0x8a /* Primary, no fault, l-endian */ +#define ASI_SNFL 0x8b /* Secondary, no fault, l-endian */ /* SpitFire and later extended ASIs. The "(III)" marker designates - * UltraSparc-III specific ASIs. + * UltraSparc-III and later specific ASIs. The "(CMT)" marker designates + * Chip Multi Threading specific ASIs. */ -#define ASI_PHYS_USE_EC 0x14 /* PADDR, E-cachable */ -#define ASI_PHYS_BYPASS_EC_E 0x15 /* PADDR, E-bit */ -#define ASI_PHYS_USE_EC_L 0x1c /* PADDR, E-cachable, little endian */ -#define ASI_PHYS_BYPASS_EC_E_L 0x1d /* PADDR, E-bit, little endian */ -#define ASI_NUCLEUS_QUAD_LDD 0x24 /* Cachable, qword load */ -#define ASI_NUCLEUS_QUAD_LDD_L 0x2c /* Cachable, qword load, little endian */ -#define ASI_PCACHE_DATA_STATUS 0x30 /* (III) PCache data status RAM diag */ -#define ASI_PCACHE_DATA 0x31 /* (III) PCache data RAM diag */ -#define ASI_PCACHE_TAG 0x32 /* (III) PCache tag RAM diag */ -#define ASI_PCACHE_SNOOP_TAG 0x33 /* (III) PCache snoop tag RAM diag */ -#define ASI_QUAD_LDD_PHYS 0x34 /* (III+) PADDR, qword load */ -#define ASI_WCACHE_VALID_BITS 0x38 /* (III) WCache Valid Bits diag */ -#define ASI_WCACHE_DATA 0x39 /* (III) WCache data RAM diag */ -#define ASI_WCACHE_TAG 0x3a /* (III) WCache tag RAM diag */ -#define ASI_WCACHE_SNOOP_TAG 0x3b /* (III) WCache snoop tag RAM diag */ -#define ASI_QUAD_LDD_PHYS_L 0x3c /* (III+) PADDR, qword load, little endian */ -#define ASI_SRAM_FAST_INIT 0x40 /* (III+) Fast SRAM init */ -#define ASI_DCACHE_INVALIDATE 0x42 /* (III) DCache Invalidate diag */ -#define ASI_DCACHE_UTAG 0x43 /* (III) DCache uTag diag */ -#define ASI_DCACHE_SNOOP_TAG 0x44 /* (III) DCache snoop tag RAM diag */ -#define ASI_LSU_CONTROL 0x45 /* Load-store control unit */ -#define ASI_DCU_CONTROL_REG 0x45 /* (III) DCache Unit Control Register */ -#define ASI_DCACHE_DATA 0x46 /* Data cache data-ram diag access */ -#define ASI_DCACHE_TAG 0x47 /* Data cache tag/valid ram diag access */ -#define ASI_INTR_DISPATCH_STAT 0x48 /* IRQ vector dispatch status */ -#define ASI_INTR_RECEIVE 0x49 /* IRQ vector receive status */ -#define ASI_UPA_CONFIG 0x4a /* UPA config space */ -#define ASI_JBUS_CONFIG 0x4a /* (IIIi) JBUS Config Register */ -#define ASI_SAFARI_CONFIG 0x4a /* (III) Safari Config Register */ -#define ASI_SAFARI_ADDRESS 0x4a /* (III) Safari Address Register */ -#define ASI_ESTATE_ERROR_EN 0x4b /* E-cache error enable space */ -#define ASI_AFSR 0x4c /* Async fault status register */ -#define ASI_AFAR 0x4d /* Async fault address register */ -#define ASI_EC_TAG_DATA 0x4e /* E-cache tag/valid ram diag access */ -#define ASI_IMMU 0x50 /* Insn-MMU main register space */ -#define ASI_IMMU_TSB_8KB_PTR 0x51 /* Insn-MMU 8KB TSB pointer register */ -#define ASI_IMMU_TSB_64KB_PTR 0x52 /* Insn-MMU 64KB TSB pointer register */ -#define ASI_ITLB_DATA_IN 0x54 /* Insn-MMU TLB data in register */ -#define ASI_ITLB_DATA_ACCESS 0x55 /* Insn-MMU TLB data access register */ -#define ASI_ITLB_TAG_READ 0x56 /* Insn-MMU TLB tag read register */ -#define ASI_IMMU_DEMAP 0x57 /* Insn-MMU TLB demap */ -#define ASI_DMMU 0x58 /* Data-MMU main register space */ -#define ASI_DMMU_TSB_8KB_PTR 0x59 /* Data-MMU 8KB TSB pointer register */ -#define ASI_DMMU_TSB_64KB_PTR 0x5a /* Data-MMU 16KB TSB pointer register */ -#define ASI_DMMU_TSB_DIRECT_PTR 0x5b /* Data-MMU TSB direct pointer register */ -#define ASI_DTLB_DATA_IN 0x5c /* Data-MMU TLB data in register */ -#define ASI_DTLB_DATA_ACCESS 0x5d /* Data-MMU TLB data access register */ -#define ASI_DTLB_TAG_READ 0x5e /* Data-MMU TLB tag read register */ -#define ASI_DMMU_DEMAP 0x5f /* Data-MMU TLB demap */ -#define ASI_IIU_INST_TRAP 0x60 /* (III) Instruction Breakpoint register */ -#define ASI_IC_INSTR 0x66 /* Insn cache instrucion ram diag access */ -#define ASI_IC_TAG 0x67 /* Insn cache tag/valid ram diag access */ -#define ASI_IC_STAG 0x68 /* (III) Insn cache snoop tag ram diag */ -#define ASI_IC_PRE_DECODE 0x6e /* Insn cache pre-decode ram diag access */ -#define ASI_IC_NEXT_FIELD 0x6f /* Insn cache next-field ram diag access */ -#define ASI_BRPRED_ARRAY 0x6f /* (III) Branch Prediction RAM diag */ -#define ASI_BLK_AIUP 0x70 /* Primary, user, block load/store */ -#define ASI_BLK_AIUS 0x71 /* Secondary, user, block load/store */ -#define ASI_MCU_CTRL_REG 0x72 /* (III) Memory controller registers */ -#define ASI_EC_DATA 0x74 /* (III) E-cache data staging register */ -#define ASI_EC_CTRL 0x75 /* (III) E-cache control register */ -#define ASI_EC_W 0x76 /* E-cache diag write access */ -#define ASI_UDB_ERROR_W 0x77 /* External UDB error registers write */ -#define ASI_UDB_CONTROL_W 0x77 /* External UDB control registers write */ -#define ASI_INTR_W 0x77 /* IRQ vector dispatch write */ -#define ASI_INTR_DATAN_W 0x77 /* (III) Outgoing irq vector data reg N */ -#define ASI_INTR_DISPATCH_W 0x77 /* (III) Interrupt vector dispatch */ -#define ASI_BLK_AIUPL 0x78 /* Primary, user, little, blk ld/st */ -#define ASI_BLK_AIUSL 0x79 /* Secondary, user, little, blk ld/st */ -#define ASI_EC_R 0x7e /* E-cache diag read access */ -#define ASI_UDBH_ERROR_R 0x7f /* External UDB error registers read hi */ -#define ASI_UDBL_ERROR_R 0x7f /* External UDB error registers read low */ -#define ASI_UDBH_CONTROL_R 0x7f /* External UDB control registers read hi */ -#define ASI_UDBL_CONTROL_R 0x7f /* External UDB control registers read low */ -#define ASI_INTR_R 0x7f /* IRQ vector dispatch read */ -#define ASI_INTR_DATAN_R 0x7f /* (III) Incoming irq vector data reg N */ -#define ASI_PST8_P 0xc0 /* Primary, 8 8-bit, partial */ -#define ASI_PST8_S 0xc1 /* Secondary, 8 8-bit, partial */ -#define ASI_PST16_P 0xc2 /* Primary, 4 16-bit, partial */ -#define ASI_PST16_S 0xc3 /* Seconary, 4 16-bit, partial */ -#define ASI_PST32_P 0xc4 /* Primary, 2 32-bit, partial */ -#define ASI_PST32_S 0xc5 /* Secondary, 2 32-bit, partial */ -#define ASI_PST8_PL 0xc8 /* Primary, 8 8-bit, partial, little */ -#define ASI_PST8_SL 0xc9 /* Secondary, 8 8-bit, partial, little */ -#define ASI_PST16_PL 0xca /* Primary, 4 16-bit, partial, little */ -#define ASI_PST16_SL 0xcb /* Seconary, 4 16-bit, partial, little */ -#define ASI_PST32_PL 0xcc /* Primary, 2 32-bit, partial, little */ -#define ASI_PST32_SL 0xcd /* Secondary, 2 32-bit, partial, little */ -#define ASI_FL8_P 0xd0 /* Primary, 1 8-bit, fpu ld/st */ -#define ASI_FL8_S 0xd1 /* Secondary, 1 8-bit, fpu ld/st */ -#define ASI_FL16_P 0xd2 /* Primary, 1 16-bit, fpu ld/st */ -#define ASI_FL16_S 0xd3 /* Secondary, 1 16-bit, fpu ld/st */ -#define ASI_FL8_PL 0xd8 /* Primary, 1 8-bit, fpu ld/st, little */ -#define ASI_FL8_SL 0xd9 /* Secondary, 1 8-bit, fpu ld/st, little */ -#define ASI_FL16_PL 0xda /* Primary, 1 16-bit, fpu ld/st, little */ -#define ASI_FL16_SL 0xdb /* Secondary, 1 16-bit, fpu ld/st, little */ -#define ASI_BLK_COMMIT_P 0xe0 /* Primary, blk store commit */ -#define ASI_BLK_COMMIT_S 0xe1 /* Secondary, blk store commit */ -#define ASI_BLK_P 0xf0 /* Primary, blk ld/st */ -#define ASI_BLK_S 0xf1 /* Secondary, blk ld/st */ -#define ASI_BLK_PL 0xf8 /* Primary, blk ld/st, little */ -#define ASI_BLK_SL 0xf9 /* Secondary, blk ld/st, little */ +#define ASI_PHYS_USE_EC 0x14 /* PADDR, E-cachable */ +#define ASI_PHYS_BYPASS_EC_E 0x15 /* PADDR, E-bit */ +#define ASI_PHYS_USE_EC_L 0x1c /* PADDR, E-cachable, little endian*/ +#define ASI_PHYS_BYPASS_EC_E_L 0x1d /* PADDR, E-bit, little endian */ +#define ASI_NUCLEUS_QUAD_LDD 0x24 /* Cachable, qword load */ +#define ASI_NUCLEUS_QUAD_LDD_L 0x2c /* Cachable, qword load, l-endian */ +#define ASI_PCACHE_DATA_STATUS 0x30 /* (III) PCache data stat RAM diag */ +#define ASI_PCACHE_DATA 0x31 /* (III) PCache data RAM diag */ +#define ASI_PCACHE_TAG 0x32 /* (III) PCache tag RAM diag */ +#define ASI_PCACHE_SNOOP_TAG 0x33 /* (III) PCache snoop tag RAM diag */ +#define ASI_QUAD_LDD_PHYS 0x34 /* (III+) PADDR, qword load */ +#define ASI_WCACHE_VALID_BITS 0x38 /* (III) WCache Valid Bits diag */ +#define ASI_WCACHE_DATA 0x39 /* (III) WCache data RAM diag */ +#define ASI_WCACHE_TAG 0x3a /* (III) WCache tag RAM diag */ +#define ASI_WCACHE_SNOOP_TAG 0x3b /* (III) WCache snoop tag RAM diag */ +#define ASI_QUAD_LDD_PHYS_L 0x3c /* (III+) PADDR, qw-load, l-endian */ +#define ASI_SRAM_FAST_INIT 0x40 /* (III+) Fast SRAM init */ +#define ASI_CORE_AVAILABLE 0x41 /* (CMT) LP Available */ +#define ASI_CORE_ENABLE_STAT 0x41 /* (CMT) LP Enable Status */ +#define ASI_CORE_ENABLE 0x41 /* (CMT) LP Enable RW */ +#define ASI_XIR_STEERING 0x41 /* (CMT) XIR Steering RW */ +#define ASI_CORE_RUNNING_RW 0x41 /* (CMT) LP Running RW */ +#define ASI_CORE_RUNNING_W1S 0x41 /* (CMT) LP Running Write-One Set */ +#define ASI_CORE_RUNNING_W1C 0x41 /* (CMT) LP Running Write-One Clr */ +#define ASI_CORE_RUNNING_STAT 0x41 /* (CMT) LP Running Status */ +#define ASI_CMT_ERROR_STEERING 0x41 /* (CMT) Error Steering RW */ +#define ASI_DCACHE_INVALIDATE 0x42 /* (III) DCache Invalidate diag */ +#define ASI_DCACHE_UTAG 0x43 /* (III) DCache uTag diag */ +#define ASI_DCACHE_SNOOP_TAG 0x44 /* (III) DCache snoop tag RAM diag */ +#define ASI_LSU_CONTROL 0x45 /* Load-store control unit */ +#define ASI_DCU_CONTROL_REG 0x45 /* (III) DCache Unit Control reg */ +#define ASI_DCACHE_DATA 0x46 /* DCache data-ram diag access */ +#define ASI_DCACHE_TAG 0x47 /* Dcache tag/valid ram diag access*/ +#define ASI_INTR_DISPATCH_STAT 0x48 /* IRQ vector dispatch status */ +#define ASI_INTR_RECEIVE 0x49 /* IRQ vector receive status */ +#define ASI_UPA_CONFIG 0x4a /* UPA config space */ +#define ASI_JBUS_CONFIG 0x4a /* (IIIi) JBUS Config Register */ +#define ASI_SAFARI_CONFIG 0x4a /* (III) Safari Config Register */ +#define ASI_SAFARI_ADDRESS 0x4a /* (III) Safari Address Register */ +#define ASI_ESTATE_ERROR_EN 0x4b /* E-cache error enable space */ +#define ASI_AFSR 0x4c /* Async fault status register */ +#define ASI_AFAR 0x4d /* Async fault address register */ +#define ASI_EC_TAG_DATA 0x4e /* E-cache tag/valid ram diag acc */ +#define ASI_IMMU 0x50 /* Insn-MMU main register space */ +#define ASI_IMMU_TSB_8KB_PTR 0x51 /* Insn-MMU 8KB TSB pointer reg */ +#define ASI_IMMU_TSB_64KB_PTR 0x52 /* Insn-MMU 64KB TSB pointer reg */ +#define ASI_ITLB_DATA_IN 0x54 /* Insn-MMU TLB data in reg */ +#define ASI_ITLB_DATA_ACCESS 0x55 /* Insn-MMU TLB data access reg */ +#define ASI_ITLB_TAG_READ 0x56 /* Insn-MMU TLB tag read reg */ +#define ASI_IMMU_DEMAP 0x57 /* Insn-MMU TLB demap */ +#define ASI_DMMU 0x58 /* Data-MMU main register space */ +#define ASI_DMMU_TSB_8KB_PTR 0x59 /* Data-MMU 8KB TSB pointer reg */ +#define ASI_DMMU_TSB_64KB_PTR 0x5a /* Data-MMU 16KB TSB pointer reg */ +#define ASI_DMMU_TSB_DIRECT_PTR 0x5b /* Data-MMU TSB direct pointer reg */ +#define ASI_DTLB_DATA_IN 0x5c /* Data-MMU TLB data in reg */ +#define ASI_DTLB_DATA_ACCESS 0x5d /* Data-MMU TLB data access reg */ +#define ASI_DTLB_TAG_READ 0x5e /* Data-MMU TLB tag read reg */ +#define ASI_DMMU_DEMAP 0x5f /* Data-MMU TLB demap */ +#define ASI_IIU_INST_TRAP 0x60 /* (III) Instruction Breakpoint */ +#define ASI_INTR_ID 0x63 /* (CMT) Interrupt ID register */ +#define ASI_CORE_ID 0x63 /* (CMT) LP ID register */ +#define ASI_CESR_ID 0x63 /* (CMT) CESR ID register */ +#define ASI_IC_INSTR 0x66 /* Insn cache instrucion ram diag */ +#define ASI_IC_TAG 0x67 /* Insn cache tag/valid ram diag */ +#define ASI_IC_STAG 0x68 /* (III) Insn cache snoop tag ram */ +#define ASI_IC_PRE_DECODE 0x6e /* Insn cache pre-decode ram diag */ +#define ASI_IC_NEXT_FIELD 0x6f /* Insn cache next-field ram diag */ +#define ASI_BRPRED_ARRAY 0x6f /* (III) Branch Prediction RAM diag*/ +#define ASI_BLK_AIUP 0x70 /* Primary, user, block load/store */ +#define ASI_BLK_AIUS 0x71 /* Secondary, user, block ld/st */ +#define ASI_MCU_CTRL_REG 0x72 /* (III) Memory controller regs */ +#define ASI_EC_DATA 0x74 /* (III) E-cache data staging reg */ +#define ASI_EC_CTRL 0x75 /* (III) E-cache control reg */ +#define ASI_EC_W 0x76 /* E-cache diag write access */ +#define ASI_UDB_ERROR_W 0x77 /* External UDB error regs W */ +#define ASI_UDB_CONTROL_W 0x77 /* External UDB control regs W */ +#define ASI_INTR_W 0x77 /* IRQ vector dispatch write */ +#define ASI_INTR_DATAN_W 0x77 /* (III) Out irq vector data reg N */ +#define ASI_INTR_DISPATCH_W 0x77 /* (III) Interrupt vector dispatch */ +#define ASI_BLK_AIUPL 0x78 /* Primary, user, little, blk ld/st*/ +#define ASI_BLK_AIUSL 0x79 /* Secondary, user, little, blk ld/st*/ +#define ASI_EC_R 0x7e /* E-cache diag read access */ +#define ASI_UDBH_ERROR_R 0x7f /* External UDB error regs rd hi */ +#define ASI_UDBL_ERROR_R 0x7f /* External UDB error regs rd low */ +#define ASI_UDBH_CONTROL_R 0x7f /* External UDB control regs rd hi */ +#define ASI_UDBL_CONTROL_R 0x7f /* External UDB control regs rd low*/ +#define ASI_INTR_R 0x7f /* IRQ vector dispatch read */ +#define ASI_INTR_DATAN_R 0x7f /* (III) In irq vector data reg N */ +#define ASI_PST8_P 0xc0 /* Primary, 8 8-bit, partial */ +#define ASI_PST8_S 0xc1 /* Secondary, 8 8-bit, partial */ +#define ASI_PST16_P 0xc2 /* Primary, 4 16-bit, partial */ +#define ASI_PST16_S 0xc3 /* Secondary, 4 16-bit, partial */ +#define ASI_PST32_P 0xc4 /* Primary, 2 32-bit, partial */ +#define ASI_PST32_S 0xc5 /* Secondary, 2 32-bit, partial */ +#define ASI_PST8_PL 0xc8 /* Primary, 8 8-bit, partial, L */ +#define ASI_PST8_SL 0xc9 /* Secondary, 8 8-bit, partial, L */ +#define ASI_PST16_PL 0xca /* Primary, 4 16-bit, partial, L */ +#define ASI_PST16_SL 0xcb /* Secondary, 4 16-bit, partial, L */ +#define ASI_PST32_PL 0xcc /* Primary, 2 32-bit, partial, L */ +#define ASI_PST32_SL 0xcd /* Secondary, 2 32-bit, partial, L */ +#define ASI_FL8_P 0xd0 /* Primary, 1 8-bit, fpu ld/st */ +#define ASI_FL8_S 0xd1 /* Secondary, 1 8-bit, fpu ld/st */ +#define ASI_FL16_P 0xd2 /* Primary, 1 16-bit, fpu ld/st */ +#define ASI_FL16_S 0xd3 /* Secondary, 1 16-bit, fpu ld/st */ +#define ASI_FL8_PL 0xd8 /* Primary, 1 8-bit, fpu ld/st, L */ +#define ASI_FL8_SL 0xd9 /* Secondary, 1 8-bit, fpu ld/st, L*/ +#define ASI_FL16_PL 0xda /* Primary, 1 16-bit, fpu ld/st, L */ +#define ASI_FL16_SL 0xdb /* Secondary, 1 16-bit, fpu ld/st,L*/ +#define ASI_BLK_COMMIT_P 0xe0 /* Primary, blk store commit */ +#define ASI_BLK_COMMIT_S 0xe1 /* Secondary, blk store commit */ +#define ASI_BLK_P 0xf0 /* Primary, blk ld/st */ +#define ASI_BLK_S 0xf1 /* Secondary, blk ld/st */ +#define ASI_BLK_PL 0xf8 /* Primary, blk ld/st, little */ +#define ASI_BLK_SL 0xf9 /* Secondary, blk ld/st, little */ #endif /* _SPARC64_ASI_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/cmt.h linux-2.4.28-pre3/include/asm-sparc64/cmt.h --- linux-2.4.27/include/asm-sparc64/cmt.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-sparc64/cmt.h 2004-09-10 19:36:46.000000000 +0000 @@ -0,0 +1,59 @@ +#ifndef _SPARC64_CMT_H +#define _SPARC64_CMT_H + +/* cmt.h: Chip Multi-Threading register definitions + * + * Copyright (C) 2004 David S. Miller (davem@redhat.com) + */ + +/* ASI_CORE_ID - private */ +#define LP_ID 0x0000000000000010UL +#define LP_ID_MAX 0x00000000003f0000UL +#define LP_ID_ID 0x000000000000003fUL + +/* ASI_INTR_ID - private */ +#define LP_INTR_ID 0x0000000000000000UL +#define LP_INTR_ID_ID 0x00000000000003ffUL + +/* ASI_CESR_ID - private */ +#define CESR_ID 0x0000000000000040UL +#define CESR_ID_ID 0x00000000000000ffUL + +/* ASI_CORE_AVAILABLE - shared */ +#define LP_AVAIL 0x0000000000000000UL +#define LP_AVAIL_1 0x0000000000000002UL +#define LP_AVAIL_0 0x0000000000000001UL + +/* ASI_CORE_ENABLE_STATUS - shared */ +#define LP_ENAB_STAT 0x0000000000000010UL +#define LP_ENAB_STAT_1 0x0000000000000002UL +#define LP_ENAB_STAT_0 0x0000000000000001UL + +/* ASI_CORE_ENABLE - shared */ +#define LP_ENAB 0x0000000000000020UL +#define LP_ENAB_1 0x0000000000000002UL +#define LP_ENAB_0 0x0000000000000001UL + +/* ASI_CORE_RUNNING - shared */ +#define LP_RUNNING_RW 0x0000000000000050UL +#define LP_RUNNING_W1S 0x0000000000000060UL +#define LP_RUNNING_W1C 0x0000000000000068UL +#define LP_RUNNING_1 0x0000000000000002UL +#define LP_RUNNING_0 0x0000000000000001UL + +/* ASI_CORE_RUNNING_STAT - shared */ +#define LP_RUN_STAT 0x0000000000000058UL +#define LP_RUN_STAT_1 0x0000000000000002UL +#define LP_RUN_STAT_0 0x0000000000000001UL + +/* ASI_XIR_STEERING - shared */ +#define LP_XIR_STEER 0x0000000000000030UL +#define LP_XIR_STEER_1 0x0000000000000002UL +#define LP_XIR_STEER_0 0x0000000000000001UL + +/* ASI_CMT_ERROR_STEERING - shared */ +#define CMT_ER_STEER 0x0000000000000040UL +#define CMT_ER_STEER_1 0x0000000000000002UL +#define CMT_ER_STEER_0 0x0000000000000001UL + +#endif /* _SPARC64_CMT_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/page.h linux-2.4.28-pre3/include/asm-sparc64/page.h --- linux-2.4.27/include/asm-sparc64/page.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-sparc64/page.h 2004-09-10 19:34:22.000000000 +0000 @@ -36,7 +36,7 @@ extern void do_BUG(const char *file, int extern void _clear_page(void *page); #define clear_page(X) _clear_page((void *)(X)) extern void clear_user_page(void *page, unsigned long vaddr); -#define copy_page(X,Y) __memcpy((void *)(X), (void *)(Y), PAGE_SIZE) +#define copy_page(X,Y) memcpy((void *)(X), (void *)(Y), PAGE_SIZE) extern void copy_user_page(void *to, void *from, unsigned long vaddr); /* GROSS, defining this makes gcc pass these types as aggregates, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/pbm.h linux-2.4.28-pre3/include/asm-sparc64/pbm.h --- linux-2.4.27/include/asm-sparc64/pbm.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-sparc64/pbm.h 2004-09-10 19:37:30.000000000 +0000 @@ -70,6 +70,13 @@ struct pci_iommu { */ u32 lowest_consistent_map; + /* In order to deal with some buggy third-party PCI bridges that + * do wrong prefetching, we never mark valid mappings as invalid. + * Instead we point them at this dummy page. + */ + unsigned long dummy_page; + unsigned long dummy_page_pa; + /* If PBM_NCLUSTERS is ever decreased to 4 or lower, * or if largest supported page_table_sz * 8K goes above * 2GB, you must increase the size of the type of @@ -93,6 +100,8 @@ struct pci_iommu { u32 dma_addr_mask; }; +extern void pci_iommu_table_init(struct pci_iommu *, int); + /* This describes a PCI bus module's streaming buffer. */ struct pci_strbuf { int strbuf_enabled; /* Present and using it? */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/pgtable.h linux-2.4.28-pre3/include/asm-sparc64/pgtable.h --- linux-2.4.27/include/asm-sparc64/pgtable.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-sparc64/pgtable.h 2004-09-10 19:32:07.000000000 +0000 @@ -101,32 +101,36 @@ #endif /* !(__ASSEMBLY__) */ /* Spitfire/Cheetah TTE bits. */ -#define _PAGE_VALID 0x8000000000000000 /* Valid TTE */ -#define _PAGE_R 0x8000000000000000 /* Used to keep ref bit up to date */ -#define _PAGE_SZ4MB 0x6000000000000000 /* 4MB Page */ -#define _PAGE_SZ512K 0x4000000000000000 /* 512K Page */ -#define _PAGE_SZ64K 0x2000000000000000 /* 64K Page */ -#define _PAGE_SZ8K 0x0000000000000000 /* 8K Page */ -#define _PAGE_NFO 0x1000000000000000 /* No Fault Only */ -#define _PAGE_IE 0x0800000000000000 /* Invert Endianness */ -#define _PAGE_SN 0x0000800000000000 /* (Cheetah) Snoop */ -#define _PAGE_PADDR_SF 0x000001FFFFFFE000 /* (Spitfire) Phys Address [40:13] */ -#define _PAGE_PADDR 0x000007FFFFFFE000 /* (Cheetah) Phys Address [42:13] */ -#define _PAGE_SOFT 0x0000000000001F80 /* Software bits */ -#define _PAGE_L 0x0000000000000040 /* Locked TTE */ -#define _PAGE_CP 0x0000000000000020 /* Cacheable in Physical Cache */ -#define _PAGE_CV 0x0000000000000010 /* Cacheable in Virtual Cache */ -#define _PAGE_E 0x0000000000000008 /* side-Effect */ -#define _PAGE_P 0x0000000000000004 /* Privileged Page */ -#define _PAGE_W 0x0000000000000002 /* Writable */ -#define _PAGE_G 0x0000000000000001 /* Global */ +#define _PAGE_VALID 0x8000000000000000 /* Valid TTE */ +#define _PAGE_R 0x8000000000000000 /* Keep ref bit up to date */ +#define _PAGE_SZ4MB 0x6000000000000000 /* 4MB Page */ +#define _PAGE_SZ512K 0x4000000000000000 /* 512K Page */ +#define _PAGE_SZ64K 0x2000000000000000 /* 64K Page */ +#define _PAGE_SZ8K 0x0000000000000000 /* 8K Page */ +#define _PAGE_NFO 0x1000000000000000 /* No Fault Only */ +#define _PAGE_IE 0x0800000000000000 /* Invert Endianness */ +#define _PAGE_SOFT2 0x07FC000000000000 /* Software bits, set 2 */ +#define _PAGE_RES1 0x0003000000000000 /* Reserved */ +#define _PAGE_SN 0x0000800000000000 /* (Cheetah) Snoop */ +#define _PAGE_RES2 0x0000780000000000 /* Reserved */ +#define _PAGE_PADDR_SF 0x000001FFFFFFE000 /* (Spitfire) paddr[40:13] */ +#define _PAGE_PADDR 0x000007FFFFFFE000 /* (Cheetah) paddr[42:13] */ +#define _PAGE_SOFT 0x0000000000001F80 /* Software bits */ +#define _PAGE_L 0x0000000000000040 /* Locked TTE */ +#define _PAGE_CP 0x0000000000000020 /* Cacheable in P-Cache */ +#define _PAGE_CV 0x0000000000000010 /* Cacheable in V-Cache */ +#define _PAGE_E 0x0000000000000008 /* side-Effect */ +#define _PAGE_P 0x0000000000000004 /* Privileged Page */ +#define _PAGE_W 0x0000000000000002 /* Writable */ +#define _PAGE_G 0x0000000000000001 /* Global */ /* Here are the SpitFire software bits we use in the TTE's. */ -#define _PAGE_MODIFIED 0x0000000000000800 /* Modified Page (ie. dirty) */ -#define _PAGE_ACCESSED 0x0000000000000400 /* Accessed Page (ie. referenced) */ -#define _PAGE_READ 0x0000000000000200 /* Readable SW Bit */ -#define _PAGE_WRITE 0x0000000000000100 /* Writable SW Bit */ -#define _PAGE_PRESENT 0x0000000000000080 /* Present Page (ie. not swapped out) */ +#define _PAGE_EXEC 0x0000000000001000 /* Executable SW bit */ +#define _PAGE_MODIFIED 0x0000000000000800 /* Modified Page (ie. dirty) */ +#define _PAGE_ACCESSED 0x0000000000000400 /* Accessed Page (ie. ref'd) */ +#define _PAGE_READ 0x0000000000000200 /* Readable SW Bit */ +#define _PAGE_WRITE 0x0000000000000100 /* Writable SW Bit */ +#define _PAGE_PRESENT 0x0000000000000080 /* Present */ #if PAGE_SHIFT == 13 #define _PAGE_SZBITS _PAGE_SZ8K @@ -150,16 +154,27 @@ /* Don't set the TTE _PAGE_W bit here, else the dirty bit never gets set. */ #define PAGE_SHARED __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ - __ACCESS_BITS | _PAGE_WRITE) + __ACCESS_BITS | _PAGE_WRITE | _PAGE_EXEC) #define PAGE_COPY __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ - __ACCESS_BITS) + __ACCESS_BITS | _PAGE_EXEC) #define PAGE_READONLY __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ - __ACCESS_BITS) + __ACCESS_BITS | _PAGE_EXEC) #define PAGE_KERNEL __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ - __PRIV_BITS | __ACCESS_BITS | __DIRTY_BITS) + __PRIV_BITS | \ + __ACCESS_BITS | __DIRTY_BITS | _PAGE_EXEC) + +#define PAGE_SHARED_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \ + _PAGE_CACHE | \ + __ACCESS_BITS | _PAGE_WRITE) + +#define PAGE_COPY_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \ + _PAGE_CACHE | __ACCESS_BITS) + +#define PAGE_READONLY_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | \ + _PAGE_CACHE | __ACCESS_BITS) #define PAGE_INVALID __pgprot (0) @@ -170,18 +185,18 @@ #define pg_iobits (_PAGE_VALID | _PAGE_PRESENT | __DIRTY_BITS | __ACCESS_BITS | _PAGE_E) #define __P000 PAGE_NONE -#define __P001 PAGE_READONLY -#define __P010 PAGE_COPY -#define __P011 PAGE_COPY +#define __P001 PAGE_READONLY_NOEXEC +#define __P010 PAGE_COPY_NOEXEC +#define __P011 PAGE_COPY_NOEXEC #define __P100 PAGE_READONLY #define __P101 PAGE_READONLY #define __P110 PAGE_COPY #define __P111 PAGE_COPY #define __S000 PAGE_NONE -#define __S001 PAGE_READONLY -#define __S010 PAGE_SHARED -#define __S011 PAGE_SHARED +#define __S001 PAGE_READONLY_NOEXEC +#define __S010 PAGE_SHARED_NOEXEC +#define __S011 PAGE_SHARED_NOEXEC #define __S100 PAGE_READONLY #define __S101 PAGE_READONLY #define __S110 PAGE_SHARED diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/sigcontext.h linux-2.4.28-pre3/include/asm-sparc64/sigcontext.h --- linux-2.4.27/include/asm-sparc64/sigcontext.h 1999-09-08 18:14:32.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-sparc64/sigcontext.h 2004-09-10 19:33:37.000000000 +0000 @@ -83,18 +83,6 @@ struct sigcontext { unsigned long sigc_mask; }; -#ifdef __KERNEL__ - -/* This magic should be in g_upper[0] for all upper parts - to be valid. */ -#define SIGINFO_EXTRA_V8PLUS_MAGIC 0x130e269 -typedef struct { - unsigned int g_upper[8]; - unsigned int o_upper[8]; -} siginfo_extra_v8plus_t; - -#endif - #endif /* !(__ASSEMBLY__) */ #endif /* !(__SPARC64_SIGCONTEXT_H) */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/string.h linux-2.4.28-pre3/include/asm-sparc64/string.h --- linux-2.4.27/include/asm-sparc64/string.h 2001-10-01 16:19:56.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-sparc64/string.h 2004-09-10 19:36:38.000000000 +0000 @@ -15,59 +15,25 @@ #include -extern void __memmove(void *,const void *,__kernel_size_t); -extern __kernel_size_t __memcpy(void *,const void *,__kernel_size_t); extern void *__memset(void *,int,__kernel_size_t); -extern void *__builtin_memcpy(void *,const void *,__kernel_size_t); -extern void *__builtin_memset(void *,int,__kernel_size_t); #ifndef EXPORT_SYMTAB_STROPS /* First the mem*() things. */ -#define __HAVE_ARCH_BCOPY #define __HAVE_ARCH_MEMMOVE - -#undef memmove -#define memmove(_to, _from, _n) \ -({ \ - void *_t = (_to); \ - __memmove(_t, (_from), (_n)); \ - _t; \ -}) +extern void *memmove(void *, const void *, __kernel_size_t); #define __HAVE_ARCH_MEMCPY - -static inline void *__constant_memcpy(void *to, const void *from, __kernel_size_t n) -{ - if(n) { - if(n <= 32) { - __builtin_memcpy(to, from, n); - } else { - __memcpy(to, from, n); - } - } - return to; -} - -static inline void *__nonconstant_memcpy(void *to, const void *from, __kernel_size_t n) -{ - __memcpy(to, from, n); - return to; -} - -#undef memcpy -#define memcpy(t, f, n) \ -(__builtin_constant_p(n) ? \ - __constant_memcpy((t),(f),(n)) : \ - __nonconstant_memcpy((t),(f),(n))) +extern void *memcpy(void *, const void *, __kernel_size_t); #define __HAVE_ARCH_MEMSET +extern void *__builtin_memset(void *,int,__kernel_size_t); static inline void *__constant_memset(void *s, int c, __kernel_size_t count) { extern __kernel_size_t __bzero(void *, __kernel_size_t); - if(!c) { + if (!c) { __bzero(s, count); return s; } else @@ -85,19 +51,19 @@ static inline void *__constant_memset(vo #define __HAVE_ARCH_MEMSCAN #undef memscan -#define memscan(__arg0, __char, __arg2) \ -({ \ - extern void *__memscan_zero(void *, size_t); \ - extern void *__memscan_generic(void *, int, size_t); \ - void *__retval, *__addr = (__arg0); \ - size_t __size = (__arg2); \ - \ - if(__builtin_constant_p(__char) && !(__char)) \ - __retval = __memscan_zero(__addr, __size); \ - else \ - __retval = __memscan_generic(__addr, (__char), __size); \ - \ - __retval; \ +#define memscan(__arg0, __char, __arg2) \ +({ \ + extern void *__memscan_zero(void *, size_t); \ + extern void *__memscan_generic(void *, int, size_t); \ + void *__retval, *__addr = (__arg0); \ + size_t __size = (__arg2); \ + \ + if(__builtin_constant_p(__char) && !(__char)) \ + __retval = __memscan_zero(__addr, __size); \ + else \ + __retval = __memscan_generic(__addr, (__char), __size); \ + \ + __retval; \ }) #define __HAVE_ARCH_MEMCMP diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/uaccess.h linux-2.4.28-pre3/include/asm-sparc64/uaccess.h --- linux-2.4.27/include/asm-sparc64/uaccess.h 2001-10-01 16:19:56.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-sparc64/uaccess.h 2004-09-10 19:34:18.000000000 +0000 @@ -249,26 +249,50 @@ __asm__ __volatile__( \ extern int __get_user_bad(void); -extern __kernel_size_t __copy_from_user(void *to, const void *from, - __kernel_size_t size); +extern unsigned long ___copy_from_user(void *to, const void *from, + unsigned long size); +extern unsigned long copy_from_user_fixup(void *to, const void *from, + unsigned long size); +static inline unsigned long copy_from_user(void *to, const void *from, + unsigned long size) +{ + unsigned long ret = ___copy_from_user(to, from, size); + + if (ret) + ret = copy_from_user_fixup(to, from, size); + return ret; +} +#define __copy_from_user copy_from_user + +extern unsigned long ___copy_to_user(void *to, const void *from, + unsigned long size); +extern unsigned long copy_to_user_fixup(void *to, const void *from, + unsigned long size); +static inline unsigned long copy_to_user(void *to, const void *from, + unsigned long size) +{ + unsigned long ret = ___copy_to_user(to, from, size); -extern __kernel_size_t __copy_to_user(void *to, const void *from, - __kernel_size_t size); + if (ret) + ret = copy_to_user_fixup(to, from, size); + return ret; +} +#define __copy_to_user copy_to_user -extern __kernel_size_t __copy_in_user(void *to, const void *from, - __kernel_size_t size); +extern unsigned long ___copy_in_user(void *to, const void *from, + unsigned long size); +extern unsigned long copy_in_user_fixup(void *to, void *from, + unsigned long size); +static inline unsigned long copy_in_user(void *to, void *from, + unsigned long size) +{ + unsigned long ret = ___copy_in_user(to, from, size); -#define copy_from_user(to,from,n) \ - __copy_from_user((void *)(to), \ - (void *)(from), (__kernel_size_t)(n)) - -#define copy_to_user(to,from,n) \ - __copy_to_user((void *)(to), \ - (void *) (from), (__kernel_size_t)(n)) - -#define copy_in_user(to,from,n) \ - __copy_in_user((void *)(to), \ - (void *) (from), (__kernel_size_t)(n)) + if (ret) + ret = copy_in_user_fixup(to, from, size); + return ret; +} +#define __copy_in_user copy_in_user extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-x86_64/apic.h linux-2.4.28-pre3/include/asm-x86_64/apic.h --- linux-2.4.27/include/asm-x86_64/apic.h 2003-06-13 14:51:38.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-x86_64/apic.h 2004-09-10 19:35:04.000000000 +0000 @@ -78,7 +78,7 @@ extern void init_apic_mappings (void); extern void smp_local_timer_interrupt (struct pt_regs * regs); extern void setup_APIC_clocks (void); extern void setup_apic_nmi_watchdog (void); -extern inline void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason); +extern void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason); extern int APIC_init_uniprocessor (void); extern void disable_APIC_timer(void); extern void enable_APIC_timer(void); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-x86_64/unistd.h linux-2.4.28-pre3/include/asm-x86_64/unistd.h --- linux-2.4.27/include/asm-x86_64/unistd.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/include/asm-x86_64/unistd.h 2004-09-10 19:36:20.000000000 +0000 @@ -673,7 +673,7 @@ static inline long close(unsigned int fd } extern long sys_exit(int) __attribute__((noreturn)); -extern inline long exit(int error_code) +static inline void exit(int error_code) { sys_exit(error_code); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/ac97_codec.h linux-2.4.28-pre3/include/linux/ac97_codec.h --- linux-2.4.27/include/linux/ac97_codec.h 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/ac97_codec.h 2004-09-10 19:32:18.000000000 +0000 @@ -290,6 +290,7 @@ struct ac97_ops #define AC97_DELUDED_MODEM 1 /* Audio codec reports its a modem */ #define AC97_NO_PCM_VOLUME 2 /* Volume control is missing */ +#define AC97_DEFAULT_POWER_OFF 4 /* Needs warm reset to power up */ }; extern int ac97_read_proc (char *page_out, char **start, off_t off, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/agp_backend.h linux-2.4.28-pre3/include/linux/agp_backend.h --- linux-2.4.27/include/linux/agp_backend.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/agp_backend.h 2004-09-10 19:36:20.000000000 +0000 @@ -55,6 +55,7 @@ enum chipset_type { INTEL_I855_PM, INTEL_I860, INTEL_I865_G, + INTEL_I915_G, INTEL_I7205, INTEL_I7505, INTEL_460GX, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/ata.h linux-2.4.28-pre3/include/linux/ata.h --- linux-2.4.27/include/linux/ata.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/ata.h 2004-09-10 19:32:51.000000000 +0000 @@ -42,6 +42,7 @@ enum { ATA_ID_SERNO_OFS = 10, ATA_ID_MAJOR_VER = 80, ATA_ID_PIO_MODES = 64, + ATA_ID_MWDMA_MODES = 63, ATA_ID_UDMA_MODES = 88, ATA_ID_PIO4 = (1 << 1), @@ -78,9 +79,11 @@ enum { ATA_NIEN = (1 << 1), /* disable-irq flag */ ATA_LBA = (1 << 6), /* LBA28 selector */ ATA_DEV1 = (1 << 4), /* Select Device 1 (slave) */ - ATA_BUSY = (1 << 7), /* BSY status bit */ ATA_DEVICE_OBS = (1 << 7) | (1 << 5), /* obs bits in dev reg */ ATA_DEVCTL_OBS = (1 << 3), /* obsolete bit in devctl reg */ + ATA_BUSY = (1 << 7), /* BSY status bit */ + ATA_DRDY = (1 << 6), /* device ready */ + ATA_DF = (1 << 5), /* device fault */ ATA_DRQ = (1 << 3), /* data request i/o */ ATA_ERR = (1 << 0), /* have an error */ ATA_SRST = (1 << 2), /* software reset */ @@ -131,13 +134,20 @@ enum { XFER_UDMA_2 = 0x42, XFER_UDMA_1 = 0x41, XFER_UDMA_0 = 0x40, + XFER_MW_DMA_2 = 0x22, + XFER_MW_DMA_1 = 0x21, + XFER_MW_DMA_0 = 0x20, XFER_PIO_4 = 0x0C, XFER_PIO_3 = 0x0B, + XFER_PIO_2 = 0x0A, + XFER_PIO_1 = 0x09, + XFER_PIO_0 = 0x08, /* ATAPI stuff */ ATAPI_PKT_DMA = (1 << 0), ATAPI_DMADIR = (1 << 2), /* ATAPI data dir: 0=to device, 1=to host */ + ATAPI_CDB_LEN = 16, /* cable types */ ATA_CBL_NONE = 0, @@ -167,16 +177,22 @@ enum ata_tf_protocols { ATA_PROT_PIO, /* PIO single sector */ ATA_PROT_PIO_MULT, /* PIO multiple sector */ ATA_PROT_DMA, /* DMA */ - ATA_PROT_ATAPI, /* packet command */ + ATA_PROT_ATAPI, /* packet command, PIO data xfer*/ + ATA_PROT_ATAPI_NODATA, /* packet command, no data */ ATA_PROT_ATAPI_DMA, /* packet command with special DMA sauce */ }; +enum ata_ioctls { + ATA_IOC_GET_IO32 = 0x309, + ATA_IOC_SET_IO32 = 0x324, +}; + /* core structures */ struct ata_prd { u32 addr; u32 flags_len; -} __attribute__((packed)); +}; struct ata_taskfile { unsigned long flags; /* ATA_TFLAG_xxx */ @@ -204,11 +220,13 @@ struct ata_taskfile { #define ata_id_is_ata(dev) (((dev)->id[0] & (1 << 15)) == 0) #define ata_id_rahead_enabled(dev) ((dev)->id[85] & (1 << 6)) #define ata_id_wcache_enabled(dev) ((dev)->id[85] & (1 << 5)) +#define ata_id_has_flush(dev) ((dev)->id[83] & (1 << 12)) +#define ata_id_has_flush_ext(dev) ((dev)->id[83] & (1 << 13)) #define ata_id_has_lba48(dev) ((dev)->id[83] & (1 << 10)) #define ata_id_has_wcache(dev) ((dev)->id[82] & (1 << 5)) #define ata_id_has_pm(dev) ((dev)->id[82] & (1 << 3)) -#define ata_id_has_lba(dev) ((dev)->id[49] & (1 << 8)) -#define ata_id_has_dma(dev) ((dev)->id[49] & (1 << 9)) +#define ata_id_has_lba(dev) ((dev)->id[49] & (1 << 9)) +#define ata_id_has_dma(dev) ((dev)->id[49] & (1 << 8)) #define ata_id_removeable(dev) ((dev)->id[0] & (1 << 7)) #define ata_id_u32(dev,n) \ (((u32) (dev)->id[(n) + 1] << 16) | ((u32) (dev)->id[(n)])) @@ -218,10 +236,27 @@ struct ata_taskfile { ((u64) dev->id[(n) + 1] << 16) | \ ((u64) dev->id[(n) + 0]) ) +static inline int atapi_cdb_len(u16 *dev_id) +{ + u16 tmp = dev_id[0] & 0x3; + switch (tmp) { + case 0: return 12; + case 1: return 16; + default: return -1; + } +} + static inline int is_atapi_taskfile(struct ata_taskfile *tf) { return (tf->protocol == ATA_PROT_ATAPI) || + (tf->protocol == ATA_PROT_ATAPI_NODATA) || (tf->protocol == ATA_PROT_ATAPI_DMA); } +static inline int ata_ok(u8 status) +{ + return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR)) + == ATA_DRDY); +} + #endif /* __LINUX_ATA_H__ */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/blkdev.h linux-2.4.28-pre3/include/linux/blkdev.h --- linux-2.4.27/include/linux/blkdev.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/blkdev.h 2004-09-10 19:33:16.000000000 +0000 @@ -233,7 +233,7 @@ extern struct blk_dev_struct blk_dev[MAX extern void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size); extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size); extern void generic_make_request(int rw, struct buffer_head * bh); -extern inline request_queue_t *blk_get_queue(kdev_t dev); +extern request_queue_t *blk_get_queue(kdev_t dev); extern void blkdev_release_request(struct request *); /* @@ -246,7 +246,7 @@ extern void blk_queue_headactive(request extern void blk_queue_throttle_sectors(request_queue_t *, int); extern void blk_queue_make_request(request_queue_t *, make_request_fn *); extern void generic_unplug_device(void *); -extern inline int blk_seg_merge_ok(struct buffer_head *, struct buffer_head *); +extern int blk_seg_merge_ok(struct buffer_head *, struct buffer_head *); extern int * blk_size[MAX_BLKDEV]; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/fs.h linux-2.4.28-pre3/include/linux/fs.h --- linux-2.4.27/include/linux/fs.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/fs.h 2004-09-10 19:33:26.000000000 +0000 @@ -1259,7 +1259,7 @@ static inline void mark_buffer_dirty_ino } extern void set_buffer_flushtime(struct buffer_head *); -extern inline int get_buffer_flushtime(void); +extern int get_buffer_flushtime(void); extern void balance_dirty(void); extern int check_disk_change(kdev_t); extern int invalidate_inodes(struct super_block *); @@ -1523,7 +1523,7 @@ extern int writeout_one_page(struct page extern int generic_file_mmap(struct file *, struct vm_area_struct *); extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *); -extern inline ssize_t do_generic_direct_read(struct file *, char *, size_t, loff_t *); +extern ssize_t do_generic_direct_read(struct file *, char *, size_t, loff_t *); extern int precheck_file_write(struct file *, struct inode *, size_t *, loff_t *); extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *); extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/fsfilter.h linux-2.4.28-pre3/include/linux/fsfilter.h --- linux-2.4.27/include/linux/fsfilter.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/fsfilter.h 2004-09-10 19:32:04.000000000 +0000 @@ -74,22 +74,22 @@ extern struct filter_fs filter_oppar[FIL struct filter_fs *filter_get_filter_fs(const char *cache_type); void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type); -inline struct super_operations *filter_c2usops(struct filter_fs *cache); -inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache); -inline struct inode_operations *filter_c2udiops(struct filter_fs *cache); -inline struct inode_operations *filter_c2usiops(struct filter_fs *cache); -inline struct file_operations *filter_c2uffops(struct filter_fs *cache); -inline struct file_operations *filter_c2udfops(struct filter_fs *cache); -inline struct file_operations *filter_c2usfops(struct filter_fs *cache); -inline struct super_operations *filter_c2csops(struct filter_fs *cache); -inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache); -inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache); -inline struct inode_operations *filter_c2csiops(struct filter_fs *cache); -inline struct file_operations *filter_c2cffops(struct filter_fs *cache); -inline struct file_operations *filter_c2cdfops(struct filter_fs *cache); -inline struct file_operations *filter_c2csfops(struct filter_fs *cache); -inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache); -inline struct dentry_operations *filter_c2udops(struct filter_fs *cache); +struct super_operations *filter_c2usops(struct filter_fs *cache); +struct inode_operations *filter_c2ufiops(struct filter_fs *cache); +struct inode_operations *filter_c2udiops(struct filter_fs *cache); +struct inode_operations *filter_c2usiops(struct filter_fs *cache); +struct file_operations *filter_c2uffops(struct filter_fs *cache); +struct file_operations *filter_c2udfops(struct filter_fs *cache); +struct file_operations *filter_c2usfops(struct filter_fs *cache); +struct super_operations *filter_c2csops(struct filter_fs *cache); +struct inode_operations *filter_c2cfiops(struct filter_fs *cache); +struct inode_operations *filter_c2cdiops(struct filter_fs *cache); +struct inode_operations *filter_c2csiops(struct filter_fs *cache); +struct file_operations *filter_c2cffops(struct filter_fs *cache); +struct file_operations *filter_c2cdfops(struct filter_fs *cache); +struct file_operations *filter_c2csfops(struct filter_fs *cache); +struct dentry_operations *filter_c2cdops(struct filter_fs *cache); +struct dentry_operations *filter_c2udops(struct filter_fs *cache); void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_ops, struct super_operations *filter_sops); void filter_setup_dir_ops(struct filter_fs *cache, struct inode *cache_inode, struct inode_operations *filter_iops, struct file_operations *ffops); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/ide.h linux-2.4.28-pre3/include/linux/ide.h --- linux-2.4.27/include/linux/ide.h 2004-04-14 13:05:40.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/ide.h 2004-09-10 19:33:03.000000000 +0000 @@ -1445,10 +1445,10 @@ typedef struct pkt_task_s { void *special; } pkt_task_t; -extern inline void SELECT_DRIVE(ide_drive_t *); -extern inline void SELECT_INTERRUPT(ide_drive_t *); -extern inline void SELECT_MASK(ide_drive_t *, int); -extern inline void QUIRK_LIST(ide_drive_t *); +extern void SELECT_DRIVE(ide_drive_t *); +extern void SELECT_INTERRUPT(ide_drive_t *); +extern void SELECT_MASK(ide_drive_t *, int); +extern void QUIRK_LIST(ide_drive_t *); extern void ata_input_data(ide_drive_t *, void *, u32); extern void ata_output_data(ide_drive_t *, void *, u32); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/in6.h linux-2.4.28-pre3/include/linux/in6.h --- linux-2.4.27/include/linux/in6.h 2003-06-13 14:51:38.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/in6.h 2004-09-10 19:35:30.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * Sources: * IPv6 Program Interfaces for BSD Systems diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/intermezzo_fs.h linux-2.4.28-pre3/include/linux/intermezzo_fs.h --- linux-2.4.27/include/linux/intermezzo_fs.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/intermezzo_fs.h 2004-09-10 19:34:33.000000000 +0000 @@ -49,8 +49,6 @@ struct lento_vfs_context { struct presto_version remote_version; }; -static inline int izo_ioctl_is_invalid(struct izo_ioctl_data *data); - #ifdef __KERNEL__ # include # include @@ -336,7 +334,7 @@ int izo_psdev_get_free_channel(void); int presto_psdev_init(void); int izo_psdev_setpid(int minor); extern void presto_psdev_cleanup(void); -inline int presto_lento_up(int minor); +int presto_lento_up(int minor); int izo_psdev_setchannel(struct file *file, int fd); /* inode.c */ @@ -347,7 +345,7 @@ void presto_set_ops(struct inode *inode, void presto_frob_dop(struct dentry *de); char *presto_path(struct dentry *dentry, struct dentry *root, char *buffer, int buflen); -inline struct presto_dentry_data *izo_alloc_ddata(void); +struct presto_dentry_data *izo_alloc_ddata(void); int presto_set_dd(struct dentry *); int presto_init_ddata_cache(void); void presto_cleanup_ddata_cache(void); @@ -412,7 +410,7 @@ int presto_set_fsetroot(struct dentry *d unsigned int flags); int presto_set_fsetroot_from_ioc(struct dentry *dentry, char *fsetname, unsigned int flags); -inline int presto_is_read_only(struct presto_file_set *); +int presto_is_read_only(struct presto_file_set *); int presto_truncate_lml(struct presto_file_set *fset); int lento_write_lml(char *path, __u64 remote_ino, @@ -420,13 +418,13 @@ int lento_write_lml(char *path, __u32 remote_version, struct presto_version *remote_file_version); int lento_complete_closes(char *path); -inline int presto_f2m(struct presto_file_set *fset); +int presto_f2m(struct presto_file_set *fset); int presto_prep(struct dentry *, struct presto_cache **, struct presto_file_set **); /* cache.c */ extern struct presto_cache *presto_cache_init(void); -extern inline void presto_cache_add(struct presto_cache *cache, kdev_t dev); -extern inline void presto_cache_init_hash(void); +extern void presto_cache_add(struct presto_cache *cache, kdev_t dev); +extern void presto_cache_init_hash(void); struct presto_cache *presto_cache_find(kdev_t dev); @@ -553,7 +551,7 @@ int lento_iopen(const char *name, ino_t #define JOURNAL_PAGE_SZ PAGE_SIZE -__inline__ int presto_no_journal(struct presto_file_set *fset); +int presto_no_journal(struct presto_file_set *fset); int journal_fetch(int minor); int presto_log(struct presto_file_set *fset, struct rec_info *rec, const char *buf, size_t size, @@ -658,6 +656,8 @@ loff_t izo_rcvd_write(struct presto_file loff_t izo_rcvd_upd_remote(struct presto_file_set *fset, char * uuid, __u64 remote_recno, __u64 remote_offset); +int izo_ioctl_packlen(struct izo_ioctl_data *data); + /* sysctl.c */ int init_intermezzo_sysctl(void); void cleanup_intermezzo_sysctl(void); @@ -715,6 +715,54 @@ static inline char *strdup(char *str) return tmp; } +static inline int izo_ioctl_is_invalid(struct izo_ioctl_data *data) +{ + if (data->ioc_len > (1<<30)) { + CERROR("IZO ioctl: ioc_len larger than 1<<30\n"); + return 1; + } + if (data->ioc_inllen1 > (1<<30)) { + CERROR("IZO ioctl: ioc_inllen1 larger than 1<<30\n"); + return 1; + } + if (data->ioc_inllen2 > (1<<30)) { + CERROR("IZO ioctl: ioc_inllen2 larger than 1<<30\n"); + return 1; + } + if (data->ioc_inlbuf1 && !data->ioc_inllen1) { + CERROR("IZO ioctl: inlbuf1 pointer but 0 length\n"); + return 1; + } + if (data->ioc_inlbuf2 && !data->ioc_inllen2) { + CERROR("IZO ioctl: inlbuf2 pointer but 0 length\n"); + return 1; + } + if (data->ioc_pbuf1 && !data->ioc_plen1) { + CERROR("IZO ioctl: pbuf1 pointer but 0 length\n"); + return 1; + } + if (data->ioc_pbuf2 && !data->ioc_plen2) { + CERROR("IZO ioctl: pbuf2 pointer but 0 length\n"); + return 1; + } + if (izo_ioctl_packlen(data) != data->ioc_len ) { + CERROR("IZO ioctl: packlen exceeds ioc_len\n"); + return 1; + } + if (data->ioc_inllen1 && + data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') { + CERROR("IZO ioctl: inlbuf1 not 0 terminated\n"); + return 1; + } + if (data->ioc_inllen2 && + data->ioc_bulk[size_round(data->ioc_inllen1) + data->ioc_inllen2 + - 1] != '\0') { + CERROR("IZO ioctl: inlbuf2 not 0 terminated\n"); + return 1; + } + return 0; +} + /* buffer MUST be at least the size of izo_ioctl_hdr */ static inline int izo_ioctl_getdata(char *buf, char *end, void *arg) { @@ -798,8 +846,6 @@ int kml_fsreint(struct kml_rec *rec, cha int kml_iocreint(__u32 size, char *ptr, __u32 offset, int dird, uuid_t uuid, __u32 generate_kml); -static inline int izo_ioctl_packlen(struct izo_ioctl_data *data); - static inline void izo_ioctl_init(struct izo_ioctl_data *data) { memset(data, 0, sizeof(*data)); @@ -861,62 +907,6 @@ static inline char *izo_error(int err) return "Unknown InterMezzo error"; } -static inline int izo_ioctl_packlen(struct izo_ioctl_data *data) -{ - int len = sizeof(struct izo_ioctl_data); - len += size_round(data->ioc_inllen1); - len += size_round(data->ioc_inllen2); - return len; -} - -static inline int izo_ioctl_is_invalid(struct izo_ioctl_data *data) -{ - if (data->ioc_len > (1<<30)) { - CERROR("IZO ioctl: ioc_len larger than 1<<30\n"); - return 1; - } - if (data->ioc_inllen1 > (1<<30)) { - CERROR("IZO ioctl: ioc_inllen1 larger than 1<<30\n"); - return 1; - } - if (data->ioc_inllen2 > (1<<30)) { - CERROR("IZO ioctl: ioc_inllen2 larger than 1<<30\n"); - return 1; - } - if (data->ioc_inlbuf1 && !data->ioc_inllen1) { - CERROR("IZO ioctl: inlbuf1 pointer but 0 length\n"); - return 1; - } - if (data->ioc_inlbuf2 && !data->ioc_inllen2) { - CERROR("IZO ioctl: inlbuf2 pointer but 0 length\n"); - return 1; - } - if (data->ioc_pbuf1 && !data->ioc_plen1) { - CERROR("IZO ioctl: pbuf1 pointer but 0 length\n"); - return 1; - } - if (data->ioc_pbuf2 && !data->ioc_plen2) { - CERROR("IZO ioctl: pbuf2 pointer but 0 length\n"); - return 1; - } - if (izo_ioctl_packlen(data) != data->ioc_len ) { - CERROR("IZO ioctl: packlen exceeds ioc_len\n"); - return 1; - } - if (data->ioc_inllen1 && - data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') { - CERROR("IZO ioctl: inlbuf1 not 0 terminated\n"); - return 1; - } - if (data->ioc_inllen2 && - data->ioc_bulk[size_round(data->ioc_inllen1) + data->ioc_inllen2 - - 1] != '\0') { - CERROR("IZO ioctl: inlbuf2 not 0 terminated\n"); - return 1; - } - return 0; -} - /* kml_unpack.c */ char *kml_print_rec(struct kml_rec *rec, int brief); int kml_unpack(struct kml_rec *rec, char **buf, char *end); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/ipv6_route.h linux-2.4.28-pre3/include/linux/ipv6_route.h --- linux-2.4.27/include/linux/ipv6_route.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/ipv6_route.h 2004-09-10 19:33:06.000000000 +0000 @@ -2,7 +2,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/irq_cpustat.h linux-2.4.28-pre3/include/linux/irq_cpustat.h --- linux-2.4.27/include/linux/irq_cpustat.h 2001-11-22 19:46:18.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/irq_cpustat.h 2004-09-10 19:36:54.000000000 +0000 @@ -22,7 +22,7 @@ extern irq_cpustat_t irq_stat[]; /* de #ifdef CONFIG_SMP #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member) #else -#define __IRQ_STAT(cpu, member) ((void)(cpu), irq_stat[0].member) +#define __IRQ_STAT(cpu, member) (irq_stat[((void)(cpu), 0)].member) #endif /* arch independent irq_stat fields */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/jbd.h linux-2.4.28-pre3/include/linux/jbd.h --- linux-2.4.27/include/linux/jbd.h 2003-06-13 14:51:38.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/jbd.h 2004-09-10 19:36:27.000000000 +0000 @@ -70,7 +70,7 @@ extern int journal_enable_debug; #define jbd_debug(f, a...) /**/ #endif -extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry); +extern void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry); #define jbd_kmalloc(size, flags) \ __jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry) #define jbd_rep_kmalloc(size, flags) \ @@ -867,7 +867,7 @@ do { \ schedule(); \ } while (1) -extern void __jbd_unexpected_dirty_buffer(char *, int, struct journal_head *); +extern void __jbd_unexpected_dirty_buffer(const char *, int, struct journal_head *); #define jbd_unexpected_dirty_buffer(jh) \ __jbd_unexpected_dirty_buffer(__FUNCTION__, __LINE__, (jh)) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/kernel.h linux-2.4.28-pre3/include/linux/kernel.h --- linux-2.4.27/include/linux/kernel.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/kernel.h 2004-09-10 19:31:52.000000000 +0000 @@ -51,8 +51,10 @@ extern int console_printk[]; #ifdef __i386__ #define FASTCALL(x) x __attribute__((regparm(3))) +#define fastcall __attribute__((regparm(3))) #else #define FASTCALL(x) x +#define fastcall #endif struct completion; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/libata.h linux-2.4.28-pre3/include/linux/libata.h --- linux-2.4.27/include/linux/libata.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/libata.h 2004-09-10 19:36:13.000000000 +0000 @@ -32,7 +32,6 @@ /* * compile-time options */ -#undef ATA_FORCE_PIO /* do not configure or use DMA */ #undef ATA_DEBUG /* debugging output */ #undef ATA_VERBOSE_DEBUG /* yet more debugging output */ #undef ATA_IRQ_TRAP /* define to ack screaming irqs */ @@ -89,9 +88,7 @@ enum { /* struct ata_device stuff */ ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */ ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */ - ATA_DFLAG_MASTER = (1 << 2), /* is device 0? */ - ATA_DFLAG_WCACHE = (1 << 3), /* has write cache we can - * (hopefully) flush? */ + ATA_DFLAG_LOCK_SECTORS = (1 << 2), /* don't adjust max_sectors */ ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ @@ -111,8 +108,9 @@ enum { ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ - ATA_QCFLAG_DMA = (1 << 2), /* data delivered via DMA */ - ATA_QCFLAG_SG = (1 << 4), /* have s/g table? */ + ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ + ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ + ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, /* various lengths of time */ ATA_TMOUT_EDD = 5 * HZ, /* hueristic */ @@ -134,24 +132,17 @@ enum { BUS_IDENTIFY = 8, BUS_PACKET = 9, - /* thread states */ - THR_UNKNOWN = 0, - THR_PORT_RESET = (THR_UNKNOWN + 1), - THR_AWAIT_DEATH = (THR_PORT_RESET + 1), - THR_PROBE_FAILED = (THR_AWAIT_DEATH + 1), - THR_IDLE = (THR_PROBE_FAILED + 1), - THR_PROBE_SUCCESS = (THR_IDLE + 1), - THR_PROBE_START = (THR_PROBE_SUCCESS + 1), - /* SATA port states */ PORT_UNKNOWN = 0, PORT_ENABLED = 1, PORT_DISABLED = 2, - /* ata_qc_cb_t flags - note uses above ATA_QCFLAG_xxx namespace, - * but not numberspace + /* encoding various smaller bitmaps into a single + * unsigned long bitmap */ - ATA_QCFLAG_TIMEOUT = (1 << 0), + ATA_SHIFT_UDMA = 0, + ATA_SHIFT_MWDMA = 8, + ATA_SHIFT_PIO = 11, }; enum pio_task_states { @@ -166,12 +157,13 @@ enum pio_task_states { }; /* forward declarations */ +struct scsi_device; struct ata_port_operations; struct ata_port; struct ata_queued_cmd; /* typedefs */ -typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc, unsigned int flags); +typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, u8 drv_stat); struct ata_ioports { unsigned long cmd_addr; @@ -199,6 +191,7 @@ struct ata_probe_ent { struct ata_ioports port[ATA_MAX_PORTS]; unsigned int n_ports; unsigned int pio_mask; + unsigned int mwdma_mask; unsigned int udma_mask; unsigned int legacy_mode; unsigned long irq; @@ -215,6 +208,7 @@ struct ata_host_set { void *mmio_base; unsigned int n_ports; void *private_data; + struct ata_port_operations *ops; struct ata_port * ports[0]; }; @@ -225,19 +219,26 @@ struct ata_queued_cmd { struct scsi_cmnd *scsicmd; void (*scsidone)(struct scsi_cmnd *); + struct ata_taskfile tf; + u8 cdb[ATAPI_CDB_LEN]; + unsigned long flags; /* ATA_QCFLAG_xxx */ unsigned int tag; unsigned int n_elem; + + int pci_dma_dir; + unsigned int nsect; unsigned int cursect; unsigned int cursg; unsigned int cursg_ofs; - struct ata_taskfile tf; + struct scatterlist sgent; + void *buf_virt; struct scatterlist *sg; - ata_qc_cb_t callback; + ata_qc_cb_t complete_fn; struct completion *waiting; @@ -256,8 +257,10 @@ struct ata_device { unsigned int class; /* ATA_DEV_xxx */ unsigned int devno; /* 0 or 1 */ u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ - unsigned int pio_mode; - unsigned int udma_mode; + u8 pio_mode; + u8 dma_mode; + u8 xfer_mode; + unsigned int xfer_shift; /* ATA_SHIFT_xxx */ /* cache info about current transfer mode */ u8 xfer_protocol; /* taskfile xfer protocol */ @@ -282,8 +285,10 @@ struct ata_port { unsigned int bus_state; unsigned int port_state; unsigned int pio_mask; + unsigned int mwdma_mask; unsigned int udma_mask; unsigned int cbl; /* cable type; ATA_CBL_xxx */ + unsigned int cdb_len; struct ata_device device[ATA_MAX_DEVICES]; @@ -294,18 +299,12 @@ struct ata_port { struct ata_host_stats stats; struct ata_host_set *host_set; - struct semaphore probe_sem; - - unsigned int thr_state; - struct tq_struct packet_task; struct tq_struct pio_task; unsigned int pio_task_state; unsigned long pio_task_timeout; - struct tq_struct probe_task; - void *private_data; }; @@ -314,10 +313,8 @@ struct ata_port_operations { void (*dev_config) (struct ata_port *, struct ata_device *); - void (*set_piomode) (struct ata_port *, struct ata_device *, - unsigned int); - void (*set_udmamode) (struct ata_port *, struct ata_device *, - unsigned int); + void (*set_piomode) (struct ata_port *, struct ata_device *); + void (*set_dmamode) (struct ata_port *, struct ata_device *); void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf); void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); @@ -330,10 +327,14 @@ struct ata_port_operations { void (*bmdma_setup) (struct ata_queued_cmd *qc); void (*bmdma_start) (struct ata_queued_cmd *qc); - void (*fill_sg) (struct ata_queued_cmd *qc); + + void (*qc_prep) (struct ata_queued_cmd *qc); + int (*qc_issue) (struct ata_queued_cmd *qc); + void (*eng_timeout) (struct ata_port *ap); irqreturn_t (*irq_handler)(int, void *, struct pt_regs *); + void (*irq_clear) (struct ata_port *); u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg); void (*scr_write) (struct ata_port *ap, unsigned int sc_reg, @@ -349,6 +350,7 @@ struct ata_port_info { Scsi_Host_Template *sht; unsigned long host_flags; unsigned long pio_mask; + unsigned long mwdma_mask; unsigned long udma_mask; struct ata_port_operations *port_ops; }; @@ -370,6 +372,7 @@ extern int ata_pci_init_one (struct pci_ extern void ata_pci_remove_one (struct pci_dev *pdev); extern int ata_device_add(struct ata_probe_ent *ent); extern int ata_scsi_detect(Scsi_Host_Template *sht); +extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_error(struct Scsi_Host *host); extern int ata_scsi_release(struct Scsi_Host *host); @@ -390,18 +393,25 @@ extern void ata_exec_command_mmio(struct extern int ata_port_start (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); -extern void ata_fill_sg(struct ata_queued_cmd *qc); +extern void ata_qc_prep(struct ata_queued_cmd *qc); +extern int ata_qc_issue_prot(struct ata_queued_cmd *qc); +extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, + unsigned int buflen); +extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, + unsigned int n_elem); extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s, unsigned int ofs, unsigned int len); extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc); extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc); extern void ata_bmdma_setup_pio (struct ata_queued_cmd *qc); extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc); +extern void ata_bmdma_irq_clear(struct ata_port *ap); extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits); extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat); extern void ata_eng_timeout(struct ata_port *ap); extern void ata_add_to_probe_list (struct ata_probe_ent *probe_ent); extern int ata_std_bios_param(Disk * disk, kdev_t dev, int *ip); +extern void libata_msleep(unsigned long msecs); static inline unsigned long msecs_to_jiffies(unsigned long msecs) @@ -476,7 +486,6 @@ static inline u8 ata_wait_idle(struct at static inline void ata_qc_set_polling(struct ata_queued_cmd *qc) { - qc->flags &= ~ATA_QCFLAG_DMA; qc->tf.ctl |= ATA_NIEN; } @@ -502,6 +511,7 @@ static inline void ata_tf_init(struct at static inline u8 ata_irq_on(struct ata_port *ap) { struct ata_ioports *ioaddr = &ap->ioaddr; + u8 tmp; ap->ctl &= ~ATA_NIEN; ap->last_ctl = ap->ctl; @@ -510,7 +520,11 @@ static inline u8 ata_irq_on(struct ata_p writeb(ap->ctl, ioaddr->ctl_addr); else outb(ap->ctl, ioaddr->ctl_addr); - return ata_wait_idle(ap); + tmp = ata_wait_idle(ap); + + ap->ops->irq_clear(ap); + + return tmp; } static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) @@ -559,4 +573,51 @@ static inline unsigned int sata_dev_pres return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0; } +static inline void ata_bmdma_stop(struct ata_port *ap) +{ + if (ap->flags & ATA_FLAG_MMIO) { + void *mmio = (void *) ap->ioaddr.bmdma_addr; + + /* clear start/stop bit */ + writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START, + mmio + ATA_DMA_CMD); + } else { + /* clear start/stop bit */ + outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, + ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + } + + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_altstatus(ap); /* dummy read */ +} + +static inline void ata_bmdma_ack_irq(struct ata_port *ap) +{ + if (ap->flags & ATA_FLAG_MMIO) { + void *mmio = ((void *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; + writeb(readb(mmio), mmio); + } else { + unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; + outb(inb(addr), addr); + } +} + +static inline u8 ata_bmdma_status(struct ata_port *ap) +{ + u8 host_stat; + if (ap->flags & ATA_FLAG_MMIO) { + void *mmio = (void *) ap->ioaddr.bmdma_addr; + host_stat = readb(mmio + ATA_DMA_STATUS); + } else + host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + return host_stat; +} + +static inline int ata_try_flush_cache(struct ata_device *dev) +{ + return ata_id_wcache_enabled(dev) || + ata_id_has_flush(dev) || + ata_id_has_flush_ext(dev); +} + #endif /* __LINUX_LIBATA_H__ */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/mm.h linux-2.4.28-pre3/include/linux/mm.h --- linux-2.4.27/include/linux/mm.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/mm.h 2004-09-10 19:32:15.000000000 +0000 @@ -308,11 +308,9 @@ typedef struct page { /* Make it prettier to test the above... */ #define UnlockPage(page) unlock_page(page) #define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags) -#define SetPageUptodate(page) \ - do { \ - arch_set_page_uptodate(page); \ - set_bit(PG_uptodate, &(page)->flags); \ - } while (0) +#ifndef SetPageUptodate +#define SetPageUptodate(page) set_bit(PG_uptodate, &(page)->flags) +#endif #define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags) #define PageDirty(page) test_bit(PG_dirty, &(page)->flags) #define SetPageDirty(page) set_bit(PG_dirty, &(page)->flags) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/netdevice.h linux-2.4.28-pre3/include/linux/netdevice.h --- linux-2.4.27/include/linux/netdevice.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/netdevice.h 2004-09-10 19:36:57.000000000 +0000 @@ -352,8 +352,8 @@ struct net_device struct Qdisc *qdisc; struct Qdisc *qdisc_sleeping; - struct Qdisc *qdisc_list; struct Qdisc *qdisc_ingress; + struct list_head qdisc_list; unsigned long tx_queue_len; /* Max frames per queue allowed */ /* hard_start_xmit synchronizer */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack.h --- linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack.h 2004-09-10 19:36:54.000000000 +0000 @@ -249,6 +249,7 @@ extern void ip_ct_refresh(struct ip_conn /* Call me when a conntrack is destroyed. */ extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack); +extern int ip_ct_no_defrag; /* Returns new sk_buff, or NULL */ struct sk_buff * ip_ct_gather_frags(struct sk_buff *skb); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack_ftp.h linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack_ftp.h --- linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack_ftp.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack_ftp.h 2004-09-10 19:37:24.000000000 +0000 @@ -4,11 +4,6 @@ #ifdef __KERNEL__ -#include - -/* Protects ftp part of conntracks */ -DECLARE_LOCK_EXTERN(ip_ftp_lock); - #define FTP_PORT 21 #endif /* __KERNEL__ */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack_irc.h linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack_irc.h --- linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack_irc.h 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack_irc.h 2004-09-10 19:34:06.000000000 +0000 @@ -33,8 +33,6 @@ struct ip_ct_irc_master { #ifdef __KERNEL__ -#include - #define IRC_PORT 6667 struct dccproto { @@ -42,9 +40,6 @@ struct dccproto { int matchlen; }; -/* Protects irc part of conntracks */ -DECLARE_LOCK_EXTERN(ip_irc_lock); - #endif /* __KERNEL__ */ #endif /* _IP_CONNTRACK_IRC_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/nfsd/const.h linux-2.4.28-pre3/include/linux/nfsd/const.h --- linux-2.4.27/include/linux/nfsd/const.h 2003-06-13 14:51:38.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/nfsd/const.h 2004-09-10 19:35:42.000000000 +0000 @@ -12,6 +12,7 @@ #include #include #include +#include /* * Maximum protocol version supported by knfsd @@ -19,9 +20,16 @@ #define NFSSVC_MAXVERS 3 /* - * Maximum blocksize supported by daemon currently at 8K + * Maximum blocksize supported by daemon. We want the largest + * value which 1) fits in a UDP datagram less some headers + * 2) is a multiple of page size 3) can be successfully kmalloc()ed + * by each nfsd. */ -#define NFSSVC_MAXBLKSIZE (8*1024) +#if PAGE_SIZE > (16*1024) +#define NFSSVC_MAXBLKSIZE (32*1024) +#else +#define NFSSVC_MAXBLKSIZE (2*PAGE_SIZE) +#endif #ifdef __KERNEL__ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/nfsd/xdr3.h linux-2.4.28-pre3/include/linux/nfsd/xdr3.h --- linux-2.4.27/include/linux/nfsd/xdr3.h 2001-11-22 19:47:57.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/nfsd/xdr3.h 2004-09-10 19:33:43.000000000 +0000 @@ -41,7 +41,7 @@ struct nfsd3_writeargs { __u32 count; int stable; __u8 * data; - int len; + __u32 len; }; struct nfsd3_createargs { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/parport_pc.h linux-2.4.28-pre3/include/linux/parport_pc.h --- linux-2.4.27/include/linux/parport_pc.h 2001-11-14 22:52:47.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/parport_pc.h 2004-09-10 19:36:33.000000000 +0000 @@ -41,7 +41,7 @@ struct parport_pc_private { struct pci_dev *dev; }; -extern __inline__ void parport_pc_write_data(struct parport *p, unsigned char d) +static __inline__ void parport_pc_write_data(struct parport *p, unsigned char d) { #ifdef DEBUG_PARPORT printk (KERN_DEBUG "parport_pc_write_data(%p,0x%02x)\n", p, d); @@ -49,7 +49,7 @@ extern __inline__ void parport_pc_write_ outb(d, DATA(p)); } -extern __inline__ unsigned char parport_pc_read_data(struct parport *p) +static __inline__ unsigned char parport_pc_read_data(struct parport *p) { unsigned char val = inb (DATA (p)); #ifdef DEBUG_PARPORT @@ -124,17 +124,17 @@ static __inline__ unsigned char __parpor return ctr; } -extern __inline__ void parport_pc_data_reverse (struct parport *p) +static __inline__ void parport_pc_data_reverse (struct parport *p) { __parport_pc_frob_control (p, 0x20, 0x20); } -extern __inline__ void parport_pc_data_forward (struct parport *p) +static __inline__ void parport_pc_data_forward (struct parport *p) { __parport_pc_frob_control (p, 0x20, 0x00); } -extern __inline__ void parport_pc_write_control (struct parport *p, +static __inline__ void parport_pc_write_control (struct parport *p, unsigned char d) { const unsigned char wm = (PARPORT_CONTROL_STROBE | @@ -152,7 +152,7 @@ extern __inline__ void parport_pc_write_ __parport_pc_frob_control (p, wm, d & wm); } -extern __inline__ unsigned char parport_pc_read_control(struct parport *p) +static __inline__ unsigned char parport_pc_read_control(struct parport *p) { const unsigned char rm = (PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD | @@ -162,7 +162,7 @@ extern __inline__ unsigned char parport_ return priv->ctr & rm; /* Use soft copy */ } -extern __inline__ unsigned char parport_pc_frob_control (struct parport *p, +static __inline__ unsigned char parport_pc_frob_control (struct parport *p, unsigned char mask, unsigned char val) { @@ -189,18 +189,18 @@ extern __inline__ unsigned char parport_ return __parport_pc_frob_control (p, mask, val); } -extern __inline__ unsigned char parport_pc_read_status(struct parport *p) +static __inline__ unsigned char parport_pc_read_status(struct parport *p) { return inb(STATUS(p)); } -extern __inline__ void parport_pc_disable_irq(struct parport *p) +static __inline__ void parport_pc_disable_irq(struct parport *p) { __parport_pc_frob_control (p, 0x10, 0x00); } -extern __inline__ void parport_pc_enable_irq(struct parport *p) +static __inline__ void parport_pc_enable_irq(struct parport *p) { __parport_pc_frob_control (p, 0x10, 0x10); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/pci.h linux-2.4.28-pre3/include/linux/pci.h --- linux-2.4.27/include/linux/pci.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/pci.h 2004-09-10 19:34:46.000000000 +0000 @@ -835,7 +835,5 @@ extern int pci_pci_problems; #define PCIPCI_VSFX 16 #define PCIPCI_ALIMAGIK 32 -extern int pciehp_msi_quirk; - #endif /* __KERNEL__ */ #endif /* LINUX_PCI_H */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/pci_ids.h linux-2.4.28-pre3/include/linux/pci_ids.h --- linux-2.4.27/include/linux/pci_ids.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/pci_ids.h 2004-09-10 19:34:18.000000000 +0000 @@ -606,6 +606,7 @@ #define PCI_DEVICE_ID_HP_ZX1_IOC 0x122a #define PCI_DEVICE_ID_HP_PCIX_LBA 0x122e #define PCI_DEVICE_ID_HP_SX1000_IOC 0x127c +#define PCI_DEVICE_ID_HP_CISS 0x3210 #define PCI_VENDOR_ID_PCTECH 0x1042 #define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000 @@ -980,13 +981,16 @@ #define PCI_DEVICE_ID_NVIDIA_UVTNT2 0x002D #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE 0x0035 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA 0x0036 +#define PCI_DEVICE_ID_NVIDIA_MCP04_AUDIO 0x003a #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2 0x003e #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE 0x0053 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA 0x0054 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2 0x0055 +#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE 0x0085 +#define PCI_DEVICE_ID_NVIDIA_MCP2S_AUDIO 0x008a #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA 0x008e #define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0 #define PCI_DEVICE_ID_NVIDIA_NFORCE3 0x00d1 @@ -995,6 +999,7 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE3S 0x00e1 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA 0x00e3 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE 0x00e5 +#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO 0x00ea #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2 0x00ee #define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/pkt_sched.h linux-2.4.28-pre3/include/linux/pkt_sched.h --- linux-2.4.27/include/linux/pkt_sched.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/pkt_sched.h 2004-09-10 19:36:01.000000000 +0000 @@ -433,6 +433,16 @@ enum { #define TCA_ATM_MAX TCA_ATM_STATE /* Network emulator */ + +enum +{ + TCA_NETEM_UNSPEC, + TCA_NETEM_CORR, + TCA_NETEM_DELAY_DIST, +}; + +#define TCA_NETEM_MAX TCA_NETEM_DELAY_DIST + struct tc_netem_qopt { __u32 latency; /* added delay (us) */ @@ -443,4 +453,13 @@ struct tc_netem_qopt __u32 jitter; /* random jitter in latency (us) */ }; +struct tc_netem_corr +{ + __u32 delay_corr; /* delay correlation */ + __u32 loss_corr; /* packet loss correlation */ + __u32 dup_corr; /* duplicate correlation */ +}; + +#define NETEM_DIST_SCALE 8192 + #endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/rbtree.h linux-2.4.28-pre3/include/linux/rbtree.h --- linux-2.4.27/include/linux/rbtree.h 2001-11-22 19:46:18.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/rbtree.h 2004-09-10 19:34:03.000000000 +0000 @@ -121,6 +121,12 @@ rb_root_t; extern void rb_insert_color(rb_node_t *, rb_root_t *); extern void rb_erase(rb_node_t *, rb_root_t *); +/* Find logical next and previous nodes in a tree */ +extern rb_node_t *rb_next(rb_node_t *); +extern rb_node_t *rb_prev(rb_node_t *); +extern rb_node_t *rb_first(rb_root_t *); +extern rb_node_t *rb_last(rb_root_t *); + static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link) { node->rb_parent = parent; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/reiserfs_fs.h linux-2.4.28-pre3/include/linux/reiserfs_fs.h --- linux-2.4.27/include/linux/reiserfs_fs.h 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/reiserfs_fs.h 2004-09-10 19:36:41.000000000 +0000 @@ -1771,25 +1771,25 @@ int reiserfs_convert_objectid_map_v1(str /* stree.c */ int B_IS_IN_TREE(const struct buffer_head *); extern inline void copy_short_key (void * to, const void * from); -extern inline void copy_item_head(struct item_head * p_v_to, +extern void copy_item_head(struct item_head * p_v_to, const struct item_head * p_v_from); // first key is in cpu form, second - le -extern inline int comp_keys (const struct key * le_key, +extern int comp_keys (const struct key * le_key, const struct cpu_key * cpu_key); -extern inline int comp_short_keys (const struct key * le_key, +extern int comp_short_keys (const struct key * le_key, const struct cpu_key * cpu_key); -extern inline void le_key2cpu_key (struct cpu_key * to, const struct key * from); +extern void le_key2cpu_key (struct cpu_key * to, const struct key * from); // both are cpu keys -extern inline int comp_cpu_keys (const struct cpu_key *, const struct cpu_key *); -extern inline int comp_short_cpu_keys (const struct cpu_key *, +extern int comp_cpu_keys (const struct cpu_key *, const struct cpu_key *); +extern int comp_short_cpu_keys (const struct cpu_key *, const struct cpu_key *); -extern inline void cpu_key2cpu_key (struct cpu_key *, const struct cpu_key *); +extern void cpu_key2cpu_key (struct cpu_key *, const struct cpu_key *); // both are in le form -extern inline int comp_le_keys (const struct key *, const struct key *); -extern inline int comp_short_le_keys (const struct key *, const struct key *); +extern int comp_le_keys (const struct key *, const struct key *); +extern int comp_short_le_keys (const struct key *, const struct key *); // // get key version from on disk key - kludge @@ -1824,7 +1824,7 @@ int search_by_key (struct super_block *, int search_for_position_by_key (struct super_block * p_s_sb, const struct cpu_key * p_s_cpu_key, struct path * p_s_search_path); -extern inline void decrement_bcount (struct buffer_head * p_s_bh); +extern void decrement_bcount (struct buffer_head * p_s_bh); void decrement_counters_in_path (struct path * p_s_search_path); void pathrelse (struct path * p_s_search_path); int reiserfs_check_path(struct path *p) ; @@ -1902,7 +1902,7 @@ void sd_attrs_to_i_attrs( __u16 sd_attrs void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs ); /* namei.c */ -inline void set_de_name_and_namelen (struct reiserfs_dir_entry * de); +void set_de_name_and_namelen (struct reiserfs_dir_entry * de); int search_by_entry_key (struct super_block * sb, const struct cpu_key * key, struct path * path, struct reiserfs_dir_entry * de); @@ -2050,7 +2050,7 @@ int balance_internal (struct tree_balanc struct buffer_head **); /* do_balance.c */ -inline void do_balance_mark_leaf_dirty (struct tree_balance * tb, +void do_balance_mark_leaf_dirty (struct tree_balance * tb, struct buffer_head * bh, int flag); #define do_balance_mark_internal_dirty do_balance_mark_leaf_dirty #define do_balance_mark_sb_dirty do_balance_mark_leaf_dirty diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/sched.h linux-2.4.28-pre3/include/linux/sched.h --- linux-2.4.27/include/linux/sched.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/sched.h 2004-09-10 19:32:37.000000000 +0000 @@ -763,7 +763,7 @@ extern struct mm_struct * start_lazy_tlb extern void end_lazy_tlb(struct mm_struct *mm); /* mmdrop drops the mm and the page tables */ -extern inline void FASTCALL(__mmdrop(struct mm_struct *)); +extern void FASTCALL(__mmdrop(struct mm_struct *)); static inline void mmdrop(struct mm_struct * mm) { if (atomic_dec_and_test(&mm->mm_count)) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/usb.h linux-2.4.28-pre3/include/linux/usb.h --- linux-2.4.27/include/linux/usb.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/include/linux/usb.h 2004-09-10 19:34:29.000000000 +0000 @@ -828,6 +828,8 @@ struct usb_device { atomic_t refcnt; /* Reference count */ struct semaphore serialize; + struct semaphore exclusive_access; /* prevent driver & proc accesses */ + /* from overlapping cmds at device */ unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */ unsigned int halted[2]; /* endpoint halts; one bit per endpoint # & direction; */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/if_inet6.h linux-2.4.28-pre3/include/net/if_inet6.h --- linux-2.4.27/include/net/if_inet6.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/include/net/if_inet6.h 2004-09-10 19:37:07.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * * This program is free software; you can redistribute it and/or diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/ip.h linux-2.4.28-pre3/include/net/ip.h --- linux-2.4.27/include/net/ip.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/include/net/ip.h 2004-09-10 19:35:52.000000000 +0000 @@ -137,7 +137,7 @@ struct ip_reply_arg { void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg, unsigned int len); -extern __inline__ int ip_finish_output(struct sk_buff *skb); +extern int ip_finish_output(struct sk_buff *skb); struct ipv4_config { @@ -228,6 +228,7 @@ extern int ip_call_ra_chain(struct sk_bu */ struct sk_buff *ip_defrag(struct sk_buff *skb); +extern void ipfrag_flush(void); extern int ip_frag_nqueues; extern atomic_t ip_frag_mem; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/ip6_fib.h linux-2.4.28-pre3/include/net/ip6_fib.h --- linux-2.4.27/include/net/ip6_fib.h 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/include/net/ip6_fib.h 2004-09-10 19:36:10.000000000 +0000 @@ -2,7 +2,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/ipv6.h linux-2.4.28-pre3/include/net/ipv6.h --- linux-2.4.27/include/net/ipv6.h 2004-04-14 13:05:40.000000000 +0000 +++ linux-2.4.28-pre3/include/net/ipv6.h 2004-09-10 19:36:28.000000000 +0000 @@ -2,7 +2,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * $Id: ipv6.h,v 1.23 2000/12/13 18:31:48 davem Exp $ * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/irda/irlmp_frame.h linux-2.4.28-pre3/include/net/irda/irlmp_frame.h --- linux-2.4.27/include/net/irda/irlmp_frame.h 2000-12-11 21:33:22.000000000 +0000 +++ linux-2.4.28-pre3/include/net/irda/irlmp_frame.h 2004-09-10 19:33:34.000000000 +0000 @@ -40,7 +40,7 @@ #define CONTROL_BIT 0x80 -inline void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, +void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, int expedited, struct sk_buff *skb); void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, __u8 opcode, struct sk_buff *skb); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/irda/timer.h linux-2.4.28-pre3/include/net/irda/timer.h --- linux-2.4.27/include/net/irda/timer.h 2001-11-09 22:22:17.000000000 +0000 +++ linux-2.4.28-pre3/include/net/irda/timer.h 2004-09-10 19:32:03.000000000 +0000 @@ -72,21 +72,21 @@ typedef void (*TIMER_CALLBACK)(void *); void irda_start_timer(struct timer_list *ptimer, int timeout, void* data, TIMER_CALLBACK callback); -inline void irlap_start_slot_timer(struct irlap_cb *self, int timeout); -inline void irlap_start_query_timer(struct irlap_cb *self, int timeout); -inline void irlap_start_final_timer(struct irlap_cb *self, int timeout); -inline void irlap_start_wd_timer(struct irlap_cb *self, int timeout); -inline void irlap_start_backoff_timer(struct irlap_cb *self, int timeout); +void irlap_start_slot_timer(struct irlap_cb *self, int timeout); +void irlap_start_query_timer(struct irlap_cb *self, int timeout); +void irlap_start_final_timer(struct irlap_cb *self, int timeout); +void irlap_start_wd_timer(struct irlap_cb *self, int timeout); +void irlap_start_backoff_timer(struct irlap_cb *self, int timeout); void irlap_start_mbusy_timer(struct irlap_cb *self, int timeout); void irlap_stop_mbusy_timer(struct irlap_cb *); struct lsap_cb; struct lap_cb; -inline void irlmp_start_watchdog_timer(struct lsap_cb *, int timeout); -inline void irlmp_start_discovery_timer(struct irlmp_cb *, int timeout); -inline void irlmp_start_idle_timer(struct lap_cb *, int timeout); -inline void irlmp_stop_idle_timer(struct lap_cb *self); +void irlmp_start_watchdog_timer(struct lsap_cb *, int timeout); +void irlmp_start_discovery_timer(struct irlmp_cb *, int timeout); +void irlmp_start_idle_timer(struct lap_cb *, int timeout); +void irlmp_stop_idle_timer(struct lap_cb *self); #endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/neighbour.h linux-2.4.28-pre3/include/net/neighbour.h --- linux-2.4.27/include/net/neighbour.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/include/net/neighbour.h 2004-09-10 19:37:07.000000000 +0000 @@ -5,7 +5,7 @@ * Generic neighbour manipulation * * Authors: - * Pedro Roque + * Pedro Roque * Alexey Kuznetsov */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/pkt_sched.h linux-2.4.28-pre3/include/net/pkt_sched.h --- linux-2.4.27/include/net/pkt_sched.h 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/include/net/pkt_sched.h 2004-09-10 19:33:03.000000000 +0000 @@ -80,11 +80,11 @@ struct Qdisc #define TCQ_F_THROTTLED 2 #define TCQ_F_INGRES 4 struct Qdisc_ops *ops; - struct Qdisc *next; u32 handle; atomic_t refcnt; struct sk_buff_head q; struct net_device *dev; + struct list_head list; struct tc_stats stats; int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/sctp/command.h linux-2.4.28-pre3/include/net/sctp/command.h --- linux-2.4.27/include/net/sctp/command.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/net/sctp/command.h 2004-09-10 19:36:21.000000000 +0000 @@ -94,6 +94,9 @@ typedef enum { SCTP_CMD_REPORT_FWDTSN, /* Report new cumulative TSN Ack. */ SCTP_CMD_PROCESS_FWDTSN, /* Skips were reported, so process further. */ SCTP_CMD_CLEAR_INIT_TAG, /* Clears association peer's inittag. */ + SCTP_CMD_DEL_NON_PRIMARY, /* Removes non-primary peer transports. */ + SCTP_CMD_T3_RTX_TIMERS_STOP, /* Stops T3-rtx pending timers */ + SCTP_CMD_FORCE_PRIM_RETRAN, /* Forces retrans. over primary path. */ SCTP_CMD_LAST } sctp_verb_t; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/sctp/constants.h linux-2.4.28-pre3/include/net/sctp/constants.h --- linux-2.4.27/include/net/sctp/constants.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/net/sctp/constants.h 2004-09-10 19:31:59.000000000 +0000 @@ -175,6 +175,10 @@ typedef enum { SCTP_IERROR_BAD_TAG, SCTP_IERROR_BIG_GAP, SCTP_IERROR_DUP_TSN, + SCTP_IERROR_HIGH_TSN, + SCTP_IERROR_IGNORE_TSN, + SCTP_IERROR_NO_DATA, + SCTP_IERROR_BAD_STREAM, } sctp_ierror_t; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/sctp/sm.h linux-2.4.28-pre3/include/net/sctp/sm.h --- linux-2.4.27/include/net/sctp/sm.h 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/include/net/sctp/sm.h 2004-09-10 19:33:49.000000000 +0000 @@ -322,6 +322,9 @@ void sctp_send_stale_cookie_err(const st const struct sctp_chunk *chunk, sctp_cmd_seq_t *commands, struct sctp_chunk *err_chunk); +int sctp_eat_data(const struct sctp_association *asoc, + struct sctp_chunk *chunk, + sctp_cmd_seq_t *commands); /* 3rd level prototypes */ __u32 sctp_generate_tag(const struct sctp_endpoint *); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/scsi/scsi.h linux-2.4.28-pre3/include/scsi/scsi.h --- linux-2.4.27/include/scsi/scsi.h 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/include/scsi/scsi.h 2004-09-10 19:37:12.000000000 +0000 @@ -91,6 +91,7 @@ #define WRITE_LONG_2 0xea #define READ_16 0x88 #define WRITE_16 0x8a +#define VERIFY_16 0x8f #define SERVICE_ACTION_IN 0x9e /* values for service action in */ #define SAI_READ_CAPACITY_16 0x10 diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/kernel/fork.c linux-2.4.28-pre3/kernel/fork.c --- linux-2.4.27/kernel/fork.c 2004-04-14 13:05:40.000000000 +0000 +++ linux-2.4.28-pre3/kernel/fork.c 2004-09-10 19:32:37.000000000 +0000 @@ -39,7 +39,7 @@ int last_pid; struct task_struct *pidhash[PIDHASH_SZ]; -void add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait) +void fastcall add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait) { unsigned long flags; @@ -49,7 +49,7 @@ void add_wait_queue(wait_queue_head_t *q wq_write_unlock_irqrestore(&q->lock, flags); } -void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait) +void fastcall add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait) { unsigned long flags; @@ -59,7 +59,7 @@ void add_wait_queue_exclusive(wait_queue wq_write_unlock_irqrestore(&q->lock, flags); } -void remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait) +void fastcall remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait) { unsigned long flags; @@ -264,7 +264,7 @@ struct mm_struct * mm_alloc(void) * is dropped: either by a lazy thread or by * mmput. Free the page directory and the mm. */ -inline void __mmdrop(struct mm_struct *mm) +void fastcall __mmdrop(struct mm_struct *mm) { BUG_ON(mm == &init_mm); pgd_free(mm->pgd); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/kernel/panic.c linux-2.4.28-pre3/kernel/panic.c --- linux-2.4.27/kernel/panic.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/kernel/panic.c 2004-09-10 19:36:59.000000000 +0000 @@ -59,7 +59,7 @@ NORET_TYPE void panic(const char * fmt, bust_spinlocks(1); va_start(args, fmt); - vsprintf(buf, fmt, args); + vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); printk(KERN_EMERG "Kernel panic: %s\n",buf); if (in_interrupt()) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/kernel/sched.c linux-2.4.28-pre3/kernel/sched.c --- linux-2.4.27/kernel/sched.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/kernel/sched.c 2004-09-10 19:36:20.000000000 +0000 @@ -209,7 +209,7 @@ static inline int preemption_goodness(st */ static FASTCALL(void reschedule_idle(struct task_struct * p)); -static void reschedule_idle(struct task_struct * p) +static void fastcall reschedule_idle(struct task_struct * p) { #ifdef CONFIG_SMP int this_cpu = smp_processor_id(); @@ -367,7 +367,7 @@ out: return success; } -inline int wake_up_process(struct task_struct * p) +inline int fastcall wake_up_process(struct task_struct * p) { return try_to_wake_up(p, 0); } @@ -405,7 +405,7 @@ static void process_timeout(unsigned lon * * In all cases the return value is guaranteed to be non-negative. */ -signed long schedule_timeout(signed long timeout) +signed long fastcall schedule_timeout(signed long timeout) { struct timer_list timer; unsigned long expire; @@ -735,7 +735,7 @@ static inline void __wake_up_common (wai } } -void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr) +void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode, int nr) { if (q) { unsigned long flags; @@ -745,7 +745,7 @@ void __wake_up(wait_queue_head_t *q, uns } } -void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr) +void fastcall __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr) { if (q) { unsigned long flags; @@ -755,7 +755,7 @@ void __wake_up_sync(wait_queue_head_t *q } } -void complete(struct completion *x) +void fastcall complete(struct completion *x) { unsigned long flags; @@ -765,7 +765,7 @@ void complete(struct completion *x) spin_unlock_irqrestore(&x->wait.lock, flags); } -void wait_for_completion(struct completion *x) +void fastcall wait_for_completion(struct completion *x) { spin_lock_irq(&x->wait.lock); if (!x->done) { @@ -800,7 +800,7 @@ void wait_for_completion(struct completi __remove_wait_queue(q, &wait); \ wq_write_unlock_irqrestore(&q->lock,flags); -void interruptible_sleep_on(wait_queue_head_t *q) +void fastcall interruptible_sleep_on(wait_queue_head_t *q) { SLEEP_ON_VAR @@ -811,7 +811,7 @@ void interruptible_sleep_on(wait_queue_h SLEEP_ON_TAIL } -long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout) +long fastcall interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout) { SLEEP_ON_VAR @@ -824,7 +824,7 @@ long interruptible_sleep_on_timeout(wait return timeout; } -void sleep_on(wait_queue_head_t *q) +void fastcall sleep_on(wait_queue_head_t *q) { SLEEP_ON_VAR @@ -835,7 +835,7 @@ void sleep_on(wait_queue_head_t *q) SLEEP_ON_TAIL } -long sleep_on_timeout(wait_queue_head_t *q, long timeout) +long fastcall sleep_on_timeout(wait_queue_head_t *q, long timeout) { SLEEP_ON_VAR diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/kernel/softirq.c linux-2.4.28-pre3/kernel/softirq.c --- linux-2.4.27/kernel/softirq.c 2002-11-28 23:53:15.000000000 +0000 +++ linux-2.4.28-pre3/kernel/softirq.c 2004-09-10 19:33:21.000000000 +0000 @@ -111,7 +111,7 @@ restart: /* * This function must run with irq disabled! */ -inline void cpu_raise_softirq(unsigned int cpu, unsigned int nr) +inline fastcall void cpu_raise_softirq(unsigned int cpu, unsigned int nr) { __cpu_raise_softirq(cpu, nr); @@ -128,7 +128,7 @@ inline void cpu_raise_softirq(unsigned i wakeup_softirqd(cpu); } -void raise_softirq(unsigned int nr) +void fastcall raise_softirq(unsigned int nr) { unsigned long flags; @@ -149,7 +149,7 @@ void open_softirq(int nr, void (*action) struct tasklet_head tasklet_vec[NR_CPUS] __cacheline_aligned; struct tasklet_head tasklet_hi_vec[NR_CPUS] __cacheline_aligned; -void __tasklet_schedule(struct tasklet_struct *t) +void fastcall __tasklet_schedule(struct tasklet_struct *t) { int cpu = smp_processor_id(); unsigned long flags; @@ -161,7 +161,7 @@ void __tasklet_schedule(struct tasklet_s local_irq_restore(flags); } -void __tasklet_hi_schedule(struct tasklet_struct *t) +void fastcall __tasklet_hi_schedule(struct tasklet_struct *t) { int cpu = smp_processor_id(); unsigned long flags; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/kernel/sysctl.c linux-2.4.28-pre3/kernel/sysctl.c --- linux-2.4.27/kernel/sysctl.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/kernel/sysctl.c 2004-09-10 19:32:38.000000000 +0000 @@ -879,7 +879,7 @@ static int do_proc_dointvec(ctl_table *t if (!isspace(c)) break; left--; - ((char *) buffer)++; + buffer++; } if (!left) break; @@ -1032,7 +1032,7 @@ int proc_dointvec_minmax(ctl_table *tabl if (!isspace(c)) break; left--; - ((char *) buffer)++; + buffer++; } if (!left) break; @@ -1133,7 +1133,7 @@ static int do_proc_doulongvec_minmax(ctl if (!isspace(c)) break; left--; - ((char *) buffer)++; + buffer++; } if (!left) break; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/lib/brlock.c linux-2.4.28-pre3/lib/brlock.c --- linux-2.4.27/lib/brlock.c 2001-11-09 22:11:15.000000000 +0000 +++ linux-2.4.28-pre3/lib/brlock.c 2004-09-10 19:35:56.000000000 +0000 @@ -20,7 +20,7 @@ brlock_read_lock_t __brlock_array[NR_CPUS][__BR_IDX_MAX] = { [0 ... NR_CPUS-1] = { [0 ... __BR_IDX_MAX-1] = RW_LOCK_UNLOCKED } }; -void __br_write_lock (enum brlock_indices idx) +void fastcall __br_write_lock (enum brlock_indices idx) { int i; @@ -28,7 +28,7 @@ void __br_write_lock (enum brlock_indice write_lock(&__brlock_array[cpu_logical_map(i)][idx]); } -void __br_write_unlock (enum brlock_indices idx) +void fastcall __br_write_unlock (enum brlock_indices idx) { int i; @@ -44,7 +44,7 @@ brlock_read_lock_t __brlock_array[NR_CPU struct br_wrlock __br_write_locks[__BR_IDX_MAX] = { [0 ... __BR_IDX_MAX-1] = { SPIN_LOCK_UNLOCKED } }; -void __br_write_lock (enum brlock_indices idx) +void fastcall __br_write_lock (enum brlock_indices idx) { int i; @@ -59,7 +59,7 @@ again: } } -void __br_write_unlock (enum brlock_indices idx) +void fastcall __br_write_unlock (enum brlock_indices idx) { spin_unlock(&__br_write_locks[idx].lock); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/lib/crc32.c linux-2.4.28-pre3/lib/crc32.c --- linux-2.4.27/lib/crc32.c 2004-04-14 13:05:40.000000000 +0000 +++ linux-2.4.28-pre3/lib/crc32.c 2004-09-10 19:31:52.000000000 +0000 @@ -99,7 +99,9 @@ u32 attribute((pure)) crc32_le(u32 crc, /* Align it */ if(unlikely(((long)b)&3 && len)){ do { - DO_CRC(*((u8 *)b)++); + u8 *p = (u8 *)b; + DO_CRC(*p++); + b = (void *)p; } while ((--len) && ((long)b)&3 ); } if(likely(len >= 4)){ @@ -120,7 +122,9 @@ u32 attribute((pure)) crc32_le(u32 crc, /* And the last few bytes */ if(len){ do { - DO_CRC(*((u8 *)b)++); + u8 *p = (u8 *)b; + DO_CRC(*p++); + b = (void *)p; } while (--len); } @@ -200,7 +204,9 @@ u32 attribute((pure)) crc32_be(u32 crc, /* Align it */ if(unlikely(((long)b)&3 && len)){ do { - DO_CRC(*((u8 *)b)++); + u8 *p = (u8 *)b; + DO_CRC(*p++); + b = (u32 *)p; } while ((--len) && ((long)b)&3 ); } if(likely(len >= 4)){ @@ -221,7 +227,9 @@ u32 attribute((pure)) crc32_be(u32 crc, /* And the last few bytes */ if(len){ do { - DO_CRC(*((u8 *)b)++); + u8 *p = (u8 *)b; + DO_CRC(*p++); + b = (void *)p; } while (--len); } return __be32_to_cpu(crc); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/lib/rbtree.c linux-2.4.28-pre3/lib/rbtree.c --- linux-2.4.27/lib/rbtree.c 2002-08-03 00:39:46.000000000 +0000 +++ linux-2.4.28-pre3/lib/rbtree.c 2004-09-10 19:35:37.000000000 +0000 @@ -294,3 +294,74 @@ void rb_erase(rb_node_t * node, rb_root_ __rb_erase_color(child, parent, root); } EXPORT_SYMBOL(rb_erase); + +/* + * This function returns the first node (in sort order) of the tree. + */ +rb_node_t *rb_first(rb_root_t *root) +{ + rb_node_t *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_left) + n = n->rb_left; + return n; +} +EXPORT_SYMBOL(rb_first); + +rb_node_t *rb_last(rb_root_t *root) +{ + rb_node_t *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_right) + n = n->rb_right; + return n; +} +EXPORT_SYMBOL(rb_last); + +rb_node_t *rb_next(rb_node_t *node) +{ + /* If we have a right-hand child, go down and then left as far + as we can. */ + if (node->rb_right) { + node = node->rb_right; + while (node->rb_left) + node = node->rb_left; + } + + /* No right-hand children. Everything down and left is + smaller than us, so any 'next' node must be in the general + direction of our parent. Go up the tree; any time the + ancestor is a right-hand child of its parent, keep going + up. First time it's a left-hand child of its parent, said + parent is our 'next' node. */ + while (node->rb_parent && node == node->rb_parent->rb_right) + node = node->rb_parent; + + return node->rb_parent; +} +EXPORT_SYMBOL(rb_next); + +rb_node_t *rb_prev(rb_node_t *node) +{ + /* If we have a left-hand child, go down and then right as far + as we can. */ + if (node->rb_left) { + node = node->rb_left; + while (node->rb_right) + node = node->rb_right; + } + + /* No left-hand children. Go up till we find an ancestor which + is a right-hand child of its parent */ + while (node->rb_parent && node == node->rb_parent->rb_left) + node = node->rb_parent; + + return node->rb_parent; +} +EXPORT_SYMBOL(rb_prev); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/lib/rwsem.c linux-2.4.28-pre3/lib/rwsem.c --- linux-2.4.27/lib/rwsem.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/lib/rwsem.c 2004-09-10 19:32:08.000000000 +0000 @@ -160,7 +160,7 @@ static inline struct rw_semaphore *rwsem /* * wait for the read lock to be granted */ -struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem) +struct rw_semaphore fastcall *rwsem_down_read_failed(struct rw_semaphore *sem) { struct rwsem_waiter waiter; @@ -176,7 +176,7 @@ struct rw_semaphore *rwsem_down_read_fai /* * wait for the write lock to be granted */ -struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem) +struct rw_semaphore fastcall *rwsem_down_write_failed(struct rw_semaphore *sem) { struct rwsem_waiter waiter; @@ -193,7 +193,7 @@ struct rw_semaphore *rwsem_down_write_fa * handle waking up a waiter on the semaphore * - up_read has decremented the active part of the count if we come here */ -struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem) +struct rw_semaphore fastcall *rwsem_wake(struct rw_semaphore *sem) { rwsemtrace(sem,"Entering rwsem_wake"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/lib/string.c linux-2.4.28-pre3/lib/string.c --- linux-2.4.27/lib/string.c 2002-08-03 00:39:46.000000000 +0000 +++ linux-2.4.28-pre3/lib/string.c 2004-09-10 19:36:36.000000000 +0000 @@ -380,14 +380,13 @@ void * memset(void * s,int c,size_t coun * You should not use this function to access IO space, use memcpy_toio() * or memcpy_fromio() instead. */ -char * bcopy(const char * src, char * dest, int count) +void bcopy(const void * srcp, void * destp, size_t count) { - char *tmp = dest; + const char *src = srcp; + char *dest = destp; while (count--) - *tmp++ = *src++; - - return dest; + *dest++ = *src++; } #endif diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/filemap.c linux-2.4.28-pre3/mm/filemap.c --- linux-2.4.27/mm/filemap.c 2004-04-14 13:05:41.000000000 +0000 +++ linux-2.4.28-pre3/mm/filemap.c 2004-09-10 19:33:53.000000000 +0000 @@ -68,7 +68,7 @@ spinlock_cacheline_t pagemap_lru_lock_ca #define CLUSTER_OFFSET(x) (((x) >> page_cluster) << page_cluster) static void FASTCALL(add_page_to_hash_queue(struct page * page, struct page **p)); -static void add_page_to_hash_queue(struct page * page, struct page **p) +static void fastcall add_page_to_hash_queue(struct page * page, struct page **p) { struct page *next = *p; @@ -151,7 +151,7 @@ static inline int sync_page(struct page /* * Add a page to the dirty page list. */ -void set_page_dirty(struct page *page) +void fastcall set_page_dirty(struct page *page) { if (!test_and_set_bit(PG_dirty, &page->flags)) { struct address_space *mapping = page->mapping; @@ -260,7 +260,7 @@ static void truncate_complete_page(struc } static int FASTCALL(truncate_list_pages(struct list_head *, unsigned long, unsigned *)); -static int truncate_list_pages(struct list_head *head, unsigned long start, unsigned *partial) +static int fastcall truncate_list_pages(struct list_head *head, unsigned long start, unsigned *partial) { struct list_head *curr; struct page * page; @@ -382,7 +382,7 @@ static inline int invalidate_this_page2( } static int FASTCALL(invalidate_list_pages2(struct list_head *)); -static int invalidate_list_pages2(struct list_head *head) +static int fastcall invalidate_list_pages2(struct list_head *head) { struct list_head *curr; struct page * page; @@ -755,7 +755,7 @@ int add_to_page_cache_unique(struct page * and schedules an I/O to read in its contents from disk. */ static int FASTCALL(page_cache_read(struct file * file, unsigned long offset)); -static int page_cache_read(struct file * file, unsigned long offset) +static int fastcall page_cache_read(struct file * file, unsigned long offset) { struct address_space *mapping = file->f_dentry->d_inode->i_mapping; struct page **hash = page_hash(mapping, offset); @@ -790,7 +790,7 @@ static int page_cache_read(struct file * */ static int FASTCALL(read_cluster_nonblocking(struct file * file, unsigned long offset, unsigned long filesize)); -static int read_cluster_nonblocking(struct file * file, unsigned long offset, +static int fastcall read_cluster_nonblocking(struct file * file, unsigned long offset, unsigned long filesize) { unsigned long pages = CLUSTER_PAGES; @@ -871,7 +871,7 @@ static inline wait_queue_head_t *page_wa * callbacks that would result into the blkdev layer waking * up the page after a queue unplug. */ -void wakeup_page_waiters(struct page * page) +void fastcall wakeup_page_waiters(struct page * page) { wait_queue_head_t * head; @@ -927,7 +927,7 @@ void ___wait_on_page(struct page *page) * of the waiters for all of the pages in the appropriate * wait queue are woken. */ -void unlock_page(struct page *page) +void fastcall unlock_page(struct page *page) { wait_queue_head_t *waitqueue = page_waitqueue(page); ClearPageLaunder(page); @@ -974,7 +974,7 @@ static void __lock_page(struct page *pag * Get an exclusive lock on the page, optimistically * assuming it's not locked.. */ -void lock_page(struct page *page) +void fastcall lock_page(struct page *page) { if (TryLockPage(page)) __lock_page(page); @@ -1025,7 +1025,7 @@ struct page *find_trylock_page(struct ad * during blocking operations.. */ static struct page * FASTCALL(__find_lock_page_helper(struct address_space *, unsigned long, struct page *)); -static struct page * __find_lock_page_helper(struct address_space *mapping, +static struct page * fastcall __find_lock_page_helper(struct address_space *mapping, unsigned long offset, struct page *hash) { struct page *page; @@ -1388,7 +1388,7 @@ static void generic_file_readahead(int r * If it was already so marked, move it to the active queue and drop * the referenced bit. Otherwise, just mark it for future action.. */ -void mark_page_accessed(struct page *page) +void fastcall mark_page_accessed(struct page *page) { if (!PageActive(page) && PageReferenced(page)) { activate_page(page); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/highmem.c linux-2.4.28-pre3/mm/highmem.c --- linux-2.4.27/mm/highmem.c 2003-06-13 14:51:39.000000000 +0000 +++ linux-2.4.28-pre3/mm/highmem.c 2004-09-10 19:35:33.000000000 +0000 @@ -129,7 +129,7 @@ start: return vaddr; } -void *kmap_high(struct page *page, int nonblocking) +void fastcall *kmap_high(struct page *page, int nonblocking) { unsigned long vaddr; @@ -154,7 +154,7 @@ void *kmap_high(struct page *page, int n return (void*) vaddr; } -void kunmap_high(struct page *page) +void fastcall kunmap_high(struct page *page) { unsigned long vaddr; unsigned long nr; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/memory.c linux-2.4.28-pre3/mm/memory.c --- linux-2.4.27/mm/memory.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/mm/memory.c 2004-09-10 19:34:37.000000000 +0000 @@ -1396,7 +1396,7 @@ int handle_mm_fault(struct mm_struct *mm * On a two-level page table, this ends up actually being entirely * optimized away. */ -pmd_t *__pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address) +pmd_t fastcall *__pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address) { pmd_t *new; @@ -1430,7 +1430,7 @@ out: * We've already handled the fast-path in-line, and we own the * page table lock. */ -pte_t *pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address) +pte_t fastcall *pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address) { if (pmd_none(*pmd)) { pte_t *new; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/oom_kill.c linux-2.4.28-pre3/mm/oom_kill.c --- linux-2.4.27/mm/oom_kill.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/mm/oom_kill.c 2004-09-10 19:31:52.000000000 +0000 @@ -141,7 +141,7 @@ static struct task_struct * select_bad_p * CAP_SYS_RAW_IO set, send SIGTERM instead (but it's unlikely that * we select a process with CAP_SYS_RAW_IO set). */ -void oom_kill_task(struct task_struct *p) +static void __oom_kill_task(struct task_struct *p) { printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n", p->pid, p->comm); @@ -161,6 +161,26 @@ void oom_kill_task(struct task_struct *p } } +static struct mm_struct *oom_kill_task(struct task_struct *p) +{ + struct mm_struct *mm; + + task_lock(p); + mm = p->mm; + if (mm) { + spin_lock(&mmlist_lock); + if (atomic_read(&mm->mm_users)) + atomic_inc(&mm->mm_users); + else + mm = NULL; + spin_unlock(&mmlist_lock); + } + task_unlock(p); + if (mm) + __oom_kill_task(p); + return mm; +} + /** * oom_kill - kill the "best" process when we run out of memory * @@ -172,21 +192,27 @@ void oom_kill_task(struct task_struct *p static void oom_kill(void) { struct task_struct *p, *q; + struct mm_struct *mm; +retry: read_lock(&tasklist_lock); p = select_bad_process(); /* Found nothing?!?! Either we hang forever, or we panic. */ if (p == NULL) panic("Out of memory and no killable processes...\n"); - + mm = oom_kill_task(p); + if (!mm) { + read_unlock(&tasklist_lock); + goto retry; + } /* kill all processes that share the ->mm (i.e. all threads) */ for_each_task(q) { - if (q->mm == p->mm) - oom_kill_task(q); + if (q->mm == mm) + __oom_kill_task(q); } read_unlock(&tasklist_lock); - + mmput(mm); /* * Make kswapd go out of the way, so "p" has a good chance of * killing itself before someone else gets the chance to ask @@ -263,7 +289,7 @@ void out_of_memory(void) spin_lock(&oom_lock); reset: - if (first < now) + if ((long)first - (long)now < 0) first = now; count = 0; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/page_alloc.c linux-2.4.28-pre3/mm/page_alloc.c --- linux-2.4.27/mm/page_alloc.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/mm/page_alloc.c 2004-09-10 19:32:27.000000000 +0000 @@ -109,7 +109,7 @@ static struct tq_struct free_pages_ok_no * -- wli */ -static void __free_pages_ok (struct page *page, unsigned int order) +static void fastcall __free_pages_ok (struct page *page, unsigned int order) { unsigned long index, page_idx, mask, flags; free_area_t *area; @@ -239,7 +239,7 @@ static inline struct page * expand (zone } static FASTCALL(struct page * rmqueue(zone_t *zone, unsigned int order)); -static struct page * rmqueue(zone_t *zone, unsigned int order) +static struct page * fastcall rmqueue(zone_t *zone, unsigned int order) { free_area_t * area = zone->free_area + order; unsigned int curr_order = order; @@ -285,7 +285,7 @@ static struct page * rmqueue(zone_t *zon } #ifndef CONFIG_DISCONTIGMEM -struct page *_alloc_pages(unsigned int gfp_mask, unsigned int order) +struct page * fastcall _alloc_pages(unsigned int gfp_mask, unsigned int order) { return __alloc_pages(gfp_mask, order, contig_page_data.node_zonelists+(gfp_mask & GFP_ZONEMASK)); @@ -293,7 +293,7 @@ struct page *_alloc_pages(unsigned int g #endif static struct page * FASTCALL(balance_classzone(zone_t *, unsigned int, unsigned int, int *)); -static struct page * balance_classzone(zone_t * classzone, unsigned int gfp_mask, unsigned int order, int * freed) +static struct page * fastcall balance_classzone(zone_t * classzone, unsigned int gfp_mask, unsigned int order, int * freed) { struct page * page = NULL; int __freed; @@ -371,7 +371,7 @@ static inline unsigned long zone_free_pa /* * This is the 'heart' of the zoned buddy allocator: */ -struct page * __alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist) +struct page * fastcall __alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist) { zone_t **zone, * classzone; struct page * page; @@ -484,7 +484,7 @@ struct page * __alloc_pages(unsigned int /* * Common helper functions. */ -unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order) +fastcall unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order) { struct page * page; @@ -494,7 +494,7 @@ unsigned long __get_free_pages(unsigned return (unsigned long) page_address(page); } -unsigned long get_zeroed_page(unsigned int gfp_mask) +fastcall unsigned long get_zeroed_page(unsigned int gfp_mask) { struct page * page; @@ -507,13 +507,13 @@ unsigned long get_zeroed_page(unsigned i return 0; } -void __free_pages(struct page *page, unsigned int order) +fastcall void __free_pages(struct page *page, unsigned int order) { if (!PageReserved(page) && put_page_testzero(page)) __free_pages_ok(page, order); } -void free_pages(unsigned long addr, unsigned int order) +fastcall void free_pages(unsigned long addr, unsigned int order) { if (addr != 0) __free_pages(virt_to_page(addr), order); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/slab.c linux-2.4.28-pre3/mm/slab.c --- linux-2.4.27/mm/slab.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/mm/slab.c 2004-09-10 19:36:16.000000000 +0000 @@ -1735,7 +1735,7 @@ static void enable_all_cpucaches (void) * * Called from do_try_to_free_pages() and __alloc_pages() */ -int kmem_cache_reap (int gfp_mask) +int fastcall kmem_cache_reap (int gfp_mask) { slab_t *slabp; kmem_cache_t *searchp; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/swap.c linux-2.4.28-pre3/mm/swap.c --- linux-2.4.27/mm/swap.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/mm/swap.c 2004-09-10 19:34:11.000000000 +0000 @@ -44,7 +44,7 @@ static inline void activate_page_nolock( } } -void activate_page(struct page * page) +void fastcall activate_page(struct page * page) { spin_lock(&pagemap_lru_lock); activate_page_nolock(page); @@ -55,7 +55,7 @@ void activate_page(struct page * page) * lru_cache_add: add a page to the page lists * @page: the page to add */ -void lru_cache_add(struct page * page) +void fastcall lru_cache_add(struct page * page) { if (!PageLRU(page)) { spin_lock(&pagemap_lru_lock); @@ -72,7 +72,7 @@ void lru_cache_add(struct page * page) * This function is for when the caller already holds * the pagemap_lru_lock. */ -void __lru_cache_del(struct page * page) +void fastcall __lru_cache_del(struct page * page) { if (TestClearPageLRU(page)) { if (PageActive(page)) { @@ -87,7 +87,7 @@ void __lru_cache_del(struct page * page) * lru_cache_del: remove a page from the page lists * @page: the page to remove */ -void lru_cache_del(struct page * page) +void fastcall lru_cache_del(struct page * page) { spin_lock(&pagemap_lru_lock); __lru_cache_del(page); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/swapfile.c linux-2.4.28-pre3/mm/swapfile.c --- linux-2.4.27/mm/swapfile.c 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/mm/swapfile.c 2004-09-10 19:33:06.000000000 +0000 @@ -256,7 +256,7 @@ static int exclusive_swap_page(struct pa * work, but we opportunistically check whether * we need to get all the locks first.. */ -int can_share_swap_page(struct page *page) +int fastcall can_share_swap_page(struct page *page) { int retval = 0; @@ -284,7 +284,7 @@ int can_share_swap_page(struct page *pag * Work out if there are any other processes sharing this * swap cache page. Free it if you can. Return success. */ -int remove_exclusive_swap_page(struct page *page) +int fastcall remove_exclusive_swap_page(struct page *page) { int retval; struct swap_info_struct * p; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/vmscan.c linux-2.4.28-pre3/mm/vmscan.c --- linux-2.4.27/mm/vmscan.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/mm/vmscan.c 2004-09-10 19:32:44.000000000 +0000 @@ -323,7 +323,7 @@ out_unlock: } static int FASTCALL(swap_out(zone_t * classzone)); -static int swap_out(zone_t * classzone) +static int fastcall swap_out(zone_t * classzone) { int counter, nr_pages = SWAP_CLUSTER_MAX; struct mm_struct *mm; @@ -366,7 +366,7 @@ empty: static void FASTCALL(refill_inactive(int nr_pages, zone_t * classzone)); static int FASTCALL(shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask, int * failed_swapout)); -static int shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask, int * failed_swapout) +static int fastcall shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask, int * failed_swapout) { struct list_head * entry; int max_scan = (classzone->nr_inactive_pages + classzone->nr_active_pages) / vm_cache_scan_ratio; @@ -577,7 +577,7 @@ page_mapped: * We move them the other way when we see the * reference bit on the page. */ -static void refill_inactive(int nr_pages, zone_t * classzone) +static void fastcall refill_inactive(int nr_pages, zone_t * classzone) { struct list_head * entry; unsigned long ratio; @@ -610,7 +610,7 @@ static void refill_inactive(int nr_pages } static int FASTCALL(shrink_caches(zone_t * classzone, unsigned int gfp_mask, int nr_pages, int * failed_swapout)); -static int shrink_caches(zone_t * classzone, unsigned int gfp_mask, int nr_pages, int * failed_swapout) +static int fastcall shrink_caches(zone_t * classzone, unsigned int gfp_mask, int nr_pages, int * failed_swapout) { nr_pages -= kmem_cache_reap(gfp_mask); if (nr_pages <= 0) @@ -627,7 +627,7 @@ out: static int check_classzone_need_balance(zone_t * classzone); -int try_to_free_pages_zone(zone_t *classzone, unsigned int gfp_mask) +int fastcall try_to_free_pages_zone(zone_t *classzone, unsigned int gfp_mask) { gfp_mask = pf_gfp_mask(gfp_mask); @@ -665,7 +665,7 @@ int try_to_free_pages_zone(zone_t *class return 0; } -int try_to_free_pages(unsigned int gfp_mask) +int fastcall try_to_free_pages(unsigned int gfp_mask) { pg_data_t *pgdat; zonelist_t *zonelist; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/appletalk/ddp.c linux-2.4.28-pre3/net/appletalk/ddp.c --- linux-2.4.27/net/appletalk/ddp.c 2001-09-10 14:57:00.000000000 +0000 +++ linux-2.4.28-pre3/net/appletalk/ddp.c 2004-09-10 19:37:18.000000000 +0000 @@ -106,8 +106,8 @@ extern void aarp_proxy_remove(struct net #endif /* APPLETALK_DEBUG */ #ifdef CONFIG_SYSCTL -extern inline void atalk_register_sysctl(void); -extern inline void atalk_unregister_sysctl(void); +extern void atalk_register_sysctl(void); +extern void atalk_unregister_sysctl(void); #endif /* CONFIG_SYSCTL */ struct datalink_proto *ddp_dl, *aarp_dl; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/atm/lec.c linux-2.4.28-pre3/net/atm/lec.c --- linux-2.4.27/net/atm/lec.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/net/atm/lec.c 2004-09-10 19:35:31.000000000 +0000 @@ -71,9 +71,9 @@ static int lec_send_packet(struct sk_buf static int lec_close(struct net_device *dev); static struct net_device_stats *lec_get_stats(struct net_device *dev); static void lec_init(struct net_device *dev); -static inline struct lec_arp_table* lec_arp_find(struct lec_priv *priv, +static struct lec_arp_table* lec_arp_find(struct lec_priv *priv, unsigned char *mac_addr); -static inline int lec_arp_remove(struct lec_priv *priv, +static int lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove); /* LANE2 functions */ static void lane2_associate_ind (struct net_device *dev, u8 *mac_address, @@ -1137,7 +1137,7 @@ lec_arp_add(struct lec_priv *priv, struc /* * Remove entry from lec_arp_table */ -static inline int +static int lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove) { @@ -1424,7 +1424,7 @@ lec_arp_destroy(struct lec_priv *priv) /* * Find entry by mac_address */ -static inline struct lec_arp_table* +static struct lec_arp_table* lec_arp_find(struct lec_priv *priv, unsigned char *mac_addr) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/bluetooth/l2cap.c linux-2.4.28-pre3/net/bluetooth/l2cap.c --- linux-2.4.27/net/bluetooth/l2cap.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/net/bluetooth/l2cap.c 2004-09-10 19:34:31.000000000 +0000 @@ -70,7 +70,7 @@ struct bluez_sock_list l2cap_sk_list = { static int l2cap_conn_del(struct hci_conn *conn, int err); -static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent); +static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent); static void l2cap_chan_del(struct sock *sk, int err); static int l2cap_chan_send(struct sock *sk, struct msghdr *msg, int len); @@ -420,6 +420,14 @@ done: return err; } +static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent) +{ + struct l2cap_chan_list *l = &conn->chan_list; + write_lock(&l->lock); + __l2cap_chan_add(conn, sk, parent); + write_unlock(&l->lock); +} + static int l2cap_do_connect(struct sock *sk) { bdaddr_t *src = &bluez_pi(sk)->src; @@ -897,14 +905,6 @@ static void __l2cap_chan_add(struct l2ca bluez_accept_enqueue(parent, sk); } -static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent) -{ - struct l2cap_chan_list *l = &conn->chan_list; - write_lock(&l->lock); - __l2cap_chan_add(conn, sk, parent); - write_unlock(&l->lock); -} - /* Delete channel. * Must be called on the locked socket. */ static void l2cap_chan_del(struct sock *sk, int err) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/bluetooth/rfcomm/core.c linux-2.4.28-pre3/net/bluetooth/rfcomm/core.c --- linux-2.4.27/net/bluetooth/rfcomm/core.c 2004-04-14 13:05:41.000000000 +0000 +++ linux-2.4.28-pre3/net/bluetooth/rfcomm/core.c 2004-09-10 19:35:38.000000000 +0000 @@ -406,7 +406,7 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d return len; } -void __rfcomm_dlc_throttle(struct rfcomm_dlc *d) +void fastcall __rfcomm_dlc_throttle(struct rfcomm_dlc *d) { BT_DBG("dlc %p state %ld", d, d->state); @@ -417,7 +417,7 @@ void __rfcomm_dlc_throttle(struct rfcomm rfcomm_schedule(RFCOMM_SCHED_TX); } -void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d) +void fastcall __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d) { BT_DBG("dlc %p state %ld", d, d->state); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/bluetooth/sco.c linux-2.4.28-pre3/net/bluetooth/sco.c --- linux-2.4.27/net/bluetooth/sco.c 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/net/bluetooth/sco.c 2004-09-10 19:37:14.000000000 +0000 @@ -67,9 +67,8 @@ static struct bluez_sock_list sco_sk_lis lock: RW_LOCK_UNLOCKED }; -static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent); +static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent); static void sco_chan_del(struct sock *sk, int err); -static inline struct sock * sco_chan_get(struct sco_conn *conn); static int sco_conn_del(struct hci_conn *conn, int err); @@ -150,6 +149,15 @@ static struct sco_conn *sco_conn_add(str return conn; } +static inline struct sock * sco_chan_get(struct sco_conn *conn) +{ + struct sock *sk = NULL; + sco_conn_lock(conn); + sk = conn->sk; + sco_conn_unlock(conn); + return sk; +} + static int sco_conn_del(struct hci_conn *hcon, int err) { struct sco_conn *conn; @@ -176,6 +184,20 @@ static int sco_conn_del(struct hci_conn return 0; } +static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent) +{ + int err = 0; + + sco_conn_lock(conn); + if (conn->sk) { + err = -EBUSY; + } else { + __sco_chan_add(conn, sk, parent); + } + sco_conn_unlock(conn); + return err; +} + int sco_connect(struct sock *sk) { bdaddr_t *src = &bluez_pi(sk)->src; @@ -743,29 +765,6 @@ static void __sco_chan_add(struct sco_co bluez_accept_enqueue(parent, sk); } -static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent) -{ - int err = 0; - - sco_conn_lock(conn); - if (conn->sk) { - err = -EBUSY; - } else { - __sco_chan_add(conn, sk, parent); - } - sco_conn_unlock(conn); - return err; -} - -static inline struct sock * sco_chan_get(struct sco_conn *conn) -{ - struct sock *sk = NULL; - sco_conn_lock(conn); - sk = conn->sk; - sco_conn_unlock(conn); - return sk; -} - /* Delete channel. * Must be called on the locked socket. */ static void sco_chan_del(struct sock *sk, int err) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/core/neighbour.c linux-2.4.28-pre3/net/core/neighbour.c --- linux-2.4.27/net/core/neighbour.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/net/core/neighbour.c 2004-09-10 19:32:17.000000000 +0000 @@ -2,7 +2,7 @@ * Generic address resolution entity * * Authors: - * Pedro Roque + * Pedro Roque * Alexey Kuznetsov * * This program is free software; you can redistribute it and/or diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/ip_fragment.c linux-2.4.28-pre3/net/ipv4/ip_fragment.c --- linux-2.4.27/net/ipv4/ip_fragment.c 2003-06-13 14:51:39.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv4/ip_fragment.c 2004-09-10 19:33:32.000000000 +0000 @@ -168,14 +168,18 @@ static void ipfrag_secret_rebuild(unsign atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */ /* Memory Tracking Functions. */ -static __inline__ void frag_kfree_skb(struct sk_buff *skb) +static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work) { + if (work) + *work -= skb->truesize; atomic_sub(skb->truesize, &ip_frag_mem); kfree_skb(skb); } -static __inline__ void frag_free_queue(struct ipq *qp) +static __inline__ void frag_free_queue(struct ipq *qp, int *work) { + if (work) + *work -= sizeof(struct ipq); atomic_sub(sizeof(struct ipq), &ip_frag_mem); kfree(qp); } @@ -194,7 +198,7 @@ static __inline__ struct ipq *frag_alloc /* Destruction primitives. */ /* Complete destruction of ipq. */ -static void ip_frag_destroy(struct ipq *qp) +static void ip_frag_destroy(struct ipq *qp, int *work) { struct sk_buff *fp; @@ -206,18 +210,18 @@ static void ip_frag_destroy(struct ipq * while (fp) { struct sk_buff *xp = fp->next; - frag_kfree_skb(fp); + frag_kfree_skb(fp, work); fp = xp; } /* Finally, release the queue descriptor itself. */ - frag_free_queue(qp); + frag_free_queue(qp, work); } -static __inline__ void ipq_put(struct ipq *ipq) +static __inline__ void ipq_put(struct ipq *ipq, int *work) { if (atomic_dec_and_test(&ipq->refcnt)) - ip_frag_destroy(ipq); + ip_frag_destroy(ipq, work); } /* Kill ipq entry. It is not destroyed immediately, @@ -236,16 +240,19 @@ static __inline__ void ipq_kill(struct i } /* Memory limiting on fragments. Evictor trashes the oldest - * fragment queue until we are back under the low threshold. + * fragment queue until we are back under the threshold. */ -static void ip_evictor(void) +static void __ip_evictor(int threshold) { struct ipq *qp; struct list_head *tmp; + int work; - for(;;) { - if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh) - return; + work = atomic_read(&ip_frag_mem) - threshold; + if (work <= 0) + return; + + while (work > 0) { read_lock(&ipfrag_lock); if (list_empty(&ipq_lru_list)) { read_unlock(&ipfrag_lock); @@ -261,11 +268,16 @@ static void ip_evictor(void) ipq_kill(qp); spin_unlock(&qp->lock); - ipq_put(qp); + ipq_put(qp, &work); IP_INC_STATS_BH(IpReasmFails); } } +static inline void ip_evictor(void) +{ + __ip_evictor(sysctl_ipfrag_low_thresh); +} + /* * Oops, a fragment queue timed out. Kill it and send an ICMP reply. */ @@ -293,7 +305,7 @@ static void ip_expire(unsigned long arg) } out: spin_unlock(&qp->lock); - ipq_put(qp); + ipq_put(qp, NULL); } /* Creation primitives. */ @@ -316,7 +328,7 @@ static struct ipq *ip_frag_intern(unsign atomic_inc(&qp->refcnt); write_unlock(&ipfrag_lock); qp_in->last_in |= COMPLETE; - ipq_put(qp_in); + ipq_put(qp_in, NULL); return qp; } } @@ -505,7 +517,7 @@ static void ip_frag_queue(struct ipq *qp qp->fragments = next; qp->meat -= free_it->len; - frag_kfree_skb(free_it); + frag_kfree_skb(free_it, NULL); } } @@ -656,7 +668,7 @@ struct sk_buff *ip_defrag(struct sk_buff ret = ip_frag_reasm(qp, dev); spin_unlock(&qp->lock); - ipq_put(qp); + ipq_put(qp, NULL); return ret; } @@ -675,3 +687,8 @@ void ipfrag_init(void) ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval; add_timer(&ipfrag_secret_timer); } + +void ipfrag_flush(void) +{ + __ip_evictor(0); +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/ip_output.c linux-2.4.28-pre3/net/ipv4/ip_output.c --- linux-2.4.27/net/ipv4/ip_output.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv4/ip_output.c 2004-09-10 19:37:11.000000000 +0000 @@ -184,7 +184,7 @@ static inline int ip_finish_output2(stru return -EINVAL; } -__inline__ int ip_finish_output(struct sk_buff *skb) +static __inline__ int __ip_finish_output(struct sk_buff *skb) { struct net_device *dev = skb->dst->dev; @@ -195,6 +195,11 @@ __inline__ int ip_finish_output(struct s ip_finish_output2); } +int ip_finish_output(struct sk_buff *skb) +{ + return __ip_finish_output(skb); +} + int ip_mc_output(struct sk_buff *skb) { struct sock *sk = skb->sk; @@ -253,7 +258,7 @@ int ip_mc_output(struct sk_buff *skb) newskb->dev, ip_dev_loopback_xmit); } - return ip_finish_output(skb); + return __ip_finish_output(skb); } int ip_output(struct sk_buff *skb) @@ -269,7 +274,7 @@ int ip_output(struct sk_buff *skb) ip_do_nat(skb); #endif - return ip_finish_output(skb); + return __ip_finish_output(skb); } /* Queues a packet to be sent, and starts the transmitter if necessary. diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/arp_tables.c linux-2.4.28-pre3/net/ipv4/netfilter/arp_tables.c --- linux-2.4.27/net/ipv4/netfilter/arp_tables.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv4/netfilter/arp_tables.c 2004-09-10 19:34:33.000000000 +0000 @@ -101,7 +101,7 @@ static inline int arp_packet_match(const { char *arpptr = (char *)(arphdr + 1); char *src_devaddr, *tgt_devaddr; - u32 *src_ipaddr, *tgt_ipaddr; + u32 src_ipaddr, tgt_ipaddr; int i, ret; #define FWINV(bool,invflg) ((bool) ^ !!(arpinfo->invflags & invflg)) @@ -140,11 +140,11 @@ static inline int arp_packet_match(const src_devaddr = arpptr; arpptr += dev->addr_len; - src_ipaddr = (u32 *) arpptr; + memcpy(&src_ipaddr, arpptr, sizeof(u32)); arpptr += sizeof(u32); tgt_devaddr = arpptr; arpptr += dev->addr_len; - tgt_ipaddr = (u32 *) arpptr; + memcpy(&tgt_ipaddr, arpptr, sizeof(u32)); if (FWINV(arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr, dev->addr_len), ARPT_INV_SRCDEVADDR) || @@ -155,19 +155,19 @@ static inline int arp_packet_match(const return 0; } - if (FWINV(((*src_ipaddr) & arpinfo->smsk.s_addr) != arpinfo->src.s_addr, + if (FWINV(((src_ipaddr) & arpinfo->smsk.s_addr) != arpinfo->src.s_addr, ARPT_INV_SRCIP) || - FWINV((((*tgt_ipaddr) & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr), + FWINV((((tgt_ipaddr) & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr), ARPT_INV_TGTIP)) { dprintf("Source or target IP address mismatch.\n"); dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n", - NIPQUAD(*src_ipaddr), + NIPQUAD(src_ipaddr), NIPQUAD(arpinfo->smsk.s_addr), NIPQUAD(arpinfo->src.s_addr), arpinfo->invflags & ARPT_INV_SRCIP ? " (INV)" : ""); dprintf("TGT: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n", - NIPQUAD(*tgt_ipaddr), + NIPQUAD(tgt_ipaddr), NIPQUAD(arpinfo->tmsk.s_addr), NIPQUAD(arpinfo->tgt.s_addr), arpinfo->invflags & ARPT_INV_TGTIP ? " (INV)" : ""); @@ -188,7 +188,10 @@ static inline int arp_packet_match(const } for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { - ret |= (((const unsigned long *)outdev)[i] + unsigned long odev; + memcpy(&odev, outdev + i*sizeof(unsigned long), + sizeof(unsigned long)); + ret |= (odev ^ ((const unsigned long *)arpinfo->outiface)[i]) & ((const unsigned long *)arpinfo->outiface_mask)[i]; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_core.c --- linux-2.4.27/net/ipv4/netfilter/ip_conntrack_core.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_core.c 2004-09-10 19:31:50.000000000 +0000 @@ -1183,6 +1183,8 @@ void ip_ct_refresh(struct ip_conntrack * WRITE_UNLOCK(&ip_conntrack_lock); } +int ip_ct_no_defrag; + /* Returns new sk_buff, or NULL */ struct sk_buff * ip_ct_gather_frags(struct sk_buff *skb) @@ -1191,6 +1193,12 @@ ip_ct_gather_frags(struct sk_buff *skb) #ifdef CONFIG_NETFILTER_DEBUG unsigned int olddebug = skb->nf_debug; #endif + + if (unlikely(ip_ct_no_defrag)) { + kfree_skb(skb); + return NULL; + } + if (sk) { sock_hold(sk); skb_orphan(skb); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_conntrack_ftp.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_ftp.c --- linux-2.4.27/net/ipv4/netfilter/ip_conntrack_ftp.c 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-09-10 19:36:16.000000000 +0000 @@ -11,7 +11,7 @@ #include #include -DECLARE_LOCK(ip_ftp_lock); +static DECLARE_LOCK(ip_ftp_lock); struct module *ip_conntrack_ftp = THIS_MODULE; #define MAX_PORTS 8 @@ -338,7 +338,6 @@ static int help(const struct iphdr *iph, memset(&expect, 0, sizeof(expect)); /* Update the ftp info */ - LOCK_BH(&ip_ftp_lock); if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]) == ct->tuplehash[dir].tuple.src.ip) { exp->seq = ntohl(tcph->seq) + matchoff; @@ -358,7 +357,8 @@ static int help(const struct iphdr *iph, for reporting this potential problem (DMZ machines opening holes to internal networks, or the packet filter itself). */ - if (!loose) goto out; + if (!loose) + return NF_ACCEPT; } exp->tuple = ((struct ip_conntrack_tuple) @@ -376,9 +376,6 @@ static int help(const struct iphdr *iph, /* Ignore failure; should only happen with NAT */ ip_conntrack_expect_related(ct, &expect); - out: - UNLOCK_BH(&ip_ftp_lock); - return NF_ACCEPT; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_conntrack_irc.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_irc.c --- linux-2.4.27/net/ipv4/netfilter/ip_conntrack_irc.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_irc.c 2004-09-10 19:36:14.000000000 +0000 @@ -29,7 +29,6 @@ #include #include -#include #include #include @@ -61,7 +60,6 @@ struct dccproto dccprotos[NUM_DCCPROTO] }; #define MINMATCHLEN 5 -DECLARE_LOCK(ip_irc_lock); struct module *ip_conntrack_irc = THIS_MODULE; #if 0 @@ -208,8 +206,6 @@ static int help(const struct iphdr *iph, memset(&expect, 0, sizeof(expect)); - LOCK_BH(&ip_irc_lock); - /* save position of address in dcc string, * neccessary for NAT */ DEBUGP("tcph->seq = %u\n", tcph->seq); @@ -236,8 +232,6 @@ static int help(const struct iphdr *iph, ntohs(exp->tuple.dst.u.tcp.port)); ip_conntrack_expect_related(ct, &expect); - UNLOCK_BH(&ip_irc_lock); - return NF_ACCEPT; } /* for .. NUM_DCCPROTO */ } /* while data < ... */ @@ -315,7 +309,5 @@ static void fini(void) } } -EXPORT_SYMBOL(ip_irc_lock); - module_init(init); module_exit(fini); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_standalone.c --- linux-2.4.27/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-08-07 23:26:06.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-09-10 19:34:35.000000000 +0000 @@ -393,6 +393,13 @@ static int init_or_cleanup(int init) cleanup_inandlocalops: nf_unregister_hook(&ip_conntrack_local_out_ops); cleanup_inops: + /* Frag queues may hold fragments with skb->dst == NULL */ + ip_ct_no_defrag = 1; + local_bh_disable(); + br_write_lock(BR_NETPROTO_LOCK); + br_write_unlock(BR_NETPROTO_LOCK); + ipfrag_flush(); + local_bh_enable(); nf_unregister_hook(&ip_conntrack_in_ops); cleanup_proc: proc_net_remove("ip_conntrack"); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_nat_ftp.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_ftp.c --- linux-2.4.27/net/ipv4/netfilter/ip_nat_ftp.c 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_ftp.c 2004-09-10 19:35:47.000000000 +0000 @@ -24,8 +24,6 @@ static int ports_c = 0; MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); #endif -DECLARE_LOCK_EXTERN(ip_ftp_lock); - /* FIXME: Time out? --RR */ static unsigned int @@ -48,8 +46,6 @@ ftp_nat_expected(struct sk_buff **pskb, DEBUGP("nat_expected: We have a connection!\n"); exp_ftp_info = &ct->master->help.exp_ftp_info; - LOCK_BH(&ip_ftp_lock); - if (exp_ftp_info->ftptype == IP_CT_FTP_PORT || exp_ftp_info->ftptype == IP_CT_FTP_EPRT) { /* PORT command: make connection go to the client. */ @@ -64,7 +60,6 @@ ftp_nat_expected(struct sk_buff **pskb, DEBUGP("nat_expected: PASV cmd. %u.%u.%u.%u->%u.%u.%u.%u\n", NIPQUAD(newsrcip), NIPQUAD(newdstip)); } - UNLOCK_BH(&ip_ftp_lock); if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) newip = newsrcip; @@ -100,8 +95,6 @@ mangle_rfc959_packet(struct sk_buff **ps { char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")]; - MUST_BE_LOCKED(&ip_ftp_lock); - sprintf(buffer, "%u,%u,%u,%u,%u,%u", NIPQUAD(newip), port>>8, port&0xFF); @@ -123,8 +116,6 @@ mangle_eprt_packet(struct sk_buff **pskb { char buffer[sizeof("|1|255.255.255.255|65535|")]; - MUST_BE_LOCKED(&ip_ftp_lock); - sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port); DEBUGP("calling ip_nat_mangle_tcp_packet\n"); @@ -145,8 +136,6 @@ mangle_epsv_packet(struct sk_buff **pskb { char buffer[sizeof("|||65535|")]; - MUST_BE_LOCKED(&ip_ftp_lock); - sprintf(buffer, "|||%u|", port); DEBUGP("calling ip_nat_mangle_tcp_packet\n"); @@ -166,7 +155,7 @@ static int (*mangle[])(struct sk_buff ** [IP_CT_FTP_EPSV] mangle_epsv_packet }; -static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info, +static int ftp_data_fixup(const struct ip_ct_ftp_expect *exp_ftp_info, struct ip_conntrack *ct, struct sk_buff **pskb, enum ip_conntrack_info ctinfo, @@ -178,15 +167,14 @@ static int ftp_data_fixup(const struct i u_int16_t port; struct ip_conntrack_tuple newtuple; - MUST_BE_LOCKED(&ip_ftp_lock); DEBUGP("FTP_NAT: seq %u + %u in %u\n", - expect->seq, ct_ftp_info->len, + expect->seq, exp_ftp_info->len, ntohl(tcph->seq)); /* Change address inside packet to match way we're mapping this connection. */ - if (ct_ftp_info->ftptype == IP_CT_FTP_PASV - || ct_ftp_info->ftptype == IP_CT_FTP_EPSV) { + if (exp_ftp_info->ftptype == IP_CT_FTP_PASV + || exp_ftp_info->ftptype == IP_CT_FTP_EPSV) { /* PASV/EPSV response: must be where client thinks server is */ newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; @@ -208,7 +196,7 @@ static int ftp_data_fixup(const struct i newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port; /* Try to get same port: if not, try to change it. */ - for (port = ct_ftp_info->port; port != 0; port++) { + for (port = exp_ftp_info->port; port != 0; port++) { newtuple.dst.u.tcp.port = htons(port); if (ip_conntrack_change_expect(expect, &newtuple) == 0) @@ -217,9 +205,9 @@ static int ftp_data_fixup(const struct i if (port == 0) return 0; - if (!mangle[ct_ftp_info->ftptype](pskb, newip, port, + if (!mangle[exp_ftp_info->ftptype](pskb, newip, port, expect->seq - ntohl(tcph->seq), - ct_ftp_info->len, ct, ctinfo)) + exp_ftp_info->len, ct, ctinfo)) return 0; return 1; @@ -236,12 +224,12 @@ static unsigned int help(struct ip_connt struct tcphdr *tcph = (void *)iph + iph->ihl*4; unsigned int datalen; int dir; - struct ip_ct_ftp_expect *ct_ftp_info; + struct ip_ct_ftp_expect *exp_ftp_info; if (!exp) DEBUGP("ip_nat_ftp: no exp!!"); - ct_ftp_info = &exp->help.exp_ftp_info; + exp_ftp_info = &exp->help.exp_ftp_info; /* Only mangle things once: original direction in POST_ROUTING and reply direction on PRE_ROUTING. */ @@ -257,29 +245,23 @@ static unsigned int help(struct ip_connt } datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4; - LOCK_BH(&ip_ftp_lock); /* If it's in the right range... */ - if (between(exp->seq + ct_ftp_info->len, + if (between(exp->seq + exp_ftp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen)) { - if (!ftp_data_fixup(ct_ftp_info, ct, pskb, ctinfo, exp)) { - UNLOCK_BH(&ip_ftp_lock); + if (!ftp_data_fixup(exp_ftp_info, ct, pskb, ctinfo, exp)) return NF_DROP; - } } else { /* Half a match? This means a partial retransmisison. It's a cracker being funky. */ if (net_ratelimit()) { printk("FTP_NAT: partial packet %u/%u in %u/%u\n", - exp->seq, ct_ftp_info->len, + exp->seq, exp_ftp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen); } - UNLOCK_BH(&ip_ftp_lock); return NF_DROP; } - UNLOCK_BH(&ip_ftp_lock); - return NF_ACCEPT; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_nat_irc.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_irc.c --- linux-2.4.27/net/ipv4/netfilter/ip_nat_irc.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_irc.c 2004-09-10 19:37:20.000000000 +0000 @@ -46,9 +46,6 @@ MODULE_PARM(ports, "1-" __MODULE_STRING( MODULE_PARM_DESC(ports, "port numbers of IRC servers"); #endif -/* protects irc part of conntracks */ -DECLARE_LOCK_EXTERN(ip_irc_lock); - /* FIXME: Time out? --RR */ static unsigned int @@ -89,7 +86,7 @@ irc_nat_expected(struct sk_buff **pskb, return ip_nat_setup_info(ct, &mr, hooknum); } -static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info, +static int irc_data_fixup(const struct ip_ct_irc_expect *exp_irc_info, struct ip_conntrack *ct, struct sk_buff **pskb, enum ip_conntrack_info ctinfo, @@ -104,23 +101,16 @@ static int irc_data_fixup(const struct i /* "4294967296 65635 " */ char buffer[18]; - MUST_BE_LOCKED(&ip_irc_lock); - DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n", - expect->seq, ct_irc_info->len, + expect->seq, exp_irc_info->len, ntohl(tcph->seq)); newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; /* Alter conntrack's expectations. */ - - /* We can read expect here without conntrack lock, since it's - only set in ip_conntrack_irc, with ip_irc_lock held - writable */ - t = expect->tuple; t.dst.ip = newip; - for (port = ct_irc_info->port; port != 0; port++) { + for (port = exp_irc_info->port; port != 0; port++) { t.dst.u.tcp.port = htons(port); if (ip_conntrack_change_expect(expect, &t) == 0) { DEBUGP("using port %d", port); @@ -150,7 +140,7 @@ static int irc_data_fixup(const struct i return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, expect->seq - ntohl(tcph->seq), - ct_irc_info->len, buffer, + exp_irc_info->len, buffer, strlen(buffer)); } @@ -165,12 +155,12 @@ static unsigned int help(struct ip_connt struct tcphdr *tcph = (void *) iph + iph->ihl * 4; unsigned int datalen; int dir; - struct ip_ct_irc_expect *ct_irc_info; + struct ip_ct_irc_expect *exp_irc_info; if (!exp) DEBUGP("ip_nat_irc: no exp!!"); - ct_irc_info = &exp->help.exp_irc_info; + exp_irc_info = &exp->help.exp_irc_info; /* Only mangle things once: original direction in POST_ROUTING and reply direction on PRE_ROUTING. */ @@ -187,30 +177,24 @@ static unsigned int help(struct ip_connt DEBUGP("got beyond not touching\n"); datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4; - LOCK_BH(&ip_irc_lock); /* Check wether the whole IP/address pattern is carried in the payload */ - if (between(exp->seq + ct_irc_info->len, + if (between(exp->seq + exp_irc_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen)) { - if (!irc_data_fixup(ct_irc_info, ct, pskb, ctinfo, exp)) { - UNLOCK_BH(&ip_irc_lock); + if (!irc_data_fixup(exp_irc_info, ct, pskb, ctinfo, exp)) return NF_DROP; - } } else { /* Half a match? This means a partial retransmisison. It's a cracker being funky. */ if (net_ratelimit()) { printk ("IRC_NAT: partial packet %u/%u in %u/%u\n", - exp->seq, ct_irc_info->len, + exp->seq, exp_irc_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen); } - UNLOCK_BH(&ip_irc_lock); return NF_DROP; } - UNLOCK_BH(&ip_irc_lock); - return NF_ACCEPT; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_nat_snmp_basic.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_snmp_basic.c --- linux-2.4.27/net/ipv4/netfilter/ip_nat_snmp_basic.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_snmp_basic.c 2004-09-10 19:36:28.000000000 +0000 @@ -862,6 +862,77 @@ static unsigned char snmp_request_decode return 1; } +/* + * Fast checksum update for possibly oddly-aligned UDP byte, from the + * code example in the draft. + */ +static void fast_csum(unsigned char *csum, + const unsigned char *optr, + const unsigned char *nptr, + int odd) +{ + long x, old, new; + + x = csum[0] * 256 + csum[1]; + + x =~ x & 0xFFFF; + + if (odd) old = optr[0] * 256; + else old = optr[0]; + + x -= old & 0xFFFF; + if (x <= 0) { + x--; + x &= 0xFFFF; + } + + if (odd) new = nptr[0] * 256; + else new = nptr[0]; + + x += new & 0xFFFF; + if (x & 0x10000) { + x++; + x &= 0xFFFF; + } + + x =~ x & 0xFFFF; + csum[0] = x / 256; + csum[1] = x & 0xFF; +} + +/* + * Mangle IP address. + * - begin points to the start of the snmp messgae + * - addr points to the start of the address + */ +static void inline mangle_address(unsigned char *begin, + unsigned char *addr, + const struct oct1_map *map, + u_int16_t *check) +{ + if (map->from == NOCT1(*addr)) { + u_int32_t old; + + if (debug) + memcpy(&old, (unsigned char *)addr, sizeof(old)); + + *addr = map->to; + + /* Update UDP checksum if being used */ + if (*check) { + unsigned char odd = !((addr - begin) % 2); + + fast_csum((unsigned char *)check, + &map->from, &map->to, odd); + + } + + if (debug) + printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to " + "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr)); + } +} + static unsigned char snmp_trap_decode(struct asn1_ctx *ctx, struct snmp_v1_trap *trap, const struct oct1_map *map, @@ -952,77 +1023,6 @@ static void hex_dump(unsigned char *buf, printk("\n"); } -/* - * Fast checksum update for possibly oddly-aligned UDP byte, from the - * code example in the draft. - */ -static void fast_csum(unsigned char *csum, - const unsigned char *optr, - const unsigned char *nptr, - int odd) -{ - long x, old, new; - - x = csum[0] * 256 + csum[1]; - - x =~ x & 0xFFFF; - - if (odd) old = optr[0] * 256; - else old = optr[0]; - - x -= old & 0xFFFF; - if (x <= 0) { - x--; - x &= 0xFFFF; - } - - if (odd) new = nptr[0] * 256; - else new = nptr[0]; - - x += new & 0xFFFF; - if (x & 0x10000) { - x++; - x &= 0xFFFF; - } - - x =~ x & 0xFFFF; - csum[0] = x / 256; - csum[1] = x & 0xFF; -} - -/* - * Mangle IP address. - * - begin points to the start of the snmp messgae - * - addr points to the start of the address - */ -static void inline mangle_address(unsigned char *begin, - unsigned char *addr, - const struct oct1_map *map, - u_int16_t *check) -{ - if (map->from == NOCT1(*addr)) { - u_int32_t old; - - if (debug) - memcpy(&old, (unsigned char *)addr, sizeof(old)); - - *addr = map->to; - - /* Update UDP checksum if being used */ - if (*check) { - unsigned char odd = !((addr - begin) % 2); - - fast_csum((unsigned char *)check, - &map->from, &map->to, odd); - - } - - if (debug) - printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to " - "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr)); - } -} - /* * Parse and mangle SNMP message according to mapping. * (And this is the fucking 'basic' method). diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/tcp_input.c linux-2.4.28-pre3/net/ipv4/tcp_input.c --- linux-2.4.27/net/ipv4/tcp_input.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv4/tcp_input.c 2004-09-10 19:33:09.000000000 +0000 @@ -851,8 +851,10 @@ static void tcp_init_metrics(struct sock * to low value, and then abruptly stops to do it and starts to delay * ACKs, wait for troubles. */ - if (dst->rtt > tp->srtt) + if (dst->rtt > tp->srtt) { tp->srtt = dst->rtt; + tp->rtt_seq = tp->snd_nxt; + } if (dst->rttvar > tp->mdev) { tp->mdev = dst->rttvar; tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/addrconf.c linux-2.4.28-pre3/net/ipv6/addrconf.c --- linux-2.4.27/net/ipv6/addrconf.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/addrconf.c 2004-09-10 19:36:55.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * Alexey Kuznetsov * * $Id: addrconf.c,v 1.69 2001/10/31 21:55:54 davem Exp $ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/af_inet6.c linux-2.4.28-pre3/net/ipv6/af_inet6.c --- linux-2.4.27/net/ipv6/af_inet6.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/af_inet6.c 2004-09-10 19:35:17.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * Adapted from linux/net/ipv4/af_inet.c * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/datagram.c linux-2.4.28-pre3/net/ipv6/datagram.c --- linux-2.4.27/net/ipv6/datagram.c 2003-06-13 14:51:39.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/datagram.c 2004-09-10 19:32:35.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * $Id: datagram.c,v 1.23 2001/09/01 00:31:50 davem Exp $ * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/exthdrs.c linux-2.4.28-pre3/net/ipv6/exthdrs.c --- linux-2.4.27/net/ipv6/exthdrs.c 2004-04-14 13:05:41.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/exthdrs.c 2004-09-10 19:32:16.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * Andi Kleen * Alexey Kuznetsov * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/icmp.c linux-2.4.28-pre3/net/ipv6/icmp.c --- linux-2.4.27/net/ipv6/icmp.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/icmp.c 2004-09-10 19:33:37.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * $Id: icmp.c,v 1.37 2001/09/18 22:29:10 davem Exp $ * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/ip6_fib.c linux-2.4.28-pre3/net/ipv6/ip6_fib.c --- linux-2.4.27/net/ipv6/ip6_fib.c 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/ip6_fib.c 2004-09-10 19:36:25.000000000 +0000 @@ -3,7 +3,7 @@ * Forwarding Information Database * * Authors: - * Pedro Roque + * Pedro Roque * * $Id: ip6_fib.c,v 1.25 2001/10/31 21:55:55 davem Exp $ * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/ip6_input.c linux-2.4.28-pre3/net/ipv6/ip6_input.c --- linux-2.4.27/net/ipv6/ip6_input.c 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/ip6_input.c 2004-09-10 19:36:09.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * Ian P. Morris * * $Id: ip6_input.c,v 1.19 2000/12/13 18:31:50 davem Exp $ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/ip6_output.c linux-2.4.28-pre3/net/ipv6/ip6_output.c --- linux-2.4.27/net/ipv6/ip6_output.c 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/ip6_output.c 2004-09-10 19:32:21.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * $Id: ip6_output.c,v 1.33 2001/09/20 00:35:35 davem Exp $ * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/ipv6_sockglue.c linux-2.4.28-pre3/net/ipv6/ipv6_sockglue.c --- linux-2.4.27/net/ipv6/ipv6_sockglue.c 2004-04-14 13:05:41.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/ipv6_sockglue.c 2004-09-10 19:32:28.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * Based on linux/net/ipv4/ip_sockglue.c * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/mcast.c linux-2.4.28-pre3/net/ipv6/mcast.c --- linux-2.4.27/net/ipv6/mcast.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/mcast.c 2004-09-10 19:36:36.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * $Id: mcast.c,v 1.38 2001/08/15 07:36:31 davem Exp $ * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/ndisc.c linux-2.4.28-pre3/net/ipv6/ndisc.c --- linux-2.4.27/net/ipv6/ndisc.c 2004-04-14 13:05:41.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/ndisc.c 2004-09-10 19:35:27.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * Mike Shaver * * This program is free software; you can redistribute it and/or diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/netfilter/ip6t_LOG.c linux-2.4.28-pre3/net/ipv6/netfilter/ip6t_LOG.c --- linux-2.4.27/net/ipv6/netfilter/ip6t_LOG.c 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/netfilter/ip6t_LOG.c 2004-09-10 19:33:38.000000000 +0000 @@ -56,7 +56,7 @@ static u_int8_t ip6_nexthdr(u_int8_t cur repeatedly...with a large stick...no, an even LARGER stick...no, you're still not thinking big enough */ nexthdr = **hdrptr; - hdrlen = *hdrptr[1] * 4 + 8; + hdrlen = (*hdrptr)[1] * 4 + 8; *hdrptr = *hdrptr + hdrlen; break; /*stupid rfc2402 */ @@ -64,7 +64,7 @@ static u_int8_t ip6_nexthdr(u_int8_t cur case IPPROTO_ROUTING: case IPPROTO_HOPOPTS: nexthdr = **hdrptr; - hdrlen = *hdrptr[1] * 8 + 8; + hdrlen = (*hdrptr)[1] * 8 + 8; *hdrptr = *hdrptr + hdrlen; break; case IPPROTO_FRAGMENT: diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/protocol.c linux-2.4.28-pre3/net/ipv6/protocol.c --- linux-2.4.27/net/ipv6/protocol.c 2001-05-20 00:56:43.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/protocol.c 2004-09-10 19:32:54.000000000 +0000 @@ -7,7 +7,7 @@ * * Version: $Id: protocol.c,v 1.10 2001/05/18 02:25:49 davem Exp $ * - * Authors: Pedro Roque + * Authors: Pedro Roque * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/raw.c linux-2.4.28-pre3/net/ipv6/raw.c --- linux-2.4.27/net/ipv6/raw.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/raw.c 2004-09-10 19:34:11.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * Adapted from linux/net/ipv4/raw.c * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/reassembly.c linux-2.4.28-pre3/net/ipv6/reassembly.c --- linux-2.4.27/net/ipv6/reassembly.c 2003-08-25 11:44:44.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/reassembly.c 2004-09-10 19:33:41.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * $Id: reassembly.c,v 1.26 2001/03/07 22:00:57 davem Exp $ * @@ -191,14 +191,18 @@ static void ip6_frag_secret_rebuild(unsi atomic_t ip6_frag_mem = ATOMIC_INIT(0); /* Memory Tracking Functions. */ -static inline void frag_kfree_skb(struct sk_buff *skb) +static inline void frag_kfree_skb(struct sk_buff *skb, int *work) { + if (work) + *work -= skb->truesize; atomic_sub(skb->truesize, &ip6_frag_mem); kfree_skb(skb); } -static inline void frag_free_queue(struct frag_queue *fq) +static inline void frag_free_queue(struct frag_queue *fq, int *work) { + if (work) + *work -= sizeof(struct frag_queue); atomic_sub(sizeof(struct frag_queue), &ip6_frag_mem); kfree(fq); } @@ -216,7 +220,7 @@ static inline struct frag_queue *frag_al /* Destruction primitives. */ /* Complete destruction of fq. */ -static void ip6_frag_destroy(struct frag_queue *fq) +static void ip6_frag_destroy(struct frag_queue *fq, int *work) { struct sk_buff *fp; @@ -228,17 +232,17 @@ static void ip6_frag_destroy(struct frag while (fp) { struct sk_buff *xp = fp->next; - frag_kfree_skb(fp); + frag_kfree_skb(fp, work); fp = xp; } - frag_free_queue(fq); + frag_free_queue(fq, work); } -static __inline__ void fq_put(struct frag_queue *fq) +static __inline__ void fq_put(struct frag_queue *fq, int *work) { if (atomic_dec_and_test(&fq->refcnt)) - ip6_frag_destroy(fq); + ip6_frag_destroy(fq, work); } /* Kill fq entry. It is not destroyed immediately, @@ -260,10 +264,13 @@ static void ip6_evictor(void) { struct frag_queue *fq; struct list_head *tmp; + int work; - for(;;) { - if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh) - return; + work = atomic_read(&ip6_frag_mem) - sysctl_ip6frag_low_thresh; + if (work <= 0) + return; + + while(work > 0) { read_lock(&ip6_frag_lock); if (list_empty(&ip6_frag_lru_list)) { read_unlock(&ip6_frag_lock); @@ -279,7 +286,7 @@ static void ip6_evictor(void) fq_kill(fq); spin_unlock(&fq->lock); - fq_put(fq); + fq_put(fq, &work); IP6_INC_STATS_BH(Ip6ReasmFails); } } @@ -316,7 +323,7 @@ static void ip6_frag_expire(unsigned lon } out: spin_unlock(&fq->lock); - fq_put(fq); + fq_put(fq, NULL); } /* Creation primitives. */ @@ -336,7 +343,7 @@ static struct frag_queue *ip6_frag_inter atomic_inc(&fq->refcnt); write_unlock(&ip6_frag_lock); fq_in->last_in |= COMPLETE; - fq_put(fq_in); + fq_put(fq_in, NULL); return fq; } } @@ -533,7 +540,7 @@ static void ip6_frag_queue(struct frag_q fq->fragments = next; fq->meat -= free_it->len; - frag_kfree_skb(free_it); + frag_kfree_skb(free_it, NULL); } } @@ -733,7 +740,7 @@ int ipv6_reassembly(struct sk_buff **skb ret = ip6_frag_reasm(fq, skbp, dev); spin_unlock(&fq->lock); - fq_put(fq); + fq_put(fq, NULL); return ret; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/route.c linux-2.4.28-pre3/net/ipv6/route.c --- linux-2.4.27/net/ipv6/route.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/route.c 2004-09-10 19:33:10.000000000 +0000 @@ -3,7 +3,7 @@ * FIB front-end. * * Authors: - * Pedro Roque + * Pedro Roque * * $Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $ * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/sit.c linux-2.4.28-pre3/net/ipv6/sit.c --- linux-2.4.27/net/ipv6/sit.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/sit.c 2004-09-10 19:36:53.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * Alexey Kuznetsov * * $Id: sit.c,v 1.53 2001/09/25 05:09:53 davem Exp $ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/tcp_ipv6.c linux-2.4.28-pre3/net/ipv6/tcp_ipv6.c --- linux-2.4.27/net/ipv6/tcp_ipv6.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/tcp_ipv6.c 2004-09-10 19:35:17.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * $Id: tcp_ipv6.c,v 1.142.2.1 2001/12/21 05:06:08 davem Exp $ * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/udp.c linux-2.4.28-pre3/net/ipv6/udp.c --- linux-2.4.27/net/ipv6/udp.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/ipv6/udp.c 2004-09-10 19:36:30.000000000 +0000 @@ -3,7 +3,7 @@ * Linux INET6 implementation * * Authors: - * Pedro Roque + * Pedro Roque * * Based on linux/ipv4/udp.c * diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipx/af_ipx.c linux-2.4.28-pre3/net/ipx/af_ipx.c --- linux-2.4.27/net/ipx/af_ipx.c 2001-09-30 19:26:13.000000000 +0000 +++ linux-2.4.28-pre3/net/ipx/af_ipx.c 2004-09-10 19:32:54.000000000 +0000 @@ -1544,7 +1544,8 @@ static int ipxrtr_route_packet(struct so ipx->ipx_pktsize = htons(len + sizeof(struct ipxhdr)); IPX_SKB_CB(skb)->ipx_tctrl = 0; ipx->ipx_type = usipx->sipx_type; - skb->h.raw = (void *)skb->nh.ipxh = ipx; + skb->nh.ipxh = ipx; + skb->h.raw = (void *)skb->nh.ipxh; IPX_SKB_CB(skb)->last_hop.index = -1; #ifdef CONFIG_IPX_INTERN diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/irda/ircomm/ircomm_param.c linux-2.4.28-pre3/net/irda/ircomm/ircomm_param.c --- linux-2.4.27/net/irda/ircomm/ircomm_param.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/net/irda/ircomm/ircomm_param.c 2004-09-10 19:34:52.000000000 +0000 @@ -198,7 +198,7 @@ static int ircomm_param_service_type(voi IRDA_DEBUG(2, "%s(), No common service type to use!\n", __FUNCTION__); return -1; } - IRDA_DEBUG(0, __FUNCTION__ "%s(), services in common=%02x\n", __FUNCTION__, + IRDA_DEBUG(0, "%s(), services in common=%02x\n", __FUNCTION__ , service_type); /* diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/irda/irlmp.c linux-2.4.28-pre3/net/irda/irlmp.c --- linux-2.4.27/net/irda/irlmp.c 2003-06-13 14:51:39.000000000 +0000 +++ linux-2.4.28-pre3/net/irda/irlmp.c 2004-09-10 19:36:47.000000000 +0000 @@ -1241,7 +1241,7 @@ void irlmp_flow_indication(struct lap_cb /* Get the number of lsap. That's the only safe way to know * that we have looped around... - Jean II */ lsap_todo = HASHBIN_GET_SIZE(self->lsaps); - IRDA_DEBUG(4, __FUNCTION__ "() : %d lsaps to scan\n", lsap_todo); + IRDA_DEBUG(4, "%s() : %d lsaps to scan\n", __FUNCTION__ , lsap_todo); /* Poll lsap in order until the queue is full or until we * tried them all. @@ -1255,7 +1255,7 @@ void irlmp_flow_indication(struct lap_cb /* Note that if there is only one LSAP on the LAP * (most common case), self->flow_next is always NULL, * so we always avoid this loop. - Jean II */ - IRDA_DEBUG(4, __FUNCTION__ "() : searching my LSAP\n"); + IRDA_DEBUG(4, "%s() : searching my LSAP\n", __FUNCTION__ ); /* We look again in hashbins, because the lsap * might have gone away... - Jean II */ @@ -1274,14 +1274,14 @@ void irlmp_flow_indication(struct lap_cb /* Next time, we will get the next one (or the first one) */ self->flow_next = (struct lsap_cb *) hashbin_get_next(self->lsaps); - IRDA_DEBUG(4, __FUNCTION__ "() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap)); + IRDA_DEBUG(4, "%s() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", __FUNCTION__ , curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap)); /* Inform lsap user that it can send one more packet. */ if (curr->notify.flow_indication != NULL) curr->notify.flow_indication(curr->notify.instance, curr, flow); else - IRDA_DEBUG(1, __FUNCTION__ "(), no handler\n"); + IRDA_DEBUG(1, "%s(), no handler\n", __FUNCTION__ ); } } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/irda/wrapper.c linux-2.4.28-pre3/net/irda/wrapper.c --- linux-2.4.27/net/irda/wrapper.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/net/irda/wrapper.c 2004-09-10 19:36:09.000000000 +0000 @@ -37,8 +37,6 @@ #include #include -static inline int stuff_byte(__u8 byte, __u8 *buf); - static void state_outside_frame(struct net_device *dev, struct net_device_stats *stats, iobuff_t *rx_buff, __u8 byte); @@ -62,6 +60,32 @@ static void (*state[])(struct net_device }; /* + * Function stuff_byte (byte, buf) + * + * Byte stuff one single byte and put the result in buffer pointed to by + * buf. The buffer must at all times be able to have two bytes inserted. + * + */ +static inline int stuff_byte(__u8 byte, __u8 *buf) +{ + switch (byte) { + case BOF: /* FALLTHROUGH */ + case EOF: /* FALLTHROUGH */ + case CE: + /* Insert transparently coded */ + buf[0] = CE; /* Send link escape */ + buf[1] = byte^IRDA_TRANS; /* Complement bit 5 */ + return 2; + /* break; */ + default: + /* Non-special value, no transparency required */ + buf[0] = byte; + return 1; + /* break; */ + } +} + +/* * Function async_wrap (skb, *tx_buff, buffsize) * * Makes a new buffer with wrapping and stuffing, should check that @@ -140,32 +164,6 @@ int async_wrap_skb(struct sk_buff *skb, } /* - * Function stuff_byte (byte, buf) - * - * Byte stuff one single byte and put the result in buffer pointed to by - * buf. The buffer must at all times be able to have two bytes inserted. - * - */ -static inline int stuff_byte(__u8 byte, __u8 *buf) -{ - switch (byte) { - case BOF: /* FALLTHROUGH */ - case EOF: /* FALLTHROUGH */ - case CE: - /* Insert transparently coded */ - buf[0] = CE; /* Send link escape */ - buf[1] = byte^IRDA_TRANS; /* Complement bit 5 */ - return 2; - /* break; */ - default: - /* Non-special value, no transparency required */ - buf[0] = byte; - return 1; - /* break; */ - } -} - -/* * Function async_bump (buf, len, stats) * * Got a frame, make a copy of it, and pass it up the stack! We can try diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/netlink/af_netlink.c linux-2.4.28-pre3/net/netlink/af_netlink.c --- linux-2.4.27/net/netlink/af_netlink.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/net/netlink/af_netlink.c 2004-09-10 19:34:55.000000000 +0000 @@ -42,6 +42,7 @@ #include #include #include +#include #define Nprintk(a...) @@ -63,6 +64,15 @@ struct netlink_opt void (*data_ready)(struct sock *sk, int bytes); }; +struct netlink_work +{ + struct sock *sk; + int len; + struct tq_struct work; +}; + +static DECLARE_TASK_QUEUE(tq_netlink); +static DECLARE_WAIT_QUEUE_HEAD(netlink_thread_wait); static struct sock *nl_table[MAX_LINKS]; static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait); static unsigned nl_nonroot[MAX_LINKS]; @@ -81,6 +91,15 @@ static atomic_t nl_table_users = ATOMIC_ static struct notifier_block *netlink_chain; +void netlink_tq_handler(void *data) +{ + struct netlink_work *work = data; + + work->sk->data_ready(work->sk, work->len); + sock_put(work->sk); + kfree(work); +} + static void netlink_sock_destruct(struct sock *sk) { skb_queue_purge(&sk->receive_queue); @@ -437,6 +456,8 @@ retry: if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf || test_bit(0, &sk->protinfo.af_netlink->state)) { + struct task_struct *client; + if (!timeo) { if (ssk->protinfo.af_netlink->pid == 0) netlink_overrun(sk); @@ -445,6 +466,19 @@ retry: return -EAGAIN; } + if (!sk->protinfo.af_netlink->pid) { + /* Kernel is sending information to user space + * and socket buffer is full: Wake up user */ + + client = find_task_by_pid(sk->protinfo.af_netlink->pid); + if (!client) { + sock_put(sk); + kfree_skb(skb); + return -EAGAIN; + } + wake_up_process(client); + } + __set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&sk->protinfo.af_netlink->wait, &wait); @@ -467,8 +501,26 @@ retry: skb_orphan(skb); skb_set_owner_r(skb, sk); skb_queue_tail(&sk->receive_queue, skb); - sk->data_ready(sk, len); - sock_put(sk); + + if (!sk->protinfo.af_netlink->pid) { + struct netlink_work *nlwork = + kmalloc(sizeof(struct netlink_work), GFP_KERNEL); + + if (!nlwork) { + sock_put(sk); + return -EAGAIN; + } + + INIT_TQUEUE(&nlwork->work, netlink_tq_handler, nlwork); + nlwork->sk = sk; + nlwork->len = len; + queue_task(&nlwork->work, &tq_netlink); + wake_up(&netlink_thread_wait); + } else { + sk->data_ready(sk, len); + sock_put(sk); + } + return len; no_dst: @@ -490,7 +542,22 @@ static __inline__ int netlink_broadcast_ skb_orphan(skb); skb_set_owner_r(skb, sk); skb_queue_tail(&sk->receive_queue, skb); - sk->data_ready(sk, skb->len); + + if (!sk->protinfo.af_netlink->pid) { + struct netlink_work *nlwork = + kmalloc(sizeof(struct netlink_work), GFP_KERNEL); + + if (!nlwork) + return -EAGAIN; + + INIT_TQUEUE(&nlwork->work, netlink_tq_handler, nlwork); + nlwork->sk = sk; + nlwork->len = skb->len; + queue_task(&nlwork->work, &tq_netlink); + wake_up(&netlink_thread_wait); + } else + sk->data_ready(sk, skb->len); + return 0; } return -1; @@ -534,11 +601,12 @@ void netlink_broadcast(struct sock *ssk, netlink_overrun(sk); /* Clone failed. Notify ALL listeners. */ failure = 1; + sock_put(sk); } else if (netlink_broadcast_deliver(sk, skb2)) { netlink_overrun(sk); + sock_put(sk); } else skb2 = NULL; - sock_put(sk); } netlink_unlock_table(); @@ -868,6 +936,26 @@ void netlink_ack(struct sk_buff *in_skb, netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); } +static int netlink_thread(void *unused) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + daemonize(); + strcpy(tsk->comm, "knetlinkd"); + sigfillset(&tsk->blocked); + mb(); + + for (;;) { + run_task_queue(&tq_netlink); + + __set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&netlink_thread_wait, &wait); + schedule(); + __set_current_state(TASK_RUNNING); + remove_wait_queue(&netlink_thread_wait, &wait); + } +} #ifdef NL_EMULATE_DEV @@ -1027,6 +1115,8 @@ static int __init netlink_proto_init(voi #ifdef CONFIG_PROC_FS create_proc_read_entry("net/netlink", 0, 0, netlink_read_proc, NULL); #endif + kernel_thread(netlink_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); + return 0; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/netsyms.c linux-2.4.28-pre3/net/netsyms.c --- linux-2.4.27/net/netsyms.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/netsyms.c 2004-09-10 19:34:17.000000000 +0000 @@ -283,6 +283,7 @@ EXPORT_SYMBOL(ip_dev_find); EXPORT_SYMBOL(inetdev_by_index); EXPORT_SYMBOL(in_dev_finish_destroy); EXPORT_SYMBOL(ip_defrag); +EXPORT_SYMBOL(ipfrag_flush); /* Route manipulation */ EXPORT_SYMBOL(ip_rt_ioctl); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_api.c linux-2.4.28-pre3/net/sched/sch_api.c --- linux-2.4.27/net/sched/sch_api.c 2002-11-28 23:53:16.000000000 +0000 +++ linux-2.4.28-pre3/net/sched/sch_api.c 2004-09-10 19:34:33.000000000 +0000 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -193,7 +194,7 @@ struct Qdisc *qdisc_lookup(struct net_de { struct Qdisc *q; - for (q = dev->qdisc_list; q; q = q->next) { + list_for_each_entry(q, &dev->qdisc_list, list) { if (q->handle == handle) return q; } @@ -424,6 +425,7 @@ qdisc_create(struct net_device *dev, u32 memset(sch, 0, size); + INIT_LIST_HEAD(&sch->list); skb_queue_head_init(&sch->q); if (handle == TC_H_INGRESS) @@ -449,8 +451,7 @@ qdisc_create(struct net_device *dev, u32 if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { write_lock(&qdisc_tree_lock); - sch->next = dev->qdisc_list; - dev->qdisc_list = sch; + list_add_tail(&sch->list, &dev->qdisc_list); write_unlock(&qdisc_tree_lock); #ifdef CONFIG_NET_ESTIMATOR if (tca[TCA_RATE-1]) @@ -805,15 +806,18 @@ static int tc_dump_qdisc(struct sk_buff if (idx > s_idx) s_q_idx = 0; read_lock(&qdisc_tree_lock); - for (q = dev->qdisc_list, q_idx = 0; q; - q = q->next, q_idx++) { - if (q_idx < s_q_idx) + q_idx = 0; + list_for_each_entry(q, &dev->qdisc_list, list) { + if (q_idx < s_q_idx) { + q_idx++; continue; + } if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) { read_unlock(&qdisc_tree_lock); goto done; } + q_idx++; } read_unlock(&qdisc_tree_lock); } @@ -1024,13 +1028,16 @@ static int tc_dump_tclass(struct sk_buff return 0; s_t = cb->args[0]; + t = 0; read_lock(&qdisc_tree_lock); - for (q=dev->qdisc_list, t=0; q; q = q->next, t++) { - if (t < s_t) continue; - if (!q->ops->cl_ops) continue; - if (tcm->tcm_parent && TC_H_MAJ(tcm->tcm_parent) != q->handle) + list_for_each_entry(q, &dev->qdisc_list, list) { + if (t < s_t || !q->ops->cl_ops || + (tcm->tcm_parent && + TC_H_MAJ(tcm->tcm_parent) != q->handle)) { + t++; continue; + } if (t > s_t) memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0])); arg.w.fn = qdisc_class_dump; @@ -1043,6 +1050,7 @@ static int tc_dump_tclass(struct sk_buff cb->args[1] = arg.w.count; if (arg.w.stop) break; + t++; } read_unlock(&qdisc_tree_lock); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_atm.c linux-2.4.28-pre3/net/sched/sch_atm.c --- linux-2.4.27/net/sched/sch_atm.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/net/sched/sch_atm.c 2004-09-10 19:34:39.000000000 +0000 @@ -566,7 +566,6 @@ static int atm_tc_init(struct Qdisc *sch struct atm_qdisc_data *p = PRIV(sch); DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt); - memset(p,0,sizeof(*p)); p->flows = &p->link; if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops))) p->link.q = &noop_qdisc; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_cbq.c linux-2.4.28-pre3/net/sched/sch_cbq.c --- linux-2.4.27/net/sched/sch_cbq.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sched/sch_cbq.c 2004-09-10 19:32:38.000000000 +0000 @@ -1712,15 +1712,18 @@ static void cbq_destroy_filters(struct c } } -static void cbq_destroy_class(struct cbq_class *cl) +static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl) { + struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data; + cbq_destroy_filters(cl); qdisc_destroy(cl->q); qdisc_put_rtab(cl->R_tab); #ifdef CONFIG_NET_ESTIMATOR qdisc_kill_estimator(&cl->stats); #endif - kfree(cl); + if (cl != &q->link) + kfree(cl); } static void @@ -1743,8 +1746,7 @@ cbq_destroy(struct Qdisc* sch) for (cl = q->classes[h]; cl; cl = next) { next = cl->next; - if (cl != &q->link) - cbq_destroy_class(cl); + cbq_destroy_class(sch, cl); } } @@ -1766,7 +1768,7 @@ static void cbq_put(struct Qdisc *sch, u spin_unlock_bh(&sch->dev->queue_lock); #endif - cbq_destroy_class(cl); + cbq_destroy_class(sch, cl); } } @@ -2000,7 +2002,7 @@ static int cbq_delete(struct Qdisc *sch, sch_tree_unlock(sch); if (--cl->refcnt == 0) - cbq_destroy_class(cl); + cbq_destroy_class(sch, cl); return 0; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_dsmark.c linux-2.4.28-pre3/net/sched/sch_dsmark.c --- linux-2.4.27/net/sched/sch_dsmark.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sched/sch_dsmark.c 2004-09-10 19:32:54.000000000 +0000 @@ -329,8 +329,6 @@ int dsmark_init(struct Qdisc *sch,struct !tb[TCA_DSMARK_INDICES-1] || RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16)) return -EINVAL; - memset(p,0,sizeof(*p)); - p->filter_list = NULL; p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]); if (!p->indices) return -EINVAL; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_generic.c linux-2.4.28-pre3/net/sched/sch_generic.c --- linux-2.4.27/net/sched/sch_generic.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/net/sched/sch_generic.c 2004-09-10 19:32:10.000000000 +0000 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -391,6 +392,7 @@ struct Qdisc * qdisc_create_dflt(struct return NULL; memset(sch, 0, size); + INIT_LIST_HEAD(&sch->list); skb_queue_head_init(&sch->q); sch->ops = ops; sch->enqueue = ops->enqueue; @@ -420,22 +422,10 @@ void qdisc_reset(struct Qdisc *qdisc) void qdisc_destroy(struct Qdisc *qdisc) { struct Qdisc_ops *ops = qdisc->ops; - struct net_device *dev; if (!atomic_dec_and_test(&qdisc->refcnt)) return; - - dev = qdisc->dev; - - if (dev) { - struct Qdisc *q, **qp; - for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) { - if (q == qdisc) { - *qp = q->next; - break; - } - } - } + list_del(&qdisc->list); #ifdef CONFIG_NET_ESTIMATOR qdisc_kill_estimator(&qdisc->stats); #endif @@ -464,10 +454,8 @@ void dev_activate(struct net_device *dev printk(KERN_INFO "%s: activation failed\n", dev->name); return; } - write_lock(&qdisc_tree_lock); - qdisc->next = dev->qdisc_list; - dev->qdisc_list = qdisc; + list_add_tail(&qdisc->list, &dev->qdisc_list); write_unlock(&qdisc_tree_lock); } else { @@ -513,7 +501,7 @@ void dev_init_scheduler(struct net_devic dev->qdisc = &noop_qdisc; spin_unlock_bh(&dev->queue_lock); dev->qdisc_sleeping = &noop_qdisc; - dev->qdisc_list = NULL; + INIT_LIST_HEAD(&dev->qdisc_list); write_unlock(&qdisc_tree_lock); dev_watchdog_init(dev); @@ -535,9 +523,8 @@ void dev_shutdown(struct net_device *dev qdisc_destroy(qdisc); } #endif - BUG_TRAP(dev->qdisc_list == NULL); + BUG_TRAP(list_empty(&dev->qdisc_list)); BUG_TRAP(!timer_pending(&dev->watchdog_timer)); - dev->qdisc_list = NULL; spin_unlock_bh(&dev->queue_lock); write_unlock(&qdisc_tree_lock); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_hfsc.c linux-2.4.28-pre3/net/sched/sch_hfsc.c --- linux-2.4.27/net/sched/sch_hfsc.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sched/sch_hfsc.c 2004-09-10 19:34:35.000000000 +0000 @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -131,9 +132,11 @@ struct hfsc_class struct list_head children; /* child classes */ struct Qdisc *qdisc; /* leaf qdisc */ - struct list_head actlist; /* active children list */ - struct list_head alist; /* active children list member */ - struct list_head ellist; /* eligible list member */ + rb_node_t el_node; /* qdisc's eligible tree member */ + rb_root_t vt_tree; /* active children sorted by cl_vt */ + rb_node_t vt_node; /* parent's vt_tree member */ + rb_root_t cf_tree; /* active children sorted by cl_f */ + rb_node_t cf_node; /* parent's cf_heap member */ struct list_head hlist; /* hash list member */ struct list_head dlist; /* drop list member */ @@ -159,6 +162,9 @@ struct hfsc_class adjustment */ u64 cl_vtoff; /* inter-period cumulative vt offset */ u64 cl_cvtmax; /* max child's vt in the last period */ + u64 cl_cvtoff; /* cumulative cvtmax of all periods */ + u64 cl_pcvtoff; /* parent's cvtoff at initalization + time */ struct internal_sc cl_rsc; /* internal real-time service curve */ struct internal_sc cl_fsc; /* internal fair service curve */ @@ -181,7 +187,7 @@ struct hfsc_sched u16 defcls; /* default class id */ struct hfsc_class root; /* root class */ struct list_head clhash[HFSC_HSIZE]; /* class hash */ - struct list_head eligible; /* eligible list */ + rb_root_t eligible; /* eligible tree */ struct list_head droplist; /* active leaf class list (for dropping) */ struct sk_buff_head requeue; /* requeued packet */ @@ -217,82 +223,51 @@ do { \ /* - * eligible list holds backlogged classes being sorted by their eligible times. - * there is one eligible list per hfsc instance. + * eligible tree holds backlogged classes being sorted by their eligible times. + * there is one eligible tree per hfsc instance. */ static void -ellist_insert(struct hfsc_class *cl) +eltree_insert(struct hfsc_class *cl) { - struct list_head *head = &cl->sched->eligible; - struct hfsc_class *p; - - /* check the last entry first */ - if (list_empty(head) || - ((p = list_entry(head->prev, struct hfsc_class, ellist)) && - p->cl_e <= cl->cl_e)) { - list_add_tail(&cl->ellist, head); - return; - } - - list_for_each_entry(p, head, ellist) { - if (cl->cl_e < p->cl_e) { - /* insert cl before p */ - list_add_tail(&cl->ellist, &p->ellist); - return; - } + rb_node_t **p = &cl->sched->eligible.rb_node; + rb_node_t *parent = NULL; + struct hfsc_class *cl1; + + while (*p != NULL) { + parent = *p; + cl1 = rb_entry(parent, struct hfsc_class, el_node); + if (cl->cl_e >= cl1->cl_e) + p = &parent->rb_right; + else + p = &parent->rb_left; } - ASSERT(0); /* should not reach here */ + rb_link_node(&cl->el_node, parent, p); + rb_insert_color(&cl->el_node, &cl->sched->eligible); } static inline void -ellist_remove(struct hfsc_class *cl) +eltree_remove(struct hfsc_class *cl) { - list_del(&cl->ellist); + rb_erase(&cl->el_node, &cl->sched->eligible); } -static void -ellist_update(struct hfsc_class *cl) +static inline void +eltree_update(struct hfsc_class *cl) { - struct list_head *head = &cl->sched->eligible; - struct hfsc_class *p, *last; - - /* - * the eligible time of a class increases monotonically. - * if the next entry has a larger eligible time, nothing to do. - */ - if (cl->ellist.next == head || - ((p = list_entry(cl->ellist.next, struct hfsc_class, ellist)) && - cl->cl_e <= p->cl_e)) - return; - - /* check the last entry */ - last = list_entry(head->prev, struct hfsc_class, ellist); - if (last->cl_e <= cl->cl_e) { - list_move_tail(&cl->ellist, head); - return; - } - - /* - * the new position must be between the next entry - * and the last entry - */ - list_for_each_entry_continue(p, head, ellist) { - if (cl->cl_e < p->cl_e) { - list_move_tail(&cl->ellist, &p->ellist); - return; - } - } - ASSERT(0); /* should not reach here */ + eltree_remove(cl); + eltree_insert(cl); } /* find the class with the minimum deadline among the eligible classes */ static inline struct hfsc_class * -ellist_get_mindl(struct list_head *head, u64 cur_time) +eltree_get_mindl(struct hfsc_sched *q, u64 cur_time) { struct hfsc_class *p, *cl = NULL; + rb_node_t *n; - list_for_each_entry(p, head, ellist) { + for (n = rb_first(&q->eligible); n != NULL; n = rb_next(n)) { + p = rb_entry(n, struct hfsc_class, el_node); if (p->cl_e > cur_time) break; if (cl == NULL || p->cl_d < cl->cl_d) @@ -303,92 +278,62 @@ ellist_get_mindl(struct list_head *head, /* find the class with minimum eligible time among the eligible classes */ static inline struct hfsc_class * -ellist_get_minel(struct list_head *head) +eltree_get_minel(struct hfsc_sched *q) { - if (list_empty(head)) + rb_node_t *n; + + n = rb_first(&q->eligible); + if (n == NULL) return NULL; - return list_entry(head->next, struct hfsc_class, ellist); + return rb_entry(n, struct hfsc_class, el_node); } /* - * active children list holds backlogged child classes being sorted - * by their virtual time. each intermediate class has one active - * children list. + * vttree holds holds backlogged child classes being sorted by their virtual + * time. each intermediate class has one vttree. */ static void -actlist_insert(struct hfsc_class *cl) +vttree_insert(struct hfsc_class *cl) { - struct list_head *head = &cl->cl_parent->actlist; - struct hfsc_class *p; - - /* check the last entry first */ - if (list_empty(head) || - ((p = list_entry(head->prev, struct hfsc_class, alist)) && - p->cl_vt <= cl->cl_vt)) { - list_add_tail(&cl->alist, head); - return; - } - - list_for_each_entry(p, head, alist) { - if (cl->cl_vt < p->cl_vt) { - /* insert cl before p */ - list_add_tail(&cl->alist, &p->alist); - return; - } + rb_node_t **p = &cl->cl_parent->vt_tree.rb_node; + rb_node_t *parent = NULL; + struct hfsc_class *cl1; + + while (*p != NULL) { + parent = *p; + cl1 = rb_entry(parent, struct hfsc_class, vt_node); + if (cl->cl_vt >= cl1->cl_vt) + p = &parent->rb_right; + else + p = &parent->rb_left; } - ASSERT(0); /* should not reach here */ + rb_link_node(&cl->vt_node, parent, p); + rb_insert_color(&cl->vt_node, &cl->cl_parent->vt_tree); } static inline void -actlist_remove(struct hfsc_class *cl) +vttree_remove(struct hfsc_class *cl) { - list_del(&cl->alist); + rb_erase(&cl->vt_node, &cl->cl_parent->vt_tree); } -static void -actlist_update(struct hfsc_class *cl) +static inline void +vttree_update(struct hfsc_class *cl) { - struct list_head *head = &cl->cl_parent->actlist; - struct hfsc_class *p, *last; - - /* - * the virtual time of a class increases monotonically. - * if the next entry has a larger virtual time, nothing to do. - */ - if (cl->alist.next == head || - ((p = list_entry(cl->alist.next, struct hfsc_class, alist)) && - cl->cl_vt <= p->cl_vt)) - return; - - /* check the last entry */ - last = list_entry(head->prev, struct hfsc_class, alist); - if (last->cl_vt <= cl->cl_vt) { - list_move_tail(&cl->alist, head); - return; - } - - /* - * the new position must be between the next entry - * and the last entry - */ - list_for_each_entry_continue(p, head, alist) { - if (cl->cl_vt < p->cl_vt) { - list_move_tail(&cl->alist, &p->alist); - return; - } - } - ASSERT(0); /* should not reach here */ + vttree_remove(cl); + vttree_insert(cl); } static inline struct hfsc_class * -actlist_firstfit(struct hfsc_class *cl, u64 cur_time) +vttree_firstfit(struct hfsc_class *cl, u64 cur_time) { struct hfsc_class *p; + rb_node_t *n; - list_for_each_entry(p, &cl->actlist, alist) { - if (p->cl_f <= cur_time) { + for (n = rb_first(&cl->vt_tree); n != NULL; n = rb_next(n)) { + p = rb_entry(n, struct hfsc_class, vt_node); + if (p->cl_f <= cur_time) return p; - } } return NULL; } @@ -397,14 +342,14 @@ actlist_firstfit(struct hfsc_class *cl, * get the leaf class with the minimum vt in the hierarchy */ static struct hfsc_class * -actlist_get_minvt(struct hfsc_class *cl, u64 cur_time) +vttree_get_minvt(struct hfsc_class *cl, u64 cur_time) { /* if root-class's cfmin is bigger than cur_time nothing to do */ if (cl->cl_cfmin > cur_time) return NULL; while (cl->level > 0) { - cl = actlist_firstfit(cl, cur_time); + cl = vttree_firstfit(cl, cur_time); if (cl == NULL) return NULL; /* @@ -416,6 +361,38 @@ actlist_get_minvt(struct hfsc_class *cl, return cl; } +static void +cftree_insert(struct hfsc_class *cl) +{ + rb_node_t **p = &cl->cl_parent->cf_tree.rb_node; + rb_node_t *parent = NULL; + struct hfsc_class *cl1; + + while (*p != NULL) { + parent = *p; + cl1 = rb_entry(parent, struct hfsc_class, cf_node); + if (cl->cl_f >= cl1->cl_f) + p = &parent->rb_right; + else + p = &parent->rb_left; + } + rb_link_node(&cl->cf_node, parent, p); + rb_insert_color(&cl->cf_node, &cl->cl_parent->cf_tree); +} + +static inline void +cftree_remove(struct hfsc_class *cl) +{ + rb_erase(&cl->cf_node, &cl->cl_parent->cf_tree); +} + +static inline void +cftree_update(struct hfsc_class *cl) +{ + cftree_remove(cl); + cftree_insert(cl); +} + /* * service curve support functions * @@ -709,7 +686,7 @@ init_ed(struct hfsc_class *cl, unsigned cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul); cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len); - ellist_insert(cl); + eltree_insert(cl); } static void @@ -718,7 +695,7 @@ update_ed(struct hfsc_class *cl, unsigne cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul); cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len); - ellist_update(cl); + eltree_update(cl); } static inline void @@ -727,32 +704,25 @@ update_d(struct hfsc_class *cl, unsigned cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len); } -static void +static inline void update_cfmin(struct hfsc_class *cl) { + rb_node_t *n = rb_first(&cl->cf_tree); struct hfsc_class *p; - u64 cfmin; - if (list_empty(&cl->actlist)) { + if (n == NULL) { cl->cl_cfmin = 0; return; } - cfmin = HT_INFINITY; - list_for_each_entry(p, &cl->actlist, alist) { - if (p->cl_f == 0) { - cl->cl_cfmin = 0; - return; - } - if (p->cl_f < cfmin) - cfmin = p->cl_f; - } - cl->cl_cfmin = cfmin; + p = rb_entry(n, struct hfsc_class, cf_node); + cl->cl_cfmin = p->cl_f; } static void init_vf(struct hfsc_class *cl, unsigned int len) { - struct hfsc_class *max_cl, *p; + struct hfsc_class *max_cl; + rb_node_t *n; u64 vt, f, cur_time; int go_active; @@ -765,9 +735,9 @@ init_vf(struct hfsc_class *cl, unsigned go_active = 0; if (go_active) { - if (!list_empty(&cl->cl_parent->actlist)) { - max_cl = list_entry(cl->cl_parent->actlist.prev, - struct hfsc_class, alist); + n = rb_last(&cl->cl_parent->vt_tree); + if (n != NULL) { + max_cl = rb_entry(n, struct hfsc_class,vt_node); /* * set vt to the average of the min and max * classes. if the parent's period didn't @@ -783,19 +753,20 @@ init_vf(struct hfsc_class *cl, unsigned } else { /* * first child for a new parent backlog period. - * add parent's cvtmax to vtoff of children - * to make a new vt (vtoff + vt) larger than - * the vt in the last period for all children. + * add parent's cvtmax to cvtoff to make a new + * vt (vtoff + vt) larger than the vt in the + * last period for all children. */ vt = cl->cl_parent->cl_cvtmax; - list_for_each_entry(p, &cl->cl_parent->children, - siblings) - p->cl_vtoff += vt; - cl->cl_vt = 0; + cl->cl_parent->cl_cvtoff += vt; cl->cl_parent->cl_cvtmax = 0; cl->cl_parent->cl_cvtmin = 0; + cl->cl_vt = 0; } + cl->cl_vtoff = cl->cl_parent->cl_cvtoff - + cl->cl_pcvtoff; + /* update the virtual curve */ vt = cl->cl_vt + cl->cl_vtoff; rtsc_min(&cl->cl_virtual, &cl->cl_fsc, vt, @@ -812,7 +783,8 @@ init_vf(struct hfsc_class *cl, unsigned cl->cl_parentperiod++; cl->cl_f = 0; - actlist_insert(cl); + vttree_insert(cl); + cftree_insert(cl); if (cl->cl_flags & HFSC_USC) { /* class has upper limit curve */ @@ -832,6 +804,7 @@ init_vf(struct hfsc_class *cl, unsigned f = max(cl->cl_myf, cl->cl_cfmin); if (f != cl->cl_f) { cl->cl_f = f; + cftree_update(cl); update_cfmin(cl->cl_parent); } } @@ -864,9 +837,10 @@ update_vf(struct hfsc_class *cl, unsigne if (cl->cl_vt > cl->cl_parent->cl_cvtmax) cl->cl_parent->cl_cvtmax = cl->cl_vt; - /* remove this class from the vt list */ - actlist_remove(cl); + /* remove this class from the vt tree */ + vttree_remove(cl); + cftree_remove(cl); update_cfmin(cl->cl_parent); continue; @@ -888,8 +862,8 @@ update_vf(struct hfsc_class *cl, unsigne cl->cl_vt = cl->cl_parent->cl_cvtmin; } - /* update the vt list */ - actlist_update(cl); + /* update the vt tree */ + vttree_update(cl); if (cl->cl_flags & HFSC_USC) { cl->cl_myf = cl->cl_myfadj + rtsc_y2x(&cl->cl_ulimit, @@ -919,6 +893,7 @@ update_vf(struct hfsc_class *cl, unsigne f = max(cl->cl_myf, cl->cl_cfmin); if (f != cl->cl_f) { cl->cl_f = f; + cftree_update(cl); update_cfmin(cl->cl_parent); } } @@ -939,13 +914,13 @@ static void set_passive(struct hfsc_class *cl) { if (cl->cl_flags & HFSC_RSC) - ellist_remove(cl); + eltree_remove(cl); list_del(&cl->dlist); /* - * actlist is now handled in update_vf() so that update_vf(cl, 0, 0) - * needs to be called explicitly to remove a class from actlist + * vttree is now handled in update_vf() so that update_vf(cl, 0, 0) + * needs to be called explicitly to remove a class from vttree. */ } @@ -1168,7 +1143,8 @@ hfsc_change_class(struct Qdisc *sch, u32 cl->qdisc = &noop_qdisc; cl->stats.lock = &sch->dev->queue_lock; INIT_LIST_HEAD(&cl->children); - INIT_LIST_HEAD(&cl->actlist); + cl->vt_tree = RB_ROOT; + cl->cf_tree = RB_ROOT; sch_tree_lock(sch); list_add_tail(&cl->hlist, &q->clhash[hfsc_hash(classid)]); @@ -1176,6 +1152,7 @@ hfsc_change_class(struct Qdisc *sch, u32 if (parent->level == 0) hfsc_purge_queue(sch, parent); hfsc_adjust_levels(parent); + cl->cl_pcvtoff = parent->cl_cvtoff; sch_tree_unlock(sch); #ifdef CONFIG_NET_ESTIMATOR @@ -1500,7 +1477,7 @@ hfsc_schedule_watchdog(struct Qdisc *sch u64 next_time = 0; long delay; - if ((cl = ellist_get_minel(&q->eligible)) != NULL) + if ((cl = eltree_get_minel(q)) != NULL) next_time = cl->cl_e; if (q->root.cl_cfmin != 0) { if (next_time == 0 || next_time > q->root.cl_cfmin) @@ -1525,13 +1502,12 @@ hfsc_init_qdisc(struct Qdisc *sch, struc return -EINVAL; qopt = RTA_DATA(opt); - memset(q, 0, sizeof(struct hfsc_sched)); sch->stats.lock = &sch->dev->queue_lock; q->defcls = qopt->defcls; for (i = 0; i < HFSC_HSIZE; i++) INIT_LIST_HEAD(&q->clhash[i]); - INIT_LIST_HEAD(&q->eligible); + q->eligible = RB_ROOT; INIT_LIST_HEAD(&q->droplist); skb_queue_head_init(&q->requeue); @@ -1543,7 +1519,8 @@ hfsc_init_qdisc(struct Qdisc *sch, struc q->root.qdisc = &noop_qdisc; q->root.stats.lock = &sch->dev->queue_lock; INIT_LIST_HEAD(&q->root.children); - INIT_LIST_HEAD(&q->root.actlist); + q->root.vt_tree = RB_ROOT; + q->root.cf_tree = RB_ROOT; list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]); @@ -1584,6 +1561,8 @@ hfsc_reset_class(struct hfsc_class *cl) cl->cl_vtoff = 0; cl->cl_cvtmin = 0; cl->cl_cvtmax = 0; + cl->cl_cvtoff = 0; + cl->cl_pcvtoff = 0; cl->cl_vtperiod = 0; cl->cl_parentperiod = 0; cl->cl_f = 0; @@ -1591,7 +1570,9 @@ hfsc_reset_class(struct hfsc_class *cl) cl->cl_myfadj = 0; cl->cl_cfmin = 0; cl->cl_nactive = 0; - INIT_LIST_HEAD(&cl->actlist); + + cl->vt_tree = RB_ROOT; + cl->cf_tree = RB_ROOT; qdisc_reset(cl->qdisc); if (cl->cl_flags & HFSC_RSC) @@ -1614,7 +1595,7 @@ hfsc_reset_qdisc(struct Qdisc *sch) hfsc_reset_class(cl); } __skb_queue_purge(&q->requeue); - INIT_LIST_HEAD(&q->eligible); + q->eligible = RB_ROOT; INIT_LIST_HEAD(&q->droplist); del_timer(&q->wd_timer); sch->flags &= ~TCQ_F_THROTTLED; @@ -1712,14 +1693,14 @@ hfsc_dequeue(struct Qdisc *sch) * find the class with the minimum deadline among * the eligible classes. */ - if ((cl = ellist_get_mindl(&q->eligible, cur_time)) != NULL) { + if ((cl = eltree_get_mindl(q, cur_time)) != NULL) { realtime = 1; } else { /* * use link-sharing criteria * get the class with the minimum vt in the hierarchy */ - cl = actlist_get_minvt(&q->root, cur_time); + cl = vttree_get_minvt(&q->root, cur_time); if (cl == NULL) { sch->stats.overlimits++; hfsc_schedule_watchdog(sch, cur_time); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_htb.c linux-2.4.28-pre3/net/sched/sch_htb.c --- linux-2.4.27/net/sched/sch_htb.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sched/sch_htb.c 2004-09-10 19:32:01.000000000 +0000 @@ -77,7 +77,7 @@ #define HTB_HYSTERESIS 1/* whether to use mode hysteresis for speedup */ #define HTB_QLOCK(S) spin_lock_bh(&(S)->dev->queue_lock) #define HTB_QUNLOCK(S) spin_unlock_bh(&(S)->dev->queue_lock) -#define HTB_VER 0x30010 /* major must be matched with number suplied by TC as version */ +#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */ #if HTB_VER >> 16 != TC_HTB_PROTOVER #error "Mismatched sch_htb.c and pkt_sch.h" @@ -172,6 +172,11 @@ struct htb_class struct htb_class_inner { rb_root_t feed[TC_HTB_NUMPRIO]; /* feed trees */ rb_node_t *ptr[TC_HTB_NUMPRIO]; /* current class ptr */ + /* When class changes from state 1->2 and disconnects from + parent's feed then we lost ptr value and start from the + first child again. Here we store classid of the + last valid ptr (used when ptr is NULL). */ + u32 last_ptr_id[TC_HTB_NUMPRIO]; } inner; } un; rb_node_t node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ @@ -218,6 +223,7 @@ struct htb_sched rb_root_t row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; int row_mask[TC_HTB_MAXDEPTH]; rb_node_t *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; + u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; /* self wait list - roots of wait PQs per row */ rb_root_t wait_pq[TC_HTB_MAXDEPTH]; @@ -576,8 +582,13 @@ static void htb_deactivate_prios(struct int prio = ffz(~m); m &= ~(1 << prio); - if (p->un.inner.ptr[prio] == cl->node+prio) - htb_next_rb_node(p->un.inner.ptr + prio); + if (p->un.inner.ptr[prio] == cl->node+prio) { + /* we are removing child which is pointed to from + parent feed - forget the pointer but remember + classid */ + p->un.inner.last_ptr_id[prio] = cl->classid; + p->un.inner.ptr[prio] = NULL; + } htb_safe_rb_erase(cl->node + prio,p->un.inner.feed + prio); @@ -908,25 +919,56 @@ static long htb_do_events(struct htb_sch return HZ/10; } +/* Returns class->node+prio from id-tree where classe's id is >= id. NULL + is no such one exists. */ +static rb_node_t * +htb_id_find_next_upper(int prio,rb_node_t *n,u32 id) +{ + rb_node_t *r = NULL; + while (n) { + struct htb_class *cl = rb_entry(n,struct htb_class,node[prio]); + if (id == cl->classid) return n; + + if (id > cl->classid) { + n = n->rb_right; + } else { + r = n; + n = n->rb_left; + } + } + return r; +} + /** * htb_lookup_leaf - returns next leaf class in DRR order * * Find leaf where current feed pointers points to. */ static struct htb_class * -htb_lookup_leaf(rb_root_t *tree,int prio,rb_node_t **pptr) +htb_lookup_leaf(HTB_ARGQ rb_root_t *tree,int prio,rb_node_t **pptr,u32 *pid) { int i; struct { rb_node_t *root; rb_node_t **pptr; + u32 *pid; } stk[TC_HTB_MAXDEPTH],*sp = stk; BUG_TRAP(tree->rb_node); sp->root = tree->rb_node; sp->pptr = pptr; + sp->pid = pid; for (i = 0; i < 65535; i++) { + HTB_DBG(4,2,"htb_lleaf ptr=%p pid=%X\n",*sp->pptr,*sp->pid); + + if (!*sp->pptr && *sp->pid) { + /* ptr was invalidated but id is valid - try to recover + the original or next ptr */ + *sp->pptr = htb_id_find_next_upper(prio,sp->root,*sp->pid); + } + *sp->pid = 0; /* ptr is valid now so that remove this hint as it + can become out of date quickly */ if (!*sp->pptr) { /* we are at right end; rewind & go up */ *sp->pptr = sp->root; while ((*sp->pptr)->rb_left) @@ -944,6 +986,7 @@ htb_lookup_leaf(rb_root_t *tree,int prio return cl; (++sp)->root = cl->un.inner.feed[prio].rb_node; sp->pptr = cl->un.inner.ptr+prio; + sp->pid = cl->un.inner.last_ptr_id+prio; } } BUG_TRAP(0); @@ -958,7 +1001,8 @@ htb_dequeue_tree(struct htb_sched *q,int struct sk_buff *skb = NULL; struct htb_class *cl,*start; /* look initial class up in the row */ - start = cl = htb_lookup_leaf (q->row[level]+prio,prio,q->ptr[level]+prio); + start = cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio, + q->ptr[level]+prio,q->last_ptr_id[level]+prio); do { next: @@ -979,8 +1023,8 @@ next: if ((q->row_mask[level] & (1 << prio)) == 0) return NULL; - next = htb_lookup_leaf (q->row[level]+prio, - prio,q->ptr[level]+prio); + next = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio, + prio,q->ptr[level]+prio,q->last_ptr_id[level]+prio); if (cl == start) /* fix start if we just deleted it */ start = next; cl = next; @@ -995,7 +1039,8 @@ next: } q->nwc_hit++; htb_next_rb_node((level?cl->parent->un.inner.ptr:q->ptr[0])+prio); - cl = htb_lookup_leaf (q->row[level]+prio,prio,q->ptr[level]+prio); + cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio,q->ptr[level]+prio, + q->last_ptr_id[level]+prio); } while (cl != start); if (likely(skb != NULL)) { @@ -1186,7 +1231,6 @@ static int htb_init(struct Qdisc *sch, s HTB_VER >> 16,HTB_VER & 0xffff,gopt->version); return -EINVAL; } - memset(q,0,sizeof(*q)); q->debug = gopt->debug; HTB_DBG(0,1,"htb_init sch=%p handle=%X r2q=%d\n",sch,sch->handle,gopt->rate2quantum); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_ingress.c linux-2.4.28-pre3/net/sched/sch_ingress.c --- linux-2.4.27/net/sched/sch_ingress.c 2004-02-18 13:36:32.000000000 +0000 +++ linux-2.4.28-pre3/net/sched/sch_ingress.c 2004-09-10 19:36:16.000000000 +0000 @@ -254,8 +254,6 @@ int ingress_init(struct Qdisc *sch,struc } DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt); - memset(p, 0, sizeof(*p)); - p->filter_list = NULL; p->q = &noop_qdisc; MOD_INC_USE_COUNT; return 0; @@ -296,9 +294,6 @@ static void ingress_destroy(struct Qdisc p->filter_list = tp->next; tcf_destroy(tp); } - memset(p, 0, sizeof(*p)); - p->filter_list = NULL; - #if 0 /* for future use */ qdisc_destroy(p->q); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_netem.c linux-2.4.28-pre3/net/sched/sch_netem.c --- linux-2.4.27/net/sched/sch_netem.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sched/sch_netem.c 2004-09-10 19:34:49.000000000 +0000 @@ -6,13 +6,15 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * + * Many of the algorithms and ideas for this came from + * NIST Net which is not copyrighted. + * * Authors: Stephen Hemminger * Catalin(ux aka Dino) BOIE */ #include #include -#include #include #include #include @@ -23,11 +25,33 @@ #include -/* Network emulator - * - * This scheduler can alters spacing and order - * Similar to NISTnet and BSD Dummynet. - */ +#define qdisc_priv(q) ((void *)(q->data)) + +/* Network Emulation Queuing algorithm. + ==================================== + + Sources: [1] Mark Carson, Darrin Santay, "NIST Net - A Linux-based + Network Emulation Tool + [2] Luigi Rizzo, DummyNet for FreeBSD + + ---------------------------------------------------------------- + + This started out as a simple way to delay outgoing packets to + test TCP but has grown to include most of the functionality + of a full blown network emulator like NISTnet. It can delay + packets and add random jitter (and correlation). The random + distribution can be loaded from a table as well to provide + normal, Pareto, or experimental curves. Packet loss, + duplication, and reordering can also be emulated. + + This qdisc does not do classification that can be handled in + layering other disciplines. It does not need to do bandwidth + control either since that can be handled by using token + bucket or other rate control. + + The simulator is limited by the Linux timer resolution + and will create packet bursts on the HZ boundary (1ms). +*/ struct netem_sched_data { struct Qdisc *qdisc; @@ -40,6 +64,17 @@ struct netem_sched_data { u32 counter; u32 gap; u32 jitter; + u32 duplicate; + + struct crndstate { + unsigned long last; + unsigned long rho; + } delay_cor, loss_cor, dup_cor; + + struct disttable { + u32 size; + s16 table[0]; + } *delay_dist; }; /* Time stamp put into socket buffer control block */ @@ -47,576 +82,110 @@ struct netem_skb_cb { psched_time_t time_to_send; }; -/* This is the distribution table for the normal distribution produced - * with NISTnet tools. - * The entries represent a scaled inverse of the cumulative distribution - * function. +/* init_crandom - initialize correlated random number generator + * Use entropy source for initial seed. */ -#define TABLESIZE 2048 -#define TABLEFACTOR 8192 +static void init_crandom(struct crndstate *state, unsigned long rho) +{ + state->rho = rho; + state->last = net_random(); +} -static const short disttable[TABLESIZE] = { - -31473, -26739, -25226, -24269, - -23560, -22993, -22518, -22109, - -21749, -21426, -21133, -20865, - -20618, -20389, -20174, -19972, - -19782, -19601, -19430, -19267, - -19112, -18962, -18819, -18681, - -18549, -18421, -18298, -18178, - -18062, -17950, -17841, -17735, - -17632, -17532, -17434, -17339, - -17245, -17155, -17066, -16979, - -16894, -16811, -16729, -16649, - -16571, -16494, -16419, -16345, - -16272, -16201, -16130, -16061, - -15993, -15926, -15861, -15796, - -15732, -15669, -15607, -15546, - -15486, -15426, -15368, -15310, - -15253, -15196, -15140, -15086, - -15031, -14977, -14925, -14872, - -14821, -14769, -14719, -14669, - -14619, -14570, -14522, -14473, - -14426, -14379, -14332, -14286, - -14241, -14196, -14150, -14106, - -14062, -14019, -13976, -13933, - -13890, -13848, -13807, -13765, - -13724, -13684, -13643, -13604, - -13564, -13525, -13486, -13447, - -13408, -13370, -13332, -13295, - -13258, -13221, -13184, -13147, - -13111, -13075, -13040, -13004, - -12969, -12934, -12899, -12865, - -12830, -12796, -12762, -12729, - -12695, -12662, -12629, -12596, - -12564, -12531, -12499, -12467, - -12435, -12404, -12372, -12341, - -12310, -12279, -12248, -12218, - -12187, -12157, -12127, -12097, - -12067, -12038, -12008, -11979, - -11950, -11921, -11892, -11863, - -11835, -11806, -11778, -11750, - -11722, -11694, -11666, -11639, - -11611, -11584, -11557, -11530, - -11503, -11476, -11450, -11423, - -11396, -11370, -11344, -11318, - -11292, -11266, -11240, -11214, - -11189, -11164, -11138, -11113, - -11088, -11063, -11038, -11013, - -10988, -10964, -10939, -10915, - -10891, -10866, -10843, -10818, - -10794, -10770, -10747, -10723, - -10700, -10676, -10652, -10630, - -10606, -10583, -10560, -10537, - -10514, -10491, -10469, -10446, - -10424, -10401, -10378, -10356, - -10334, -10312, -10290, -10267, - -10246, -10224, -10202, -10180, - -10158, -10137, -10115, -10094, - -10072, -10051, -10030, -10009, - -9988, -9967, -9945, -9925, - -9904, -9883, -9862, -9842, - -9821, -9800, -9780, -9760, - -9739, -9719, -9699, -9678, - -9658, -9638, -9618, -9599, - -9578, -9559, -9539, -9519, - -9499, -9480, -9461, -9441, - -9422, -9402, -9383, -9363, - -9344, -9325, -9306, -9287, - -9268, -9249, -9230, -9211, - -9192, -9173, -9155, -9136, - -9117, -9098, -9080, -9062, - -9043, -9025, -9006, -8988, - -8970, -8951, -8933, -8915, - -8897, -8879, -8861, -8843, - -8825, -8807, -8789, -8772, - -8754, -8736, -8718, -8701, - -8683, -8665, -8648, -8630, - -8613, -8595, -8578, -8561, - -8543, -8526, -8509, -8492, - -8475, -8458, -8441, -8423, - -8407, -8390, -8373, -8356, - -8339, -8322, -8305, -8289, - -8272, -8255, -8239, -8222, - -8206, -8189, -8172, -8156, - -8140, -8123, -8107, -8090, - -8074, -8058, -8042, -8025, - -8009, -7993, -7977, -7961, - -7945, -7929, -7913, -7897, - -7881, -7865, -7849, -7833, - -7817, -7802, -7786, -7770, - -7754, -7739, -7723, -7707, - -7692, -7676, -7661, -7645, - -7630, -7614, -7599, -7583, - -7568, -7553, -7537, -7522, - -7507, -7492, -7476, -7461, - -7446, -7431, -7416, -7401, - -7385, -7370, -7356, -7340, - -7325, -7311, -7296, -7281, - -7266, -7251, -7236, -7221, - -7207, -7192, -7177, -7162, - -7148, -7133, -7118, -7104, - -7089, -7075, -7060, -7046, - -7031, -7016, -7002, -6988, - -6973, -6959, -6944, -6930, - -6916, -6901, -6887, -6873, - -6859, -6844, -6830, -6816, - -6802, -6788, -6774, -6760, - -6746, -6731, -6717, -6704, - -6690, -6675, -6661, -6647, - -6633, -6620, -6606, -6592, - -6578, -6564, -6550, -6537, - -6523, -6509, -6495, -6482, - -6468, -6454, -6441, -6427, - -6413, -6400, -6386, -6373, - -6359, -6346, -6332, -6318, - -6305, -6291, -6278, -6264, - -6251, -6238, -6224, -6211, - -6198, -6184, -6171, -6158, - -6144, -6131, -6118, -6105, - -6091, -6078, -6065, -6052, - -6039, -6025, -6012, -5999, - -5986, -5973, -5960, -5947, - -5934, -5921, -5908, -5895, - -5882, -5869, -5856, -5843, - -5830, -5817, -5804, -5791, - -5779, -5766, -5753, -5740, - -5727, -5714, -5702, -5689, - -5676, -5663, -5650, -5638, - -5625, -5612, -5600, -5587, - -5575, -5562, -5549, -5537, - -5524, -5512, -5499, -5486, - -5474, -5461, -5449, -5436, - -5424, -5411, -5399, -5386, - -5374, -5362, -5349, -5337, - -5324, -5312, -5299, -5287, - -5275, -5263, -5250, -5238, - -5226, -5213, -5201, -5189, - -5177, -5164, -5152, -5140, - -5128, -5115, -5103, -5091, - -5079, -5067, -5055, -5043, - -5030, -5018, -5006, -4994, - -4982, -4970, -4958, -4946, - -4934, -4922, -4910, -4898, - -4886, -4874, -4862, -4850, - -4838, -4826, -4814, -4803, - -4791, -4778, -4767, -4755, - -4743, -4731, -4719, -4708, - -4696, -4684, -4672, -4660, - -4649, -4637, -4625, -4613, - -4601, -4590, -4578, -4566, - -4554, -4543, -4531, -4520, - -4508, -4496, -4484, -4473, - -4461, -4449, -4438, -4427, - -4415, -4403, -4392, -4380, - -4368, -4357, -4345, -4334, - -4322, -4311, -4299, -4288, - -4276, -4265, -4253, -4242, - -4230, -4219, -4207, -4196, - -4184, -4173, -4162, -4150, - -4139, -4128, -4116, -4105, - -4094, -4082, -4071, -4060, - -4048, -4037, -4026, -4014, - -4003, -3992, -3980, -3969, - -3958, -3946, -3935, -3924, - -3913, -3901, -3890, -3879, - -3868, -3857, -3845, -3834, - -3823, -3812, -3801, -3790, - -3779, -3767, -3756, -3745, - -3734, -3723, -3712, -3700, - -3689, -3678, -3667, -3656, - -3645, -3634, -3623, -3612, - -3601, -3590, -3579, -3568, - -3557, -3545, -3535, -3524, - -3513, -3502, -3491, -3480, - -3469, -3458, -3447, -3436, - -3425, -3414, -3403, -3392, - -3381, -3370, -3360, -3348, - -3337, -3327, -3316, -3305, - -3294, -3283, -3272, -3262, - -3251, -3240, -3229, -3218, - -3207, -3197, -3185, -3175, - -3164, -3153, -3142, -3132, - -3121, -3110, -3099, -3088, - -3078, -3067, -3056, -3045, - -3035, -3024, -3013, -3003, - -2992, -2981, -2970, -2960, - -2949, -2938, -2928, -2917, - -2906, -2895, -2885, -2874, - -2864, -2853, -2842, -2832, - -2821, -2810, -2800, -2789, - -2778, -2768, -2757, -2747, - -2736, -2725, -2715, -2704, - -2694, -2683, -2673, -2662, - -2651, -2641, -2630, -2620, - -2609, -2599, -2588, -2578, - -2567, -2556, -2546, -2535, - -2525, -2515, -2504, -2493, - -2483, -2472, -2462, -2451, - -2441, -2431, -2420, -2410, - -2399, -2389, -2378, -2367, - -2357, -2347, -2336, -2326, - -2315, -2305, -2295, -2284, - -2274, -2263, -2253, -2243, - -2232, -2222, -2211, -2201, - -2191, -2180, -2170, -2159, - -2149, -2139, -2128, -2118, - -2107, -2097, -2087, -2076, - -2066, -2056, -2046, -2035, - -2025, -2014, -2004, -1994, - -1983, -1973, -1963, -1953, - -1942, -1932, -1921, -1911, - -1901, -1891, -1880, -1870, - -1860, -1849, -1839, -1829, - -1819, -1808, -1798, -1788, - -1778, -1767, -1757, -1747, - -1736, -1726, -1716, -1706, - -1695, -1685, -1675, -1665, - -1654, -1644, -1634, -1624, - -1613, -1603, -1593, -1583, - -1573, -1563, -1552, -1542, - -1532, -1522, -1511, -1501, - -1491, -1481, -1471, -1461, - -1450, -1440, -1430, -1420, - -1409, -1400, -1389, -1379, - -1369, -1359, -1348, -1339, - -1328, -1318, -1308, -1298, - -1288, -1278, -1267, -1257, - -1247, -1237, -1227, -1217, - -1207, -1196, -1186, -1176, - -1166, -1156, -1146, -1135, - -1126, -1115, -1105, -1095, - -1085, -1075, -1065, -1055, - -1044, -1034, -1024, -1014, - -1004, -994, -984, -974, - -964, -954, -944, -933, - -923, -913, -903, -893, - -883, -873, -863, -853, - -843, -833, -822, -812, - -802, -792, -782, -772, - -762, -752, -742, -732, - -722, -712, -702, -691, - -682, -671, -662, -651, - -641, -631, -621, -611, - -601, -591, -581, -571, - -561, -551, -541, -531, - -521, -511, -501, -491, - -480, -471, -460, -451, - -440, -430, -420, -410, - -400, -390, -380, -370, - -360, -350, -340, -330, - -320, -310, -300, -290, - -280, -270, -260, -250, - -240, -230, -220, -210, - -199, -190, -179, -170, - -159, -150, -139, -129, - -119, -109, -99, -89, - -79, -69, -59, -49, - -39, -29, -19, -9, - 1, 11, 21, 31, - 41, 51, 61, 71, - 81, 91, 101, 111, - 121, 131, 141, 152, - 161, 172, 181, 192, - 202, 212, 222, 232, - 242, 252, 262, 272, - 282, 292, 302, 312, - 322, 332, 342, 352, - 362, 372, 382, 392, - 402, 412, 422, 433, - 442, 453, 462, 473, - 483, 493, 503, 513, - 523, 533, 543, 553, - 563, 573, 583, 593, - 603, 613, 623, 633, - 643, 653, 664, 673, - 684, 694, 704, 714, - 724, 734, 744, 754, - 764, 774, 784, 794, - 804, 815, 825, 835, - 845, 855, 865, 875, - 885, 895, 905, 915, - 925, 936, 946, 956, - 966, 976, 986, 996, - 1006, 1016, 1026, 1037, - 1047, 1057, 1067, 1077, - 1087, 1097, 1107, 1117, - 1128, 1138, 1148, 1158, - 1168, 1178, 1188, 1198, - 1209, 1219, 1229, 1239, - 1249, 1259, 1269, 1280, - 1290, 1300, 1310, 1320, - 1330, 1341, 1351, 1361, - 1371, 1381, 1391, 1402, - 1412, 1422, 1432, 1442, - 1452, 1463, 1473, 1483, - 1493, 1503, 1513, 1524, - 1534, 1544, 1554, 1565, - 1575, 1585, 1595, 1606, - 1616, 1626, 1636, 1647, - 1656, 1667, 1677, 1687, - 1697, 1708, 1718, 1729, - 1739, 1749, 1759, 1769, - 1780, 1790, 1800, 1810, - 1821, 1831, 1841, 1851, - 1862, 1872, 1883, 1893, - 1903, 1913, 1923, 1934, - 1944, 1955, 1965, 1975, - 1985, 1996, 2006, 2016, - 2027, 2037, 2048, 2058, - 2068, 2079, 2089, 2099, - 2110, 2120, 2130, 2141, - 2151, 2161, 2172, 2182, - 2193, 2203, 2213, 2224, - 2234, 2245, 2255, 2265, - 2276, 2286, 2297, 2307, - 2318, 2328, 2338, 2349, - 2359, 2370, 2380, 2391, - 2401, 2412, 2422, 2433, - 2443, 2454, 2464, 2475, - 2485, 2496, 2506, 2517, - 2527, 2537, 2548, 2559, - 2569, 2580, 2590, 2601, - 2612, 2622, 2632, 2643, - 2654, 2664, 2675, 2685, - 2696, 2707, 2717, 2728, - 2738, 2749, 2759, 2770, - 2781, 2791, 2802, 2813, - 2823, 2834, 2845, 2855, - 2866, 2877, 2887, 2898, - 2909, 2919, 2930, 2941, - 2951, 2962, 2973, 2984, - 2994, 3005, 3015, 3027, - 3037, 3048, 3058, 3069, - 3080, 3091, 3101, 3113, - 3123, 3134, 3145, 3156, - 3166, 3177, 3188, 3199, - 3210, 3220, 3231, 3242, - 3253, 3264, 3275, 3285, - 3296, 3307, 3318, 3329, - 3340, 3351, 3362, 3373, - 3384, 3394, 3405, 3416, - 3427, 3438, 3449, 3460, - 3471, 3482, 3493, 3504, - 3515, 3526, 3537, 3548, - 3559, 3570, 3581, 3592, - 3603, 3614, 3625, 3636, - 3647, 3659, 3670, 3681, - 3692, 3703, 3714, 3725, - 3736, 3747, 3758, 3770, - 3781, 3792, 3803, 3814, - 3825, 3837, 3848, 3859, - 3870, 3881, 3893, 3904, - 3915, 3926, 3937, 3949, - 3960, 3971, 3983, 3994, - 4005, 4017, 4028, 4039, - 4051, 4062, 4073, 4085, - 4096, 4107, 4119, 4130, - 4141, 4153, 4164, 4175, - 4187, 4198, 4210, 4221, - 4233, 4244, 4256, 4267, - 4279, 4290, 4302, 4313, - 4325, 4336, 4348, 4359, - 4371, 4382, 4394, 4406, - 4417, 4429, 4440, 4452, - 4464, 4475, 4487, 4499, - 4510, 4522, 4533, 4545, - 4557, 4569, 4581, 4592, - 4604, 4616, 4627, 4639, - 4651, 4663, 4674, 4686, - 4698, 4710, 4722, 4734, - 4746, 4758, 4769, 4781, - 4793, 4805, 4817, 4829, - 4841, 4853, 4865, 4877, - 4889, 4900, 4913, 4925, - 4936, 4949, 4961, 4973, - 4985, 4997, 5009, 5021, - 5033, 5045, 5057, 5070, - 5081, 5094, 5106, 5118, - 5130, 5143, 5155, 5167, - 5179, 5191, 5204, 5216, - 5228, 5240, 5253, 5265, - 5278, 5290, 5302, 5315, - 5327, 5340, 5352, 5364, - 5377, 5389, 5401, 5414, - 5426, 5439, 5451, 5464, - 5476, 5489, 5502, 5514, - 5527, 5539, 5552, 5564, - 5577, 5590, 5603, 5615, - 5628, 5641, 5653, 5666, - 5679, 5691, 5704, 5717, - 5730, 5743, 5756, 5768, - 5781, 5794, 5807, 5820, - 5833, 5846, 5859, 5872, - 5885, 5897, 5911, 5924, - 5937, 5950, 5963, 5976, - 5989, 6002, 6015, 6028, - 6042, 6055, 6068, 6081, - 6094, 6108, 6121, 6134, - 6147, 6160, 6174, 6187, - 6201, 6214, 6227, 6241, - 6254, 6267, 6281, 6294, - 6308, 6321, 6335, 6348, - 6362, 6375, 6389, 6403, - 6416, 6430, 6443, 6457, - 6471, 6485, 6498, 6512, - 6526, 6540, 6554, 6567, - 6581, 6595, 6609, 6623, - 6637, 6651, 6665, 6679, - 6692, 6706, 6721, 6735, - 6749, 6763, 6777, 6791, - 6805, 6819, 6833, 6848, - 6862, 6876, 6890, 6905, - 6919, 6933, 6948, 6962, - 6976, 6991, 7005, 7020, - 7034, 7049, 7064, 7078, - 7093, 7107, 7122, 7136, - 7151, 7166, 7180, 7195, - 7210, 7225, 7240, 7254, - 7269, 7284, 7299, 7314, - 7329, 7344, 7359, 7374, - 7389, 7404, 7419, 7434, - 7449, 7465, 7480, 7495, - 7510, 7526, 7541, 7556, - 7571, 7587, 7602, 7618, - 7633, 7648, 7664, 7680, - 7695, 7711, 7726, 7742, - 7758, 7773, 7789, 7805, - 7821, 7836, 7852, 7868, - 7884, 7900, 7916, 7932, - 7948, 7964, 7981, 7997, - 8013, 8029, 8045, 8061, - 8078, 8094, 8110, 8127, - 8143, 8160, 8176, 8193, - 8209, 8226, 8242, 8259, - 8276, 8292, 8309, 8326, - 8343, 8360, 8377, 8394, - 8410, 8428, 8444, 8462, - 8479, 8496, 8513, 8530, - 8548, 8565, 8582, 8600, - 8617, 8634, 8652, 8670, - 8687, 8704, 8722, 8740, - 8758, 8775, 8793, 8811, - 8829, 8847, 8865, 8883, - 8901, 8919, 8937, 8955, - 8974, 8992, 9010, 9029, - 9047, 9066, 9084, 9103, - 9121, 9140, 9159, 9177, - 9196, 9215, 9234, 9253, - 9272, 9291, 9310, 9329, - 9349, 9368, 9387, 9406, - 9426, 9445, 9465, 9484, - 9504, 9524, 9544, 9563, - 9583, 9603, 9623, 9643, - 9663, 9683, 9703, 9723, - 9744, 9764, 9785, 9805, - 9826, 9846, 9867, 9888, - 9909, 9930, 9950, 9971, - 9993, 10013, 10035, 10056, - 10077, 10099, 10120, 10142, - 10163, 10185, 10207, 10229, - 10251, 10273, 10294, 10317, - 10339, 10361, 10384, 10406, - 10428, 10451, 10474, 10496, - 10519, 10542, 10565, 10588, - 10612, 10635, 10658, 10682, - 10705, 10729, 10752, 10776, - 10800, 10824, 10848, 10872, - 10896, 10921, 10945, 10969, - 10994, 11019, 11044, 11069, - 11094, 11119, 11144, 11169, - 11195, 11221, 11246, 11272, - 11298, 11324, 11350, 11376, - 11402, 11429, 11456, 11482, - 11509, 11536, 11563, 11590, - 11618, 11645, 11673, 11701, - 11728, 11756, 11785, 11813, - 11842, 11870, 11899, 11928, - 11957, 11986, 12015, 12045, - 12074, 12104, 12134, 12164, - 12194, 12225, 12255, 12286, - 12317, 12348, 12380, 12411, - 12443, 12475, 12507, 12539, - 12571, 12604, 12637, 12670, - 12703, 12737, 12771, 12804, - 12839, 12873, 12907, 12942, - 12977, 13013, 13048, 13084, - 13120, 13156, 13192, 13229, - 13267, 13304, 13341, 13379, - 13418, 13456, 13495, 13534, - 13573, 13613, 13653, 13693, - 13734, 13775, 13817, 13858, - 13901, 13943, 13986, 14029, - 14073, 14117, 14162, 14206, - 14252, 14297, 14343, 14390, - 14437, 14485, 14533, 14582, - 14631, 14680, 14731, 14782, - 14833, 14885, 14937, 14991, - 15044, 15099, 15154, 15210, - 15266, 15324, 15382, 15441, - 15500, 15561, 15622, 15684, - 15747, 15811, 15877, 15943, - 16010, 16078, 16148, 16218, - 16290, 16363, 16437, 16513, - 16590, 16669, 16749, 16831, - 16915, 17000, 17088, 17177, - 17268, 17362, 17458, 17556, - 17657, 17761, 17868, 17977, - 18090, 18207, 18328, 18452, - 18581, 18715, 18854, 18998, - 19149, 19307, 19472, 19645, - 19828, 20021, 20226, 20444, - 20678, 20930, 21204, 21503, - 21835, 22206, 22630, 23124, - 23721, 24478, 25529, 27316, -}; +/* get_crandom - correlated random number generator + * Next number depends on last value. + * rho is scaled to avoid floating point. + */ +static unsigned long get_crandom(struct crndstate *state) +{ + u64 value, rho; + unsigned long answer; + + if (state->rho == 0) /* no correllation */ + return net_random(); + + value = net_random(); + rho = (u64)state->rho + 1; + answer = (value * ((1ull<<32) - rho) + state->last * rho) >> 32; + state->last = answer; + return answer; +} /* tabledist - return a pseudo-randomly distributed value with mean mu and * std deviation sigma. Uses table lookup to approximate the desired * distribution, and a uniformly-distributed pseudo-random source. */ -static inline int tabledist(int mu, int sigma) +static long tabledist(unsigned long mu, long sigma, + struct crndstate *state, const struct disttable *dist) { - int x; - int index; - int sigmamod, sigmadiv; + long t, x; + unsigned long rnd; if (sigma == 0) return mu; - index = (net_random() & (TABLESIZE-1)); - sigmamod = sigma%TABLEFACTOR; - sigmadiv = sigma/TABLEFACTOR; - x = sigmamod*disttable[index]; + rnd = get_crandom(state); + + /* default uniform distribution */ + if (dist == NULL) + return (rnd % (2*sigma)) - sigma + mu; + t = dist->table[rnd % dist->size]; + x = (sigma % NETEM_DIST_SCALE) * t; if (x >= 0) - x += TABLEFACTOR/2; + x += NETEM_DIST_SCALE/2; else - x -= TABLEFACTOR/2; + x -= NETEM_DIST_SCALE/2; - x /= TABLEFACTOR; - x += sigmadiv*disttable[index]; - x += mu; - return x; + return x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu; } -/* Enqueue packets with underlying discipline (fifo) - * but mark them with current time first. - */ -static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) +/* Put skb in the private delayed queue. */ +static int delay_skb(struct Qdisc *sch, struct sk_buff *skb) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb; psched_time_t now; - long delay; + + PSCHED_GET_TIME(now); + PSCHED_TADD2(now, tabledist(q->latency, q->jitter, + &q->delay_cor, q->delay_dist), + cb->time_to_send); + + /* Always queue at tail to keep packets in order */ + if (likely(q->delayed.qlen < q->limit)) { + __skb_queue_tail(&q->delayed, skb); + sch->q.qlen++; + sch->stats.bytes += skb->len; + sch->stats.packets++; + return NET_XMIT_SUCCESS; + } + + sch->stats.drops++; + kfree_skb(skb); + return NET_XMIT_DROP; +} + +static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) +{ + struct netem_sched_data *q = qdisc_priv(sch); pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies); /* Random packet drop 0 => none, ~0 => all */ - if (q->loss && q->loss >= net_random()) { + if (q->loss && q->loss >= get_crandom(&q->loss_cor)) { + pr_debug("netem_enqueue: random loss\n"); sch->stats.drops++; return 0; /* lie about loss so TCP doesn't know */ } + /* Random duplication */ + if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) { + struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); + + pr_debug("netem_enqueue: dup %p\n", skb2); + if (skb2) + delay_skb(sch, skb2); + } /* If doing simple delay then gap == 0 so all packets * go into the delayed holding queue @@ -634,33 +203,14 @@ static int netem_enqueue(struct sk_buff } q->counter = 0; - - PSCHED_GET_TIME(now); - if (q->jitter) - delay = tabledist(q->latency, q->jitter); - else - delay = q->latency; - PSCHED_TADD2(now, delay, cb->time_to_send); - - /* Always queue at tail to keep packets in order */ - if (likely(q->delayed.qlen < q->limit)) { - __skb_queue_tail(&q->delayed, skb); - sch->q.qlen++; - sch->stats.bytes += skb->len; - sch->stats.packets++; - return 0; - } - - sch->stats.drops++; - kfree_skb(skb); - return NET_XMIT_DROP; + return delay_skb(sch, skb); } /* Requeue packets but don't change time stamp */ static int netem_requeue(struct sk_buff *skb, struct Qdisc *sch) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); int ret; if ((ret = q->qdisc->ops->requeue(skb, q->qdisc)) == 0) @@ -671,7 +221,7 @@ static int netem_requeue(struct sk_buff static unsigned int netem_drop(struct Qdisc* sch) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); unsigned int len; if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) { @@ -687,7 +237,7 @@ static unsigned int netem_drop(struct Qd */ static struct sk_buff *netem_dequeue(struct Qdisc *sch) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); struct sk_buff *skb; psched_time_t now; @@ -727,7 +277,7 @@ static void netem_watchdog(unsigned long static void netem_reset(struct Qdisc *sch) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); qdisc_reset(q->qdisc); skb_queue_purge(&q->delayed); @@ -753,92 +303,163 @@ static int set_fifo_limit(struct Qdisc * return ret; } -static int netem_change(struct Qdisc *sch, struct rtattr *opt) +/* + * Distribution data is a variable size payload containing + * signed 16 bit values. + */ +static int get_dist_table(struct Qdisc *sch, const struct rtattr *attr) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; - struct tc_netem_qopt *qopt = RTA_DATA(opt); - struct Qdisc *child; - int ret; + struct netem_sched_data *q = qdisc_priv(sch); + unsigned long n = RTA_PAYLOAD(attr)/sizeof(__s16); + const __s16 *data = RTA_DATA(attr); + struct disttable *d; + int i; + + if (n > 65536) + return -EINVAL; - if (opt->rta_len < RTA_LENGTH(sizeof(*qopt))) + d = kmalloc(sizeof(*d) + n*sizeof(d->table[0]), GFP_KERNEL); + if (!d) + return -ENOMEM; + + d->size = n; + for (i = 0; i < n; i++) + d->table[i] = data[i]; + + spin_lock_bh(&sch->dev->queue_lock); + d = xchg(&q->delay_dist, d); + spin_unlock_bh(&sch->dev->queue_lock); + + kfree(d); + return 0; +} + +static int get_correlation(struct Qdisc *sch, const struct rtattr *attr) +{ + struct netem_sched_data *q = qdisc_priv(sch); + const struct tc_netem_corr *c = RTA_DATA(attr); + + if (RTA_PAYLOAD(attr) != sizeof(*c)) return -EINVAL; - child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); - if (!child) + init_crandom(&q->delay_cor, c->delay_corr); + init_crandom(&q->loss_cor, c->loss_corr); + init_crandom(&q->dup_cor, c->dup_corr); + return 0; +} + +static int netem_change(struct Qdisc *sch, struct rtattr *opt) +{ + struct netem_sched_data *q = qdisc_priv(sch); + struct tc_netem_qopt *qopt; + int ret; + + if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt)) return -EINVAL; - ret = set_fifo_limit(child, qopt->limit); + qopt = RTA_DATA(opt); + ret = set_fifo_limit(q->qdisc, qopt->limit); if (ret) { - qdisc_destroy(child); + pr_debug("netem: can't set fifo limit\n"); return ret; } - - sch_tree_lock(sch); - if (child) { - child = xchg(&q->qdisc, child); - if (child != &noop_qdisc) - qdisc_destroy(child); - q->latency = qopt->latency; - q->jitter = qopt->jitter; - q->limit = qopt->limit; - q->gap = qopt->gap; - q->loss = qopt->loss; + q->latency = qopt->latency; + q->jitter = qopt->jitter; + q->limit = qopt->limit; + q->gap = qopt->gap; + q->loss = qopt->loss; + q->duplicate = qopt->duplicate; + + /* Handle nested options after initial queue options. + * Should have put all options in nested format but too late now. + */ + if (RTA_PAYLOAD(opt) > sizeof(*qopt)) { + struct rtattr *tb[TCA_NETEM_MAX]; + if (rtattr_parse(tb, TCA_NETEM_MAX, + RTA_DATA(opt) + sizeof(*qopt), + RTA_PAYLOAD(opt) - sizeof(*qopt))) + return -EINVAL; + + if (tb[TCA_NETEM_CORR-1]) { + ret = get_correlation(sch, tb[TCA_NETEM_CORR-1]); + if (ret) + return ret; + } + + if (tb[TCA_NETEM_DELAY_DIST-1]) { + ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST-1]); + if (ret) + return ret; + } } - sch_tree_unlock(sch); + return 0; } static int netem_init(struct Qdisc *sch, struct rtattr *opt) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; - int err; + struct netem_sched_data *q = qdisc_priv(sch); + int ret; if (!opt) return -EINVAL; MOD_INC_USE_COUNT; skb_queue_head_init(&q->delayed); - q->qdisc = &noop_qdisc; - init_timer(&q->timer); q->timer.function = netem_watchdog; q->timer.data = (unsigned long) sch; q->counter = 0; - err = netem_change(sch, opt); - if (err != 0) + q->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + if (!q->qdisc) { + pr_debug("netem: qdisc create failed\n"); + return -ENOMEM; + } + + ret = netem_change(sch, opt); + if (ret) { + pr_debug("netem: change failed\n"); + qdisc_destroy(q->qdisc); MOD_DEC_USE_COUNT; - return err; + } + return ret; } static void netem_destroy(struct Qdisc *sch) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; - - del_timer(&q->timer); + struct netem_sched_data *q = qdisc_priv(sch); + del_timer_sync(&q->timer); qdisc_destroy(q->qdisc); - q->qdisc = &noop_qdisc; - + kfree(q->delay_dist); MOD_DEC_USE_COUNT; } static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + const struct netem_sched_data *q = qdisc_priv(sch); unsigned char *b = skb->tail; + struct rtattr *rta = (struct rtattr *) b; struct tc_netem_qopt qopt; + struct tc_netem_corr cor; qopt.latency = q->latency; qopt.jitter = q->jitter; qopt.limit = q->limit; qopt.loss = q->loss; qopt.gap = q->gap; - + qopt.duplicate = q->duplicate; RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt); + cor.delay_corr = q->delay_cor.rho; + cor.loss_corr = q->loss_cor.rho; + cor.dup_corr = q->dup_cor.rho; + RTA_PUT(skb, TCA_NETEM_CORR, sizeof(cor), &cor); + rta->rta_len = skb->tail - b; + return skb->len; rtattr_failure: @@ -849,7 +470,7 @@ rtattr_failure: static int netem_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, struct tcmsg *tcm) { - struct netem_sched_data *q = (struct netem_sched_data*)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); if (cl != 1) /* only one class */ return -ENOENT; @@ -863,7 +484,7 @@ static int netem_dump_class(struct Qdisc static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct Qdisc **old) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); if (new == NULL) new = &noop_qdisc; @@ -879,7 +500,7 @@ static int netem_graft(struct Qdisc *sch static struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg) { - struct netem_sched_data *q = (struct netem_sched_data *)sch->data; + struct netem_sched_data *q = qdisc_priv(sch); return q->qdisc; } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/associola.c linux-2.4.28-pre3/net/sctp/associola.c --- linux-2.4.27/net/sctp/associola.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sctp/associola.c 2004-09-10 19:34:10.000000000 +0000 @@ -1108,6 +1108,7 @@ static inline int sctp_peer_needs_update case SCTP_STATE_ESTABLISHED: case SCTP_STATE_SHUTDOWN_PENDING: case SCTP_STATE_SHUTDOWN_RECEIVED: + case SCTP_STATE_SHUTDOWN_SENT: if ((asoc->rwnd > asoc->a_rwnd) && ((asoc->rwnd - asoc->a_rwnd) >= min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pmtu))) diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/inqueue.c linux-2.4.28-pre3/net/sctp/inqueue.c --- linux-2.4.27/net/sctp/inqueue.c 2004-04-14 13:05:41.000000000 +0000 +++ linux-2.4.28-pre3/net/sctp/inqueue.c 2004-09-10 19:34:10.000000000 +0000 @@ -81,7 +81,7 @@ void sctp_inq_free(struct sctp_inq *queu struct sctp_chunk *chunk; /* Empty the queue. */ - while ((chunk = (struct sctp_chunk *) skb_dequeue(&queue->in))) + while ((chunk = (struct sctp_chunk *) skb_dequeue(&queue->in)) != NULL) sctp_chunk_free(chunk); /* If there is a packet which is currently being worked on, diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/output.c linux-2.4.28-pre3/net/sctp/output.c --- linux-2.4.27/net/sctp/output.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sctp/output.c 2004-09-10 19:34:36.000000000 +0000 @@ -133,7 +133,7 @@ void sctp_packet_free(struct sctp_packet SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet); - while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) + while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL) sctp_chunk_free(chunk); if (packet->malloced) @@ -370,7 +370,7 @@ int sctp_packet_transmit(struct sctp_pac * [This whole comment explains WORD_ROUND() below.] */ SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n"); - while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) { + while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL) { if (sctp_chunk_is_data(chunk)) { if (!chunk->has_tsn) { @@ -511,7 +511,7 @@ err: * will get resent or dropped later. */ - while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) { + while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL) { if (!sctp_chunk_is_data(chunk)) sctp_chunk_free(chunk); } diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/outqueue.c linux-2.4.28-pre3/net/sctp/outqueue.c --- linux-2.4.27/net/sctp/outqueue.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sctp/outqueue.c 2004-09-10 19:33:27.000000000 +0000 @@ -245,7 +245,7 @@ void sctp_outq_teardown(struct sctp_outq /* Throw away unacknowledged chunks. */ list_for_each(pos, &q->asoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); - while ((lchunk = sctp_list_dequeue(&transport->transmitted))) { + while ((lchunk = sctp_list_dequeue(&transport->transmitted)) != NULL) { chunk = list_entry(lchunk, struct sctp_chunk, transmitted_list); /* Mark as part of a failed message. */ @@ -282,7 +282,7 @@ void sctp_outq_teardown(struct sctp_outq } /* Throw away any leftover data chunks. */ - while ((chunk = sctp_outq_dequeue_data(q))) { + while ((chunk = sctp_outq_dequeue_data(q)) != NULL) { /* Mark as send failure. */ sctp_chunk_fail(chunk, q->error); @@ -292,7 +292,7 @@ void sctp_outq_teardown(struct sctp_outq q->error = 0; /* Throw away any leftover control chunks. */ - while ((chunk = (struct sctp_chunk *) skb_dequeue(&q->control))) + while ((chunk = (struct sctp_chunk *) skb_dequeue(&q->control)) != NULL) sctp_chunk_free(chunk); } @@ -525,10 +525,10 @@ static int sctp_outq_flush_rtx(struct sc int rtx_timeout, int *start_timer) { struct list_head *lqueue; - struct list_head *lchunk; + struct list_head *lchunk, *lchunk1; struct sctp_transport *transport = pkt->transport; sctp_xmit_t status; - struct sctp_chunk *chunk; + struct sctp_chunk *chunk, *chunk1; struct sctp_association *asoc; int error = 0; @@ -615,6 +615,12 @@ static int sctp_outq_flush_rtx(struct sc * the transmitted list. */ list_add_tail(lchunk, &transport->transmitted); + + /* Mark the chunk as ineligible for fast retransmit + * after it is retransmitted. + */ + chunk->fast_retransmit = 0; + *start_timer = 1; q->empty = 0; @@ -622,6 +628,18 @@ static int sctp_outq_flush_rtx(struct sc lchunk = sctp_list_dequeue(lqueue); break; }; + + /* If we are here due to a retransmit timeout or a fast + * retransmit and if there are any chunks left in the retransmit + * queue that could not fit in the PMTU sized packet, they need * to be marked as ineligible for a subsequent fast retransmit. + */ + if (rtx_timeout && !lchunk) { + list_for_each(lchunk1, lqueue) { + chunk1 = list_entry(lchunk1, struct sctp_chunk, + transmitted_list); + chunk1->fast_retransmit = 0; + } + } } return error; @@ -681,7 +699,7 @@ int sctp_outq_flush(struct sctp_outq *q, */ queue = &q->control; - while ((chunk = (struct sctp_chunk *)skb_dequeue(queue))) { + while ((chunk = (struct sctp_chunk *)skb_dequeue(queue)) != NULL) { /* Pick the right transport to use. */ new_transport = chunk->transport; @@ -812,7 +830,7 @@ int sctp_outq_flush(struct sctp_outq *q, start_timer = 0; queue = &q->out; - while ((chunk = sctp_outq_dequeue_data(q))) { + while ((chunk = sctp_outq_dequeue_data(q)) != NULL) { /* RFC 2960 6.5 Every DATA chunk MUST carry a valid * stream identifier. */ @@ -866,7 +884,7 @@ int sctp_outq_flush(struct sctp_outq *q, SCTP_DEBUG_PRINTK("TX TSN 0x%x skb->head " "%p skb->users %d.\n", ntohl(chunk->subh.data_hdr->tsn), - chunk->skb ?chunk->skb->head : 0, + chunk->skb ?chunk->skb->head : NULL, chunk->skb ? atomic_read(&chunk->skb->users) : -1); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/protocol.c linux-2.4.28-pre3/net/sctp/protocol.c --- linux-2.4.27/net/sctp/protocol.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sctp/protocol.c 2004-09-10 19:35:00.000000000 +0000 @@ -97,7 +97,7 @@ __init int sctp_proc_init(void) { if (!proc_net_sctp) { struct proc_dir_entry *ent; - ent = proc_mkdir("net/sctp", 0); + ent = proc_mkdir("net/sctp", NULL); if (ent) { ent->owner = THIS_MODULE; proc_net_sctp = ent; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/sm_sideeffect.c linux-2.4.28-pre3/net/sctp/sm_sideeffect.c --- linux-2.4.27/net/sctp/sm_sideeffect.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sctp/sm_sideeffect.c 2004-09-10 19:35:31.000000000 +0000 @@ -529,6 +529,23 @@ static void sctp_cmd_hb_timers_stop(sctp } } +/* Helper function to stop any pending T3-RTX timers */ +static void sctp_cmd_t3_rtx_timers_stop(sctp_cmd_seq_t *cmds, + struct sctp_association *asoc) +{ + struct sctp_transport *t; + struct list_head *pos; + + list_for_each(pos, &asoc->peer.transport_addr_list) { + t = list_entry(pos, struct sctp_transport, transports); + if (timer_pending(&t->T3_rtx_timer) && + del_timer(&t->T3_rtx_timer)) { + sctp_transport_put(t); + } + } +} + + /* Helper function to update the heartbeat timer. */ static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds, struct sctp_association *asoc, @@ -749,6 +766,26 @@ static void sctp_cmd_process_fwdtsn(stru return; } +/* Helper function to remove the association non-primary peer + * transports. + */ +static void sctp_cmd_del_non_primary(struct sctp_association *asoc) +{ + struct sctp_transport *t; + struct list_head *pos; + struct list_head *temp; + + list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { + t = list_entry(pos, struct sctp_transport, transports); + if (!sctp_cmp_addr_exact(&t->ipaddr, + &asoc->peer.primary_addr)) { + sctp_assoc_del_peer(asoc, &t->ipaddr); + } + } + + return; +} + /* These three macros allow us to pull the debugging code out of the * main flow of sctp_do_sm() to keep attention focused on the real * functionality there. @@ -1048,6 +1085,27 @@ int sctp_cmd_interpreter(sctp_event_t ev if (cmd->obj.ptr) sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(cmd->obj.ptr)); + + /* FIXME - Eventually come up with a cleaner way to + * enabling COOKIE-ECHO + DATA bundling during + * multihoming stale cookie scenarios, the following + * command plays with asoc->peer.retran_path to + * avoid the problem of sending the COOKIE-ECHO and + * DATA in different paths, which could result + * in the association being ABORTed if the DATA chunk + * is processed first by the server. Checking the + * init error counter simply causes this command + * to be executed only during failed attempts of + * association establishment. + */ + if ((asoc->peer.retran_path != + asoc->peer.primary_path) && + (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) { + sctp_add_cmd_sf(commands, + SCTP_CMD_FORCE_PRIM_RETRAN, + SCTP_NULL()); + } + break; case SCTP_CMD_GEN_SHUTDOWN: @@ -1282,6 +1340,19 @@ int sctp_cmd_interpreter(sctp_event_t ev case SCTP_CMD_CLEAR_INIT_TAG: asoc->peer.i.init_tag = 0; break; + case SCTP_CMD_DEL_NON_PRIMARY: + sctp_cmd_del_non_primary(asoc); + break; + case SCTP_CMD_T3_RTX_TIMERS_STOP: + sctp_cmd_t3_rtx_timers_stop(commands, asoc); + break; + case SCTP_CMD_FORCE_PRIM_RETRAN: + t = asoc->peer.retran_path; + asoc->peer.retran_path = asoc->peer.primary_path; + error = sctp_outq_uncork(&asoc->outqueue); + local_cork = 0; + asoc->peer.retran_path = t; + break; default: printk(KERN_WARNING "Impossible command: %u, %p\n", cmd->verb, cmd->obj.ptr); diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/sm_statefuns.c linux-2.4.28-pre3/net/sctp/sm_statefuns.c --- linux-2.4.27/net/sctp/sm_statefuns.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sctp/sm_statefuns.c 2004-09-10 19:34:36.000000000 +0000 @@ -472,8 +472,6 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(c */ sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); - sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET, - SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR)); sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, @@ -674,6 +672,15 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(co if (!sctp_vtag_verify(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); + /* Reset init error count upon receipt of COOKIE-ACK, + * to avoid problems with the managemement of this + * counter in stale cookie situations when a transition back + * from the COOKIE-ECHOED state to the COOKIE-WAIT + * state is performed. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET, + SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR)); + /* RFC 2960 5.1 Normal Establishment of an Association * * E) Upon reception of the COOKIE ACK, endpoint "A" will move @@ -995,7 +1002,7 @@ static int sctp_sf_check_restart_addrs(c /* Search through all current addresses and make sure * we aren't adding any new ones. */ - new_addr = 0; + new_addr = NULL; found = 0; list_for_each(pos, &new_asoc->peer.transport_addr_list) { @@ -1872,8 +1879,6 @@ sctp_disposition_t sctp_sf_do_5_2_6_stal time_t stale; sctp_cookie_preserve_param_t bht; sctp_errhdr_t *err; - struct list_head *pos; - struct sctp_transport *t; struct sctp_chunk *reply; struct sctp_bind_addr *bp; int attempts; @@ -1920,20 +1925,27 @@ sctp_disposition_t sctp_sf_do_5_2_6_stal /* Clear peer's init_tag cached in assoc as we are sending a new INIT */ sctp_add_cmd_sf(commands, SCTP_CMD_CLEAR_INIT_TAG, SCTP_NULL()); + /* Stop pending T3-rtx and heartbeat timers */ + sctp_add_cmd_sf(commands, SCTP_CMD_T3_RTX_TIMERS_STOP, SCTP_NULL()); + sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL()); + + /* Delete non-primary peer ip addresses since we are transitioning + * back to the COOKIE-WAIT state + */ + sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL()); + + /* If we've sent any data bundled with COOKIE-ECHO we will need to + * resend + */ + sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, + SCTP_TRANSPORT(asoc->peer.primary_path)); + /* Cast away the const modifier, as we want to just * rerun it through as a sideffect. */ sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC, SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR)); - /* If we've sent any data bundled with COOKIE-ECHO we need to - * resend. - */ - list_for_each(pos, &asoc->peer.transport_addr_list) { - t = list_entry(pos, struct sctp_transport, transports); - sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, SCTP_TRANSPORT(t)); - } - sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, @@ -2321,12 +2333,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2( sctp_cmd_seq_t *commands) { struct sctp_chunk *chunk = arg; - sctp_datahdr_t *data_hdr; - struct sctp_chunk *err; - size_t datalen; - sctp_verb_t deliver; - int tmp; - __u32 tsn; + int error; if (!sctp_vtag_verify(chunk, asoc)) { sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, @@ -2334,158 +2341,22 @@ sctp_disposition_t sctp_sf_eat_data_6_2( return sctp_sf_pdiscard(ep, asoc, type, arg, commands); } - data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data; - skb_pull(chunk->skb, sizeof(sctp_datahdr_t)); - - tsn = ntohl(data_hdr->tsn); - SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn); - - /* ASSERT: Now skb->data is really the user data. */ - - /* Process ECN based congestion. - * - * Since the chunk structure is reused for all chunks within - * a packet, we use ecn_ce_done to track if we've already - * done CE processing for this packet. - * - * We need to do ECN processing even if we plan to discard the - * chunk later. - */ - - if (!chunk->ecn_ce_done) { - struct sctp_af *af; - chunk->ecn_ce_done = 1; - - af = sctp_get_af_specific( - ipver2af(chunk->skb->nh.iph->version)); - - if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) { - /* Do real work as sideffect. */ - sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, - SCTP_U32(tsn)); - } - } - - tmp = sctp_tsnmap_check(&asoc->peer.tsn_map, tsn); - if (tmp < 0) { - /* The TSN is too high--silently discard the chunk and - * count on it getting retransmitted later. - */ + error = sctp_eat_data(asoc, chunk, commands ); + switch (error) { + case SCTP_IERROR_NO_ERROR: + break; + case SCTP_IERROR_HIGH_TSN: + case SCTP_IERROR_BAD_STREAM: goto discard_noforce; - } else if (tmp > 0) { - /* This is a duplicate. Record it. */ - sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_DUP, SCTP_U32(tsn)); + case SCTP_IERROR_DUP_TSN: + case SCTP_IERROR_IGNORE_TSN: goto discard_force; + case SCTP_IERROR_NO_DATA: + goto consume; + default: + BUG(); } - /* This is a new TSN. */ - - /* Discard if there is no room in the receive window. - * Actually, allow a little bit of overflow (up to a MTU). - */ - datalen = ntohs(chunk->chunk_hdr->length); - datalen -= sizeof(sctp_data_chunk_t); - - deliver = SCTP_CMD_CHUNK_ULP; - - /* Think about partial delivery. */ - if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { - - /* Even if we don't accept this chunk there is - * memory pressure. - */ - sctp_add_cmd_sf(commands, SCTP_CMD_PART_DELIVER, SCTP_NULL()); - } - - /* Spill over rwnd a little bit. Note: While allowed, this spill over - * seems a bit troublesome in that frag_point varies based on - * PMTU. In cases, such as loopback, this might be a rather - * large spill over. - */ - if (!asoc->rwnd || asoc->rwnd_over || - (datalen > asoc->rwnd + asoc->frag_point)) { - - /* If this is the next TSN, consider reneging to make - * room. Note: Playing nice with a confused sender. A - * malicious sender can still eat up all our buffer - * space and in the future we may want to detect and - * do more drastic reneging. - */ - if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) && - (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) { - SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn); - deliver = SCTP_CMD_RENEGE; - } else { - SCTP_DEBUG_PRINTK("Discard tsn: %u len: %Zd, " - "rwnd: %d\n", tsn, datalen, - asoc->rwnd); - goto discard_force; - } - } - - /* - * Section 3.3.10.9 No User Data (9) - * - * Cause of error - * --------------- - * No User Data: This error cause is returned to the originator of a - * DATA chunk if a received DATA chunk has no user data. - */ - if (unlikely(0 == datalen)) { - err = sctp_make_abort_no_data(asoc, chunk, tsn); - if (err) { - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, - SCTP_CHUNK(err)); - } - /* We are going to ABORT, so we might as well stop - * processing the rest of the chunks in the packet. - */ - sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); - sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_NO_DATA)); - SCTP_INC_STATS(SctpAborteds); - SCTP_DEC_STATS(SctpCurrEstab); - return SCTP_DISPOSITION_CONSUME; - } - - /* If definately accepting the DATA chunk, record its TSN, otherwise - * wait for renege processing. - */ - if (SCTP_CMD_CHUNK_ULP == deliver) - sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn)); - - /* Note: Some chunks may get overcounted (if we drop) or overcounted - * if we renege and the chunk arrives again. - */ - if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) - SCTP_INC_STATS(SctpInUnorderChunks); - else - SCTP_INC_STATS(SctpInOrderChunks); - - /* RFC 2960 6.5 Stream Identifier and Stream Sequence Number - * - * If an endpoint receive a DATA chunk with an invalid stream - * identifier, it shall acknowledge the reception of the DATA chunk - * following the normal procedure, immediately send an ERROR chunk - * with cause set to "Invalid Stream Identifier" (See Section 3.3.10) - * and discard the DATA chunk. - */ - if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) { - err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM, - &data_hdr->stream, - sizeof(data_hdr->stream)); - if (err) - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, - SCTP_CHUNK(err)); - goto discard_noforce; - } - - /* Send the data up to the user. Note: Schedule the - * SCTP_CMD_CHUNK_ULP cmd before the SCTP_CMD_GEN_SACK, as the SACK - * chunk needs the updated rwnd. - */ - sctp_add_cmd_sf(commands, deliver, SCTP_CHUNK(chunk)); - if (asoc->autoclose) { sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); @@ -2551,6 +2422,9 @@ discard_noforce: SCTP_TO(SCTP_EVENT_TIMEOUT_SACK)); } return SCTP_DISPOSITION_DISCARD; +consume: + return SCTP_DISPOSITION_CONSUME; + } /* @@ -2576,11 +2450,7 @@ sctp_disposition_t sctp_sf_eat_data_fast sctp_cmd_seq_t *commands) { struct sctp_chunk *chunk = arg; - sctp_datahdr_t *data_hdr; - struct sctp_chunk *err; - size_t datalen; - int tmp; - __u32 tsn; + int error; if (!sctp_vtag_verify(chunk, asoc)) { sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, @@ -2588,110 +2458,23 @@ sctp_disposition_t sctp_sf_eat_data_fast return sctp_sf_pdiscard(ep, asoc, type, arg, commands); } - data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *) chunk->skb->data; - skb_pull(chunk->skb, sizeof(sctp_datahdr_t)); - - tsn = ntohl(data_hdr->tsn); - - SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn); - - /* ASSERT: Now skb->data is really the user data. */ - - /* Process ECN based congestion. - * - * Since the chunk structure is reused for all chunks within - * a packet, we use ecn_ce_done to track if we've already - * done CE processing for this packet. - * - * We need to do ECN processing even if we plan to discard the - * chunk later. - */ - if (!chunk->ecn_ce_done) { - struct sctp_af *af; - chunk->ecn_ce_done = 1; - - af = sctp_get_af_specific( - ipver2af(chunk->skb->nh.iph->version)); - - if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) { - /* Do real work as sideffect. */ - sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, - SCTP_U32(tsn)); - } - } - - tmp = sctp_tsnmap_check(&asoc->peer.tsn_map, tsn); - if (tmp < 0) { - /* The TSN is too high--silently discard the chunk and - * count on it getting retransmitted later. - */ - goto gen_shutdown; - } else if (tmp > 0) { - /* This is a duplicate. Record it. */ - sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_DUP, SCTP_U32(tsn)); - goto gen_shutdown; - } - - /* This is a new TSN. */ - datalen = ntohs(chunk->chunk_hdr->length); - datalen -= sizeof(sctp_data_chunk_t); - - /* - * Section 3.3.10.9 No User Data (9) - * - * Cause of error - * --------------- - * No User Data: This error cause is returned to the originator of a - * DATA chunk if a received DATA chunk has no user data. - */ - if (unlikely(0 == datalen)) { - err = sctp_make_abort_no_data(asoc, chunk, tsn); - if (err) { - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, - SCTP_CHUNK(err)); - } - /* We are going to ABORT, so we might as well stop - * processing the rest of the chunks in the packet. - */ - sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); - sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_U32(SCTP_ERROR_NO_DATA)); - SCTP_INC_STATS(SctpAborteds); - SCTP_DEC_STATS(SctpCurrEstab); - return SCTP_DISPOSITION_CONSUME; - } - - /* We are accepting this DATA chunk. */ - - /* Record the fact that we have received this TSN. */ - sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn)); - - if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) - SCTP_INC_STATS(SctpInUnorderChunks); - else - SCTP_INC_STATS(SctpInOrderChunks); - - /* RFC 2960 6.5 Stream Identifier and Stream Sequence Number - * - * If an endpoint receive a DATA chunk with an invalid stream - * identifier, it shall acknowledge the reception of the DATA chunk - * following the normal procedure, immediately send an ERROR chunk - * with cause set to "Invalid Stream Identifier" (See Section 3.3.10) - * and discard the DATA chunk. - */ - if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) { - err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM, - &data_hdr->stream, - sizeof(data_hdr->stream)); - if (err) { - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, - SCTP_CHUNK(err)); - } + error = sctp_eat_data(asoc, chunk, commands ); + switch (error) { + case SCTP_IERROR_NO_ERROR: + case SCTP_IERROR_HIGH_TSN: + case SCTP_IERROR_DUP_TSN: + case SCTP_IERROR_IGNORE_TSN: + case SCTP_IERROR_BAD_STREAM: + break; + case SCTP_IERROR_NO_DATA: + goto consume; + default: + BUG(); } /* Go a head and force a SACK, since we are shutting down. */ -gen_shutdown: + /* Implementor's Guide. * * While in SHUTDOWN-SENT state, the SHUTDOWN sender MUST immediately @@ -2707,6 +2490,8 @@ gen_shutdown: sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); } + +consume: return SCTP_DISPOSITION_CONSUME; } @@ -4709,7 +4494,7 @@ struct sctp_sackhdr *sctp_sm_pull_sack(s num_blocks = ntohs(sack->num_gap_ack_blocks); num_dup_tsns = ntohs(sack->num_dup_tsns); len = sizeof(struct sctp_sackhdr); - len = (num_blocks + num_dup_tsns) * sizeof(__u32); + len += (num_blocks + num_dup_tsns) * sizeof(__u32); if (len > chunk->skb->len) return NULL; @@ -4848,3 +4633,171 @@ void sctp_send_stale_cookie_err(const st sctp_chunk_free (err_chunk); } } + + +/* Process a data chunk */ +int sctp_eat_data(const struct sctp_association *asoc, + struct sctp_chunk *chunk, + sctp_cmd_seq_t *commands) +{ + sctp_datahdr_t *data_hdr; + struct sctp_chunk *err; + size_t datalen; + sctp_verb_t deliver; + int tmp; + __u32 tsn; + + data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data; + skb_pull(chunk->skb, sizeof(sctp_datahdr_t)); + + tsn = ntohl(data_hdr->tsn); + SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn); + + /* ASSERT: Now skb->data is really the user data. */ + + /* Process ECN based congestion. + * + * Since the chunk structure is reused for all chunks within + * a packet, we use ecn_ce_done to track if we've already + * done CE processing for this packet. + * + * We need to do ECN processing even if we plan to discard the + * chunk later. + */ + + if (!chunk->ecn_ce_done) { + struct sctp_af *af; + chunk->ecn_ce_done = 1; + + af = sctp_get_af_specific( + ipver2af(chunk->skb->nh.iph->version)); + + if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) { + /* Do real work as sideffect. */ + sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, + SCTP_U32(tsn)); + } + } + + tmp = sctp_tsnmap_check(&asoc->peer.tsn_map, tsn); + if (tmp < 0) { + /* The TSN is too high--silently discard the chunk and + * count on it getting retransmitted later. + */ + return SCTP_IERROR_HIGH_TSN; + } else if (tmp > 0) { + /* This is a duplicate. Record it. */ + sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_DUP, SCTP_U32(tsn)); + return SCTP_IERROR_DUP_TSN; + } + + /* This is a new TSN. */ + + /* Discard if there is no room in the receive window. + * Actually, allow a little bit of overflow (up to a MTU). + */ + datalen = ntohs(chunk->chunk_hdr->length); + datalen -= sizeof(sctp_data_chunk_t); + + deliver = SCTP_CMD_CHUNK_ULP; + + /* Think about partial delivery. */ + if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { + + /* Even if we don't accept this chunk there is + * memory pressure. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_PART_DELIVER, SCTP_NULL()); + } + + /* Spill over rwnd a little bit. Note: While allowed, this spill over + * seems a bit troublesome in that frag_point varies based on + * PMTU. In cases, such as loopback, this might be a rather + * large spill over. + */ + if (!asoc->rwnd || asoc->rwnd_over || + (datalen > asoc->rwnd + asoc->frag_point)) { + + /* If this is the next TSN, consider reneging to make + * room. Note: Playing nice with a confused sender. A + * malicious sender can still eat up all our buffer + * space and in the future we may want to detect and + * do more drastic reneging. + */ + if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) && + (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) { + SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn); + deliver = SCTP_CMD_RENEGE; + } else { + SCTP_DEBUG_PRINTK("Discard tsn: %u len: %Zd, " + "rwnd: %d\n", tsn, datalen, + asoc->rwnd); + return SCTP_IERROR_IGNORE_TSN; + } + } + + /* + * Section 3.3.10.9 No User Data (9) + * + * Cause of error + * --------------- + * No User Data: This error cause is returned to the originator of a + * DATA chunk if a received DATA chunk has no user data. + */ + if (unlikely(0 == datalen)) { + err = sctp_make_abort_no_data(asoc, chunk, tsn); + if (err) { + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, + SCTP_CHUNK(err)); + } + /* We are going to ABORT, so we might as well stop + * processing the rest of the chunks in the packet. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); + sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, + SCTP_U32(SCTP_ERROR_NO_DATA)); + SCTP_INC_STATS(SctpAborteds); + SCTP_DEC_STATS(SctpCurrEstab); + return SCTP_IERROR_NO_DATA; + } + + /* If definately accepting the DATA chunk, record its TSN, otherwise + * wait for renege processing. + */ + if (SCTP_CMD_CHUNK_ULP == deliver) + sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn)); + + /* Note: Some chunks may get overcounted (if we drop) or overcounted + * if we renege and the chunk arrives again. + */ + if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) + SCTP_INC_STATS(SctpInUnorderChunks); + else + SCTP_INC_STATS(SctpInOrderChunks); + + /* RFC 2960 6.5 Stream Identifier and Stream Sequence Number + * + * If an endpoint receive a DATA chunk with an invalid stream + * identifier, it shall acknowledge the reception of the DATA chunk + * following the normal procedure, immediately send an ERROR chunk + * with cause set to "Invalid Stream Identifier" (See Section 3.3.10) + * and discard the DATA chunk. + */ + if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) { + err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM, + &data_hdr->stream, + sizeof(data_hdr->stream)); + if (err) + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, + SCTP_CHUNK(err)); + return SCTP_IERROR_BAD_STREAM; + } + + /* Send the data up to the user. Note: Schedule the + * SCTP_CMD_CHUNK_ULP cmd before the SCTP_CMD_GEN_SACK, as the SACK + * chunk needs the updated rwnd. + */ + sctp_add_cmd_sf(commands, deliver, SCTP_CHUNK(chunk)); + + return SCTP_IERROR_NO_ERROR; +} diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/socket.c linux-2.4.28-pre3/net/sctp/socket.c --- linux-2.4.27/net/sctp/socket.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sctp/socket.c 2004-09-10 19:32:58.000000000 +0000 @@ -86,8 +86,6 @@ /* Forward declarations for internal helper functions. */ static int sctp_writeable(struct sock *sk); -static inline int sctp_wspace(struct sctp_association *asoc); -static inline void sctp_set_owner_w(struct sctp_chunk *chunk); static void sctp_wfree(struct sk_buff *skb); static int sctp_wait_for_sndbuf(struct sctp_association *, long *timeo_p, size_t msg_len); @@ -95,7 +93,8 @@ static int sctp_wait_for_packet(struct s static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p); static int sctp_wait_for_accept(struct sock *sk, long timeo); static void sctp_wait_for_close(struct sock *sk, long timeo); -static inline int sctp_verify_addr(struct sock *, union sctp_addr *, int); +static struct sctp_af *sctp_sockaddr_af(struct sctp_opt *opt, + union sctp_addr *addr, int len); static int sctp_bindx_add(struct sock *, struct sockaddr *, int); static int sctp_bindx_rem(struct sock *, struct sockaddr *, int); static int sctp_send_asconf_add_ip(struct sock *, struct sockaddr *, int); @@ -111,6 +110,64 @@ static char *sctp_hmac_alg = SCTP_COOKIE extern kmem_cache_t *sctp_bucket_cachep; extern int sctp_assoc_valid(struct sock *sk, struct sctp_association *asoc); +/* Get the sndbuf space available at the time on the association. */ +static inline int sctp_wspace(struct sctp_association *asoc) +{ + struct sock *sk = asoc->base.sk; + int amt = 0; + + amt = sk->sk_sndbuf - asoc->sndbuf_used; + if (amt < 0) + amt = 0; + return amt; +} + +/* Increment the used sndbuf space count of the corresponding association by + * the size of the outgoing data chunk. + * Also, set the skb destructor for sndbuf accounting later. + * + * Since it is always 1-1 between chunk and skb, and also a new skb is always + * allocated for chunk bundling in sctp_packet_transmit(), we can use the + * destructor in the data chunk skb for the purpose of the sndbuf space + * tracking. + */ +static inline void sctp_set_owner_w(struct sctp_chunk *chunk) +{ + struct sctp_association *asoc = chunk->asoc; + struct sock *sk = asoc->base.sk; + + /* The sndbuf space is tracked per association. */ + sctp_association_hold(asoc); + + chunk->skb->destructor = sctp_wfree; + /* Save the chunk pointer in skb for sctp_wfree to use later. */ + *((struct sctp_chunk **)(chunk->skb->cb)) = chunk; + + asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk); + sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk); +} + +/* Verify that this is a valid address. */ +static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr, + int len) +{ + struct sctp_af *af; + + /* Verify basic sockaddr. */ + af = sctp_sockaddr_af(sctp_sk(sk), addr, len); + if (!af) + return -EINVAL; + + /* Is this a valid SCTP address? */ + if (!af->addr_valid(addr, sctp_sk(sk))) + return -EINVAL; + + if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr))) + return -EINVAL; + + return 0; +} + /* Look up the association by its id. If this is not a UDP-style * socket, the ID field is always ignored. */ @@ -999,7 +1056,7 @@ SCTP_STATIC int sctp_sendmsg(struct sock struct sctp_sndrcvinfo *sinfo; struct sctp_initmsg *sinit; sctp_assoc_t associd = NULL; - sctp_cmsgs_t cmsgs = { 0 }; + sctp_cmsgs_t cmsgs = { NULL }; int err; sctp_scope_t scope; long timeo; @@ -1630,6 +1687,32 @@ static int sctp_setsockopt_peer_addr_par if (copy_from_user(¶ms, optval, optlen)) return -EFAULT; + /* + * API 7. Socket Options (setting the default value for the endpoint) + * All options that support specific settings on an association by + * filling in either an association id variable or a sockaddr_storage + * SHOULD also support setting of the same value for the entire endpoint + * (i.e. future associations). To accomplish this the following logic is + * used when setting one of these options: + + * c) If neither the sockaddr_storage or association identification is + * set i.e. the sockaddr_storage is set to all 0's (INADDR_ANY) and + * the association identification is 0, the settings are a default + * and to be applied to the endpoint (all future associations). + */ + + /* update default value for endpoint (all future associations) */ + if (!params.spp_assoc_id && + sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { + if (params.spp_hbinterval) + sctp_sk(sk)->paddrparam.spp_hbinterval = + params.spp_hbinterval; + if (sctp_max_retrans_path) + sctp_sk(sk)->paddrparam.spp_pathmaxrxt = + params.spp_pathmaxrxt; + return 0; + } + trans = sctp_addr_id2transport(sk, ¶ms.spp_address, params.spp_assoc_id); if (!trans) @@ -2795,6 +2878,17 @@ static int sctp_getsockopt_peer_addr_par if (copy_from_user(¶ms, optval, *optlen)) return -EFAULT; + /* If no association id is specified retrieve the default value + * for the endpoint that will be used for all future associations + */ + if (!params.spp_assoc_id && + sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { + params.spp_hbinterval = sctp_sk(sk)->paddrparam.spp_hbinterval; + params.spp_pathmaxrxt = sctp_sk(sk)->paddrparam.spp_pathmaxrxt; + + goto done; + } + trans = sctp_addr_id2transport(sk, ¶ms.spp_address, params.spp_assoc_id); if (!trans) @@ -2814,6 +2908,7 @@ static int sctp_getsockopt_peer_addr_par */ params.spp_pathmaxrxt = trans->error_threshold; +done: if (copy_to_user(optval, ¶ms, len)) return -EFAULT; @@ -4138,64 +4233,6 @@ no_packet: return NULL; } -/* Verify that this is a valid address. */ -static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr, - int len) -{ - struct sctp_af *af; - - /* Verify basic sockaddr. */ - af = sctp_sockaddr_af(sctp_sk(sk), addr, len); - if (!af) - return -EINVAL; - - /* Is this a valid SCTP address? */ - if (!af->addr_valid(addr, sctp_sk(sk))) - return -EINVAL; - - if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr))) - return -EINVAL; - - return 0; -} - -/* Get the sndbuf space available at the time on the association. */ -static inline int sctp_wspace(struct sctp_association *asoc) -{ - struct sock *sk = asoc->base.sk; - int amt = 0; - - amt = sk->sk_sndbuf - asoc->sndbuf_used; - if (amt < 0) - amt = 0; - return amt; -} - -/* Increment the used sndbuf space count of the corresponding association by - * the size of the outgoing data chunk. - * Also, set the skb destructor for sndbuf accounting later. - * - * Since it is always 1-1 between chunk and skb, and also a new skb is always - * allocated for chunk bundling in sctp_packet_transmit(), we can use the - * destructor in the data chunk skb for the purpose of the sndbuf space - * tracking. - */ -static inline void sctp_set_owner_w(struct sctp_chunk *chunk) -{ - struct sctp_association *asoc = chunk->asoc; - struct sock *sk = asoc->base.sk; - - /* The sndbuf space is tracked per association. */ - sctp_association_hold(asoc); - - chunk->skb->destructor = sctp_wfree; - /* Save the chunk pointer in skb for sctp_wfree to use later. */ - *((struct sctp_chunk **)(chunk->skb->cb)) = chunk; - - asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk); - sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk); -} - /* If sndbuf has changed, wake up per association sndbuf waiters. */ static void __sctp_write_space(struct sctp_association *asoc) { diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/ulpevent.c linux-2.4.28-pre3/net/sctp/ulpevent.c --- linux-2.4.27/net/sctp/ulpevent.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sctp/ulpevent.c 2004-09-10 19:35:54.000000000 +0000 @@ -48,13 +48,23 @@ #include #include -static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event, - const struct sctp_association *asoc); -static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event); static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, struct sctp_association *asoc); static void sctp_ulpevent_release_data(struct sctp_ulpevent *event); +/* Stub skb destructor. */ +static void sctp_stub_rfree(struct sk_buff *skb) +{ +/* WARNING: This function is just a warning not to use the + * skb destructor. If the skb is shared, we may get the destructor + * callback on some processor that does not own the sock_lock. This + * was occuring with PACKET socket applications that were monitoring + * our skbs. We can't take the sock_lock, because we can't risk + * recursing if we do really own the sock lock. Instead, do all + * of our rwnd manipulation while we own the sock_lock outright. + */ +} + /* Create a new sctp_ulpevent. */ struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp) { @@ -87,6 +97,30 @@ int sctp_ulpevent_is_notification(const return MSG_NOTIFICATION == (event->msg_flags & MSG_NOTIFICATION); } +/* Hold the association in case the msg_name needs read out of + * the association. + */ +static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event, + const struct sctp_association *asoc) +{ + struct sk_buff *skb; + + /* Cast away the const, as we are just wanting to + * bump the reference count. + */ + sctp_association_hold((struct sctp_association *)asoc); + skb = sctp_event2skb(event); + skb->sk = asoc->base.sk; + event->asoc = (struct sctp_association *)asoc; + skb->destructor = sctp_stub_rfree; +} + +/* A simple destructor to give up the reference to the association. */ +static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) +{ + sctp_association_put(event->asoc); +} + /* Create and initialize an SCTP_ASSOC_CHANGE event. * * 5.3.1.1 SCTP_ASSOC_CHANGE @@ -789,43 +823,6 @@ void sctp_ulpevent_read_sndrcvinfo(const sizeof(struct sctp_sndrcvinfo), (void *)&sinfo); } -/* Stub skb destructor. */ -static void sctp_stub_rfree(struct sk_buff *skb) -{ -/* WARNING: This function is just a warning not to use the - * skb destructor. If the skb is shared, we may get the destructor - * callback on some processor that does not own the sock_lock. This - * was occuring with PACKET socket applications that were monitoring - * our skbs. We can't take the sock_lock, because we can't risk - * recursing if we do really own the sock lock. Instead, do all - * of our rwnd manipulation while we own the sock_lock outright. - */ -} - -/* Hold the association in case the msg_name needs read out of - * the association. - */ -static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event, - const struct sctp_association *asoc) -{ - struct sk_buff *skb; - - /* Cast away the const, as we are just wanting to - * bump the reference count. - */ - sctp_association_hold((struct sctp_association *)asoc); - skb = sctp_event2skb(event); - skb->sk = asoc->base.sk; - event->asoc = (struct sctp_association *)asoc; - skb->destructor = sctp_stub_rfree; -} - -/* A simple destructor to give up the reference to the association. */ -static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) -{ - sctp_association_put(event->asoc); -} - /* Do accounting for bytes received and hold a reference to the association * for each skb. */ diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/ulpqueue.c linux-2.4.28-pre3/net/sctp/ulpqueue.c --- linux-2.4.27/net/sctp/ulpqueue.c 2004-08-07 23:26:07.000000000 +0000 +++ linux-2.4.28-pre3/net/sctp/ulpqueue.c 2004-09-10 19:31:49.000000000 +0000 @@ -49,10 +49,10 @@ #include /* Forward declarations for internal helpers. */ -static inline struct sctp_ulpevent * sctp_ulpq_reasm(struct sctp_ulpq *ulpq, - struct sctp_ulpevent *); -static inline struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *, - struct sctp_ulpevent *); +static struct sctp_ulpevent * sctp_ulpq_reasm(struct sctp_ulpq *ulpq, + struct sctp_ulpevent *); +static struct sctp_ulpevent * sctp_ulpq_order(struct sctp_ulpq *, + struct sctp_ulpevent *); /* 1st Level Abstractions */ @@ -97,12 +97,12 @@ void sctp_ulpq_flush(struct sctp_ulpq *u struct sk_buff *skb; struct sctp_ulpevent *event; - while ((skb = __skb_dequeue(&ulpq->lobby))) { + while ((skb = __skb_dequeue(&ulpq->lobby)) != NULL) { event = sctp_skb2event(skb); sctp_ulpevent_free(event); } - while ((skb = __skb_dequeue(&ulpq->reasm))) { + while ((skb = __skb_dequeue(&ulpq->reasm)) != NULL) { event = sctp_skb2event(skb); sctp_ulpevent_free(event); } @@ -466,8 +466,8 @@ done: /* Helper function to reassemble chunks. Hold chunks on the reasm queue that * need reassembling. */ -static inline struct sctp_ulpevent *sctp_ulpq_reasm(struct sctp_ulpq *ulpq, - struct sctp_ulpevent *event) +static struct sctp_ulpevent *sctp_ulpq_reasm(struct sctp_ulpq *ulpq, + struct sctp_ulpevent *event) { struct sctp_ulpevent *retval = NULL; @@ -645,8 +645,8 @@ static inline void sctp_ulpq_store_order } -static inline struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, - struct sctp_ulpevent *event) +static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, + struct sctp_ulpevent *event) { __u16 sid, ssn; struct sctp_stream *in; @@ -756,7 +756,7 @@ static __u16 sctp_ulpq_renege_order(stru tsnmap = &ulpq->asoc->peer.tsn_map; - while ((skb = __skb_dequeue_tail(&ulpq->lobby))) { + while ((skb = __skb_dequeue_tail(&ulpq->lobby)) != NULL) { freed += skb_headlen(skb); event = sctp_skb2event(skb); tsn = event->tsn; @@ -782,7 +782,7 @@ static __u16 sctp_ulpq_renege_frags(stru tsnmap = &ulpq->asoc->peer.tsn_map; /* Walk backwards through the list, reneges the newest tsns. */ - while ((skb = __skb_dequeue_tail(&ulpq->reasm))) { + while ((skb = __skb_dequeue_tail(&ulpq->reasm)) != NULL) { freed += skb_headlen(skb); event = sctp_skb2event(skb); tsn = event->tsn; diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sunrpc/xprt.c linux-2.4.28-pre3/net/sunrpc/xprt.c --- linux-2.4.27/net/sunrpc/xprt.c 2003-11-28 18:26:21.000000000 +0000 +++ linux-2.4.28-pre3/net/sunrpc/xprt.c 2004-09-10 19:35:48.000000000 +0000 @@ -1244,19 +1244,6 @@ do_xprt_transmit(struct rpc_task *task) /* * Reserve an RPC call slot. */ -void -xprt_reserve(struct rpc_task *task) -{ - struct rpc_xprt *xprt = task->tk_xprt; - - task->tk_status = -EIO; - if (!xprt->shutdown) { - spin_lock(&xprt->xprt_lock); - do_xprt_reserve(task); - spin_unlock(&xprt->xprt_lock); - } -} - static inline void do_xprt_reserve(struct rpc_task *task) { @@ -1279,6 +1266,19 @@ do_xprt_reserve(struct rpc_task *task) rpc_sleep_on(&xprt->backlog, task, NULL, NULL); } +void +xprt_reserve(struct rpc_task *task) +{ + struct rpc_xprt *xprt = task->tk_xprt; + + task->tk_status = -EIO; + if (!xprt->shutdown) { + spin_lock(&xprt->xprt_lock); + do_xprt_reserve(task); + spin_unlock(&xprt->xprt_lock); + } +} + /* * Allocate a 'unique' XID */