From 31d65e93a998f57f3640a446029d9153198d4c56 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:41:06 -0500 Subject: [PATCH] Ok, there's a test13-pre6 out there now, which does a partial sync with 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 --- CREDITS | 8 + Documentation/Changes | 6 +- Documentation/i2c/functionality | 135 ++ Documentation/modules.txt | 2 +- Documentation/sound/ALS | 49 +- Makefile | 2 +- arch/i386/boot/setup.S | 8 +- arch/i386/config.in | 22 +- arch/i386/kernel/Makefile | 2 +- arch/i386/kernel/smp.c | 11 +- arch/i386/kernel/time.c | 2 +- drivers/acpi/include/aclinux.h | 1 - drivers/acpi/ksyms.c | 1 - drivers/atm/Config.in | 1 + drivers/atm/ambassador.c | 9 +- drivers/atm/atmdev_init.c | 2 +- drivers/atm/atmtcp.c | 12 +- drivers/atm/firestream.c | 2088 +++++++++++++++++++++++++++++++ drivers/atm/firestream.h | 505 ++++++++ drivers/atm/fore200e.c | 42 +- drivers/atm/horizon.c | 11 +- drivers/atm/iphase.c | 5 +- drivers/atm/nicstar.c | 5 +- drivers/char/generic_serial.c | 7 +- drivers/char/i810-tco.c | 19 +- drivers/char/pcxx.c | 3 +- drivers/char/sh-sci.c | 2 +- drivers/char/sx.c | 122 +- drivers/i2c/i2c-algo-pcf.c | 4 +- drivers/i2c/i2c-core.c | 33 +- drivers/i2c/i2c-dev.c | 89 +- drivers/isdn/Config.in | 70 +- drivers/isdn/Makefile | 27 +- drivers/isdn/act2000/Makefile | 13 +- drivers/isdn/avmb1/Makefile | 9 +- drivers/isdn/divert/Makefile | 15 +- drivers/isdn/eicon/Makefile | 11 +- drivers/isdn/hisax/Makefile | 24 +- drivers/isdn/hysdn/Makefile | 13 +- drivers/isdn/icn/Makefile | 13 +- drivers/isdn/isdn_cards.c | 4 +- drivers/isdn/isdn_common.c | 3 + drivers/isdn/isdnloop/Makefile | 13 +- drivers/isdn/pcbit/Makefile | 13 +- drivers/isdn/sc/Makefile | 13 +- drivers/net/8139too.c | 1 - drivers/net/hamradio/bpqether.c | 58 +- drivers/net/hamradio/mkiss.c | 379 ++---- drivers/net/hamradio/yam.c | 283 ++--- drivers/pcmcia/cs.c | 6 +- drivers/scsi/aha152x.c | 4 +- drivers/scsi/pci2000.c | 2 +- drivers/scsi/pci2220i.c | 6 +- drivers/scsi/sim710.c | 2 +- drivers/sound/cmpci.c | 25 +- drivers/sound/cs4281.c | 22 +- drivers/sound/es1370.c | 14 +- drivers/sound/es1371.c | 14 +- drivers/sound/esssolo1.c | 14 +- drivers/sound/maestro.c | 23 +- drivers/sound/sonicvibes.c | 14 +- drivers/sound/trident.c | 21 +- drivers/telephony/ixj.c | 4 +- drivers/telephony/ixj.h | 2 +- fs/adfs/inode.c | 2 +- fs/affs/file.c | 2 +- fs/affs/symlink.c | 2 +- fs/buffer.c | 18 +- fs/coda/dir.c | 8 +- fs/coda/file.c | 4 +- fs/coda/inode.c | 2 +- fs/coda/symlink.c | 2 +- fs/cramfs/inode.c | 2 +- fs/efs/symlink.c | 2 +- fs/ext2/balloc.c | 70 +- fs/ext2/inode.c | 10 +- fs/ext2/super.c | 105 +- fs/fat/inode.c | 2 +- fs/hfs/inode.c | 2 +- fs/hpfs/file.c | 2 +- fs/hpfs/namei.c | 2 +- fs/inode.c | 17 +- fs/isofs/rock.c | 2 +- fs/jffs/inode-v23.c | 2 +- fs/lockd/xdr4.c | 3 +- fs/ncpfs/symlink.c | 2 +- fs/nfs/file.c | 4 +- fs/nfs/read.c | 2 +- fs/nfs/write.c | 2 +- fs/nls/Config.in | 9 +- fs/ntfs/fs.c | 2 +- fs/qnx4/inode.c | 2 +- fs/ramfs/inode.c | 2 +- fs/romfs/inode.c | 2 +- fs/smbfs/file.c | 2 +- fs/udf/file.c | 6 +- fs/udf/symlink.c | 2 +- include/linux/atm_tcp.h | 1 + include/linux/atmdev.h | 1 + include/linux/ext2_fs.h | 22 +- include/linux/ext2_fs_sb.h | 5 +- include/linux/fs.h | 25 +- include/linux/generic_serial.h | 2 +- include/linux/i2c-dev.h | 16 +- include/linux/i2c-id.h | 28 +- include/linux/i2c.h | 18 +- include/linux/lvm.h | 1 + include/linux/mm.h | 10 +- include/net/ax25.h | 5 + ipc/shm.c | 1 + mm/filemap.c | 205 +-- mm/memory.c | 16 +- mm/shmem.c | 15 +- mm/swap_state.c | 7 +- mm/vmscan.c | 9 +- net/atm/addr.c | 4 +- net/atm/common.c | 379 ++++-- net/atm/lec.c | 12 +- net/atm/proc.c | 2 +- net/atm/resources.c | 7 + net/atm/signaling.c | 4 + net/ax25/af_ax25.c | 15 +- net/ax25/ax25_addr.c | 3 - net/ax25/ax25_dev.c | 24 +- net/ax25/ax25_ds_in.c | 3 - net/ax25/ax25_ds_subr.c | 3 - net/ax25/ax25_ds_timer.c | 4 - net/ax25/ax25_iface.c | 8 +- net/ax25/ax25_in.c | 2 - net/ax25/ax25_ip.c | 2 - net/ax25/ax25_out.c | 2 - net/ax25/ax25_route.c | 13 +- net/ax25/ax25_std_in.c | 4 - net/ax25/ax25_std_subr.c | 4 - net/ax25/ax25_std_timer.c | 4 - net/ax25/ax25_subr.c | 4 - net/ax25/ax25_timer.c | 3 - net/ax25/ax25_uid.c | 12 +- net/ipv4/ipconfig.c | 2 +- net/netrom/af_netrom.c | 17 +- net/netrom/nr_dev.c | 3 - net/netrom/nr_in.c | 4 - net/netrom/nr_loopback.c | 11 +- net/netrom/nr_out.c | 4 - net/netrom/nr_route.c | 15 +- net/netrom/nr_subr.c | 4 - net/netrom/nr_timer.c | 4 - net/rose/af_rose.c | 11 +- net/rose/rose_dev.c | 3 - net/rose/rose_in.c | 4 - net/rose/rose_link.c | 4 - net/rose/rose_loopback.c | 11 +- net/rose/rose_out.c | 4 - net/rose/rose_route.c | 19 +- net/rose/rose_subr.c | 4 - net/rose/rose_timer.c | 4 - scripts/kernel-doc | 38 +- 157 files changed, 4228 insertions(+), 1484 deletions(-) create mode 100644 Documentation/i2c/functionality create mode 100644 drivers/atm/firestream.c create mode 100644 drivers/atm/firestream.h diff --git a/CREDITS b/CREDITS index b2e00bf576fe..580bc44bab58 100644 --- 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 diff --git a/Documentation/Changes b/Documentation/Changes index a8a568c5de3b..4c0881fff9d1 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -31,7 +31,7 @@ al espa Eine deutsche Version dieser Datei finden Sie unter . -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 Modutils -------- -o +o Mkinitrd -------- diff --git a/Documentation/i2c/functionality b/Documentation/i2c/functionality new file mode 100644 index 000000000000..8a78a95ae04e --- /dev/null +++ b/Documentation/i2c/functionality @@ -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 +! + + 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 ! */ + 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 */ diff --git a/Documentation/modules.txt b/Documentation/modules.txt index e7e371945222..885a4d6afdb6 100644 --- a/Documentation/modules.txt +++ b/Documentation/modules.txt @@ -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 diff --git a/Documentation/sound/ALS b/Documentation/sound/ALS index c5e55d5b76be..d01ffbfd5808 100644 --- a/Documentation/sound/ALS +++ b/Documentation/sound/ALS @@ -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. diff --git a/Makefile b/Makefile index 28778a009e9a..1308977149a2 100644 --- 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) diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S index c52b170ecdca..adbbcc3c64b2 100644 --- a/arch/i386/boot/setup.S +++ b/arch/i386/boot/setup.S @@ -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? diff --git a/arch/i386/config.in b/arch/i386/config.in index ecbb22b340fd..4dc863995d3b 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -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 diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 6e7535a70abd..67872949d8d7 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -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 diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index f39e42522fd6..6607edf8a20d 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -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) diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 12ba21b926a7..c7672ceed5b1 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -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 */ diff --git a/drivers/acpi/include/aclinux.h b/drivers/acpi/include/aclinux.h index 7b5407654829..673d5f96b34d 100644 --- a/drivers/acpi/include/aclinux.h +++ b/drivers/acpi/include/aclinux.h @@ -29,7 +29,6 @@ #define ACPI_OS_NAME "Linux" -#include #include #include #include diff --git a/drivers/acpi/ksyms.c b/drivers/acpi/ksyms.c index cb4c5a4b92a5..13f4fe0e78fc 100644 --- a/drivers/acpi/ksyms.c +++ b/drivers/acpi/ksyms.c @@ -18,7 +18,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include #include #include #include diff --git a/drivers/atm/Config.in b/drivers/atm/Config.in index b04a354bc140..2f82a75e8d60 100644 --- a/drivers/atm/Config.in +++ b/drivers/atm/Config.in @@ -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 diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 8a24cfb66f66..3de74d517115 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -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 **********/ diff --git a/drivers/atm/atmdev_init.c b/drivers/atm/atmdev_init.c index 73c785fe05fa..14f6df532670 100644 --- a/drivers/atm/atmdev_init.c +++ b/drivers/atm/atmdev_init.c @@ -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; } diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c index 9c4f2e7f3c98..17f607a73ead 100644 --- a/drivers/atm/atmtcp.c +++ b/drivers/atm/atmtcp.c @@ -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 index 000000000000..7671afd9d573 --- /dev/null +++ b/drivers/atm/firestream.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for request_region */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 = /, 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;ival;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 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 index 000000000000..cde9d9bf9292 --- /dev/null +++ b/drivers/atm/firestream.h @@ -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) diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 5d4fdd543930..4d51e762b2c2 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -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, }; diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 913b6f2edfdb..3a5cf5f9d802 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -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) { diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 2187039d44ec..e2300a8450ab 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -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); diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 8b6d71237fd9..7e9dc5ee21ac 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -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 { diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 3e8c404df067..acd3402f89c2 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -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); diff --git a/drivers/char/i810-tco.c b/drivers/char/i810-tco.c index b01564030839..f7083afeeca0 100644 --- a/drivers/char/i810-tco.c +++ b/drivers/char/i810-tco.c @@ -55,6 +55,7 @@ #define TIMER_MARGIN 50 /* steps of 0.6sec, 2 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")) { diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c index 582503ec3428..4010973c74f1 100644 --- a/drivers/char/pcxx.c +++ b/drivers/char/pcxx.c @@ -1823,8 +1823,7 @@ static void doevent(int crd) */ static void pcxxdelay(int msec) { - while(msec-- > 0) - __delay(loops_per_sec/1000); + mdelay(mseconds); } diff --git a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c index 01812ecb0096..c14fa8487a2d 100644 --- a/drivers/char/sh-sci.c +++ b/drivers/char/sh-sci.c @@ -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; diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 9026421513ed..024bada51198 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -223,7 +223,8 @@ #include #include #include -#include +#include +#include #include /* 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); + diff --git a/drivers/i2c/i2c-algo-pcf.c b/drivers/i2c/i2c-algo-pcf.c index 8a4f50f449a8..cadd051b7350 100644 --- a/drivers/i2c/i2c-algo-pcf.c +++ b/drivers/i2c/i2c-algo-pcf.c @@ -24,7 +24,7 @@ Frodo Looijaard ,and also from Martin Bailey */ -/* $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 #include @@ -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. All SMBus-related things are written by Frodo Looijaard */ -/* $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 #include @@ -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: diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 0981a96c06f9..cf6afc575ce2 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -25,14 +25,24 @@ /* The I2C_RDWR ioctl code is written by Kolja Waschk */ -/* $Id: i2c-dev.c,v 1.32 2000/07/25 23:52:17 frodo Exp $ */ +/* The devfs code is contributed by Philipp Matthias Hahn + */ +/* $Id: i2c-dev.c,v 1.36 2000/09/22 02:19:35 mds Exp $ */ + +#include #include #include #include #include #include +#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) #include +#endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */ +#ifdef CONFIG_DEVFS_FS +#include +#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; diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in index 81092ded69a5..d63dd5981f47 100644 --- a/drivers/isdn/Config.in +++ b/drivers/isdn/Config.in @@ -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 diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile index 11ea08c2d55c..d1ab6cd7bf7f 100644 --- a/drivers/isdn/Makefile +++ b/drivers/isdn/Makefile @@ -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. diff --git a/drivers/isdn/act2000/Makefile b/drivers/isdn/act2000/Makefile index e8946317ae95..556c402b17cf 100644 --- a/drivers/isdn/act2000/Makefile +++ b/drivers/isdn/act2000/Makefile @@ -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 diff --git a/drivers/isdn/avmb1/Makefile b/drivers/isdn/avmb1/Makefile index d1f090d3d89d..36690928780b 100644 --- a/drivers/isdn/avmb1/Makefile +++ b/drivers/isdn/avmb1/Makefile @@ -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. diff --git a/drivers/isdn/divert/Makefile b/drivers/isdn/divert/Makefile index 88d09095a49b..dc1084cb6355 100644 --- a/drivers/isdn/divert/Makefile +++ b/drivers/isdn/divert/Makefile @@ -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 diff --git a/drivers/isdn/eicon/Makefile b/drivers/isdn/eicon/Makefile index cd9b2e3fb43c..35f59701d8d4 100644 --- a/drivers/isdn/eicon/Makefile +++ b/drivers/isdn/eicon/Makefile @@ -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 diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile index a7904f0c927b..66f6b5d4ad91 100644 --- a/drivers/isdn/hisax/Makefile +++ b/drivers/isdn/hisax/Makefile @@ -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 diff --git a/drivers/isdn/hysdn/Makefile b/drivers/isdn/hysdn/Makefile index 92d8bb988503..1f119beb70a9 100644 --- a/drivers/isdn/hysdn/Makefile +++ b/drivers/isdn/hysdn/Makefile @@ -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 diff --git a/drivers/isdn/icn/Makefile b/drivers/isdn/icn/Makefile index 9931761c9226..bd716cf0b87f 100644 --- a/drivers/isdn/icn/Makefile +++ b/drivers/isdn/icn/Makefile @@ -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. diff --git a/drivers/isdn/isdn_cards.c b/drivers/isdn/isdn_cards.c index 8c7636b4692d..268711139828 100644 --- a/drivers/isdn/isdn_cards.c +++ b/drivers/isdn/isdn_cards.c @@ -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 } diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c index eea88399bea2..615d11fc1d77 100644 --- a/drivers/isdn/isdn_common.c +++ b/drivers/isdn/isdn_common.c @@ -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 #endif CONFIG_ISDN_DIVERSION diff --git a/drivers/isdn/isdnloop/Makefile b/drivers/isdn/isdnloop/Makefile index 154363b762f2..312e9b96937b 100644 --- a/drivers/isdn/isdnloop/Makefile +++ b/drivers/isdn/isdnloop/Makefile @@ -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. diff --git a/drivers/isdn/pcbit/Makefile b/drivers/isdn/pcbit/Makefile index de125f2fee66..7a6a80447212 100644 --- a/drivers/isdn/pcbit/Makefile +++ b/drivers/isdn/pcbit/Makefile @@ -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 diff --git a/drivers/isdn/sc/Makefile b/drivers/isdn/sc/Makefile index 7c5998a87710..60ac3ce6d983 100644 --- a/drivers/isdn/sc/Makefile +++ b/drivers/isdn/sc/Makefile @@ -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 diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index b66edcc44b3f..b356808c1fd5 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -536,7 +536,6 @@ MODULE_AUTHOR ("Jeff Garzik "); 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); diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 5f765d5bf9ef..75539ecef360 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -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 #include #include +#include #include #include #include @@ -86,6 +87,8 @@ #include +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); diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 3a861650643d..976bb9ebd6a0 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -40,9 +40,7 @@ #include #include #include - -#include - +#include #include #include #include @@ -56,12 +54,7 @@ #include #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 "); -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 "); +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); + diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 6ca7e2cc157a..38957568b6e4 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -60,7 +60,7 @@ #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) /* prototypes for ax25_encapsulate and ax25_rebuild_header */ #include -#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */ +#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */ /* make genksyms happy */ #include @@ -81,33 +81,33 @@ /* --------------------------------------------------------------------- */ 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); + +/* --------------------------------------------------------------------- */ + diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index b6e99d212948..b527596fe281 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -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 */ diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 25636b008aad..4274c52cf14c 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -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(); diff --git a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c index 3b9b0e2271b7..8b91bb2bf11f 100644 --- a/drivers/scsi/pci2000.c +++ b/drivers/scsi/pci2000.c @@ -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) ) diff --git a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c index 6b767a1c8db4..2b6d3122d2f3 100644 --- a/drivers/scsi/pci2220i.c +++ b/drivers/scsi/pci2220i.c @@ -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); diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c index c479ccfc5bed..7035a4f06284 100644 --- a/drivers/scsi/sim710.c +++ b/drivers/scsi/sim710.c @@ -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; diff --git a/drivers/sound/cmpci.c b/drivers/sound/cmpci.c index 38ac2abf45a2..b9f345f8b4f8 100644 --- a/drivers/sound/cmpci.c +++ b/drivers/sound/cmpci.c @@ -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; diff --git a/drivers/sound/cs4281.c b/drivers/sound/cs4281.c index 661caa2144ab..13f1b6c92c18 100644 --- a/drivers/sound/cs4281.c +++ b/drivers/sound/cs4281.c @@ -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; diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c index 9da701604f99..885612f8ce5a 100644 --- a/drivers/sound/es1370.c +++ b/drivers/sound/es1370.c @@ -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; diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c index 6c525355011e..ae22d6cacc92 100644 --- a/drivers/sound/es1371.c +++ b/drivers/sound/es1371.c @@ -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; diff --git a/drivers/sound/esssolo1.c b/drivers/sound/esssolo1.c index c06c57633902..ac2b6d243699 100644 --- a/drivers/sound/esssolo1.c +++ b/drivers/sound/esssolo1.c @@ -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; diff --git a/drivers/sound/maestro.c b/drivers/sound/maestro.c index 7529c1db3dba..6bdb2ade8a37 100644 --- a/drivers/sound/maestro.c +++ b/drivers/sound/maestro.c @@ -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; diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c index 14f11dcafe18..c0f337a4cfb6 100644 --- a/drivers/sound/sonicvibes.c +++ b/drivers/sound/sonicvibes.c @@ -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; diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c index 9e32811acce8..db5f2b611bf6 100644 --- a/drivers/sound/trident.c +++ b/drivers/sound/trident.c @@ -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; diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index a3be533e600d..398e0a757e66 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c @@ -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; diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h index 1fb90b2be1ff..7d2f1db08738 100644 --- a/drivers/telephony/ixj.h +++ b/drivers/telephony/ixj.h @@ -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; diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 161122650231..b4ea3a1a9de9 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c @@ -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) diff --git a/fs/affs/file.c b/fs/affs/file.c index 341660c4b392..fac21f70ba55 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -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) { diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index b125dee4e855..78b7f147ebe7 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -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; diff --git a/fs/buffer.c b/fs/buffer.c index 61c3d457470a..8aa7b3f06e01 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -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); diff --git a/fs/coda/dir.c b/fs/coda/dir.c index e1ab9e89610b..7011582fe3d7 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -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); } diff --git a/fs/coda/file.c b/fs/coda/file.c index 0344c20728aa..94c54ecd98ea 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -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); diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 45acf28c6b62..3cf258a2359c 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -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; diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c index 2df6cf719f4b..018c4410b064 100644 --- a/fs/coda/symlink.c +++ b/fs/coda/symlink.c @@ -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; diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 51eff1caae27..3ce1b2e01453 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -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; diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c index d1c788cc29a3..b5d17f3cc954 100644 --- a/fs/efs/symlink.c +++ b/fs/efs/symlink.c @@ -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; diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 81448e71b798..e592850db53b 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -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", diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 658a0641605f..fd54c3040c97 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -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); } diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 4d2dfedbff66..7b88355f884a 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -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 diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 82f58826db5e..61ad8c2b2657 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -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) { diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 7414a4c297c9..32712550617f 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -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) { diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index a9675ef546f7..4c0306815887 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -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) { diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 0d38b408c9da..094767362712 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -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; diff --git a/fs/inode.c b/fs/inode.c index abbc04f1c58e..1d2b23b70dfe 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -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; } diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 4ac4bc0ced43..e20f3ad61c75 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -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); diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index f61005aaca61..94fd0797d148 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -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; diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index 739387ab9545..78e783974009 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c @@ -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); diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c index 022cbce783fb..52f095848c3c 100644 --- a/fs/ncpfs/symlink.c +++ b/fs/ncpfs/symlink.c @@ -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); diff --git a/fs/nfs/file.c b/fs/nfs/file.c index d5c92ba3be85..2b3f22777b0f 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -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<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; diff --git a/fs/nfs/read.c b/fs/nfs/read.c index e0f7313be780..211d3a3db0a3 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -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) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f75190be5d5e..8b9a28556905 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -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; diff --git a/fs/nls/Config.in b/fs/nls/Config.in index 5c9754acac52..8baecf971f02 100644 --- a/fs/nls/Config.in +++ b/fs/nls/Config.in @@ -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 diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c index cbcd5201650c..f54a7eb57a43 100644 --- a/fs/ntfs/fs.c +++ b/fs/ntfs/fs.c @@ -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) { diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 45a94520978d..c40f488e5704 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -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) { diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 36fa933a499b..6a096c0ff49e 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -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); diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 081209a487c2..76c811852d98 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -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; diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index 79627f880470..0a95735fddc3 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -161,7 +161,7 @@ smb_writepage(struct page *page) if (!mapping) BUG(); - inode = (struct inode *)mapping->host; + inode = mapping->host; if (!inode) BUG(); diff --git a/fs/udf/file.c b/fs/udf/file.c index 3895d769bf0d..9ab57d370ec8 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -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; diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index 547fc784b851..be4e80165eb0 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c @@ -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; diff --git a/include/linux/atm_tcp.h b/include/linux/atm_tcp.h index a79f45bc315c..18787f9b2f19 100644 --- a/include/linux/atm_tcp.h +++ b/include/linux/atm_tcp.h @@ -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; diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index d169bf7f22c9..ef8931cd7b5f 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h @@ -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; }; diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h index dd9fdcfaf910..63922d2c0d32 100644 --- a/include/linux/ext2_fs.h +++ b/include/linux/ext2_fs.h @@ -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 *); diff --git a/include/linux/ext2_fs_sb.h b/include/linux/ext2_fs_sb.h index 69b35b7f74e8..2e72dfbefd00 100644 --- a/include/linux/ext2_fs_sb.h +++ b/include/linux/ext2_fs_sb.h @@ -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 */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 8c72860bbd30..8032db992126 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -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 *); diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h index c90f838a4d14..cc89518003c5 100644 --- a/include/linux/generic_serial.h +++ b/include/linux/generic_serial.h @@ -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); diff --git a/include/linux/i2c-dev.h b/include/linux/i2c-dev.h index 39ed2adfa56e..4d9ef78e06e4 100644 --- a/include/linux/i2c-dev.h +++ b/include/linux/i2c-dev.h @@ -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 diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 9c123fa48a02..b5793e818105 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -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 @@ -71,6 +71,20 @@ #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 @@ -94,6 +108,11 @@ #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 */ @@ -128,6 +147,12 @@ #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 @@ -136,6 +161,7 @@ #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 diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 4043c0353a17..4a9eb86c883b 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -23,7 +23,7 @@ /* With some changes from Kyösti Mälkki and Frodo Looijaard */ -/* $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: diff --git a/include/linux/lvm.h b/include/linux/lvm.h index 2fe9bcdfcb3f..7b4ff94f9e53 100644 --- a/include/linux/lvm.h +++ b/include/linux/lvm.h @@ -66,6 +66,7 @@ #define _LVM_KERNEL_H_VERSION "LVM 0.9 (13/11/2000)" +#include #include #include diff --git a/include/linux/mm.h b/include/linux/mm.h index 017755ad8749..5b67b326d67b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -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 diff --git a/include/net/ax25.h b/include/net/ax25.h index 525786901fb4..0957d1aae683 100644 --- a/include/net/ax25.h +++ b/include/net/ax25.h @@ -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 diff --git a/ipc/shm.c b/ipc/shm.c index ca569f1d0b35..b1c0b96c267b 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -15,6 +15,7 @@ * */ +#include #include #include #include diff --git a/mm/filemap.c b/mm/filemap.c index 172300f04888..c9ab9a4e2fc5 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -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; diff --git a/mm/memory.c b/mm/memory.c index 13dad21a06ca..f4bb0141f050 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -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; } diff --git a/mm/shmem.c b/mm/shmem.c index 1980f635efed..a81a746593e8 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -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; } diff --git a/mm/swap_state.c b/mm/swap_state.c index cd7ab1623e67..2a5a55b7bd7d 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -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, }; diff --git a/mm/vmscan.c b/mm/vmscan.c index 9776b0b978a0..d4a74f41f8a9 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -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; } diff --git a/net/atm/addr.c b/net/atm/addr.c index 8bca9d1c32f6..1814a8b212cf 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c @@ -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); } diff --git a/net/atm/common.c b/net/atm/common.c index 16a6fb6b409c..ea0ad690a57a 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -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; } diff --git a/net/atm/lec.c b/net/atm/lec.c index d9921b408148..6b68d7995952 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -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; } diff --git a/net/atm/proc.c b/net/atm/proc.c index e8d3170bef0c..ef0091735aa7 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -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); diff --git a/net/atm/resources.c b/net/atm/resources.c index 9502367efa9c..910afff617a7 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -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; } diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 0b3d64941196..fab17e7c66e3 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -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); } diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 8e34e42e2040..b73b4e5f27b2 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -105,7 +105,6 @@ */ #include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -140,7 +139,7 @@ -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 "); 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 diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c index 1b0f9da67e11..f96c65586c04 100644 --- a/net/ax25/ax25_addr.c +++ b/net/ax25/ax25_addr.c @@ -19,8 +19,6 @@ * AX.25 036 Jonathan(G4KLX) Split from ax25_subr.c. */ -#include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -303,4 +301,3 @@ void ax25_digi_invert(ax25_digi *in, ax25_digi *out) } } -#endif diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c index 0436db90301e..efeec64e03ec 100644 --- a/net/ax25/ax25_dev.c +++ b/net/ax25/ax25_dev.c @@ -17,7 +17,6 @@ */ #include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -39,8 +38,9 @@ #include #include #include +#include -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 diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c index 3354206dfb97..6c65baea59af 100644 --- a/net/ax25/ax25_ds_in.c +++ b/net/ax25/ax25_ds_in.c @@ -22,8 +22,6 @@ * Joerg(DL1BKE) ax25->n2count never got reset */ -#include -#if defined(CONFIG_AX25_DAMA_SLAVE) #include #include #include @@ -312,4 +310,3 @@ int ax25_ds_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type) return queued; } -#endif diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c index 3a6f6c259476..e3e88d7710af 100644 --- a/net/ax25/ax25_ds_subr.c +++ b/net/ax25/ax25_ds_subr.c @@ -22,8 +22,6 @@ * AX.25 037 Jonathan(G4KLX) New timer architecture. */ -#include -#if defined(CONFIG_AX25_DAMA_SLAVE) #include #include #include @@ -217,4 +215,3 @@ void ax25_dama_off(ax25_cb *ax25) ax25_dev_dama_off(ax25->ax25_dev); } -#endif diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c index 06135e9de491..3c5b2ea9c32b 100644 --- a/net/ax25/ax25_ds_timer.c +++ b/net/ax25/ax25_ds_timer.c @@ -15,8 +15,6 @@ * AX.25 037 Jonathan(G4KLX) New timer architecture. */ -#include -#if defined(CONFIG_AX25_DAMA_SLAVE) #include #include #include @@ -224,5 +222,3 @@ void ax25_ds_t1_timeout(ax25_cb *ax25) ax25_calculate_t1(ax25); ax25_start_t1timer(ax25); } - -#endif diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c index 2e53ad95912d..15ca9c45304e 100644 --- a/net/ax25/ax25_iface.c +++ b/net/ax25/ax25_iface.c @@ -14,7 +14,6 @@ */ #include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -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 diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c index 6efbc57f2122..ed5e6fbcecc6 100644 --- a/net/ax25/ax25_in.c +++ b/net/ax25/ax25_in.c @@ -39,7 +39,6 @@ */ #include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -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 diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c index a298fb59d737..e6dcda83d93f 100644 --- a/net/ax25/ax25_ip.c +++ b/net/ax25/ax25_ip.c @@ -14,7 +14,6 @@ */ #include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -210,4 +209,3 @@ int ax25_rebuild_header(struct sk_buff *skb) #endif -#endif diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index e6b19f53be74..231c170e7a0b 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c @@ -35,7 +35,6 @@ */ #include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -408,4 +407,3 @@ int ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr) return 0; } -#endif diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index 32a7ab515712..254ff36fb669 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -41,8 +41,6 @@ * Arnaldo C. Melo s/suser/capable/ */ -#include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -64,8 +62,9 @@ #include #include #include +#include -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 diff --git a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c index 1e27580cf061..d1cfc3ff9573 100644 --- a/net/ax25/ax25_std_in.c +++ b/net/ax25/ax25_std_in.c @@ -37,8 +37,6 @@ * AX.25 037 Jonathan(G4KLX) New timer architecture. */ -#include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -467,5 +465,3 @@ int ax25_std_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type) return queued; } - -#endif diff --git a/net/ax25/ax25_std_subr.c b/net/ax25/ax25_std_subr.c index 1b1d1c8bb7e8..c868e0507952 100644 --- a/net/ax25/ax25_std_subr.c +++ b/net/ax25/ax25_std_subr.c @@ -20,8 +20,6 @@ * AX.25 037 Jonathan(G4KLX) New timer architecture. */ -#include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -102,5 +100,3 @@ void ax25_std_timeout_response(ax25_cb *ax25) ax25->condition &= ~AX25_COND_ACK_PENDING; } - -#endif diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c index 4e97c51b8566..5a2d8771c96b 100644 --- a/net/ax25/ax25_std_timer.c +++ b/net/ax25/ax25_std_timer.c @@ -22,8 +22,6 @@ * AX.25 037 Jonathan(G4KLX) New timer architecture. */ -#include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -170,5 +168,3 @@ void ax25_std_t1timer_expiry(ax25_cb *ax25) ax25_calculate_t1(ax25); ax25_start_t1timer(ax25); } - -#endif diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c index 97ef02d08ce7..66978964628a 100644 --- a/net/ax25/ax25_subr.c +++ b/net/ax25/ax25_subr.c @@ -33,8 +33,6 @@ * AX.25 037 Jonathan(G4KLX) New timer architecture. */ -#include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -324,5 +322,3 @@ void ax25_disconnect(ax25_cb *ax25, int reason) ax25->sk->dead = 1; } } - -#endif diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c index 08e1904569bf..01e7596f3d3a 100644 --- a/net/ax25/ax25_timer.c +++ b/net/ax25/ax25_timer.c @@ -26,7 +26,6 @@ */ #include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -255,5 +254,3 @@ static void ax25_idletimer_expiry(unsigned long param) #endif } } - -#endif diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index eb226b14cdf7..603d8b8cc864 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c @@ -13,8 +13,6 @@ * AX.25 036 Jonathan(G4KLX) Split from af_ax25.c. */ -#include -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include #include #include @@ -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 diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index f0e9bb5bb3d6..b7af2b9f6997 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -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; diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index a0c139b3a436..a4b89d294b90 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -34,7 +34,6 @@ */ #include -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #include #include #include @@ -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 "); 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 diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 1625d1c90132..d5a472703d92 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -19,7 +19,6 @@ */ #include -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #define __NO_VERSION__ #include #include @@ -236,5 +235,3 @@ int nr_init(struct net_device *dev) return 0; }; - -#endif diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c index fadf69de8c25..29762e929e93 100644 --- a/net/netrom/nr_in.c +++ b/net/netrom/nr_in.c @@ -24,8 +24,6 @@ * NET/ROM 007 Jonathan(G4KLX) New timer architecture. */ -#include -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #include #include #include @@ -304,5 +302,3 @@ int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb) return queued; } - -#endif diff --git a/net/netrom/nr_loopback.c b/net/netrom/nr_loopback.c index fc0665de289f..5290ae024957 100644 --- a/net/netrom/nr_loopback.c +++ b/net/netrom/nr_loopback.c @@ -15,14 +15,13 @@ * */ -#include -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #include #include #include #include #include #include +#include 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 diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c index 93da60adb7ab..0900689883b1 100644 --- a/net/netrom/nr_out.c +++ b/net/netrom/nr_out.c @@ -16,8 +16,6 @@ * NET/ROM 007 Jonathan(G4KLX) New timer architecture. */ -#include -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #include #include #include @@ -272,5 +270,3 @@ void nr_check_iframes_acked(struct sock *sk, unsigned short nr) } } } - -#endif diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index 308e73af26da..ec0578b51316 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c @@ -21,8 +21,6 @@ * Tomi(OH2BNS) Routing quality and link failure changes. */ -#include -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #include #include #include @@ -48,12 +46,13 @@ #include #include #include +#include #include 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 diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c index 096ca3a8f582..fee0478fa170 100644 --- a/net/netrom/nr_subr.c +++ b/net/netrom/nr_subr.c @@ -15,8 +15,6 @@ * NET/ROM 007 Jonathan(G4KLX) New timer architecture. */ -#include -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #include #include #include @@ -297,5 +295,3 @@ void nr_disconnect(struct sock *sk, int reason) sk->dead = 1; } - -#endif diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c index ac62ad54a2e9..116770434ab5 100644 --- a/net/netrom/nr_timer.c +++ b/net/netrom/nr_timer.c @@ -15,8 +15,6 @@ * Implemented idle timer. */ -#include -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #include #include #include @@ -245,5 +243,3 @@ static void nr_t1timer_expiry(unsigned long param) nr_start_t1timer(sk); } - -#endif diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index f639e578abd0..a92bf86f5977 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -25,7 +25,6 @@ */ #include -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include #include #include @@ -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 diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 88f2d55e7e77..92ad1e55ad74 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -15,7 +15,6 @@ */ #include -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #define __NO_VERSION__ #include #include @@ -205,5 +204,3 @@ int rose_init(struct net_device *dev) return 0; }; - -#endif diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c index be86c9e16725..38fb76c1b5ef 100644 --- a/net/rose/rose_in.c +++ b/net/rose/rose_in.c @@ -22,8 +22,6 @@ * Removed M bit processing. */ -#include -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include #include #include @@ -303,5 +301,3 @@ int rose_process_rx_frame(struct sock *sk, struct sk_buff *skb) return queued; } - -#endif diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index d9b5a4a1dd91..2c793e4e6b5e 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c @@ -14,8 +14,6 @@ * ROSE 003 Jonathan(G4KLX) New timer architecture. */ -#include -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include #include #include @@ -322,5 +320,3 @@ void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh) } } } - -#endif diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index 2136fd601c2e..ad00608a3911 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c @@ -14,14 +14,13 @@ * */ -#include -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include #include #include #include #include #include +#include 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 diff --git a/net/rose/rose_out.c b/net/rose/rose_out.c index aea1d9f68efa..8f9855df7eaa 100644 --- a/net/rose/rose_out.c +++ b/net/rose/rose_out.c @@ -15,8 +15,6 @@ * Removed M bit processing. */ -#include -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include #include #include @@ -130,5 +128,3 @@ void rose_enquiry_response(struct sock *sk) rose_stop_timer(sk); } - -#endif diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index d5d4de9ec1b0..1bedfdf0d3b4 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -19,8 +19,6 @@ * Added use count to neighbours. */ -#include -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include #include #include @@ -47,15 +45,16 @@ #include #include #include +#include #include 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 diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index dc172ac3be4e..384347a0e94b 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c @@ -15,8 +15,6 @@ * ROSE 003 Jonathan(G4KLX) Added use count to neighbours. */ -#include -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include #include #include @@ -528,5 +526,3 @@ void rose_disconnect(struct sock *sk, int reason, int cause, int diagnostic) sk->dead = 1; } - -#endif diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c index 718a64ec04d2..8bd30424d990 100644 --- a/net/rose/rose_timer.c +++ b/net/rose/rose_timer.c @@ -15,8 +15,6 @@ * Implemented idle timer. */ -#include -#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE) #include #include #include @@ -207,5 +205,3 @@ static void rose_idletimer_expiry(unsigned long param) sk->dead = 1; } - -#endif diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 77dba8e220c6..4f8fb25becc4 100644 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -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"; } -- 2.39.5