]> git.neil.brown.name Git - history.git/commitdiff
Ok, there's a test13-pre6 out there now, which does a partial sync with 2.4.0-test13pre6
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:41:06 +0000 (15:41 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:41:06 +0000 (15:41 -0500)
Alan, in addition to hopefully fixing the innd shared mapping writeback
problem for good.  Thanks to Marcelo Tosatti and others..

I've pounded on the shared dirty page writeback logic quite a bit, and
verified (by doing timings with "strace -ttT") that it should do the right
thing with sync/fsync/fdatasync/msync(MS_ASYNC)/msync(MS_SYNC).

The reason I'm fairly confident that the problem is gone for good is that
the dirty page handling is now quite integral to the whole address space
code, and it fell out rather nicely from some mapping host cleanups.

Al: this changes "mapping->host" to be truly defined as a pointer to the
inode that owns the mapping. That's how every user actually _used_ the
host pointer, so this cleans those up to not need any casts. The main
reason, however, is that we needed to have some FS-level anchor for dirty
pages in order to get the correct sync() semantics. If you think it's
worth it to have a notion of an anonymous host we need to add something
else.

Stephen: mind trying your fsync/etc tests on this one, to verify that the
inode dirty stuff is all done right?

Marco d'Itri and everybody else who has seen innd problems (or other
shared map problems): can you verify that test13-pre6 works for you?

Linus

- Marc Joosen: BIOS int15/e820 memory query: don't assume %edx
  unchanged by the BIOS. Fixes at least some IBM ThinkPads.
- Alan Cox: synchronize
- Marcelo Tosatti & me: properly sync dirty pages
- Andreas Dilger: proper ext2 compat flag checking

157 files changed:
CREDITS
Documentation/Changes
Documentation/i2c/functionality [new file with mode: 0644]
Documentation/modules.txt
Documentation/sound/ALS
Makefile
arch/i386/boot/setup.S
arch/i386/config.in
arch/i386/kernel/Makefile
arch/i386/kernel/smp.c
arch/i386/kernel/time.c
drivers/acpi/include/aclinux.h
drivers/acpi/ksyms.c
drivers/atm/Config.in
drivers/atm/ambassador.c
drivers/atm/atmdev_init.c
drivers/atm/atmtcp.c
drivers/atm/firestream.c [new file with mode: 0644]
drivers/atm/firestream.h [new file with mode: 0644]
drivers/atm/fore200e.c
drivers/atm/horizon.c
drivers/atm/iphase.c
drivers/atm/nicstar.c
drivers/char/generic_serial.c
drivers/char/i810-tco.c
drivers/char/pcxx.c
drivers/char/sh-sci.c
drivers/char/sx.c
drivers/i2c/i2c-algo-pcf.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/isdn/Config.in
drivers/isdn/Makefile
drivers/isdn/act2000/Makefile
drivers/isdn/avmb1/Makefile
drivers/isdn/divert/Makefile
drivers/isdn/eicon/Makefile
drivers/isdn/hisax/Makefile
drivers/isdn/hysdn/Makefile
drivers/isdn/icn/Makefile
drivers/isdn/isdn_cards.c
drivers/isdn/isdn_common.c
drivers/isdn/isdnloop/Makefile
drivers/isdn/pcbit/Makefile
drivers/isdn/sc/Makefile
drivers/net/8139too.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/mkiss.c
drivers/net/hamradio/yam.c
drivers/pcmcia/cs.c
drivers/scsi/aha152x.c
drivers/scsi/pci2000.c
drivers/scsi/pci2220i.c
drivers/scsi/sim710.c
drivers/sound/cmpci.c
drivers/sound/cs4281.c
drivers/sound/es1370.c
drivers/sound/es1371.c
drivers/sound/esssolo1.c
drivers/sound/maestro.c
drivers/sound/sonicvibes.c
drivers/sound/trident.c
drivers/telephony/ixj.c
drivers/telephony/ixj.h
fs/adfs/inode.c
fs/affs/file.c
fs/affs/symlink.c
fs/buffer.c
fs/coda/dir.c
fs/coda/file.c
fs/coda/inode.c
fs/coda/symlink.c
fs/cramfs/inode.c
fs/efs/symlink.c
fs/ext2/balloc.c
fs/ext2/inode.c
fs/ext2/super.c
fs/fat/inode.c
fs/hfs/inode.c
fs/hpfs/file.c
fs/hpfs/namei.c
fs/inode.c
fs/isofs/rock.c
fs/jffs/inode-v23.c
fs/lockd/xdr4.c
fs/ncpfs/symlink.c
fs/nfs/file.c
fs/nfs/read.c
fs/nfs/write.c
fs/nls/Config.in
fs/ntfs/fs.c
fs/qnx4/inode.c
fs/ramfs/inode.c
fs/romfs/inode.c
fs/smbfs/file.c
fs/udf/file.c
fs/udf/symlink.c
include/linux/atm_tcp.h
include/linux/atmdev.h
include/linux/ext2_fs.h
include/linux/ext2_fs_sb.h
include/linux/fs.h
include/linux/generic_serial.h
include/linux/i2c-dev.h
include/linux/i2c-id.h
include/linux/i2c.h
include/linux/lvm.h
include/linux/mm.h
include/net/ax25.h
ipc/shm.c
mm/filemap.c
mm/memory.c
mm/shmem.c
mm/swap_state.c
mm/vmscan.c
net/atm/addr.c
net/atm/common.c
net/atm/lec.c
net/atm/proc.c
net/atm/resources.c
net/atm/signaling.c
net/ax25/af_ax25.c
net/ax25/ax25_addr.c
net/ax25/ax25_dev.c
net/ax25/ax25_ds_in.c
net/ax25/ax25_ds_subr.c
net/ax25/ax25_ds_timer.c
net/ax25/ax25_iface.c
net/ax25/ax25_in.c
net/ax25/ax25_ip.c
net/ax25/ax25_out.c
net/ax25/ax25_route.c
net/ax25/ax25_std_in.c
net/ax25/ax25_std_subr.c
net/ax25/ax25_std_timer.c
net/ax25/ax25_subr.c
net/ax25/ax25_timer.c
net/ax25/ax25_uid.c
net/ipv4/ipconfig.c
net/netrom/af_netrom.c
net/netrom/nr_dev.c
net/netrom/nr_in.c
net/netrom/nr_loopback.c
net/netrom/nr_out.c
net/netrom/nr_route.c
net/netrom/nr_subr.c
net/netrom/nr_timer.c
net/rose/af_rose.c
net/rose/rose_dev.c
net/rose/rose_in.c
net/rose/rose_link.c
net/rose/rose_loopback.c
net/rose/rose_out.c
net/rose/rose_route.c
net/rose/rose_subr.c
net/rose/rose_timer.c
scripts/kernel-doc

diff --git a/CREDITS b/CREDITS
index b2e00bf576fe4620a5f93df99840f720a7384c5e..580bc44bab58e6e1587b58928be235b8ba473d79 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -948,6 +948,14 @@ S: University of California, Riverside
 S: Riverside, California 92521-0304
 S: USA
 
+N: Hans Grobler
+E: grobh@sun.ac.za
+D: Various AX.25/ROSE/NETROM + hamradio driver patches
+S: Department of Electronic Engineering
+S: University of Stellenbosch
+S: Stellenbosch, Western Cape
+S: South Africa
+
 N: Grant Guenther
 E: grant@torque.net
 W: http://www.torque.net/linux-pp.html
index a8a568c5de3bdac13e2b2ebb6f3c32e797935277..4c0881fff9d1dfeb7f3b3b5cf008137fcb642690 100644 (file)
@@ -31,7 +31,7 @@ al espa
 Eine deutsche Version dieser Datei finden Sie unter
 <http://www.stefan-winter.de/Changes-2.4.0.txt>.
 
-Last updated: October 25, 2000
+Last updated: December 11, 2000
 
 Chris Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu).
 
@@ -52,7 +52,7 @@ o  Gnu C                  2.91.66                 # gcc --version
 o  Gnu make               3.77                    # make --version
 o  binutils               2.9.1.0.25              # ld -v
 o  util-linux             2.10o                   # fdformat --version
-o  modutils               2.3.18                  # insmod -V
+o  modutils               2.3.21                  # insmod -V
 o  e2fsprogs              1.19                    # tune2fs --version
 o  pcmcia-cs              3.1.21                  # cardmgr -V
 o  PPP                    2.4.0                   # pppd --version
@@ -291,7 +291,7 @@ o  <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.3>
 
 Modutils
 --------
-o  <ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.3/modutils-2.3.18.tar.bz2>
+o  <ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.3/modutils-2.3.21.tar.bz2>
 
 Mkinitrd
 --------
diff --git a/Documentation/i2c/functionality b/Documentation/i2c/functionality
new file mode 100644 (file)
index 0000000..8a78a95
--- /dev/null
@@ -0,0 +1,135 @@
+INTRODUCTION
+------------
+
+Because not every I2C or SMBus adapter implements everything in the 
+I2C specifications, a client can not trust that everything it needs
+is implemented when it is given the option to attach to an adapter:
+the client needs some way to check whether an adapter has the needed
+functionality. 
+
+
+FUNCTIONALITY CONSTANTS
+-----------------------
+
+For the most up-to-date list of functionality constants, please check
+<linux/i2c.h>!
+
+  I2C_FUNC_I2C                    Plain i2c-level commands (Pure SMBus
+                                  adapters typically can not do these)
+  I2C_FUNC_10BIT_ADDR             Handles the 10-bit address extensions
+  I2C_FUNC_PROTOCOL_MANGLING      Knows about the I2C_M_REV_DIR_ADDR,
+                                  I2C_M_REV_DIR_ADDR and I2C_M_REV_DIR_NOSTART
+                                  flags (which modify the i2c protocol!)
+  I2C_FUNC_SMBUS_QUICK            Handles the SMBus write_quick command
+  I2C_FUNC_SMBUS_READ_BYTE        Handles the SMBus read_byte command
+  I2C_FUNC_SMBUS_WRITE_BYTE       Handles the SMBus write_byte command
+  I2C_FUNC_SMBUS_READ_BYTE_DATA   Handles the SMBus read_byte_data command
+  I2C_FUNC_SMBUS_WRITE_BYTE_DATA  Handles the SMBus write_byte_data command
+  I2C_FUNC_SMBUS_READ_WORD_DATA   Handles the SMBus read_word_data command
+  I2C_FUNC_SMBUS_WRITE_WORD_DATA  Handles the SMBus write_byte_data command
+  I2C_FUNC_SMBUS_PROC_CALL        Handles the SMBus process_call command
+  I2C_FUNC_SMBUS_READ_BLOCK_DATA  Handles the SMBus read_block_data command
+  I2C_FUNC_SMBUS_WRITE_BLOCK_DATA Handles the SMBus write_block_data command
+  I2C_FUNC_SMBUS_READ_I2C_BLOCK   Handles the SMBus read_i2c_block_data command
+  I2C_FUNC_SMBUS_WRITE_I2C_BLOCK  Handles the SMBus write_i2c_block_data command
+
+A few combinations of the above flags are also defined for your convenience:
+
+  I2C_FUNC_SMBUS_BYTE             Handles the SMBus read_byte
+                                  and write_byte commands
+  I2C_FUNC_SMBUS_BYTE_DATA        Handles the SMBus read_byte_data
+                                  and write_byte_data commands
+  I2C_FUNC_SMBUS_WORD_DATA        Handles the SMBus read_word_data
+                                  and write_word_data commands
+  I2C_FUNC_SMBUS_BLOCK_DATA       Handles the SMBus read_block_data
+                                  and write_block_data commands
+  I2C_FUNC_SMBUS_I2C_BLOCK        Handles the SMBus read_i2c_block_data
+                                  and write_i2c_block_data commands
+  I2C_FUNC_SMBUS_EMUL             Handles all SMBus commands than can be
+                                  emulated by a real I2C adapter (using
+                                  the transparent emulation layer)
+
+
+ALGORITHM/ADAPTER IMPLEMENTATION
+--------------------------------
+
+When you write a new algorithm driver, you will have to implement a
+function callback `functionality', that gets an i2c_adapter structure
+pointer as its only parameter:
+
+  struct i2c_algorithm {
+       /* Many other things of course; check <linux/i2c.h>! */
+       u32 (*functionality) (struct i2c_adapter *);
+  }
+
+A typically implementation is given below, from i2c-algo-bit.c:
+
+  static u32 bit_func(struct i2c_adapter *adap)
+  {
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | 
+              I2C_FUNC_PROTOCOL_MANGLING;
+  }
+
+
+
+CLIENT CHECKING
+---------------
+
+Before a client tries to attach to an adapter, or even do tests to check
+whether one of the devices it supports is present on an adapter, it should
+check whether the needed functionality is present. There are two functions
+defined which should be used instead of calling the functionality hook
+in the algorithm structure directly:
+
+  /* Return the functionality mask */
+  extern u32 i2c_get_functionality (struct i2c_adapter *adap);
+
+  /* Return 1 if adapter supports everything we need, 0 if not. */
+  extern int i2c_check_functionality (struct i2c_adapter *adap, u32 func);
+
+This is a typical way to use these functions (from the writing-clients
+document):
+  int foo_detect_client(struct i2c_adapter *adapter, int address, 
+                          unsigned short flags, int kind)
+  {
+       /* Define needed variables */
+
+       /* As the very first action, we check whether the adapter has the
+          needed functionality: we need the SMBus read_word_data,
+           write_word_data and write_byte functions in this example. */
+       if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
+                                            I2C_FUNC_SMBUS_WRITE_BYTE))
+               goto ERROR0;
+
+       /* Now we can do the real detection */
+
+       ERROR0:
+               /* Return an error */
+  }
+
+
+
+CHECKING THROUGH /DEV
+---------------------
+
+If you try to access an adapter from a userspace program, you will have
+to use the /dev interface. You will still have to check whether the
+functionality you need is supported, of course. This is done using
+the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2c_detect
+program, is below:
+
+  int file;
+  if (file = open("/dev/i2c-0",O_RDWR) < 0) {
+       /* Some kind of error handling */
+       exit(1);
+  }
+  if (ioctl(file,I2C_FUNCS,&funcs) < 0) {
+       /* Some kind of error handling */
+       exit(1);
+  }
+  if (! (funcs & I2C_FUNC_SMBUS_QUICK)) {
+       /* Oops, the needed functionality (SMBus write_quick function) is
+           not available! */
+       exit(1);
+  }
+  /* Now it is safe to use the SMBus write_quick command */
index e7e371945222f015752911e25cd869729cc5054e..885a4d6afdb60c5cbb47566022df04724c3dc1c5 100644 (file)
@@ -124,7 +124,7 @@ And, yes, there _are_ man-pages for all this...
 
 To use modprobe successfully, you generally place the following
 command in your /etc/rc.d/rc.S script.  (Read more about this in the
-"rc.hints" file in the module utilities package, "modules-x.y.z.tar.gz".)
+"rc.hints" file in the module utilities package, "modutils-x.y.z.tar.gz".)
 
        /sbin/depmod -a
 
index c5e55d5b76be48d155e86666a4f96b5e915bfdc2..d01ffbfd58080943378e685cc026d341eb0fd25f 100644 (file)
@@ -9,25 +9,42 @@ the mixer registers.  For this reason the ALS code is integrated
 as part of the Sound Blaster 16 driver (adding only 800 bytes to the
 SB16 driver).
 
-To use an ALS sound card under Linux, enable the following options in the
-sound configuration section of the kernel config:
+To use an ALS sound card under Linux, enable the following options as
+modules in the sound configuration section of the kernel config:
   - 100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support
   - FM synthesizer (YM3812/OPL-3) support 
+  - standalone MPU401 support may be required for some cards; for the
+    ALS-007, when using isapnptools, it is required
 Since the ALS-007/100/200 are PnP cards, ISAPnP support should probably be
-compiled in.
+compiled in.  If kernel level PnP support is not included, isapnptools will
+be required to configure the card before the sound modules are loaded.
 
-Alternatively, if you decide not to use kernel level ISAPnP, you can use the
-user mode isapnptools to wake up the sound card, as in 2.2.X. Set the "I/O 
-base for SB", "Sound Blaster IRQ" and "Sound Blaster DMA" (8 bit -
-either 0, 1 or 3) to the values used in your particular installation (they
-should match the values used to configure the card using isapnp).  The
-ALS-007 does NOT implement 16 bit DMA, so the "Sound Blaster 16 bit DMA"
-should be set to -1.  If you wish to use the external MPU-401 interface on
-the card, "MPU401 I/O base of SB16" and "SB MPU401 IRQ" should be set to
-the appropriate values for your installation.  (Note that the ALS-007
-requires a separate IRQ for the MPU-401, so don't specify -1 here).  (Note
-that the base port of the internal FM synth is fixed at 0x388 on the ALS007; 
-in any case the FM synth location cannot be set in the kernel configuration).
+When using kernel level ISAPnP, the kernel should correctly identify and
+configure all resources required by the card when the "sb" module is
+inserted.  Note that the ALS-007 does not have a 16 bit DMA channel and that
+the MPU401 interface on this card uses a different interrupt to the audio
+section.  This should all be correctly configured by the kernel; if problems
+with the MPU401 interface surface, try using the standalone MPU401 module,
+passing "0" as the "sb" module's "mpu_io" module parameter to prevent the
+soundblaster driver attempting to register the MPU401 itself.  The onboard
+synth device can be accessed using the "opl3" module.
+
+If isapnptools is used to wake up the sound card (as in 2.2.x), the settings
+of the card's resources should be passed to the kernel modules ("sb", "opl3"
+and "mpu401") using the module parameters.  When configuring an ALS-007, be
+sure to specify different IRQs for the audio and MPU401 sections - this card
+requires they be different.  For "sb", "io", "irq" and "dma" should be set
+to the same values used to configure the audio section of the card with
+isapnp.  "dma16" should be explicitly set to "-1" for an ALS-007 since this
+card does not have a 16 bit dma channel; if not specified the kernel will
+default to using channel 5 anyway which will cause audio not to work. 
+"mpu_io" should be set to 0.  The "io" parameter of the "opl3" module should
+also agree with the setting used by isapnp.  To get the MPU401 interface
+working on an ALS-007 card, the "mpu401" module will be required since this
+card uses separate IRQs for the audio and MPU401 sections and there is no
+parameter available to pass a different IRQ to the "sb" driver (whose
+inbuilt MPU401 driver would otherwise be fine).  Insert the mpu401 module
+passing appropriate values using the "io" and "irq" parameters.
 
 The resulting sound driver will provide the following capabilities:
   - 8 and 16 bit audio playback
@@ -45,3 +62,5 @@ jwoithe@physics.adelaide.edu.au
 
 Modified 2000-02-26 by Dave Forrest, drf5n@virginia.edu to add ALS100/ALS200
 Modified 2000-04-10 by Paul Laufer, pelaufer@csupomona.edu to add ISAPnP info.
+Modified 2000-11-19 by Jonathan Woithe, jwoithe@physics.adelaide.edu.au
+ - updated information for kernel 2.4.x.
index 28778a009e9ade8a15db8afb2a90a942ce467f77..1308977149a2cd53163bd23841ae6580511ce4f0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 0
-EXTRAVERSION = -test13-pre5
+EXTRAVERSION = -test13-pre6
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
index c52b170ecdcaebe2e0ff0ef6d165659bf39e724a..adbbcc3c64b2b4b7fc7daec2d10abd5784b46bf8 100644 (file)
@@ -289,10 +289,11 @@ loader_ok:
 # a whole bunch of different types, and allows memory holes and
 # everything.  We scan through this memory map and build a list
 # of the first 32 memory areas, which we return at [E820MAP].
-#
+# This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm
+
+#define SMAP  0x534d4150
 
 meme820:
-       movl    $0x534d4150, %edx               # ascii `SMAP'
        xorl    %ebx, %ebx                      # continuation counter
        movw    $E820MAP, %di                   # point into the whitelist
                                                # so we can have the bios
@@ -300,13 +301,14 @@ meme820:
 
 jmpe820:
        movl    $0x0000e820, %eax               # e820, upper word zeroed
+       movl    $SMAP, %edx                     # ascii 'SMAP'
        movl    $20, %ecx                       # size of the e820rec
        pushw   %ds                             # data record.
        popw    %es
        int     $0x15                           # make the call
        jc      bail820                         # fall to e801 if it fails
 
-       cmpl    $0x534d4150, %eax               # check the return is `SMAP'
+       cmpl    $SMAP, %eax                     # check the return is `SMAP'
        jne     bail820                         # fall to e801 if it fails
 
 #      cmpl    $1, 16(%di)                     # is this usable memory?
index ecbb22b340fd1173f72b2d11b7535a3fc253de00..4dc863995d3be09c05208c43630e19a03f1adbf0 100644 (file)
@@ -44,6 +44,9 @@ choice 'Processor family' \
 #
 # Define implied options from the CPU selection here
 #
+
+unset CONFIG_X86_FXSR
+
 if [ "$CONFIG_M386" = "y" ]; then
    define_bool CONFIG_X86_CMPXCHG n
    define_int  CONFIG_X86_L1_CACHE_SHIFT 4
@@ -136,7 +139,6 @@ if [ "$CONFIG_MWINCHIP3D" = "y" ]; then
    define_bool CONFIG_X86_ALIGNMENT_16 y
    define_bool CONFIG_X86_TSC y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
-   define_bool CONFIG_X86_USE_3DNOW y
 fi
 tristate 'Toshiba Laptop support' CONFIG_TOSHIBA
 
@@ -162,15 +164,15 @@ fi
 bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
 bool 'Symmetric multi-processing support' CONFIG_SMP
 if [ "$CONFIG_SMP" != "y" ]; then
-    bool 'APIC and IO-APIC support on uniprocessors' CONFIG_X86_UP_IOAPIC
-    if [ "$CONFIG_X86_UP_IOAPIC" = "y" ]; then
-       define_bool CONFIG_X86_IO_APIC y
-       define_bool CONFIG_X86_LOCAL_APIC y
-    fi
+   bool 'APIC and IO-APIC support on uniprocessors' CONFIG_X86_UP_IOAPIC
+   if [ "$CONFIG_X86_UP_IOAPIC" = "y" ]; then
+      define_bool CONFIG_X86_IO_APIC y
+      define_bool CONFIG_X86_LOCAL_APIC y
+   fi
 fi
 
 if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
-    define_bool CONFIG_HAVE_DEC_LOCK y
+   define_bool CONFIG_HAVE_DEC_LOCK y
 fi
 endmenu
 
@@ -274,10 +276,10 @@ comment 'ATA/IDE/MFM/RLL support'
 tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
 
 if [ "$CONFIG_IDE" != "n" ]; then
-  source drivers/ide/Config.in
+   source drivers/ide/Config.in
 else
-  define_bool CONFIG_BLK_DEV_IDE_MODES n
-  define_bool CONFIG_BLK_DEV_HD n
+   define_bool CONFIG_BLK_DEV_IDE_MODES n
+   define_bool CONFIG_BLK_DEV_HD n
 fi
 endmenu
 
index 6e7535a70abd9bfb39363cedd839f2e297a12ad3..67872949d8d7deded644709d2dbf06f375dd1237 100644 (file)
@@ -18,7 +18,7 @@ export-objs     := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o
 
 obj-y  := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
                ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
-               pci-dma.o i386_ksyms.o i387.o bluesmoke.o
+               pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o
 
 
 ifdef CONFIG_PCI
index f39e42522fd6739f1f55cfc251c48971c813495f..6607edf8a20d02d1f55a7f3f36976a8b94e71f72 100644 (file)
@@ -278,7 +278,16 @@ asmlinkage void smp_invalidate_interrupt (void)
        unsigned long cpu = smp_processor_id();
 
        if (!test_bit(cpu, &flush_cpumask))
-               BUG();
+               return;
+               /* 
+                * This was a BUG() but until someone can quote me the
+                * line from the intel manual that guarantees an IPI to
+                * multiple CPUs is retried _only_ on the erroring CPUs
+                * its staying as a return
+                *
+                * BUG();
+                */
+                
        if (flush_mm == cpu_tlbstate[cpu].active_mm) {
                if (cpu_tlbstate[cpu].state == TLBSTATE_OK) {
                        if (flush_va == FLUSH_ALL)
index 12ba21b926a7cd4373e107b669dee46431448c76..c7672ceed5b1caa5ff9c8c81d297b6c406246fa9 100644 (file)
@@ -105,7 +105,7 @@ static inline unsigned long do_fast_gettimeoffset(void)
 
        __asm__("mull %2"
                :"=a" (eax), "=d" (edx)
-               :"g" (fast_gettimeoffset_quotient),
+               :"rm" (fast_gettimeoffset_quotient),
                 "0" (eax));
 
        /* our adjusted time offset in microseconds */
index 7b54076548291b140c1e3a322a8d73b18def3019..673d5f96b34dff2b128da0d1d91e3caab7516985 100644 (file)
@@ -29,7 +29,6 @@
 
 #define ACPI_OS_NAME                "Linux"
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/ctype.h>
index cb4c5a4b92a5330985b2925080046f7748fba6d2..13f4fe0e78fc18dcf50303e9671dc9350f662ea8 100644 (file)
@@ -18,7 +18,6 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
index b04a354bc14007ad54e9e26dc78022fc334e736a..2f82a75e8d601d64a270a204301da862676ebfb7 100644 (file)
@@ -22,6 +22,7 @@ if [ "$CONFIG_PCI" = "y" ]; then
         bool '    Enable 2W RX bursts (optional)' CONFIG_ATM_ENI_BURST_RX_2W
       fi
    fi
+   tristate 'Fujitsu FireStream (FS50/FS155) ' CONFIG_ATM_FIRESTREAM
    tristate 'ZeitNet ZN1221/ZN1225' CONFIG_ATM_ZATM
    if [ "$CONFIG_ATM_ZATM" != "n" ]; then
       bool '  Enable extended debugging' CONFIG_ATM_ZATM_DEBUG
index 8a24cfb66f662f370a69b4c5f8d27ac15838df1d..3de74d517115fa8a1a0ae3301af80bf9b01f65fd 100644 (file)
@@ -1251,15 +1251,10 @@ static int amb_open (struct atm_vcc * atm_vcc, short vpi, int vci) {
     }
   }
   
-  // prevent module unload while sleeping (kmalloc/down)
-  // doing this any earlier would complicate more error return paths
-  MOD_INC_USE_COUNT;
-  
   // get space for our vcc stuff
   vcc = kmalloc (sizeof(amb_vcc), GFP_KERNEL);
   if (!vcc) {
     PRINTK (KERN_ERR, "out of memory!");
-    MOD_DEC_USE_COUNT;
     return -ENOMEM;
   }
   atm_vcc->dev_data = (void *) vcc;
@@ -1425,7 +1420,6 @@ static void amb_close (struct atm_vcc * atm_vcc) {
   // say the VPI/VCI is free again
   clear_bit(ATM_VF_ADDR,&atm_vcc->flags);
 
-  MOD_DEC_USE_COUNT;
   return;
 }
 
@@ -1703,7 +1697,8 @@ static const struct atmdev_ops amb_ops = {
   close:       amb_close,
   send:                amb_send,
   sg_send:     amb_sg_send,
-  proc_read:   amb_proc_read
+  proc_read:   amb_proc_read,
+  owner:       THIS_MODULE,
 };
 
 /********** housekeeping **********/
index 73c785fe05faa0619a1117f55fdc918dbec34ff4..14f6df5326701224ec3850c9c23faa6632778082 100644 (file)
@@ -54,7 +54,7 @@ int __init atmdev_init(void)
        devs += ia_detect();
 #endif
 #ifdef CONFIG_ATM_FORE200E
-        devs += fore200e_detect();
+       devs += fore200e_detect();
 #endif
        return devs;
 }
index 9c4f2e7f3c987f280c2e0b908ef7024e62040603..17f607a73eadf94749897f7899d7c08cafdab46a 100644 (file)
@@ -110,7 +110,7 @@ static int atmtcp_recv_control(const struct atmtcp_control *msg)
 
 static void atmtcp_v_dev_close(struct atm_dev *dev)
 {
-       MOD_DEC_USE_COUNT;
+       /* Nothing.... Isn't this simple :-)  -- REW */
 }
 
 
@@ -298,7 +298,8 @@ static struct atmdev_ops atmtcp_v_dev_ops = {
        close:          atmtcp_v_close,
        ioctl:          atmtcp_v_ioctl,
        send:           atmtcp_v_send,
-       proc_read:      atmtcp_v_proc
+       proc_read:      atmtcp_v_proc,
+       owner:          THIS_MODULE
 };
 
 
@@ -331,18 +332,13 @@ static int atmtcp_create(int itf,int persist,struct atm_dev **result)
        struct atmtcp_dev_data *dev_data;
        struct atm_dev *dev;
 
-       MOD_INC_USE_COUNT;
-
        dev_data = kmalloc(sizeof(*dev_data),GFP_KERNEL);
-       if (!dev_data) {
-               MOD_DEC_USE_COUNT;
+       if (!dev_data)
                return -ENOMEM;
-       }
 
        dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL);
        if (!dev) {
                kfree(dev_data);
-               MOD_DEC_USE_COUNT;
                return itf == -1 ? -ENOMEM : -EBUSY;
        }
        dev->ci_range.vpi_bits = MAX_VPI_BITS;
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
new file mode 100644 (file)
index 0000000..7671afd
--- /dev/null
@@ -0,0 +1,2088 @@
+
+/* drivers/atm/firestream.c - FireStream 155 (MB86697) and
+ *                            FireStream  50 (MB86695) device driver 
+ */
+/* Written & (C) 2000 by R.E.Wolff@BitWizard.nl 
+ * Copied snippets from zatm.c by Werner Almesberger, EPFL LRC/ICA 
+ * and ambassador.c Copyright (C) 1995-1999  Madge Networks Ltd 
+ */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  The GNU GPL is contained in /usr/doc/copyright/GPL on a Debian
+  system and in the file COPYING in the Linux kernel source.
+*/
+
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/atm.h>
+#include <linux/atmdev.h>
+#include <linux/sonet.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/ioport.h> /* for request_region */
+#include <linux/uio.h>
+#include <linux/init.h>
+#include <linux/capability.h>
+#include <linux/bitops.h>
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+#include <linux/wait.h>
+
+#include "firestream.h"
+
+static int loopback = 0;
+static int num=0x5a;
+
+/* According to measurements (but they look suspicious to me!) done in
+ * '97, 37% of the packets are one cell in size. So it pays to have
+ * buffers allocated at that size. A large jump in percentage of
+ * packets occurs at packets around 536 bytes in length. So it also
+ * pays to have those pre-allocated. Unfortunately, we can't fully
+ * take advantage of this as the majority of the packets is likely to
+ * be TCP/IP (As where obviously the measurement comes from) There the
+ * link would be opened with say a 1500 byte MTU, and we can't handle
+ * smaller buffers more efficiently than the larger ones. -- REW
+ */
+
+/* Due to the way Linux memory management works, specifying "576" as
+ * an allocation size here isn't going to help. They are allocated
+ * from 1024-byte regions anyway. With the size of the sk_buffs (quite
+ * large), it doesn't pay to allocate the smallest size (64) -- REW */
+
+/* This is all guesswork. Hard numbers to back this up or disprove this, 
+ * are appreciated. -- REW */
+
+/* The last entry should be about 64k. However, the "buffer size" is
+ * passed to the chip in a 16 bit field. I don't know how "65536"
+ * would be interpreted. -- REW */
+
+#define NP FS_NR_FREE_POOLS
+int rx_buf_sizes[NP]  = {128,  256,  512, 1024, 2048, 4096, 16384, 65520};
+/* log2:                 7     8     9    10    11    12    14     16 */
+
+#if 0
+int rx_pool_sizes[NP] = {1024, 1024, 512, 256,  128,  64,   32,    32};
+#else
+/* debug */
+int rx_pool_sizes[NP] = {128,  128,  128, 64,   64,   64,   32,    32};
+#endif
+/* log2:                 10    10    9    8     7     6     5      5  */
+/* sumlog2:              17    18    18   18    18    18    19     21 */
+/* mem allocated:        128k  256k  256k 256k  256k  256k  512k   2M */
+/* tot mem: almost 4M */
+
+/* NP is shorter, so that it fits on a single line. */
+#undef NP
+
+
+/* Small hardware gotcha:
+
+   The FS50 CAM (VP/VC match registers) always take the lowest channel
+   number that matches. This is not a problem.
+
+   However, they also ignore wether the channel is enabled or
+   not. This means that if you allocate channel 0 to 1.2 and then
+   channel 1 to 0.0, then disabeling channel 0 and writing 0 to the
+   match channel for channel 0 will "steal" the traffic from channel
+   1, even if you correctly disable channel 0.
+
+   Workaround: 
+
+   - When disabling channels, write an invalid VP/VC value to the
+   match register. (We use 0xffffffff, which in the worst case 
+   matches VP/VC = <maxVP>/<maxVC>, but I expect it not to match
+   anything as some "when not in use, program to 0" bits are now
+   programmed to 1...)
+
+   - Don't initialize the match registers to 0, as 0.0 is a valid
+   channel.
+*/
+
+
+/* Optimization hints and tips.
+
+   The FireStream chips are very capable of reducing the amount of
+   "interrupt-traffic" for the CPU. This driver requests an interrupt on EVERY
+   action. You could try to minimize this a bit. 
+
+   Besides that, the userspace->kernel copy and the PCI bus are the
+   performance limiting issues for this driver.
+
+   You could queue up a bunch of outgoing packets without telling the
+   FireStream. I'm not sure that's going to win you much though. The
+   Linux layer won't tell us in advance when it's not going to give us
+   any more packets in a while. So this is tricky to implement right without
+   introducing extra delays. 
+  
+   -- REW
+ */
+
+
+
+
+/* The strings that define what the RX queue entry is all about. */
+/* Fujitsu: Please tell me which ones can have a pointer to a 
+   freepool descriptor! */
+static char *res_strings[] = {
+       "RX OK: streaming not EOP", 
+       "RX OK: streaming EOP", 
+       "RX OK: Single buffer packet", 
+       "RX OK: packet mode", 
+       "RX OK: F4 OAM (end to end)", 
+       "RX OK: F4 OAM (Segment)", 
+       "RX OK: F5 OAM (end to end)", 
+       "RX OK: F5 OAM (Segment)", 
+       "RX OK: RM cell", 
+       "RX OK: TRANSP cell", 
+       "RX OK: TRANSPC cell", 
+       "Unmatched cell", 
+       "reserved 12", 
+       "reserved 13", 
+       "reserved 14", 
+       "Unrecognized cell", 
+       "reserved 16", 
+       "reassemby abort: AAL5 abort", 
+       "packet purged", 
+       "packet ageing timeout", 
+       "channel ageing timeout", 
+       "calculated lenght error", 
+       "programmed lenght limit error", 
+       "aal5 crc32 error", 
+       "oam transp or transpc crc10 error", 
+       "reserved 25", 
+       "reserved 26", 
+       "reserved 27", 
+       "reserved 28", 
+       "reserved 29", 
+       "reserved 30", 
+       "reassembly abort: no buffers", 
+       "receive buffer overflow", 
+       "change in GFC", 
+       "receive buffer full", 
+       "low priority discard - no receive descriptor", 
+       "low priority discard - missing end of packet", 
+       "reserved 41", 
+       "reserved 42", 
+       "reserved 43", 
+       "reserved 44", 
+       "reserved 45", 
+       "reserved 46", 
+       "reserved 47", 
+       "reserved 48", 
+       "reserved 49", 
+       "reserved 50", 
+       "reserved 51", 
+       "reserved 52", 
+       "reserved 53", 
+       "reserved 54", 
+       "reserved 55", 
+       "reserved 56", 
+       "reserved 57", 
+       "reserved 58", 
+       "reserved 59", 
+       "reserved 60", 
+       "reserved 61", 
+       "reserved 62", 
+       "reserved 63", 
+};  
+
+static char *irq_bitname[] = {
+       "LPCO",
+       "DPCO",
+       "RBRQ0_W",
+       "RBRQ1_W",
+       "RBRQ2_W",
+       "RBRQ3_W",
+       "RBRQ0_NF",
+       "RBRQ1_NF",
+       "RBRQ2_NF",
+       "RBRQ3_NF",
+       "BFP_SC",
+       "INIT",
+       "INIT_ERR",
+       "USCEO",
+       "UPEC0",
+       "VPFCO",
+       "CRCCO",
+       "HECO",
+       "TBRQ_W",
+       "TBRQ_NF",
+       "CTPQ_E",
+       "GFC_C0",
+       "PCI_FTL",
+       "CSQ_W",
+       "CSQ_NF",
+       "EXT_INT",
+       "RXDMA_S"
+};
+
+
+#define PHY_EOF -1
+#define PHY_CLEARALL -2
+
+struct reginit_item {
+       int reg, val;
+};
+
+
+struct reginit_item PHY_NTC_INIT[] __initdata = {
+       { PHY_CLEARALL, 0x40 }, 
+       { 0x12,  0x0001 },
+       { 0x13,  0x7605 },
+       { 0x1A,  0x0001 },
+       { 0x1B,  0x0005 },
+       { 0x38,  0x0003 },
+       { 0x39,  0x0006 },   /* changed here to make loopback */
+       { 0x01,  0x5262 },
+       { 0x15,  0x0213 },
+       { 0x00,  0x0003 },
+       { PHY_EOF, 0},    /* -1 signals end of list */
+};
+
+
+/* Safetyfeature: If the card interrupts more than this number of times
+   in a jiffy (1/100th of a second) then we just disable the interrupt and
+   print a message. This prevents the system from hanging. 
+
+   150000 packets per second is close to the limit a PC is going to have
+   anyway. We therefore have to disable this for production. -- REW */
+#undef IRQ_RATE_LIMIT 100
+
+/* Interrupts work now. Unlike serial cards, ATM cards don't work all
+   that great without interrupts. -- REW */
+#undef FS_POLL_FREQ 100
+
+/* 
+   This driver can spew a whole lot of debugging output at you. If you
+   need maximum performance, you should disable the DEBUG define. To
+   aid in debugging in the field, I'm leaving the compile-time debug
+   features enabled, and disable them "runtime". That allows me to
+   instruct people with problems to enable debugging without requiring
+   them to recompile... -- REW
+*/
+#define DEBUG
+
+#ifdef DEBUG
+#define fs_dprintk(f, str...) if (fs_debug & f) printk (str)
+#else
+#define fs_dprintk(f, str...) /* nothing */
+#endif
+
+
+#ifdef DEBUG
+/* I didn't forget to set this to zero before shipping. Hit me with a stick 
+   if you get this with the debug default not set to zero again. -- REW */
+static int fs_debug = 0;
+#else
+#define fs_debug 0
+#endif
+
+#ifdef MODULE
+#ifdef DEBUG 
+MODULE_PARM(fs_debug, "i");
+#endif
+MODULE_PARM(loopback, "i");
+MODULE_PARM(num, "i");
+/* XXX Add rx_buf_sizes, and rx_pool_sizes As per request Amar. -- REW */
+#endif
+
+
+#define FS_DEBUG_FLOW    0x00000001
+#define FS_DEBUG_OPEN    0x00000002
+#define FS_DEBUG_QUEUE   0x00000004
+#define FS_DEBUG_IRQ     0x00000008
+#define FS_DEBUG_INIT    0x00000010
+#define FS_DEBUG_SEND    0x00000020
+#define FS_DEBUG_PHY     0x00000040
+#define FS_DEBUG_CLEANUP 0x00000080
+#define FS_DEBUG_QOS     0x00000100
+#define FS_DEBUG_TXQ     0x00000200
+#define FS_DEBUG_ALLOC   0x00000400
+#define FS_DEBUG_TXMEM   0x00000800
+#define FS_DEBUG_QSIZE   0x00001000
+
+
+#define func_enter() fs_dprintk (FS_DEBUG_FLOW, "fs: enter " __FUNCTION__ "\n")
+#define func_exit()  fs_dprintk (FS_DEBUG_FLOW, "fs: exit  " __FUNCTION__ "\n")
+
+
+struct fs_dev *fs_boards = NULL;
+
+#ifdef DEBUG
+
+static void my_hd (void *addr, int len)
+{
+       int j, ch;
+       unsigned char *ptr = addr;
+
+       while (len > 0) {
+               printk ("%p ", ptr);
+               for (j=0;j < ((len < 16)?len:16);j++) {
+                       printk ("%02x %s", ptr[j], (j==7)?" ":"");
+               }
+               for (  ;j < 16;j++) {
+                       printk ("   %s", (j==7)?" ":"");
+               }
+               for (j=0;j < ((len < 16)?len:16);j++) {
+                       ch = ptr[j];
+                       printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+               }
+               printk ("\n");
+               ptr += 16;
+               len -= 16;
+       }
+}
+#else /* DEBUG */
+static void my_hd (void *addr, int len){}
+#endif /* DEBUG */
+
+/********** free an skb (as per ATM device driver documentation) **********/
+
+/* Hmm. If this is ATM specific, why isn't there an ATM routine for this?
+ * I copied it over from the ambassador driver. -- REW */
+
+static inline void fs_kfree_skb (struct sk_buff * skb) 
+{
+       if (ATM_SKB(skb)->vcc->pop)
+               ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb);
+       else
+               dev_kfree_skb_any (skb);
+}
+
+
+
+
+/* It seems the ATM forum recomends this horribly complicated 16bit
+ * floating point format. Turns out the Ambassador uses the exact same
+ * encoding. I just copied it over. If Mitch agrees, I'll move it over
+ * to the atm_misc file or something like that. (and remove it from 
+ * here and the ambassador driver) -- REW
+ */
+
+/* The good thing about this format is that it is monotonic. So, 
+   a conversion routine need not be very complicated. To be able to
+   round "nearest" we need to take along a few extra bits. Lets
+   put these after 16 bits, so that we can just return the top 16
+   bits of the 32bit number as the result:
+
+   int mr (unsigned int rate, int r) 
+     {
+     int e = 16+9;
+     static int round[4]={0, 0, 0xffff, 0x8000};
+     if (!rate) return 0;
+     while (rate & 0xfc000000) {
+       rate >>= 1;
+       e++;
+     }
+     while (! (rate & 0xfe000000)) {
+       rate <<= 1;
+       e--;
+     }
+
+// Now the mantissa is in positions bit 16-25. Excepf for the "hidden 1" that's in bit 26.
+     rate &= ~0x02000000;
+// Next add in the exponent
+     rate |= e << (16+9);
+// And perform the rounding:
+     return (rate + round[r]) >> 16;
+   }
+
+   14 lines-of-code. Compare that with the 120 that the Ambassador
+   guys needed. (would be 8 lines shorter if I'd try to really reduce
+   the number of lines:
+
+   int mr (unsigned int rate, int r) 
+   {
+     int e = 16+9;
+     static int round[4]={0, 0, 0xffff, 0x8000};
+     if (!rate) return 0;
+     for (;  rate & 0xfc000000 ;rate >>= 1, e++);
+     for (;!(rate & 0xfe000000);rate <<= 1, e--);
+     return ((rate & ~0x02000000) | (e << (16+9)) + round[r]) >> 16;
+   }
+
+   Exercise for the reader: Remove one more line-of-code, without
+   cheating. (Just joining two lines is cheating). (I know it's
+   possible, don't think you've beat me if you found it... If you
+   manage to lose two lines or more, keep me updated! ;-)
+
+   -- REW */
+
+
+#define ROUND_UP      1
+#define ROUND_DOWN    2
+#define ROUND_NEAREST 3
+/********** make rate (not quite as much fun as Horizon) **********/
+
+static unsigned int make_rate (unsigned int rate, int r,
+                              u16 * bits, unsigned int * actual) 
+{
+       unsigned char exp = -1; /* hush gcc */
+       unsigned int man = -1;  /* hush gcc */
+  
+       fs_dprintk (FS_DEBUG_QOS, "make_rate %u", rate);
+  
+       /* rates in cells per second, ITU format (nasty 16-bit floating-point)
+          given 5-bit e and 9-bit m:
+          rate = EITHER (1+m/2^9)*2^e    OR 0
+          bits = EITHER 1<<14 | e<<9 | m OR 0
+          (bit 15 is "reserved", bit 14 "non-zero")
+          smallest rate is 0 (special representation)
+          largest rate is (1+511/512)*2^31 = 4290772992 (< 2^32-1)
+          smallest non-zero rate is (1+0/512)*2^0 = 1 (> 0)
+          simple algorithm:
+          find position of top bit, this gives e
+          remove top bit and shift (rounding if feeling clever) by 9-e
+       */
+       /* Ambassador ucode bug: please don't set bit 14! so 0 rate not
+          representable. // This should move into the ambassador driver
+          when properly merged. -- REW */
+  
+       if (rate > 0xffc00000U) {
+               /* larger than largest representable rate */
+    
+               if (r == ROUND_UP) {
+                       return -EINVAL;
+               } else {
+                       exp = 31;
+                       man = 511;
+               }
+    
+       } else if (rate) {
+               /* representable rate */
+    
+               exp = 31;
+               man = rate;
+    
+               /* invariant: rate = man*2^(exp-31) */
+               while (!(man & (1<<31))) {
+                       exp = exp - 1;
+                       man = man<<1;
+               }
+    
+               /* man has top bit set
+                  rate = (2^31+(man-2^31))*2^(exp-31)
+                  rate = (1+(man-2^31)/2^31)*2^exp 
+               */
+               man = man<<1;
+               man &= 0xffffffffU; /* a nop on 32-bit systems */
+               /* rate = (1+man/2^32)*2^exp
+    
+                  exp is in the range 0 to 31, man is in the range 0 to 2^32-1
+                  time to lose significance... we want m in the range 0 to 2^9-1
+                  rounding presents a minor problem... we first decide which way
+                  we are rounding (based on given rounding direction and possibly
+                  the bits of the mantissa that are to be discarded).
+               */
+
+               switch (r) {
+               case ROUND_DOWN: {
+                       /* just truncate */
+                       man = man>>(32-9);
+                       break;
+               }
+               case ROUND_UP: {
+                       /* check all bits that we are discarding */
+                       if (man & (-1>>9)) {
+                               man = (man>>(32-9)) + 1;
+                               if (man == (1<<9)) {
+                                       /* no need to check for round up outside of range */
+                                       man = 0;
+                                       exp += 1;
+                               }
+                       } else {
+                               man = (man>>(32-9));
+                       }
+                       break;
+               }
+               case ROUND_NEAREST: {
+                       /* check msb that we are discarding */
+                       if (man & (1<<(32-9-1))) {
+                               man = (man>>(32-9)) + 1;
+                               if (man == (1<<9)) {
+                                       /* no need to check for round up outside of range */
+                                       man = 0;
+                                       exp += 1;
+                               }
+                       } else {
+                               man = (man>>(32-9));
+                       }
+                       break;
+               }
+               }
+    
+       } else {
+               /* zero rate - not representable */
+    
+               if (r == ROUND_DOWN) {
+                       return -EINVAL;
+               } else {
+                       exp = 0;
+                       man = 0;
+               }
+       }
+  
+       fs_dprintk (FS_DEBUG_QOS, "rate: man=%u, exp=%hu", man, exp);
+  
+       if (bits)
+               *bits = /* (1<<14) | */ (exp<<9) | man;
+  
+       if (actual)
+               *actual = (exp >= 9)
+                       ? (1 << exp) + (man << (exp-9))
+                       : (1 << exp) + ((man + (1<<(9-exp-1))) >> (9-exp));
+  
+       return 0;
+}
+
+
+
+
+/* FireStream access routines */
+/* For DEEP-DOWN debugging these can be rigged to intercept accesses to
+   certain registers or to just log all accesses. */
+
+static inline void write_fs (struct fs_dev *dev, int offset, u32 val)
+{
+       writel (val, dev->base + offset);
+}
+
+
+static inline u32  read_fs (struct fs_dev *dev, int offset)
+{
+       return readl (dev->base + offset);
+}
+
+
+
+static inline struct FS_QENTRY *get_qentry (struct fs_dev *dev, struct queue *q)
+{
+       return bus_to_virt (read_fs (dev, Q_WP(q->offset)) & Q_ADDR_MASK);
+}
+
+
+static void submit_qentry (struct fs_dev *dev, struct queue *q, struct FS_QENTRY *qe)
+{
+       u32 wp;
+       struct FS_QENTRY *cqe;
+
+       /* XXX Sanity check: the write pointer can be checked to be 
+          still the same as the value passed as qe... -- REW */
+       /*  udelay (5); */
+       while ((wp = read_fs (dev, Q_WP (q->offset))) & Q_FULL) {
+               fs_dprintk (FS_DEBUG_TXQ, "Found queue at %x full. Waiting.\n", 
+                           q->offset);
+               schedule ();
+       }
+
+       wp &= ~0xf;
+       cqe = bus_to_virt (wp);
+       if (qe != cqe) {
+               fs_dprintk (FS_DEBUG_TXQ, "q mismatch! %p %p\n", qe, cqe);
+       }
+
+       write_fs (dev, Q_WP(q->offset), Q_INCWRAP);
+
+       {
+               static int c;
+               if (!(c++ % 100))
+                       {
+                               int rp, wp;
+                               rp =  read_fs (dev, Q_RP(q->offset));
+                               wp =  read_fs (dev, Q_WP(q->offset));
+                               fs_dprintk (FS_DEBUG_TXQ, "q at %d: %x-%x: %x entries.\n", 
+                                           q->offset, rp, wp, wp-rp);
+                       }
+       }
+}
+
+#ifdef DEBUG_EXTRA
+static struct FS_QENTRY pq[60];
+static int qp;
+
+static struct FS_BPENTRY dq[60];
+static int qd;
+static void *da[60];
+#endif 
+
+static void submit_queue (struct fs_dev *dev, struct queue *q, 
+                         u32 cmd, u32 p1, u32 p2, u32 p3)
+{
+       struct FS_QENTRY *qe;
+
+       qe = get_qentry (dev, q);
+       qe->cmd = cmd;
+       qe->p0 = p1;
+       qe->p1 = p2;
+       qe->p2 = p3;
+       submit_qentry (dev,  q, qe);
+
+#ifdef DEBUG_EXTRA
+       pq[qp].cmd = cmd;
+       pq[qp].p0 = p1;
+       pq[qp].p1 = p2;
+       pq[qp].p2 = p3;
+       qp++;
+       if (qp >= 60) qp = 0;
+#endif
+}
+
+/* Test the "other" way one day... -- REW */
+#if 1
+#define submit_command submit_queue
+#else
+
+static void submit_command (struct fs_dev *dev, struct queue *q, 
+                           u32 cmd, u32 p1, u32 p2, u32 p3)
+{
+       write_fs (dev, CMDR0, cmd);
+       write_fs (dev, CMDR1, p1);
+       write_fs (dev, CMDR2, p2);
+       write_fs (dev, CMDR3, p3);
+}
+#endif
+
+
+
+static void process_return_queue (struct fs_dev *dev, struct queue *q)
+{
+       long rq;
+       struct FS_QENTRY *qe;
+       void *tc;
+  
+       while (!((rq = read_fs (dev, Q_RP(q->offset))) & Q_EMPTY)) {
+               fs_dprintk (FS_DEBUG_QUEUE, "reaping return queue entry at %lx\n", rq); 
+               qe = bus_to_virt (rq);
+    
+               fs_dprintk (FS_DEBUG_QUEUE, "queue entry: %08x %08x %08x %08x. (%d)\n", 
+                           qe->cmd, qe->p0, qe->p1, qe->p2, STATUS_CODE (qe));
+
+               switch (STATUS_CODE (qe)) {
+               case 5:
+                       tc = bus_to_virt (qe->p0);
+                       fs_dprintk (FS_DEBUG_ALLOC, "Free tc: %p\n", tc);
+                       kfree (tc);
+                       break;
+               }
+    
+               write_fs (dev, Q_RP(q->offset), Q_INCWRAP);
+       }
+}
+
+
+static void process_txdone_queue (struct fs_dev *dev, struct queue *q)
+{
+       long rq;
+       long tmp;
+       struct FS_QENTRY *qe;
+       struct sk_buff *skb;
+       struct FS_BPENTRY *td;
+
+       while (!((rq = read_fs (dev, Q_RP(q->offset))) & Q_EMPTY)) {
+               fs_dprintk (FS_DEBUG_QUEUE, "reaping txdone entry at %lx\n", rq); 
+               qe = bus_to_virt (rq);
+    
+               fs_dprintk (FS_DEBUG_QUEUE, "queue entry: %08x %08x %08x %08x: %d\n", 
+                           qe->cmd, qe->p0, qe->p1, qe->p2, STATUS_CODE (qe));
+
+               if (STATUS_CODE (qe) != 2)
+                       fs_dprintk (FS_DEBUG_TXMEM, "queue entry: %08x %08x %08x %08x: %d\n", 
+                                   qe->cmd, qe->p0, qe->p1, qe->p2, STATUS_CODE (qe));
+
+
+               switch (STATUS_CODE (qe)) {
+               case 0x02:
+                       /* Process a real txdone entry. */
+                       tmp = qe->p0;
+                       if (tmp & 0x0f)
+                               printk (KERN_WARNING "td not aligned: %ld\n", tmp);
+                       tmp &= ~0x0f;
+                       td = bus_to_virt (tmp);
+
+                       fs_dprintk (FS_DEBUG_QUEUE, "Pool entry: %08x %08x %08x %08x %p.\n", 
+                                   td->flags, td->next, td->bsa, td->aal_bufsize, td->skb );
+      
+                       skb = td->skb;
+                       if (skb == FS_VCC (ATM_SKB(skb)->vcc)->last_skb) {
+                               wake_up_interruptible (& FS_VCC (ATM_SKB(skb)->vcc)->close_wait);
+                               FS_VCC (ATM_SKB(skb)->vcc)->last_skb = NULL;
+                       }
+                       td->dev->ntxpckts--;
+
+                       {
+                               static int c=0;
+       
+                               if (!(c++ % 100)) {
+                                       fs_dprintk (FS_DEBUG_QSIZE, "[%d]", td->dev->ntxpckts);
+                               }
+                       }
+
+                       atomic_inc(&ATM_SKB(skb)->vcc->stats->tx);
+
+                       fs_dprintk (FS_DEBUG_TXMEM, "i");
+                       fs_dprintk (FS_DEBUG_ALLOC, "Free t-skb: %p\n", skb);
+                       fs_kfree_skb (skb);
+
+                       fs_dprintk (FS_DEBUG_ALLOC, "Free trans-d: %p\n", td); 
+                       memset (td, 0x12, sizeof (struct FS_BPENTRY));
+                       kfree (td);
+                       break;
+               default:
+                       /* Here we get the tx purge inhibit command ... */
+                       /* Action, I believe, is "don't do anything". -- REW */
+               }
+    
+               write_fs (dev, Q_RP(q->offset), Q_INCWRAP);
+       }
+}
+
+
+static void process_incoming (struct fs_dev *dev, struct queue *q)
+{
+       long rq;
+       struct FS_QENTRY *qe;
+       struct FS_BPENTRY *pe;    
+       struct sk_buff *skb;
+       unsigned int channo;
+       struct atm_vcc *atm_vcc;
+
+       while (!((rq = read_fs (dev, Q_RP(q->offset))) & Q_EMPTY)) {
+               fs_dprintk (FS_DEBUG_QUEUE, "reaping incoming queue entry at %lx\n", rq); 
+               qe = bus_to_virt (rq);
+    
+               fs_dprintk (FS_DEBUG_QUEUE, "queue entry: %08x %08x %08x %08x.  ", 
+                           qe->cmd, qe->p0, qe->p1, qe->p2);
+
+               fs_dprintk (FS_DEBUG_QUEUE, "-> %x: %s\n", 
+                           STATUS_CODE (qe), 
+                           res_strings[STATUS_CODE(qe)]);
+
+               pe = bus_to_virt (qe->p0);
+               fs_dprintk (FS_DEBUG_QUEUE, "Pool entry: %08x %08x %08x %08x %p %p.\n", 
+                           pe->flags, pe->next, pe->bsa, pe->aal_bufsize, 
+                           pe->skb, pe->fp);
+      
+               channo = qe->cmd & 0xffff;
+
+               if (channo < dev->nchannels)
+                       atm_vcc = dev->atm_vccs[channo];
+               else
+                       atm_vcc = NULL;
+
+               /* Single buffer packet */
+               switch (STATUS_CODE (qe)) {
+               case 0x2:/* Packet received OK.... */
+                       if (atm_vcc) {
+                               skb = pe->skb;
+                               pe->fp->n--;
+#if 0
+                               fs_dprintk (FS_DEBUG_QUEUE, "Got skb: %p\n", skb);
+                               if (FS_DEBUG_QUEUE & fs_debug) my_hd (bus_to_virt (pe->bsa), 0x20);
+#endif
+                               skb_put (skb, qe->p1 & 0xffff); 
+                               ATM_SKB(skb)->vcc = atm_vcc;
+                               atomic_inc(&atm_vcc->stats->rx);
+                               skb->stamp = xtime;
+                               fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p (pushed)\n", skb);
+                               atm_vcc->push (atm_vcc, skb);
+                               fs_dprintk (FS_DEBUG_ALLOC, "Free rec-d: %p\n", pe);
+                               kfree (pe);
+                       } else {
+                               printk (KERN_ERR "Got a receive on a non-open channel %d.\n", channo);
+                       }
+                       break;
+               case 0x17:/* AAL 5 CRC32 error. IFF the length field is nonzero, a buffer
+                            has been consumed and needs to be processed. -- REW */
+                       if (qe->p1 & 0xffff) {
+                               pe = bus_to_virt (qe->p0);
+                               pe->fp->n--;
+                               fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p\n", pe->skb);
+                               dev_kfree_skb_any (pe->skb);
+                               fs_dprintk (FS_DEBUG_ALLOC, "Free rec-d: %p\n", pe);
+                               kfree (pe);
+                       }
+                       if (atm_vcc)
+                               atomic_inc(&atm_vcc->stats->rx_drop);
+                       break;
+               case 0x1f: /*  Reassembly abort: no buffers. */
+                       /* Silently increment error counter. */
+                       if (atm_vcc)
+                               atomic_inc(&atm_vcc->stats->rx_drop);
+                       break;
+               default: /* Hmm. Haven't written the code to handle the others yet... -- REW */
+                       printk (KERN_WARNING "Don't know what to do with RX status %x: %s.\n", 
+                               STATUS_CODE(qe), res_strings[STATUS_CODE (qe)]);
+               }
+               write_fs (dev, Q_RP(q->offset), Q_INCWRAP);
+       }
+}
+
+
+
+#define DO_DIRECTION(tp) ((tp)->traffic_class != ATM_NONE)
+
+static int fs_open(struct atm_vcc *atm_vcc, short vpi, int vci)
+{
+       struct fs_dev *dev;
+       struct fs_vcc *vcc;
+       struct fs_transmit_config *tc;
+       struct atm_trafprm * txtp;
+       struct atm_trafprm * rxtp;
+       /*  struct fs_receive_config *rc;*/
+       /*  struct FS_QENTRY *qe; */
+       int error;
+       int bfp;
+       int to;
+       unsigned short tmc0;
+
+       func_enter ();
+
+       dev = FS_DEV(atm_vcc->dev);
+       fs_dprintk (FS_DEBUG_OPEN, "fs: open on dev: %p, vcc at %p\n", 
+                   dev, atm_vcc);
+
+       error = atm_find_ci(atm_vcc, &vpi, &vci);
+       if (error) {
+               fs_dprintk (FS_DEBUG_OPEN, "fs: find_ci failed.\n");
+               return error;
+       }
+
+       atm_vcc->vpi = vpi;
+       atm_vcc->vci = vci;
+       if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
+               set_bit(ATM_VF_ADDR, &atm_vcc->flags);
+
+       if (atm_vcc->qos.aal != ATM_AAL5) return -EINVAL; /* XXX AAL0 */
+
+       fs_dprintk (FS_DEBUG_OPEN, "fs: (itf %d): open %d.%d\n", 
+                   atm_vcc->dev->number, atm_vcc->vpi, atm_vcc->vci);  
+
+       /* XXX handle qos parameters (rate limiting) ? */
+
+       vcc = kmalloc(sizeof(struct fs_vcc), GFP_KERNEL);
+       fs_dprintk (FS_DEBUG_ALLOC, "Alloc VCC: %p(%d)\n", vcc, sizeof(struct fs_vcc));
+       if (!vcc) {
+               clear_bit(ATM_VF_ADDR, &atm_vcc->flags);
+               return -ENOMEM;
+       }
+  
+       atm_vcc->dev_data = vcc;
+       vcc->last_skb = NULL;
+
+       init_waitqueue_head (&vcc->close_wait);
+
+       txtp = &atm_vcc->qos.txtp;
+       rxtp = &atm_vcc->qos.rxtp;
+
+       if (!test_bit(ATM_VF_PARTIAL, &atm_vcc->flags)) {
+               if (IS_FS50(dev)) {
+                       /* Increment the channel numer: take a free one next time.  */
+                       for (to=33;to;to--, dev->channo++) {
+                               /* If we need to do RX, AND the RX is inuse, try the next */
+                               if (DO_DIRECTION(rxtp) && dev->atm_vccs[dev->channo])
+                                       continue;
+                               /* If we need to do TX, AND the TX is inuse, try the next */
+                               if (DO_DIRECTION(txtp) && test_bit (dev->channo, dev->tx_inuse))
+                                       continue;
+                               /* Ok, both are free! (or not needed) */
+                               break;
+                       }
+                       if (!to) {
+                               printk ("No more free channels for FS50..\n");
+                               return -EBUSY;
+                       }
+                       vcc->channo = dev->channo;
+                       dev->channo &= dev->channel_mask;
+      
+               } else {
+                       vcc->channo = (vpi << FS155_VCI_BITS) | (vci);
+                       if (((DO_DIRECTION(rxtp) && dev->atm_vccs[vcc->channo])) ||
+                           ( DO_DIRECTION(txtp) && test_bit (vcc->channo, dev->tx_inuse))) {
+                               printk ("Channel is in use for FS155.\n");
+                               return -EBUSY;
+                       }
+               }
+               fs_dprintk (FS_DEBUG_OPEN, "OK. Allocated channel %x(%d).\n", 
+                           vcc->channo, vcc->channo);
+       }
+
+       if (DO_DIRECTION (txtp)) {
+               tc = kmalloc (sizeof (struct fs_transmit_config), GFP_KERNEL);
+               fs_dprintk (FS_DEBUG_ALLOC, "Alloc tc: %p(%d)\n", 
+                           tc, sizeof (struct fs_transmit_config));
+               if (!tc) {
+                       fs_dprintk (FS_DEBUG_OPEN, "fs: can't alloc transmit_config.\n");
+                       return -ENOMEM;
+               }
+
+               /* Allocate the "open" entry from the high priority txq. This makes
+                  it most likely that the chip will notice it. It also prevents us
+                  from having to wait for completion. On the other hand, we may
+                  need to wait for completion anyway, to see if it completed
+                  succesfully. */
+
+               tc->flags = 0
+                       | TC_FLAGS_AAL5
+                       | TC_FLAGS_PACKET  /* ??? */
+                       | TC_FLAGS_TYPE_CBR
+                       | TC_FLAGS_CAL0;
+
+               /* Docs are vague about this atm_hdr field. By the way, the FS
+                * chip makes odd errors if lower bits are set.... -- REW */
+               tc->atm_hdr =  (vpi << 20) | (vci << 4); 
+               {
+                       int pcr = atm_pcr_goal (txtp);
+
+                       fs_dprintk (FS_DEBUG_OPEN, "pcr = %d.\n", pcr);
+
+                       /* XXX Hmm. officially we're only allowed to do this if rounding 
+                          is round_down -- REW */
+                       if (IS_FS50(dev)) {
+                               if (pcr > 51840000/53/8)  pcr = 51840000/53/8;
+                       } else {
+                               if (pcr > 155520000/53/8) pcr = 155520000/53/8;
+                       }
+                       if (!pcr) {
+                               /* no rate cap */
+                               tmc0 = IS_FS50(dev)?0x61BE:0x64c9; /* Just copied over the bits from Fujitsu -- REW */
+                       } else {
+                               int r;
+                               if (pcr < 0) {
+                                       r = ROUND_DOWN;
+                                       pcr = -pcr;
+                               } else {
+                                       r = ROUND_UP;
+                               }
+                               error = make_rate (pcr, r, &tmc0, 0);
+                       }
+                       fs_dprintk (FS_DEBUG_OPEN, "pcr = %d.\n", pcr);
+               }
+      
+               tc->TMC[0] = tmc0 | 0x4000;
+               tc->TMC[1] = 0; /* Unused */
+               tc->TMC[2] = 0; /* Unused */
+               tc->TMC[3] = 0; /* Unused */
+    
+               tc->spec = 0;    /* UTOPIA address, UDF, HEC: Unused -> 0 */
+               tc->rtag[0] = 0; /* What should I do with routing tags??? 
+                                   -- Not used -- AS -- Thanks -- REW*/
+               tc->rtag[1] = 0;
+               tc->rtag[2] = 0;
+
+               if (fs_debug & FS_DEBUG_OPEN) {
+                       fs_dprintk (FS_DEBUG_OPEN, "TX config record:\n");
+                       my_hd (tc, sizeof (*tc));
+               }
+
+               /* We now use the "submit_command" function to submit commands to
+                  the firestream. There is a define up near the definition of
+                  that routine that switches this routine between immediate write
+                  to the immediate comamnd registers and queuing the commands in
+                  the HPTXQ for execution. This last technique might be more
+                  efficient if we know we're going to submit a whole lot of
+                  commands in one go, but this driver is not setup to be able to
+                  use such a construct. So it probably doen't matter much right
+                  now. -- REW */
+    
+               /* The command is IMMediate and INQueue. The parameters are out-of-line.. */
+               submit_command (dev, &dev->hp_txq, 
+                               QE_CMD_CONFIG_TX | QE_CMD_IMM_INQ | vcc->channo,
+                               virt_to_bus (tc), 0, 0);
+
+               submit_command (dev, &dev->hp_txq, 
+                               QE_CMD_TX_EN | QE_CMD_IMM_INQ | vcc->channo,
+                               0, 0, 0);
+               set_bit (vcc->channo, dev->tx_inuse);
+       }
+
+       if (DO_DIRECTION (rxtp)) {
+               dev->atm_vccs[vcc->channo] = atm_vcc;
+
+               for (bfp = 0;bfp < FS_NR_FREE_POOLS; bfp++)
+                       if (atm_vcc->qos.rxtp.max_sdu <= dev->rx_fp[bfp].bufsize) break;
+    
+               if (bfp >= FS_NR_FREE_POOLS) {
+                       fs_dprintk (FS_DEBUG_OPEN, "No free pool fits sdu: %d.\n", 
+                                   atm_vcc->qos.rxtp.max_sdu);
+                       /* XXX Cleanup? -- Would just calling fs_close work??? -- REW */
+
+                       /* XXX clear tx inuse. Close TX part? */
+                       dev->atm_vccs[vcc->channo] = NULL;
+                       kfree (vcc);
+                       return -EINVAL;
+               }
+
+               submit_command (dev, &dev->hp_txq, 
+                               QE_CMD_CONFIG_RX | QE_CMD_IMM_INQ | vcc->channo,
+                               RC_FLAGS_AAL5 | 
+                               RC_FLAGS_BFPS_BFP * bfp |
+                               RC_FLAGS_RXBM_PSB, 0, 0);
+    
+               if (IS_FS50 (dev)) {
+                       submit_command (dev, &dev->hp_txq, 
+                                       QE_CMD_REG_WR | QE_CMD_IMM_INQ,
+                                       0x80 + vcc->channo,
+                                       (vpi << 16) | vci, 0 ); /* XXX -- Use defines. */
+               }
+               submit_command (dev, &dev->hp_txq, 
+                               QE_CMD_RX_EN | QE_CMD_IMM_INQ | vcc->channo,
+                               0, 0, 0);
+       }
+    
+       /* Indicate we're done! */
+       set_bit(ATM_VF_READY, &atm_vcc->flags);
+
+       func_exit ();
+       return 0;
+}
+
+
+static void fs_close(struct atm_vcc *atm_vcc)
+{
+       struct fs_dev *dev = FS_DEV (atm_vcc->dev);
+       struct fs_vcc *vcc = FS_VCC (atm_vcc);
+       struct atm_trafprm * txtp;
+       struct atm_trafprm * rxtp;
+
+       func_enter ();
+
+       clear_bit(ATM_VF_READY, &atm_vcc->flags);
+
+       fs_dprintk (FS_DEBUG_QSIZE, "--==**[%d]**==--", dev->ntxpckts);
+       if (vcc->last_skb) {
+               fs_dprintk (FS_DEBUG_QUEUE, "Waiting for skb %p to be sent.\n", 
+                           vcc->last_skb);
+               /* We're going to wait for the last packet to get sent on this VC. It would
+                  be impolite not to send them don't you think? 
+                  XXX
+                  We don't know which packets didn't get sent. So if we get interrupted in 
+                  this sleep_on, we'll lose any reference to these packets. Memory leak!
+                  On the other hand, it's awfully convenient that we can abort a "close" that
+                  is taking too long. Maybe just use non-interruptible sleep on? -- REW */
+               interruptible_sleep_on (& vcc->close_wait);
+       }
+
+       txtp = &atm_vcc->qos.txtp;
+       rxtp = &atm_vcc->qos.rxtp;
+  
+
+       /* See App note XXX (Unpublished as of now) for the reason for the 
+          removal of the "CMD_IMM_INQ" part of the TX_PURGE_INH... -- REW */
+
+       if (DO_DIRECTION (txtp)) {
+               submit_command (dev,  &dev->hp_txq,
+                               QE_CMD_TX_PURGE_INH | /*QE_CMD_IMM_INQ|*/ vcc->channo, 0,0,0);
+               clear_bit (vcc->channo, dev->tx_inuse);
+       }
+
+       if (DO_DIRECTION (rxtp)) {
+               submit_command (dev,  &dev->hp_txq,
+                               QE_CMD_RX_PURGE_INH | QE_CMD_IMM_INQ | vcc->channo, 0,0,0);
+               dev->atm_vccs [vcc->channo] = NULL;
+  
+               /* This means that this is configured as a receive channel */
+               if (IS_FS50 (dev)) {
+                       /* Disable the receive filter. Is 0/0 indeed an invalid receive
+                          channel? -- REW.  Yes it is. -- Hang. Ok. I'll use -1
+                          (0xfff...) -- REW */
+                       submit_command (dev, &dev->hp_txq, 
+                                       QE_CMD_REG_WR | QE_CMD_IMM_INQ,
+                                       0x80 + vcc->channo, -1, 0 ); 
+               }
+       }
+
+       fs_dprintk (FS_DEBUG_ALLOC, "Free vcc: %p\n", vcc);
+       kfree (vcc);
+
+       func_exit ();
+}
+
+
+static int fs_send (struct atm_vcc *atm_vcc, struct sk_buff *skb)
+{
+       struct fs_dev *dev = FS_DEV (atm_vcc->dev);
+       struct fs_vcc *vcc = FS_VCC (atm_vcc);
+       struct FS_BPENTRY *td;
+
+       func_enter ();
+
+       fs_dprintk (FS_DEBUG_TXMEM, "I");
+       fs_dprintk (FS_DEBUG_SEND, "Send: atm_vcc %p skb %p vcc %p dev %p\n", 
+                   atm_vcc, skb, vcc, dev);
+
+       fs_dprintk (FS_DEBUG_ALLOC, "Alloc t-skb: %p (atm_send)\n", skb);
+
+       ATM_SKB(skb)->vcc = atm_vcc;
+
+       vcc->last_skb = skb;
+
+       td = kmalloc (sizeof (struct FS_BPENTRY), GFP_ATOMIC);
+       fs_dprintk (FS_DEBUG_ALLOC, "Alloc transd: %p(%d)\n", td, sizeof (struct FS_BPENTRY));
+       if (!td) {
+               /* Oops out of mem */
+               return -ENOMEM;
+       }
+
+       fs_dprintk (FS_DEBUG_SEND, "first word in buffer: %x\n", 
+                   *(int *) skb->data);
+
+       td->flags =  TD_EPI | TD_DATA | skb->len;
+       td->next = 0;
+       td->bsa  = virt_to_bus (skb->data);
+       td->skb = skb;
+       td->dev = dev;
+       dev->ntxpckts++;
+
+#ifdef DEBUG_EXTRA
+       da[qd] = td;
+       dq[qd].flags = td->flags;
+       dq[qd].next  = td->next;
+       dq[qd].bsa   = td->bsa;
+       dq[qd].skb   = td->skb;
+       dq[qd].dev   = td->dev;
+       qd++;
+       if (qd >= 60) qd = 0;
+#endif
+
+       submit_queue (dev, &dev->hp_txq, 
+                     QE_TRANSMIT_DE | vcc->channo,
+                     virt_to_bus (td), 0, 
+                     virt_to_bus (td));
+
+       fs_dprintk (FS_DEBUG_QUEUE, "in send: txq %d txrq %d\n", 
+                   read_fs (dev, Q_EA (dev->hp_txq.offset)) -
+                   read_fs (dev, Q_SA (dev->hp_txq.offset)),
+                   read_fs (dev, Q_EA (dev->tx_relq.offset)) -
+                   read_fs (dev, Q_SA (dev->tx_relq.offset)));
+
+       func_exit ();
+       return 0;
+}
+
+
+/* Some function placeholders for functions we don't yet support. */
+
+#if 0
+static int fs_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
+{
+       func_enter ();
+       func_exit ();
+       return 0;
+}
+
+
+static int fs_getsockopt(struct atm_vcc *vcc,int level,int optname,
+                        void *optval,int optlen)
+{
+       func_enter ();
+       func_exit ();
+       return 0;
+}
+
+
+static int fs_setsockopt(struct atm_vcc *vcc,int level,int optname,
+                        void *optval,int optlen)
+{
+       func_enter ();
+       func_exit ();
+       return 0;
+}
+
+
+static void fs_phy_put(struct atm_dev *dev,unsigned char value,
+                      unsigned long addr)
+{
+       func_enter ();
+       func_exit ();
+}
+
+
+static unsigned char fs_phy_get(struct atm_dev *dev,unsigned long addr)
+{
+       func_enter ();
+       func_exit ();
+       return 0;
+}
+
+
+static void fs_feedback(struct atm_vcc *vcc,struct sk_buff *skb,
+                       unsigned long start,unsigned long dest,int len)
+{
+       func_enter ();
+       func_exit ();
+}
+
+
+static int fs_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flags)
+{
+       func_enter ();
+       func_exit ();
+       return 0;
+};
+
+#endif
+
+
+static const struct atmdev_ops ops = {
+       open:           fs_open,
+       close:          fs_close,
+       send:           fs_send,
+#if 0
+       owner:          THIS_MODULE,
+#endif
+       /*                 fs_sg_send */
+       /* ioctl:          fs_ioctl, */
+       /* getsockopt:     fs_getsockopt, */
+       /* setsockopt:     fs_setsockopt, */
+       /* feedback:       fs_feedback, */
+       /* change_qos:     fs_change_qos, */
+
+       /* For now implement these internally here... */  
+       /* phy_put:        fs_phy_put, */
+       /* phy_get:        fs_phy_get, */
+};
+
+
+static void __init undocumented_pci_fix (struct pci_dev *pdev)
+{
+       int tint;
+
+       /* The Windows driver says: */
+       /* Switch off FireStream Retry Limit Threshold 
+        */
+
+       /* The register at 0x28 is documented as "reserved", no further
+          comments. */
+
+       pci_read_config_dword (pdev, 0x28, &tint);
+       if (tint != 0x80) {
+               tint = 0x80;
+               pci_write_config_dword (pdev, 0x28, tint);
+       }
+}
+
+
+
+/**************************************************************************
+ *                              PHY routines                              *
+ **************************************************************************/
+
+static void __init write_phy (struct fs_dev *dev, int regnum, int val)
+{
+       submit_command (dev,  &dev->hp_txq, QE_CMD_PRP_WR | QE_CMD_IMM_INQ,
+                       regnum, val, 0);
+}
+
+static int __init init_phy (struct fs_dev *dev, struct reginit_item *reginit)
+{
+       int i;
+
+       func_enter ();
+       while (reginit->reg != PHY_EOF) {
+               if (reginit->reg == PHY_CLEARALL) {
+                       /* "PHY_CLEARALL means clear all registers. Numregisters is in "val". */
+                       for (i=0;i<reginit->val;i++) {
+                               write_phy (dev, i, 0);
+                       }
+               } else {
+                       write_phy (dev, reginit->reg, reginit->val);
+               }
+               reginit++;
+       }
+       func_exit ();
+       return 0;
+}
+
+static void reset_chip (struct fs_dev *dev)
+{
+       int i;
+
+       write_fs (dev, SARMODE0, SARMODE0_SRTS0);
+
+       /* Undocumented delay */
+       udelay (128);
+
+       /* The "internal registers are documented to all reset to zero, but 
+          comments & code in the Windows driver indicates that the pools are
+          NOT reset. */
+       for (i=0;i < FS_NR_FREE_POOLS;i++) {
+               write_fs (dev, FP_CNF (RXB_FP(i)), 0);
+               write_fs (dev, FP_SA  (RXB_FP(i)), 0);
+               write_fs (dev, FP_EA  (RXB_FP(i)), 0);
+               write_fs (dev, FP_CNT (RXB_FP(i)), 0);
+               write_fs (dev, FP_CTU (RXB_FP(i)), 0);
+       }
+
+       /* The same goes for the match channel registers, although those are
+          NOT documented that way in the Windows driver. -- REW */
+       /* The Windows driver DOES write 0 to these registers somewhere in
+          the init sequence. However, a small hardware-feature, will
+          prevent reception of data on VPI/VCI = 0/0 (Unless the channel
+          allocated happens to have no disabled channels that have a lower
+          number. -- REW */
+
+       /* Clear the match channel registers. */
+       if (IS_FS50 (dev)) {
+               for (i=0;i<FS50_NR_CHANNELS;i++) {
+                       write_fs (dev, 0x200 + i * 4, -1);
+               }
+       }
+}
+
+static void __init *aligned_kmalloc (int size, int flags, int alignment)
+{
+       void  *t;
+
+       if (alignment <= 0x10) {
+               t = kmalloc (size, flags);
+               if ((unsigned int)t & (alignment-1)) {
+                       printk ("Kmalloc doesn't align things correctly! %p\n", t);
+                       kfree (t);
+                       return aligned_kmalloc (size, flags, alignment * 4);
+               }
+               return t;
+       }
+       printk (KERN_ERR "Request for > 0x10 alignment not yet implemented (hard!)\n");
+       return NULL;
+}
+
+static int __init init_q (struct fs_dev *dev, 
+                         struct queue *txq, int queue, int nentries, int is_rq)
+{
+       int sz = nentries * sizeof (struct FS_QENTRY);
+       struct FS_QENTRY *p;
+
+       func_enter ();
+
+       fs_dprintk (FS_DEBUG_INIT, "Inititing queue at %x: %d entries:\n", 
+                   queue, nentries);
+
+       p = aligned_kmalloc (sz, GFP_KERNEL, 0x10);
+       fs_dprintk (FS_DEBUG_ALLOC, "Alloc queue: %p(%d)\n", p, sz);
+
+       if (!p) return 0;
+
+       write_fs (dev, Q_SA(queue), virt_to_bus(p));
+       write_fs (dev, Q_EA(queue), virt_to_bus(p+nentries-1));
+       write_fs (dev, Q_WP(queue), virt_to_bus(p));
+       write_fs (dev, Q_RP(queue), virt_to_bus(p));
+       if (is_rq) {
+               /* Configuration for the receive queue: 0: interrupt immediately,
+                  no pre-warning to empty queues: We do our best to keep the
+                  queue filled anyway. */
+               write_fs (dev, Q_CNF(queue), 0 ); 
+       }
+
+       txq->sa = p;
+       txq->ea = p;
+       txq->offset = queue; 
+
+       func_exit ();
+       return 1;
+}
+
+
+static int __init init_fp (struct fs_dev *dev, 
+                          struct freepool *fp, int queue, int bufsize, int nr_buffers)
+{
+       func_enter ();
+
+       fs_dprintk (FS_DEBUG_INIT, "Inititing free pool at %x:\n", queue);
+
+       write_fs (dev, FP_CNF(queue), (bufsize * RBFP_RBS) | RBFP_RBSVAL | RBFP_CME);
+       write_fs (dev, FP_SA(queue),  0);
+       write_fs (dev, FP_EA(queue),  0);
+       write_fs (dev, FP_CTU(queue), 0);
+       write_fs (dev, FP_CNT(queue), 0);
+
+       fp->offset = queue; 
+       fp->bufsize = bufsize;
+       fp->nr_buffers = nr_buffers;
+
+       func_exit ();
+       return 1;
+}
+
+
+static inline int nr_buffers_in_freepool (struct fs_dev *dev, struct freepool *fp)
+{
+#if 0
+       /* This seems to be unreliable.... */
+       return read_fs (dev, FP_CNT (fp->offset));
+#else
+       return fp->n;
+#endif
+}
+
+
+/* Check if this gets going again if a pool ever runs out.  -- Yes, it
+   does. I've seen "recieve abort: no buffers" and things started
+   working again after that...  -- REW */
+
+static void top_off_fp (struct fs_dev *dev, struct freepool *fp, int gfp_flags)
+{
+       struct FS_BPENTRY *qe, *ne;
+       struct sk_buff *skb;
+       int n = 0;
+
+       fs_dprintk (FS_DEBUG_QUEUE, "Topping off queue at %x (%d-%d/%d)\n", 
+                   fp->offset, read_fs (dev, FP_CNT (fp->offset)), fp->n, 
+                   fp->nr_buffers);
+       while (nr_buffers_in_freepool(dev, fp) < fp->nr_buffers) {
+
+               skb = alloc_skb (fp->bufsize, gfp_flags);
+               fs_dprintk (FS_DEBUG_ALLOC, "Alloc rec-skb: %p(%d)\n", skb, fp->bufsize);
+               if (!skb) break;
+               ne = kmalloc (sizeof (struct FS_BPENTRY), gfp_flags);
+               fs_dprintk (FS_DEBUG_ALLOC, "Alloc rec-d: %p(%d)\n", ne, sizeof (struct FS_BPENTRY));
+               if (!ne) {
+                       fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p\n", skb);
+                       dev_kfree_skb_any (skb);
+                       break;
+               }
+
+               fs_dprintk (FS_DEBUG_QUEUE, "Adding skb %p desc %p -> %p(%p) ", 
+                           skb, ne, skb->data, skb->head);
+               n++;
+               ne->flags = FP_FLAGS_EPI | fp->bufsize;
+               ne->next  = virt_to_bus (NULL);
+               ne->bsa   = virt_to_bus (skb->data);
+               ne->aal_bufsize = fp->bufsize;
+               ne->skb = skb;
+               ne->fp = fp;
+
+               qe = (struct FS_BPENTRY *) (read_fs (dev, FP_EA(fp->offset)));
+               fs_dprintk (FS_DEBUG_QUEUE, "link at %p\n", qe);
+               if (qe) {
+                       qe = bus_to_virt ((long) qe);
+                       qe->next = virt_to_bus(ne);
+                       qe->flags &= ~FP_FLAGS_EPI;
+               } else
+                       write_fs (dev, FP_SA(fp->offset), virt_to_bus(ne));
+
+               write_fs (dev, FP_EA(fp->offset), virt_to_bus (ne));
+               fp->n++;   /* XXX Atomic_inc? */
+               write_fs (dev, FP_CTU(fp->offset), 1);
+       }
+
+       fs_dprintk (FS_DEBUG_QUEUE, "Added %d entries. \n", n);
+}
+
+static void __exit free_queue (struct fs_dev *dev, struct queue *txq)
+{
+       func_enter ();
+
+       write_fs (dev, Q_SA(txq->offset), 0);
+       write_fs (dev, Q_EA(txq->offset), 0);
+       write_fs (dev, Q_RP(txq->offset), 0);
+       write_fs (dev, Q_WP(txq->offset), 0);
+       /* Configuration ? */
+
+       fs_dprintk (FS_DEBUG_ALLOC, "Free queue: %p\n", txq->sa);
+       kfree (txq->sa);
+
+       func_exit ();
+}
+
+static void __exit free_freepool (struct fs_dev *dev, struct freepool *fp)
+{
+       func_enter ();
+
+       write_fs (dev, FP_CNF(fp->offset), 0);
+       write_fs (dev, FP_SA (fp->offset), 0);
+       write_fs (dev, FP_EA (fp->offset), 0);
+       write_fs (dev, FP_CNT(fp->offset), 0);
+       write_fs (dev, FP_CTU(fp->offset), 0);
+
+       func_exit ();
+}
+
+
+
+static void fs_irq (int irq, void *dev_id,  struct pt_regs * pt_regs) 
+{
+       int i;
+       u32 status;
+       struct fs_dev *dev = dev_id;
+
+       status = read_fs (dev, ISR);
+       if (!status) return;
+
+       func_enter ();
+
+#ifdef IRQ_RATE_LIMIT
+       /* Aaargh! I'm ashamed. This costs more lines-of-code than the actual 
+          interrupt routine!. (Well, used to when I wrote that comment) -- REW */
+       {
+               static int lastjif;
+               static int nintr=0;
+    
+               if (lastjif == jiffies) {
+                       if (++nintr > IRQ_RATE_LIMIT) {
+                               free_irq (dev->irq, dev_id);
+                               printk (KERN_ERR "fs: Too many interrupts. Turning off interrupt %d.\n", 
+                                       dev->irq);
+                       }
+               } else {
+                       lastjif = jiffies;
+                       nintr = 0;
+               }
+       }
+#endif
+       fs_dprintk (FS_DEBUG_QUEUE, "in intr: txq %d txrq %d\n", 
+                   read_fs (dev, Q_EA (dev->hp_txq.offset)) -
+                   read_fs (dev, Q_SA (dev->hp_txq.offset)),
+                   read_fs (dev, Q_EA (dev->tx_relq.offset)) -
+                   read_fs (dev, Q_SA (dev->tx_relq.offset)));
+
+       /* print the bits in the ISR register. */
+       if (fs_debug & FS_DEBUG_IRQ) {
+               /* The FS_DEBUG things are unneccesary here. But this way it is
+                  clear for grep that these are debug prints. */
+               fs_dprintk (FS_DEBUG_IRQ,  "IRQ status:");
+               for (i=0;i<27;i++) 
+                       if (status & (1 << i)) 
+                               fs_dprintk (FS_DEBUG_IRQ, " %s", irq_bitname[i]);
+               fs_dprintk (FS_DEBUG_IRQ, "\n");
+       }
+  
+       if (status & ISR_RBRQ0_W) {
+               fs_dprintk (FS_DEBUG_IRQ, "Iiiin-coming (0)!!!!\n");
+               process_incoming (dev, &dev->rx_rq[0]);
+               /* items mentioned on RBRQ0 are from FP 0 or 1. */
+               top_off_fp (dev, &dev->rx_fp[0], GFP_ATOMIC);
+               top_off_fp (dev, &dev->rx_fp[1], GFP_ATOMIC);
+       }
+
+       if (status & ISR_RBRQ1_W) {
+               fs_dprintk (FS_DEBUG_IRQ, "Iiiin-coming (1)!!!!\n");
+               process_incoming (dev, &dev->rx_rq[1]);
+               top_off_fp (dev, &dev->rx_fp[2], GFP_ATOMIC);
+               top_off_fp (dev, &dev->rx_fp[3], GFP_ATOMIC);
+       }
+
+       if (status & ISR_RBRQ2_W) {
+               fs_dprintk (FS_DEBUG_IRQ, "Iiiin-coming (2)!!!!\n");
+               process_incoming (dev, &dev->rx_rq[2]);
+               top_off_fp (dev, &dev->rx_fp[4], GFP_ATOMIC);
+               top_off_fp (dev, &dev->rx_fp[5], GFP_ATOMIC);
+       }
+
+       if (status & ISR_RBRQ3_W) {
+               fs_dprintk (FS_DEBUG_IRQ, "Iiiin-coming (3)!!!!\n");
+               process_incoming (dev, &dev->rx_rq[3]);
+               top_off_fp (dev, &dev->rx_fp[6], GFP_ATOMIC);
+               top_off_fp (dev, &dev->rx_fp[7], GFP_ATOMIC);
+       }
+
+       if (status & ISR_CSQ_W) {
+               fs_dprintk (FS_DEBUG_IRQ, "Command executed ok!\n");
+               process_return_queue (dev, &dev->st_q);
+       }
+
+       if (status & ISR_TBRQ_W) {
+               fs_dprintk (FS_DEBUG_IRQ, "Data tramsitted!\n");
+               process_txdone_queue (dev, &dev->tx_relq);
+       }
+
+       func_exit ();
+}
+
+
+#ifdef FS_POLL_FREQ
+static void fs_poll (unsigned long data)
+{
+       struct fs_dev *dev = (struct fs_dev *) data;
+  
+       fs_irq (0, dev, NULL);
+       dev->timer.expires = jiffies + FS_POLL_FREQ;
+       add_timer (&dev->timer);
+}
+#endif
+
+static int __init fs_init (struct fs_dev *dev)
+{
+       struct pci_dev  *pci_dev;
+       int isr, to;
+       int i;
+
+       func_enter ();
+       pci_dev = dev->pci_dev;
+
+       printk (KERN_INFO "found a FireStream %d card, base %08lx, irq%d.\n", 
+               IS_FS50(dev)?50:155,
+               pci_resource_start(pci_dev, 0), dev->pci_dev->irq);
+
+       if (fs_debug & FS_DEBUG_INIT)
+               my_hd ((unsigned char *) dev, sizeof (*dev));
+
+       undocumented_pci_fix (pci_dev);
+
+       dev->hw_base = pci_resource_start(pci_dev, 0);
+
+       dev->base = (ulong) ioremap(dev->hw_base, 0x1000);
+
+       reset_chip (dev);
+  
+       write_fs (dev, SARMODE0, 0 
+                 | (0 * SARMODE0_SHADEN) /* We don't use shadow registers. */
+                 | (1 * SARMODE0_INTMODE_READCLEAR)
+                 | (1 * SARMODE0_CWRE)
+                 | IS_FS50(dev)?SARMODE0_PRPWT_FS50_5: 
+                                SARMODE0_PRPWT_FS155_3
+                 | (1 * SARMODE0_CALSUP_1)
+                 | IS_FS50 (dev)?(0
+                                  | SARMODE0_RXVCS_32
+                                  | SARMODE0_ABRVCS_32 
+                                  | SARMODE0_TXVCS_32):
+                                 (0
+                                  | SARMODE0_RXVCS_1k
+                                  | SARMODE0_ABRVCS_1k 
+                                  | SARMODE0_TXVCS_1k));
+
+       /* 10ms * 100 is 1 second. That should be enough, as AN3:9 says it takes
+          1ms. */
+       to = 100;
+       while (--to) {
+               isr = read_fs (dev, ISR);
+
+               /* This bit is documented as "RESERVED" */
+               if (isr & ISR_INIT_ERR) {
+                       printk (KERN_ERR "Error initializing the FS... \n");
+                       return 1;
+               }
+               if (isr & ISR_INIT) {
+                       fs_dprintk (FS_DEBUG_INIT, "Ha! Initialized OK!\n");
+                       break;
+               }
+
+               /* Try again after 10ms. */
+               current->state = TASK_UNINTERRUPTIBLE;
+               schedule_timeout ((HZ+99)/100);
+       }
+
+       if (!to) {
+               printk (KERN_ERR "timeout initializing the FS... \n");
+               return 1;
+       }
+
+       /* XXX fix for fs155 */
+       dev->channel_mask = 0x1f; 
+       dev->channo = 0;
+
+       /* AN3: 10 */
+       write_fs (dev, SARMODE1, 0 
+                 | (0 * SARMODE1_DEFHEC) /* XXX PHY */
+                 | ((loopback == 1) * SARMODE1_TSTLP) /* XXX Loopback mode enable... */
+                 | (1 * SARMODE1_DCRM)
+                 | (1 * SARMODE1_DCOAM)
+                 | (0 * SARMODE1_OAMCRC)
+                 | (0 * SARMODE1_DUMPE)
+                 | (0 * SARMODE1_GPLEN) 
+                 | (0 * SARMODE1_GNAM)
+                 | (0 * SARMODE1_GVAS)
+                 | (0 * SARMODE1_GPAS)
+                 | (1 * SARMODE1_GPRI)
+                 | (0 * SARMODE1_PMS)
+                 | (0 * SARMODE1_GFCR)
+                 | (1 * SARMODE1_HECM2)
+                 | (1 * SARMODE1_HECM1)
+                 | (1 * SARMODE1_HECM0)
+                 | (1 << 12) /* That's what hang's driver does. Program to 0 */
+                 | (0 * 0xff) /* XXX FS155 */);
+
+
+       /* Cal prescale etc */
+
+       /* AN3: 11 */
+       write_fs (dev, TMCONF, 0x0000000f);
+       write_fs (dev, CALPRESCALE, 0x01010101 * num);
+       write_fs (dev, 0x80, 0x000F00E4);
+
+       /* AN3: 12 */
+       write_fs (dev, CELLOSCONF, 0
+                 | (   0 * CELLOSCONF_CEN)
+                 | (       CELLOSCONF_SC1)
+                 | (0x80 * CELLOSCONF_COBS)
+                 | (num  * CELLOSCONF_COPK)  /* Changed from 0xff to 0x5a */
+                 | (num  * CELLOSCONF_COST));/* after a hint from Hang. 
+                                              * performance jumped 50->70... */
+
+       /* Magic value by Hang */
+       write_fs (dev, CELLOSCONF_COST, 0x0B809191);
+
+       if (IS_FS50 (dev)) {
+               write_fs (dev, RAS0, RAS0_DCD_XHLT);
+               dev->atm_dev->ci_range.vpi_bits = 12;
+               dev->atm_dev->ci_range.vci_bits = 16;
+               dev->nchannels = FS50_NR_CHANNELS;
+       } else {
+               write_fs (dev, RAS0, RAS0_DCD_XHLT 
+                         | (((1 << FS155_VPI_BITS) - 1) * RAS0_VPSEL)
+                         | (((1 << FS155_VCI_BITS) - 1) * RAS0_VCSEL));
+               /* We can chose the split arbitarily. We might be able to 
+                  support more. Whatever. This should do for now. */
+               dev->atm_dev->ci_range.vpi_bits = FS155_VPI_BITS;
+               dev->atm_dev->ci_range.vci_bits = FS155_VCI_BITS;
+    
+               /* Address bits we can't use should be compared to 0. */
+               write_fs (dev, RAC, 0);
+
+               /* Manual (AN9, page 6) says ASF1=0 means compare Utopia address
+                * too.  I can't find ASF1 anywhere. Anyway, we AND with just hte
+                * other bits, then compare with 0, which is exactly what we
+                * want. */
+               write_fs (dev, RAM, (1 << (28 - FS155_VPI_BITS - FS155_VCI_BITS)) - 1);
+               dev->nchannels = FS155_NR_CHANNELS;
+       }
+       dev->atm_vccs = kmalloc (dev->nchannels * sizeof (struct atm_vcc *), 
+                                GFP_KERNEL);
+       fs_dprintk (FS_DEBUG_ALLOC, "Alloc atmvccs: %p(%d)\n", 
+                   dev->atm_vccs, dev->nchannels * sizeof (struct atm_vcc *));
+
+       if (!dev->atm_vccs) {
+               printk (KERN_WARNING "Couldn't allocate memory for VCC buffers. Woops!\n");
+               /* XXX Clean up..... */
+               return 1;
+       }
+       memset (dev->atm_vccs, 0, dev->nchannels * sizeof (struct atm_vcc *));
+
+       dev->tx_inuse = kmalloc (dev->nchannels / 8 /* bits/byte */ , GFP_KERNEL);
+       fs_dprintk (FS_DEBUG_ALLOC, "Alloc tx_inuse: %p(%d)\n", 
+                   dev->atm_vccs, dev->nchannels / 8);
+
+       if (!dev->tx_inuse) {
+               printk (KERN_WARNING "Couldn't allocate memory for tx_inuse bits!\n");
+               /* XXX Clean up..... */
+               return 1;
+       }
+       memset (dev->tx_inuse, 0, dev->nchannels / 8);
+
+       /* -- RAS1 : FS155 and 50 differ. Default (0) should be OK for both */
+       /* -- RAS2 : FS50 only: Default is OK. */
+
+       /* DMAMODE, default should be OK. -- REW */
+       write_fs (dev, DMAMR, DMAMR_TX_MODE_FULL);
+
+       init_q (dev, &dev->hp_txq, TX_PQ(TXQ_HP), TXQ_NENTRIES, 0);
+       init_q (dev, &dev->lp_txq, TX_PQ(TXQ_LP), TXQ_NENTRIES, 0);
+       init_q (dev, &dev->tx_relq, TXB_RQ, TXQ_NENTRIES, 1);
+       init_q (dev, &dev->st_q, ST_Q, TXQ_NENTRIES, 1);
+
+       for (i=0;i < FS_NR_FREE_POOLS;i++) {
+               init_fp (dev, &dev->rx_fp[i], RXB_FP(i), 
+                        rx_buf_sizes[i], rx_pool_sizes[i]);
+               top_off_fp (dev, &dev->rx_fp[i], GFP_KERNEL);
+       }
+
+
+       for (i=0;i < FS_NR_RX_QUEUES;i++)
+               init_q (dev, &dev->rx_rq[i], RXB_RQ(i), RXRQ_NENTRIES, 1);
+
+       dev->irq = pci_dev->irq;
+       if (request_irq (dev->irq, fs_irq, SA_SHIRQ, "firestream", dev)) {
+               printk (KERN_WARNING "couldn't get irq %d for firestream.\n", pci_dev->irq);
+               /* XXX undo all previous stuff... */
+               return 1;
+       }
+       fs_dprintk (FS_DEBUG_INIT, "Grabbed irq %d for dev at %p.\n", dev->irq, dev);
+  
+       /* We want to be notified of most things. Just the statistics count
+          overflows are not interesting */
+       write_fs (dev, IMR, 0
+                 | ISR_RBRQ0_W 
+                 | ISR_RBRQ1_W 
+                 | ISR_RBRQ2_W 
+                 | ISR_RBRQ3_W 
+                 | ISR_TBRQ_W
+                 | ISR_CSQ_W);
+
+       write_fs (dev, SARMODE0, 0 
+                 | (0 * SARMODE0_SHADEN) /* We don't use shadow registers. */
+                 | (1 * SARMODE0_GINT)
+                 | (1 * SARMODE0_INTMODE_READCLEAR)
+                 | (0 * SARMODE0_CWRE)
+                 | (IS_FS50(dev)?SARMODE0_PRPWT_FS50_5: 
+                                 SARMODE0_PRPWT_FS155_3)
+                 | (1 * SARMODE0_CALSUP_1)
+                 | (IS_FS50 (dev)?(0
+                                   | SARMODE0_RXVCS_32
+                                   | SARMODE0_ABRVCS_32 
+                                   | SARMODE0_TXVCS_32):
+                                  (0
+                                   | SARMODE0_RXVCS_1k
+                                   | SARMODE0_ABRVCS_1k 
+                                   | SARMODE0_TXVCS_1k))
+                 | (1 * SARMODE0_RUN));
+
+       init_phy (dev, PHY_NTC_INIT);
+
+       if (loopback == 2) {
+               write_phy (dev, 0x39, 0x000e);
+       }
+
+#ifdef FS_POLL_FREQ
+       init_timer (&dev->timer);
+       dev->timer.data = (unsigned long) dev;
+       dev->timer.function = fs_poll;
+       dev->timer.expires = jiffies + FS_POLL_FREQ;
+       add_timer (&dev->timer);
+#endif
+
+       dev->atm_dev->dev_data = dev;
+  
+       func_exit ();
+       return 0;
+}
+
+static int __init firestream_init_one (struct pci_dev *pci_dev,
+                                      const struct pci_device_id *ent) 
+{
+       struct atm_dev *atm_dev;
+       struct fs_dev *fs_dev;
+       
+       if (pci_enable_device(pci_dev)) 
+               goto err_out;
+
+       fs_dev = kmalloc (sizeof (struct fs_dev), GFP_KERNEL);
+       fs_dprintk (FS_DEBUG_ALLOC, "Alloc fs-dev: %p(%d)\n", 
+                   fs_dev, sizeof (struct fs_dev));
+       if (!fs_dev)
+               goto err_out;
+
+       memset (fs_dev, 0, sizeof (struct fs_dev));
+  
+       atm_dev = atm_dev_register("fs", &ops, -1, NULL);
+       if (!atm_dev)
+               goto err_out_free_fs_dev;
+  
+       fs_dev->pci_dev = pci_dev;
+       fs_dev->atm_dev = atm_dev;
+       fs_dev->flags = ent->driver_data;
+
+       if (fs_init(fs_dev))
+               goto err_out_free_atm_dev;
+
+       fs_dev->next = fs_boards;
+       fs_boards = fs_dev;
+       return 0;
+
+ err_out_free_atm_dev:
+       atm_dev_deregister(atm_dev);
+ err_out_free_fs_dev:
+       kfree(fs_dev);
+ err_out:
+       return -ENODEV;
+}
+
+void __devexit firestream_remove_one (struct pci_dev *pdev)
+{
+       int i;
+       struct fs_dev *dev, *nxtdev;
+       struct fs_vcc *vcc;
+       struct FS_BPENTRY *fp, *nxt;
+  
+       func_enter ();
+
+#if 0
+       printk ("hptxq:\n");
+       for (i=0;i<60;i++) {
+               printk ("%d: %08x %08x %08x %08x \n", 
+                       i, pq[qp].cmd, pq[qp].p0, pq[qp].p1, pq[qp].p2);
+               qp++;
+               if (qp >= 60) qp = 0;
+       }
+
+       printk ("descriptors:\n");
+       for (i=0;i<60;i++) {
+               printk ("%d: %p: %08x %08x %p %p\n", 
+                       i, da[qd], dq[qd].flags, dq[qd].bsa, dq[qd].skb, dq[qd].dev);
+               qd++;
+               if (qd >= 60) qd = 0;
+       }
+#endif
+
+       for (dev = fs_boards;dev != NULL;dev=nxtdev) {
+               fs_dprintk (FS_DEBUG_CLEANUP, "Releasing resources for dev at %p.\n", dev);
+
+               /* XXX Hit all the tx channels too! */
+
+               for (i=0;i < dev->nchannels;i++) {
+                       if (dev->atm_vccs[i]) {
+                               vcc = FS_VCC (dev->atm_vccs[i]);
+                               submit_command (dev,  &dev->hp_txq,
+                                               QE_CMD_TX_PURGE_INH | QE_CMD_IMM_INQ | vcc->channo, 0,0,0);
+                               submit_command (dev,  &dev->hp_txq,
+                                               QE_CMD_RX_PURGE_INH | QE_CMD_IMM_INQ | vcc->channo, 0,0,0);
+
+                       }
+               }
+
+               /* XXX Wait a while for the chip to release all buffers. */
+
+               for (i=0;i < FS_NR_FREE_POOLS;i++) {
+                       for (fp=bus_to_virt (read_fs (dev, FP_SA(dev->rx_fp[i].offset)));
+                            !(fp->flags & FP_FLAGS_EPI);fp = nxt) {
+                               fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p\n", fp->skb);
+                               dev_kfree_skb_any (fp->skb);
+                               nxt = bus_to_virt (fp->next);
+                               fs_dprintk (FS_DEBUG_ALLOC, "Free rec-d: %p\n", fp);
+                               kfree (fp);
+                       }
+                       fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p\n", fp->skb);
+                       dev_kfree_skb_any (fp->skb);
+                       fs_dprintk (FS_DEBUG_ALLOC, "Free rec-d: %p\n", fp);
+                       kfree (fp);
+               }
+
+               /* Hang the chip in "reset", prevent it clobbering memory that is
+                  no longer ours. */
+               reset_chip (dev);
+
+               fs_dprintk (FS_DEBUG_CLEANUP, "Freeing irq%d.\n", dev->irq);
+               free_irq (dev->irq, dev);
+               del_timer (&dev->timer);
+
+               atm_dev_deregister(dev->atm_dev);
+               free_queue (dev, &dev->hp_txq);
+               free_queue (dev, &dev->lp_txq);
+               free_queue (dev, &dev->tx_relq);
+               free_queue (dev, &dev->st_q);
+
+               fs_dprintk (FS_DEBUG_ALLOC, "Free atmvccs: %p\n", dev->atm_vccs);
+               kfree (dev->atm_vccs);
+
+               for (i=0;i< FS_NR_FREE_POOLS;i++)
+                       free_freepool (dev, &dev->rx_fp[i]);
+    
+               for (i=0;i < FS_NR_RX_QUEUES;i++)
+                       free_queue (dev, &dev->rx_rq[i]);
+
+               fs_dprintk (FS_DEBUG_ALLOC, "Free fs-dev: %p\n", dev);
+               nxtdev = dev->next;
+               kfree (dev);
+       }
+
+       func_exit ();
+}
+
+
+#if 0
+int __init fs_detect(void)
+{
+       struct pci_dev  *pci_dev;
+       int devs = 0;
+
+       func_enter ();
+       pci_dev = NULL;
+       while ((pci_dev = pci_find_device(PCI_VENDOR_ID_FUJITSU_ME,
+                                         PCI_DEVICE_ID_FUJITSU_FS50, 
+                                         pci_dev))) {
+               if (fs_register_and_init (pci_dev, &fs_pci_tbl[0]))
+                       break;
+               devs++;
+       }
+
+       while ((pci_dev = pci_find_device(PCI_VENDOR_ID_FUJITSU_ME,
+                                         PCI_DEVICE_ID_FUJITSU_FS155, 
+                                         pci_dev))) {
+               if (fs_register_and_init (pci_dev, FS_IS155)) 
+                       break;
+               devs++;
+       }
+       func_exit ();
+       return devs;
+}
+#else
+
+#if 0
+int __init init_PCI (void)
+{ /* Begin init_PCI */
+       
+       int pci_count;
+       printk ("init_PCI\n");
+       /*
+         memset (&firestream_driver, 0, sizeof (firestream_driver));
+         firestream_driver.name = "firestream";
+         firestream_driver.id_table = firestream_pci_tbl;
+         firestream_driver.probe = fs_register_and_init;
+       */
+       pci_count = pci_register_driver (&firestream_driver);
+       
+       if (pci_count <= 0) {
+               pci_unregister_driver (&firestream_driver);
+               pci_count = 0;
+       }
+
+       return(pci_count);
+
+} /* End init_PCI */
+#endif
+#endif
+
+/*
+#ifdef MODULE
+#define firestream_init init_module
+#endif 
+*/
+
+const static struct pci_device_id firestream_pci_tbl[] __devinitdata = {
+       { PCI_VENDOR_ID_FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS50, 
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, FS_IS50},
+       { PCI_VENDOR_ID_FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS155, 
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, FS_IS155},
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, firestream_pci_tbl);
+
+static struct pci_driver firestream_driver = {
+       name:           "firestream",
+       id_table:       firestream_pci_tbl,
+       probe:          firestream_init_one,
+       remove:         firestream_remove_one,
+};
+
+static int __init firestream_init_module (void)
+{
+       int error;
+
+       func_enter ();
+       error = pci_module_init(&firestream_driver);
+       func_exit ();
+       return error;
+}
+
+static void __exit firestream_cleanup_module(void)
+{
+       pci_unregister_driver(&firestream_driver);
+}
+
+module_init(firestream_init_module);
+module_exit(firestream_cleanup_module);
+
diff --git a/drivers/atm/firestream.h b/drivers/atm/firestream.h
new file mode 100644 (file)
index 0000000..cde9d9b
--- /dev/null
@@ -0,0 +1,505 @@
+/* drivers/atm/firestream.h - FireStream 155 (MB86697) and
+ *                            FireStream  50 (MB86695) device driver 
+ */
+/* Written & (C) 2000 by R.E.Wolff@BitWizard.nl 
+ * Copied snippets from zatm.c by Werner Almesberger, EPFL LRC/ICA 
+ * and ambassador.c Copyright (C) 1995-1999  Madge Networks Ltd 
+ */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  The GNU GPL is contained in /usr/doc/copyright/GPL on a Debian
+  system and in the file COPYING in the Linux kernel source.
+*/
+
+
+/***********************************************************************
+ *                  first the defines for the chip.                    *
+ ***********************************************************************/
+
+
+/********************* General chip parameters. ************************/
+
+#define FS_NR_FREE_POOLS   8
+#define FS_NR_RX_QUEUES    4
+
+
+/********************* queues and queue access macros ******************/
+
+
+/* A queue entry. */
+struct FS_QENTRY {
+       u32 cmd;
+       u32 p0, p1, p2;
+};
+
+
+/* A freepool entry. */
+struct FS_BPENTRY {
+       u32 flags;
+       u32 next;
+       u32 bsa;
+       u32 aal_bufsize;
+
+       /* The hardware doesn't look at this, but we need the SKB somewhere... */
+       struct sk_buff *skb;
+       struct freepool *fp;
+       struct fs_dev *dev;
+};
+
+
+#define STATUS_CODE(qe)  ((qe->cmd >> 22) & 0x3f)
+
+
+/* OFFSETS against the base of a QUEUE... */
+#define QSA     0x00
+#define QEA     0x04
+#define QRP     0x08
+#define QWP     0x0c
+#define QCNF    0x10   /* Only for Release queues! */
+/* Not for the transmit pending queue. */
+
+
+/* OFFSETS against the base of a FREE POOL... */
+#define FPCNF   0x00
+#define FPSA    0x04
+#define FPEA    0x08
+#define FPCNT   0x0c
+#define FPCTU   0x10
+
+#define Q_SA(b)     (b + QSA )
+#define Q_EA(b)     (b + QEA )
+#define Q_RP(b)     (b + QRP )
+#define Q_WP(b)     (b + QWP )
+#define Q_CNF(b)    (b + QCNF)
+
+#define FP_CNF(b)   (b + FPCNF)
+#define FP_SA(b)    (b + FPSA)
+#define FP_EA(b)    (b + FPEA)
+#define FP_CNT(b)   (b + FPCNT)
+#define FP_CTU(b)   (b + FPCTU)
+
+/* bits in a queue register. */
+#define Q_FULL      0x1
+#define Q_EMPTY     0x2
+#define Q_INCWRAP   0x4
+#define Q_ADDR_MASK 0xfffffff0
+
+/* bits in a FreePool config register */
+#define RBFP_RBS    (0x1 << 16)
+#define RBFP_RBSVAL (0x1 << 15)
+#define RBFP_CME    (0x1 << 12)
+#define RBFP_DLP    (0x1 << 11)
+#define RBFP_BFPWT  (0x1 <<  0)
+
+
+
+
+/* FireStream commands. */
+#define QE_CMD_NULL             (0x00 << 22)
+#define QE_CMD_REG_RD           (0x01 << 22)
+#define QE_CMD_REG_RDM          (0x02 << 22)
+#define QE_CMD_REG_WR           (0x03 << 22)
+#define QE_CMD_REG_WRM          (0x04 << 22)
+#define QE_CMD_CONFIG_TX        (0x05 << 22)
+#define QE_CMD_CONFIG_RX        (0x06 << 22)
+#define QE_CMD_PRP_RD           (0x07 << 22)
+#define QE_CMD_PRP_RDM          (0x2a << 22)
+#define QE_CMD_PRP_WR           (0x09 << 22)
+#define QE_CMD_PRP_WRM          (0x2b << 22)
+#define QE_CMD_RX_EN            (0x0a << 22)
+#define QE_CMD_RX_PURGE         (0x0b << 22)
+#define QE_CMD_RX_PURGE_INH     (0x0c << 22)
+#define QE_CMD_TX_EN            (0x0d << 22)
+#define QE_CMD_TX_PURGE         (0x0e << 22)
+#define QE_CMD_TX_PURGE_INH     (0x0f << 22)
+#define QE_CMD_RST_CG           (0x10 << 22)
+#define QE_CMD_SET_CG           (0x11 << 22)
+#define QE_CMD_RST_CLP          (0x12 << 22)
+#define QE_CMD_SET_CLP          (0x13 << 22)
+#define QE_CMD_OVERRIDE         (0x14 << 22)
+#define QE_CMD_ADD_BFP          (0x15 << 22)
+#define QE_CMD_DUMP_TX          (0x16 << 22)
+#define QE_CMD_DUMP_RX          (0x17 << 22)
+#define QE_CMD_LRAM_RD          (0x18 << 22)
+#define QE_CMD_LRAM_RDM         (0x28 << 22)
+#define QE_CMD_LRAM_WR          (0x19 << 22)
+#define QE_CMD_LRAM_WRM         (0x29 << 22)
+#define QE_CMD_LRAM_BSET        (0x1a << 22)
+#define QE_CMD_LRAM_BCLR        (0x1b << 22)
+#define QE_CMD_CONFIG_SEGM      (0x1c << 22)
+#define QE_CMD_READ_SEGM        (0x1d << 22)
+#define QE_CMD_CONFIG_ROUT      (0x1e << 22)
+#define QE_CMD_READ_ROUT        (0x1f << 22)
+#define QE_CMD_CONFIG_TM        (0x20 << 22)
+#define QE_CMD_READ_TM          (0x21 << 22)
+#define QE_CMD_CONFIG_TXBM      (0x22 << 22)
+#define QE_CMD_READ_TXBM        (0x23 << 22)
+#define QE_CMD_CONFIG_RXBM      (0x24 << 22)
+#define QE_CMD_READ_RXBM        (0x25 << 22)
+#define QE_CMD_CONFIG_REAS      (0x26 << 22)
+#define QE_CMD_READ_REAS        (0x27 << 22)
+
+#define QE_TRANSMIT_DE          (0x0 << 30)
+#define QE_CMD_LINKED           (0x1 << 30)
+#define QE_CMD_IMM              (0x2 << 30)
+#define QE_CMD_IMM_INQ          (0x3 << 30)
+
+#define TD_EPI                  (0x1 << 27)
+#define TD_COMMAND              (0x1 << 28)
+
+#define TD_DATA                 (0x0 << 29)
+#define TD_RM_CELL              (0x1 << 29)
+#define TD_OAM_CELL             (0x2 << 29)
+#define TD_OAM_CELL_SEGMENT     (0x3 << 29)
+
+#define TD_BPI                  (0x1 << 20)
+
+#define FP_FLAGS_EPI            (0x1 << 27)
+
+
+#define TX_PQ(i)  (0x00  + (i) * 0x10)
+#define TXB_RQ    (0x20)
+#define ST_Q      (0x48)
+#define RXB_FP(i) (0x90  + (i) * 0x14)
+#define RXB_RQ(i) (0x134 + (i) * 0x14)
+
+
+#define TXQ_HP 0
+#define TXQ_LP 1
+
+/* Phew. You don't want to know how many revisions these simple queue
+ * address macros went through before I got them nice and compact as
+ * they are now. -- REW
+ */
+
+
+/* And now for something completely different: 
+ * The rest of the registers... */
+
+
+#define CMDR0 0x34
+#define CMDR1 0x38
+#define CMDR2 0x3c
+#define CMDR3 0x40
+
+
+#define SARMODE0     0x5c
+
+#define SARMODE0_TXVCS_0    (0x0 << 0)
+#define SARMODE0_TXVCS_1k   (0x1 << 0)
+#define SARMODE0_TXVCS_2k   (0x2 << 0)
+#define SARMODE0_TXVCS_4k   (0x3 << 0)
+#define SARMODE0_TXVCS_8k   (0x4 << 0)
+#define SARMODE0_TXVCS_16k  (0x5 << 0)
+#define SARMODE0_TXVCS_32k  (0x6 << 0)
+#define SARMODE0_TXVCS_64k  (0x7 << 0)
+#define SARMODE0_TXVCS_32   (0x8 << 0)
+
+#define SARMODE0_ABRVCS_0   (0x0 << 4)
+#define SARMODE0_ABRVCS_512 (0x1 << 4)
+#define SARMODE0_ABRVCS_1k  (0x2 << 4)
+#define SARMODE0_ABRVCS_2k  (0x3 << 4)
+#define SARMODE0_ABRVCS_4k  (0x4 << 4)
+#define SARMODE0_ABRVCS_8k  (0x5 << 4)
+#define SARMODE0_ABRVCS_16k (0x6 << 4)
+#define SARMODE0_ABRVCS_32k (0x7 << 4)
+#define SARMODE0_ABRVCS_32  (0x9 << 4) /* The others are "8", this one really has to 
+                                         be 9. Tell me you don't believe me. -- REW */
+
+#define SARMODE0_RXVCS_0    (0x0 << 8)
+#define SARMODE0_RXVCS_1k   (0x1 << 8)
+#define SARMODE0_RXVCS_2k   (0x2 << 8)
+#define SARMODE0_RXVCS_4k   (0x3 << 8)
+#define SARMODE0_RXVCS_8k   (0x4 << 8)
+#define SARMODE0_RXVCS_16k  (0x5 << 8)
+#define SARMODE0_RXVCS_32k  (0x6 << 8)
+#define SARMODE0_RXVCS_64k  (0x7 << 8)
+#define SARMODE0_RXVCS_32   (0x8 << 8) 
+
+#define SARMODE0_CALSUP_1  (0x0 << 12)
+#define SARMODE0_CALSUP_2  (0x1 << 12)
+#define SARMODE0_CALSUP_3  (0x2 << 12)
+#define SARMODE0_CALSUP_4  (0x3 << 12)
+
+#define SARMODE0_PRPWT_FS50_0  (0x0 << 14)
+#define SARMODE0_PRPWT_FS50_2  (0x1 << 14)
+#define SARMODE0_PRPWT_FS50_5  (0x2 << 14)
+#define SARMODE0_PRPWT_FS50_11 (0x3 << 14)
+
+#define SARMODE0_PRPWT_FS155_0 (0x0 << 14)
+#define SARMODE0_PRPWT_FS155_1 (0x1 << 14)
+#define SARMODE0_PRPWT_FS155_2 (0x2 << 14)
+#define SARMODE0_PRPWT_FS155_3 (0x3 << 14)
+
+#define SARMODE0_SRTS0     (0x1 << 23)
+#define SARMODE0_SRTS1     (0x1 << 24)
+
+#define SARMODE0_RUN       (0x1 << 25)
+
+#define SARMODE0_UNLOCK    (0x1 << 26)
+#define SARMODE0_CWRE      (0x1 << 27)
+
+
+#define SARMODE0_INTMODE_READCLEAR          (0x0 << 28)
+#define SARMODE0_INTMODE_READNOCLEAR        (0x1 << 28)
+#define SARMODE0_INTMODE_READNOCLEARINHIBIT (0x2 << 28)
+#define SARMODE0_INTMODE_READCLEARINHIBIT   (0x3 << 28)  /* Tell me you don't believe me. */
+
+#define SARMODE0_GINT      (0x1 << 30)
+#define SARMODE0_SHADEN    (0x1 << 31)
+
+
+#define SARMODE1     0x60
+
+
+#define SARMODE1_TRTL_SHIFT 0   /* Program to 0 */
+#define SARMODE1_RRTL_SHIFT 4   /* Program to 0 */
+
+#define SARMODE1_TAGM       (0x1 <<  8)  /* Program to 0 */
+
+#define SARMODE1_HECM0      (0x1 <<  9)
+#define SARMODE1_HECM1      (0x1 << 10)
+#define SARMODE1_HECM2      (0x1 << 11)
+
+#define SARMODE1_GFCE       (0x1 << 14)
+#define SARMODE1_GFCR       (0x1 << 15)
+#define SARMODE1_PMS        (0x1 << 18)
+#define SARMODE1_GPRI       (0x1 << 19)
+#define SARMODE1_GPAS       (0x1 << 20)
+#define SARMODE1_GVAS       (0x1 << 21)
+#define SARMODE1_GNAM       (0x1 << 22)
+#define SARMODE1_GPLEN      (0x1 << 23)
+#define SARMODE1_DUMPE      (0x1 << 24)
+#define SARMODE1_OAMCRC     (0x1 << 25)
+#define SARMODE1_DCOAM      (0x1 << 26)
+#define SARMODE1_DCRM       (0x1 << 27)
+#define SARMODE1_TSTLP      (0x1 << 28)
+#define SARMODE1_DEFHEC     (0x1 << 29)
+
+
+#define ISR      0x64
+#define IUSR     0x68
+#define IMR      0x6c
+
+#define ISR_LPCO          (0x1 <<  0)
+#define ISR_DPCO          (0x1 <<  1)
+#define ISR_RBRQ0_W       (0x1 <<  2)
+#define ISR_RBRQ1_W       (0x1 <<  3)
+#define ISR_RBRQ2_W       (0x1 <<  4)
+#define ISR_RBRQ3_W       (0x1 <<  5)
+#define ISR_RBRQ0_NF      (0x1 <<  6)
+#define ISR_RBRQ1_NF      (0x1 <<  7)
+#define ISR_RBRQ2_NF      (0x1 <<  8)
+#define ISR_RBRQ3_NF      (0x1 <<  9)
+#define ISR_BFP_SC        (0x1 << 10)
+#define ISR_INIT          (0x1 << 11)
+#define ISR_INIT_ERR      (0x1 << 12) /* Documented as "reserved" */
+#define ISR_USCEO         (0x1 << 13)
+#define ISR_UPEC0         (0x1 << 14)
+#define ISR_VPFCO         (0x1 << 15)
+#define ISR_CRCCO         (0x1 << 16)
+#define ISR_HECO          (0x1 << 17)
+#define ISR_TBRQ_W        (0x1 << 18)
+#define ISR_TBRQ_NF       (0x1 << 19)
+#define ISR_CTPQ_E        (0x1 << 20)
+#define ISR_GFC_C0        (0x1 << 21)
+#define ISR_PCI_FTL       (0x1 << 22)
+#define ISR_CSQ_W         (0x1 << 23)
+#define ISR_CSQ_NF        (0x1 << 24)
+#define ISR_EXT_INT       (0x1 << 25)
+#define ISR_RXDMA_S       (0x1 << 26)
+
+
+#define TMCONF 0x78
+/* Bits? */
+
+
+#define CALPRESCALE 0x7c
+/* Bits? */
+
+#define CELLOSCONF 0x84
+#define CELLOSCONF_COTS   (0x1 << 28)
+#define CELLOSCONF_CEN    (0x1 << 27)
+#define CELLOSCONF_SC8    (0x3 << 24)
+#define CELLOSCONF_SC4    (0x2 << 24)
+#define CELLOSCONF_SC2    (0x1 << 24)
+#define CELLOSCONF_SC1    (0x0 << 24)
+
+#define CELLOSCONF_COBS   (0x1 << 16)
+#define CELLOSCONF_COPK   (0x1 <<  8)
+#define CELLOSCONF_COST   (0x1 <<  0)
+/* Bits? */
+
+
+#define RAS0 0x1bc
+#define RAS0_DCD_XHLT (0x1 << 31)
+
+#define RAS0_VPSEL    (0x1 << 16)
+#define RAS0_VCSEL    (0x1 <<  0)
+
+
+#define DMAMR 0x1cc
+#define DMAMR_TX_MODE_FULL (0x0 << 0)
+#define DMAMR_TX_MODE_PART (0x1 << 0)
+#define DMAMR_TX_MODE_NONE (0x2 << 0) /* And 3 */
+
+
+
+struct fs_transmit_config {
+       u32 flags;
+       u32 atm_hdr;
+       u32 TMC[4];
+       u32 spec;
+       u32 rtag[3];
+};
+
+#define TC_FLAGS_AAL5      (0x0 << 29)
+#define TC_FLAGS_PACKET    (0x0) 
+#define TC_FLAGS_TYPE_ABR  (0x0 << 22)
+#define TC_FLAGS_TYPE_CBR  (0x1 << 22)
+#define TC_FLAGS_TYPE_VBR  (0x2 << 22)
+#define TC_FLAGS_TYPE_UBR  (0x3 << 22)
+#define TC_FLAGS_CAL0      (0x0 << 20)
+#define TC_FLAGS_CAL1      (0x1 << 20)
+#define TC_FLAGS_CAL2      (0x2 << 20)
+#define TC_FLAGS_CAL3      (0x3 << 20)
+
+
+#define RC_FLAGS_NAM        (0x1 << 13)
+#define RC_FLAGS_RXBM_PSB   (0x0 << 14)
+#define RC_FLAGS_RXBM_CIF   (0x1 << 14)
+#define RC_FLAGS_RXBM_PMB   (0x2 << 14)
+#define RC_FLAGS_RXBM_STR   (0x4 << 14)
+#define RC_FLAGS_RXBM_SAF   (0x6 << 14)
+#define RC_FLAGS_RXBM_POS   (0x6 << 14)
+#define RC_FLAGS_BFPS       (0x1 << 17)
+
+#define RC_FLAGS_BFPS_BFP   (0x1 << 17)
+
+#define RC_FLAGS_BFPS_BFP0  (0x0 << 17)
+#define RC_FLAGS_BFPS_BFP1  (0x1 << 17)
+#define RC_FLAGS_BFPS_BFP2  (0x2 << 17)
+#define RC_FLAGS_BFPS_BFP3  (0x3 << 17)
+#define RC_FLAGS_BFPS_BFP4  (0x4 << 17)
+#define RC_FLAGS_BFPS_BFP5  (0x5 << 17)
+#define RC_FLAGS_BFPS_BFP6  (0x6 << 17)
+#define RC_FLAGS_BFPS_BFP7  (0x7 << 17)
+#define RC_FLAGS_BFPS_BFP01 (0x8 << 17)
+#define RC_FLAGS_BFPS_BFP23 (0x9 << 17)
+#define RC_FLAGS_BFPS_BFP45 (0xa << 17)
+#define RC_FLAGS_BFPS_BFP67 (0xb << 17)
+#define RC_FLAGS_BFPS_BFP07 (0xc << 17)
+#define RC_FLAGS_BFPS_BFP27 (0xd << 17)
+#define RC_FLAGS_BFPS_BFP47 (0xe << 17)
+
+#define RC_FLAGS_BFPS       (0x1 << 17)
+#define RC_FLAGS_BFPP       (0x1 << 21)
+#define RC_FLAGS_TEVC       (0x1 << 22)
+#define RC_FLAGS_TEP        (0x1 << 23)
+#define RC_FLAGS_AAL5       (0x0 << 24)
+#define RC_FLAGS_TRANSP     (0x1 << 24)
+#define RC_FLAGS_TRANSC     (0x2 << 24)
+#define RC_FLAGS_ML         (0x1 << 27)
+#define RC_FLAGS_TRBRM      (0x1 << 28)
+#define RC_FLAGS_PRI        (0x1 << 29)
+#define RC_FLAGS_HOAM       (0x1 << 30)
+#define RC_FLAGS_CRC10      (0x1 << 31)
+
+
+#define RAC 0x1c8
+#define RAM 0x1c4
+
+
+
+/************************************************************************
+ *         Then the datastructures that the DRIVER uses.                *
+ ************************************************************************/
+
+#define TXQ_NENTRIES  32
+#define RXRQ_NENTRIES 1024
+
+
+struct fs_vcc {
+       int channo;
+       wait_queue_head_t close_wait;
+       struct sk_buff *last_skb;
+};
+
+
+struct queue {
+       struct FS_QENTRY *sa, *ea;  
+       int offset;
+};
+
+struct freepool {
+       int offset;
+       int bufsize;
+       int nr_buffers;
+       int n;
+};
+
+
+struct fs_dev {
+       struct fs_dev *next;            /* other FS devices */
+       int flags;
+
+       unsigned char irq;              /* IRQ */
+       struct pci_dev *pci_dev;        /* PCI stuff */
+       struct atm_dev *atm_dev;
+       struct timer_list timer;
+
+       unsigned long hw_base;          /* mem base address */
+       unsigned long base;             /* Mapping of base address */
+       int channo;
+       unsigned long channel_mask;
+
+       struct queue    hp_txq, lp_txq, tx_relq, st_q;
+       struct freepool rx_fp[FS_NR_FREE_POOLS];
+       struct queue    rx_rq[FS_NR_RX_QUEUES];
+
+       int nchannels;
+       struct atm_vcc **atm_vccs;
+       void *tx_inuse;
+       int ntxpckts;
+};
+
+
+
+
+/* Number of channesl that the FS50 supports. */
+#define FS50_CHANNEL_BITS  5
+#define FS50_NR_CHANNELS      (1 << FS50_CHANNEL_BITS)
+
+         
+#define FS_DEV(atm_dev) ((struct fs_dev *) (atm_dev)->dev_data)
+#define FS_VCC(atm_vcc) ((struct fs_vcc *) (atm_vcc)->dev_data)
+
+
+#define FS_IS50  0x1
+#define FS_IS155 0x2
+
+#define IS_FS50(dev)  (dev->flags & FS_IS50)
+#define IS_FS155(dev) (dev->flags & FS_IS155)
+/* Within limits this is user-configurable. */
+/* Note: Currently the sum (10 -> 1k channels) is hardcoded in the driver. */
+#define FS155_VPI_BITS 5
+#define FS155_VCI_BITS 5
+
+#define FS155_CHANNEL_BITS  (FS155_VPI_BITS + FS155_VCI_BITS)
+#define FS155_NR_CHANNELS   (1 << FS155_CHANNEL_BITS)
index 5d4fdd543930e452fdca99ec3604b3d61791cb4e..4d51e762b2c264c02f401ed9744c8945b0cb74de 100644 (file)
@@ -1407,8 +1407,6 @@ fore200e_open(struct atm_vcc *vcc, short vpi, int vci)
     struct fore200e*     fore200e = FORE200E_DEV(vcc->dev);
     struct fore200e_vcc* fore200e_vcc;
     
-    MOD_INC_USE_COUNT;
-
     /* find a free VPI/VCI */
     fore200e_walk_vccs(vcc, &vpi, &vci);
 
@@ -1416,10 +1414,8 @@ fore200e_open(struct atm_vcc *vcc, short vpi, int vci)
     vcc->vci = vci;
 
     /* ressource checking only? */
-    if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) {
-       MOD_DEC_USE_COUNT;
+    if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC)
        return 0;
-    }
 
     set_bit(ATM_VF_ADDR, &vcc->flags);
     vcc->itf    = vcc->dev->number;
@@ -1437,7 +1433,6 @@ fore200e_open(struct atm_vcc *vcc, short vpi, int vci)
        down(&fore200e->rate_sf);
        if (fore200e->available_cell_rate < vcc->qos.txtp.max_pcr) {
            up(&fore200e->rate_sf);
-           MOD_DEC_USE_COUNT;
            return -EAGAIN;
        }
        /* reserving the pseudo-CBR bandwidth at this point grants us
@@ -1454,7 +1449,6 @@ fore200e_open(struct atm_vcc *vcc, short vpi, int vci)
        down(&fore200e->rate_sf);
        fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
        up(&fore200e->rate_sf);
-       MOD_DEC_USE_COUNT;
        return -ENOMEM;
     }
 
@@ -1465,7 +1459,6 @@ fore200e_open(struct atm_vcc *vcc, short vpi, int vci)
        down(&fore200e->rate_sf);
        fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
        up(&fore200e->rate_sf);
-       MOD_DEC_USE_COUNT;
        return -EBUSY;
     }
     
@@ -1498,10 +1491,6 @@ fore200e_close(struct atm_vcc* vcc)
     
     fore200e_activate_vcin(fore200e, 0, vcc, 0);
     
-#ifdef MODULE
-    MOD_DEC_USE_COUNT;
-#endif
-       
     kfree(FORE200E_VCC(vcc));
        
     if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) {
@@ -2599,8 +2588,6 @@ fore200e_detect(void)
 
     printk(FORE200E "FORE Systems 200E-series driver - version " FORE200E_VERSION "\n");
 
-    MOD_INC_USE_COUNT;
-
     /* for each configured bus interface */
     for (link = 0, bus = fore200e_bus; bus->model_name; bus++) {
 
@@ -2626,9 +2613,6 @@ fore200e_detect(void)
        }
     }
 
-    if (link <= 0)
-       MOD_DEC_USE_COUNT;
-
     return link;
 }
 
@@ -2943,21 +2927,15 @@ module_exit(fore200e_module_cleanup);
 
 static const struct atmdev_ops fore200e_ops =
 {
-    NULL, /* fore200e_dev_close   */
-    fore200e_open,
-    fore200e_close,
-    fore200e_ioctl,
-    fore200e_getsockopt,
-    fore200e_setsockopt,
-    fore200e_send,
-    NULL, /* fore200e_sg_send,    */
-    NULL, /* fore200e_send_oam,   */
-    NULL, /* fore200e_phy_put,    */
-    NULL, /* fore200e_phy_get,    */
-    NULL, /* fore200e_feedback,   */
-    fore200e_change_qos,
-    NULL, /* fore200e_free_rx_skb */
-    fore200e_proc_read
+       open:         fore200e_open,
+       close:        fore200e_close,
+       ioctl:        fore200e_ioctl,
+       getsockopt:   fore200e_getsockopt,
+       setsockopt:   fore200e_setsockopt,
+       send:         fore200e_send,
+       change_qos:   fore200e_change_qos,
+       proc_read:    fore200e_proc_read,
+       owner:        THIS_MODULE,
 };
 
 
index 913b6f2edfdbf10f6da2fb723ba9a73d0ff6dfdb..3a5cf5f9d8024d03c4e7f76a9ae13d1aee691c21 100644 (file)
@@ -2491,15 +2491,10 @@ static int hrz_open (struct atm_vcc * atm_vcc, short vpi, int vci) {
     return -EINVAL;
   }
   
-  // prevent module unload while sleeping (kmalloc)
-  // doing this any earlier would complicate more error return paths
-  MOD_INC_USE_COUNT;
-  
   // get space for our vcc stuff and copy parameters into it
   vccp = kmalloc (sizeof(hrz_vcc), GFP_KERNEL);
   if (!vccp) {
     PRINTK (KERN_ERR, "out of memory!");
-    MOD_DEC_USE_COUNT;
     return -ENOMEM;
   }
   *vccp = vcc;
@@ -2531,7 +2526,6 @@ static int hrz_open (struct atm_vcc * atm_vcc, short vpi, int vci) {
   if (error) {
     PRINTD (DBG_QOS|DBG_VCC, "insufficient cell rate resources");
     kfree (vccp);
-    MOD_DEC_USE_COUNT;
     return error;
   }
   
@@ -2550,7 +2544,6 @@ static int hrz_open (struct atm_vcc * atm_vcc, short vpi, int vci) {
       error = hrz_open_rx (dev, channel);
     if (error) {
       kfree (vccp);
-      MOD_DEC_USE_COUNT;
       return error;
     }
     // this link allows RX frames through
@@ -2620,7 +2613,6 @@ static void hrz_close (struct atm_vcc * atm_vcc) {
   kfree (vcc);
   // say the VPI/VCI is free again
   clear_bit(ATM_VF_ADDR,&atm_vcc->flags);
-  MOD_DEC_USE_COUNT;
 }
 
 #if 0
@@ -2751,7 +2743,8 @@ static const struct atmdev_ops hrz_ops = {
   close:       hrz_close,
   send:                hrz_send,
   sg_send:     hrz_sg_send,
-  proc_read:   hrz_proc_read
+  proc_read:   hrz_proc_read,
+  owner:       THIS_MODULE,
 };
 
 static int __init hrz_probe (void) {
index 2187039d44ec5fa265ebab43e37f50649f29e603..e2300a8450abd8ccffd2d15ebe248614ca89d602 100644 (file)
@@ -3143,7 +3143,8 @@ static const struct atmdev_ops ops = {
        phy_put:        ia_phy_put,  
        phy_get:        ia_phy_get,  
        change_qos:     ia_change_qos,  
-        proc_read:     ia_proc_read
+       proc_read:      ia_proc_read,
+       owner:          THIS_MODULE,
 };  
          
   
@@ -3219,7 +3220,6 @@ int init_module(void)
                printk(KERN_ERR DEV_LABEL ": no adapter found\n");  
                return -ENXIO;  
        }  
-       // MOD_INC_USE_COUNT; 
        ia_timer.expires = jiffies + 3*HZ;
        add_timer(&ia_timer); 
    
@@ -3235,7 +3235,6 @@ void cleanup_module(void)
         int i, j= 0;
  
        IF_EVENT(printk(">ia cleanup_module\n");)  
-        // MOD_DEC_USE_COUNT;
        if (MOD_IN_USE)  
                printk("ia: module in use\n");  
         del_timer(&ia_timer);
index 8b6d71237fd988d34bd64b05826ce65f895f57c1..7e9dc5ee21ac940a43c9e9dd0a8e5c09ae2c0f0b 100644 (file)
@@ -268,7 +268,8 @@ static struct atmdev_ops atm_ops =
    send:       ns_send,
    phy_put:    ns_phy_put,
    phy_get:    ns_phy_get,
-   proc_read:  ns_proc_read
+   proc_read:  ns_proc_read,
+   owner:      THIS_MODULE,
 };
 static struct timer_list ns_timer;
 static char *mac[NS_MAX_CARDS];
@@ -1633,7 +1634,6 @@ static int ns_open(struct atm_vcc *vcc, short vpi, int vci)
    }
    
    set_bit(ATM_VF_READY,&vcc->flags);
-   MOD_INC_USE_COUNT;
    return 0;
 }
 
@@ -1762,7 +1762,6 @@ static void ns_close(struct atm_vcc *vcc)
    vcc->dev_data = NULL;
    clear_bit(ATM_VF_PARTIAL,&vcc->flags);
    clear_bit(ATM_VF_ADDR,&vcc->flags);
-   MOD_DEC_USE_COUNT;
 
 #ifdef RX_DEBUG
    {
index 3e8c404df067d3ef78f7b09d4aef3c589a22a437..acd3402f89c2429f2cb2f4948b4c8748a801123a 100644 (file)
@@ -35,7 +35,6 @@ static DECLARE_MUTEX(tmp_buf_sem);
 
 static int gs_debug;
 
-
 #ifdef DEBUG
 #define gs_dprintk(f, str...) if (gs_debug & f) printk (str)
 #else
@@ -583,7 +582,7 @@ void gs_do_softint(void *private_)
 }
 
 
-int block_til_ready(void *port_, struct file * filp)
+int gs_block_til_ready(void *port_, struct file * filp)
 {
        struct gs_port *port = port_;
        DECLARE_WAITQUEUE(wait, current);
@@ -600,7 +599,7 @@ int block_til_ready(void *port_, struct file * filp)
 
        if (!tty) return 0;
 
-       gs_dprintk (GS_DEBUG_BTR, "Entering block_till_ready.\n"); 
+       gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); 
        /*
         * If the device is in the middle of being closed, then block
         * until it's done, and then try again.
@@ -1070,7 +1069,7 @@ EXPORT_SYMBOL(gs_stop);
 EXPORT_SYMBOL(gs_start);
 EXPORT_SYMBOL(gs_hangup);
 EXPORT_SYMBOL(gs_do_softint);
-EXPORT_SYMBOL(block_til_ready);
+EXPORT_SYMBOL(gs_block_til_ready);
 EXPORT_SYMBOL(gs_close);
 EXPORT_SYMBOL(gs_set_termios);
 EXPORT_SYMBOL(gs_init_port);
index b015640308390aaa8b191806bf8f7b139b878aaf..f7083afeeca05475b6efd0aeed25a72c0739d6a8 100644 (file)
@@ -55,6 +55,7 @@
 #define TIMER_MARGIN   50      /* steps of 0.6sec, 2<n<64. Default is 30 seconds */
 
 static unsigned int ACPIBASE;
+static spinlock_t tco_lock;    /* Guards the hardware */
 
 static int i810_margin = TIMER_MARGIN; /* steps of 0.6sec */
 
@@ -79,10 +80,13 @@ static int tco_timer_start (void)
 {
        unsigned char val;
 
+       spin_lock(&tco_lock);
        val = inb (TCO1_CNT + 1);
        val &= 0xf7;
        outb (val, TCO1_CNT + 1);
        val = inb (TCO1_CNT + 1);
+       spin_unlock(&tco_lock);
+       
        if (val & 0x08)
                return -1;
        return 0;
@@ -95,10 +99,13 @@ static int tco_timer_stop (void)
 {
        unsigned char val;
 
+       spin_lock(&tco_lock);
        val = inb (TCO1_CNT + 1);
        val |= 0x08;
        outb (val, TCO1_CNT + 1);
        val = inb (TCO1_CNT + 1);
+       spin_unlock(&tco_lock);
+       
        if ((val & 0x08) == 0)
                return -1;
        return 0;
@@ -115,12 +122,15 @@ static int tco_timer_settimer (unsigned char tmrval)
        /* "Values of 0h-3h are ignored and should not be attempted" */
        if (tmrval > 0x3f || tmrval < 0x03)
                return -1;
-
+       
+       spin_lock(&tco_lock);
        val = inb (TCO1_TMR);
        val &= 0xc0;
        val |= tmrval;
        outb (val, TCO1_TMR);
        val = inb (TCO1_TMR);
+       spin_unlock(&tco_lock);
+       
        if ((val & 0x3f) != tmrval)
                return -1;
 
@@ -128,11 +138,15 @@ static int tco_timer_settimer (unsigned char tmrval)
 }
 
 /*
- * Reload (trigger) the timer
+ * Reload (trigger) the timer. Lock is needed so we dont reload it during
+ * a reprogramming event
  */
 static void tco_timer_reload (void)
 {
+       spin_lock(&tco_lock);
        outb (0x01, TCO1_RLD);
+       spin_unlock(&tco_lock);
 }
 
 /*
@@ -285,6 +299,7 @@ static struct miscdevice i810tco_miscdev = {
 
 static int __init watchdog_init (void)
 {
+       spin_lock_init(&tco_lock);
        if (!i810tco_getdevice () || i810tco_pci == NULL)
                return -ENODEV;
        if (!request_region (TCOBASE, 0x10, "i810 TCO")) {
index 582503ec3428bfc2efa7f7bc0f23222a8a01ebda..4010973c74f1eff27ae2fc865daf5ad95a18fc96 100644 (file)
@@ -1823,8 +1823,7 @@ static void doevent(int crd)
  */
 static void pcxxdelay(int msec)
 {
-       while(msec-- > 0)
-               __delay(loops_per_sec/1000);
+       mdelay(mseconds);
 }
 
 
index 01812ecb0096e85649466114f835f7c212c0d4c2..c14fa8487a2da79e7376cd82a46bcdd86c5b071c 100644 (file)
@@ -839,7 +839,7 @@ static int sci_open(struct tty_struct * tty, struct file * filp)
                MOD_INC_USE_COUNT;
        }
 
-       retval = block_til_ready(port, filp);
+       retval = gs_block_til_ready(port, filp);
 
        if (retval) {
                MOD_DEC_USE_COUNT;
index 9026421513ed0e8d1020bf1335487f02a55f95f4..024bada51198d26f10a4961a2d2ea1c1966173a6 100644 (file)
 #include <linux/tqueue.h>
 #include <linux/version.h>
 #include <linux/pci.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
+#include <linux/init.h>
 #include <linux/miscdevice.h>
 
 /* The 3.0.0 version of sxboards/sxwindow.h  uses BYTE and WORD.... */
@@ -313,12 +314,12 @@ static struct tty_struct * sx_table[SX_NPORTS];
 static struct termios ** sx_termios;
 static struct termios ** sx_termios_locked;
 
-struct sx_board boards[SX_NBOARDS];
-struct sx_port *sx_ports;
-int sx_refcount;
-int sx_initialized;
-int sx_nports;
-int sx_debug;
+static struct sx_board boards[SX_NBOARDS];
+static struct sx_port *sx_ports;
+static int sx_refcount;
+static int sx_initialized;
+static int sx_nports;
+static int sx_debug;
 
 
 /* You can have the driver poll your card. 
@@ -329,24 +330,24 @@ int sx_debug;
       the driver misses an interrupt (report this if it DOES happen to you!)
       everything will continue to work.... 
  */
-int sx_poll = 1;
-int sx_slowpoll;
+static int sx_poll = 1;
+static int sx_slowpoll;
 
 /* The card limits the number of interrupts per second. 
    At 115k2 "100" should be sufficient. 
    If you're using higher baudrates, you can increase this...
  */
 
-int sx_maxints = 100;
+static int sx_maxints = 100;
 
 /* These are the only open spaces in my computer. Yours may have more
    or less.... -- REW 
    duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
 */
-int sx_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
-                       0xc8000, 0xd8000, 0xe8000};
-int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
-                       0xc8000, 0xd8000, 0xe8000, 0xa0000};
+static int sx_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
+                              0xc8000, 0xd8000, 0xe8000};
+static int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
+                              0xc8000, 0xd8000, 0xe8000, 0xa0000};
 
 #define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int))
 #define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int))
@@ -354,10 +355,8 @@ int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000,
 
 /* Set the mask to all-ones. This alas, only supports 32 interrupts. 
    Some architectures may need more. */
-int sx_irqmask = -1;
+static int sx_irqmask = -1;
 
-#ifndef TWO_ZERO
-#ifdef MODULE
 MODULE_PARM(sx_probe_addrs, "i");
 MODULE_PARM(si_probe_addrs, "i");
 MODULE_PARM(sx_poll, "i");
@@ -365,8 +364,6 @@ MODULE_PARM(sx_slowpoll, "i");
 MODULE_PARM(sx_maxints, "i");
 MODULE_PARM(sx_debug, "i");
 MODULE_PARM(sx_irqmask, "i");
-#endif
-#endif
 
 static struct real_driver sx_real_driver = {
        sx_disable_tx_interrupts,
@@ -379,7 +376,6 @@ static struct real_driver sx_real_driver = {
        sx_chars_in_buffer,
        sx_close,
        sx_hungup,
-       NULL
 };
 
 
@@ -421,7 +417,7 @@ static struct file_operations sx_fw_fops = {
        ioctl:          sx_fw_ioctl,
 };
 
-struct miscdevice sx_fw_device = {
+static struct miscdevice sx_fw_device = {
        SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops
 };
 
@@ -488,32 +484,30 @@ static void my_hd (unsigned char *addr, int len)
 
 /* This needs redoing for Alpha -- REW -- Done. */
 
-inline void write_sx_byte (struct sx_board *board, int offset, u8 byte)
+static inline void write_sx_byte (struct sx_board *board, int offset, u8 byte)
 {
        writeb (byte, board->base+offset);
 }
 
-inline u8 read_sx_byte (struct sx_board *board, int offset)
+static inline u8 read_sx_byte (struct sx_board *board, int offset)
 {
        return readb (board->base+offset);
 }
 
 
-inline void write_sx_word (struct sx_board *board, int offset, u16 word)
+static inline void write_sx_word (struct sx_board *board, int offset, u16 word)
 {
        writew (word, board->base+offset);
 }
 
-inline u16 read_sx_word (struct sx_board *board, int offset)
+static inline u16 read_sx_word (struct sx_board *board, int offset)
 {
        return readw (board->base + offset);
 }
 
 
-int sx_busy_wait_eq (struct sx_board *board, 
-                     int offset,
-                     int mask,
-                     int correctval)
+static int sx_busy_wait_eq (struct sx_board *board, 
+                           int offset, int mask, int correctval)
 {
        int i;
 
@@ -538,10 +532,8 @@ int sx_busy_wait_eq (struct sx_board *board,
 }
 
 
-int sx_busy_wait_neq (struct sx_board *board, 
-                      int offset,
-                      int mask,
-                      int badval)
+static int sx_busy_wait_neq (struct sx_board *board, 
+                            int offset, int mask, int badval)
 {
        int i;
 
@@ -568,7 +560,7 @@ int sx_busy_wait_neq (struct sx_board *board,
 
 
 /* 5.6.4 of 6210028 r2.3 */
-int sx_reset (struct sx_board *board)
+static int sx_reset (struct sx_board *board)
 {
        func_enter ();
 
@@ -650,7 +642,7 @@ int sx_reset (struct sx_board *board)
    read_sx_word (board, BRD_OFFSET (board, elem))
 
 
-int sx_start_board (struct sx_board *board)
+static int sx_start_board (struct sx_board *board)
 {
        if (IS_SX_BOARD (board)) {
                write_sx_byte (board, SX_CONFIG, SX_CONF_BUSEN);
@@ -671,7 +663,7 @@ int sx_start_board (struct sx_board *board)
 
 /* Note. The SX register is write-only. Therefore, we have to enable the
    bus too. This is a no-op, if you don't mess with this driver... */
-int sx_start_interrupts (struct sx_board *board)
+static int sx_start_interrupts (struct sx_board *board)
 {
 
        /* Don't call this with board->irq == 0 */
@@ -698,10 +690,8 @@ int sx_start_interrupts (struct sx_board *board)
 }
 
 
-int sx_send_command (struct sx_port *port, 
-                     int command,
-                     int mask,
-                     int newstat)
+static int sx_send_command (struct sx_port *port, 
+                           int command, int mask, int newstat)
 {
        func_enter2 ();
        write_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat), command);
@@ -710,7 +700,7 @@ int sx_send_command (struct sx_port *port,
 }
 
 
-char *mod_type_s (int module_type)
+static char *mod_type_s (int module_type)
 {
        switch (module_type) {
        case TA4:       return "TA4";
@@ -724,7 +714,7 @@ char *mod_type_s (int module_type)
 }
 
 
-char *pan_type_s (int pan_type)
+static char *pan_type_s (int pan_type)
 {
        switch (pan_type) {
        case MOD_RS232DB25:     return "MOD_RS232DB25";
@@ -742,7 +732,7 @@ char *pan_type_s (int pan_type)
 }
 
 
-int mod_compat_type (int module_type)
+static int mod_compat_type (int module_type)
 {
        return module_type >> 4;
 }
@@ -986,7 +976,7 @@ static int sx_set_real_termios (void *ptr)
    case.  */
 
 
-void sx_transmit_chars (struct sx_port *port)
+static void sx_transmit_chars (struct sx_port *port)
 {
        int c;
        int tx_ip;
@@ -1069,7 +1059,7 @@ void sx_transmit_chars (struct sx_port *port)
    a transmit buffer. */
 
 /* Inlined: Called only once. Remove the inline when you add another call */
-inline void sx_receive_chars (struct sx_port *port)
+static inline void sx_receive_chars (struct sx_port *port)
 {
        int c;
        int rx_op;
@@ -1136,7 +1126,7 @@ inline void sx_receive_chars (struct sx_port *port)
 
 /* Inlined: it is called only once. Remove the inline if you add another 
    call */
-inline void sx_check_modem_signals (struct sx_port *port)
+static inline void sx_check_modem_signals (struct sx_port *port)
 {
        int hi_state;
        int c_dcd;
@@ -1478,7 +1468,7 @@ static int sx_open  (struct tty_struct * tty, struct file * filp)
                return -EIO;
        }
 
-       retval = block_til_ready(port, filp);
+       retval = gs_block_til_ready(port, filp);
        sx_dprintk (SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", 
                    retval, port->gs.count);
 
@@ -1594,7 +1584,7 @@ static void sx_close (void *ptr)
 
 /* This memtest takes a human-noticable time. You normally only do it
    once a boot, so I guess that it is worth it. */
-int do_memtest (struct sx_board *board, int min, int max)
+static int do_memtest (struct sx_board *board, int min, int max)
 {
        int i;
 
@@ -1629,7 +1619,7 @@ int do_memtest (struct sx_board *board, int min, int max)
 
 /* This memtest takes a human-noticable time. You normally only do it
    once a boot, so I guess that it is worth it. */
-int do_memtest_w (struct sx_board *board, int min, int max)
+static int do_memtest_w (struct sx_board *board, int min, int max)
 {
        int i;
 
@@ -1756,13 +1746,15 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
                        sx_initialized++;
                break;
        case SXIO_SETDEBUG:
-       case SXIO_SETGSDEBUG:
                sx_debug = arg;
                break;
        case SXIO_GETDEBUG:
-       case SXIO_GETGSDEBUG:
                rc = sx_debug;
                break;
+       case SXIO_GETGSDEBUG:
+       case SXIO_SETGSDEBUG:
+               rc = -EINVAL;
+               break;
        case SXIO_GETNPORTS:
                rc = sx_nports;
                break;
@@ -2071,7 +2063,7 @@ static int sx_init_board (struct sx_board *board)
 }
 
 
-void printheader(void)
+static void printheader(void)
 {
        static int header_printed;
 
@@ -2084,7 +2076,7 @@ void printheader(void)
 }
 
 
-int probe_sx (struct sx_board *board)
+static int probe_sx (struct sx_board *board)
 {
        struct vpd_prom vpdp;
        char *p;
@@ -2162,7 +2154,7 @@ int probe_sx (struct sx_board *board)
    card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves 
    0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */
 
-int probe_si (struct sx_board *board)
+static int probe_si (struct sx_board *board)
 {
        int i;
 
@@ -2262,7 +2254,7 @@ static int sx_init_drivers(void)
 }
 
 
-void * ckmalloc (int size)
+static void * ckmalloc (int size)
 {
        void *p;
 
@@ -2369,15 +2361,13 @@ static int sx_init_portstructs (int nboards, int nports)
        return 0;
 }
 
-#ifdef MODULE
-static void sx_release_drivers(void)
+static void __exit sx_release_drivers(void)
 {
        func_enter();
        tty_unregister_driver(&sx_driver);
        tty_unregister_driver(&sx_callout_driver);
        func_exit();
 }
-#endif
 
 #ifdef TWO_ZERO
 #define PDEV unsigned char pci_bus, unsigned pci_fun
@@ -2399,7 +2389,7 @@ static void sx_release_drivers(void)
    EEprom.  As the bit is read/write for the CPU, we can fix it here,
    if we detect that it isn't set correctly. -- REW */
 
-void fix_sx_pci (PDEV, struct sx_board *board)
+static void fix_sx_pci (PDEV, struct sx_board *board)
 {
        unsigned int hwbase;
        unsigned long rebase;
@@ -2421,11 +2411,7 @@ void fix_sx_pci (PDEV, struct sx_board *board)
 #endif
 
 
-#ifdef MODULE
-#define sx_init init_module
-#endif
-
-int sx_init(void) 
+static int __init sx_init(void) 
 {
        int i;
        int found = 0;
@@ -2593,8 +2579,7 @@ int sx_init(void)
 }
 
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit sx_exit (void)
 {
        int i; 
        struct sx_board *board;
@@ -2627,4 +2612,7 @@ void cleanup_module(void)
        kfree (sx_termios_locked);
        func_exit();
 }
-#endif
+
+module_init(sx_init);
+module_exit(sx_exit);
+
index 8a4f50f449a8ae1b9f0253ef4e6f01173e724dc0..cadd051b735026fbdcb81242a679ffc6c5972092 100644 (file)
@@ -24,7 +24,7 @@
    Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey
    <mbailey@littlefeet-inc.com> */
 
-/* $Id: i2c-algo-pcf.c,v 1.24 2000/07/09 15:16:16 frodo Exp $ */
+/* $Id: i2c-algo-pcf.c,v 1.25 2000/11/10 13:43:32 frodo Exp $ */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -323,7 +323,7 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
        int rdcount=0, i, status, timeout, dummy=1;
        struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
     
-       for (i=0; i<count-1; ++i) {
+       for (i=0; i<count; ++i) {
                buf[rdcount] = i2c_inb(adap);
                if (dummy) {
                        dummy = 0;
index 50d13efbbc7b04753899d9a0315c71efaa05f35d..84e6003640a44a927665b5ed56783d7f883c07b1 100644 (file)
@@ -20,7 +20,7 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
    All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c-core.c,v 1.56 2000/07/09 15:13:05 frodo Exp $ */
+/* $Id: i2c-core.c,v 1.58 2000/10/29 22:57:38 frodo Exp $ */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -105,7 +105,7 @@ static struct inode_operations i2cproc_inode_operations = {
 };
 #endif
 
-static int i2cproc_initialized;
+static int i2cproc_initialized = 0;
 
 #else /* undef CONFIG_PROC_FS */
 
@@ -1109,6 +1109,21 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
                              I2C_SMBUS_BLOCK_DATA,&data);
 }
 
+extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
+                                          u8 command, u8 length, u8 *values)
+{
+       union i2c_smbus_data data;
+       int i;
+       if (length > 32)
+               length = 32;
+       for (i = 1; i <= length; i++)
+               data.block[i] = values[i-1];
+       data.block[0] = length;
+       return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
+                             I2C_SMBUS_WRITE,command,
+                             I2C_SMBUS_I2C_BLOCK_DATA,&data);
+}
+
 /* Simulate a SMBus command using the i2c protocol 
    No checking of parameters is done!  */
 static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, 
@@ -1120,8 +1135,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
          need to use only one message; when reading, we need two. We initialize
          most things with sane defaults, to keep the code below somewhat
          simpler. */
-       unsigned char msgbuf0[33];
-       unsigned char msgbuf1[33];
+       unsigned char msgbuf0[34];
+       unsigned char msgbuf1[34];
        int num = read_write == I2C_SMBUS_READ?2:1;
        struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, 
                                  { addr, flags | I2C_M_RD, 0, msgbuf1 }
@@ -1173,15 +1188,15 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                               "I2C emulation!\n");
                return -1;
                } else {
-                       msg[1].len = data->block[0] + 1;
-                       if (msg[1].len > 32) {
+                       msg[0].len = data->block[0] + 2;
+                       if (msg[0].len > 34) {
                                printk("i2c-core.o: smbus_access called with "
                                       "invalid block write size (%d)\n",
-                                      msg[1].len);
+                                      msg[0].len);
                                return -1;
                        }
-                       for (i = 1; i <= msg[1].len; i++)
-                               msgbuf0[i] = data->block[i];
+                       for (i = 1; i <= msg[0].len; i++)
+                               msgbuf0[i] = data->block[i-1];
                }
                break;
        default:
index 0981a96c06f92747bec2b83f56a7491d08330ea5..cf6afc575ce2dde70ecd7a04198f7a7a25ff671b 100644 (file)
 
 /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
 
-/* $Id: i2c-dev.c,v 1.32 2000/07/25 23:52:17 frodo Exp $ */
+/* The devfs code is contributed by Philipp Matthias Hahn 
+   <pmhahn@titan.lahn.de> */
 
+/* $Id: i2c-dev.c,v 1.36 2000/09/22 02:19:35 mds Exp $ */
+
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/malloc.h>
 #include <linux/version.h>
+#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
 #include <linux/smp_lock.h>
+#endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
+#ifdef CONFIG_DEVFS_FS
+#include <linux/devfs_fs_kernel.h>
+#endif
+
 
 /* If you want debugging uncomment: */
 /* #define DEBUG */
@@ -77,7 +87,9 @@ extern
 static int i2cdev_cleanup(void);
 
 static struct file_operations i2cdev_fops = {
+#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
        owner:          THIS_MODULE,
+#endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
        llseek:         i2cdev_lseek,
        read:           i2cdev_read,
        write:          i2cdev_write,
@@ -88,26 +100,30 @@ static struct file_operations i2cdev_fops = {
 
 #define I2CDEV_ADAPS_MAX I2C_ADAP_MAX
 static struct i2c_adapter *i2cdev_adaps[I2CDEV_ADAPS_MAX];
+#ifdef CONFIG_DEVFS_FS
+static devfs_handle_t devfs_i2c[I2CDEV_ADAPS_MAX];
+static devfs_handle_t devfs_handle = NULL;
+#endif
 
 static struct i2c_driver i2cdev_driver = {
-       /* name */              "i2c-dev dummy driver",
-       /* id */                I2C_DRIVERID_I2CDEV,
-       /* flags */             I2C_DF_DUMMY,
-       /* attach_adapter */    i2cdev_attach_adapter,
-       /* detach_client */     i2cdev_detach_client,
-       /* command */           i2cdev_command,
-       /* inc_use */           NULL,
-       /* dec_use */           NULL,
+       name:           "i2c-dev dummy driver",
+       id:             I2C_DRIVERID_I2CDEV,
+       flags:          I2C_DF_DUMMY,
+       attach_adapter: i2cdev_attach_adapter,
+       detach_client:  i2cdev_detach_client,
+       command:        i2cdev_command,
+/*     inc_use:        NULL,
+       dec_use:        NULL, */
 };
 
 static struct i2c_client i2cdev_client_template = {
-       /* name */              "I2C /dev entry",
-       /* id */                1,
-       /* flags */             0,
-       /* addr */              -1,
-       /* adapter */           NULL,
-       /* driver */            &i2cdev_driver,
-       /* data */              NULL
+       name:           "I2C /dev entry",
+       id:             1,
+       flags:          0,
+       addr:           -1,
+/*     adapter:        NULL, */
+       driver:         &i2cdev_driver,
+/*     data:           NULL */
 };
 
 static int i2cdev_initialized;
@@ -118,7 +134,7 @@ loff_t i2cdev_lseek (struct file *file, loff_t offset, int origin)
 {
 #ifdef DEBUG
        struct inode *inode = file->f_dentry->d_inode;
-       printk("i2c-dev,o: i2c-%d lseek to %ld bytes relative to %d.\n",
+       printk("i2c-dev.o: i2c-%d lseek to %ld bytes relative to %d.\n",
               MINOR(inode->i_rdev),(long) offset,origin);
 #endif /* DEBUG */
        return -ESPIPE;
@@ -142,7 +158,7 @@ static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
                return -ENOMEM;
 
 #ifdef DEBUG
-       printk("i2c-dev,o: i2c-%d reading %d bytes.\n",MINOR(inode->i_rdev),
+       printk("i2c-dev.o: i2c-%d reading %d bytes.\n",MINOR(inode->i_rdev),
               count);
 #endif
 
@@ -174,7 +190,7 @@ static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
        }
 
 #ifdef DEBUG
-       printk("i2c-dev,o: i2c-%d writing %d bytes.\n",MINOR(inode->i_rdev),
+       printk("i2c-dev.o: i2c-%d writing %d bytes.\n",MINOR(inode->i_rdev),
               count);
 #endif
        ret = i2c_master_send(client,tmp,count);
@@ -289,7 +305,8 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
                    (data_arg.size != I2C_SMBUS_BYTE_DATA) && 
                    (data_arg.size != I2C_SMBUS_WORD_DATA) &&
                    (data_arg.size != I2C_SMBUS_PROC_CALL) &&
-                   (data_arg.size != I2C_SMBUS_BLOCK_DATA)) {
+                   (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
+                   (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA)) {
 #ifdef DEBUG
                        printk("i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n",
                               data_arg.size);
@@ -379,6 +396,9 @@ int i2cdev_open (struct inode *inode, struct file *file)
 
        if (i2cdev_adaps[minor]->inc_use)
                i2cdev_adaps[minor]->inc_use(i2cdev_adaps[minor]);
+#if LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0)
+       MOD_INC_USE_COUNT;
+#endif /* LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0) */
 
 #ifdef DEBUG
        printk("i2c-dev.o: opened i2c-%d\n",minor);
@@ -394,16 +414,23 @@ static int i2cdev_release (struct inode *inode, struct file *file)
 #ifdef DEBUG
        printk("i2c-dev.o: Closed: i2c-%d\n", minor);
 #endif
+#if LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0)
+       MOD_DEC_USE_COUNT;
+#else /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
        lock_kernel();
+#endif /* LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0) */
        if (i2cdev_adaps[minor]->dec_use)
                i2cdev_adaps[minor]->dec_use(i2cdev_adaps[minor]);
+#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
        unlock_kernel();
+#endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
        return 0;
 }
 
 int i2cdev_attach_adapter(struct i2c_adapter *adap)
 {
        int i;
+       char name[8];
 
        if ((i = i2c_adapter_id(adap)) < 0) {
                printk("i2c-dev.o: Unknown adapter ?!?\n");
@@ -414,11 +441,21 @@ int i2cdev_attach_adapter(struct i2c_adapter *adap)
                return -ENODEV;
        }
 
+       sprintf (name, "%d", i);
        if (! i2cdev_adaps[i]) {
                i2cdev_adaps[i] = adap;
+#ifdef CONFIG_DEVFS_FS
+               devfs_i2c[i] = devfs_register (devfs_handle, name,
+                       DEVFS_FL_DEFAULT, I2C_MAJOR, i,
+                       S_IFCHR | S_IRUSR | S_IWUSR,
+                       &i2cdev_fops, NULL);
+#endif
                printk("i2c-dev.o: Registered '%s' as minor %d\n",adap->name,i);
        } else {
                /* This is actually a detach_adapter call! */
+#ifdef CONFIG_DEVFS_FS
+               devfs_unregister(devfs_i2c[i]);
+#endif
                i2cdev_adaps[i] = NULL;
 #ifdef DEBUG
                printk("i2c-dev.o: Adapter unregistered: %s\n",adap->name);
@@ -446,11 +483,18 @@ int __init i2c_dev_init(void)
        printk("i2c-dev.o: i2c /dev entries driver module\n");
 
        i2cdev_initialized = 0;
+#ifdef CONFIG_DEVFS_FS
+       if (devfs_register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops)) {
+#else
        if (register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops)) {
+#endif
                printk("i2c-dev.o: unable to get major %d for i2c bus\n",
                       I2C_MAJOR);
                return -EIO;
        }
+#ifdef CONFIG_DEVFS_FS
+       devfs_handle = devfs_mk_dir(NULL, "i2c", NULL);
+#endif
        i2cdev_initialized ++;
 
        if ((res = i2c_add_driver(&i2cdev_driver))) {
@@ -476,7 +520,12 @@ int i2cdev_cleanup(void)
        }
 
        if (i2cdev_initialized >= 1) {
+#ifdef CONFIG_DEVFS_FS
+               devfs_unregister(devfs_handle);
+               if ((res = devfs_unregister_chrdev(I2C_MAJOR, "i2c"))) {
+#else
                if ((res = unregister_chrdev(I2C_MAJOR,"i2c"))) {
+#endif
                        printk("i2c-dev.o: unable to release major %d for i2c bus\n",
                               I2C_MAJOR);
                        return res;
index 81092ded69a5293ad8405a31b831a431f97eeb6a..d63dd5981f4784c52f67a31671b539ed33e515a3 100644 (file)
@@ -1,12 +1,15 @@
 #
 # ISDN device configuration
 #
+
+# only included if CONFIG_ISDN != n
+
 if [ "$CONFIG_INET" != "n" ]; then
    bool '  Support synchronous PPP' CONFIG_ISDN_PPP
    if [ "$CONFIG_ISDN_PPP" != "n" ]; then
-      bool     '    Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
-      bool     '    Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
-      tristate '    Support BSD compression with sync PPP' CONFIG_ISDN_PPP_BSDCOMP
+      bool         '    Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
+      bool         '    Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
+      dep_tristate '    Support BSD compression (module only)' CONFIG_ISDN_PPP_BSDCOMP m
    fi
 fi
 bool '  Support audio via ISDN' CONFIG_ISDN_AUDIO
@@ -20,7 +23,7 @@ fi
 mainmenu_option next_comment
 comment 'ISDN feature submodules'
    dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
-   bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION
+   dep_tristate 'Support isdn diversion services' CONFIG_ISDN_DIVERSION $CONFIG_ISDN
 endmenu
 
 comment 'low-level hardware drivers'
@@ -81,49 +84,58 @@ endmenu
 mainmenu_option next_comment
 comment 'Active ISDN cards'
 
-dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
-dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
-if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-   dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
-   dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
-fi
+dep_tristate       'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
+dep_tristate       'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
+dep_tristate       'Spellcaster support' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
+dep_tristate       'IBM Active 2000 support' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
 
-dep_tristate 'Eicon active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
+bool               'Eicon active card support' CONFIG_ISDN_DRV_EICON
 if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then
-   tristate '  Old Eicon driver' CONFIG_ISDN_DRV_EICON_OLD
-   if [ "$CONFIG_ISDN_DRV_EICON_OLD" != "n" ]; then 
-      dep_bool  '    Eicon PCI DIVA Server BRI/PRI/4BRI support' CONFIG_ISDN_DRV_EICON_PCI $CONFIG_PCI
-      bool      '    Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
+   if [ "$CONFIG_ISDN_DRV_EICON_OLD" != "y" ]; then
+      dep_tristate '  Build Eicon driver type standalone' CONFIG_ISDN_DRV_EICON_DIVAS $CONFIG_ISDN
+   fi
+   if [ "$CONFIG_ISDN_DRV_EICON_DIVAS" != "y" ]; then
+      dep_tristate '  Legacy Eicon driver' CONFIG_ISDN_DRV_EICON_OLD $CONFIG_ISDN
+      if [ "$CONFIG_ISDN_DRV_EICON_OLD" != "n" ]; then
+         dep_bool  '    Eicon PCI DIVA Server BRI/PRI/4BRI support' CONFIG_ISDN_DRV_EICON_PCI $CONFIG_PCI
+         bool      '    Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
+      fi
    fi
-   tristate '  Build Eicon driver type standalone' CONFIG_ISDN_DRV_EICON_DIVAS
 fi
 
 # CAPI subsystem
 
-tristate     'CAPI2.0 support' CONFIG_ISDN_CAPI
+tristate           'CAPI2.0 support' CONFIG_ISDN_CAPI
 if [ "$CONFIG_ISDN_CAPI" != "n" ]; then
-   dep_bool     '  CAPI2.0 Middleware support (EXPERIMENTAL)' CONFIG_ISDN_CAPI_MIDDLEWARE $CONFIG_EXPERIMENTAL
-   dep_tristate '  CAPI2.0 filesystem support' CONFIG_ISDN_CAPI_CAPIFS $CONFIG_ISDN_CAPI_MIDDLEWARE
-   dep_tristate '  CAPI2.0 /dev/capi support' CONFIG_ISDN_CAPI_CAPI20 $CONFIG_ISDN_CAPIFS
-   dep_tristate '  CAPI2.0 capidrv interface support' CONFIG_ISDN_CAPI_CAPIDRV $CONFIG_ISDN
-   bool         '  Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
+   bool            '  Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
+   dep_bool        '  CAPI2.0 Middleware support (EXPERIMENTAL)' CONFIG_ISDN_CAPI_MIDDLEWARE $CONFIG_EXPERIMENTAL
+   dep_tristate    '  CAPI2.0 /dev/capi support' CONFIG_ISDN_CAPI_CAPI20 $CONFIG_ISDN_CAPI
+   if [ "$CONFIG_ISDN_CAPI_MIDDLEWARE" = "y" ]; then
+      dep_mbool    '    CAPI2.0 filesystem support' CONFIG_ISDN_CAPI_CAPIFS_BOOL $CONFIG_ISDN_CAPI_CAPI20
+      if [ "$CONFIG_ISDN_CAPI_CAPIFS_BOOL" = "y" ]; then
+        define_tristate CONFIG_ISDN_CAPI_CAPIFS $CONFIG_ISDN_CAPI_CAPI20
+      else
+        define_tristate CONFIG_ISDN_CAPI_CAPIFS n
+      fi
+   fi
+   dep_tristate    '  CAPI2.0 capidrv interface support' CONFIG_ISDN_CAPI_CAPIDRV $CONFIG_ISDN_CAPI $CONFIG_ISDN
 fi
 
 # CAPI drivers
 
 if [ "$CONFIG_ISDN_CAPI" != "n" ]; then
-   tristate     '  AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
-   dep_tristate '  AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI $CONFIG_PCI
+   dep_tristate '  AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA $CONFIG_ISDN_CAPI
+   dep_tristate '  AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI $CONFIG_ISDN_CAPI $CONFIG_PCI
    dep_mbool    '    AVM B1 PCI V4 support' CONFIG_ISDN_DRV_AVMB1_B1PCIV4 $CONFIG_ISDN_DRV_AVMB1_B1PCI
-   tristate     '  AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
-   dep_tristate '  AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA $CONFIG_PCMCIA
+   dep_tristate '  AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA $CONFIG_ISDN_CAPI
+   dep_tristate '  AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA $CONFIG_ISDN_CAPI $CONFIG_PCMCIA
    dep_tristate '  AVM B1/M1/M2 PCMCIA cs module' CONFIG_ISDN_DRV_AVMB1_AVM_CS $CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
-   dep_tristate '  AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI $CONFIG_PCI
-   dep_tristate '  AVM C4 support' CONFIG_ISDN_DRV_AVMB1_C4 $CONFIG_PCI
+   dep_tristate '  AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI $CONFIG_ISDN_CAPI $CONFIG_PCI
+   dep_tristate '  AVM C4 support' CONFIG_ISDN_DRV_AVMB1_C4 $CONFIG_ISDN_CAPI $CONFIG_PCI
 fi
 
 # HYSDN
 
-dep_tristate '  Hypercope HYSDN cards (Champ, Ergo, Metro) support (module)' CONFIG_HYSDN m $CONFIG_PROC_FS
+dep_tristate '  Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)' CONFIG_HYSDN m $CONFIG_PROC_FS
 dep_mbool    '    HYSDN CAPI 2.0 support' CONFIG_HYSDN_CAPI $CONFIG_HYSDN $CONFIG_ISDN_CAPI
 endmenu
index 11ea08c2d55c21974dd98baa0b8a174f50d5813c..d1ab6cd7bf7f31df3eedc9d303159f79b500a06a 100644 (file)
@@ -24,41 +24,28 @@ isdn-objs-$(CONFIG_ISDN_WITH_ABC)   += isdn_dwabc.o
 
 isdn-objs                              += $(isdn-objs-y)
 
-# Object file lists.
+# Ordering constraints: isdn.o first, rest doesn't matter
 
-obj-y  :=
-obj-m  :=
-obj-n  :=
-obj-   :=
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_ISDN)                     += isdn.o
+obj-$(CONFIG_ISDN_PPP_BSDCOMP)         += isdn_bsdcomp.o
 
 # Object files in subdirectories
 
+mod-subdirs                            := avmb1 eicon
 subdir-$(CONFIG_ISDN_DIVERSION)                += divert
 subdir-$(CONFIG_ISDN_DRV_HISAX)                += hisax
-subobj-$(CONFIG_ISDN_DRV_HISAX)                += hisax/hisax_drv.o
 subdir-$(CONFIG_ISDN_DRV_ICN)          += icn
-subobj-$(CONFIG_ISDN_DRV_ICN)          += icn/icn_drv.o
 subdir-$(CONFIG_ISDN_DRV_PCBIT)                += pcbit
-subobj-$(CONFIG_ISDN_DRV_PCBIT)                += pcbit/pcbit_drv.o
 subdir-$(CONFIG_ISDN_DRV_SC)           += sc
-subobj-$(CONFIG_ISDN_DRV_SC)           += sc/sc_drv.o
 subdir-$(CONFIG_ISDN_CAPI)             += avmb1
-subobj-$(CONFIG_ISDN_CAPI)             += avmb1/avmb1.o
 subdir-$(CONFIG_ISDN_DRV_LOOP)         += isdnloop
-subobj-$(CONFIG_ISDN_DRV_LOOP)         += isdnloop/isdnloop_drv.o
 subdir-$(CONFIG_ISDN_DRV_ACT2000)      += act2000
-subobj-$(CONFIG_ISDN_DRV_ACT2000)      += act2000/act2000_drv.o
 subdir-$(CONFIG_ISDN_DRV_EICON)                += eicon
-subobj-$(CONFIG_ISDN_DRV_EICON)                += eicon/eicon_drv.o
 subdir-$(CONFIG_HYSDN)                 += hysdn
-subobj-$(CONFIG_HYSDN)                 += hysdn/hysdn_drv.o
-
-obj-y                                  += $(subobj-y)
 
-# Each configuration option enables a list of files.
-
-obj-$(CONFIG_ISDN)                     += isdn.o
-obj-$(CONFIG_ISDN_PPP_BSDCOMP)         += isdn_bsdcomp.o
+obj-y += $(addsuffix /vmlinux-obj.o, $(subdir-y))
 
 # The global Rules.make.
 
index e8946317ae950bbf46cdb420f6e2874bf4b08723..556c402b17cf5cd5bfbb6db9df6a3fcd8096255a 100644 (file)
@@ -2,24 +2,13 @@
 
 # The target object and module list name.
 
-O_TARGET       := act2000_drv.o
-
-# Objects that export symbols.
-
-export-objs    :=
+O_TARGET       := vmlinux-obj.o
 
 # Multipart objects.
 
 list-multi     := act2000.o
 act2000-objs   := module.o capi.o act2000_isa.o
 
-# Object file lists.
-
-obj-y  :=
-obj-m  :=
-obj-n  :=
-obj-   :=
-
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000.o
index d1f090d3d89d3779ef3d12bca4d6bc3afb734451..36690928780b8ef54f4a2a3b63b6e7197ce733dd 100644 (file)
@@ -2,7 +2,7 @@
 
 # The target object and module list name.
 
-O_TARGET       := avmb1.o
+O_TARGET       := vmlinux-obj.o
 
 # Objects that export symbols.
 
@@ -13,12 +13,7 @@ export-objs  := kcapi.o capiutil.o b1dma.o b1pcmcia.o b1.o capifs.o
 list-multi     := kernelcapi.o
 kernelcapi-objs        := kcapi.o
 
-# Object file lists.
-
-obj-y  :=
-obj-m  :=
-obj-n  :=
-obj-   :=
+# Ordering constraints: kernelcapi.o first
 
 # Each configuration option enables a list of files.
 
index 88d09095a49b4c822c1df3985954db2ab7bf0923..dc1084cb6355a00a7086ee869f4b619126e20961 100644 (file)
@@ -4,27 +4,16 @@
 
 # The target object and module list name.
 
-O_TARGET       :=
-
-# Objects that export symbols.
-
-export-objs    :=
+O_TARGET       := vmlinux-obj.o
 
 # Multipart objects.
 
 list-multi             := dss1_divert.o
 dss1_divert-objs       := isdn_divert.o divert_procfs.o divert_init.o
 
-# Object file lists.
-
-obj-y  :=
-obj-m  :=
-obj-n  :=
-obj-   :=
-
 # Each configuration option enables a list of files.
 
-obj-m  += dss1_divert.o
+obj-$(CONFIG_ISDN_DIVERSION)   += dss1_divert.o
 
 include $(TOPDIR)/Rules.make
 
index cd9b2e3fb43cf329122819719685b7294c75e045..35f59701d8d4c9998e21371334b39eed96cda310 100644 (file)
@@ -2,7 +2,7 @@
 
 # The target object and module list name.
 
-O_TARGET       := eicon_drv.o
+O_TARGET       := vmlinux-obj.o
 
 # Objects that export symbols.
 
@@ -25,16 +25,9 @@ eicon-objs-$(CONFIG_ISDN_DRV_EICON_PCI) += common.o idi.o bri.o pri.o log.o \
 
 eicon-objs     += $(eicon-objs-y)
 
-# Object file lists.
-
-obj-y  :=
-obj-m  :=
-obj-n  :=
-obj-   :=
-
 # Each configuration option enables a list of files.
 
-obj-$(CONFIG_ISDN_DRV_EICON_OLD)       += eicon.o
+obj-$(CONFIG_ISDN_DRV_EICON_OLD)       += eicon.o
 obj-$(CONFIG_ISDN_DRV_EICON_DIVAS)     += divas.o
 
 include $(TOPDIR)/Rules.make
index a7904f0c927bdef7a7b0d7b2b9272cc2adef53b3..66f6b5d4ad914896d68e9a55935c2428da44faea 100644 (file)
@@ -2,7 +2,7 @@
 
 # The target object and module list name.
 
-O_TARGET       := hisax_drv.o
+O_TARGET       := vmlinux-obj.o
 
 # Objects that export symbols.
 
@@ -52,29 +52,19 @@ hisax-objs-$(CONFIG_HISAX_W6692) += w6692.o
 
 hisax-objs += $(sort $(hisax-objs-y))
 
-# Object file lists.
-
-obj-y  :=
-obj-m  :=
-obj-n  :=
-obj-   :=
-
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_ISDN_DRV_HISAX)   += hisax.o
 
+MD5FILES       := isac.c isdnl1.c isdnl2.c isdnl3.c \
+                  tei.c callc.c cert.c l3dss1.c l3_1tr6.c \
+                  elsa.c diva.c sedlbauer.c
+CERT := $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
+CFLAGS_cert.o := -DCERTIFICATION=$(CERT)
+
 include $(TOPDIR)/Rules.make
 
 # Link rules for multi-part drivers.
 
 hisax.o: $(hisax-objs)
        $(LD) -r -o $@ $(hisax-objs)
-
-MD5FILES += isac.c isdnl1.c isdnl2.c isdnl3.c \
-           tei.c callc.c cert.c l3dss1.c l3_1tr6.c \
-           elsa.c diva.c sedlbauer.c
-
-CERT = $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
-
-cert.o:        $(MD5FILES) md5sums.asc
-       $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -D CERTIFICATION=$(CERT) -c -o cert.o cert.c
index 92d8bb988503ea09be8d7e1d1a5145e96847ef95..1f119beb70a91992b0609aac0b58339721004e89 100644 (file)
@@ -2,11 +2,7 @@
 
 # The target object and module list name.
 
-O_TARGET       := hysdn_drv.o
-
-# Objects that export symbols.
-
-export-objs    :=
+O_TARGET       := vmlinux-obj.o
 
 # Multipart objects.
 
@@ -20,13 +16,6 @@ hysdn-objs-$(CONFIG_HYSDN_CAPI) += hycapi.o
 
 hysdn-objs     += $(hysdn-objs-y)
 
-# Object file lists.
-
-obj-y  :=
-obj-m  :=
-obj-n  :=
-obj-   :=
-
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_HYSDN)    += hysdn.o
index 9931761c9226ed77d03d7cf3e64f2fd56d7554fc..bd716cf0b87fa019b65b92d24e5d51d1e004d48b 100644 (file)
@@ -2,18 +2,7 @@
 
 # The target object and module list name.
 
-O_TARGET       := icn_drv.o
-
-# Objects that export symbols.
-
-export-objs    :=
-
-# Object file lists.
-
-obj-y  :=
-obj-m  :=
-obj-n  :=
-obj-   :=
+O_TARGET       := vmlinux-obj.o
 
 # Each configuration option enables a list of files.
 
index 8c7636b4692d20e0c27c26d2be6d40172165d200..26871113982851a0123c486e18321fc6c61181ba 100644 (file)
@@ -34,7 +34,7 @@ extern void HiSax_init(void);
 extern void pcbit_init(void);
 #endif
 
-#ifdef CONFIG_ISDN_DRV_EICON
+#if defined(CONFIG_ISDN_DRV_EICON_OLD) || defined(CONFIG_ISDN_DRV_EICON_DIVAS)
 extern void eicon_init(void);
 #endif
 
@@ -57,7 +57,7 @@ isdn_cards_init(void)
 #if CONFIG_ISDN_DRV_ACT2000
        act2000_init();
 #endif
-#if CONFIG_ISDN_DRV_EICON
+#if defined(CONFIG_ISDN_DRV_EICON_OLD) || defined(CONFIG_ISDN_DRV_EICON_DIVAS)
        eicon_init();
 #endif
 }
index eea88399bea26e21dee6c4673cc088da85ebf8c8..615d11fc1d7774d4b7ffce6b31903d377d6dab46 100644 (file)
@@ -36,6 +36,9 @@
 #ifdef CONFIG_ISDN_AUDIO
 #include "isdn_audio.h"
 #endif
+#ifdef CONFIG_ISDN_DIVERSION_MODULE
+#define CONFIG_ISDN_DIVERSION
+#endif
 #ifdef CONFIG_ISDN_DIVERSION
 #include <linux/isdn_divertif.h>
 #endif CONFIG_ISDN_DIVERSION
index 154363b762f23c14f8294d693268ce4243b2686f..312e9b96937b5a9dc41fc624b73d42576e068f39 100644 (file)
@@ -4,18 +4,7 @@
 
 # The target object and module list name.
 
-O_TARGET       := isdnloop_drv.o
-
-# Objects that export symbols.
-
-export-objs    :=
-
-# Object file lists.
-
-obj-y  :=
-obj-m  :=
-obj-n  :=
-obj-   :=
+O_TARGET       := vmlinux-obj.o
 
 # Each configuration option enables a list of files.
 
index de125f2fee66870784cf38faf4c017fcf5f5ae68..7a6a8044721208fb3e0065ad138e43c0806f1129 100644 (file)
@@ -2,24 +2,13 @@
 
 # The target object and module list name.
 
-O_TARGET       := pcbit_drv.o
-
-# Objects that export symbols.
-
-export-objs    :=
+O_TARGET       := vmlinux-obj.o
 
 # Multipart objects.
 
 list-multi     := pcbit.o
 pcbit-objs     := module.o edss1.o drv.o layer2.o capi.o callbacks.o
 
-# Object file lists.
-
-obj-y  :=
-obj-m  :=
-obj-n  :=
-obj-   :=
-
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_ISDN_DRV_PCBIT)   += pcbit.o
index 7c5998a877100f6a0cf6429d8420485f7efdc844..60ac3ce6d983f7016099c188cb093d88687d6919 100644 (file)
@@ -2,11 +2,7 @@
 
 # The target object and module list name.
 
-O_TARGET       := sc_drv.o
-
-# Objects that export symbols.
-
-export-objs    :=
+O_TARGET       := vmlinux-obj.o
 
 # Multipart objects.
 
@@ -14,13 +10,6 @@ list-multi   := sc.o
 sc-objs                := shmem.o init.o debug.o packet.o command.o event.o \
                   ioctl.o interrupt.o message.o timer.o        
 
-# Object file lists.
-
-obj-y  :=
-obj-m  :=
-obj-n  :=
-obj-   :=
-
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_ISDN_DRV_SC)      += sc.o
index b66edcc44b3f407662187ab90a760e4346d64a10..b356808c1fd503f61edb5f5820fd6b00da688751 100644 (file)
@@ -536,7 +536,6 @@ MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
 MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver");
 MODULE_PARM (multicast_filter_limit, "i");
 MODULE_PARM (max_interrupt_work, "i");
-MODULE_PARM (debug, "i");
 MODULE_PARM (media, "1-" __MODULE_STRING(8) "i");
 
 static int read_eeprom (void *ioaddr, int location, int addr_len);
index 5f765d5bf9ef7e8b694cc06dc7211460ac265a02..75539ecef360ddab2ddc29342dc7a7c792723279 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     G8BPQ compatible "AX.25 via ethernet" driver release 003
+ *     G8BPQ compatible "AX.25 via ethernet" driver release 004
  *
  *     This code REQUIRES 2.0.0 or higher/ NET3.029
  *
@@ -65,6 +65,7 @@
 #include <net/ax25.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/if_ether.h>
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
@@ -86,6 +87,8 @@
 
 #include <linux/bpqether.h>
 
+static const char banner[] __initdata = KERN_INFO "AX.25: bpqether driver version 004\n";
+
 static unsigned char ax25_bcast[AX25_ADDR_LEN] =
        {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
 static unsigned char ax25_defaddr[AX25_ADDR_LEN] =
@@ -100,16 +103,12 @@ static int bpq_device_event(struct notifier_block *, unsigned long, void *);
 static char *bpq_print_ethaddr(unsigned char *);
 
 static struct packet_type bpq_packet_type = {
-       0,              /* ntohs(ETH_P_BPQ),*/
-       0,              /* copy */
-       bpq_rcv,
-       NULL,
-       NULL,
+       type:   __constant_htons(ETH_P_BPQ),
+       func:   bpq_rcv,
 };
 
 static struct notifier_block bpq_dev_notifier = {
-       bpq_device_event,
-       0
+       notifier_call:  bpq_device_event,
 };
 
 
@@ -123,7 +122,7 @@ static struct bpqdev {
        struct net_device_stats stats;  /* some statistics */
        char   dest_addr[6];            /* ether destination address */
        char   acpt_addr[6];            /* accept ether frames from this address only */
-} *bpq_devices = NULL;
+} *bpq_devices;
 
 
 /* ------------------------------------------------------------------------ */
@@ -132,19 +131,17 @@ static struct bpqdev {
 /*
  *     Get the ethernet device for a BPQ device
  */
-static __inline__ struct net_device *bpq_get_ether_dev(struct net_device *dev)
+static inline struct net_device *bpq_get_ether_dev(struct net_device *dev)
 {
-       struct bpqdev *bpq;
-
-       bpq = (struct bpqdev *)dev->priv;
+       struct bpqdev *bpq = (struct bpqdev *) dev->priv;
 
-       return (bpq != NULL) ? bpq->ethdev : NULL;
+       return bpq ? bpq->ethdev : NULL;
 }
 
 /*
  *     Get the BPQ device for the ethernet device
  */
-static __inline__ struct net_device *bpq_get_ax25_dev(struct net_device *dev)
+static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev)
 {
        struct bpqdev *bpq;
 
@@ -155,7 +152,7 @@ static __inline__ struct net_device *bpq_get_ax25_dev(struct net_device *dev)
        return NULL;
 }
 
-static __inline__ int dev_is_ethdev(struct net_device *dev)
+static inline int dev_is_ethdev(struct net_device *dev)
 {
        return (
                        dev->type == ARPHRD_ETHER
@@ -245,8 +242,8 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
        skb_pull(skb, 2);       /* Remove the length bytes */
        skb_trim(skb, len);     /* Set the length of the data */
 
-       ((struct bpqdev *)dev->priv)->stats.rx_packets++;
-       ((struct bpqdev *)dev->priv)->stats.rx_bytes+=len;
+       bpq->stats.rx_packets++;
+       bpq->stats.rx_bytes += len;
 
        ptr = skb_push(skb, 1);
        *ptr = 0;
@@ -333,9 +330,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
  */
 static struct net_device_stats *bpq_get_stats(struct net_device *dev)
 {
-       struct bpqdev *bpq;
-
-       bpq = (struct bpqdev *)dev->priv;
+       struct bpqdev *bpq = (struct bpqdev *) dev->priv;
 
        return &bpq->stats;
 }
@@ -361,7 +356,6 @@ static int bpq_set_mac_address(struct net_device *dev, void *addr)
  */
 static int bpq_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-       int err;
        struct bpq_ethaddr *ethaddr = (struct bpq_ethaddr *)ifr->ifr_data;
        struct bpqdev *bpq = dev->priv;
        struct bpq_req req;
@@ -374,9 +368,8 @@ static int bpq_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
        switch (cmd) {
                case SIOCSBPQETHOPT:
-                       if ((err = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct bpq_req))) != 0)
-                               return err;
-                       copy_from_user(&req, ifr->ifr_data, sizeof(struct bpq_req));
+                       if (copy_from_user(&req, ifr->ifr_data, sizeof(struct bpq_req)))
+                               return -EFAULT;
                        switch (req.cmd) {
                                case SIOCGBPQETHPARAM:
                                case SIOCSBPQETHPARAM:
@@ -387,10 +380,10 @@ static int bpq_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                        break;
 
                case SIOCSBPQETHADDR:
-                       if ((err = verify_area(VERIFY_READ, ethaddr, sizeof(struct bpq_ethaddr))) != 0)
-                               return err;
-                       copy_from_user(bpq->dest_addr, ethaddr->destination, ETH_ALEN);
-                       copy_from_user(bpq->acpt_addr, ethaddr->accept, ETH_ALEN);
+                       if (copy_from_user(bpq->dest_addr, ethaddr->destination, ETH_ALEN))
+                               return -EFAULT;
+                       if (copy_from_user(bpq->acpt_addr, ethaddr->accept, ETH_ALEN))
+                               return -EFAULT;
                        break;
 
                default:
@@ -617,14 +610,13 @@ static int __init bpq_init_driver(void)
 {
        struct net_device *dev;
 
-       bpq_packet_type.type  = htons(ETH_P_BPQ);
        dev_add_pack(&bpq_packet_type);
 
        register_netdevice_notifier(&bpq_dev_notifier);
 
-       printk(KERN_INFO "AX.25: bpqether driver version 0.01\n");
+       printk(banner);
 
-       proc_net_create ("bpqether", 0, bpq_get_info);
+       proc_net_create("bpqether", 0, bpq_get_info);
 
        read_lock_bh(&dev_base_lock);
        for (dev = dev_base; dev != NULL; dev = dev->next) {
@@ -646,7 +638,7 @@ static void __exit bpq_cleanup_driver(void)
 
        unregister_netdevice_notifier(&bpq_dev_notifier);
 
-       proc_net_remove ("bpqether");
+       proc_net_remove("bpqether");
 
        for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next)
                unregister_netdev(&bpq->axdev);
index 3a861650643d70a1ad13e96dfc360923af9b453a..976bb9ebd6a08fa2ef001f5ea8bc3c10c1bd7013 100644 (file)
@@ -40,9 +40,7 @@
 #include <linux/netdevice.h>
 #include <linux/major.h>
 #include <linux/init.h>
-
-#include <linux/timer.h>
-
+#include <linux/rtnetlink.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/tcp.h>
 #endif
 
-#ifdef MODULE
-#define AX25_VERSION    "AX25-MODULAR-NET3.019-NEWTTY"
-#define        min(a,b)        (a < b ? a : b)
-#else
-#define        AX25_VERSION    "AX25-NET3.019-NEWTTY"
-#endif
+static const char banner[] __initdata = KERN_INFO "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
 
 #define NR_MKISS 4
 #define MKISS_SERIAL_TYPE_NORMAL 1
@@ -77,21 +70,13 @@ typedef struct ax25_ctrl {
        struct net_device  dev; /* the device                   */
 } ax25_ctrl_t;
 
-static ax25_ctrl_t **ax25_ctrls = NULL;
+static ax25_ctrl_t **ax25_ctrls;
 
 int ax25_maxdev = AX25_MAXDEV;         /* Can be overridden with insmod! */
 
 static struct tty_ldisc        ax_ldisc;
-static struct tty_driver mkiss_driver;
-static int mkiss_refcount;
-static struct tty_struct *mkiss_table[NR_MKISS];
-static struct termios *mkiss_termios[NR_MKISS];
-static struct termios *mkiss_termios_locked[NR_MKISS];
-struct mkiss_channel MKISS_Info[NR_MKISS];
 
 static int ax25_init(struct net_device *);
-static int mkiss_init(void);
-static int mkiss_write(struct tty_struct *, int, const unsigned char *, int);
 static int kiss_esc(unsigned char *, unsigned char *, int);
 static int kiss_esc_crc(unsigned char *, unsigned char *, unsigned short, int);
 static void kiss_unesc(struct ax_disp *, unsigned char);
@@ -135,8 +120,7 @@ static const unsigned short Crc_flex_table[] = {
 
 /*---------------------------------------------------------------------------*/
 
-static unsigned short 
-calc_crc_flex(unsigned char *cp, int size)
+static unsigned short calc_crc_flex(unsigned char *cp, int size)
 {
     unsigned short crc = 0xffff;
     
@@ -148,8 +132,7 @@ calc_crc_flex(unsigned char *cp, int size)
 
 /*---------------------------------------------------------------------------*/
 
-static int 
-check_crc_flex(unsigned char *cp, int size)
+static int check_crc_flex(unsigned char *cp, int size)
 {
   unsigned short crc = 0xffff;
 
@@ -173,9 +156,6 @@ static inline struct ax_disp *ax_alloc(void)
        ax25_ctrl_t *axp;
        int i;
 
-       if (ax25_ctrls == NULL)         /* Master array missing ! */
-               return NULL;
-
        for (i = 0; i < ax25_maxdev; i++) {
                axp = ax25_ctrls[i];
 
@@ -217,7 +197,7 @@ static inline struct ax_disp *ax_alloc(void)
                        /* (Re-)Set the INUSE bit.   Very Important! */
                        set_bit(AXF_INUSE, &axp->ctrl.flags);
                        axp->ctrl.dev = &axp->dev;
-                       axp->dev.priv = (void *)&axp->ctrl;
+                       axp->dev.priv = (void *) &axp->ctrl;
 
                        return &axp->ctrl;
                } else {
@@ -315,14 +295,14 @@ static void ax_changedmtu(struct ax_disp *ax)
 }
 
 
-/* Set the "sending" flag.  This must be atomic, hence the ASM. */
+/* Set the "sending" flag.  This must be atomic. */
 static inline void ax_lock(struct ax_disp *ax)
 {
        netif_stop_queue(ax->dev);
 }
 
 
-/* Clear the "sending" flag.  This must be atomic, hence the ASM. */
+/* Clear the "sending" flag.  This must be atomic. */
 static inline void ax_unlock(struct ax_disp *ax)
 {
        netif_start_queue(ax->dev);
@@ -392,7 +372,7 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
        if (mkiss->magic  != MKISS_DRIVER_MAGIC) {
                switch (ax->crcmode) {
                         unsigned short crc;
-                        
+
                case CRC_MODE_FLEX:
                         *p |= 0x20;
                         crc = calc_crc_flex(p, len);
@@ -427,7 +407,7 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
 static void ax25_write_wakeup(struct tty_struct *tty)
 {
        int actual;
-       struct ax_disp *ax = (struct ax_disp *)tty->disc_data;
+       struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
        struct mkiss_channel *mkiss;
 
        /* First make sure we're connected. */
@@ -441,7 +421,7 @@ static void ax25_write_wakeup(struct tty_struct *tty)
 
                if (ax->mkiss != NULL) {
                        mkiss= ax->mkiss->tty->driver_data;
-                       if (mkiss->magic  == MKISS_DRIVER_MAGIC)
+                       if (mkiss->magic  == MKISS_DRIVER_MAGIC)
                                ax_unlock(ax->mkiss);
                }
 
@@ -457,7 +437,7 @@ static void ax25_write_wakeup(struct tty_struct *tty)
 /* Encapsulate an AX.25 packet and kick it into a TTY queue. */
 static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       struct ax_disp *ax = (struct ax_disp*)dev->priv;
+       struct ax_disp *ax = (struct ax_disp *) dev->priv;
        struct mkiss_channel *mkiss = ax->tty->driver_data;
        struct ax_disp *tmp_ax;
 
@@ -543,7 +523,7 @@ static int ax_rebuild_header(struct sk_buff *skb)
 /* Open the low-level part of the AX25 channel. Easy! */
 static int ax_open(struct net_device *dev)
 {
-       struct ax_disp *ax = (struct ax_disp*)dev->priv;
+       struct ax_disp *ax = (struct ax_disp *) dev->priv;
        unsigned long len;
 
        if (ax->tty == NULL)
@@ -554,7 +534,6 @@ static int ax_open(struct net_device *dev)
         *
         * rbuff        Receive buffer.
         * xbuff        Transmit buffer.
-        * cbuff        Temporary compression buffer.
         */
        len = dev->mtu * 2;
 
@@ -582,9 +561,6 @@ static int ax_open(struct net_device *dev)
        netif_start_queue(dev);
        return 0;
 
-       /* Cleanup */
-       kfree(ax->xbuff);
-
 noxbuff:
        kfree(ax->rbuff);
 
@@ -596,7 +572,7 @@ norbuff:
 /* Close the low-level part of the AX25 channel. Easy! */
 static int ax_close(struct net_device *dev)
 {
-       struct ax_disp *ax = (struct ax_disp*)dev->priv;
+       struct ax_disp *ax = (struct ax_disp *) dev->priv;
 
        if (ax->tty == NULL)
                return -EBUSY;
@@ -621,7 +597,7 @@ static int ax25_receive_room(struct tty_struct *tty)
  */
 static void ax25_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
 {
-       struct ax_disp *ax = (struct ax_disp *)tty->disc_data;
+       struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
 
        if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))
                return;
@@ -648,7 +624,7 @@ static void ax25_receive_buf(struct tty_struct *tty, const unsigned char *cp, ch
 
 static int ax25_open(struct tty_struct *tty)
 {
-       struct ax_disp *ax = (struct ax_disp *)tty->disc_data;
+       struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
        struct ax_disp *tmp_ax;
        struct mkiss_channel *mkiss;
        int err, cnt;
@@ -679,7 +655,7 @@ static int ax25_open(struct tty_struct *tty)
        if ((err = ax_open(ax->dev)))
                return err;
 
-       mkiss= ax->tty->driver_data;
+       mkiss = ax->tty->driver_data;
 
        if (mkiss->magic  == MKISS_DRIVER_MAGIC) {
                for (cnt = 1; cnt < ax25_maxdev; cnt++) {
@@ -708,24 +684,19 @@ static int ax25_open(struct tty_struct *tty)
 
 static void ax25_close(struct tty_struct *tty)
 {
-       struct ax_disp *ax = (struct ax_disp *)tty->disc_data;
-       int mkiss ;
+       struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
 
        /* First make sure we're connected. */
        if (ax == NULL || ax->magic != AX25_MAGIC)
                return;
 
-       mkiss = ax->mode;
-
        dev_close(ax->dev);
 
        tty->disc_data = 0;
        ax->tty        = NULL;
 
-       /* VSV = very important to remove timers */
        ax_free(ax);
        unregister_netdev(ax->dev);
-
        MOD_DEC_USE_COUNT;
 }
 
@@ -733,7 +704,7 @@ static void ax25_close(struct tty_struct *tty)
 static struct net_device_stats *ax_get_stats(struct net_device *dev)
 {
        static struct net_device_stats stats;
-       struct ax_disp *ax = (struct ax_disp*)dev->priv;
+       struct ax_disp *ax = (struct ax_disp *) dev->priv;
 
        memset(&stats, 0, sizeof(struct net_device_stats));
 
@@ -753,7 +724,7 @@ static struct net_device_stats *ax_get_stats(struct net_device *dev)
  *                        STANDARD ENCAPSULATION                        *
  ************************************************************************/
 
-int kiss_esc(unsigned char *s, unsigned char *d, int len)
+static int kiss_esc(unsigned char *s, unsigned char *d, int len)
 {
        unsigned char *ptr = d;
        unsigned char c;
@@ -866,7 +837,7 @@ static void kiss_unesc(struct ax_disp *ax, unsigned char s)
 }
 
 
-int ax_set_mac_address(struct net_device *dev, void *addr)
+static int ax_set_mac_address(struct net_device *dev, void *addr)
 {
        if (copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN))
                return -EFAULT;
@@ -886,7 +857,7 @@ static int ax_set_dev_mac_address(struct net_device *dev, void *addr)
 /* Perform I/O control on an active ax25 channel. */
 static int ax25_disp_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
 {
-       struct ax_disp *ax = (struct ax_disp *)tty->disc_data;
+       struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
        unsigned int tmp;
 
        /* First make sure we're connected. */
@@ -900,12 +871,12 @@ static int ax25_disp_ioctl(struct tty_struct *tty, void *file, int cmd, void *ar
                        return 0;
 
                case SIOCGIFENCAP:
-                       put_user(4, (int *)arg);
-                       return 0;
+                       return put_user(4, (int *)arg);
 
                case SIOCSIFENCAP:
-                       get_user(tmp, (int *)arg);
-                       ax->mode = tmp;
+                       if (get_user(tmp, (int *)arg))
+                               return -EFAULT;
+                       ax->mode = tmp;
                        ax->dev->addr_len        = AX25_ADDR_LEN;         /* sizeof an AX.25 addr */
                        ax->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
                        ax->dev->type            = ARPHRD_AX25;
@@ -921,59 +892,19 @@ static int ax25_disp_ioctl(struct tty_struct *tty, void *file, int cmd, void *ar
 
 static int ax_open_dev(struct net_device *dev)
 {
-       struct ax_disp *ax = (struct ax_disp*)dev->priv;
+       struct ax_disp *ax = (struct ax_disp *) dev->priv;
 
-       if (ax->tty==NULL)
+       if (ax->tty == NULL)
                return -ENODEV;
 
        return 0;
 }
 
-/* Initialize AX25 control device -- register AX25 line discipline */
-int __init mkiss_init_ctrl_dev(void)
-{
-       int status;
-
-       if (ax25_maxdev < 4) ax25_maxdev = 4; /* Sanity */
-
-       if ((ax25_ctrls = kmalloc(sizeof(void*) * ax25_maxdev, GFP_KERNEL)) == NULL) {
-               printk(KERN_ERR "mkiss: Can't allocate ax25_ctrls[] array !  No mkiss available\n");
-               return -ENOMEM;
-       }
-
-       /* Clear the pointer array, we allocate devices when we need them */
-       memset(ax25_ctrls, 0, sizeof(void*) * ax25_maxdev); /* Pointers */
-
-       /* Fill in our line protocol discipline, and register it */
-       memset(&ax_ldisc, 0, sizeof(ax_ldisc));
-       ax_ldisc.magic  = TTY_LDISC_MAGIC;
-       ax_ldisc.name   = "mkiss";
-       ax_ldisc.flags  = 0;
-       ax_ldisc.open   = ax25_open;
-       ax_ldisc.close  = ax25_close;
-       ax_ldisc.read   = NULL;
-       ax_ldisc.write  = NULL;
-       ax_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *, unsigned int, unsigned long))ax25_disp_ioctl;
-       ax_ldisc.poll   = NULL;
-
-       ax_ldisc.receive_buf  = ax25_receive_buf;
-       ax_ldisc.receive_room = ax25_receive_room;
-       ax_ldisc.write_wakeup = ax25_write_wakeup;
-
-       if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0)
-               printk(KERN_ERR "mkiss: can't register line discipline (err = %d)\n", status);
-
-       mkiss_init();
-
-       return status;
-}
-
 
 /* Initialize the driver.  Called by network startup. */
-
 static int ax25_init(struct net_device *dev)
 {
-       struct ax_disp *ax = (struct ax_disp*)dev->priv;
+       struct ax_disp *ax = (struct ax_disp *) dev->priv;
 
        static char ax25_bcast[AX25_ADDR_LEN] =
                {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
@@ -994,22 +925,17 @@ static int ax25_init(struct net_device *dev)
        dev->open            = ax_open_dev;
        dev->stop            = ax_close;
        dev->get_stats       = ax_get_stats;
-#ifdef HAVE_SET_MAC_ADDR
        dev->set_mac_address = ax_set_dev_mac_address;
-#endif
        dev->hard_header_len = 0;
        dev->addr_len        = 0;
        dev->type            = ARPHRD_AX25;
        dev->tx_queue_len    = 10;
+       dev->hard_header     = ax_header;
+       dev->rebuild_header  = ax_rebuild_header;
 
        memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
        memcpy(dev->dev_addr,  ax25_test,  AX25_ADDR_LEN);
 
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
-       dev->hard_header     = ax_header;
-       dev->rebuild_header  = ax_rebuild_header;
-#endif
-
        dev_init_buffers(dev);
 
        /* New-style flags. */
@@ -1018,219 +944,74 @@ static int ax25_init(struct net_device *dev)
        return 0;
 }
 
-static int mkiss_open(struct tty_struct *tty, struct file *filp)
-{
-       struct mkiss_channel *mkiss;
-       int chan;
-
-       chan = MINOR(tty->device) - tty->driver.minor_start;
-
-       if (chan < 0 || chan >= NR_MKISS)
-               return -ENODEV;
-
-       mkiss = &MKISS_Info[chan];
-
-       mkiss->magic =  MKISS_DRIVER_MAGIC;
-       mkiss->init  = 1;
-       mkiss->tty   = tty;
-
-       tty->driver_data = mkiss;
-
-       tty->termios->c_iflag  = IGNBRK | IGNPAR;
-       tty->termios->c_cflag  = B9600 | CS8 | CLOCAL;
-       tty->termios->c_cflag &= ~CBAUD;
-
-       return 0;
-}
-
-static void mkiss_close(struct tty_struct *tty, struct file * filp)
-{
-       struct mkiss_channel *mkiss = tty->driver_data;
-
-       if (mkiss == NULL || mkiss->magic != MKISS_DRIVER_MAGIC)
-                return;
-
-       mkiss->tty   = NULL;
-       mkiss->init  = 0;
-       tty->stopped = 0;
-}
-
-static int mkiss_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
-{
-       return 0;
-}
-
-static int mkiss_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
-{
-       /* Ignore serial ioctl's */
-       switch (cmd) {
-               case TCSBRK:
-               case TIOCMGET:
-               case TIOCMBIS:
-               case TIOCMBIC:
-               case TIOCMSET:
-               case TCSETS:
-               case TCSETSF:           /* should flush first, but... */
-               case TCSETSW:           /* should wait until flush, but... */
-                       return 0;
-               default:
-                       return -ENOIOCTLCMD;
-       }
-}
-
-
-static void mkiss_dummy(struct tty_struct *tty)
-{
-       struct mkiss_channel *mkiss = tty->driver_data;
-
-       if (tty == NULL)
-               return;
-
-       if (mkiss == NULL)
-               return;
-}
-
-static void mkiss_dummy2(struct tty_struct *tty, unsigned char ch)
-{
-       struct mkiss_channel *mkiss = tty->driver_data;
-
-       if (tty == NULL)
-               return;
-
-       if (mkiss == NULL)
-               return;
-}
-
-
-static int mkiss_write_room(struct tty_struct * tty)
-{
-       struct mkiss_channel *mkiss = tty->driver_data;
-
-       if (tty == NULL)
-               return 0;
-
-       if (mkiss == NULL)
-               return 0;
-
-       return 65536;  /* We can handle an infinite amount of data. :-) */
-}
-
-
-static int mkiss_chars_in_buffer(struct tty_struct *tty)
-{
-       struct mkiss_channel *mkiss = tty->driver_data;
-
-       if (tty == NULL)
-               return 0;
-
-       if (mkiss == NULL)
-               return 0;
-
-       return 0;
-}
-
-
-static void mkiss_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
-       /* we don't do termios */
-}
 
 /* ******************************************************************** */
-/* *                   Init MKISS driver                             * */
+/* *                   Init MKISS driver                             * */
 /* ******************************************************************** */
 
-static int __init mkiss_init(void)
+static int __init mkiss_init_driver(void)
 {
-       memset(&mkiss_driver, 0, sizeof(struct tty_driver));
-
-       mkiss_driver.magic       = MKISS_DRIVER_MAGIC;
-       mkiss_driver.name        = "mkiss";
-       mkiss_driver.major       = MKISS_MAJOR;
-       mkiss_driver.minor_start = 0;
-       mkiss_driver.num         = NR_MKISS;
-       mkiss_driver.type        = TTY_DRIVER_TYPE_SERIAL;
-       mkiss_driver.subtype     = MKISS_SERIAL_TYPE_NORMAL;    /* not needed */
-
-       mkiss_driver.init_termios         = tty_std_termios;
-       mkiss_driver.init_termios.c_iflag = IGNBRK | IGNPAR;
-       mkiss_driver.init_termios.c_cflag = B9600 | CS8 | CLOCAL;
-
-       mkiss_driver.flags           = TTY_DRIVER_REAL_RAW;
-       mkiss_driver.refcount        = &mkiss_refcount;
-       mkiss_driver.table           = mkiss_table;
-       mkiss_driver.termios         = (struct termios **)mkiss_termios;
-       mkiss_driver.termios_locked  = (struct termios **)mkiss_termios_locked;
-
-       mkiss_driver.ioctl           = mkiss_ioctl;
-       mkiss_driver.open            = mkiss_open;
-       mkiss_driver.close           = mkiss_close;
-       mkiss_driver.write           = mkiss_write;
-       mkiss_driver.write_room      = mkiss_write_room;
-       mkiss_driver.chars_in_buffer = mkiss_chars_in_buffer;
-       mkiss_driver.set_termios     = mkiss_set_termios;
-
-       /* some unused functions */
-       mkiss_driver.flush_buffer = mkiss_dummy;
-       mkiss_driver.throttle     = mkiss_dummy;
-       mkiss_driver.unthrottle   = mkiss_dummy;
-       mkiss_driver.stop         = mkiss_dummy;
-       mkiss_driver.start        = mkiss_dummy;
-       mkiss_driver.hangup       = mkiss_dummy;
-       mkiss_driver.flush_chars  = mkiss_dummy;
-       mkiss_driver.put_char     = mkiss_dummy2;
-
-       if (tty_register_driver(&mkiss_driver)) {
-               printk(KERN_ERR "mkiss: couldn't register Mkiss device\n");
-               return -EIO;
-       }
+       int status;
 
-       printk(KERN_INFO "AX.25 Multikiss device enabled\n");
+       printk(banner);
 
-       return 0;
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
+       if (ax25_maxdev < 4)
+         ax25_maxdev = 4; /* Sanity */
 
-MODULE_PARM(ax25_maxdev, "i");
-MODULE_PARM_DESC(ax25_maxdev, "number of MKISS devices");
+       if ((ax25_ctrls = kmalloc(sizeof(void *) * ax25_maxdev, GFP_KERNEL)) == NULL) {
+               printk(KERN_ERR "mkiss: Can't allocate ax25_ctrls[] array!\n");
+               return -ENOMEM;
+       }
 
-MODULE_AUTHOR("Hans Albas PE1AYX <hans@esrac.ele.tue.nl>");
-MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
+       /* Clear the pointer array, we allocate devices when we need them */
+       memset(ax25_ctrls, 0, sizeof(void*) * ax25_maxdev); /* Pointers */
 
-int init_module(void)
-{
-       return mkiss_init_ctrl_dev();
+       /* Fill in our line protocol discipline, and register it */
+       ax_ldisc.magic          = TTY_LDISC_MAGIC;
+       ax_ldisc.name           = "mkiss";
+       ax_ldisc.open           = ax25_open;
+       ax_ldisc.close          = ax25_close;
+       ax_ldisc.ioctl          = (int (*)(struct tty_struct *, struct file *,
+                                       unsigned int, unsigned long))ax25_disp_ioctl;
+       ax_ldisc.receive_buf    = ax25_receive_buf;
+       ax_ldisc.receive_room   = ax25_receive_room;
+       ax_ldisc.write_wakeup   = ax25_write_wakeup;
+
+       if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0) {
+               printk(KERN_ERR "mkiss: can't register line discipline (err = %d)\n", status);
+               kfree(ax25_ctrls);
+       }
+       return status;
 }
 
-void cleanup_module(void)
+static void __exit mkiss_exit_driver(void)
 {
        int i;
 
-       if (ax25_ctrls != NULL) {
-               for (i = 0; i < ax25_maxdev; i++) {
-                       if (ax25_ctrls[i]) {
-                               /*
-                                * VSV = if dev->start==0, then device
-                                * unregistred while close proc.
-                                */
-                               if (netif_running(&ax25_ctrls[i]->dev))
-                                       unregister_netdev(&(ax25_ctrls[i]->dev));
-
-                               kfree(ax25_ctrls[i]);
-                               ax25_ctrls[i] = NULL;
-                       }
+       for (i = 0; i < ax25_maxdev; i++) {
+               if (ax25_ctrls[i]) {
+                       /*
+                       * VSV = if dev->start==0, then device
+                       * unregistered while close proc.
+                       */
+                       if (netif_running(&ax25_ctrls[i]->dev))
+                               unregister_netdev(&ax25_ctrls[i]->dev);
+                       kfree(ax25_ctrls[i]);
                }
-
-               kfree(ax25_ctrls);
-               ax25_ctrls = NULL;
        }
 
+       kfree(ax25_ctrls);
+       ax25_ctrls = NULL;
+
        if ((i = tty_register_ldisc(N_AX25, NULL)))
                printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i);
-
-       if (tty_unregister_driver(&mkiss_driver))       /* remove devive */
-               printk(KERN_ERR "mkiss: can't unregister MKISS device\n");
 }
 
-#endif /* MODULE */
+MODULE_AUTHOR("Hans Albas PE1AYX <hans@esrac.ele.tue.nl>");
+MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
+MODULE_PARM(ax25_maxdev, "i");
+MODULE_PARM_DESC(ax25_maxdev, "number of MKISS devices");
+
+module_init(mkiss_init_driver);
+module_exit(mkiss_exit_driver);
+
index 6ca7e2cc157aac2bc482eb1782ece0891dc078d6..38957568b6e4a0d8aad65c235e862f6748527f1a 100644 (file)
@@ -60,7 +60,7 @@
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 /* prototypes for ax25_encapsulate and ax25_rebuild_header */
 #include <net/ax25.h>
-#endif                                                 /* CONFIG_AX25 || CONFIG_AX25_MODULE */
+#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
 
 /* make genksyms happy */
 #include <linux/ip.h>
 /* --------------------------------------------------------------------- */
 
 static const char yam_drvname[] = "yam";
-static const char yam_drvinfo[] = KERN_INFO "YAM driver version 0.8 by F1OAT/F6FBB\n";
+static const char yam_drvinfo[] __initdata = KERN_INFO "YAM driver version 0.8 by F1OAT/F6FBB\n";
 
 /* --------------------------------------------------------------------- */
 
 #define YAM_9600       1
 #define YAM_1200       2
 
-#define NR_PORTS       4
+#define NR_PORTS       4
 #define YAM_MAGIC      0xF10A7654
 
 /* Transmitter states */
 
-#define TX_OFF         0
+#define TX_OFF         0
 #define TX_HEAD                1
-#define TX_DATA        2
-#define TX_CRC1        3
-#define TX_CRC2        4
-#define TX_TAIL        5
+#define TX_DATA                2
+#define TX_CRC1                3
+#define TX_CRC2                4
+#define TX_TAIL                5
 
 #define YAM_MAX_FRAME  1024
 
-#define DEFAULT_BITRATE        9600    /* bps */
-#define DEFAULT_HOLDD   10             /* sec */
-#define DEFAULT_TXD        300         /* ms */
-#define DEFAULT_TXTAIL  10             /* ms */
-#define DEFAULT_SLOT    100            /* ms */
-#define DEFAULT_PERS    64             /* 0->255 */
+#define DEFAULT_BITRATE        9600                    /* bps */
+#define DEFAULT_HOLDD  10                      /* sec */
+#define DEFAULT_TXD    300                     /* ms */
+#define DEFAULT_TXTAIL 10                      /* ms */
+#define DEFAULT_SLOT   100                     /* ms */
+#define DEFAULT_PERS   64                      /* 0->255 */
 
 struct yam_port {
        int magic;
@@ -128,11 +128,11 @@ struct yam_port {
 
        /* Parameters section */
 
-       int txd;                                        /* tx delay */
-       int holdd;                                      /* duplex ptt delay */
-       int txtail;                                     /* txtail delay */
-       int slot;                                       /* slottime */
-       int pers;                                       /* persistence */
+       int txd;                                /* tx delay */
+       int holdd;                              /* duplex ptt delay */
+       int txtail;                             /* txtail delay */
+       int slot;                               /* slottime */
+       int pers;                               /* persistence */
 
        /* Tx section */
 
@@ -160,9 +160,7 @@ struct yam_mcs {
 
 static struct yam_port yam_ports[NR_PORTS];
 
-static struct yam_mcs *yam_data = NULL;
-
-static unsigned irqs[16];
+static struct yam_mcs *yam_data;
 
 static char ax25_bcast[7] =
 {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
@@ -173,91 +171,89 @@ static struct timer_list yam_timer;
 
 /* --------------------------------------------------------------------- */
 
-#define RBR(iobase) (iobase+0)
-#define THR(iobase) (iobase+0)
-#define IER(iobase) (iobase+1)
-#define IIR(iobase) (iobase+2)
-#define FCR(iobase) (iobase+2)
-#define LCR(iobase) (iobase+3)
-#define MCR(iobase) (iobase+4)
-#define LSR(iobase) (iobase+5)
-#define MSR(iobase) (iobase+6)
-#define SCR(iobase) (iobase+7)
-#define DLL(iobase) (iobase+0)
-#define DLM(iobase) (iobase+1)
-
-#define YAM_EXTENT 8
+#define RBR(iobase)    (iobase+0)
+#define THR(iobase)    (iobase+0)
+#define IER(iobase)    (iobase+1)
+#define IIR(iobase)    (iobase+2)
+#define FCR(iobase)    (iobase+2)
+#define LCR(iobase)    (iobase+3)
+#define MCR(iobase)    (iobase+4)
+#define LSR(iobase)    (iobase+5)
+#define MSR(iobase)    (iobase+6)
+#define SCR(iobase)    (iobase+7)
+#define DLL(iobase)    (iobase+0)
+#define DLM(iobase)    (iobase+1)
+
+#define YAM_EXTENT     8
 
 /* Interrupt Identification Register Bit Masks */
-#define IIR_NOPEND     1
-#define IIR_MSR        0
-#define IIR_TX         2
-#define IIR_RX         4
-#define IIR_LSR        6
+#define IIR_NOPEND     1
+#define IIR_MSR                0
+#define IIR_TX         2
+#define IIR_RX         4
+#define IIR_LSR                6
 #define IIR_TIMEOUT    12                      /* Fifo mode only */
 
 #define IIR_MASK       0x0F
 
 /* Interrupt Enable Register Bit Masks */
-#define IER_RX  1                              /* enable rx interrupt */
-#define IER_TX  2                              /* enable tx interrupt */
-#define IER_LSR 4                              /* enable line status interrupts */
-#define IER_MSR 8                              /* enable modem status interrupts */
+#define IER_RX         1                       /* enable rx interrupt */
+#define IER_TX         2                       /* enable tx interrupt */
+#define IER_LSR                4                       /* enable line status interrupts */
+#define IER_MSR                8                       /* enable modem status interrupts */
 
 /* Modem Control Register Bit Masks */
-#define MCR_DTR  0x01                  /* DTR output */
-#define MCR_RTS  0x02                  /* RTS output */
-#define MCR_OUT1 0x04                  /* OUT1 output (not accessible in RS232) */
-#define MCR_OUT2 0x08                  /* Master Interrupt enable (must be set on PCs) */
-#define MCR_LOOP 0x10                  /* Loopback enable */
+#define MCR_DTR                0x01                    /* DTR output */
+#define MCR_RTS                0x02                    /* RTS output */
+#define MCR_OUT1       0x04                    /* OUT1 output (not accessible in RS232) */
+#define MCR_OUT2       0x08                    /* Master Interrupt enable (must be set on PCs) */
+#define MCR_LOOP       0x10                    /* Loopback enable */
 
 /* Modem Status Register Bit Masks */
-#define MSR_DCTS 0x01                  /* Delta CTS input */
-#define MSR_DDSR 0x02                  /* Delta DSR */
-#define MSR_DRIN 0x04                  /* Delta RI */
-#define MSR_DDCD 0x08                  /* Delta DCD */
-#define MSR_CTS  0x10                  /* CTS input */
-#define MSR_DSR  0x20                  /* DSR input */
-#define MSR_RING 0x40                  /* RI  input */
-#define MSR_DCD  0x80                  /* DCD input */
+#define MSR_DCTS       0x01                    /* Delta CTS input */
+#define MSR_DDSR       0x02                    /* Delta DSR */
+#define MSR_DRIN       0x04                    /* Delta RI */
+#define MSR_DDCD       0x08                    /* Delta DCD */
+#define MSR_CTS                0x10                    /* CTS input */
+#define MSR_DSR                0x20                    /* DSR input */
+#define MSR_RING       0x40                    /* RI  input */
+#define MSR_DCD                0x80                    /* DCD input */
 
 /* line status register bit mask */
-#define LSR_RXC           0x01
-#define LSR_OE    0x02
-#define LSR_PE    0x04
-#define LSR_FE    0x08
-#define LSR_BREAK  0x10
-#define LSR_THRE   0x20
-#define LSR_TSRE   0x40
+#define LSR_RXC                0x01
+#define LSR_OE         0x02
+#define LSR_PE         0x04
+#define LSR_FE         0x08
+#define LSR_BREAK      0x10
+#define LSR_THRE       0x20
+#define LSR_TSRE       0x40
 
 /* Line Control Register Bit Masks */
-#define LCR_DLAB    0x80
-#define LCR_BREAK   0x40
-#define LCR_PZERO   0x28
-#define LCR_PEVEN   0x18
-#define LCR_PODD    0x08
-#define LCR_STOP1   0x00
-#define LCR_STOP2   0x04
-#define LCR_BIT5    0x00
-#define LCR_BIT6    0x02
-#define LCR_BIT7    0x01
-#define LCR_BIT8    0x03
+#define LCR_DLAB       0x80
+#define LCR_BREAK      0x40
+#define LCR_PZERO      0x28
+#define LCR_PEVEN      0x18
+#define LCR_PODD       0x08
+#define LCR_STOP1      0x00
+#define LCR_STOP2      0x04
+#define LCR_BIT5       0x00
+#define LCR_BIT6       0x02
+#define LCR_BIT7       0x01
+#define LCR_BIT8       0x03
 
 /* YAM Modem <-> UART Port mapping */
 
-#define TX_RDY           MSR_DCTS              /* transmitter ready to send */
-#define RX_DCD    MSR_DCD              /* carrier detect */
-#define RX_FLAG   MSR_RING             /* hdlc flag received */
-#define FPGA_DONE MSR_DSR              /* FPGA is configured */
-#define PTT_ON    (MCR_RTS|MCR_OUT2)   /* activate PTT */
-#define PTT_OFF   (MCR_DTR|MCR_OUT2)   /* release PTT */
+#define TX_RDY         MSR_DCTS                /* transmitter ready to send */
+#define RX_DCD         MSR_DCD                 /* carrier detect */
+#define RX_FLAG                MSR_RING                /* hdlc flag received */
+#define FPGA_DONE      MSR_DSR                 /* FPGA is configured */
+#define PTT_ON         (MCR_RTS|MCR_OUT2)      /* activate PTT */
+#define PTT_OFF                (MCR_DTR|MCR_OUT2)      /* release PTT */
 
-#define ENABLE_RXINT   IER_RX  /* enable uart rx interrupt during rx */
-#define ENABLE_TXINT   IER_MSR /* enable uart ms interrupt during tx */
-#define ENABLE_RTXINT  (IER_RX|IER_MSR)                /* full duplex operations */
+#define ENABLE_RXINT   IER_RX                  /* enable uart rx interrupt during rx */
+#define ENABLE_TXINT   IER_MSR                 /* enable uart ms interrupt during tx */
+#define ENABLE_RTXINT  (IER_RX|IER_MSR)        /* full duplex operations */
 
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
 
 /*************************************************************************
 * CRC Tables
@@ -357,21 +353,7 @@ static int fpga_write(int iobase, unsigned char wrd)
        return 0;
 }
 
-#ifdef MODULE
-static void free_mcs(void)
-{
-       struct yam_mcs *p;
-
-       while (yam_data) {
-               p = yam_data;
-               yam_data = yam_data->next;
-               kfree(p);
-       }
-}
-#endif
-
-static unsigned char *
- add_mcs(unsigned char *bits, int bitrate)
+static unsigned char *add_mcs(unsigned char *bits, int bitrate)
 {
        struct yam_mcs *p;
 
@@ -386,8 +368,7 @@ static unsigned char *
        }
 
        /* Allocate a new mcs */
-       p = kmalloc(sizeof(struct yam_mcs), GFP_ATOMIC);
-       if (p == NULL) {
+       if ((p = kmalloc(sizeof(struct yam_mcs), GFP_KERNEL)) == NULL) {
                printk(KERN_WARNING "YAM: no memory to allocate mcs\n");
                return NULL;
        }
@@ -421,7 +402,7 @@ static unsigned char *get_mcs(int bitrate)
 
 /*
  * download bitstream to FPGA
- * data is contained in bits[] array in fpgaconf.h
+ * data is contained in bits[] array in yam1200.h resp. yam9600.h
  */
 
 static int fpga_download(int iobase, int bitrate)
@@ -436,7 +417,7 @@ static int fpga_download(int iobase, int bitrate)
        fpga_reset(iobase);
        for (i = 0; i < YAM_FPGA_SIZE; i++) {
                if (fpga_write(iobase, pbits[i])) {
-                       printk("yam: error in write cycle\n");
+                       printk(KERN_ERR "yam: error in write cycle\n");
                        return -1;                      /* write... */
                }
        }
@@ -523,8 +504,7 @@ static enum uart yam_check_uart(unsigned int iobase)
 /******************************************************************************
 * Rx Section
 ******************************************************************************/
-static void inline
- yam_rx_flag(struct net_device *dev, struct yam_port *yp)
+static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp)
 {
        if (yp->dcd && yp->rx_len >= 3 && yp->rx_len < YAM_MAX_FRAME) {
                int pkt_len = yp->rx_len - 2 + 1;       /* -CRC + kiss */
@@ -534,7 +514,7 @@ static void inline
                        /* Bad crc */
                } else {
                        if (!(skb = dev_alloc_skb(pkt_len))) {
-                               printk("%s: memory squeeze, dropping packet\n", dev->name);
+                               printk(KERN_WARNING "%s: memory squeeze, dropping packet\n", dev->name);
                                ++yp->stats.rx_dropped;
                        } else {
                                unsigned char *cp;
@@ -554,8 +534,7 @@ static void inline
        yp->rx_crch = 0xf3;
 }
 
-static void inline
- yam_rx_byte(struct net_device *dev, struct yam_port *yp, unsigned char rxb)
+static inline void yam_rx_byte(struct net_device *dev, struct yam_port *yp, unsigned char rxb)
 {
        if (yp->rx_len < YAM_MAX_FRAME) {
                unsigned char c = yp->rx_crcl;
@@ -583,9 +562,6 @@ static int yam_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
        struct yam_port *yp = dev->priv;
 
-       if (skb == NULL) {
-               return 0;
-       }
        skb_queue_tail(&yp->send_queue, skb);
        dev->trans_start = jiffies;
        return 0;
@@ -761,7 +737,7 @@ static void yam_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        yp->dcd = (msr & RX_DCD) ? 1 : 0;
 
                        if (--counter <= 0) {
-                               printk("%s: too many irq iir=%d\n", dev->name, iir);
+                               printk(KERN_ERR "%s: too many irq iir=%d\n", dev->name, iir);
                                return;
                        }
                        if (msr & TX_RDY) {
@@ -833,19 +809,6 @@ static int yam_net_get_info(char *buffer, char **start, off_t offset, int length
        return len;
 }
 
-#ifdef CONFIG_INET
-#ifdef CONFIG_PROC_FS
-#define yam_net_procfs_init() proc_net_create("yam",0,yam_net_get_info)
-#define yam_net_procfs_remove() proc_net_remove("yam")
-#else
-#define yam_net_procfs_init()
-#define yam_net_procfs_remove()
-#endif /* CONFIG_PROC_FS */
-#else
-#define yam_net_procfs_init()
-#define yam_net_procfs_remove()
-#endif /* CONFIG_INET */
-
 /* --------------------------------------------------------------------- */
 
 static struct net_device_stats *yam_get_stats(struct net_device *dev)
@@ -883,20 +846,20 @@ static int yam_open(struct net_device *dev)
                return -ENXIO;
        }
        if (check_region(dev->base_addr, YAM_EXTENT)) {
-               printk("%s: cannot 0x%lx busy\n", dev->name, dev->base_addr);
+               printk(KERN_ERR "%s: cannot 0x%lx busy\n", dev->name, dev->base_addr);
                return -EACCES;
        }
        if ((u = yam_check_uart(dev->base_addr)) == c_uart_unknown) {
-               printk("%s: cannot find uart type\n", dev->name);
+               printk(KERN_ERR "%s: cannot find uart type\n", dev->name);
                return -EIO;
        }
        if (fpga_download(dev->base_addr, yp->bitrate)) {
-               printk("%s: cannot init FPGA\n", dev->name);
+               printk(KERN_ERR "%s: cannot init FPGA\n", dev->name);
                return -EIO;
        }
        outb(0, IER(dev->base_addr));
        if (request_irq(dev->irq, yam_interrupt, SA_INTERRUPT | SA_SHIRQ, dev->name, NULL)) {
-               printk("%s: irq %d busy\n", dev->name, dev->irq);
+               printk(KERN_ERR "%s: irq %d busy\n", dev->name, dev->irq);
                return -EBUSY;
        }
        request_region(dev->base_addr, YAM_EXTENT, dev->name);
@@ -975,7 +938,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case SIOCYAMSMCS:
                if (netif_running(dev))
                        return -EINVAL;         /* Cannot change this parameter when up */
-               ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_ATOMIC);
+               ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_KERNEL);
                if(ym==NULL)
                        return -ENOBUFS;
                ym->bitrate = 9600;
@@ -1135,17 +1098,13 @@ static int yam_probe(struct net_device *dev)
 
 /* --------------------------------------------------------------------- */
 
-int __init yam_init(void)
+static int __init yam_init_driver(void)
 {
        struct net_device *dev;
        int i;
 
        printk(yam_drvinfo);
 
-       /* Clears the IRQ table */
-       memset(irqs, 0, sizeof(irqs));
-       memset(yam_ports, 0, sizeof(yam_ports));
-
        for (i = 0; i < NR_PORTS; i++) {
                sprintf(yam_ports[i].dev.name, "yam%d", i);
                yam_ports[i].magic = YAM_MAGIC;
@@ -1169,7 +1128,7 @@ int __init yam_init(void)
                dev->if_port = 0;
 
                if (register_netdev(dev)) {
-                       printk(KERN_WARNING "yam: cannot register net  device %s\n", dev->name);
+                       printk(KERN_WARNING "yam: cannot register net device %s\n", dev->name);
                        return -ENXIO;
                }
        }
@@ -1178,33 +1137,15 @@ int __init yam_init(void)
        yam_timer.expires = jiffies + HZ / 100;
        add_timer(&yam_timer);
 
-       yam_net_procfs_init();
-       return 1;
-}
-
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-/*
- * command line settable parameters
- */
-
-
-MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr");
-MODULE_DESCRIPTION("Yam amateur radio modem driver");
-
-int init_module(void)
-{
-       int ret = yam_init();
-
-       return (ret == 1) ? 0 : ret;
+       proc_net_create("yam", 0, yam_net_get_info);
+       return 0;
 }
 
 /* --------------------------------------------------------------------- */
 
-void cleanup_module(void)
+static void __exit yam_cleanup_driver(void)
 {
+       struct yam_mcs *p;
        int i;
 
        del_timer(&yam_timer);
@@ -1216,9 +1157,23 @@ void cleanup_module(void)
                        yam_close(dev);
                unregister_netdev(dev);
        }
-       free_mcs();
-       yam_net_procfs_remove();
+
+       while (yam_data) {
+               p = yam_data;
+               yam_data = yam_data->next;
+               kfree(p);
+       }
+
+       proc_net_remove("yam");
 }
 
-#endif                                                 /* MODULE */
 /* --------------------------------------------------------------------- */
+
+MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr");
+MODULE_DESCRIPTION("Yam amateur radio modem driver");
+
+module_init(yam_init_driver);
+module_exit(yam_cleanup_driver);
+
+/* --------------------------------------------------------------------- */
+
index b6e99d212948e3c2d17840b31c214a7ee9039394..b527596fe281e03e42653228936ffd66bd728073 100644 (file)
@@ -416,12 +416,10 @@ void unregister_ss_entry(struct pccard_operations * ss_entry)
 {
     int i;
 
-    for (i = 0; i < sockets; i++) {
+    for (i = sockets-1; i >= 0; i-- ) {
        socket_info_t *socket = socket_table[i];
        if (socket->ss_entry == ss_entry)
-           pcmcia_unregister_socket (socket);
-       else
-           i++;
+               pcmcia_unregister_socket (socket);
     }
 } /* unregister_ss_entry */
 
index 25636b008aad0ab75189bdfdc982db5cdeac166e..4274c52cf14c0e5d0e17de96d42a28b7c1341480 100644 (file)
@@ -1604,7 +1604,7 @@ int aha152x_device_reset(Scsi_Cmnd * SCpnt)
 
        init_timer(&timer);
        timer.data     = (unsigned long) &sem;
-       timer.expires  = jiffies + 10000;   /* 10s */
+       timer.expires  = jiffies + 10 * HZ;   /* 10s */
        timer.function = (void (*)(unsigned long)) timer_expired;
        add_timer(&timer);
 
@@ -2579,7 +2579,7 @@ static void datai_run(struct Scsi_Host *shpnt)
                if(TESTHI(DMASTAT, DFIFOFULL)) {
                        fifodata = 128;
                } else {
-                       the_time=jiffies + 100;
+                       the_time=jiffies + HZ;
                        while(TESTLO(SSTAT2, SEMPTY) && time_before(jiffies,the_time))
                                barrier();
 
index 3b9b0e2271b7aeb7f3f67d6d8c11a26f6fd6fa3f..8b91bb2bf11f4154d382eba78df960cbc870eb23 100644 (file)
@@ -281,7 +281,7 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
      */
     spin_lock_irqsave (&io_request_lock, flags);
 
-       DEB(printk ("\npci2000 recieved interrupt "));
+       DEB(printk ("\npci2000 received interrupt "));
        for ( z = 0; z < NumAdapters;  z++ )                                                                            // scan for interrupt to process
                {
                if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
index 6b767a1c8db4149d6d0b7c8afcd9f5d009c86adf..2b6d3122d2f3f1e86655231030d30d554f847ea9 100644 (file)
@@ -370,7 +370,7 @@ static int AtapiWaitDrq (PADAPTER2220I padapter, int msec)
 static int HardReset (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot)
        {
        DEB (printk ("\npci2220i:RESET  spigot = %X  devices = %d, %d", spigot, pdev->deviceID[0], pdev->deviceID[1]));
-       udelay (100000);                                                                                // just wait 100 mSec to let drives flush       
+       mdelay (100);                                                                           // just wait 100 mSec to let drives flush       
        SelectSpigot (padapter, spigot | SEL_IRQ_OFF);
        
        outb_p (0x0E, padapter->regAltStat);                                    // reset the suvivor
@@ -1602,7 +1602,7 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
      */
     spin_lock_irqsave (&io_request_lock, flags);
 
-//     DEB (printk ("\npci2220i recieved interrupt\n"));
+//     DEB (printk ("\npci2220i received interrupt\n"));
 
        for ( z = 0; z < NumAdapters;  z++ )                                                            // scan for interrupt to process
                {
@@ -2855,7 +2855,7 @@ int Pci2220i_Release (struct Scsi_Host *pshost)
                {
                padapter->reconOn = FALSE;                                              // shut down the hot reconstruct
                if ( padapter->reconPhase )
-                       udelay (300000);
+                       mdelay (300);
                if ( padapter->reconTimer.data )                                // is the timer running?
                        {
                        del_timer (&padapter->reconTimer);
index c479ccfc5bed91e448ceb3ec8dc1b4a895576ac4..7035a4f062845566c5a460a7b4add0d46da685d0 100644 (file)
@@ -1449,7 +1449,7 @@ sim710_detect(Scsi_Host_Template * tpnt)
 
     for(indx = 0; indx < no_of_boards; indx++) {
         unsigned long page = __get_free_pages(GFP_ATOMIC, order);
-        if(page == NULL)
+        if(page == 0UL)
         {
                printk(KERN_WARNING "sim710: out of memory registering board %d.\n", indx);
                break;
index 38ac2abf45a2aea9158ce3e8484cc31454cdfa74..b9f345f8b4f827c315bfb480717f002365b60a15 100644 (file)
@@ -1373,10 +1373,17 @@ static unsigned int cm_poll(struct file *file, struct poll_table_struct *wait)
        unsigned int mask = 0;
 
        VALIDATE_STATE(s);
-       if (file->f_mode & FMODE_WRITE)
+       if (file->f_mode & FMODE_WRITE) {
+               if (!s->dma_dac.ready && prog_dmabuf(s, 0))
+                       return 0;
                poll_wait(file, &s->dma_dac.wait, wait);
-       if (file->f_mode & FMODE_READ)
+       }
+       if (file->f_mode & FMODE_READ) {
+               if (!s->dma_adc.ready && prog_dmabuf(s, 1))
+                       return 0;
                poll_wait(file, &s->dma_adc.wait, wait);
+       }
+
        spin_lock_irqsave(&s->lock, flags);
        cm_update_ptr(s);
        if (file->f_mode & FMODE_READ) {
@@ -1604,8 +1611,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!(s->enable & CM_CENABLE_PE) && (val = prog_dmabuf(s, 0)) != 0)
-                       return val;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                cm_update_ptr(s);
                abinfo.fragsize = s->dma_dac.fragsize;
@@ -1618,8 +1625,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!(s->enable & CM_CENABLE_RE) && (val = prog_dmabuf(s, 1)) != 0)
-                       return val;
+               if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                cm_update_ptr(s);
                abinfo.fragsize = s->dma_adc.fragsize;
@@ -1636,6 +1643,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
         case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                cm_update_ptr(s);
                 val = s->dma_dac.count;
@@ -1645,6 +1654,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
         case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                cm_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
@@ -1658,6 +1669,8 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
         case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                cm_update_ptr(s);
                 cinfo.bytes = s->dma_dac.total_bytes;
index 661caa2144ab15fbae7fae4ecf4eb1950daace53..13f1b6c92c18054e32c39fcfc503a7e867ce65f3 100644 (file)
@@ -2489,14 +2489,19 @@ static unsigned int cs4281_poll(struct file *file,
                CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
                          printk(KERN_INFO
                                 "cs4281: cs4281_poll() wait on FMODE_WRITE\n"));
+               if (!s->dma_dac.ready && prog_dmabuf_dac(s))
+                       return 0;
                poll_wait(file, &s->dma_dac.wait, wait);
        }
        if (file->f_mode & FMODE_READ) {
                CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
                          printk(KERN_INFO
                                 "cs4281: cs4281_poll() wait on FMODE_READ\n"));
+               if (!s->dma_adc.ready && prog_dmabuf_adc(s))
+                       return 0;
                poll_wait(file, &s->dma_adc.wait, wait);
        }
+
        spin_lock_irqsave(&s->lock, flags);
        cs4281_update_ptr(s);
        if (file->f_mode & FMODE_WRITE) {
@@ -2516,8 +2521,8 @@ static unsigned int cs4281_poll(struct file *file,
        } else if (file->f_mode & FMODE_READ) {
                if (s->dma_adc.mapped) {
                        if (s->dma_adc.count >=
-                           (signed) s->dma_adc.fragsize) mask |=
-                                   POLLIN | POLLRDNORM;
+                           (signed) s->dma_adc.fragsize)
+                               mask |= POLLIN | POLLRDNORM;
                } else {
                        if (s->dma_adc.count > 0)
                                mask |= POLLIN | POLLRDNORM;
@@ -2836,8 +2841,7 @@ static int cs4281_ioctl(struct inode *inode, struct file *file,
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!(s->ena & FMODE_WRITE)
-                   && (val = prog_dmabuf_dac(s)) != 0)
+               if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)))
                        return val;
                spin_lock_irqsave(&s->lock, flags);
                cs4281_update_ptr(s);
@@ -2865,8 +2869,8 @@ static int cs4281_ioctl(struct inode *inode, struct file *file,
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!(s->ena & FMODE_READ)
-                   && (val = prog_dmabuf_adc(s)) != 0) return val;
+               if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)))
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                cs4281_update_ptr(s);
                if (s->conversion) {
@@ -2893,6 +2897,8 @@ static int cs4281_ioctl(struct inode *inode, struct file *file,
        case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)))
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                cs4281_update_ptr(s);
                val = s->dma_dac.count;
@@ -2902,6 +2908,8 @@ static int cs4281_ioctl(struct inode *inode, struct file *file,
        case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)))
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                cs4281_update_ptr(s);
                cinfo.bytes = s->dma_adc.total_bytes;
@@ -2933,6 +2941,8 @@ static int cs4281_ioctl(struct inode *inode, struct file *file,
        case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)))
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                cs4281_update_ptr(s);
                cinfo.bytes = s->dma_dac.total_bytes;
index 9da701604f99e99574828abf2eb926c89ce653c4..885612f8ce5a693970d7ac19b19282553a6fcd84 100644 (file)
@@ -1537,8 +1537,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!(s->ctrl & CTRL_DAC2_EN) && (val = prog_dmabuf_dac2(s)) != 0)
-                       return val;
+               if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
                abinfo.fragsize = s->dma_dac2.fragsize;
@@ -1554,8 +1554,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!(s->ctrl & CTRL_ADC_EN) && (val = prog_dmabuf_adc(s)) != 0)
-                       return val;
+               if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
                abinfo.fragsize = s->dma_adc.fragsize;
@@ -1575,6 +1575,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
         case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
                 count = s->dma_dac2.count;
@@ -1586,6 +1588,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
         case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
@@ -1602,6 +1606,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
         case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
                 cinfo.bytes = s->dma_dac2.total_bytes;
index 6c525355011eae528f8b9c795e61a616530f5d5e..ae22d6cacc9225fb29f9774b9f083c03861bc887 100644 (file)
@@ -1717,8 +1717,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!(s->ctrl & CTRL_DAC2_EN) && (val = prog_dmabuf_dac2(s)) != 0)
-                       return val;
+               if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
                abinfo.fragsize = s->dma_dac2.fragsize;
@@ -1734,8 +1734,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!(s->ctrl & CTRL_ADC_EN) && (val = prog_dmabuf_adc(s)) != 0)
-                       return val;
+               if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
                abinfo.fragsize = s->dma_adc.fragsize;
@@ -1755,6 +1755,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
         case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
                 count = s->dma_dac2.count;
@@ -1766,6 +1768,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
         case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
@@ -1782,6 +1786,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
         case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
                 cinfo.bytes = s->dma_dac2.total_bytes;
index c06c57633902e70a2dd18395c51ef5d8204462a4..ac2b6d2436995207efab12d7df03314eb3520806 100644 (file)
@@ -1389,8 +1389,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!(s->ena & FMODE_WRITE) && (val = prog_dmabuf_dac(s)) != 0)
-                       return val;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                solo1_update_ptr(s);
                abinfo.fragsize = s->dma_dac.fragsize;
@@ -1406,8 +1406,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!(s->ena & FMODE_READ) && (val = prog_dmabuf_adc(s)) != 0)
-                       return val;
+               if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                solo1_update_ptr(s);
                abinfo.fragsize = s->dma_adc.fragsize;
@@ -1424,6 +1424,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
         case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                solo1_update_ptr(s);
                 count = s->dma_dac.count;
@@ -1435,6 +1437,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
         case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                solo1_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
@@ -1448,6 +1452,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
         case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                solo1_update_ptr(s);
                 cinfo.bytes = s->dma_dac.total_bytes;
index 7529c1db3dbad7e50e06c39b340eab97ba035c1d..6bdb2ade8a37d5529731243385d6e02b878effb5 100644 (file)
@@ -2394,18 +2394,17 @@ static unsigned int ess_poll(struct file *file, struct poll_table_struct *wait)
        struct ess_state *s = (struct ess_state *)file->private_data;
        unsigned long flags;
        unsigned int mask = 0;
-       int ret;
 
        VALIDATE_STATE(s);
 
 /* In 0.14 prog_dmabuf always returns success anyway ... */
        if (file->f_mode & FMODE_WRITE) {
-               if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) 
-                       return POLLERR;
+               if (!s->dma_dac.ready && prog_dmabuf(s, 0)) 
+                       return 0;
        }
        if (file->f_mode & FMODE_READ) {
-               if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
-                       return POLLERR;
+               if (!s->dma_adc.ready && prog_dmabuf(s, 1))
+                       return 0;
        }
 
        if (file->f_mode & FMODE_WRITE)
@@ -2655,8 +2654,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!(s->enable & DAC_RUNNING) && (val = prog_dmabuf(s, 0)) != 0)
-                       return val;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                ess_update_ptr(s);
                abinfo.fragsize = s->dma_dac.fragsize;
@@ -2669,8 +2668,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!(s->enable & ADC_RUNNING) && (val = prog_dmabuf(s, 1)) != 0)
-                       return val;
+               if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                ess_update_ptr(s);
                abinfo.fragsize = s->dma_adc.fragsize;
@@ -2687,6 +2686,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
         case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                ess_update_ptr(s);
                 val = s->dma_dac.count;
@@ -2696,6 +2697,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
         case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                ess_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
@@ -2709,6 +2712,8 @@ static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
         case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                ess_update_ptr(s);
                 cinfo.bytes = s->dma_dac.total_bytes;
index 14f11dcafe188a7bc1fc6f52e6be6b1171deafda..c0f337a4cfb6de5d3ae18caf8196dd4941bc9519 100644 (file)
@@ -1723,8 +1723,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!(s->enable & SV_CENABLE_PE) && (val = prog_dmabuf(s, 0)) != 0)
-                       return val;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                sv_update_ptr(s);
                abinfo.fragsize = s->dma_dac.fragsize;
@@ -1740,8 +1740,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!(s->enable & SV_CENABLE_RE) && (val = prog_dmabuf(s, 1)) != 0)
-                       return val;
+               if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                sv_update_ptr(s);
                abinfo.fragsize = s->dma_adc.fragsize;
@@ -1761,6 +1761,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
         case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                sv_update_ptr(s);
                 count = s->dma_dac.count;
@@ -1772,6 +1774,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
         case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                sv_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
@@ -1788,6 +1792,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
         case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+                       return ret;
                spin_lock_irqsave(&s->lock, flags);
                sv_update_ptr(s);
                 cinfo.bytes = s->dma_dac.total_bytes;
index 9e32811acce8a3d090c5abfaad5103866a982fe2..db5f2b611bf6e092df8d4b0c1f14998cf89f55d0 100644 (file)
@@ -1595,10 +1595,17 @@ static unsigned int trident_poll(struct file *file, struct poll_table_struct *wa
        unsigned int mask = 0;
 
        VALIDATE_STATE(state);
-       if (file->f_mode & FMODE_WRITE)
+
+       if (file->f_mode & FMODE_WRITE) {
+               if (!dmabuf->ready && prog_dmabuf(state, 0))
+                       return 0;
                poll_wait(file, &dmabuf->wait, wait);
-       if (file->f_mode & FMODE_READ)
+       }
+       if (file->f_mode & FMODE_READ) {
+               if (!dmabuf->ready && prog_dmabuf(state, 1))
+                       return 0;
                poll_wait(file, &dmabuf->wait, wait);
+       }
 
        spin_lock_irqsave(&state->card->lock, flags);
        trident_update_ptr(state);
@@ -1866,7 +1873,7 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!dmabuf->enable && (val = prog_dmabuf(state, 0)) != 0)
+               if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
                        return val;
                spin_lock_irqsave(&state->card->lock, flags);
                trident_update_ptr(state);
@@ -1880,7 +1887,7 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!dmabuf->enable && (val = prog_dmabuf(state, 1)) != 0)
+               if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0)
                        return val;
                spin_lock_irqsave(&state->card->lock, flags);
                trident_update_ptr(state);
@@ -1931,6 +1938,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm
        case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0)
+                       return val;
                spin_lock_irqsave(&state->card->lock, flags);
                trident_update_ptr(state);
                cinfo.bytes = dmabuf->total_bytes;
@@ -1944,6 +1953,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm
        case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
+                       return val;
                spin_lock_irqsave(&state->card->lock, flags);
                trident_update_ptr(state);
                cinfo.bytes = dmabuf->total_bytes;
@@ -1960,6 +1971,8 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm
        case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
+                       return val;
                spin_lock_irqsave(&state->card->lock, flags);
                trident_update_ptr(state);
                val = dmabuf->count;
index a3be533e600dfd7afbbff430d5f5fec9e55ca177..398e0a757e669bb10441218d01606d6de35c4d4e 100644 (file)
@@ -725,7 +725,7 @@ static void ixj_timeout(unsigned long ptr)
                                                if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Caller_ID) {
                                                        if (j->daa_mode == SOP_PU_RINGING && j->flags.pstn_ringing) {
                                                                j->pstn_cid_intr = 1;
-                                                               j->pstn_cid_recieved = jiffies;
+                                                               j->pstn_cid_received = jiffies;
                                                        }
                                                }
                                        } else {
@@ -733,7 +733,7 @@ static void ixj_timeout(unsigned long ptr)
                                                        daa_int_read(board);
                                                }
                                                j->ex.bits.pstn_ring = 0;
-                                               if (j->pstn_cid_intr && jiffies > j->pstn_cid_recieved + (hertz * 3)) {
+                                               if (j->pstn_cid_intr && jiffies > j->pstn_cid_received + (hertz * 3)) {
                                                        if (j->daa_mode == SOP_PU_RINGING) {
                                                                ixj_daa_cid_read(board);
                                                                j->ex.bits.caller_id = 1;
index 1fb90b2be1ff0cc1fd191ee46cd5a954fcac2178..7d2f1db08738d907be50ecc5ceafb5242f23725d 100644 (file)
@@ -1250,7 +1250,7 @@ typedef struct {
        unsigned char fskz;
        unsigned char fskphase;
        unsigned char fskcnt;
-       unsigned pstn_cid_recieved;
+       unsigned pstn_cid_received;
        PHONE_CID cid;
        PHONE_CID cid_send;
        unsigned long pstn_ring_start;
index 16112265023176610fedafc2907a3735a939c3f2..b4ea3a1a9de9ad9db03a08f4f622af0063b61f04 100644 (file)
@@ -66,7 +66,7 @@ static int adfs_readpage(struct file *file, struct page *page)
 static int adfs_prepare_write(struct file *file, struct page *page, unsigned int from, unsigned int to)
 {
        return cont_prepare_write(page, from, to, adfs_get_block,
-               &((struct inode *)page->mapping->host)->u.adfs_i.mmu_private);
+               &page->mapping->host->u.adfs_i.mmu_private);
 }
 
 static int _adfs_bmap(struct address_space *mapping, long block)
index 341660c4b3928abb606c9b0681e9ae60de2dd0ee..fac21f70ba55da00ac0506041091afa95412da87 100644 (file)
@@ -349,7 +349,7 @@ static int affs_readpage(struct file *file, struct page *page)
 static int affs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
 {
        return cont_prepare_write(page,from,to,affs_get_block,
-               &((struct inode*)page->mapping->host)->u.affs_i.mmu_private);
+               &page->mapping->host->u.affs_i.mmu_private);
 }
 static int _affs_bmap(struct address_space *mapping, long block)
 {
index b125dee4e855f117ee3560fea60469e70f291acd..78b7f147ebe746de876d1806e95194415fc92add 100644 (file)
@@ -19,7 +19,7 @@
 static int affs_symlink_readpage(struct file *file, struct page *page)
 {
        struct buffer_head *bh;
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        char *link = kmap(page);
        struct slink_front *lf;
        int err;
index 61c3d457470ab5836835afa725f0c62aff0403c5..8aa7b3f06e019b81b53630f39f8ad3fdeb2973ce 100644 (file)
@@ -369,7 +369,9 @@ asmlinkage long sys_fsync(unsigned int fd)
 
        /* We need to protect against concurrent writers.. */
        down(&inode->i_sem);
+       filemap_fdatasync(inode->i_mapping);
        err = file->f_op->fsync(file, dentry, 0);
+       filemap_fdatawait(inode->i_mapping);
        up(&inode->i_sem);
 
 out_putf:
@@ -398,7 +400,9 @@ asmlinkage long sys_fdatasync(unsigned int fd)
                goto out_putf;
 
        down(&inode->i_sem);
+       filemap_fdatasync(inode->i_mapping);
        err = file->f_op->fsync(file, dentry, 1);
+       filemap_fdatawait(inode->i_mapping);
        up(&inode->i_sem);
 
 out_putf:
@@ -1662,7 +1666,7 @@ static int __block_commit_write(struct inode *inode, struct page *page,
  */
 int block_read_full_page(struct page *page, get_block_t *get_block)
 {
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        unsigned long iblock, lblock;
        struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
        unsigned int blocksize, blocks;
@@ -1740,7 +1744,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
 int cont_prepare_write(struct page *page, unsigned offset, unsigned to, get_block_t *get_block, unsigned long *bytes)
 {
        struct address_space *mapping = page->mapping;
-       struct inode *inode = (struct inode*)mapping->host;
+       struct inode *inode = mapping->host;
        struct page *new_page;
        unsigned long pgpos;
        long status;
@@ -1821,7 +1825,7 @@ out:
 int block_prepare_write(struct page *page, unsigned from, unsigned to,
                        get_block_t *get_block)
 {
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        int err = __block_prepare_write(inode, page, from, to, get_block);
        if (err) {
                ClearPageUptodate(page);
@@ -1833,7 +1837,7 @@ int block_prepare_write(struct page *page, unsigned from, unsigned to,
 int generic_commit_write(struct file *file, struct page *page,
                unsigned from, unsigned to)
 {
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
        __block_commit_write(inode,page,from,to);
        kunmap(page);
@@ -1849,7 +1853,7 @@ int block_truncate_page(struct address_space *mapping, loff_t from, get_block_t
        unsigned long index = from >> PAGE_CACHE_SHIFT;
        unsigned offset = from & (PAGE_CACHE_SIZE-1);
        unsigned blocksize, iblock, length, pos;
-       struct inode *inode = (struct inode *)mapping->host;
+       struct inode *inode = mapping->host;
        struct page *page;
        struct buffer_head *bh;
        int err;
@@ -1921,7 +1925,7 @@ out:
 
 int block_write_full_page(struct page *page, get_block_t *get_block)
 {
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
        unsigned offset;
        int err;
@@ -1956,7 +1960,7 @@ done:
 int generic_block_bmap(struct address_space *mapping, long block, get_block_t *get_block)
 {
        struct buffer_head tmp;
-       struct inode *inode = (struct inode*)mapping->host;
+       struct inode *inode = mapping->host;
        tmp.b_state = 0;
        tmp.b_blocknr = 0;
        get_block(inode, block, &tmp, 0);
index e1ab9e89610bdbd7b9a943344fd497477ce57e85..7011582fe3d7e5b4f353976a89161e1308e7d8fd 100644 (file)
@@ -525,7 +525,7 @@ int coda_readdir(struct file *file, void *dirent,  filldir_t filldir)
                 return -EIO;
         }
 
-       container = (struct inode *)inode->i_mapping->host;
+       container = inode->i_mapping->host;
 
        coda_prepare_fakefile(inode, file, container, &open_file, &open_dentry);
 
@@ -614,7 +614,7 @@ int coda_open(struct inode *i, struct file *f)
        f->private_data = cred;
 
        if ( i->i_mapping != &i->i_data ) {
-               old_container = (struct inode *)i->i_mapping->host;
+               old_container = i->i_mapping->host;
                i->i_mapping = &i->i_data;
                iput(old_container);
        }
@@ -649,7 +649,7 @@ int coda_release(struct inode *i, struct file *f)
        cred = (struct coda_cred *)f->private_data;
 
        if (i->i_mapping != &i->i_data)
-               container = (struct inode *)i->i_mapping->host;
+               container = i->i_mapping->host;
 
         cii = ITOC(i);
         CDEBUG(D_FILE, "RELEASE coda (ino %ld, ct %d, cc %d) cache (ino %ld, ct %d)\n",
@@ -922,7 +922,7 @@ ok:
 
 return_bad_inode:
        if ( inode->i_mapping != &inode->i_data ) {
-               container = (struct inode *)inode->i_mapping->host;
+               container = inode->i_mapping->host;
                inode->i_mapping = &inode->i_data;
                iput(container);
        }
index 0344c20728aa5a93f89dc89134feff38a76c9037..94c54ecd98ea89543df8566e580d84d5a49f97e9 100644 (file)
@@ -29,7 +29,7 @@ static ssize_t
 coda_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct inode *container = (struct inode*)inode->i_mapping->host;
+       struct inode *container = inode->i_mapping->host;
        ssize_t n;
 
         down(&container->i_sem);
@@ -60,7 +60,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
                 return -1; 
         }
 
-       cont_dentry.d_inode = (struct inode *)inode->i_mapping->host;
+       cont_dentry.d_inode = inode->i_mapping->host;
   
        down(&cont_dentry.d_inode->i_sem);
        result = file_fsync(NULL, &cont_dentry, datasync);
index 45acf28c6b62f8b9e8647358c8125058454e8d9c..3cf258a2359c948daf349f577be80682d53a56ed 100644 (file)
@@ -231,7 +231,7 @@ static void coda_clear_inode(struct inode *inode)
                goto out;
 
        if ( inode->i_mapping != &inode->i_data ) {
-               open_inode = (struct inode *)inode->i_mapping->host;
+               open_inode = inode->i_mapping->host;
                 CDEBUG(D_SUPER, "DELINO cached file: ino %ld count %d.\n",  
                        open_inode->i_ino,  atomic_read(&open_inode->i_count));
                inode->i_mapping = &inode->i_data;
index 2df6cf719f4b0bc69984de1217f988064bb394b0..018c4410b064e18ba1a89a537e2c2d7f07d3469f 100644 (file)
@@ -24,7 +24,7 @@
 
 static int coda_symlink_filler(struct file *file, struct page *page)
 {
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        int error;
        struct coda_inode_info *cnp;
        unsigned int len = PAGE_SIZE;
index 51eff1caae27a89536801e52c8145c36380f1ecc..3ce1b2e01453303c92f910db2245cb6b987ac7f4 100644 (file)
@@ -306,7 +306,7 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry)
 
 static int cramfs_readpage(struct file *file, struct page * page)
 {
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        u32 maxblock, bytes_filled;
 
        maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
index d1c788cc29a344367a21f499ad7329a2d9da3a9a..b5d17f3cc9544130f3f9f617a32871440747ecff 100644 (file)
@@ -15,7 +15,7 @@ static int efs_symlink_readpage(struct file *file, struct page *page)
 {
        char *link = kmap(page);
        struct buffer_head * bh;
-       struct inode * inode = (struct inode*)page->mapping->host;
+       struct inode * inode = page->mapping->host;
        efs_block_t size = inode->i_size;
        int err;
   
index 81448e71b798390ab057e2930f2bfeb99b327af9..e592850db53bc10119a610ae82624e3e33b4435f 100644 (file)
@@ -663,7 +663,7 @@ static inline int block_in_use (unsigned long block,
                         EXT2_BLOCKS_PER_GROUP(sb), map);
 }
 
-static int test_root(int a, int b)
+static inline int test_root(int a, int b)
 {
        if (a == 0)
                return 1;
@@ -682,24 +682,55 @@ int ext2_group_sparse(int group)
                test_root(group, 7));
 }
 
+/**
+ *     ext2_bg_has_super - number of blocks used by the superblock in group
+ *     @sb: superblock for filesystem
+ *     @group: group number to check
+ *
+ *     Return the number of blocks used by the superblock (primary or backup)
+ *     in this group.  Currently this will be only 0 or 1.
+ */
+int ext2_bg_has_super(struct super_block *sb, int group)
+{
+       if (EXT2_HAS_RO_COMPAT_FEATURE(sb,EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)&&
+           !ext2_group_sparse(group))
+               return 0;
+       return 1;
+}
+
+/**
+ *     ext2_bg_num_gdb - number of blocks used by the group table in group
+ *     @sb: superblock for filesystem
+ *     @group: group number to check
+ *
+ *     Return the number of blocks used by the group descriptor table
+ *     (primary or backup) in this group.  In the future there may be a
+ *     different number of descriptor blocks in each group.
+ */
+unsigned long ext2_bg_num_gdb(struct super_block *sb, int group)
+{
+       if (EXT2_HAS_RO_COMPAT_FEATURE(sb,EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)&&
+           !ext2_group_sparse(group))
+               return 0;
+       return EXT2_SB(sb)->s_gdb_count;
+}
+
 #ifdef CONFIG_EXT2_CHECK
 /* Called at mount-time, super-block is locked */
 void ext2_check_blocks_bitmap (struct super_block * sb)
 {
        struct buffer_head * bh;
        struct ext2_super_block * es;
-       unsigned long desc_count, bitmap_count, x;
+       unsigned long desc_count, bitmap_count, x, j;
        unsigned long desc_blocks;
        int bitmap_nr;
        struct ext2_group_desc * gdp;
-       int i, j;
+       int i;
 
        es = sb->u.ext2_sb.s_es;
        desc_count = 0;
        bitmap_count = 0;
        gdp = NULL;
-       desc_blocks = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
-                     EXT2_DESC_PER_BLOCK(sb);
        for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
                gdp = ext2_get_group_desc (sb, i, NULL);
                if (!gdp)
@@ -708,24 +739,19 @@ void ext2_check_blocks_bitmap (struct super_block * sb)
                bitmap_nr = load_block_bitmap (sb, i);
                if (bitmap_nr < 0)
                        continue;
-               
-               bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 
-               if (!(sb->u.ext2_sb.s_feature_ro_compat &
-                    EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
-                   ext2_group_sparse(i)) {
-                       if (!ext2_test_bit (0, bh->b_data))
-                               ext2_error (sb, "ext2_check_blocks_bitmap",
-                                           "Superblock in group %d "
-                                           "is marked free", i);
-
-                       for (j = 0; j < desc_blocks; j++)
-                               if (!ext2_test_bit (j + 1, bh->b_data))
-                                       ext2_error (sb,
-                                           "ext2_check_blocks_bitmap",
-                                           "Descriptor block #%d in group "
-                                           "%d is marked free", j, i);
-               }
+               bh = EXT2_SB(sb)->s_block_bitmap[bitmap_nr];
+
+               if (ext2_bg_has_super(sb, i) && !ext2_test_bit(0, bh->b_data))
+                       ext2_error(sb, __FUNCTION__,
+                                  "Superblock in group %d is marked free", i);
+
+               desc_blocks = ext2_bg_num_gdb(sb, i);
+               for (j = 0; j < desc_blocks; j++)
+                       if (!ext2_test_bit(j + 1, bh->b_data))
+                               ext2_error(sb, __FUNCTION__,
+                                          "Descriptor block #%ld in group "
+                                          "%d is marked free", j, i);
 
                if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap), sb, bh->b_data))
                        ext2_error (sb, "ext2_check_blocks_bitmap",
index 658a0641605fd3c13a71aa267dd639a4300efb05..fd54c3040c975bb431072dba60b8e00a58ab30cf 100644 (file)
@@ -1190,13 +1190,17 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
                raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);
                if (raw_inode->i_size_high) {
                        struct super_block *sb = inode->i_sb;
-                       struct ext2_super_block *es = sb->u.ext2_sb.s_es;
-                       if (!(es->s_feature_ro_compat & cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) {
+                       if (!EXT2_HAS_RO_COMPAT_FEATURE(sb,
+                                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) ||
+                           EXT2_SB(sb)->s_es->s_rev_level ==
+                                       cpu_to_le32(EXT2_GOOD_OLD_REV)) {
                               /* If this is the first large file
                                * created, add a flag to the superblock.
                                */
                                lock_kernel();
-                               es->s_feature_ro_compat |= cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
+                               ext2_update_dynamic_rev(sb);
+                               EXT2_SET_RO_COMPAT_FEATURE(sb,
+                                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
                                unlock_kernel();
                                ext2_write_super(sb);
                        }
index 4d2dfedbff6667973ae6f6e6a36d56aa331b8e35..7b88355f884a9d3717864f95fde6e4206678357b 100644 (file)
@@ -95,6 +95,31 @@ void ext2_warning (struct super_block * sb, const char * function,
                bdevname(sb->s_dev), function, error_buf);
 }
 
+void ext2_update_dynamic_rev(struct super_block *sb)
+{
+       struct ext2_super_block *es = EXT2_SB(sb)->s_es;
+
+       if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV)
+               return;
+
+       ext2_warning(sb, __FUNCTION__,
+                    "updating to rev %d because of new feature flag, "
+                    "running e2fsck is recommended",
+                    EXT2_DYNAMIC_REV);
+
+       es->s_first_ino = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO);
+       es->s_inode_size = cpu_to_le16(EXT2_GOOD_OLD_INODE_SIZE);
+       es->s_rev_level = cpu_to_le32(EXT2_DYNAMIC_REV);
+       /* leave es->s_feature_*compat flags alone */
+       /* es->s_uuid will be set by e2fsck if empty */
+
+       /*
+        * The rest of the superblock fields should be zero, and if not it
+        * means they are likely already in use, so leave them alone.  We
+        * can leave it up to e2fsck to clean up any inconsistencies there.
+        */
+}
+
 void ext2_put_super (struct super_block * sb)
 {
        int db_count;
@@ -104,7 +129,7 @@ void ext2_put_super (struct super_block * sb)
                sb->u.ext2_sb.s_es->s_state = le16_to_cpu(sb->u.ext2_sb.s_mount_state);
                mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
        }
-       db_count = sb->u.ext2_sb.s_db_per_group;
+       db_count = EXT2_SB(sb)->s_gdb_count;
        for (i = 0; i < db_count; i++)
                if (sb->u.ext2_sb.s_group_desc[i])
                        brelse (sb->u.ext2_sb.s_group_desc[i]);
@@ -261,9 +286,9 @@ static int ext2_setup_super (struct super_block * sb,
 {
        int res = 0;
        if (le32_to_cpu(es->s_rev_level) > EXT2_MAX_SUPP_REV) {
-                       printk ("EXT2-fs warning: revision level too high, "
-                               "forcing read/only mode\n");
-                       res = MS_RDONLY;
+               printk ("EXT2-fs warning: revision level too high, "
+                       "forcing read-only mode\n");
+               res = MS_RDONLY;
        }
        if (read_only)
                return res;
@@ -423,22 +448,32 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
                        brelse(bh);
                return NULL;
        }
-       if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) {
-               if (le32_to_cpu(es->s_feature_incompat) & ~EXT2_FEATURE_INCOMPAT_SUPP) {
-                       printk("EXT2-fs: %s: couldn't mount because of "
-                              "unsupported optional features.\n",
-                              bdevname(dev));
-                       goto failed_mount;
-               }
-               if (!(sb->s_flags & MS_RDONLY) &&
-                   (le32_to_cpu(es->s_feature_ro_compat) & ~EXT2_FEATURE_RO_COMPAT_SUPP)) {
-                       printk("EXT2-fs: %s: couldn't mount RDWR because of "
-                              "unsupported optional features.\n",
-                              bdevname(dev));
-                       goto failed_mount;
-               }
+       if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV &&
+           (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
+            EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
+            EXT2_HAS_INCOMPAT_FEATURE(sb, ~0U)))
+               printk("EXT2-fs warning: feature flags set on rev 0 fs, "
+                      "running e2fsck is recommended\n");
+       /*
+        * Check feature flags regardless of the revision level, since we
+        * previously didn't change the revision level when setting the flags,
+        * so there is a chance incompat flags are set on a rev 0 filesystem.
+        */
+       if ((i = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP))) {
+               printk("EXT2-fs: %s: couldn't mount because of "
+                      "unsupported optional features (%x).\n",
+                      bdevname(dev), i);
+               goto failed_mount;
+       }
+       if (!(sb->s_flags & MS_RDONLY) &&
+           (i = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
+               printk("EXT2-fs: %s: couldn't mount RDWR because of "
+                      "unsupported optional features (%x).\n",
+                      bdevname(dev), i);
+               goto failed_mount;
        }
-       sb->s_blocksize_bits = le32_to_cpu(sb->u.ext2_sb.s_es->s_log_block_size) + 10;
+       sb->s_blocksize_bits =
+               le32_to_cpu(EXT2_SB(sb)->s_es->s_log_block_size) + 10;
        sb->s_blocksize = 1 << sb->s_blocksize_bits;
        if (sb->s_blocksize != BLOCK_SIZE &&
            (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||
@@ -484,9 +519,6 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
                        goto failed_mount;
                }
        }
-       sb->u.ext2_sb.s_feature_compat = le32_to_cpu(es->s_feature_compat);
-       sb->u.ext2_sb.s_feature_incompat = le32_to_cpu(es->s_feature_incompat);
-       sb->u.ext2_sb.s_feature_ro_compat = le32_to_cpu(es->s_feature_ro_compat);
        sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
                                   le32_to_cpu(es->s_log_frag_size);
        if (sb->u.ext2_sb.s_frag_size)
@@ -590,7 +622,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
        }
        sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
        sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
-       sb->u.ext2_sb.s_db_per_group = db_count;
+       sb->u.ext2_sb.s_gdb_count = db_count;
        /*
         * set up enough so that it can read an inode
         */
@@ -683,6 +715,14 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
                ext2_commit_super (sb, es);
        }
        else {
+               int ret;
+               if ((ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
+                                              ~EXT2_FEATURE_RO_COMPAT_SUPP))) {
+                       printk("EXT2-fs: %s: couldn't remount RDWR because of "
+                              "unsupported optional features (%x).\n",
+                              bdevname(sb->s_dev), ret);
+                       return -EROFS;
+               }
                /*
                 * Mounting a RDONLY partition read-write, so reread and
                 * store the current valid flag.  (It may have been changed
@@ -698,7 +738,7 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
 int ext2_statfs (struct super_block * sb, struct statfs * buf)
 {
        unsigned long overhead;
-       int     ngroups, i;
+       int i;
 
        if (test_opt (sb, MINIX_DF))
                overhead = 0;
@@ -715,19 +755,12 @@ int ext2_statfs (struct super_block * sb, struct statfs * buf)
 
                /*
                 * Add the overhead attributed to the superblock and
-                * block group descriptors.  If this is sparse
-                * superblocks is turned on, then not all groups have
-                * this.
+                * block group descriptors.  If the sparse superblocks
+                * feature is turned on, then not all groups have this.
                 */
-               if (sb->u.ext2_sb.s_feature_ro_compat &
-                   EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) {
-                       ngroups = 0;
-                       for (i=0 ; i < sb->u.ext2_sb.s_groups_count; i++)
-                               if (ext2_group_sparse(i))
-                                       ngroups++;
-               } else
-                       ngroups = sb->u.ext2_sb.s_groups_count;
-               overhead += ngroups * (1 + sb->u.ext2_sb.s_db_per_group);
+               for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++)
+                       overhead += ext2_bg_has_super(sb, i) +
+                               ext2_bg_num_gdb(sb, i);
 
                /*
                 * Every block group has an inode bitmap, a block
index 82f58826db5ed8ded21921cfe0bbec6cc8106adc..61ad8c2b2657e3c3abe7a317e463490c901f97b5 100644 (file)
@@ -746,7 +746,7 @@ static int fat_readpage(struct file *file, struct page *page)
 static int fat_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
 {
        return cont_prepare_write(page,from,to,fat_get_block,
-               &MSDOS_I((struct inode*)page->mapping->host)->mmu_private);
+               &MSDOS_I(page->mapping->host)->mmu_private);
 }
 static int _fat_bmap(struct address_space *mapping, long block)
 {
index 7414a4c297c9f1dd6a4f8b4965f4ca9ba8f3760a..32712550617fefad0c1dec299b6cf8491bbaa990 100644 (file)
@@ -231,7 +231,7 @@ static int hfs_readpage(struct file *file, struct page *page)
 static int hfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
 {
        return cont_prepare_write(page,from,to,hfs_get_block,
-               &((struct inode*)page->mapping->host)->u.hfs_i.mmu_private);
+               &page->mapping->host->u.hfs_i.mmu_private);
 }
 static int hfs_bmap(struct address_space *mapping, long block)
 {
index a9675ef546f75ddd313232386eb69b5c456226ec..4c03068158872493a03e3406475e4936720f64cb 100644 (file)
@@ -104,7 +104,7 @@ static int hpfs_readpage(struct file *file, struct page *page)
 static int hpfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
 {
        return cont_prepare_write(page,from,to,hpfs_get_block,
-               &((struct inode*)page->mapping->host)->u.hpfs_i.mmu_private);
+               &page->mapping->host->u.hpfs_i.mmu_private);
 }
 static int _hpfs_bmap(struct address_space *mapping, long block)
 {
index 0d38b408c9da03af8a59f46eb4c7b6f1cc2597c5..0947673627120d0aee41ca81fa3597cc81cadab7 100644 (file)
@@ -402,7 +402,7 @@ int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
 int hpfs_symlink_readpage(struct file *file, struct page *page)
 {
        char *link = kmap(page);
-       struct inode *i = (struct inode*)page->mapping->host;
+       struct inode *i = page->mapping->host;
        struct fnode *fnode;
        struct buffer_head *bh;
        int err;
index abbc04f1c58e05de1443fea97c98d7d8e5e7fa14..1d2b23b70dfef5f8f33a0a6de9caba001e9d9b1c 100644 (file)
@@ -100,7 +100,9 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
                memset(inode, 0, sizeof(*inode));
                init_waitqueue_head(&inode->i_wait);
                INIT_LIST_HEAD(&inode->i_hash);
-               INIT_LIST_HEAD(&inode->i_data.pages);
+               INIT_LIST_HEAD(&inode->i_data.clean_pages);
+               INIT_LIST_HEAD(&inode->i_data.dirty_pages);
+               INIT_LIST_HEAD(&inode->i_data.locked_pages);
                INIT_LIST_HEAD(&inode->i_dentry);
                INIT_LIST_HEAD(&inode->i_dirty_buffers);
                sema_init(&inode->i_sem, 1);
@@ -198,16 +200,25 @@ static inline void sync_one(struct inode *inode, int sync)
                iput(inode);
                spin_lock(&inode_lock);
        } else {
+               unsigned dirty;
+
                list_del(&inode->i_list);
                list_add(&inode->i_list, atomic_read(&inode->i_count)
                                                        ? &inode_in_use
                                                        : &inode_unused);
                /* Set I_LOCK, reset I_DIRTY */
+               dirty = inode->i_state & I_DIRTY;
                inode->i_state |= I_LOCK;
                inode->i_state &= ~I_DIRTY;
                spin_unlock(&inode_lock);
 
-               write_inode(inode, sync);
+               filemap_fdatasync(inode->i_mapping);
+
+               /* Don't write the inode if only I_DIRTY_PAGES was set */
+               if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC))
+                       write_inode(inode, sync);
+
+               filemap_fdatawait(inode->i_mapping);
 
                spin_lock(&inode_lock);
                inode->i_state &= ~I_LOCK;
@@ -595,7 +606,7 @@ static void clean_inode(struct inode *inode)
        inode->i_pipe = NULL;
        inode->i_bdev = NULL;
        inode->i_data.a_ops = &empty_aops;
-       inode->i_data.host = (void*)inode;
+       inode->i_data.host = inode;
        inode->i_mapping = &inode->i_data;
 }
 
index 4ac4bc0ced4363d44ca8c74518a29399a25555ba..e20f3ad61c75ca39e58759b2977d884454dc620e 100644 (file)
@@ -437,7 +437,7 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr)
 
 static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
 {
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        char *link = kmap(page);
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
        unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
index f61005aaca616b0cd3f65d90de58c85541afe1de..94fd0797d14866cf68c57187ef10a5dcf1d0c938 100644 (file)
@@ -697,7 +697,7 @@ jffs_readpage(struct file *file, struct page *page)
        void *buf;
        unsigned long read_len;
        int result = -EIO;
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        struct jffs_file *f = (struct jffs_file *)inode->u.generic_ip;
        struct jffs_control *c = (struct jffs_control *)inode->i_sb->u.generic_sbp;
        int r;
index 739387ab954504f2061233cb0def844c3b1128b6..78e7839740092d2ccd41a6d9bb61f401a465da0b 100644 (file)
@@ -167,13 +167,14 @@ nlm4_encode_lock(u32 *p, struct nlm_lock *lock)
         || (fl->fl_end > NLM4_OFFSET_MAX && fl->fl_end != OFFSET_MAX))
                return NULL;
 
+       *p++ = htonl(fl->fl_pid);
+
        start = loff_t_to_s64(fl->fl_start);
        if (fl->fl_end == OFFSET_MAX)
                len = 0;
        else
                len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
 
-       *p++ = htonl(fl->fl_pid);
        p = xdr_encode_hyper(p, start);
        p = xdr_encode_hyper(p, len);
 
index 022cbce783fb4ab2d26e8a9261694238fc4ae2ff..52f095848c3c87d072217949a19a6a15cccf5ee1 100644 (file)
@@ -45,7 +45,7 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry,
 
 static int ncp_symlink_readpage(struct file *file, struct page *page)
 {
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        int error, length, len, cnt;
        char *link;
        char *buf = kmap(page);
index d5c92ba3be8542bf9d9da21863aadd7c190538ae..2b3f22777b0fe0c7ffb9bc633a3a7b787f744ec9 100644 (file)
@@ -161,7 +161,7 @@ static int nfs_commit_write(struct file *file, struct page *page, unsigned offse
 {
        long status;
        loff_t pos = ((loff_t)page->index<<PAGE_CACHE_SHIFT) + to;
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
 
        kunmap(page);
        lock_kernel();
@@ -188,7 +188,7 @@ static int nfs_sync_page(struct page *page)
        mapping = page->mapping;
        if (!mapping)
                return 0;
-       inode = (struct inode *)mapping->host;
+       inode = mapping->host;
        if (!inode)
                return 0;
 
index e0f7313be780aa068da45a903555e0bbd6d22657..211d3a3db0a377f28dab166f781ea876cb6152f7 100644 (file)
@@ -479,7 +479,7 @@ nfs_readpage(struct file *file, struct page *page)
                struct address_space *mapping = page->mapping;
                if (!mapping)
                        BUG();
-               inode = (struct inode *)mapping->host;
+               inode = mapping->host;
        } else
                inode = file->f_dentry->d_inode;
        if (!inode)
index f75190be5d5e47992bf6a610d6328eff93c89583..8b9a28556905e0a3fbecd029ddfe45e077ca1d8a 100644 (file)
@@ -263,7 +263,7 @@ nfs_writepage(struct page *page)
 
        if (!mapping)
                BUG();
-       inode = (struct inode *)mapping->host;
+       inode = mapping->host;
        if (!inode)
                BUG();
        end_index = inode->i_size >> PAGE_CACHE_SHIFT;
index 5c9754acac5252167e907411c63d8c6fe5ae85bd..8baecf971f0205cee25660c208e4ed3d1deb160b 100644 (file)
@@ -2,10 +2,17 @@
 # Native language support configuration
 #
 
+# smb wants NLS
+if [ "$CONFIG_SMB_FS" = "m" -o "$CONFIG_SMB_FS" = "y" ]; then
+  define_bool CONFIG_SMB_NLS y
+else
+  define_bool CONFIG_SMB_NLS n
+fi
+
 # msdos and Joliet want NLS
 if [ "$CONFIG_JOLIET" = "y" -o "$CONFIG_FAT_FS" != "n" \
        -o "$CONFIG_NTFS_FS" != "n" -o "$CONFIG_NCPFS_NLS" = "y" \
-       -o "$CONFIG_SMB_FS" != "n" ]; then
+       -o "$CONFIG_SMB_NLS" = "y" ]; then
   define_bool CONFIG_NLS y
 else
   define_bool CONFIG_NLS n
index cbcd5201650cccc3572d97dce371977590a92a48..f54a7eb57a43d730898a7ed38ca9a22931086c43 100644 (file)
@@ -601,7 +601,7 @@ static int ntfs_readpage(struct file *file, struct page *page)
 static int ntfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
 {
        return cont_prepare_write(page,from,to,ntfs_get_block,
-               &((struct inode*)page->mapping->host)->u.ntfs_i.mmu_private);
+               &page->mapping->host->u.ntfs_i.mmu_private);
 }
 static int _ntfs_bmap(struct address_space *mapping, long block)
 {
index 45a94520978d2f781864c2d24fd1edbf2300df3f..c40f488e5704aec95b520cc9c0c8e0161acf033c 100644 (file)
@@ -426,7 +426,7 @@ static int qnx4_readpage(struct file *file, struct page *page)
 static int qnx4_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
 {
        return cont_prepare_write(page,from,to,qnx4_get_block,
-               &((struct inode*)page->mapping->host)->u.qnx4_i.mmu_private);
+               &page->mapping->host->u.qnx4_i.mmu_private);
 }
 static int qnx4_bmap(struct address_space *mapping, long block)
 {
index 36fa933a499bf2aae534dc2158bea848a74bb4ac..6a096c0ff49e2bb0e25a9d61535063363fb40b21 100644 (file)
@@ -98,7 +98,7 @@ static int ramfs_prepare_write(struct file *file, struct page *page, unsigned of
 
 static int ramfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 
        kunmap(page);
index 081209a487c2ea584090e3e60c0c181edadb124d..76c811852d98f7a617db8dc9f2febc929a532793 100644 (file)
@@ -395,7 +395,7 @@ out:        return ERR_PTR(res);
 static int
 romfs_readpage(struct file *file, struct page * page)
 {
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        unsigned long offset, avail, readlen;
        void *buf;
        int result = -EIO;
index 79627f8804709bbcc6cf69db44007460c35a5221..0a95735fddc32a73d1bc943ccc617afbe8edb84b 100644 (file)
@@ -161,7 +161,7 @@ smb_writepage(struct page *page)
 
        if (!mapping)
                BUG();
-       inode = (struct inode *)mapping->host;
+       inode = mapping->host;
        if (!inode)
                BUG();
 
index 3895d769bf0dee7493667ccf53fe5a592f8c42f8..9ab57d370ec8a1cf3daa238b10d3abb1629e6afb 100644 (file)
@@ -45,7 +45,7 @@
 
 static int udf_adinicb_readpage(struct file *file, struct page * page)
 {
-       struct inode *inode = (struct inode *)page->mapping->host;
+       struct inode *inode = page->mapping->host;
 
        struct buffer_head *bh;
        int block;
@@ -69,7 +69,7 @@ static int udf_adinicb_readpage(struct file *file, struct page * page)
 
 static int udf_adinicb_writepage(struct page *page)
 {
-       struct inode *inode = (struct inode *)page->mapping->host;
+       struct inode *inode = page->mapping->host;
 
        struct buffer_head *bh;
        int block;
@@ -97,7 +97,7 @@ static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsig
 
 static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
-       struct inode *inode = (struct inode *)page->mapping->host;
+       struct inode *inode = page->mapping->host;
 
        struct buffer_head *bh;
        int block;
index 547fc784b8514ae1db67673e2d41a8fd2c889801..be4e80165eb00035875b7a6e1281266fba33e752 100644 (file)
@@ -79,7 +79,7 @@ static void udf_pc_to_char(char *from, int fromlen, char *to)
 
 static int udf_symlink_filler(struct file *file, struct page *page)
 {
-       struct inode *inode = (struct inode*)page->mapping->host;
+       struct inode *inode = page->mapping->host;
        struct buffer_head *bh = NULL;
        char *symlink;
        int err = -EIO;
index a79f45bc315cad937d8dd7fa0a795a6d14e5e851..18787f9b2f194ac686bcef4dd17eb959693c46e9 100644 (file)
@@ -65,6 +65,7 @@ struct atm_tcp_ops {
        int (*attach)(struct atm_vcc *vcc,int itf);
        int (*create_persistent)(int itf);
        int (*remove_persistent)(int itf);
+       struct module *owner;
 };
 
 extern struct atm_tcp_ops atm_tcp_ops;
index d169bf7f22c902f90641aade9c59bdd60d99bdd6..ef8931cd7b5fe086733a01c5afde56a60211947d 100644 (file)
@@ -375,6 +375,7 @@ struct atmdev_ops { /* only send is required */
        void (*free_rx_skb)(struct atm_vcc *vcc, struct sk_buff *skb);
                /* @@@ temporary hack */
        int (*proc_read)(struct atm_dev *dev,loff_t *pos,char *page);
+       struct module *owner;
 };
 
 
index dd9fdcfaf910bfb02fd3e5a9094529eac82b7dfc..63922d2c0d328f956993e7ef1638bec39d5ea64a 100644 (file)
@@ -429,11 +429,23 @@ struct ext2_super_block {
  */
 
 #define EXT2_HAS_COMPAT_FEATURE(sb,mask)                       \
-       ( EXT2_SB(sb)->s_feature_compat & (mask) )
+       ( EXT2_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
 #define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask)                    \
-       ( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
+       ( EXT2_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) )
 #define EXT2_HAS_INCOMPAT_FEATURE(sb,mask)                     \
-       ( EXT2_SB(sb)->s_feature_incompat & (mask) )
+       ( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
+#define EXT2_SET_COMPAT_FEATURE(sb,mask)                       \
+       EXT2_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
+#define EXT2_SET_RO_COMPAT_FEATURE(sb,mask)                    \
+       EXT2_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask)
+#define EXT2_SET_INCOMPAT_FEATURE(sb,mask)                     \
+       EXT2_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask)
+#define EXT2_CLEAR_COMPAT_FEATURE(sb,mask)                     \
+       EXT2_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask)
+#define EXT2_CLEAR_RO_COMPAT_FEATURE(sb,mask)                  \
+       EXT2_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask)
+#define EXT2_CLEAR_INCOMPAT_FEATURE(sb,mask)                   \
+       EXT2_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask)
 
 #define EXT2_FEATURE_COMPAT_DIR_PREALLOC       0x0001
 
@@ -524,7 +536,8 @@ struct ext2_dir_entry_2 {
 extern int ext2_permission (struct inode *, int);
 
 /* balloc.c */
-extern int ext2_group_sparse(int group);
+extern int ext2_bg_has_super(struct super_block *sb, int group);
+extern unsigned long ext2_bg_num_gdb(struct super_block *sb, int group);
 extern int ext2_new_block (const struct inode *, unsigned long,
                           __u32 *, __u32 *, int *);
 extern void ext2_free_blocks (const struct inode *, unsigned long,
@@ -584,6 +597,7 @@ extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
        __attribute__ ((NORET_AND format (printf, 3, 4)));
 extern void ext2_warning (struct super_block *, const char *, const char *, ...)
        __attribute__ ((format (printf, 3, 4)));
+extern void ext2_update_dynamic_rev (struct super_block *sb);
 extern void ext2_put_super (struct super_block *);
 extern void ext2_write_super (struct super_block *);
 extern int ext2_remount (struct super_block *, int *, char *);
index 69b35b7f74e8ec65116a6365d13307e057ea83e3..2e72dfbefd0063112f91a83bed2470bd4741ef2a 100644 (file)
@@ -35,7 +35,7 @@ struct ext2_sb_info {
        unsigned long s_blocks_per_group;/* Number of blocks in a group */
        unsigned long s_inodes_per_group;/* Number of inodes in a group */
        unsigned long s_itb_per_group;  /* Number of inode table blocks per group */
-       unsigned long s_db_per_group;   /* Number of descriptor blocks per group */
+       unsigned long s_gdb_count;      /* Number of group descriptor blocks */
        unsigned long s_desc_per_block; /* Number of group descriptors per block */
        unsigned long s_groups_count;   /* Number of groups in the fs */
        struct buffer_head * s_sbh;     /* Buffer containing the super block */
@@ -56,9 +56,6 @@ struct ext2_sb_info {
        int s_desc_per_block_bits;
        int s_inode_size;
        int s_first_ino;
-       int s_feature_compat;
-       int s_feature_incompat;
-       int s_feature_ro_compat;
 };
 
 #endif /* _LINUX_EXT2_FS_SB */
index 8c72860bbd3025cd460859b1217042b67c73759e..8032db9921264da6d19898ce189ce6f47c18efcd 100644 (file)
@@ -363,10 +363,12 @@ struct address_space_operations {
 };
 
 struct address_space {
-       struct list_head        pages;          /* list of pages */
-       unsigned long           nrpages;        /* number of pages */
+       struct list_head        clean_pages;    /* list of clean pages */
+       struct list_head        dirty_pages;    /* list of dirty pages */
+       struct list_head        locked_pages;   /* list of locked pages */
+       unsigned long           nrpages;        /* number of total pages */
        struct address_space_operations *a_ops; /* methods */
-       void                    *host;          /* owner: inode, block_device */
+       struct inode            *host;          /* owner: inode, block_device */
        struct vm_area_struct   *i_mmap;        /* list of private mappings */
        struct vm_area_struct   *i_mmap_shared; /* list of shared mappings */
        spinlock_t              i_shared_lock;  /* and spinlock protecting it */
@@ -461,11 +463,12 @@ struct inode {
 /* Inode state bits.. */
 #define I_DIRTY_SYNC           1 /* Not dirty enough for O_DATASYNC */
 #define I_DIRTY_DATASYNC       2 /* Data-related inode changes pending */
-#define I_LOCK                 4
-#define I_FREEING              8
-#define I_CLEAR                        16
+#define I_DIRTY_PAGES          4 /* Data-related inode changes pending */
+#define I_LOCK                 8
+#define I_FREEING              16
+#define I_CLEAR                        32
 
-#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
+#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
 
 extern void __mark_inode_dirty(struct inode *, int);
 static inline void mark_inode_dirty(struct inode *inode)
@@ -480,6 +483,12 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
                __mark_inode_dirty(inode, I_DIRTY_SYNC);
 }
 
+static inline void mark_inode_dirty_pages(struct inode *inode)
+{
+       if (inode && !(inode->i_state & I_DIRTY_PAGES))
+               __mark_inode_dirty(inode, I_DIRTY_PAGES);
+}
+
 struct fown_struct {
        int pid;                /* pid or -pgrp where SIGIO should be sent */
        uid_t uid, euid;        /* uid/euid of process setting the owner */
@@ -1064,6 +1073,8 @@ extern int fsync_dev(kdev_t);
 extern int fsync_inode_buffers(struct inode *);
 extern int osync_inode_buffers(struct inode *);
 extern int inode_has_buffers(struct inode *);
+extern void filemap_fdatasync(struct address_space *);
+extern void filemap_fdatawait(struct address_space *);
 extern void sync_supers(kdev_t);
 extern int bmap(struct inode *, int);
 extern int notify_change(struct dentry *, struct iattr *);
index c90f838a4d14ac9525369ff2467ec1c26e1058c1..cc89518003c53f2d48d83465a52c38515b6d5b85 100644 (file)
@@ -92,7 +92,7 @@ void gs_stop(struct tty_struct *tty);
 void gs_start(struct tty_struct *tty);
 void gs_hangup(struct tty_struct *tty);
 void gs_do_softint(void *private_);
-int  block_til_ready(void *port, struct file *filp);
+int  gs_block_til_ready(void *port, struct file *filp);
 void gs_close(struct tty_struct *tty, struct file *filp);
 void gs_set_termios (struct tty_struct * tty, 
                      struct termios * old_termios);
index 39ed2adfa56e30f08ac8ac6727c72094525eaaff..4d9ef78e06e4289dfc2704f3507c0ddc6f1e5e1d 100644 (file)
@@ -19,7 +19,7 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* $Id: i2c-dev.h,v 1.7 2000/02/15 17:57:27 frodo Exp $ */
+/* $Id: i2c-dev.h,v 1.8 2000/08/12 16:37:15 mds Exp $ */
 
 #ifndef I2C_DEV_H
 #define I2C_DEV_H
@@ -162,6 +162,20 @@ extern inline __s32 i2c_smbus_write_block_data(int file, __u8 command,
                                I2C_SMBUS_BLOCK_DATA, &data);
 }
 
+extern inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command,
+                                               __u8 length, __u8 *values)
+{
+       union i2c_smbus_data data;
+       int i;
+       if (length > 32)
+               length = 32;
+       for (i = 1; i <= length; i++)
+               data.block[i] = values[i-1];
+       data.block[0] = length;
+       return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+                               I2C_SMBUS_I2C_BLOCK_DATA, &data);
+}
+
 #endif /* ndef __KERNEL__ */
 
 #endif
index 9c123fa48a023e7bda08ba435f1a532ebc876c72..b5793e81810542b5bfeb3646d7b6386f9e12914d 100644 (file)
@@ -20,7 +20,7 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
 /* ------------------------------------------------------------------------- */
 
-/* $Id: i2c-id.h,v 1.16 2000/04/03 18:57:42 frodo Exp $ */
+/* $Id: i2c-id.h,v 1.25 2000/10/12 07:27:29 simon Exp $ */
 
 #ifndef I2C_ID_H
 #define I2C_ID_H
 #define I2C_DRIVERID_PCF8583   25      /* real time clock              */
 #define I2C_DRIVERID_SAB3036   26      /* SAB3036 tuner                */
 #define I2C_DRIVERID_TDA7432   27      /* Stereo sound processor       */
+#define I2C_DRIVERID_TVMIXER    28      /* Mixer driver for tv cards    */
+#define I2C_DRIVERID_TVAUDIO    29      /* Generic TV sound driver      */
+#define I2C_DRIVERID_DPL3518    30      /* Dolby decoder chip           */
+#define I2C_DRIVERID_TDA9873    31      /* TV sound decoder chip        */
+#define I2C_DRIVERID_TDA9875    32      /* TV sound decoder chip        */
+#define I2C_DRIVERID_PIC16C54_PV9 33    /* Audio mux/ir receiver        */
+
+#define I2C_DRIVERID_SBATT      34     /* Smart Battery Device         */
+#define I2C_DRIVERID_SBS        35     /* SB System Manager            */
+#define I2C_DRIVERID_VES1893   36     /* VLSI DVB-S decoder            */
+#define I2C_DRIVERID_VES1820   37     /* VLSI DVB-C decoder            */
+#define I2C_DRIVERID_SAA7113   38     /* video decoder                 */
+#define I2C_DRIVERID_TDA8444   39     /* octuple 6-bit DAC             */
+
 
 #define I2C_DRIVERID_EXP0      0xF0    /* experimental use id's        */
 #define I2C_DRIVERID_EXP1      0xF1
 #define I2C_ALGO_SMBUS 0x040000
 #define I2C_ALGO_ISA   0x050000        /* lm_sensors ISA pseudo-adapter */
 #define I2C_ALGO_SAA7146 0x060000      /* SAA 7146 video decoder bus   */
+#define I2C_ALGO_ACB   0x070000        /* ACCESS.bus algorithm         */
+
+#define I2C_ALGO_EC     0x100000        /* ACPI embedded controller     */
+
+#define I2C_ALGO_MPC8XX 0x110000       /* MPC8xx PowerPC I2C algorithm */
 
 #define I2C_ALGO_EXP   0x800000        /* experimental                 */
 
 #define I2C_HW_P_ISA   0x01    /* generic ISA Bus inteface card        */
 #define I2C_HW_P_ELEK  0x02    /* Elektor ISA Bus inteface card        */
 
+/* --- ACPI Embedded controller algorithms                              */
+#define I2C_HW_ACPI_EC          0x00
+
+/* --- MPC8xx PowerPC adapters                                         */
+#define I2C_HW_MPC8XX_EPON 0x00        /* Eponymous MPC8xx I2C adapter         */
+
 /* --- SMBus only adapters                                             */
 #define I2C_HW_SMBUS_PIIX4     0x00
 #define I2C_HW_SMBUS_ALI15X3   0x01
 #define I2C_HW_SMBUS_I801      0x04
 #define I2C_HW_SMBUS_AMD756    0x05
 #define I2C_HW_SMBUS_SIS5595   0x06
+#define I2C_HW_SMBUS_ALI1535   0x07
 
 /* --- ISA pseudo-adapter                                              */
 #define I2C_HW_ISA 0x00
index 4043c0353a178b0b772fd3ef399773009e691601..4a9eb86c883ba928a728485738d1e880e01ee0fa 100644 (file)
@@ -23,7 +23,7 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
    Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c.h,v 1.40 2000/07/19 19:55:45 frodo Exp $ */
+/* $Id: i2c.h,v 1.42 2000/09/06 20:14:06 frodo Exp $ */
 
 #ifndef I2C_H
 #define I2C_H
@@ -120,6 +120,9 @@ extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
 extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
                                       u8 command, u8 length,
                                       u8 *values);
+extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
+                                          u8 command, u8 length,
+                                          u8 *values);
 
 
 /*
@@ -436,12 +439,13 @@ union i2c_smbus_data {
 
 /* SMBus transaction types (size parameter in the above functions) 
    Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
-#define I2C_SMBUS_QUICK                0
-#define I2C_SMBUS_BYTE         1
-#define I2C_SMBUS_BYTE_DATA    2 
-#define I2C_SMBUS_WORD_DATA    3
-#define I2C_SMBUS_PROC_CALL    4
-#define I2C_SMBUS_BLOCK_DATA   5
+#define I2C_SMBUS_QUICK                    0
+#define I2C_SMBUS_BYTE             1
+#define I2C_SMBUS_BYTE_DATA        2 
+#define I2C_SMBUS_WORD_DATA        3
+#define I2C_SMBUS_PROC_CALL        4
+#define I2C_SMBUS_BLOCK_DATA       5
+#define I2C_SMBUS_I2C_BLOCK_DATA    6
 
 
 /* ----- commands for the ioctl like i2c_command call:
index 2fe9bcdfcb3f68eb440312e917cbe4491552fcd0..7b4ff94f9e5328091d3fdc873e201300c6af234c 100644 (file)
@@ -66,6 +66,7 @@
 
 #define        _LVM_KERNEL_H_VERSION   "LVM 0.9 (13/11/2000)"
 
+#include <linux/config.h>
 #include <linux/version.h>
 #include <endian.h>
 
index 017755ad87494273ee264495f61a002d712a378a..5b67b326d67b24a1aba2f966cfe48b2643c85e23 100644 (file)
@@ -175,7 +175,6 @@ typedef struct page {
 #define PG_arch_1              30
 #define PG_reserved            31
 
-
 /* Make it prettier to test the above... */
 #define Page_Uptodate(page)    test_bit(PG_uptodate, &(page)->flags)
 #define SetPageUptodate(page)  set_bit(PG_uptodate, &(page)->flags)
@@ -186,6 +185,15 @@ typedef struct page {
 #define PageLocked(page)       test_bit(PG_locked, &(page)->flags)
 #define LockPage(page)         set_bit(PG_locked, &(page)->flags)
 #define TryLockPage(page)      test_and_set_bit(PG_locked, &(page)->flags)
+
+extern void __set_page_dirty(struct page *);
+
+static inline void set_page_dirty(struct page * page)
+{
+       if (!test_and_set_bit(PG_dirty, &page->flags))
+               __set_page_dirty(page);
+}
+
 /*
  * The first mb is necessary to safely close the critical section opened by the
  * TryLockPage(), the second mb is necessary to enforce ordering between
index 525786901fb4471384dc9626f894543289c1e8a7..0957d1aae683f93aa002f6a44ce3dcd415f3b46d 100644 (file)
@@ -339,7 +339,12 @@ extern int  ax25_uid_get_info(char *, char **, off_t, int);
 extern void ax25_uid_free(void);
 
 /* sysctl_net_ax25.c */
+#ifdef CONFIG_SYSCTL
 extern void ax25_register_sysctl(void);
 extern void ax25_unregister_sysctl(void);
+#else
+extern inline void ax25_register_sysctl(void) {};
+extern inline void ax25_unregister_sysctl(void) {};
+#endif /* CONFIG_SYSCTL */
 
 #endif
index ca569f1d0b351c74ac8fb3c2900ad2e39068b343..b1c0b96c267bb0d5b3604d32969ba1e5d46fb92b 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -15,6 +15,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/malloc.h>
 #include <linux/shm.h>
 #include <linux/init.h>
index 172300f04888c4660eb812af88da95c56947c9cb..c9ab9a4e2fc5c0d9d6191893bd0ed5f3e1a389d1 100644 (file)
@@ -71,7 +71,7 @@ static void add_page_to_hash_queue(struct page * page, struct page **p)
 
 static inline void add_page_to_inode_queue(struct address_space *mapping, struct page * page)
 {
-       struct list_head *head = &mapping->pages;
+       struct list_head *head = &mapping->clean_pages;
 
        mapping->nrpages++;
        list_add(&page->list, head);
@@ -131,6 +131,21 @@ static inline int sync_page(struct page *page)
        return 0;
 }
 
+/*
+ * Add a page to the dirty page list.
+ */
+void __set_page_dirty(struct page *page)
+{
+       struct address_space *mapping = page->mapping;
+
+       spin_lock(&pagecache_lock);
+       list_del(&page->list);
+       list_add(&page->list, &mapping->dirty_pages);
+       spin_unlock(&pagecache_lock);
+
+       mark_inode_dirty_pages(mapping->host);
+}
+
 /**
  * invalidate_inode_pages - Invalidate all the unlocked pages of one inode
  * @inode: the inode which pages we want to invalidate
@@ -144,7 +159,7 @@ void invalidate_inode_pages(struct inode * inode)
        struct list_head *head, *curr;
        struct page * page;
 
-       head = &inode->i_mapping->pages;
+       head = &inode->i_mapping->clean_pages;
 
        spin_lock(&pagecache_lock);
        spin_lock(&pagemap_lru_lock);
@@ -204,26 +219,12 @@ static inline void truncate_complete_page(struct page *page)
        page_cache_release(page);
 }
 
-/**
- * truncate_inode_pages - truncate *all* the pages from an offset
- * @mapping: mapping to truncate
- * @lstart: offset from with to truncate
- *
- * Truncate the page cache at a set offset, removing the pages
- * that are beyond that offset (and zeroing out partial pages).
- * If any page is locked we wait for it to become unlocked.
- */
-void truncate_inode_pages(struct address_space * mapping, loff_t lstart)
+void truncate_list_pages(struct list_head *head, unsigned long start, unsigned partial)
 {
-       struct list_head *head, *curr;
+       struct list_head *curr;
        struct page * page;
-       unsigned partial = lstart & (PAGE_CACHE_SIZE - 1);
-       unsigned long start;
-
-       start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
 repeat:
-       head = &mapping->pages;
        spin_lock(&pagecache_lock);
        curr = head->next;
        while (curr != head) {
@@ -267,6 +268,26 @@ repeat:
        spin_unlock(&pagecache_lock);
 }
 
+
+/**
+ * truncate_inode_pages - truncate *all* the pages from an offset
+ * @mapping: mapping to truncate
+ * @lstart: offset from with to truncate
+ *
+ * Truncate the page cache at a set offset, removing the pages
+ * that are beyond that offset (and zeroing out partial pages).
+ * If any page is locked we wait for it to become unlocked.
+ */
+void truncate_inode_pages(struct address_space * mapping, loff_t lstart) 
+{
+       unsigned long start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       unsigned partial = lstart & (PAGE_CACHE_SIZE - 1);
+
+       truncate_list_pages(&mapping->clean_pages, start, partial);
+       truncate_list_pages(&mapping->dirty_pages, start, partial);
+       truncate_list_pages(&mapping->locked_pages, start, partial);
+}
+
 static inline struct page * __find_page_nolock(struct address_space *mapping, unsigned long offset, struct page *page)
 {
        goto inside;
@@ -328,14 +349,12 @@ static int waitfor_one_page(struct page *page)
        return error;
 }
 
-static int do_buffer_fdatasync(struct inode *inode, unsigned long start, unsigned long end, int (*fn)(struct page *))
+static int do_buffer_fdatasync(struct list_head *head, unsigned long start, unsigned long end, int (*fn)(struct page *))
 {
-       struct list_head *head, *curr;
+       struct list_head *curr;
        struct page *page;
        int retval = 0;
 
-       head = &inode->i_mapping->pages;
-
        spin_lock(&pagecache_lock);
        curr = head->next;
        while (curr != head) {
@@ -374,11 +393,89 @@ int generic_buffer_fdatasync(struct inode *inode, unsigned long start_idx, unsig
 {
        int retval;
 
-       retval = do_buffer_fdatasync(inode, start_idx, end_idx, writeout_one_page);
-       retval |= do_buffer_fdatasync(inode, start_idx, end_idx, waitfor_one_page);
+       /* writeout dirty buffers on pages from both clean and dirty lists */
+       retval = do_buffer_fdatasync(&inode->i_mapping->dirty_pages, start_idx, end_idx, writeout_one_page);
+       retval |= do_buffer_fdatasync(&inode->i_mapping->clean_pages, start_idx, end_idx, writeout_one_page);
+       retval |= do_buffer_fdatasync(&inode->i_mapping->locked_pages, start_idx, end_idx, writeout_one_page);
+
+       /* now wait for locked buffers on pages from both clean and dirty lists */
+       retval |= do_buffer_fdatasync(&inode->i_mapping->dirty_pages, start_idx, end_idx, writeout_one_page);
+       retval |= do_buffer_fdatasync(&inode->i_mapping->clean_pages, start_idx, end_idx, waitfor_one_page);
+       retval |= do_buffer_fdatasync(&inode->i_mapping->locked_pages, start_idx, end_idx, waitfor_one_page);
+
        return retval;
 }
 
+/**
+ *      filemap_fdatasync - walk the list of dirty pages of the given address space
+ *             and writepage() all of them.
+ * 
+ *      @mapping: address space structure to write
+ *
+ */
+void filemap_fdatasync(struct address_space * mapping)
+{
+       int (*writepage)(struct page *) = mapping->a_ops->writepage;
+
+       spin_lock(&pagecache_lock);
+
+        while (!list_empty(&mapping->dirty_pages)) {
+               struct page *page = list_entry(mapping->dirty_pages.next, struct page, list);
+
+               list_del(&page->list);
+               list_add(&page->list, &mapping->locked_pages);
+
+               if (!PageDirty(page))
+                       continue;
+
+               page_cache_get(page);
+               spin_unlock(&pagecache_lock);
+
+               lock_page(page);
+
+               if (PageDirty(page)) {
+                       ClearPageDirty(page);
+                       writepage(page);
+               } else
+                       UnlockPage(page);
+
+               page_cache_release(page);
+               spin_lock(&pagecache_lock);
+       }
+       spin_unlock(&pagecache_lock);
+}
+
+/**
+ *      filemap_fdatawait - walk the list of locked pages of the given address space
+ *             and wait for all of them.
+ * 
+ *      @mapping: address space structure to wait for
+ *
+ */
+void filemap_fdatawait(struct address_space * mapping)
+{
+       spin_lock(&pagecache_lock);
+
+        while (!list_empty(&mapping->locked_pages)) {
+               struct page *page = list_entry(mapping->locked_pages.next, struct page, list);
+
+               list_del(&page->list);
+               list_add(&page->list, &mapping->clean_pages);
+
+               if (!PageLocked(page))
+                       continue;
+
+               page_cache_get(page);
+               spin_unlock(&pagecache_lock);
+
+               ___wait_on_page(page);
+
+               page_cache_release(page);
+               spin_lock(&pagecache_lock);
+       }
+       spin_unlock(&pagecache_lock);
+}
+
 /*
  * Add a page to the inode page cache.
  *
@@ -1485,60 +1582,19 @@ page_not_uptodate:
        return NULL;
 }
 
-/*
- * If a task terminates while we're swapping the page, the vma and
- * and file could be released: try_to_swap_out has done a get_file.
- * vma/file is guaranteed to exist in the unmap/sync cases because
- * mmap_sem is held.
- *
- * The "mapping" test takes care of somebody having truncated the
- * page and thus made this write-page a no-op..
- */
-static int filemap_write_page(struct page * page, int wait)
-{
-       struct address_space * mapping = page->mapping;
-       int error = 0;
-
-       if (mapping && mapping->a_ops->writepage) {
-               ClearPageDirty(page);
-               error = mapping->a_ops->writepage(page);
-       }
-       return error;
-}
-
-
 /* Called with mm->page_table_lock held to protect against other
  * threads/the swapper from ripping pte's out from under us.
  */
 static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
        unsigned long address, unsigned int flags)
 {
-       pte_t pte;
-       struct page *page;
-       int error;
-
-       pte = *ptep;
+       pte_t pte = *ptep;
 
-       if (!pte_present(pte))
-               goto out;
-       if (!ptep_test_and_clear_dirty(ptep))
-               goto out;
-
-       flush_page_to_ram(pte_page(pte));
-       flush_cache_page(vma, address);
-       flush_tlb_page(vma, address);
-       page = pte_page(pte);
-       page_cache_get(page);
-       spin_unlock(&vma->vm_mm->page_table_lock);
-
-       lock_page(page);
-       error = filemap_write_page(page, 1);
-       page_cache_free(page);
-
-       spin_lock(&vma->vm_mm->page_table_lock);
-       return error;
-
-out:
+       if (pte_present(pte) && ptep_test_and_clear_dirty(ptep)) {
+               struct page *page = pte_page(pte);
+               flush_tlb_page(vma, address);
+               set_page_dirty(page);
+       }
        return 0;
 }
 
@@ -1685,9 +1741,12 @@ static int msync_interval(struct vm_area_struct * vma,
                if (!error && (flags & MS_SYNC)) {
                        struct file * file = vma->vm_file;
                        if (file && file->f_op && file->f_op->fsync) {
-                               down(&file->f_dentry->d_inode->i_sem);
+                               struct inode * inode = file->f_dentry->d_inode;
+                               down(&inode->i_sem);
+                               filemap_fdatasync(inode->i_mapping);
                                error = file->f_op->fsync(file, file->f_dentry, 1);
-                               up(&file->f_dentry->d_inode->i_sem);
+                               filemap_fdatawait(inode->i_mapping);
+                               up(&inode->i_sem);
                        }
                }
                return error;
index 13dad21a06caf129a1172280ccbcacba972a6ccf..f4bb0141f05050428d50c05c9c9eea6479d6a549 100644 (file)
@@ -259,22 +259,22 @@ nomem:
 /*
  * Return indicates whether a page was freed so caller can adjust rss
  */
-static inline int free_pte(pte_t page)
+static inline int free_pte(pte_t pte)
 {
-       if (pte_present(page)) {
-               struct page *ptpage = pte_page(page);
-               if ((!VALID_PAGE(ptpage)) || PageReserved(ptpage))
+       if (pte_present(pte)) {
+               struct page *page = pte_page(pte);
+               if ((!VALID_PAGE(page)) || PageReserved(page))
                        return 0;
                /* 
                 * free_page() used to be able to clear swap cache
                 * entries.  We may now have to do it manually.  
                 */
-               if (pte_dirty(page))
-                       SetPageDirty(ptpage);
-               free_page_and_swap_cache(ptpage);
+               if (pte_dirty(pte) && page->mapping)
+                       set_page_dirty(page);
+               free_page_and_swap_cache(page);
                return 1;
        }
-       swap_free(pte_to_swp_entry(page));
+       swap_free(pte_to_swp_entry(pte));
        return 0;
 }
 
index 1980f635efed9260999643477e93c9da2d196d74..a81a746593e83d7590ebc9b1298e81c8851795e3 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/file.h>
 #include <linux/swap.h>
 #include <linux/pagemap.h>
-#include <linux/init.h>
 #include <linux/string.h>
 #include <linux/locks.h>
 #include <asm/smplock.h>
@@ -201,7 +200,7 @@ static int shmem_writepage(struct page * page)
        struct shmem_inode_info *info;
        swp_entry_t *entry, swap;
 
-       info = &((struct inode *)page->mapping->host)->u.shmem_i;
+       info = &page->mapping->host->u.shmem_i;
        if (info->locked)
                return 1;
        swap = __get_swap_page(2);
@@ -227,7 +226,7 @@ static int shmem_writepage(struct page * page)
        /* Add it to the swap cache */
        add_to_swap_cache(page, swap);
        page_cache_release(page);
-       SetPageDirty(page);
+       set_page_dirty(page);
        info->swapped++;
 out:
        spin_unlock(&info->lock);
@@ -770,12 +769,12 @@ out:
        spin_unlock (&info->lock);
        return 0;
 found:
-       add_to_page_cache (page, inode->i_mapping, offset + idx);
-       SetPageDirty (page);
-       SetPageUptodate (page);
-       UnlockPage (page);
+       add_to_page_cache(page, inode->i_mapping, offset + idx);
+       set_page_dirty(page);
+       SetPageUptodate(page);
+       UnlockPage(page);
        info->swapped--;
-       spin_unlock (&info->lock);
+       spin_unlock(&info->lock);
        return 1;
 }
 
index cd7ab1623e67f2c6a8caa717d4e4f7e5f219cb4b..2a5a55b7bd7da2169dc6ed16dea89da96feb1607 100644 (file)
@@ -29,10 +29,9 @@ static struct address_space_operations swap_aops = {
 };
 
 struct address_space swapper_space = {
-       {                               /* pages        */
-               &swapper_space.pages,   /*        .next */
-               &swapper_space.pages    /*        .prev */
-       },
+       LIST_HEAD_INIT(swapper_space.clean_pages),
+       LIST_HEAD_INIT(swapper_space.dirty_pages),
+       LIST_HEAD_INIT(swapper_space.locked_pages),
        0,                              /* nrpages      */
        &swap_aops,
 };
index 9776b0b978a0907ec948914c07b8318eee88d2b2..d4a74f41f8a9913df078333d1d74becf408eac8f 100644 (file)
@@ -91,7 +91,7 @@ static int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* vma, un
        if (PageSwapCache(page)) {
                entry.val = page->index;
                if (pte_dirty(pte))
-                       SetPageDirty(page);
+                       set_page_dirty(page);
 set_swap_pte:
                swap_duplicate(entry);
                set_pte(page_table, swp_entry_to_pte(entry));
@@ -128,9 +128,8 @@ out_failed:
         * entry for it, or we should write it back
         * to its own backing store.
         */
-       flush_cache_page(vma, address);
        if (page->mapping) {
-               SetPageDirty(page);
+               set_page_dirty(page);
                goto drop_pte;
        }
 
@@ -146,7 +145,7 @@ out_failed:
 
        /* Add it to the swap cache and mark it dirty */
        add_to_swap_cache(page, entry);
-       SetPageDirty(page);
+       set_page_dirty(page);
        goto set_swap_pte;
 
 out_unlock_restore:
@@ -579,7 +578,7 @@ dirty_page_rescan:
                        if (result != 1)
                                continue;
                        /* writepage refused to do anything */
-                       SetPageDirty(page);
+                       set_page_dirty(page);
                        goto page_active;
                }
 
index 8bca9d1c32f6d3451515d404b958f4acdcc909bf..1814a8b212cf368d885accaad9d796b458dd0536 100644 (file)
@@ -42,7 +42,7 @@ static int identical(struct sockaddr_atmsvc *a,struct sockaddr_atmsvc *b)
  */
 
 static DECLARE_MUTEX(local_lock);
-
+extern  spinlock_t atm_dev_lock;
 
 static void notify_sigd(struct atm_dev *dev)
 {
@@ -58,12 +58,14 @@ void reset_addr(struct atm_dev *dev)
        struct atm_dev_addr *this;
 
        down(&local_lock);
+       spin_lock (&atm_dev_lock);              
        while (dev->local) {
                this = dev->local;
                dev->local = this->next;
                kfree(this);
        }
        up(&local_lock);
+       spin_unlock (&atm_dev_lock);
        notify_sigd(dev);
 }
 
index 16a6fb6b409c812d0373151ac0f58cf6ac5c60f9..ea0ad690a57a16b5657a265d1683b97647ebc81a 100644 (file)
@@ -72,6 +72,7 @@ EXPORT_SYMBOL(atm_tcp_ops);
 #define DPRINTK(format,args...)
 #endif
 
+spinlock_t atm_dev_lock = SPIN_LOCK_UNLOCKED;
 
 static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
 {
@@ -139,13 +140,19 @@ void atm_release_vcc_sk(struct sock *sk,int free_sk)
                                vcc->dev->ops->free_rx_skb(vcc,skb);
                        else kfree_skb(skb);
                }
+               spin_lock (&atm_dev_lock);      
+               fops_put (vcc->dev->ops);
                if (atomic_read(&vcc->rx_inuse))
                        printk(KERN_WARNING "atm_release_vcc: strange ... "
                            "rx_inuse == %d after closing\n",
                            atomic_read(&vcc->rx_inuse));
                bind_vcc(vcc,NULL);
-       }
+       } else
+               spin_lock (&atm_dev_lock);      
+
        if (free_sk) free_atm_vcc_sk(sk);
+
+       spin_unlock (&atm_dev_lock);
 }
 
 
@@ -238,9 +245,11 @@ static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi,
            vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu);
        DPRINTK("  RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class,
            vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu);
+       fops_get (dev->ops);
        if (dev->ops->open) {
                error = dev->ops->open(vcc,vpi,vci);
                if (error) {
+                       fops_put (dev->ops);
                        bind_vcc(vcc,NULL);
                        return error;
                }
@@ -252,10 +261,18 @@ static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi,
 static int atm_do_connect(struct atm_vcc *vcc,int itf,int vpi,int vci)
 {
        struct atm_dev *dev;
+       int return_val;
 
+       spin_lock (&atm_dev_lock);
        dev = atm_find_dev(itf);
-       if (!dev) return -ENODEV;
-       return atm_do_connect_dev(vcc,dev,vpi,vci);
+       if (!dev)
+               return_val =  -ENODEV;
+       else
+               return_val = atm_do_connect_dev(vcc,dev,vpi,vci);
+
+       spin_unlock (&atm_dev_lock);
+
+       return return_val;
 }
 
 
@@ -285,8 +302,10 @@ int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci)
        else {
                struct atm_dev *dev;
 
+               spin_lock (&atm_dev_lock);
                for (dev = atm_devs; dev; dev = dev->next)
                        if (!atm_do_connect_dev(vcc,dev,vpi,vci)) break;
+               spin_unlock (&atm_dev_lock);
                if (!dev) return -ENODEV;
        }
        if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
@@ -523,57 +542,86 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
        struct atm_vcc *vcc;
        int *tmp_buf;
        void *buf;
-       int error,len,size,number;
+       int error,len,size,number, ret_val;
 
+       ret_val = 0;
+       spin_lock (&atm_dev_lock);
        vcc = ATM_SD(sock);
        switch (cmd) {
                case SIOCOUTQ:
                        if (sock->state != SS_CONNECTED ||
-                           !test_bit(ATM_VF_READY,&vcc->flags))
-                               return -EINVAL;
-                       return put_user(vcc->sk->sndbuf-
+                           !test_bit(ATM_VF_READY,&vcc->flags)) {
+                               ret_val =  -EINVAL;
+                               goto done;
+                       }
+                       ret_val =  put_user(vcc->sk->sndbuf-
                            atomic_read(&vcc->tx_inuse)-ATM_PDU_OVHD,
                            (int *) arg) ? -EFAULT : 0;
+                       goto done;
                case SIOCINQ:
                        {
                                struct sk_buff *skb;
 
-                               if (sock->state != SS_CONNECTED)
-                                       return -EINVAL;
+                               if (sock->state != SS_CONNECTED) {
+                                       ret_val = -EINVAL;
+                                       goto done;
+                               }
                                skb = skb_peek(&vcc->recvq);
-                               return put_user(skb ? skb->len : 0,(int *) arg)
+                               ret_val = put_user(skb ? skb->len : 0,(int *) arg)
                                    ? -EFAULT : 0;
+                               goto done;
                        }
                case ATM_GETNAMES:
                        if (get_user(buf,
-                           &((struct atm_iobuf *) arg)->buffer))
-                               return -EFAULT;
+                                    &((struct atm_iobuf *) arg)->buffer)) {
+                               ret_val = -EFAULT;
+                               goto done;
+                       }
                        if (get_user(len,
-                           &((struct atm_iobuf *) arg)->length))
-                               return -EFAULT;
+                                    &((struct atm_iobuf *) arg)->length)) {
+                               ret_val = -EFAULT;
+                               goto done;
+                       }
                        size = 0;
                        for (dev = atm_devs; dev; dev = dev->next)
                                size += sizeof(int);
-                       if (size > len) return -E2BIG;
+                       if (size > len) {
+                               ret_val = -E2BIG;
+                               goto done;
+                       }
                        tmp_buf = kmalloc(size,GFP_KERNEL);
-                       if (!tmp_buf) return -ENOMEM;
+                       if (!tmp_buf) {
+                               ret_val = -ENOMEM;
+                               goto done;
+                       }
                        for (dev = atm_devs; dev; dev = dev->next)
                                *tmp_buf++ = dev->number;
-                       if (copy_to_user(buf,(char *) tmp_buf-size,size))
-                               return -EFAULT;
-                       return put_user(size,
+                       if (copy_to_user(buf,(char *) tmp_buf-size,size)) {
+                               ret_val = -EFAULT;
+                               goto done;
+                       }
+                       ret_val = put_user(size,
                            &((struct atm_iobuf *) arg)->length) ? -EFAULT : 0;
+                       goto done;
                case SIOCGSTAMP: /* borrowed from IP */
-                       if (!vcc->timestamp.tv_sec) return -ENOENT;
+                       if (!vcc->timestamp.tv_sec) {
+                               ret_val = -ENOENT;
+                               goto done;
+                       }
                        vcc->timestamp.tv_sec += vcc->timestamp.tv_usec/1000000;
                        vcc->timestamp.tv_usec %= 1000000;
-                       return copy_to_user((void *) arg,&vcc->timestamp,
+                       ret_val = copy_to_user((void *) arg,&vcc->timestamp,
                            sizeof(struct timeval)) ? -EFAULT : 0;
+                       goto done;
                case ATM_SETSC:
                        printk(KERN_WARNING "ATM_SETSC is obsolete\n");
-                       return 0;
+                       ret_val = 0;
+                       goto done;
                case ATMSIGD_CTRL:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
+                       if (!capable(CAP_NET_ADMIN)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
                        /*
                         * The user/kernel protocol for exchanging signalling
                         * info uses kernel pointers as opaque references,
@@ -581,175 +629,308 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
                         * on the kernel... so we should make sure that we
                         * have the same privledges that /proc/kcore needs
                         */
-                       if (!capable(CAP_SYS_RAWIO)) return -EPERM;
+                       if (!capable(CAP_SYS_RAWIO)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
                        error = sigd_attach(vcc);
                        if (!error) sock->state = SS_CONNECTED;
-                       return error;
+                       ret_val = error;
+                       goto done;
 #ifdef CONFIG_ATM_CLIP
                case SIOCMKCLIP:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                       return clip_create(arg);
+                       if (!capable(CAP_NET_ADMIN))
+                               ret_val = -EPERM;
+                       else 
+                               ret_val = clip_create(arg);
+                       goto done;
                case ATMARPD_CTRL:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
+                       if (!capable(CAP_NET_ADMIN)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
                        error = atm_init_atmarp(vcc);
                        if (!error) sock->state = SS_CONNECTED;
-                       return error;
+                       ret_val = error;
+                       goto done;
                case ATMARP_MKIP:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                       return clip_mkip(vcc,arg);
+                       if (!capable(CAP_NET_ADMIN)) 
+                               ret_val = -EPERM;
+                       else 
+                               ret_val = clip_mkip(vcc,arg);
+                       goto done;
                case ATMARP_SETENTRY:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                       return clip_setentry(vcc,arg);
+                       if (!capable(CAP_NET_ADMIN)) 
+                               ret_val = -EPERM;
+                       else
+                               ret_val = clip_setentry(vcc,arg);
+                       goto done;
                case ATMARP_ENCAP:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                       return clip_encap(vcc,arg);
+                       if (!capable(CAP_NET_ADMIN)) 
+                               ret_val = -EPERM;
+                       else
+                               ret_val = clip_encap(vcc,arg);
+                       goto done;
 #endif
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
                 case ATMLEC_CTRL:
-                        if (!capable(CAP_NET_ADMIN)) return -EPERM;
+                        if (!capable(CAP_NET_ADMIN)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
                         if (atm_lane_ops.lecd_attach == NULL)
                                 atm_lane_init();
-                        if (atm_lane_ops.lecd_attach == NULL) /* try again */
-                                return -ENOSYS;
-                        error = atm_lane_ops.lecd_attach(vcc, (int)arg);
-                        if (error >= 0) sock->state = SS_CONNECTED;
-                        return error;
+                        if (atm_lane_ops.lecd_attach == NULL) { /* try again */
+                               ret_val = -ENOSYS;
+                               goto done;
+                       }
+                       error = atm_lane_ops.lecd_attach(vcc, (int)arg);
+                       if (error >= 0) sock->state = SS_CONNECTED;
+                       ret_val =  error;
+                       goto done;
                 case ATMLEC_MCAST:
-                        if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                        return atm_lane_ops.mcast_attach(vcc, (int)arg);
+                       if (!capable(CAP_NET_ADMIN))
+                               ret_val = -EPERM;
+                       else
+                               ret_val = atm_lane_ops.mcast_attach(vcc, (int)arg);
+                       goto done;
                 case ATMLEC_DATA:
-                        if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                        return atm_lane_ops.vcc_attach(vcc, (void*)arg);
+                       if (!capable(CAP_NET_ADMIN))
+                               ret_val = -EPERM;
+                       else
+                               ret_val = atm_lane_ops.vcc_attach(vcc, (void*)arg);
+                       goto done;
 #endif
 #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
                case ATMMPC_CTRL:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                        if (atm_mpoa_ops.mpoad_attach == NULL)
+                       if (!capable(CAP_NET_ADMIN)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
+                       if (atm_mpoa_ops.mpoad_attach == NULL)
                                 atm_mpoa_init();
-                        if (atm_mpoa_ops.mpoad_attach == NULL) /* try again */
-                                return -ENOSYS;
-                        error = atm_mpoa_ops.mpoad_attach(vcc, (int)arg);
-                        if (error >= 0) sock->state = SS_CONNECTED;
-                        return error;
+                       if (atm_mpoa_ops.mpoad_attach == NULL) { /* try again */
+                               ret_val = -ENOSYS;
+                               goto done;
+                       }
+                       error = atm_mpoa_ops.mpoad_attach(vcc, (int)arg);
+                       if (error >= 0) sock->state = SS_CONNECTED;
+                       ret_val = error;
+                       goto done;
                case ATMMPC_DATA:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                       return atm_mpoa_ops.vcc_attach(vcc, arg);
+                       if (!capable(CAP_NET_ADMIN)) 
+                               ret_val = -EPERM;
+                       else
+                               ret_val = atm_mpoa_ops.vcc_attach(vcc, arg);
+                       goto done;
 #endif
 #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
                case SIOCSIFATMTCP:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                       if (!atm_tcp_ops.attach) return -ENOPKG;
+                       if (!capable(CAP_NET_ADMIN)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
+                       if (!atm_tcp_ops.attach) {
+                               ret_val = -ENOPKG;
+                               goto done;
+                       }
+                       fops_get (&atm_tcp_ops);
                        error = atm_tcp_ops.attach(vcc,(int) arg);
                        if (error >= 0) sock->state = SS_CONNECTED;
-                       return error;
+                       else            fops_put (&atm_tcp_ops);
+                       ret_val = error;
+                       goto done;
                case ATMTCP_CREATE:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                       if (!atm_tcp_ops.create_persistent) return -ENOPKG;
-                       return atm_tcp_ops.create_persistent((int) arg);
+                       if (!capable(CAP_NET_ADMIN)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
+                       if (!atm_tcp_ops.create_persistent) {
+                               ret_val = -ENOPKG;
+                               goto done;
+                       }
+                       error = atm_tcp_ops.create_persistent((int) arg);
+                       if (error < 0) fops_put (&atm_tcp_ops);
+                       ret_val = error;
+                       goto done;
                case ATMTCP_REMOVE:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                       if (!atm_tcp_ops.remove_persistent) return -ENOPKG;
-                       return atm_tcp_ops.remove_persistent((int) arg);
+                       if (!capable(CAP_NET_ADMIN)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
+                       if (!atm_tcp_ops.remove_persistent) {
+                               ret_val = -ENOPKG;
+                               goto done;
+                       }
+                       error = atm_tcp_ops.remove_persistent((int) arg);
+                       fops_put (&atm_tcp_ops);
+                       ret_val = error;
+                       goto done;
 #endif
                default:
                        break;
        }
-       if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) return -EFAULT;
-       if (get_user(len,&((struct atmif_sioc *) arg)->length)) return -EFAULT;
-       if (get_user(number,&((struct atmif_sioc *) arg)->number))
-               return -EFAULT;
-       if (!(dev = atm_find_dev(number))) return -ENODEV;
+       if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) {
+               ret_val = -EFAULT;
+               goto done;
+       }
+       if (get_user(len,&((struct atmif_sioc *) arg)->length)) {
+               ret_val = -EFAULT;
+               goto done;
+       }
+       if (get_user(number,&((struct atmif_sioc *) arg)->number)) {
+               ret_val = -EFAULT;
+               goto done;
+       }
+       if (!(dev = atm_find_dev(number))) {
+               ret_val = -ENODEV;
+               goto done;
+       }
+       
        size = 0;
        switch (cmd) {
                case ATM_GETTYPE:
                        size = strlen(dev->type)+1;
-                       if (copy_to_user(buf,dev->type,size)) return -EFAULT;
+                       if (copy_to_user(buf,dev->type,size)) {
+                               ret_val = -EFAULT;
+                               goto done;
+                       }
                        break;
                case ATM_GETESI:
                        size = ESI_LEN;
-                       if (copy_to_user(buf,dev->esi,size)) return -EFAULT;
+                       if (copy_to_user(buf,dev->esi,size)) {
+                               ret_val = -EFAULT;
+                               goto done;
+                       }
                        break;
                case ATM_SETESI:
                        {
                                int i;
 
                                for (i = 0; i < ESI_LEN; i++)
-                                       if (dev->esi[i]) return -EEXIST;
+                                       if (dev->esi[i]) {
+                                               ret_val = -EEXIST;
+                                               goto done;
+                                       }
                        }
                        /* fall through */
                case ATM_SETESIF:
                        {
                                unsigned char esi[ESI_LEN];
 
-                               if (!capable(CAP_NET_ADMIN)) return -EPERM;
-                               if (copy_from_user(esi,buf,ESI_LEN))
-                                       return -EFAULT;
+                               if (!capable(CAP_NET_ADMIN)) {
+                                       ret_val = -EPERM;
+                                       goto done;
+                               }
+                               if (copy_from_user(esi,buf,ESI_LEN)) {
+                                       ret_val = -EFAULT;
+                                       goto done;
+                               }
                                memcpy(dev->esi,esi,ESI_LEN);
-                               return ESI_LEN;
+                               ret_val =  ESI_LEN;
+                               goto done;
                        }
                case ATM_GETSTATZ:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
+                       if (!capable(CAP_NET_ADMIN)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
                        /* fall through */
                case ATM_GETSTAT:
                        size = sizeof(struct atm_dev_stats);
                        error = fetch_stats(dev,buf,cmd == ATM_GETSTATZ);
-                       if (error) return error;
+                       if (error) {
+                               ret_val = error;
+                               goto done;
+                       }
                        break;
                case ATM_GETCIRANGE:
                        size = sizeof(struct atm_cirange);
-                       if (copy_to_user(buf,&dev->ci_range,size))
-                               return -EFAULT;
+                       if (copy_to_user(buf,&dev->ci_range,size)) {
+                               ret_val = -EFAULT;
+                               goto done;
+                       }
                        break;
                case ATM_GETLINKRATE:
                        size = sizeof(int);
-                       if (copy_to_user(buf,&dev->link_rate,size))
-                               return -EFAULT;
+                       if (copy_to_user(buf,&dev->link_rate,size)) {
+                               ret_val = -EFAULT;
+                               goto done;
+                       }
                        break;
                case ATM_RSTADDR:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
+                       if (!capable(CAP_NET_ADMIN)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
                        reset_addr(dev);
                        break;
                case ATM_ADDADDR:
                case ATM_DELADDR:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
+                       if (!capable(CAP_NET_ADMIN)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
                        {
                                struct sockaddr_atmsvc addr;
 
-                               if (copy_from_user(&addr,buf,sizeof(addr)))
-                                       return -EFAULT;
+                               if (copy_from_user(&addr,buf,sizeof(addr))) {
+                                       ret_val = -EFAULT;
+                                       goto done;
+                               }
                                if (cmd == ATM_ADDADDR)
-                                       return add_addr(dev,&addr);
-                               else return del_addr(dev,&addr);
+                                       ret_val = add_addr(dev,&addr);
+                               else
+                                       ret_val = del_addr(dev,&addr);
+                               goto done;
                        }
                case ATM_GETADDR:
                        size = get_addr(dev,buf,len);
-                       if (size < 0) return size;
+                       if (size < 0)
+                               ret_val = size;
+                       else
                        /* may return 0, but later on size == 0 means "don't
                           write the length" */
-                       return put_user(size,
-                           &((struct atmif_sioc *) arg)->length) ? -EFAULT : 0;
+                               ret_val = put_user(size,
+                                                  &((struct atmif_sioc *) arg)->length) ? -EFAULT : 0;
+                       goto done;
                case ATM_SETLOOP:
                        if (__ATM_LM_XTRMT((int) (long) buf) &&
                            __ATM_LM_XTLOC((int) (long) buf) >
-                           __ATM_LM_XTRMT((int) (long) buf))
-                               return -EINVAL;
+                           __ATM_LM_XTRMT((int) (long) buf)) {
+                               ret_val = -EINVAL;
+                               goto done;
+                       }
                        /* fall through */
                case ATM_SETCIRANGE:
                case SONET_GETSTATZ:
                case SONET_SETDIAG:
                case SONET_CLRDIAG:
                case SONET_SETFRAMING:
-                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
+                       if (!capable(CAP_NET_ADMIN)) {
+                               ret_val = -EPERM;
+                               goto done;
+                       }
                        /* fall through */
                default:
-                       if (!dev->ops->ioctl) return -EINVAL;
+                       if (!dev->ops->ioctl) {
+                               ret_val = -EINVAL;
+                               goto done;
+                       }
                        size = dev->ops->ioctl(dev,cmd,buf);
-                       if (size < 0)
-                               return size == -ENOIOCTLCMD ? -EINVAL : size;
+                       if (size < 0) {
+                               ret_val = (size == -ENOIOCTLCMD ? -EINVAL : size);
+                               goto done;
+                       }
        }
-       if (!size) return 0;
-       return put_user(size,&((struct atmif_sioc *) arg)->length) ?
-           -EFAULT : 0;
+       
+       if (size)
+               ret_val =  put_user(size,&((struct atmif_sioc *) arg)->length) ?
+                       -EFAULT : 0;
+
+ done:
+       spin_unlock (&atm_dev_lock); 
+       return ret_val;
 }
 
 
index d9921b408148cf2c38fd69751f73b5aabd2f5071..6b68d7995952509dad468b80bd655133f19a074e 100644 (file)
@@ -772,10 +772,10 @@ lecd_attach(struct atm_vcc *vcc, int arg)
                 size = sizeof(struct lec_priv);
 #ifdef CONFIG_TR
                 if (is_trdev)
-                        dev_lec[i] = init_trdev(NULL, size);
+                        dev_lec[i] = prepare_trdev(NULL, size);
                 else
 #endif
-                dev_lec[i] = init_etherdev(NULL, size);
+                dev_lec[i] = prepare_etherdev(NULL, size);
                 if (!dev_lec[i])
                         return -ENOMEM;
 
@@ -783,6 +783,7 @@ lecd_attach(struct atm_vcc *vcc, int arg)
                 priv->is_trdev = is_trdev;
                 sprintf(dev_lec[i]->name, "lec%d", i);
                 lec_init(dev_lec[i]);
+               publish_netdev(dev_lec[i]);
         } else {
                 priv = dev_lec[i]->priv;
                 if (priv->lecd)
@@ -857,12 +858,7 @@ void cleanup_module(void)
         for (i = 0; i < MAX_LEC_ITF; i++) {
                 if (dev_lec[i] != NULL) {
                         priv = (struct lec_priv *)dev_lec[i]->priv;
-                        if (priv->is_trdev) {
-#ifdef CONFIG_TR
-                                unregister_trdev(dev_lec[i]);
-#endif
-                        } else
-                                unregister_netdev(dev_lec[i]);
+                        unregister_netdev(dev_lec[i]);
                         kfree(dev_lec[i]);
                         dev_lec[i] = NULL;
                 }
index e8d3170bef0c7795325144d3ca2f252bd278a3ab..ef0091735aa765931f3718845c3f6e1874bfcbf7 100644 (file)
@@ -220,7 +220,7 @@ static void vc_info(struct atm_vcc *vcc,char *buf)
                default:
                        here += sprintf(here,"%3d",vcc->family);
        }
-       here += sprintf(here," %04x  %5ld %7d/%7d %7d/%7d\n",vcc->flags.bits,
+       here += sprintf(here," %04lx  %5d %7d/%7d %7d/%7d\n",vcc->flags.bits,
            vcc->reply,
            atomic_read(&vcc->tx_inuse),vcc->sk->sndbuf,
            atomic_read(&vcc->rx_inuse),vcc->sk->rcvbuf);
index 9502367efa9c661d908aeaf636c6fd7218310588..910afff617a7fcc2aece018e9568fa1128bd117d 100644 (file)
@@ -25,6 +25,7 @@
 struct atm_dev *atm_devs = NULL;
 static struct atm_dev *last_dev = NULL;
 struct atm_vcc *nodev_vccs = NULL;
+extern spinlock_t atm_dev_lock;
 
 
 static struct atm_dev *alloc_atm_dev(const char *type)
@@ -48,11 +49,15 @@ static struct atm_dev *alloc_atm_dev(const char *type)
 
 static void free_atm_dev(struct atm_dev *dev)
 {
+       spin_lock (&atm_dev_lock);
+       
        if (dev->prev) dev->prev->next = dev->next;
        else atm_devs = dev->next;
        if (dev->next) dev->next->prev = dev->prev;
        else last_dev = dev->prev;
        kfree(dev);
+       
+       spin_unlock (&atm_dev_lock);
 }
 
 
@@ -100,10 +105,12 @@ struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
                if (atm_proc_dev_register(dev) < 0) {
                        printk(KERN_ERR "atm_dev_register: "
                            "atm_proc_dev_register failed for dev %s\n",type);
+                       spin_unlock (&atm_dev_lock);            
                        free_atm_dev(dev);
                        return NULL;
                }
 #endif
+       spin_unlock (&atm_dev_lock);            
        return dev;
 }
 
index 0b3d64941196721ba29f9fcd61f628aa6bf51c8b..fab17e7c66e34348b50f97d6b233539564eef39e 100644 (file)
@@ -33,6 +33,7 @@
 struct atm_vcc *sigd = NULL;
 static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep);
 
+extern spinlock_t atm_dev_lock;
 
 static void sigd_put_skb(struct sk_buff *skb)
 {
@@ -219,7 +220,10 @@ static void sigd_close(struct atm_vcc *vcc)
                printk(KERN_ERR "sigd_close: closing with requests pending\n");
        while ((skb = skb_dequeue(&vcc->recvq))) kfree_skb(skb);
        purge_vccs(nodev_vccs);
+
+       spin_lock (&atm_dev_lock);
        for (dev = atm_devs; dev; dev = dev->next) purge_vccs(dev->vccs);
+       spin_unlock (&atm_dev_lock);
 }
 
 
index 8e34e42e2040e47bbc20d4c94bda97b2991d397e..b73b4e5f27b2e2c19cbfb0f41962036b7c76b9d4 100644 (file)
  */
 
 #include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 
 
 
-ax25_cb *volatile ax25_list = NULL;
+ax25_cb *volatile ax25_list;
 
 static struct proto_ops ax25_proto_ops;
 
@@ -1853,15 +1852,11 @@ static int __init ax25_init(void)
        ax25_packet_type.type = htons(ETH_P_AX25);
        dev_add_pack(&ax25_packet_type);
        register_netdevice_notifier(&ax25_dev_notifier);
-#ifdef CONFIG_SYSCTL
        ax25_register_sysctl();
-#endif
 
-#ifdef CONFIG_PROC_FS
        proc_net_create("ax25_route", 0, ax25_rt_get_info);
        proc_net_create("ax25", 0, ax25_get_info);
        proc_net_create("ax25_calls", 0, ax25_uid_get_info);
-#endif
 
        printk(KERN_INFO "NET4: G4KLX/GW4PTS AX.25 for Linux. Version 0.37 for Linux NET4.0\n");
        return 0;
@@ -1869,24 +1864,19 @@ static int __init ax25_init(void)
 module_init(ax25_init);
 
 
-#ifdef MODULE
 MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
 MODULE_DESCRIPTION("The amateur radio AX.25 link layer protocol");
 
 static void __exit ax25_exit(void)
 {
-#ifdef CONFIG_PROC_FS
        proc_net_remove("ax25_route");
        proc_net_remove("ax25");
        proc_net_remove("ax25_calls");
-#endif
        ax25_rt_free();
        ax25_uid_free();
        ax25_dev_free();
 
-#ifdef CONFIG_SYSCTL
        ax25_unregister_sysctl();
-#endif
        unregister_netdevice_notifier(&ax25_dev_notifier);
 
        ax25_packet_type.type = htons(ETH_P_AX25);
@@ -1895,6 +1885,3 @@ static void __exit ax25_exit(void)
        sock_unregister(PF_AX25);
 }
 module_exit(ax25_exit);
-#endif /* MODULE */
-
-#endif
index 1b0f9da67e11ea8eb1ea49bce768c81cb3f9b775..f96c65586c04b80b2354557c82e72b8f290ed70f 100644 (file)
@@ -19,8 +19,6 @@
  *     AX.25 036       Jonathan(G4KLX) Split from ax25_subr.c.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -303,4 +301,3 @@ void ax25_digi_invert(ax25_digi *in, ax25_digi *out)
        }
 }
 
-#endif
index 0436db90301e89a533ca5b12d8173ae11792b4b5..efeec64e03ec355e5580ed18c5d24011b560c712 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -39,8 +38,9 @@
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
+#include <linux/init.h>
 
-ax25_dev *ax25_dev_list = NULL;
+ax25_dev *ax25_dev_list;
 
 ax25_dev *ax25_dev_ax25dev(struct net_device *dev)
 {
@@ -78,9 +78,7 @@ void ax25_dev_device_up(struct net_device *dev)
                return;
        }
 
-#ifdef CONFIG_SYSCTL
        ax25_unregister_sysctl();
-#endif
 
        memset(ax25_dev, 0x00, sizeof(*ax25_dev));
 
@@ -107,9 +105,7 @@ void ax25_dev_device_up(struct net_device *dev)
        ax25_dev_list  = ax25_dev;
        restore_flags(flags);
 
-#ifdef CONFIG_SYSCTL
        ax25_register_sysctl();
-#endif
 }
 
 void ax25_dev_device_down(struct net_device *dev)
@@ -120,9 +116,7 @@ void ax25_dev_device_down(struct net_device *dev)
        if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
                return;
 
-#ifdef CONFIG_SYSCTL
        ax25_unregister_sysctl();
-#endif
 
        save_flags(flags); cli();
 
@@ -141,9 +135,7 @@ void ax25_dev_device_down(struct net_device *dev)
                ax25_dev_list = s->next;
                restore_flags(flags);
                kfree(ax25_dev);
-#ifdef CONFIG_SYSCTL
                ax25_register_sysctl();
-#endif
                return;
        }
 
@@ -152,9 +144,7 @@ void ax25_dev_device_down(struct net_device *dev)
                        s->next = ax25_dev->next;
                        restore_flags(flags);
                        kfree(ax25_dev);
-#ifdef CONFIG_SYSCTL
                        ax25_register_sysctl();
-#endif
                        return;
                }
 
@@ -162,9 +152,7 @@ void ax25_dev_device_down(struct net_device *dev)
        }
 
        restore_flags(flags);
-#ifdef CONFIG_SYSCTL
        ax25_register_sysctl();
-#endif
 }
 
 int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
@@ -209,12 +197,10 @@ struct net_device *ax25_fwd_dev(struct net_device *dev)
        return ax25_dev->forward;
 }
 
-#ifdef MODULE
-
 /*
  *     Free all memory associated with device structures.
  */
-void ax25_dev_free(void)
+void __exit ax25_dev_free(void)
 {
        ax25_dev *s, *ax25_dev = ax25_dev_list;
 
@@ -225,7 +211,3 @@ void ax25_dev_free(void)
                kfree(s);
        }
 }
-
-#endif
-
-#endif
index 3354206dfb97749ab8f2b9dfa92d0b6de71406d0..6c65baea59af48ac41db398e29c13f8c85cd2198 100644 (file)
@@ -22,8 +22,6 @@
  *                     Joerg(DL1BKE)   ax25->n2count never got reset
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_AX25_DAMA_SLAVE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -312,4 +310,3 @@ int ax25_ds_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type)
        return queued;
 }
 
-#endif
index 3a6f6c2594767ad9cac7300db5291df92e2d2ba5..e3e88d7710af9c8b052b3cea1915fcd882cd3e29 100644 (file)
@@ -22,8 +22,6 @@
  *     AX.25 037       Jonathan(G4KLX) New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_AX25_DAMA_SLAVE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -217,4 +215,3 @@ void ax25_dama_off(ax25_cb *ax25)
        ax25_dev_dama_off(ax25->ax25_dev);
 }
 
-#endif
index 06135e9de491c8dfb81b7e04f5bffeededf0863b..3c5b2ea9c32ba4472a91901958c15ffe30ba2d96 100644 (file)
@@ -15,8 +15,6 @@
  *     AX.25 037       Jonathan(G4KLX) New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_AX25_DAMA_SLAVE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -224,5 +222,3 @@ void ax25_ds_t1_timeout(ax25_cb *ax25)
        ax25_calculate_t1(ax25);
        ax25_start_t1timer(ax25);
 }
-
-#endif
index 2e53ad95912d76304ac424271d2e841cc53d756d..15ca9c45304e1aa68c989e0bae2c9181ff65767f 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -40,18 +39,18 @@ static struct protocol_struct {
        struct protocol_struct *next;
        unsigned int pid;
        int (*func)(struct sk_buff *, ax25_cb *);
-} *protocol_list = NULL;
+} *protocol_list;
 
 static struct linkfail_struct {
        struct linkfail_struct *next;
        void (*func)(ax25_cb *, int);
-} *linkfail_list = NULL;
+} *linkfail_list;
 
 static struct listen_struct {
        struct listen_struct *next;
        ax25_address  callsign;
        struct net_device *dev;
-} *listen_list = NULL;
+} *listen_list;
 
 int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_cb *))
 {
@@ -267,4 +266,3 @@ int ax25_protocol_is_registered(unsigned int pid)
        return 0;
 }
 
-#endif
index 6efbc57f21229f5d65dcfa21f4475042dd2371a5..ed5e6fbcecc658f86bc404e672a00e9eb8095969 100644 (file)
@@ -39,7 +39,6 @@
  */
 
 #include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -480,4 +479,3 @@ int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_typ
        return ax25_rcv(skb, dev, (ax25_address *)dev->dev_addr, ptype);
 }
 
-#endif
index a298fb59d737b9dad0f2de8007d669bbfdb35ceb..e6dcda83d93ff172461046b5e3d1d7d45fb4e39a 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -210,4 +209,3 @@ int ax25_rebuild_header(struct sk_buff *skb)
 
 #endif
 
-#endif
index e6b19f53be7489bff1949082e6982fdf60822779..231c170e7a0b71cab818cf459f98739436de957c 100644 (file)
@@ -35,7 +35,6 @@
  */
 
 #include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -408,4 +407,3 @@ int ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)
        return 0;
 }
 
-#endif
index 32a7ab51571217b7bae5b2f9bad45a1a2689e72b..254ff36fb6691fd7ee0932b08873685246e48349 100644 (file)
@@ -41,8 +41,6 @@
  *                     Arnaldo C. Melo s/suser/capable/
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -64,8 +62,9 @@
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
+#include <linux/init.h>
 
-static ax25_route *ax25_route_list = NULL;
+static ax25_route *ax25_route_list;
 
 static ax25_route *ax25_find_route(ax25_address *, struct net_device *);
 
@@ -434,12 +433,10 @@ struct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src, ax25_
        return skb;
 }
 
-#ifdef MODULE
-
 /*
  *     Free all memory associated with routing structures.
  */
-void ax25_rt_free(void)
+void __exit ax25_rt_free(void)
 {
        ax25_route *s, *ax25_rt = ax25_route_list;
 
@@ -453,7 +450,3 @@ void ax25_rt_free(void)
                kfree(s);
        }
 }
-
-#endif
-
-#endif
index 1e27580cf0615a4eb39eaff1cfcf18ac0c0b29c8..d1cfc3ff95733fe328f1c1d6bc572faea2a64868 100644 (file)
@@ -37,8 +37,6 @@
  *     AX.25 037       Jonathan(G4KLX) New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -467,5 +465,3 @@ int ax25_std_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type)
 
        return queued;
 }
-
-#endif
index 1b1d1c8bb7e8fc65292d1f61faf7c7ae023ea847..c868e0507952ee07ad9539055e964337e78783a6 100644 (file)
@@ -20,8 +20,6 @@
  *     AX.25 037       Jonathan(G4KLX) New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -102,5 +100,3 @@ void ax25_std_timeout_response(ax25_cb *ax25)
 
        ax25->condition &= ~AX25_COND_ACK_PENDING;
 }
-
-#endif
index 4e97c51b8566893819292916ebd4519f699f620c..5a2d8771c96b3dd073630a51a58b09a957afbd2d 100644 (file)
@@ -22,8 +22,6 @@
  *     AX.25 037       Jonathan(G4KLX) New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -170,5 +168,3 @@ void ax25_std_t1timer_expiry(ax25_cb *ax25)
        ax25_calculate_t1(ax25);
        ax25_start_t1timer(ax25);
 }
-
-#endif
index 97ef02d08ce77ae93ed0b2269f9039c331d32fc4..66978964628a9153fd8c751f587c9f660db8f955 100644 (file)
@@ -33,8 +33,6 @@
  *     AX.25 037       Jonathan(G4KLX) New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -324,5 +322,3 @@ void ax25_disconnect(ax25_cb *ax25, int reason)
                ax25->sk->dead      = 1;
        }
 }
-
-#endif
index 08e1904569bfeabcf3fe068fe4cda2b166fa800d..01e7596f3d3a5249b4c13e02ea0f18e3d69f39da 100644 (file)
@@ -26,7 +26,6 @@
  */
 
 #include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -255,5 +254,3 @@ static void ax25_idletimer_expiry(unsigned long param)
 #endif
        }
 }
-
-#endif
index eb226b14cdf79dc0ca2a555332cdd51531be6457..603d8b8cc8642b3d3441ca518d52404bb91463ec 100644 (file)
@@ -13,8 +13,6 @@
  *     AX.25 036       Jonathan(G4KLX) Split from af_ax25.c.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -48,7 +46,7 @@
  *     Callsign/UID mapper. This is in kernel space for security on multi-amateur machines.
  */
 
-static ax25_uid_assoc *ax25_uid_list = NULL;
+static ax25_uid_assoc *ax25_uid_list;
 
 int ax25_uid_policy = 0;
 
@@ -164,12 +162,10 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
        return len;
 }
 
-#ifdef MODULE
-
 /*
  *     Free all memory associated with UID/Callsign structures.
  */
-void ax25_uid_free(void)
+void __exit ax25_uid_free(void)
 {
        ax25_uid_assoc *s, *ax25_uid = ax25_uid_list;
 
@@ -180,7 +176,3 @@ void ax25_uid_free(void)
                kfree(s);
        }
 }
-
-#endif
-
-#endif
index f0e9bb5bb3d61300f0be11ff460782a9c3a0eeab..b7af2b9f6997ab2f921aa5c1efeba7262d5da90e 100644 (file)
@@ -783,7 +783,7 @@ static int __init ic_dynamic(void)
                printk(".");
                jiff = jiffies + timeout;
                while (jiffies < jiff && !ic_got_reply)
-                       ;
+                       barrier();
                if (ic_got_reply) {
                        printk(" OK\n");
                        break;
index a0c139b3a436308d6afd7a8fbe2bffaa01152d61..a4b89d294b900030e4a54bc216ad12e761dd1686 100644 (file)
@@ -34,7 +34,6 @@
  */
 
 #include <linux/config.h>
-#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -82,7 +81,7 @@ int sysctl_netrom_link_fails_count                = NR_DEFAULT_FAILS;
 
 static unsigned short circuit = 0x101;
 
-static struct sock *volatile nr_list = NULL;
+static struct sock *volatile nr_list;
 
 static struct proto_ops nr_proto_ops;
 
@@ -1280,7 +1279,7 @@ static int __init nr_proto_init(void)
 
        sock_register(&nr_family_ops);
        register_netdevice_notifier(&nr_dev_notifier);
-       printk(KERN_INFO "G4KLX NET/ROM for Linux. Version 0.7 for AX25.037 Linux 2.1\n");
+       printk(KERN_INFO "G4KLX NET/ROM for Linux. Version 0.7 for AX25.037 Linux 2.4\n");
 
        ax25_protocol_register(AX25_P_NETROM, nr_route_frame);
        ax25_linkfail_register(nr_link_failed);
@@ -1291,18 +1290,15 @@ static int __init nr_proto_init(void)
 
        nr_loopback_init();
 
-#ifdef CONFIG_PROC_FS
        proc_net_create("nr", 0, nr_get_info);
        proc_net_create("nr_neigh", 0, nr_neigh_get_info);
        proc_net_create("nr_nodes", 0, nr_nodes_get_info);
-#endif 
        return 0;
 }
 
 module_init(nr_proto_init);
 
 
-#ifdef MODULE
 EXPORT_NO_SYMBOLS;
 
 MODULE_PARM(nr_ndevs, "i");
@@ -1311,15 +1307,13 @@ MODULE_PARM_DESC(nr_ndevs, "number of NET/ROM devices");
 MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
 MODULE_DESCRIPTION("The amateur radio NET/ROM network and transport layer protocol");
 
-static void nr_exit(void)
+static void __exit nr_exit(void)
 {
        int i;
 
-#ifdef CONFIG_PROC_FS
        proc_net_remove("nr");
        proc_net_remove("nr_neigh");
        proc_net_remove("nr_nodes");
-#endif
        nr_loopback_clear();
 
        nr_rt_free();
@@ -1346,8 +1340,3 @@ static void nr_exit(void)
        kfree(dev_nr);
 }
 module_exit(nr_exit);
-#endif /* MODULE */
-
-
-
-#endif
index 1625d1c9013256c91961551ff521b3df62e16079..d5a472703d92e0bd459053bab2570e0fd103f3e2 100644 (file)
@@ -19,7 +19,6 @@
  */
 
 #include <linux/config.h>
-#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 #define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/proc_fs.h>
@@ -236,5 +235,3 @@ int nr_init(struct net_device *dev)
 
        return 0;
 };
-
-#endif
index fadf69de8c256f73c010287f43738359a786e132..29762e929e93f5298622630418ce2d91e70263fc 100644 (file)
@@ -24,8 +24,6 @@
  *     NET/ROM 007     Jonathan(G4KLX) New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -304,5 +302,3 @@ int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb)
 
        return queued;
 }
-
-#endif
index fc0665de289ffbe2905bec8d026ee9d849a87411..5290ae024957d35db37d0e6a0a8cf85a5d0b9708 100644 (file)
  *
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/timer.h>
 #include <net/ax25.h>
 #include <linux/skbuff.h>
 #include <net/netrom.h>
+#include <linux/init.h>
 
 static struct sk_buff_head loopback_queue;
 static struct timer_list loopback_timer;
@@ -91,9 +90,7 @@ static void nr_loopback_timer(unsigned long param)
        }
 }
 
-#ifdef MODULE
-
-void nr_loopback_clear(void)
+void __exit nr_loopback_clear(void)
 {
        struct sk_buff *skb;
 
@@ -102,7 +99,3 @@ void nr_loopback_clear(void)
        while ((skb = skb_dequeue(&loopback_queue)) != NULL)
                kfree_skb(skb);
 }
-
-#endif
-
-#endif
index 93da60adb7abf85a4f0d1a890eb4b9e0f8d7ac17..0900689883b18348518b51009ced1adcc0d9ee77 100644 (file)
@@ -16,8 +16,6 @@
  *     NET/ROM 007     Jonathan(G4KLX) New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -272,5 +270,3 @@ void nr_check_iframes_acked(struct sock *sk, unsigned short nr)
                }
        }
 }
-
-#endif
index 308e73af26da2e5cc28f5b894e90ed63d15f9e50..ec0578b51316f7edeedd68e405876b3568888b62 100644 (file)
@@ -21,8 +21,6 @@
  *                     Tomi(OH2BNS)    Routing quality and link failure changes.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/netfilter.h>
+#include <linux/init.h>
 #include <net/netrom.h>
 
 static unsigned int nr_neigh_no = 1;
 
-static struct nr_node  *nr_node_list  = NULL;
-static struct nr_neigh *nr_neigh_list = NULL;
+static struct nr_node  *nr_node_list;
+static struct nr_neigh *nr_neigh_list;
 
 static void nr_remove_neigh(struct nr_neigh *);
 
@@ -850,12 +849,10 @@ int nr_neigh_get_info(char *buffer, char **start, off_t offset, int length)
        return len;
 } 
 
-#ifdef MODULE
-
 /*
  *     Free all memory associated with the nodes and routes lists.
  */
-void nr_rt_free(void)
+void __exit nr_rt_free(void)
 {
        struct nr_neigh *s, *nr_neigh = nr_neigh_list;
        struct nr_node  *t, *nr_node  = nr_node_list;
@@ -874,7 +871,3 @@ void nr_rt_free(void)
                nr_remove_neigh(s);
        }
 }
-
-#endif
-
-#endif
index 096ca3a8f5820269272bb427993e3d474e032d54..fee0478fa1705f4092273793ffb49c1c2823fac1 100644 (file)
@@ -15,8 +15,6 @@
  *     NET/ROM 007     Jonathan(G4KLX) New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -297,5 +295,3 @@ void nr_disconnect(struct sock *sk, int reason)
 
        sk->dead = 1;
 }
-
-#endif
index ac62ad54a2e944a13ad0ceeb5c354e4c4ea222ac..116770434ab5efea79494c12321e5721f1bf6b29 100644 (file)
@@ -15,8 +15,6 @@
  *                                     Implemented idle timer.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -245,5 +243,3 @@ static void nr_t1timer_expiry(unsigned long param)
 
        nr_start_t1timer(sk);
 }
-
-#endif
index f639e578abd0fa6eff03ae13dc73f40385449b06..a92bf86f5977d8ef2f5430002ad757e40d4dfc5e 100644 (file)
@@ -25,7 +25,6 @@
  */
 
 #include <linux/config.h>
-#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/errno.h>
@@ -1448,7 +1447,7 @@ static int __init rose_proto_init(void)
 
        sock_register(&rose_family_ops);
        register_netdevice_notifier(&rose_dev_notifier);
-       printk(KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62 for AX25.037 Linux 2.1\n");
+       printk(KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62 for AX25.037 Linux 2.4\n");
 
        ax25_protocol_register(AX25_P_ROSE, rose_route_frame);
        ax25_linkfail_register(rose_link_failed);
@@ -1460,17 +1459,14 @@ static int __init rose_proto_init(void)
 
        rose_add_loopback_neigh();
 
-#ifdef CONFIG_PROC_FS
        proc_net_create("rose", 0, rose_get_info);
        proc_net_create("rose_neigh", 0, rose_neigh_get_info);
        proc_net_create("rose_nodes", 0, rose_nodes_get_info);
        proc_net_create("rose_routes", 0, rose_routes_get_info);
-#endif
        return 0;
 }
 module_init(rose_proto_init);
 
-#ifdef MODULE
 EXPORT_NO_SYMBOLS;
 
 MODULE_PARM(rose_ndevs, "i");
@@ -1483,12 +1479,10 @@ static void __exit rose_exit(void)
 {
        int i;
 
-#ifdef CONFIG_PROC_FS
        proc_net_remove("rose");
        proc_net_remove("rose_neigh");
        proc_net_remove("rose_nodes");
        proc_net_remove("rose_routes");
-#endif
        rose_loopback_clear();
 
        rose_rt_free();
@@ -1518,7 +1512,4 @@ static void __exit rose_exit(void)
        kfree(dev_rose);
 }
 module_exit(rose_exit);
-#endif /* MODULE */
 
-
-#endif
index 88f2d55e7e77c42378309c1dd45ab2393c1ad383..92ad1e55ad749f49c65bc029d14a18d56d6960e9 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/config.h>
-#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/proc_fs.h>
@@ -205,5 +204,3 @@ int rose_init(struct net_device *dev)
 
        return 0;
 };
-
-#endif
index be86c9e16725bfb7c5277fb13cc213fada370c3d..38fb76c1b5efc2268e18af78bf39295a072cdd4e 100644 (file)
@@ -22,8 +22,6 @@
  *                                     Removed M bit processing.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -303,5 +301,3 @@ int rose_process_rx_frame(struct sock *sk, struct sk_buff *skb)
 
        return queued;
 }
-
-#endif
index d9b5a4a1dd91862af1d574194422773d7df4b60e..2c793e4e6b5e04e100c93f210a07a546cac7c5e2 100644 (file)
@@ -14,8 +14,6 @@
  *     ROSE 003        Jonathan(G4KLX) New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -322,5 +320,3 @@ void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh)
                }
        }
 }
-
-#endif
index 2136fd601c2e819b68201163e10d121372692100..ad00608a3911d6b67197b2886769ba83105929c2 100644 (file)
  *
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/timer.h>
 #include <net/ax25.h>
 #include <linux/skbuff.h>
 #include <net/rose.h>
+#include <linux/init.h>
 
 static struct sk_buff_head loopback_queue;
 static struct timer_list loopback_timer;
@@ -107,9 +106,7 @@ static void rose_loopback_timer(unsigned long param)
        }
 }
 
-#ifdef MODULE
-
-void rose_loopback_clear(void)
+void __exit rose_loopback_clear(void)
 {
        struct sk_buff *skb;
 
@@ -120,7 +117,3 @@ void rose_loopback_clear(void)
                kfree_skb(skb);
        }
 }
-
-#endif
-
-#endif
index aea1d9f68efab971d4a51d7c97c859ddfcf9412b..8f9855df7eaa930fd889ccb6b50ef139a9799073 100644 (file)
@@ -15,8 +15,6 @@
  *                                     Removed M bit processing.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -130,5 +128,3 @@ void rose_enquiry_response(struct sock *sk)
 
        rose_stop_timer(sk);
 }
-
-#endif
index d5d4de9ec1b01c1e9c8ef55916ebc89201f31bd4..1bedfdf0d3b492002eb8f56de1e54164096e6ebc 100644 (file)
@@ -19,8 +19,6 @@
  *                                     Added use count to neighbours.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/netfilter.h>
+#include <linux/init.h>
 #include <net/rose.h>
 
 static unsigned int rose_neigh_no = 1;
 
-static struct rose_node  *rose_node_list  = NULL;
-static struct rose_neigh *rose_neigh_list = NULL;
-static struct rose_route *rose_route_list = NULL;
+static struct rose_node  *rose_node_list;
+static struct rose_neigh *rose_neigh_list;
+static struct rose_route *rose_route_list;
 
-struct rose_neigh *rose_loopback_neigh = NULL;
+struct rose_neigh *rose_loopback_neigh;
 
 static void rose_remove_neigh(struct rose_neigh *);
 
@@ -1126,12 +1125,10 @@ int rose_routes_get_info(char *buffer, char **start, off_t offset, int length)
        return len;
 } 
 
-#ifdef MODULE
-
 /*
  *     Release all memory associated with ROSE routing structures.
  */
-void rose_rt_free(void)
+void __exit rose_rt_free(void)
 {
        struct rose_neigh *s, *rose_neigh = rose_neigh_list;
        struct rose_node  *t, *rose_node  = rose_node_list;
@@ -1158,7 +1155,3 @@ void rose_rt_free(void)
                rose_remove_route(u);
        }
 }
-
-#endif
-
-#endif
index dc172ac3be4e5ed1ec8365e337747176a7c7a5f1..384347a0e94bad03d74cc3b5504608c16633961a 100644 (file)
@@ -15,8 +15,6 @@
  *     ROSE 003        Jonathan(G4KLX) Added use count to neighbours.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -528,5 +526,3 @@ void rose_disconnect(struct sock *sk, int reason, int cause, int diagnostic)
 
        sk->dead  = 1;
 }
-
-#endif
index 718a64ec04d2aed8cfed9a3b02be15f355248107..8bd30424d990b408df1a44c9a4f4bb7f8a389d73 100644 (file)
@@ -15,8 +15,6 @@
  *                                     Implemented idle timer.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -207,5 +205,3 @@ static void rose_idletimer_expiry(unsigned long param)
 
        sk->dead = 1;
 }
-
-#endif
index 77dba8e220c6177068bdad67469aa83027b332cc..4f8fb25becc4d8ee9cec02ae4112adc6e5cff971 100644 (file)
@@ -664,26 +664,46 @@ sub output_intro {
 
 ##
 # takes a function prototype and spits out all the details
-# stored in the global arrays/hsahes.
+# stored in the global arrays/hashes.
 sub dump_function {
     my $prototype = shift @_;
 
-    $prototype =~ s/^static+ //;
-    $prototype =~ s/^extern+ //;
-    $prototype =~ s/^inline+ //;
-    $prototype =~ s/^__inline__+ //;
-    $prototype =~ s/^#define+ //; #ak added
+    $prototype =~ s/^static +//;
+    $prototype =~ s/^extern +//;
+    $prototype =~ s/^inline +//;
+    $prototype =~ s/^__inline__ +//;
+    $prototype =~ s/^#define +//; #ak added
+
+    # Yes, this truly is vile.  We are looking for:
+    # 1. Return type (may be nothing if we're looking at a macro)
+    # 2. Function name
+    # 3. Function parameters.
+    #
+    # All the while we have to watch out for function pointer parameters
+    # (which IIRC is what the two sections are for), C types (these
+    # regexps don't even start to express all the possibilities), and
+    # so on.
+    #
+    # If you mess with these regexps, it's a good idea to check that
+    # the following functions' documentation still comes out right:
+    # - parport_register_device (function pointer parameters)
+    # - atomic_set (macro)
+    # - pci_match_device (long return type)
 
     if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
        $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
        $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
        $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
        $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+       $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+       $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
        $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
        $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
        $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
        $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
-       $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
+       $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+       $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+       $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
        $return_type = $1;
        $function_name = $2;
        $args = $3;
@@ -728,13 +748,13 @@ sub dump_function {
                $param="...";
                $parameters{"..."} = "variable arguments";
            }
-           if ($type eq "")
+           elsif ($type eq "" && $param eq "")
            {
                $type="";
                $param="void";
                $parameters{void} = "no arguments";
            }
-            if ($parameters{$param} eq "") {
+            if ($type ne "" && $parameters{$param} eq "") {
                $parameters{$param} = "-- undescribed --";
                print STDERR "Warning($file:$lineno): Function parameter '$param' not described in '$function_name'\n";
            }