summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <greg@kroah.com>2003-05-07 11:10:22 -0700
committerGreg Kroah-Hartman <greg@kroah.com>2003-05-07 11:10:22 -0700
commit2f2a2dd085f6abd2a875401a99523a172108f496 (patch)
treeef751436a2ce57daf48d4ae8cf44126ba0f66cab
parent29abb650987802c94d7464d0af20ec5d9f641284 (diff)
parentc495aaaf4d5dddc7e626e7e305bb7dac5e166b29 (diff)
Merge gregkh@kernel.bkbits.net:/home/gregkh/linux/linus-2.5
into kroah.com:/home/linux/linux/BK/gregkh-2.5
-rw-r--r--CREDITS4
-rw-r--r--Documentation/Changes2
-rw-r--r--MAINTAINERS4
-rw-r--r--Makefile15
-rw-r--r--arch/i386/Kconfig27
-rw-r--r--arch/i386/Makefile5
-rw-r--r--arch/i386/kernel/io_apic.c8
-rw-r--r--arch/i386/kernel/mpparse.c2
-rw-r--r--arch/i386/kernel/setup.c9
-rw-r--r--arch/i386/kernel/smp.c6
-rw-r--r--arch/i386/kernel/timers/Makefile2
-rw-r--r--arch/i386/kernel/timers/timer.c4
-rw-r--r--arch/i386/lib/usercopy.c50
-rw-r--r--arch/i386/mach-generic/Makefile18
-rw-r--r--arch/i386/mach-generic/bigsmp.c23
-rw-r--r--arch/i386/mach-generic/default.c22
-rw-r--r--arch/i386/mach-generic/probe.c96
-rw-r--r--arch/i386/mach-generic/summit.c22
-rw-r--r--arch/i386/mm/fault.c89
-rw-r--r--arch/i386/vmlinux.lds.S8
-rw-r--r--arch/mips/au1000/common/serial.c8
-rw-r--r--arch/sparc64/solaris/socksys.c7
-rw-r--r--arch/um/drivers/mmapper_kern.c4
-rw-r--r--drivers/atm/Kconfig14
-rw-r--r--drivers/atm/Makefile4
-rw-r--r--drivers/atm/he.c3419
-rw-r--r--drivers/atm/he.h935
-rw-r--r--drivers/block/acsi_slm.c7
-rw-r--r--drivers/block/paride/pg.c7
-rw-r--r--drivers/block/paride/pt.c15
-rw-r--r--drivers/char/amiserial.c7
-rw-r--r--drivers/char/cyclades.c8
-rw-r--r--drivers/char/drm/drm_drv.h2
-rw-r--r--drivers/char/drm/radeon_cp.c4
-rw-r--r--drivers/char/dsp56k.c7
-rw-r--r--drivers/char/dtlk.c7
-rw-r--r--drivers/char/dz.c5
-rw-r--r--drivers/char/esp.c9
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c38
-rw-r--r--drivers/char/hvc_console.c3
-rw-r--r--drivers/char/ip2main.c27
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c21
-rw-r--r--drivers/char/isicom.c8
-rw-r--r--drivers/char/istallion.c17
-rw-r--r--drivers/char/keyboard.c4
-rw-r--r--drivers/char/lp.c9
-rw-r--r--drivers/char/mem.c42
-rw-r--r--drivers/char/misc.c4
-rw-r--r--drivers/char/moxa.c12
-rw-r--r--drivers/char/mwave/mwavedd.h2
-rw-r--r--drivers/char/mxser.c19
-rw-r--r--drivers/char/pcxx.c6
-rw-r--r--drivers/char/ppdev.c6
-rw-r--r--drivers/char/random.c2
-rw-r--r--drivers/char/raw.c4
-rw-r--r--drivers/char/rio/rio_linux.c26
-rw-r--r--drivers/char/rio/rio_linux.h3
-rw-r--r--drivers/char/rio/riotty.c5
-rw-r--r--drivers/char/riscom8.c8
-rw-r--r--drivers/char/rocket.c10
-rw-r--r--drivers/char/ser_a2232.c7
-rw-r--r--drivers/char/serial167.c1
-rw-r--r--drivers/char/serial_tx3912.c35
-rw-r--r--drivers/char/sh-sci.c22
-rw-r--r--drivers/char/specialix.c8
-rw-r--r--drivers/char/stallion.c38
-rw-r--r--drivers/char/sysrq.c122
-rw-r--r--drivers/char/tipar.c12
-rw-r--r--drivers/char/tpqic02.c53
-rw-r--r--drivers/char/tty_io.c161
-rw-r--r--drivers/char/vc_screen.c47
-rw-r--r--drivers/char/vme_scc.c7
-rw-r--r--drivers/char/vt.c31
-rw-r--r--drivers/i2c/i2c-dev.c9
-rw-r--r--drivers/ide/ide-tape.c2
-rw-r--r--drivers/ieee1394/amdtp.c7
-rw-r--r--drivers/ieee1394/dv1394.c40
-rw-r--r--drivers/ieee1394/raw1394.c5
-rw-r--r--drivers/ieee1394/video1394.c11
-rw-r--r--drivers/input/evdev.c5
-rw-r--r--drivers/input/input.c12
-rw-r--r--drivers/input/joydev.c4
-rw-r--r--drivers/input/mousedev.c9
-rw-r--r--drivers/input/serio/i8042.c21
-rw-r--r--drivers/input/tsdev.c6
-rw-r--r--drivers/isdn/capi/capi.c14
-rw-r--r--drivers/isdn/hardware/eicon/divamnt.c4
-rw-r--r--drivers/isdn/hardware/eicon/divasi.c4
-rw-r--r--drivers/isdn/hardware/eicon/divasmain.c3
-rw-r--r--drivers/isdn/i4l/isdn_common.c79
-rw-r--r--drivers/macintosh/adb.c6
-rw-r--r--drivers/macintosh/macserial.c7
-rw-r--r--drivers/md/md.c29
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c19
-rw-r--r--drivers/media/video/cpia.c4
-rw-r--r--drivers/media/video/videodev.c4
-rw-r--r--drivers/mtd/mtdchar.c18
-rw-r--r--drivers/net/pcmcia/3c589_cs.c15
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c7
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c2
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c13
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c16
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c10
-rw-r--r--drivers/net/ppp_generic.c11
-rw-r--r--drivers/net/wan/cosa.c9
-rw-r--r--drivers/s390/char/tuball.c9
-rw-r--r--drivers/s390/char/tubfs.c29
-rw-r--r--drivers/s390/char/tubio.h4
-rw-r--r--drivers/s390/char/tubtty.c2
-rw-r--r--drivers/sbus/char/bpp.c7
-rw-r--r--drivers/sbus/char/vfc_dev.c10
-rw-r--r--drivers/scsi/osst.c21
-rw-r--r--drivers/scsi/sg.c7
-rw-r--r--drivers/scsi/st.c15
-rw-r--r--drivers/serial/core.c2
-rw-r--r--drivers/sgi/char/sgiserial.c1
-rw-r--r--drivers/sgi/char/shmiq.c5
-rw-r--r--drivers/tc/zs.c5
-rw-r--r--drivers/usb/class/bluetty.c2
-rw-r--r--drivers/usb/class/cdc-acm.c2
-rw-r--r--drivers/usb/core/file.c3
-rw-r--r--drivers/usb/misc/tiglusb.c14
-rw-r--r--drivers/usb/serial/bus.c17
-rw-r--r--drivers/video/fbmem.c8
-rw-r--r--fs/Kconfig24
-rw-r--r--fs/bfs/dir.c2
-rw-r--r--fs/buffer.c16
-rw-r--r--fs/coda/psdev.c10
-rw-r--r--fs/dcache.c5
-rw-r--r--fs/devfs/base.c46
-rw-r--r--fs/ext2/Makefile4
-rw-r--r--fs/ext2/dir.c2
-rw-r--r--fs/ext2/xattr.c21
-rw-r--r--fs/ext2/xattr.h2
-rw-r--r--fs/ext2/xattr_security.c54
-rw-r--r--fs/ext3/Makefile4
-rw-r--r--fs/ext3/dir.c4
-rw-r--r--fs/ext3/fsync.c2
-rw-r--r--fs/ext3/xattr.c21
-rw-r--r--fs/ext3/xattr.h2
-rw-r--r--fs/ext3/xattr_security.c55
-rw-r--r--fs/file_table.c30
-rw-r--r--fs/hugetlbfs/inode.c2
-rw-r--r--fs/minix/dir.c2
-rw-r--r--fs/namei.c4
-rw-r--r--fs/namespace.c5
-rw-r--r--fs/nfs/inode.c2
-rw-r--r--fs/nfsd/vfs.c2
-rw-r--r--fs/ntfs/inode.c2
-rw-r--r--fs/partitions/check.c63
-rw-r--r--fs/pipe.c2
-rw-r--r--fs/qnx4/dir.c2
-rw-r--r--fs/read_write.c49
-rw-r--r--fs/reiserfs/dir.c2
-rw-r--r--fs/select.c76
-rw-r--r--fs/stat.c2
-rw-r--r--fs/super.c49
-rw-r--r--fs/sysv/dir.c2
-rw-r--r--fs/udf/dir.c2
-rw-r--r--fs/ufs/dir.c2
-rw-r--r--fs/xattr.c7
-rw-r--r--include/asm-i386/apicdef.h7
-rw-r--r--include/asm-i386/edd.h2
-rw-r--r--include/asm-i386/fixmap.h2
-rw-r--r--include/asm-i386/genapic.h106
-rw-r--r--include/asm-i386/kmap_types.h2
-rw-r--r--include/asm-i386/mach-bigsmp/mach_apic.h27
-rw-r--r--include/asm-i386/mach-bigsmp/mach_ipi.h2
-rw-r--r--include/asm-i386/mach-default/mach_apic.h37
-rw-r--r--include/asm-i386/mach-default/mach_ipi.h4
-rw-r--r--include/asm-i386/mach-default/mach_mpparse.h6
-rw-r--r--include/asm-i386/mach-generic/mach_apic.h30
-rw-r--r--include/asm-i386/mach-generic/mach_ipi.h10
-rw-r--r--include/asm-i386/mach-generic/mach_mpparse.h12
-rw-r--r--include/asm-i386/mach-numaq/mach_apic.h12
-rw-r--r--include/asm-i386/mach-summit/mach_apic.h41
-rw-r--r--include/asm-i386/mach-summit/mach_ipi.h2
-rw-r--r--include/asm-i386/mach-summit/mach_mpparse.h12
-rw-r--r--include/asm-i386/mmzone.h2
-rw-r--r--include/asm-i386/mpspec.h2
-rw-r--r--include/asm-i386/numnodes.h2
-rw-r--r--include/asm-i386/processor.h2
-rw-r--r--include/asm-i386/smp.h8
-rw-r--r--include/asm-i386/uaccess.h30
-rw-r--r--include/asm-i386/unistd.h2
-rw-r--r--include/linux/atm_he.h20
-rw-r--r--include/linux/atmbr2684.h101
-rw-r--r--include/linux/atmdev.h7
-rw-r--r--include/linux/blkpg.h6
-rw-r--r--include/linux/devfs_fs_kernel.h6
-rw-r--r--include/linux/file.h8
-rw-r--r--include/linux/fs.h6
-rw-r--r--include/linux/input.h3
-rw-r--r--include/linux/major.h1
-rw-r--r--include/linux/raid/md.h15
-rw-r--r--include/linux/rtnetlink.h12
-rw-r--r--include/linux/sched.h5
-rw-r--r--include/linux/security.h15
-rw-r--r--include/linux/slab.h1
-rw-r--r--include/linux/sunrpc/svc.h6
-rw-r--r--include/linux/swap.h8
-rw-r--r--include/linux/sysrq.h18
-rw-r--r--include/linux/tty.h3
-rw-r--r--init/main.c3
-rw-r--r--ipc/shm.c2
-rw-r--r--kernel/ksyms.c2
-rw-r--r--kernel/panic.c5
-rw-r--r--lib/inflate.c44
-rw-r--r--mm/filemap.c6
-rw-r--r--mm/page-writeback.c2
-rw-r--r--mm/page_alloc.c6
-rw-r--r--mm/shmem.c4
-rw-r--r--mm/slab.c115
-rw-r--r--mm/swapfile.c45
-rw-r--r--mm/vmalloc.c3
-rw-r--r--mm/vmscan.c37
-rw-r--r--net/Kconfig17
-rw-r--r--net/atm/Makefile1
-rw-r--r--net/atm/br2684.c803
-rw-r--r--net/atm/clip.c5
-rw-r--r--net/atm/common.c17
-rw-r--r--net/atm/lec.c2
-rw-r--r--net/atm/signaling.c6
-rw-r--r--net/atm/svc.c8
-rw-r--r--net/bridge/br_input.c3
-rw-r--r--net/core/skbuff.c3
-rw-r--r--net/ipv4/af_inet.c1
-rw-r--r--net/ipv4/fib_frontend.c4
-rw-r--r--net/ipv4/fib_semantics.c6
-rw-r--r--net/ipv4/tcp_minisocks.c2
-rw-r--r--net/ipv6/af_inet6.c1
-rw-r--r--net/ipv6/ip6_fib.c10
-rw-r--r--net/ipv6/route.c38
-rw-r--r--net/netlink/netlink_dev.c22
-rw-r--r--net/socket.c12
-rw-r--r--net/unix/af_unix.c4
-rw-r--r--scripts/Makefile.build21
-rw-r--r--security/dummy.c6
-rw-r--r--sound/core/info.c12
-rw-r--r--sound/core/sound.c19
-rw-r--r--sound/oss/opl3sa2.c12
-rw-r--r--sound/oss/soundcard.c20
-rw-r--r--sound/sound_core.c4
243 files changed, 7234 insertions, 1556 deletions
diff --git a/CREDITS b/CREDITS
index b4cb37af1077..01d119a12322 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3027,8 +3027,8 @@ E: torvalds@transmeta.com
W: http://www.cs.helsinki.fi/Linus.Torvalds
P: 1024/A86B35C5 96 54 50 29 EC 11 44 7A BE 67 3C 24 03 13 62 C8
D: Original kernel hacker
-S: 1050 Woodduck Avenue
-S: Santa Clara, California 95051
+S: 3990 Freedom Circle
+S: Santa Clara, California 95054
S: USA
N: Marcelo W. Tosatti
diff --git a/Documentation/Changes b/Documentation/Changes
index af797256a231..d62f1be5365e 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -50,7 +50,7 @@ with pcmcia-cs.
o Gnu C 2.95.3 # gcc --version
o Gnu make 3.78 # make --version
-o binutils 2.9.5.0.25 # ld -v
+o binutils 2.12 # ld -v
o util-linux 2.10o # fdformat --version
o module-init-tools 0.9.9 # depmod -V
o e2fsprogs 1.29 # tune2fs
diff --git a/MAINTAINERS b/MAINTAINERS
index b1c4cffac43a..ffc7f122aadc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -679,7 +679,7 @@ S: Maintained
EXT3 FILE SYSTEM
P: Stephen Tweedie, Andrew Morton
-M: sct@redhat.com, akpm@zip.com.au, adilger@clusterfs.com
+M: sct@redhat.com, akpm@digeo.com, adilger@clusterfs.com
L: ext3-users@redhat.com
S: Maintained
@@ -1257,7 +1257,7 @@ S: Maintained
NETWORK DEVICE DRIVERS
P: Andrew Morton
-M: akpm@zip.com.au
+M: akpm@digeo.com
P: Jeff Garzik
M: jgarzik@pobox.com
L: linux-net@vger.kernel.org
diff --git a/Makefile b/Makefile
index a96e715ce2a8..dd6caeb1a57d 100644
--- a/Makefile
+++ b/Makefile
@@ -90,7 +90,7 @@ ifneq ($(filter all,$(MAKECMDGOALS)),)
KBUILD_MODULES := 1
endif
-export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE
+export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE KBUILD_CHECKSRC
# Beautify output
# ---------------------------------------------------------------------------
@@ -118,6 +118,16 @@ ifndef KBUILD_VERBOSE
KBUILD_VERBOSE = 1
endif
+ifdef C
+ ifeq ("$(origin C)", "command line")
+ KBUILD_CHECKSRC = $(C)
+ endif
+endif
+ifndef KBUILD_CHECKSRC
+ KBUILD_CHECKSRC = 0
+endif
+
+
MAKEFLAGS += --no-print-directory
# For maximum performance (+ possibly random breakage, uncomment
@@ -172,6 +182,7 @@ GENKSYMS = scripts/genksyms/genksyms
DEPMOD = /sbin/depmod
KALLSYMS = scripts/kallsyms
PERL = perl
+CHECK = /home/torvalds/parser/check
MODFLAGS = -DMODULE
CFLAGS_MODULE = $(MODFLAGS)
AFLAGS_MODULE = $(MODFLAGS)
@@ -189,7 +200,7 @@ AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \
CONFIG_SHELL TOPDIR HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
- HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE
+ HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE CHECK
export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS
export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index e8db108b8194..d4e84e5c7f1b 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -65,19 +65,16 @@ config X86_NUMAQ
config X86_SUMMIT
bool "Summit/EXA (IBM x440)"
+ depends on SMP
help
This option is needed for IBM systems that use the Summit/EXA chipset.
In particular, it is needed for the x440.
If you don't have one of these computers, you should say N here.
-config ACPI_SRAT
- bool
- default y
- depends on NUMA && X86_SUMMIT
-
config X86_BIGSMP
bool "Support for other sub-arch SMP systems with more than 8 CPUs"
+ depends on SMP
help
This option is needed for the systems that have more than 8 CPUs
and if the system is not of any sub-arch type above.
@@ -95,8 +92,24 @@ config X86_VISWS
A kernel compiled for the Visual Workstation will not run on PCs
and vice versa. See <file:Documentation/sgi-visws.txt> for details.
+config X86_GENERICARCH
+ bool "Generic architecture (Summit, bigsmp, default)"
+ depends on SMP
+ help
+ This option compiles in the Summit, bigsmp, default subarchitectures.
+ It is intended for a generic binary kernel.
+
endchoice
+config ACPI_SRAT
+ bool
+ default y
+ depends on NUMA && (X86_SUMMIT || X86_GENERICARCH)
+
+config X86_CYCLONE_TIMER
+ bool
+ default y
+ depends on X86_SUMMIT || X86_GENERICARCH
choice
prompt "Processor family"
@@ -666,7 +679,7 @@ config X86_PAE
# Common NUMA Features
config NUMA
bool "Numa Memory Allocation Support"
- depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))
+ depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))
default n if X86_PC
default y if (X86_NUMAQ || X86_SUMMIT)
@@ -764,7 +777,7 @@ config HAVE_DEC_LOCK
# Summit needs it only when NUMA is on
config BOOT_IOREMAP
bool
- depends on (X86_SUMMIT && NUMA)
+ depends on ((X86_SUMMIT || X86_GENERICARCH) && NUMA)
default y
endmenu
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 341eca790a6b..3470efa154e9 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -73,6 +73,11 @@ mcore-$(CONFIG_X86_BIGSMP) := mach-default
mflags-$(CONFIG_X86_SUMMIT) := -Iinclude/asm-i386/mach-summit
mcore-$(CONFIG_X86_SUMMIT) := mach-default
+# generic subarchitecture
+mflags-$(CONFIG_X86_GENERICARCH) := -Iinclude/asm-i386/mach-generic
+mcore-$(CONFIG_X86_GENERICARCH) := mach-default
+core-$(CONFIG_X86_GENERICARCH) += arch/i386/mach-generic/
+
# default subarch .h files
mflags-y += -Iinclude/asm-i386/mach-default
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index ebf2aba5e1d5..d6729a396b63 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -280,7 +280,9 @@ static void set_ioapic_affinity (unsigned int irq, unsigned long mask)
extern unsigned long irq_affinity[NR_IRQS];
static int __cacheline_aligned pending_irq_balance_apicid[NR_IRQS];
-static int irqbalance_disabled = NO_BALANCE_IRQ;
+
+#define IRQBALANCE_CHECK_ARCH -999
+static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
static int physical_balance = 0;
struct irq_cpu_info {
@@ -342,8 +344,10 @@ static inline void balance_irq(int cpu, int irq)
unsigned long allowed_mask;
unsigned int new_cpu;
- if (irqbalance_disabled)
+ if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH && NO_BALANCE_IRQ)
return;
+ else if (irqbalance_disabled)
+ return;
allowed_mask = cpu_online_map & irq_affinity[irq];
new_cpu = move(cpu, allowed_mask, now, 1);
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 13d4cf6109c3..767051a4ca8c 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -73,7 +73,9 @@ static unsigned int __initdata num_processors;
/* Bitmask of physically existing CPUs */
unsigned long phys_cpu_present_map;
+#ifndef CONFIG_X86_GENERICARCH
int x86_summit = 0;
+#endif
u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
/*
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 26efeeb167c2..da559474baf2 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -91,6 +91,7 @@ unsigned char aux_device_present;
extern void early_cpu_init(void);
extern void dmi_scan_machine(void);
+extern void generic_apic_probe(char *);
extern int root_mountflags;
extern char _text, _etext, _edata, _end;
extern int blk_nohighio;
@@ -959,6 +960,13 @@ void __init setup_arch(char **cmdline_p)
smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
#endif
paging_init();
+
+ dmi_scan_machine();
+
+#ifdef CONFIG_X86_GENERICARCH
+ generic_apic_probe(*cmdline_p);
+#endif
+
#ifdef CONFIG_ACPI_BOOT
/*
* Parse the ACPI tables for possible boot-time SMP configuration.
@@ -980,7 +988,6 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &dummy_con;
#endif
#endif
- dmi_scan_machine();
}
static int __init highio_setup(char *str)
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index a7e159e6ba49..335a0404ee3c 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -123,7 +123,7 @@ static inline int __prepare_ICR2 (unsigned int mask)
return SET_APIC_DEST_FIELD(mask);
}
-static inline void __send_IPI_shortcut(unsigned int shortcut, int vector)
+inline void __send_IPI_shortcut(unsigned int shortcut, int vector)
{
/*
* Subtle. In the case of the 'never do double writes' workaround
@@ -155,7 +155,7 @@ void send_IPI_self(int vector)
__send_IPI_shortcut(APIC_DEST_SELF, vector);
}
-static inline void send_IPI_mask_bitmask(int mask, int vector)
+inline void send_IPI_mask_bitmask(int mask, int vector)
{
unsigned long cfg;
unsigned long flags;
@@ -186,7 +186,7 @@ static inline void send_IPI_mask_bitmask(int mask, int vector)
local_irq_restore(flags);
}
-static inline void send_IPI_mask_sequence(int mask, int vector)
+inline void send_IPI_mask_sequence(int mask, int vector)
{
unsigned long cfg, flags;
unsigned int query_cpu, query_mask;
diff --git a/arch/i386/kernel/timers/Makefile b/arch/i386/kernel/timers/Makefile
index fcffc11ff90a..60e0a271ecfb 100644
--- a/arch/i386/kernel/timers/Makefile
+++ b/arch/i386/kernel/timers/Makefile
@@ -4,4 +4,4 @@
obj-y := timer.o timer_none.o timer_tsc.o timer_pit.o
-obj-$(CONFIG_X86_SUMMIT) += timer_cyclone.o
+obj-$(CONFIG_X86_CYCLONE_TIMER) += timer_cyclone.o
diff --git a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c
index fc23421ead74..6eac9cc9097f 100644
--- a/arch/i386/kernel/timers/timer.c
+++ b/arch/i386/kernel/timers/timer.c
@@ -6,12 +6,12 @@
/* list of externed timers */
extern struct timer_opts timer_pit;
extern struct timer_opts timer_tsc;
-#ifdef CONFIG_X86_SUMMIT
+#ifdef CONFIG_X86_CYCLONE_TIMER
extern struct timer_opts timer_cyclone;
#endif
/* list of timers, ordered by preference, NULL terminated */
static struct timer_opts* timers[] = {
-#ifdef CONFIG_X86_SUMMIT
+#ifdef CONFIG_X86_CYCLONE_TIMER
&timer_cyclone,
#endif
&timer_tsc,
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
index 452e53c2c91d..fd1237b79a59 100644
--- a/arch/i386/lib/usercopy.c
+++ b/arch/i386/lib/usercopy.c
@@ -6,6 +6,9 @@
* Copyright 1997 Linus Torvalds
*/
#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/blkdev.h>
#include <asm/uaccess.h>
#include <asm/mmx.h>
@@ -483,6 +486,53 @@ do { \
unsigned long __copy_to_user_ll(void *to, const void *from, unsigned long n)
{
+#ifndef CONFIG_X86_WP_WORKS_OK
+ if (unlikely(boot_cpu_data.wp_works_ok == 0) &&
+ ((unsigned long )to) < TASK_SIZE) {
+ /*
+ * CPU does not honor the WP bit when writing
+ * from supervisory mode, and due to preemption or SMP,
+ * the page tables can change at any time.
+ * Do it manually. Manfred <manfred@colorfullife.com>
+ */
+ while (n) {
+ unsigned long offset = ((unsigned long)to)%PAGE_SIZE;
+ unsigned long len = PAGE_SIZE - offset;
+ int retval;
+ struct page *pg;
+ void *maddr;
+
+ if (len > n)
+ len = n;
+
+survive:
+ down_read(&current->mm->mmap_sem);
+ retval = get_user_pages(current, current->mm,
+ (unsigned long )to, 1, 1, 0, &pg, NULL);
+
+ if (retval == -ENOMEM && current->pid == 1) {
+ up_read(&current->mm->mmap_sem);
+ blk_congestion_wait(WRITE, HZ/50);
+ goto survive;
+ }
+
+ if (retval != 1)
+ break;
+
+ maddr = kmap_atomic(pg, KM_USER0);
+ memcpy(maddr + offset, from, len);
+ kunmap_atomic(maddr, KM_USER0);
+ set_page_dirty_lock(pg);
+ put_page(pg);
+ up_read(&current->mm->mmap_sem);
+
+ from += len;
+ to += len;
+ n -= len;
+ }
+ return n;
+ }
+#endif
if (movsl_is_ok(to, from, n))
__copy_user(to, from, n);
else
diff --git a/arch/i386/mach-generic/Makefile b/arch/i386/mach-generic/Makefile
new file mode 100644
index 000000000000..07bfdcbd9081
--- /dev/null
+++ b/arch/i386/mach-generic/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the generic architecture
+#
+
+EXTRA_CFLAGS += -I../kernel
+
+obj-y := probe.o summit.o bigsmp.o default.o
+
+
+#
+# Makefile for the generic architecture
+#
+
+EXTRA_CFLAGS += -I../kernel
+
+obj-y := probe.o summit.o bigsmp.o default.o
+
+
diff --git a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c
new file mode 100644
index 000000000000..13951aa60c18
--- /dev/null
+++ b/arch/i386/mach-generic/bigsmp.c
@@ -0,0 +1,23 @@
+/*
+ * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs.
+ * Drives the local APIC in "clustered mode".
+ */
+#define APIC_DEFINITION 1
+#include <asm/genapic.h>
+#include <asm/fixmap.h>
+#include <asm/apicdef.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <asm/mach-bigsmp/mach_apic.h>
+#include <asm/mach-bigsmp/mach_ipi.h>
+#include <asm/mach-default/mach_mpparse.h>
+
+int dmi_bigsmp; /* can be set by dmi scanners */
+
+static __init int probe_bigsmp(void)
+{
+ return dmi_bigsmp;
+}
+
+struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp);
diff --git a/arch/i386/mach-generic/default.c b/arch/i386/mach-generic/default.c
new file mode 100644
index 000000000000..01093057f8d2
--- /dev/null
+++ b/arch/i386/mach-generic/default.c
@@ -0,0 +1,22 @@
+/*
+ * Default generic APIC driver. This handles upto 8 CPUs.
+ */
+#define APIC_DEFINITION 1
+#include <asm/genapic.h>
+#include <asm/fixmap.h>
+#include <asm/apicdef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <asm/mach-default/mach_apic.h>
+#include <asm/mach-default/mach_ipi.h>
+#include <asm/mach-default/mach_mpparse.h>
+
+/* should be called last. */
+static __init int probe_default(void)
+{
+ return 1;
+}
+
+struct genapic apic_default = APIC_INIT("default", probe_default);
diff --git a/arch/i386/mach-generic/probe.c b/arch/i386/mach-generic/probe.c
new file mode 100644
index 000000000000..10db5efccce6
--- /dev/null
+++ b/arch/i386/mach-generic/probe.c
@@ -0,0 +1,96 @@
+/* Copyright 2003 Andi Kleen, SuSE Labs.
+ * Subject to the GNU Public License, v.2
+ *
+ * Generic x86 APIC driver probe layer.
+ */
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <asm/fixmap.h>
+#include <asm/apicdef.h>
+#include <asm/genapic.h>
+
+extern struct genapic apic_summit;
+extern struct genapic apic_bigsmp;
+extern struct genapic apic_default;
+
+struct genapic *genapic = &apic_default;
+
+struct genapic *apic_probe[] __initdata = {
+ &apic_summit,
+ &apic_bigsmp,
+ &apic_default, /* must be last */
+ NULL,
+};
+
+void __init generic_apic_probe(char *command_line)
+{
+ char *s;
+ int i;
+ int changed = 0;
+
+ s = strstr(command_line, "apic=");
+ if (s && (s == command_line || isspace(s[-1]))) {
+ char *p = strchr(s, ' '), old;
+ if (!p)
+ p = strchr(s, '\0');
+ old = *p;
+ *p = 0;
+ for (i = 0; !changed && apic_probe[i]; i++) {
+ if (!strcmp(apic_probe[i]->name, s+5)) {
+ changed = 1;
+ genapic = apic_probe[i];
+ }
+ }
+ if (!changed)
+ printk(KERN_ERR "Unknown genapic `%s' specified.\n", s);
+ *p = old;
+ }
+ for (i = 0; !changed && apic_probe[i]; i++) {
+ if (apic_probe[i]->probe()) {
+ changed = 1;
+ genapic = apic_probe[i];
+ }
+ }
+ /* Not visible without early console */
+ if (!changed)
+ panic("Didn't find an APIC driver");
+
+ printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
+}
+
+/* These functions can switch the APIC even after the initial ->probe() */
+
+int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid)
+{
+ int i;
+ for (i = 0; apic_probe[i]; ++i) {
+ if (apic_probe[i]->mps_oem_check(mpc,oem,productid)) {
+ genapic = apic_probe[i];
+ printk(KERN_INFO "Switched to APIC driver `%s'.\n",
+ genapic->name);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+ int i;
+ for (i = 0; apic_probe[i]; ++i) {
+ if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
+ genapic = apic_probe[i];
+ printk(KERN_INFO "Switched to APIC driver `%s'.\n",
+ genapic->name);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int hard_smp_processor_id(void)
+{
+ return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID));
+}
diff --git a/arch/i386/mach-generic/summit.c b/arch/i386/mach-generic/summit.c
new file mode 100644
index 000000000000..d4f573c67219
--- /dev/null
+++ b/arch/i386/mach-generic/summit.c
@@ -0,0 +1,22 @@
+/*
+ * APIC driver for the IBM "Summit" chipset.
+ */
+#define APIC_DEFINITION 1
+#include <asm/genapic.h>
+#include <asm/fixmap.h>
+#include <asm/apicdef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <asm/mach-summit/mach_apic.h>
+#include <asm/mach-summit/mach_ipi.h>
+#include <asm/mach-summit/mach_mpparse.h>
+
+static __init int probe_summit(void)
+{
+ /* probed later in mptable/ACPI hooks */
+ return 0;
+}
+
+struct genapic apic_summit = APIC_INIT("summit", probe_summit);
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index f7dde2ba9ba1..d2976f9c2120 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -29,87 +29,6 @@
extern void die(const char *,struct pt_regs *,long);
-#ifndef CONFIG_X86_WP_WORKS_OK
-/*
- * Ugly, ugly, but the goto's result in better assembly..
- */
-int __verify_write(const void * addr, unsigned long size)
-{
- struct mm_struct *mm = current->mm;
- struct vm_area_struct * vma;
- unsigned long start = (unsigned long) addr;
-
- if (!size || segment_eq(get_fs(),KERNEL_DS))
- return 1;
-
- down_read(&mm->mmap_sem);
- vma = find_vma(current->mm, start);
- if (!vma)
- goto bad_area;
- if (vma->vm_start > start)
- goto check_stack;
-
-good_area:
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
- size--;
- size += start & ~PAGE_MASK;
- size >>= PAGE_SHIFT;
- start &= PAGE_MASK;
-
- for (;;) {
- survive:
- switch (handle_mm_fault(current->mm, vma, start, 1)) {
- case VM_FAULT_SIGBUS:
- goto bad_area;
- case VM_FAULT_OOM:
- goto out_of_memory;
- case VM_FAULT_MINOR:
- case VM_FAULT_MAJOR:
- break;
- default:
- BUG();
- }
- if (!size)
- break;
- size--;
- start += PAGE_SIZE;
- if (start < vma->vm_end)
- continue;
- vma = vma->vm_next;
- if (!vma || vma->vm_start != start)
- goto bad_area;
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;;
- }
- /*
- * We really need to hold mmap_sem over the whole access to
- * userspace, else another thread could change permissions.
- * This is unfixable, so don't use i386-class machines for
- * critical servers.
- */
- up_read(&mm->mmap_sem);
- return 1;
-
-check_stack:
- if (!(vma->vm_flags & VM_GROWSDOWN))
- goto bad_area;
- if (expand_stack(vma, start) == 0)
- goto good_area;
-
-bad_area:
- up_read(&mm->mmap_sem);
- return 0;
-
-out_of_memory:
- if (current->pid == 1) {
- yield();
- goto survive;
- }
- goto bad_area;
-}
-#endif
-
/*
* Unlock any spinlocks which will prevent us from getting the
* message out
@@ -405,8 +324,12 @@ vmalloc_fault:
if (!pgd_present(*pgd_k))
goto no_context;
- set_pgd(pgd, *pgd_k);
-
+
+ /*
+ * set_pgd(pgd, *pgd_k); here would be useless on PAE
+ * and redundant with the set_pmd() on non-PAE.
+ */
+
pmd = pmd_offset(pgd, address);
pmd_k = pmd_offset(pgd_k, address);
if (!pmd_present(*pmd_k))
diff --git a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
index 56401363b4f6..5f024651c44a 100644
--- a/arch/i386/vmlinux.lds.S
+++ b/arch/i386/vmlinux.lds.S
@@ -85,7 +85,11 @@ SECTIONS
__alt_instructions = .;
.altinstructions : { *(.altinstructions) }
__alt_instructions_end = .;
- .altinstr_replacement : { *(.altinstr_replacement) }
+ .altinstr_replacement : { *(.altinstr_replacement) }
+ /* .exit.text is discard at runtime, not link time, to deal with references
+ from .altinstructions and .eh_frame */
+ .exit.text : { *(.exit.text) }
+ .exit.data : { *(.exit.data) }
. = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
@@ -106,8 +110,6 @@ SECTIONS
/* Sections to be discarded */
/DISCARD/ : {
- *(.exit.text)
- *(.exit.data)
*(.exitcall.exit)
}
diff --git a/arch/mips/au1000/common/serial.c b/arch/mips/au1000/common/serial.c
index 6a8ecd768632..7de7a5058cc7 100644
--- a/arch/mips/au1000/common/serial.c
+++ b/arch/mips/au1000/common/serial.c
@@ -2681,8 +2681,8 @@ static int __init rs_init(void)
(state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
state->port, state->irq,
uart_config[state->type].name);
- tty_register_device(&serial_driver, state->line);
- tty_register_device(&callout_driver, state->line);
+ tty_register_device(&serial_driver, state->line, NULL);
+ tty_register_device(&callout_driver, state->line, NULL);
}
return 0;
}
@@ -2769,8 +2769,8 @@ int register_serial(struct serial_struct *req)
state->iomem_base ? "iomem" : "port",
state->iomem_base ? (unsigned long)state->iomem_base :
state->port, state->irq, uart_config[state->type].name);
- tty_register_device(&serial_driver, state->line);
- tty_register_device(&callout_driver, state->line);
+ tty_register_device(&serial_driver, state->line, NULL);
+ tty_register_device(&callout_driver, state->line, NULL);
return state->line + SERIAL_DEV_OFFSET;
}
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index b97f38bee178..18252eea15b7 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -191,10 +191,9 @@ init_socksys(void)
printk ("Couldn't create socket\n");
return ret;
}
- devfs_register (NULL, "socksys", DEVFS_FL_DEFAULT,
- 30, 0,
- S_IFCHR | S_IRUSR | S_IWUSR,
- &socksys_fops, NULL);
+
+ devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUSR|S_IWUSR, "socksys");
+
file = fcheck(ret);
/* N.B. Is this valid? Suppose the f_ops are in a module ... */
socksys_file_ops = *file->f_op;
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 2e07681d56b3..628d8f80434e 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -124,9 +124,7 @@ static int __init mmapper_init(void)
p_buf = __pa(v_buf);
- devfs_register (NULL, "mmapper", DEVFS_FL_DEFAULT,
- 30, 0, S_IFCHR | S_IRUGO | S_IWUGO,
- &mmapper_fops, NULL);
+ devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUGO|S_IWUGO, "mmapper");
devfs_mk_symlink("mmapper0", "mmapper");
return(0);
}
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig
index a6ff17d08bb1..b2ed5fde96a9 100644
--- a/drivers/atm/Kconfig
+++ b/drivers/atm/Kconfig
@@ -440,5 +440,19 @@ config ATM_FORE200E
default m if ATM_FORE200E_MAYBE!=y
default y if ATM_FORE200E_MAYBE=y
+config ATM_HE
+ tristate "ForeRunner HE Series"
+ depends on PCI && ATM
+ help
+ This is a driver for the Marconi ForeRunner HE-series ATM adapter
+ cards. It simultaneously supports the 155 and 622 versions.
+
+config ATM_HE_USE_SUNI
+ bool "Use S/UNI PHY driver"
+ depends on ATM_HE
+ help
+ Support for the S/UNI-Ultra and S/UNI-622 found in the ForeRunner
+ HE cards. This driver provides carrier detection some statistics.
+
endmenu
diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile
index f3e0c0cbc39c..c66d937fe2d5 100644
--- a/drivers/atm/Makefile
+++ b/drivers/atm/Makefile
@@ -49,6 +49,10 @@ ifeq ($(CONFIG_ATM_FORE200E_SBA),y)
CONFIG_ATM_FORE200E_SBA_FW := $(obj)/sba200e_ecd.bin2
endif
endif
+obj-$(CONFIG_ATM_HE) += he.o
+ifeq ($(CONFIG_ATM_HE_USE_SUNI),y)
+ obj-$(CONFIG_ATM_HE) += suni.o
+endif
# FORE Systems 200E-series firmware magic
$(obj)/fore200e_pca_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_PCA_FW)) \
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
new file mode 100644
index 000000000000..26eeea094644
--- /dev/null
+++ b/drivers/atm/he.c
@@ -0,0 +1,3419 @@
+/* $Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $ */
+
+/*
+
+ he.c
+
+ ForeRunnerHE ATM Adapter driver for ATM on Linux
+ Copyright (C) 1999-2001 Naval Research Laboratory
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+/*
+
+ he.c
+
+ ForeRunnerHE ATM Adapter driver for ATM on Linux
+ Copyright (C) 1999-2001 Naval Research Laboratory
+
+ Permission to use, copy, modify and distribute this software and its
+ documentation is hereby granted, provided that both the copyright
+ notice and this permission notice appear in all copies of the software,
+ derivative works or modified versions, and any portions thereof, and
+ that both notices appear in supporting documentation.
+
+ NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
+ DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
+ RESULTING FROM THE USE OF THIS SOFTWARE.
+
+ This driver was written using the "Programmer's Reference Manual for
+ ForeRunnerHE(tm)", MANU0361-01 - Rev. A, 08/21/98.
+
+ AUTHORS:
+ chas williams <chas@cmf.nrl.navy.mil>
+ eric kinzie <ekinzie@cmf.nrl.navy.mil>
+
+ NOTES:
+ 4096 supported 'connections'
+ group 0 is used for all traffic
+ interrupt queue 0 is used for all interrupts
+ aal0 support for receive only
+
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <linux/atmdev.h>
+#include <linux/atm.h>
+#include <linux/sonet.h>
+#ifndef ATM_OC12_PCR
+#define ATM_OC12_PCR (622080000/1080*1040/8/53)
+#endif
+
+#ifdef BUS_INT_WAR
+void sn_add_polled_interrupt(int irq, int interval);
+void sn_delete_polled_interrupt(int irq);
+#endif
+
+#define USE_TASKLET
+#define USE_HE_FIND_VCC
+#undef USE_SCATTERGATHER
+#undef USE_CHECKSUM_HW /* still confused about this */
+#define USE_RBPS
+#undef USE_RBPS_POOL /* if memory is tight try this */
+#undef USE_RBPL_POOL /* if memory is tight try this */
+#define USE_TPD_POOL
+/* #undef CONFIG_ATM_HE_USE_SUNI */
+
+/* 2.2 kernel support */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
+#define dev_kfree_skb_irq(skb) dev_kfree_skb(skb)
+#define dev_kfree_skb_any(skb) dev_kfree_skb(skb)
+#undef USE_TASKLET
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
+#define set_current_state(x) current->state = (x);
+#endif
+
+#include "he.h"
+
+#include "suni.h"
+
+#include <linux/atm_he.h>
+
+#define hprintk(fmt,args...) printk(DEV_LABEL "%d: " fmt, he_dev->number, args)
+#define hprintk1(fmt) printk(DEV_LABEL "%d: " fmt, he_dev->number)
+
+#undef DEBUG
+#ifdef DEBUG
+#define HPRINTK(fmt,args...) hprintk(fmt,args)
+#define HPRINTK1(fmt) hprintk1(fmt)
+#else
+#define HPRINTK(fmt,args...)
+#define HPRINTK1(fmt,args...)
+#endif /* DEBUG */
+
+
+/* version definition */
+
+static char *version = "$Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $";
+
+/* defines */
+#define ALIGN_ADDRESS(addr, alignment) \
+ ((((unsigned long) (addr)) + (((unsigned long) (alignment)) - 1)) & ~(((unsigned long) (alignment)) - 1))
+
+/* declarations */
+
+static int he_open(struct atm_vcc *vcc, short vpi, int vci);
+static void he_close(struct atm_vcc *vcc);
+static int he_send(struct atm_vcc *vcc, struct sk_buff *skb);
+static int he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size);
+static int he_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69)
+static irqreturn_t he_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+#else
+static void he_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+#endif
+static void he_tasklet(unsigned long data);
+static int he_proc_read(struct atm_dev *dev,loff_t *pos,char *page);
+static int he_start(struct atm_dev *dev);
+static void he_stop(struct he_dev *dev);
+static void he_phy_put(struct atm_dev *, unsigned char, unsigned long);
+static unsigned char he_phy_get(struct atm_dev *, unsigned long);
+
+static u8 read_prom_byte(struct he_dev *he_dev, int addr);
+
+/* globals */
+
+struct he_dev *he_devs = NULL;
+static short disable64 = -1;
+static short nvpibits = -1;
+static short nvcibits = -1;
+static short rx_skb_reserve = 16;
+static short irq_coalesce = 1;
+static short sdh = 1;
+
+static struct atmdev_ops he_ops =
+{
+ open: he_open,
+ close: he_close,
+ ioctl: he_ioctl,
+ send: he_send,
+ sg_send: he_sg_send,
+ phy_put: he_phy_put,
+ phy_get: he_phy_get,
+ proc_read: he_proc_read,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,1)
+ owner: THIS_MODULE
+#endif
+};
+
+/* see the comments in he.h about global_lock */
+
+#define HE_SPIN_LOCK(dev, flags) spin_lock_irqsave(&(dev)->global_lock, flags)
+#define HE_SPIN_UNLOCK(dev, flags) spin_unlock_irqrestore(&(dev)->global_lock, flags)
+
+#define he_writel(dev, val, reg) do { writel(val, (dev)->membase + (reg)); wmb(); } while(0)
+#define he_readl(dev, reg) readl((dev)->membase + (reg))
+
+/* section 2.12 connection memory access */
+
+static __inline__ void
+he_writel_internal(struct he_dev *he_dev, unsigned val, unsigned addr,
+ unsigned flags)
+{
+ he_writel(he_dev, val, CON_DAT);
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl(he_dev, CON_DAT);
+#endif
+ he_writel(he_dev, flags | CON_CTL_WRITE | CON_CTL_ADDR(addr), CON_CTL);
+ while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY);
+}
+
+#define he_writel_rcm(dev, val, reg) \
+ he_writel_internal(dev, val, reg, CON_CTL_RCM)
+
+#define he_writel_tcm(dev, val, reg) \
+ he_writel_internal(dev, val, reg, CON_CTL_TCM)
+
+#define he_writel_mbox(dev, val, reg) \
+ he_writel_internal(dev, val, reg, CON_CTL_MBOX)
+
+static unsigned
+he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags)
+{
+ he_writel(he_dev, flags | CON_CTL_READ | CON_CTL_ADDR(addr), CON_CTL);
+ while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY);
+ return he_readl(he_dev, CON_DAT);
+}
+
+#define he_readl_rcm(dev, reg) \
+ he_readl_internal(dev, reg, CON_CTL_RCM)
+
+#define he_readl_tcm(dev, reg) \
+ he_readl_internal(dev, reg, CON_CTL_TCM)
+
+#define he_readl_mbox(dev, reg) \
+ he_readl_internal(dev, reg, CON_CTL_MBOX)
+
+
+/* figure 2.2 connection id */
+
+#define he_mkcid(dev, vpi, vci) (((vpi<<(dev)->vcibits) | vci) & 0x1fff)
+
+/* 2.5.1 per connection transmit state registers */
+
+#define he_writel_tsr0(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 0)
+#define he_readl_tsr0(dev, cid) \
+ he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 0)
+
+#define he_writel_tsr1(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 1)
+
+#define he_writel_tsr2(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 2)
+
+#define he_writel_tsr3(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 3)
+
+#define he_writel_tsr4(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 4)
+
+ /* from page 2-20
+ *
+ * NOTE While the transmit connection is active, bits 23 through 0
+ * of this register must not be written by the host. Byte
+ * enables should be used during normal operation when writing
+ * the most significant byte.
+ */
+
+#define he_writel_tsr4_upper(dev, val, cid) \
+ he_writel_internal(dev, val, CONFIG_TSRA | (cid<<3) | 4, \
+ CON_CTL_TCM \
+ | CON_BYTE_DISABLE_2 \
+ | CON_BYTE_DISABLE_1 \
+ | CON_BYTE_DISABLE_0)
+
+#define he_readl_tsr4(dev, cid) \
+ he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 4)
+
+#define he_writel_tsr5(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 5)
+
+#define he_writel_tsr6(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 6)
+
+#define he_writel_tsr7(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 7)
+
+
+#define he_writel_tsr8(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 0)
+
+#define he_writel_tsr9(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 1)
+
+#define he_writel_tsr10(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 2)
+
+#define he_writel_tsr11(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 3)
+
+
+#define he_writel_tsr12(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<1) | 0)
+
+#define he_writel_tsr13(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<1) | 1)
+
+
+#define he_writel_tsr14(dev, val, cid) \
+ he_writel_tcm(dev, val, CONFIG_TSRD | cid)
+
+#define he_writel_tsr14_upper(dev, val, cid) \
+ he_writel_internal(dev, val, CONFIG_TSRD | cid, \
+ CON_CTL_TCM \
+ | CON_BYTE_DISABLE_2 \
+ | CON_BYTE_DISABLE_1 \
+ | CON_BYTE_DISABLE_0)
+
+/* 2.7.1 per connection receive state registers */
+
+#define he_writel_rsr0(dev, val, cid) \
+ he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 0)
+#define he_readl_rsr0(dev, cid) \
+ he_readl_rcm(dev, 0x00000 | (cid<<3) | 0)
+
+#define he_writel_rsr1(dev, val, cid) \
+ he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 1)
+
+#define he_writel_rsr2(dev, val, cid) \
+ he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 2)
+
+#define he_writel_rsr3(dev, val, cid) \
+ he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 3)
+
+#define he_writel_rsr4(dev, val, cid) \
+ he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 4)
+
+#define he_writel_rsr5(dev, val, cid) \
+ he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 5)
+
+#define he_writel_rsr6(dev, val, cid) \
+ he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 6)
+
+#define he_writel_rsr7(dev, val, cid) \
+ he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 7)
+
+static __inline__ struct atm_vcc*
+he_find_vcc(struct he_dev *he_dev, unsigned cid)
+{
+ struct atm_vcc *vcc;
+ short vpi;
+ int vci;
+
+ vpi = cid >> he_dev->vcibits;
+ vci = cid & ((1<<he_dev->vcibits)-1);
+
+ for (vcc = he_dev->atm_dev->vccs; vcc; vcc = vcc->next)
+ if (vcc->vci == vci && vcc->vpi == vpi
+ && vcc->qos.rxtp.traffic_class != ATM_NONE) return vcc;
+
+ return NULL;
+}
+
+static int __devinit
+he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+{
+ struct atm_dev *atm_dev;
+ struct he_dev *he_dev;
+
+ printk(KERN_INFO "he: %s\n", version);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,43)
+ if (pci_enable_device(pci_dev)) return -EIO;
+#endif
+ if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0)
+ {
+ printk(KERN_WARNING "he: no suitable dma available\n");
+ return -EIO;
+ }
+
+ atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, 0);
+ if (!atm_dev) return -ENODEV;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
+ pci_set_drvdata(pci_dev, atm_dev);
+#else
+ pci_dev->driver_data = atm_dev;
+#endif
+
+ he_dev = (struct he_dev *) kmalloc(sizeof(struct he_dev),
+ GFP_KERNEL);
+ if (!he_dev) return -ENOMEM;
+ memset(he_dev, 0, sizeof(struct he_dev));
+
+ he_dev->pci_dev = pci_dev;
+ he_dev->atm_dev = atm_dev;
+ he_dev->atm_dev->dev_data = he_dev;
+ HE_DEV(atm_dev) = he_dev;
+ he_dev->number = atm_dev->number; /* was devs */
+ if (he_start(atm_dev)) {
+ atm_dev_deregister(atm_dev);
+ he_stop(he_dev);
+ kfree(he_dev);
+ return -ENODEV;
+ }
+ he_dev->next = NULL;
+ if (he_devs) he_dev->next = he_devs;
+ he_devs = he_dev;
+
+ return 0;
+}
+
+static void __devexit
+he_remove_one (struct pci_dev *pci_dev)
+{
+ struct atm_dev *atm_dev;
+ struct he_dev *he_dev;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
+ atm_dev = pci_get_drvdata(pci_dev);
+#else
+ atm_dev = pci_dev->driver_data;
+#endif
+ he_dev = HE_DEV(atm_dev);
+
+ /* need to remove from he_devs */
+
+ he_stop(he_dev);
+ atm_dev_deregister(atm_dev);
+ kfree(he_dev);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3)
+ pci_set_drvdata(pci_dev, NULL);
+#else
+ pci_dev->driver_data = NULL;
+#endif
+}
+
+
+static unsigned
+rate_to_atmf(unsigned rate) /* cps to atm forum format */
+{
+#define NONZERO (1<<14)
+
+ unsigned exp = 0;
+
+ if (rate == 0) return(0);
+
+ rate <<= 9;
+ while (rate > 0x3ff)
+ {
+ ++exp;
+ rate >>= 1;
+ }
+
+ return (NONZERO | (exp << 9) | (rate & 0x1ff));
+}
+
+static void __init
+he_init_rx_lbfp0(struct he_dev *he_dev)
+{
+ unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
+ unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
+ unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
+ unsigned row_offset = he_dev->r0_startrow * he_dev->bytes_per_row;
+
+ lbufd_index = 0;
+ lbm_offset = he_readl(he_dev, RCMLBM_BA);
+
+ he_writel(he_dev, lbufd_index, RLBF0_H);
+
+ for (i = 0, lbuf_count = 0; i < he_dev->r0_numbuffs; ++i)
+ {
+ lbufd_index += 2;
+ lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
+
+ he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
+ he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
+
+ if (++lbuf_count == lbufs_per_row)
+ {
+ lbuf_count = 0;
+ row_offset += he_dev->bytes_per_row;
+ }
+ lbm_offset += 4;
+ }
+
+ he_writel(he_dev, lbufd_index - 2, RLBF0_T);
+ he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C);
+}
+
+static void __init
+he_init_rx_lbfp1(struct he_dev *he_dev)
+{
+ unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
+ unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
+ unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
+ unsigned row_offset = he_dev->r1_startrow * he_dev->bytes_per_row;
+
+ lbufd_index = 1;
+ lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
+
+ he_writel(he_dev, lbufd_index, RLBF1_H);
+
+ for (i = 0, lbuf_count = 0; i < he_dev->r1_numbuffs; ++i)
+ {
+ lbufd_index += 2;
+ lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
+
+ he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
+ he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
+
+ if (++lbuf_count == lbufs_per_row)
+ {
+ lbuf_count = 0;
+ row_offset += he_dev->bytes_per_row;
+ }
+ lbm_offset += 4;
+ }
+
+ he_writel(he_dev, lbufd_index - 2, RLBF1_T);
+ he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C);
+}
+
+static void __init
+he_init_tx_lbfp(struct he_dev *he_dev)
+{
+ unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count;
+ unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf;
+ unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD;
+ unsigned row_offset = he_dev->tx_startrow * he_dev->bytes_per_row;
+
+ lbufd_index = he_dev->r0_numbuffs + he_dev->r1_numbuffs;
+ lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index);
+
+ he_writel(he_dev, lbufd_index, TLBF_H);
+
+ for (i = 0, lbuf_count = 0; i < he_dev->tx_numbuffs; ++i)
+ {
+ lbufd_index += 1;
+ lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32;
+
+ he_writel_rcm(he_dev, lbuf_addr, lbm_offset);
+ he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1);
+
+ if (++lbuf_count == lbufs_per_row)
+ {
+ lbuf_count = 0;
+ row_offset += he_dev->bytes_per_row;
+ }
+ lbm_offset += 2;
+ }
+
+ he_writel(he_dev, lbufd_index - 1, TLBF_T);
+}
+
+static int __init
+he_init_tpdrq(struct he_dev *he_dev)
+{
+ he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev,
+ CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys);
+ if (he_dev->tpdrq_base == NULL)
+ {
+ hprintk1("failed to alloc tpdrq\n");
+ return -ENOMEM;
+ }
+ memset(he_dev->tpdrq_base, 0,
+ CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq));
+
+ he_dev->tpdrq_tail = he_dev->tpdrq_base;
+ he_dev->tpdrq_head = he_dev->tpdrq_base;
+
+ he_writel(he_dev, he_dev->tpdrq_phys, TPDRQ_B_H);
+ he_writel(he_dev, 0, TPDRQ_T);
+ he_writel(he_dev, CONFIG_TPDRQ_SIZE - 1, TPDRQ_S);
+
+ return 0;
+}
+
+static void __init
+he_init_cs_block(struct he_dev *he_dev)
+{
+ unsigned clock, rate, delta;
+ int reg;
+
+ /* 5.1.7 cs block initialization */
+
+ for(reg = 0; reg < 0x20; ++reg)
+ he_writel_mbox(he_dev, 0x0, CS_STTIM0 + reg);
+
+ /* rate grid timer reload values */
+
+ clock = he_is622(he_dev) ? 66667000 : 50000000;
+ rate = he_dev->atm_dev->link_rate;
+ delta = rate / 16 / 2;
+
+ for(reg = 0; reg < 0x10; ++reg)
+ {
+ /* 2.4 internal transmit function
+ *
+ * we initialize the first row in the rate grid.
+ * values are period (in clock cycles) of timer
+ */
+ unsigned period = clock / rate;
+
+ he_writel_mbox(he_dev, period, CS_TGRLD0 + reg);
+ rate -= delta;
+ }
+
+ if (he_is622(he_dev))
+ {
+ /* table 5.2 (4 cells per lbuf) */
+ he_writel_mbox(he_dev, 0x000800fa, CS_ERTHR0);
+ he_writel_mbox(he_dev, 0x000c33cb, CS_ERTHR1);
+ he_writel_mbox(he_dev, 0x0010101b, CS_ERTHR2);
+ he_writel_mbox(he_dev, 0x00181dac, CS_ERTHR3);
+ he_writel_mbox(he_dev, 0x00280600, CS_ERTHR4);
+
+ /* table 5.3, 5.4, 5.5, 5.6, 5.7 */
+ he_writel_mbox(he_dev, 0x023de8b3, CS_ERCTL0);
+ he_writel_mbox(he_dev, 0x1801, CS_ERCTL1);
+ he_writel_mbox(he_dev, 0x68b3, CS_ERCTL2);
+ he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0);
+ he_writel_mbox(he_dev, 0x68b3, CS_ERSTAT1);
+ he_writel_mbox(he_dev, 0x14585, CS_RTFWR);
+
+ he_writel_mbox(he_dev, 0x4680, CS_RTATR);
+
+ /* table 5.8 */
+ he_writel_mbox(he_dev, 0x00159ece, CS_TFBSET);
+ he_writel_mbox(he_dev, 0x68b3, CS_WCRMAX);
+ he_writel_mbox(he_dev, 0x5eb3, CS_WCRMIN);
+ he_writel_mbox(he_dev, 0xe8b3, CS_WCRINC);
+ he_writel_mbox(he_dev, 0xdeb3, CS_WCRDEC);
+ he_writel_mbox(he_dev, 0x68b3, CS_WCRCEIL);
+
+ /* table 5.9 */
+ he_writel_mbox(he_dev, 0x5, CS_OTPPER);
+ he_writel_mbox(he_dev, 0x14, CS_OTWPER);
+ }
+ else
+ {
+ /* table 5.1 (4 cells per lbuf) */
+ he_writel_mbox(he_dev, 0x000400ea, CS_ERTHR0);
+ he_writel_mbox(he_dev, 0x00063388, CS_ERTHR1);
+ he_writel_mbox(he_dev, 0x00081018, CS_ERTHR2);
+ he_writel_mbox(he_dev, 0x000c1dac, CS_ERTHR3);
+ he_writel_mbox(he_dev, 0x0014051a, CS_ERTHR4);
+
+ /* table 5.3, 5.4, 5.5, 5.6, 5.7 */
+ he_writel_mbox(he_dev, 0x0235e4b1, CS_ERCTL0);
+ he_writel_mbox(he_dev, 0x4701, CS_ERCTL1);
+ he_writel_mbox(he_dev, 0x64b1, CS_ERCTL2);
+ he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0);
+ he_writel_mbox(he_dev, 0x64b1, CS_ERSTAT1);
+ he_writel_mbox(he_dev, 0xf424, CS_RTFWR);
+
+ he_writel_mbox(he_dev, 0x4680, CS_RTATR);
+
+ /* table 5.8 */
+ he_writel_mbox(he_dev, 0x000563b7, CS_TFBSET);
+ he_writel_mbox(he_dev, 0x64b1, CS_WCRMAX);
+ he_writel_mbox(he_dev, 0x5ab1, CS_WCRMIN);
+ he_writel_mbox(he_dev, 0xe4b1, CS_WCRINC);
+ he_writel_mbox(he_dev, 0xdab1, CS_WCRDEC);
+ he_writel_mbox(he_dev, 0x64b1, CS_WCRCEIL);
+
+ /* table 5.9 */
+ he_writel_mbox(he_dev, 0x6, CS_OTPPER);
+ he_writel_mbox(he_dev, 0x1e, CS_OTWPER);
+
+ }
+
+ he_writel_mbox(he_dev, 0x8, CS_OTTLIM);
+
+ for(reg = 0; reg < 0x8; ++reg)
+ he_writel_mbox(he_dev, 0x0, CS_HGRRT0 + reg);
+
+}
+
+static void __init
+he_init_cs_block_rcm(struct he_dev *he_dev)
+{
+ unsigned rategrid[16][16];
+ unsigned rate, delta;
+ int i, j, reg;
+
+ unsigned rate_atmf, exp, man;
+ unsigned long long rate_cps;
+ int mult, buf, buf_limit = 4;
+
+ /* initialize rate grid group table */
+
+ for (reg = 0x0; reg < 0xff; ++reg)
+ he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
+
+ /* initialize rate controller groups */
+
+ for (reg = 0x100; reg < 0x1ff; ++reg)
+ he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg);
+
+ /* initialize tNrm lookup table */
+
+ /* the manual makes reference to a routine in a sample driver
+ for proper configuration; fortunately, we only need this
+ in order to support abr connection */
+
+ /* initialize rate to group table */
+
+ rate = he_dev->atm_dev->link_rate;
+ delta = rate / 32;
+
+ /*
+ * 2.4 transmit internal functions
+ *
+ * we construct a copy of the rate grid used by the scheduler
+ * in order to construct the rate to group table below
+ */
+
+ for (j = 0; j < 16; j++)
+ {
+ rategrid[0][j] = rate;
+ rate -= delta;
+ }
+
+ for (i = 1; i < 16; i++)
+ for (j = 0; j < 16; j++)
+ if (i > 14)
+ rategrid[i][j] = rategrid[i - 1][j] / 4;
+ else
+ rategrid[i][j] = rategrid[i - 1][j] / 2;
+
+ /*
+ * 2.4 transmit internal function
+ *
+ * this table maps the upper 5 bits of exponent and mantissa
+ * of the atm forum representation of the rate into an index
+ * on rate grid
+ */
+
+ rate_atmf = 0;
+ while (rate_atmf < 0x400)
+ {
+ man = (rate_atmf & 0x1f) << 4;
+ exp = rate_atmf >> 5;
+
+ /*
+ instead of '/ 512', use '>> 9' to prevent a call
+ to divdu3 on x86 platforms
+ */
+ rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9;
+
+ if (rate_cps < 10) rate_cps = 10;
+ /* 2.2.1 minimum payload rate is 10 cps */
+
+ for (i = 255; i > 0; i--)
+ if (rategrid[i/16][i%16] >= rate_cps) break;
+ /* pick nearest rate instead? */
+
+ /*
+ * each table entry is 16 bits: (rate grid index (8 bits)
+ * and a buffer limit (8 bits)
+ * there are two table entries in each 32-bit register
+ */
+
+#ifdef notdef
+ buf = rate_cps * he_dev->tx_numbuffs /
+ (he_dev->atm_dev->link_rate * 2);
+#else
+ /* this is pretty, but avoids _divdu3 and is mostly correct */
+ buf = 0;
+ mult = he_dev->atm_dev->link_rate / ATM_OC3_PCR;
+ if (rate_cps > (68 * mult)) buf = 1;
+ if (rate_cps > (136 * mult)) buf = 2;
+ if (rate_cps > (204 * mult)) buf = 3;
+ if (rate_cps > (272 * mult)) buf = 4;
+#endif
+ if (buf > buf_limit) buf = buf_limit;
+ reg = (reg<<16) | ((i<<8) | buf);
+
+#define RTGTBL_OFFSET 0x400
+
+ if (rate_atmf & 0x1)
+ he_writel_rcm(he_dev, reg,
+ CONFIG_RCMABR + RTGTBL_OFFSET + (rate_atmf>>1));
+
+ ++rate_atmf;
+ }
+}
+
+static int __init
+he_init_group(struct he_dev *he_dev, int group)
+{
+ int i;
+
+#ifdef USE_RBPS
+ /* small buffer pool */
+#ifdef USE_RBPS_POOL
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
+ he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
+ CONFIG_RBPS_BUFSIZE, 8, 0, SLAB_KERNEL);
+#else
+ he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
+ CONFIG_RBPS_BUFSIZE, 8, 0);
+#endif
+ if (he_dev->rbps_pool == NULL)
+ {
+ hprintk1("unable to create rbps pages\n");
+ return -ENOMEM;
+ }
+#else /* !USE_RBPS_POOL */
+ he_dev->rbps_pages = pci_alloc_consistent(he_dev->pci_dev,
+ CONFIG_RBPS_SIZE * CONFIG_RBPS_BUFSIZE, &he_dev->rbps_pages_phys);
+ if (he_dev->rbps_pages == NULL) {
+ hprintk1("unable to create rbps page pool\n");
+ return -ENOMEM;
+ }
+#endif /* USE_RBPS_POOL */
+
+ he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
+ CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
+ if (he_dev->rbps_base == NULL)
+ {
+ hprintk1("failed to alloc rbps\n");
+ return -ENOMEM;
+ }
+ memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
+ he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+
+ for (i = 0; i < CONFIG_RBPS_SIZE; ++i)
+ {
+ dma_addr_t dma_handle;
+ void *cpuaddr;
+
+#ifdef USE_RBPS_POOL
+ cpuaddr = pci_pool_alloc(he_dev->rbps_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
+ if (cpuaddr == NULL)
+ return -ENOMEM;
+#else
+ cpuaddr = he_dev->rbps_pages + (i * CONFIG_RBPS_BUFSIZE);
+ dma_handle = he_dev->rbps_pages_phys + (i * CONFIG_RBPS_BUFSIZE);
+#endif
+
+ he_dev->rbps_virt[i].virt = cpuaddr;
+ he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
+ he_dev->rbps_base[i].phys = dma_handle;
+
+ }
+ he_dev->rbps_tail = &he_dev->rbps_base[CONFIG_RBPS_SIZE-1];
+
+ he_writel(he_dev, he_dev->rbps_phys, G0_RBPS_S + (group * 32));
+ he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail),
+ G0_RBPS_T + (group * 32));
+ he_writel(he_dev, CONFIG_RBPS_BUFSIZE/4,
+ G0_RBPS_BS + (group * 32));
+ he_writel(he_dev,
+ RBP_THRESH(CONFIG_RBPS_THRESH) |
+ RBP_QSIZE(CONFIG_RBPS_SIZE-1) |
+ RBP_INT_ENB,
+ G0_RBPS_QI + (group * 32));
+#else /* !USE_RBPS */
+ he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));
+ he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));
+ he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));
+ he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
+ G0_RBPS_BS + (group * 32));
+#endif /* USE_RBPS */
+
+ /* large buffer pool */
+#ifdef USE_RBPL_POOL
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
+ he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev,
+ CONFIG_RBPL_BUFSIZE, 8, 0, SLAB_KERNEL);
+#else
+ he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev,
+ CONFIG_RBPL_BUFSIZE, 8, 0);
+#endif
+ if (he_dev->rbpl_pool == NULL)
+ {
+ hprintk1("unable to create rbpl pool\n");
+ return -ENOMEM;
+ }
+#else /* !USE_RBPL_POOL */
+ he_dev->rbpl_pages = (void *) pci_alloc_consistent(he_dev->pci_dev,
+ CONFIG_RBPL_SIZE * CONFIG_RBPL_BUFSIZE, &he_dev->rbpl_pages_phys);
+ if (he_dev->rbpl_pages == NULL)
+ {
+ hprintk1("unable to create rbpl pages\n");
+ return -ENOMEM;
+ }
+#endif /* USE_RBPL_POOL */
+
+ he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
+ CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
+ if (he_dev->rbpl_base == NULL)
+ {
+ hprintk1("failed to alloc rbpl\n");
+ return -ENOMEM;
+ }
+ memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
+ he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+
+ for (i = 0; i < CONFIG_RBPL_SIZE; ++i)
+ {
+ dma_addr_t dma_handle;
+ void *cpuaddr;
+
+#ifdef USE_RBPL_POOL
+ cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle);
+ if (cpuaddr == NULL)
+ return -ENOMEM;
+#else
+ cpuaddr = he_dev->rbpl_pages + (i * CONFIG_RBPL_BUFSIZE);
+ dma_handle = he_dev->rbpl_pages_phys + (i * CONFIG_RBPL_BUFSIZE);
+#endif
+
+ he_dev->rbpl_virt[i].virt = cpuaddr;
+ he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
+ he_dev->rbpl_base[i].phys = dma_handle;
+
+ }
+ he_dev->rbpl_tail = &he_dev->rbpl_base[CONFIG_RBPL_SIZE-1];
+
+ he_writel(he_dev, he_dev->rbpl_phys, G0_RBPL_S + (group * 32));
+ he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail),
+ G0_RBPL_T + (group * 32));
+ he_writel(he_dev, CONFIG_RBPL_BUFSIZE/4,
+ G0_RBPL_BS + (group * 32));
+ he_writel(he_dev,
+ RBP_THRESH(CONFIG_RBPL_THRESH) |
+ RBP_QSIZE(CONFIG_RBPL_SIZE-1) |
+ RBP_INT_ENB,
+ G0_RBPL_QI + (group * 32));
+
+ /* rx buffer ready queue */
+
+ he_dev->rbrq_base = pci_alloc_consistent(he_dev->pci_dev,
+ CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
+ if (he_dev->rbrq_base == NULL)
+ {
+ hprintk1("failed to allocate rbrq\n");
+ return -ENOMEM;
+ }
+ memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
+
+ he_dev->rbrq_head = he_dev->rbrq_base;
+ he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16));
+ he_writel(he_dev, 0, G0_RBRQ_H + (group * 16));
+ he_writel(he_dev,
+ RBRQ_THRESH(CONFIG_RBRQ_THRESH) | RBRQ_SIZE(CONFIG_RBRQ_SIZE-1),
+ G0_RBRQ_Q + (group * 16));
+ if (irq_coalesce)
+ {
+ hprintk1("coalescing interrupts\n");
+ he_writel(he_dev, RBRQ_TIME(768) | RBRQ_COUNT(7),
+ G0_RBRQ_I + (group * 16));
+ }
+ else
+ he_writel(he_dev, RBRQ_TIME(0) | RBRQ_COUNT(1),
+ G0_RBRQ_I + (group * 16));
+
+ /* tx buffer ready queue */
+
+ he_dev->tbrq_base = pci_alloc_consistent(he_dev->pci_dev,
+ CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
+ if (he_dev->tbrq_base == NULL)
+ {
+ hprintk1("failed to allocate tbrq\n");
+ return -ENOMEM;
+ }
+ memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
+
+ he_dev->tbrq_head = he_dev->tbrq_base;
+
+ he_writel(he_dev, he_dev->tbrq_phys, G0_TBRQ_B_T + (group * 16));
+ he_writel(he_dev, 0, G0_TBRQ_H + (group * 16));
+ he_writel(he_dev, CONFIG_TBRQ_SIZE - 1, G0_TBRQ_S + (group * 16));
+ he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
+
+ return 0;
+}
+
+static int __init
+he_init_irq(struct he_dev *he_dev)
+{
+ int i;
+
+ /* 2.9.3.5 tail offset for each interrupt queue is located after the
+ end of the interrupt queue */
+
+ he_dev->irq_base = pci_alloc_consistent(he_dev->pci_dev,
+ (CONFIG_IRQ_SIZE+1) * sizeof(struct he_irq), &he_dev->irq_phys);
+ if (he_dev->irq_base == NULL)
+ {
+ hprintk1("failed to allocate irq\n");
+ return -ENOMEM;
+ }
+ he_dev->irq_tailoffset = (unsigned *)
+ &he_dev->irq_base[CONFIG_IRQ_SIZE];
+ *he_dev->irq_tailoffset = 0;
+ he_dev->irq_head = he_dev->irq_base;
+ he_dev->irq_tail = he_dev->irq_base;
+
+ for(i=0; i < CONFIG_IRQ_SIZE; ++i)
+ he_dev->irq_base[i].isw = ITYPE_INVALID;
+
+ he_writel(he_dev, he_dev->irq_phys, IRQ0_BASE);
+ he_writel(he_dev,
+ IRQ_SIZE(CONFIG_IRQ_SIZE) | IRQ_THRESH(CONFIG_IRQ_THRESH),
+ IRQ0_HEAD);
+ he_writel(he_dev, IRQ_INT_A | IRQ_TYPE_LINE, IRQ0_CNTL);
+ he_writel(he_dev, 0x0, IRQ0_DATA);
+
+ he_writel(he_dev, 0x0, IRQ1_BASE);
+ he_writel(he_dev, 0x0, IRQ1_HEAD);
+ he_writel(he_dev, 0x0, IRQ1_CNTL);
+ he_writel(he_dev, 0x0, IRQ1_DATA);
+
+ he_writel(he_dev, 0x0, IRQ2_BASE);
+ he_writel(he_dev, 0x0, IRQ2_HEAD);
+ he_writel(he_dev, 0x0, IRQ2_CNTL);
+ he_writel(he_dev, 0x0, IRQ2_DATA);
+
+ he_writel(he_dev, 0x0, IRQ3_BASE);
+ he_writel(he_dev, 0x0, IRQ3_HEAD);
+ he_writel(he_dev, 0x0, IRQ3_CNTL);
+ he_writel(he_dev, 0x0, IRQ3_DATA);
+
+ /* 2.9.3.2 interrupt queue mapping registers */
+
+ he_writel(he_dev, 0x0, GRP_10_MAP);
+ he_writel(he_dev, 0x0, GRP_32_MAP);
+ he_writel(he_dev, 0x0, GRP_54_MAP);
+ he_writel(he_dev, 0x0, GRP_76_MAP);
+
+ if (request_irq(he_dev->pci_dev->irq, he_irq_handler, SA_INTERRUPT|SA_SHIRQ, DEV_LABEL, he_dev))
+ {
+ hprintk("irq %d already in use\n", he_dev->pci_dev->irq);
+ return -EINVAL;
+ }
+
+ he_dev->irq = he_dev->pci_dev->irq;
+
+#ifdef BUS_INT_WAR
+ HPRINTK("sn_add_polled_interrupt(irq %d, 1)\n", he_dev->irq);
+ sn_add_polled_interrupt(he_dev->irq, 1);
+#endif
+
+ return 0;
+}
+
+static int __init
+he_start(struct atm_dev *dev)
+{
+ struct he_dev *he_dev;
+ struct pci_dev *pci_dev;
+
+ u16 command;
+ u32 gen_cntl_0, host_cntl, lb_swap;
+ u8 cache_size, timer;
+
+ unsigned err;
+ unsigned int status, reg;
+ int i, group;
+
+ he_dev = HE_DEV(dev);
+ pci_dev = he_dev->pci_dev;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,3)
+ he_dev->membase = pci_dev->resource[0].start;
+#else
+ he_dev->membase = pci_dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+#endif
+ HPRINTK("membase = 0x%lx irq = %d.\n", he_dev->membase, pci_dev->irq);
+
+ /*
+ * pci bus controller initialization
+ */
+
+ /* 4.3 pci bus controller-specific initialization */
+ if (pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0) != 0)
+ {
+ hprintk1("can't read GEN_CNTL_0\n");
+ return -EINVAL;
+ }
+ gen_cntl_0 |= (MRL_ENB | MRM_ENB | IGNORE_TIMEOUT);
+ if (pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0) != 0)
+ {
+ hprintk1("can't write GEN_CNTL_0.\n");
+ return -EINVAL;
+ }
+
+ if (pci_read_config_word(pci_dev, PCI_COMMAND, &command) != 0)
+ {
+ hprintk1("can't read PCI_COMMAND.\n");
+ return -EINVAL;
+ }
+
+ command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
+ if (pci_write_config_word(pci_dev, PCI_COMMAND, command) != 0)
+ {
+ hprintk1("can't enable memory.\n");
+ return -EINVAL;
+ }
+
+ if (pci_read_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, &cache_size))
+ {
+ hprintk1("can't read cache line size?\n");
+ return -EINVAL;
+ }
+
+ if (cache_size < 16)
+ {
+ cache_size = 16;
+ if (pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, cache_size))
+ hprintk("can't set cache line size to %d\n", cache_size);
+ }
+
+ if (pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &timer))
+ {
+ hprintk1("can't read latency timer?\n");
+ return -EINVAL;
+ }
+
+ /* from table 3.9
+ *
+ * LAT_TIMER = 1 + AVG_LAT + BURST_SIZE/BUS_SIZE
+ *
+ * AVG_LAT: The average first data read/write latency [maximum 16 clock cycles]
+ * BURST_SIZE: 1536 bytes (read) for 622, 768 bytes (read) for 155 [192 clock cycles]
+ *
+ */
+#define LAT_TIMER 209
+ if (timer < LAT_TIMER)
+ {
+ HPRINTK("latency timer was %d, setting to %d\n", timer, LAT_TIMER);
+ timer = LAT_TIMER;
+ if (pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, timer))
+ hprintk("can't set latency timer to %d\n", timer);
+ }
+
+ if (!(he_dev->membase = (unsigned long) ioremap(he_dev->membase, HE_REGMAP_SIZE))) {
+ hprintk1("can't set up page mapping\n");
+ return -EINVAL;
+ }
+
+ /* 4.4 card reset */
+ he_writel(he_dev, 0x0, RESET_CNTL);
+ he_writel(he_dev, 0xff, RESET_CNTL);
+
+ udelay(16*1000); /* 16 ms */
+ status = he_readl(he_dev, RESET_CNTL);
+ if ((status & BOARD_RST_STATUS) == 0)
+ {
+ hprintk1("reset failed\n");
+ return -EINVAL;
+ }
+
+ /* 4.5 set bus width */
+ host_cntl = he_readl(he_dev, HOST_CNTL);
+ if (host_cntl & PCI_BUS_SIZE64)
+ gen_cntl_0 |= ENBL_64;
+ else
+ gen_cntl_0 &= ~ENBL_64;
+
+ if (disable64 == 1)
+ {
+ hprintk1("disabling 64-bit pci bus transfers\n");
+ gen_cntl_0 &= ~ENBL_64;
+ }
+
+ if (gen_cntl_0 & ENBL_64) hprintk1("64-bit transfers enabled\n");
+
+ pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
+
+ /* 4.7 read prom contents */
+ for(i=0; i<PROD_ID_LEN; ++i)
+ he_dev->prod_id[i] = read_prom_byte(he_dev, PROD_ID + i);
+
+ he_dev->media = read_prom_byte(he_dev, MEDIA);
+
+ for(i=0; i<6; ++i)
+ dev->esi[i] = read_prom_byte(he_dev, MAC_ADDR + i);
+
+ hprintk("%s%s, %x:%x:%x:%x:%x:%x\n",
+ he_dev->prod_id,
+ he_dev->media & 0x40 ? "SM" : "MM",
+ dev->esi[0],
+ dev->esi[1],
+ dev->esi[2],
+ dev->esi[3],
+ dev->esi[4],
+ dev->esi[5]);
+ he_dev->atm_dev->link_rate = he_is622(he_dev) ?
+ ATM_OC12_PCR : ATM_OC3_PCR;
+
+ /* 4.6 set host endianess */
+ lb_swap = he_readl(he_dev, LB_SWAP);
+ if (he_is622(he_dev))
+ lb_swap &= ~XFER_SIZE; /* 4 cells */
+ else
+ lb_swap |= XFER_SIZE; /* 8 cells */
+#ifdef __BIG_ENDIAN
+ lb_swap |= DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST;
+#else
+ lb_swap &= ~(DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST |
+ DATA_WR_SWAP | DATA_RD_SWAP | DESC_RD_SWAP);
+#endif /* __BIG_ENDIAN */
+ he_writel(he_dev, lb_swap, LB_SWAP);
+
+ /* 4.8 sdram controller initialization */
+ he_writel(he_dev, he_is622(he_dev) ? LB_64_ENB : 0x0, SDRAM_CTL);
+
+ /* 4.9 initialize rnum value */
+ lb_swap |= SWAP_RNUM_MAX(0xf);
+ he_writel(he_dev, lb_swap, LB_SWAP);
+
+ /* 4.10 initialize the interrupt queues */
+ if ((err = he_init_irq(he_dev)) != 0) return err;
+
+#ifdef USE_TASKLET
+ tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev);
+#endif
+ spin_lock_init(&he_dev->global_lock);
+
+ /* 4.11 enable pci bus controller state machines */
+ host_cntl |= (OUTFF_ENB | CMDFF_ENB |
+ QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB);
+ he_writel(he_dev, host_cntl, HOST_CNTL);
+
+ gen_cntl_0 |= INT_PROC_ENBL|INIT_ENB;
+ pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
+
+ /*
+ * atm network controller initialization
+ */
+
+ /* 5.1.1 generic configuration state */
+
+ /*
+ * local (cell) buffer memory map
+ *
+ * HE155 HE622
+ *
+ * 0 ____________1023 bytes 0 _______________________2047 bytes
+ * | | | | |
+ * | utility | | rx0 | |
+ * 5|____________| 255|___________________| u |
+ * 6| | 256| | t |
+ * | | | | i |
+ * | rx0 | row | tx | l |
+ * | | | | i |
+ * | | 767|___________________| t |
+ * 517|____________| 768| | y |
+ * row 518| | | rx1 | |
+ * | | 1023|___________________|___|
+ * | |
+ * | tx |
+ * | |
+ * | |
+ * 1535|____________|
+ * 1536| |
+ * | rx1 |
+ * 2047|____________|
+ *
+ */
+
+ /* total 4096 connections */
+ he_dev->vcibits = CONFIG_DEFAULT_VCIBITS;
+ he_dev->vpibits = CONFIG_DEFAULT_VPIBITS;
+
+ if (nvpibits != -1 && nvcibits != -1 && nvpibits+nvcibits != HE_MAXCIDBITS)
+ {
+ hprintk("nvpibits + nvcibits != %d\n", HE_MAXCIDBITS);
+ return -ENODEV;
+ }
+
+ if (nvpibits != -1)
+ {
+ he_dev->vpibits = nvpibits;
+ he_dev->vcibits = HE_MAXCIDBITS - nvpibits;
+ }
+
+ if (nvcibits != -1)
+ {
+ he_dev->vcibits = nvcibits;
+ he_dev->vpibits = HE_MAXCIDBITS - nvcibits;
+ }
+
+
+ if (he_is622(he_dev))
+ {
+ he_dev->cells_per_row = 40;
+ he_dev->bytes_per_row = 2048;
+ he_dev->r0_numrows = 256;
+ he_dev->tx_numrows = 512;
+ he_dev->r1_numrows = 256;
+ he_dev->r0_startrow = 0;
+ he_dev->tx_startrow = 256;
+ he_dev->r1_startrow = 768;
+ }
+ else
+ {
+ he_dev->cells_per_row = 20;
+ he_dev->bytes_per_row = 1024;
+ he_dev->r0_numrows = 512;
+ he_dev->tx_numrows = 1018;
+ he_dev->r1_numrows = 512;
+ he_dev->r0_startrow = 6;
+ he_dev->tx_startrow = 518;
+ he_dev->r1_startrow = 1536;
+ }
+
+ he_dev->cells_per_lbuf = 4;
+ he_dev->buffer_limit = 4;
+ he_dev->r0_numbuffs = he_dev->r0_numrows *
+ he_dev->cells_per_row / he_dev->cells_per_lbuf;
+ if (he_dev->r0_numbuffs > 2560) he_dev->r0_numbuffs = 2560;
+
+ he_dev->r1_numbuffs = he_dev->r1_numrows *
+ he_dev->cells_per_row / he_dev->cells_per_lbuf;
+ if (he_dev->r1_numbuffs > 2560) he_dev->r1_numbuffs = 2560;
+
+ he_dev->tx_numbuffs = he_dev->tx_numrows *
+ he_dev->cells_per_row / he_dev->cells_per_lbuf;
+ if (he_dev->tx_numbuffs > 5120) he_dev->tx_numbuffs = 5120;
+
+ /* 5.1.2 configure hardware dependent registers */
+
+ he_writel(he_dev,
+ SLICE_X(0x2) | ARB_RNUM_MAX(0xf) | TH_PRTY(0x3) |
+ RH_PRTY(0x3) | TL_PRTY(0x2) | RL_PRTY(0x1) |
+ (he_is622(he_dev) ? BUS_MULTI(0x28) : BUS_MULTI(0x46)) |
+ (he_is622(he_dev) ? NET_PREF(0x50) : NET_PREF(0x8c)),
+ LBARB);
+
+ he_writel(he_dev, BANK_ON |
+ (he_is622(he_dev) ? (REF_RATE(0x384) | WIDE_DATA) : REF_RATE(0x150)),
+ SDRAMCON);
+
+ he_writel(he_dev,
+ (he_is622(he_dev) ? RM_BANK_WAIT(1) : RM_BANK_WAIT(0)) |
+ RM_RW_WAIT(1), RCMCONFIG);
+ he_writel(he_dev,
+ (he_is622(he_dev) ? TM_BANK_WAIT(2) : TM_BANK_WAIT(1)) |
+ TM_RW_WAIT(1), TCMCONFIG);
+
+ he_writel(he_dev, he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD, LB_CONFIG);
+
+ he_writel(he_dev,
+ (he_is622(he_dev) ? UT_RD_DELAY(8) : UT_RD_DELAY(0)) |
+ (he_is622(he_dev) ? RC_UT_MODE(0) : RC_UT_MODE(1)) |
+ RX_VALVP(he_dev->vpibits) |
+ RX_VALVC(he_dev->vcibits), RC_CONFIG);
+
+ he_writel(he_dev, DRF_THRESH(0x20) |
+ (he_is622(he_dev) ? TX_UT_MODE(0) : TX_UT_MODE(1)) |
+ TX_VCI_MASK(he_dev->vcibits) |
+ LBFREE_CNT(he_dev->tx_numbuffs), TX_CONFIG);
+
+ he_writel(he_dev, 0x0, TXAAL5_PROTO);
+
+ he_writel(he_dev, PHY_INT_ENB |
+ (he_is622(he_dev) ? PTMR_PRE(67-1) : PTMR_PRE(50-1)),
+ RH_CONFIG);
+
+ /* 5.1.3 initialize connection memory */
+
+ for(i=0; i < TCM_MEM_SIZE; ++i)
+ he_writel_tcm(he_dev, 0, i);
+
+ for(i=0; i < RCM_MEM_SIZE; ++i)
+ he_writel_rcm(he_dev, 0, i);
+
+ /*
+ * transmit connection memory map
+ *
+ * tx memory
+ * 0x0 ___________________
+ * | |
+ * | |
+ * | TSRa |
+ * | |
+ * | |
+ * 0x8000|___________________|
+ * | |
+ * | TSRb |
+ * 0xc000|___________________|
+ * | |
+ * | TSRc |
+ * 0xe000|___________________|
+ * | TSRd |
+ * 0xf000|___________________|
+ * | tmABR |
+ * 0x10000|___________________|
+ * | |
+ * | tmTPD |
+ * |___________________|
+ * | |
+ * ....
+ * 0x1ffff|___________________|
+ *
+ *
+ */
+
+ he_writel(he_dev, CONFIG_TSRB, TSRB_BA);
+ he_writel(he_dev, CONFIG_TSRC, TSRC_BA);
+ he_writel(he_dev, CONFIG_TSRD, TSRD_BA);
+ he_writel(he_dev, CONFIG_TMABR, TMABR_BA);
+ he_writel(he_dev, CONFIG_TPDBA, TPD_BA);
+
+
+ /*
+ * receive connection memory map
+ *
+ * 0x0 ___________________
+ * | |
+ * | |
+ * | RSRa |
+ * | |
+ * | |
+ * 0x8000|___________________|
+ * | |
+ * | rx0/1 |
+ * | LBM | link lists of local
+ * | tx | buffer memory
+ * | |
+ * 0xd000|___________________|
+ * | |
+ * | rmABR |
+ * 0xe000|___________________|
+ * | |
+ * | RSRb |
+ * |___________________|
+ * | |
+ * ....
+ * 0xffff|___________________|
+ */
+
+ he_writel(he_dev, 0x08000, RCMLBM_BA);
+ he_writel(he_dev, 0x0e000, RCMRSRB_BA);
+ he_writel(he_dev, 0x0d800, RCMABR_BA);
+
+ /* 5.1.4 initialize local buffer free pools linked lists */
+
+ he_init_rx_lbfp0(he_dev);
+ he_init_rx_lbfp1(he_dev);
+
+ he_writel(he_dev, 0x0, RLBC_H);
+ he_writel(he_dev, 0x0, RLBC_T);
+ he_writel(he_dev, 0x0, RLBC_H2);
+
+ he_writel(he_dev, 512, RXTHRSH); /* 10% of r0+r1 buffers */
+ he_writel(he_dev, 256, LITHRSH); /* 5% of r0+r1 buffers */
+
+ he_init_tx_lbfp(he_dev);
+
+ he_writel(he_dev, he_is622(he_dev) ? 0x104780 : 0x800, UBUFF_BA);
+
+ /* 5.1.5 initialize intermediate receive queues */
+
+ if (he_is622(he_dev))
+ {
+ he_writel(he_dev, 0x000f, G0_INMQ_S);
+ he_writel(he_dev, 0x200f, G0_INMQ_L);
+
+ he_writel(he_dev, 0x001f, G1_INMQ_S);
+ he_writel(he_dev, 0x201f, G1_INMQ_L);
+
+ he_writel(he_dev, 0x002f, G2_INMQ_S);
+ he_writel(he_dev, 0x202f, G2_INMQ_L);
+
+ he_writel(he_dev, 0x003f, G3_INMQ_S);
+ he_writel(he_dev, 0x203f, G3_INMQ_L);
+
+ he_writel(he_dev, 0x004f, G4_INMQ_S);
+ he_writel(he_dev, 0x204f, G4_INMQ_L);
+
+ he_writel(he_dev, 0x005f, G5_INMQ_S);
+ he_writel(he_dev, 0x205f, G5_INMQ_L);
+
+ he_writel(he_dev, 0x006f, G6_INMQ_S);
+ he_writel(he_dev, 0x206f, G6_INMQ_L);
+
+ he_writel(he_dev, 0x007f, G7_INMQ_S);
+ he_writel(he_dev, 0x207f, G7_INMQ_L);
+ }
+ else
+ {
+ he_writel(he_dev, 0x0000, G0_INMQ_S);
+ he_writel(he_dev, 0x0008, G0_INMQ_L);
+
+ he_writel(he_dev, 0x0001, G1_INMQ_S);
+ he_writel(he_dev, 0x0009, G1_INMQ_L);
+
+ he_writel(he_dev, 0x0002, G2_INMQ_S);
+ he_writel(he_dev, 0x000a, G2_INMQ_L);
+
+ he_writel(he_dev, 0x0003, G3_INMQ_S);
+ he_writel(he_dev, 0x000b, G3_INMQ_L);
+
+ he_writel(he_dev, 0x0004, G4_INMQ_S);
+ he_writel(he_dev, 0x000c, G4_INMQ_L);
+
+ he_writel(he_dev, 0x0005, G5_INMQ_S);
+ he_writel(he_dev, 0x000d, G5_INMQ_L);
+
+ he_writel(he_dev, 0x0006, G6_INMQ_S);
+ he_writel(he_dev, 0x000e, G6_INMQ_L);
+
+ he_writel(he_dev, 0x0007, G7_INMQ_S);
+ he_writel(he_dev, 0x000f, G7_INMQ_L);
+ }
+
+ /* 5.1.6 application tunable parameters */
+
+ he_writel(he_dev, 0x0, MCC);
+ he_writel(he_dev, 0x0, OEC);
+ he_writel(he_dev, 0x0, DCC);
+ he_writel(he_dev, 0x0, CEC);
+
+ /* 5.1.7 cs block initialization */
+
+ he_init_cs_block(he_dev);
+
+ /* 5.1.8 cs block connection memory initialization */
+
+ he_init_cs_block_rcm(he_dev);
+
+ /* 5.1.10 initialize host structures */
+
+ he_init_tpdrq(he_dev);
+
+#ifdef USE_TPD_POOL
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
+ he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev,
+ sizeof(struct he_tpd), TPD_ALIGNMENT, 0, SLAB_KERNEL);
+#else
+ he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev,
+ sizeof(struct he_tpd), TPD_ALIGNMENT, 0);
+#endif
+ if (he_dev->tpd_pool == NULL)
+ {
+ hprintk1("unable to create tpd pci_pool\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&he_dev->outstanding_tpds);
+#else
+ he_dev->tpd_base = (void *) pci_alloc_consistent(he_dev->pci_dev,
+ CONFIG_NUMTPDS * sizeof(struct he_tpd), &he_dev->tpd_base_phys);
+ if (!he_dev->tpd_base)
+ return -ENOMEM;
+
+ for(i = 0; i < CONFIG_NUMTPDS; ++i)
+ {
+ he_dev->tpd_base[i].status = (i << TPD_ADDR_SHIFT);
+ he_dev->tpd_base[i].inuse = 0;
+ }
+
+ he_dev->tpd_head = he_dev->tpd_base;
+ he_dev->tpd_end = &he_dev->tpd_base[CONFIG_NUMTPDS-1];
+#endif
+
+ if (he_init_group(he_dev, 0) != 0)
+ return -ENOMEM;
+
+ for (group = 1; group < HE_NUM_GROUPS; ++group)
+ {
+ he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));
+ he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));
+ he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));
+ he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
+ G0_RBPS_BS + (group * 32));
+
+ he_writel(he_dev, 0x0, G0_RBPL_S + (group * 32));
+ he_writel(he_dev, 0x0, G0_RBPL_T + (group * 32));
+ he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
+ G0_RBPL_QI + (group * 32));
+ he_writel(he_dev, 0x0, G0_RBPL_BS + (group * 32));
+
+ he_writel(he_dev, 0x0, G0_RBRQ_ST + (group * 16));
+ he_writel(he_dev, 0x0, G0_RBRQ_H + (group * 16));
+ he_writel(he_dev, RBRQ_THRESH(0x1) | RBRQ_SIZE(0x0),
+ G0_RBRQ_Q + (group * 16));
+ he_writel(he_dev, 0x0, G0_RBRQ_I + (group * 16));
+
+ he_writel(he_dev, 0x0, G0_TBRQ_B_T + (group * 16));
+ he_writel(he_dev, 0x0, G0_TBRQ_H + (group * 16));
+ he_writel(he_dev, TBRQ_THRESH(0x1),
+ G0_TBRQ_THRESH + (group * 16));
+ he_writel(he_dev, 0x0, G0_TBRQ_S + (group * 16));
+ }
+
+ /* host status page */
+
+ he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev,
+ sizeof(struct he_hsp), &he_dev->hsp_phys);
+ if (he_dev->hsp == NULL)
+ {
+ hprintk1("failed to allocate host status page\n");
+ return -ENOMEM;
+ }
+ memset(he_dev->hsp, 0, sizeof(struct he_hsp));
+ he_writel(he_dev, he_dev->hsp_phys, HSP_BA);
+
+ /* initialize framer */
+
+#ifdef CONFIG_ATM_HE_USE_SUNI
+ suni_init(he_dev->atm_dev);
+ if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->start)
+ he_dev->atm_dev->phy->start(he_dev->atm_dev);
+#endif /* CONFIG_ATM_HE_USE_SUNI */
+
+ if (sdh)
+ {
+ /* this really should be in suni.c but for now... */
+
+ int val;
+
+ val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM);
+ val = (val & ~SUNI_TPOP_APM_S) | ( 0x2 << SUNI_TPOP_APM_S_SHIFT);
+ he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM);
+ }
+
+ /* 5.1.12 enable transmit and receive */
+
+ reg = he_readl_mbox(he_dev, CS_ERCTL0);
+ reg |= TX_ENABLE|ER_ENABLE;
+ he_writel_mbox(he_dev, reg, CS_ERCTL0);
+
+ reg = he_readl(he_dev, RC_CONFIG);
+ reg |= RX_ENABLE;
+ he_writel(he_dev, reg, RC_CONFIG);
+
+#ifndef USE_HE_FIND_VCC
+ he_dev->he_vcc_table = kmalloc(sizeof(struct he_vcc_table) *
+ (1 << (he_dev->vcibits + he_dev->vpibits)), GFP_KERNEL);
+ if (he_dev->he_vcc_table == NULL)
+ {
+ hprintk1("failed to alloc he_vcc_table\n");
+ return -ENOMEM;
+ }
+ memset(he_dev->he_vcc_table, 0, sizeof(struct he_vcc_table) *
+ (1 << (he_dev->vcibits + he_dev->vpibits)));
+#endif
+
+ for (i = 0; i < HE_NUM_CS_STPER; ++i)
+ {
+ he_dev->cs_stper[i].inuse = 0;
+ he_dev->cs_stper[i].pcr = -1;
+ }
+ he_dev->total_bw = 0;
+
+
+ /* atm linux initialization */
+
+ he_dev->atm_dev->ci_range.vpi_bits = he_dev->vpibits;
+ he_dev->atm_dev->ci_range.vci_bits = he_dev->vcibits;
+
+ he_dev->irq_peak = 0;
+ he_dev->rbrq_peak = 0;
+ he_dev->rbpl_peak = 0;
+ he_dev->tbrq_peak = 0;
+
+ HPRINTK("hell bent for leather!\n");
+
+ return 0;
+}
+
+static void
+he_stop(struct he_dev *he_dev)
+{
+ u16 command;
+ u32 gen_cntl_0, reg;
+ struct pci_dev *pci_dev;
+
+ pci_dev = he_dev->pci_dev;
+
+ /* disable interrupts */
+
+ if (he_dev->membase)
+ {
+ pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0);
+ gen_cntl_0 &= ~(INT_PROC_ENBL | INIT_ENB);
+ pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0);
+
+#ifdef USE_TASKLET
+ tasklet_disable(&he_dev->tasklet);
+#endif
+
+ /* disable recv and transmit */
+
+ reg = he_readl_mbox(he_dev, CS_ERCTL0);
+ reg &= ~(TX_ENABLE|ER_ENABLE);
+ he_writel_mbox(he_dev, reg, CS_ERCTL0);
+
+ reg = he_readl(he_dev, RC_CONFIG);
+ reg &= ~(RX_ENABLE);
+ he_writel(he_dev, reg, RC_CONFIG);
+ }
+
+#ifdef CONFIG_ATM_HE_USE_SUNI
+ if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->stop)
+ he_dev->atm_dev->phy->stop(he_dev->atm_dev);
+#endif /* CONFIG_ATM_HE_USE_SUNI */
+
+ if (he_dev->irq)
+ {
+#ifdef BUS_INT_WAR
+ sn_delete_polled_interrupt(he_dev->irq);
+#endif
+ free_irq(he_dev->irq, he_dev);
+ }
+
+ if (he_dev->irq_base)
+ pci_free_consistent(he_dev->pci_dev, (CONFIG_IRQ_SIZE+1)
+ * sizeof(struct he_irq), he_dev->irq_base, he_dev->irq_phys);
+
+ if (he_dev->hsp)
+ pci_free_consistent(he_dev->pci_dev, sizeof(struct he_hsp),
+ he_dev->hsp, he_dev->hsp_phys);
+
+ if (he_dev->rbpl_base)
+ {
+#ifdef USE_RBPL_POOL
+ for (i=0; i<CONFIG_RBPL_SIZE; ++i)
+ {
+ void *cpuaddr = he_dev->rbpl_virt[i].virt;
+ dma_addr_t dma_handle = he_dev->rbpl_base[i].phys;
+
+ pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle);
+ }
+#else
+ pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE
+ * CONFIG_RBPL_BUFSIZE, he_dev->rbpl_pages, he_dev->rbpl_pages_phys);
+#endif
+ pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE
+ * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys);
+ }
+
+#ifdef USE_RBPL_POOL
+ if (he_dev->rbpl_pool)
+ pci_pool_destroy(he_dev->rbpl_pool);
+#endif
+
+#ifdef USE_RBPS
+ if (he_dev->rbps_base)
+ {
+#ifdef USE_RBPS_POOL
+ for (i=0; i<CONFIG_RBPS_SIZE; ++i)
+ {
+ void *cpuaddr = he_dev->rbps_virt[i].virt;
+ dma_addr_t dma_handle = he_dev->rbps_base[i].phys;
+
+ pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle);
+ }
+#else
+ pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE
+ * CONFIG_RBPS_BUFSIZE, he_dev->rbps_pages, he_dev->rbps_pages_phys);
+#endif
+ pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE
+ * sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys);
+ }
+
+#ifdef USE_RBPS_POOL
+ if (he_dev->rbps_pool)
+ pci_pool_destroy(he_dev->rbps_pool);
+#endif
+
+#endif /* USE_RBPS */
+
+ if (he_dev->rbrq_base)
+ pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
+ he_dev->rbrq_base, he_dev->rbrq_phys);
+
+ if (he_dev->tbrq_base)
+ pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
+ he_dev->tbrq_base, he_dev->tbrq_phys);
+
+ if (he_dev->tpdrq_base)
+ pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
+ he_dev->tpdrq_base, he_dev->tpdrq_phys);
+
+#ifdef USE_TPD_POOL
+ if (he_dev->tpd_pool)
+ pci_pool_destroy(he_dev->tpd_pool);
+#else
+ if (he_dev->tpd_base)
+ pci_free_consistent(he_dev->pci_dev, CONFIG_NUMTPDS * sizeof(struct he_tpd),
+ he_dev->tpd_base, he_dev->tpd_base_phys);
+#endif
+
+#ifndef USE_HE_FIND_VCC
+ if (he_dev->he_vcc_table)
+ kfree(he_dev->he_vcc_table);
+#endif
+
+ if (he_dev->pci_dev)
+ {
+ pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command);
+ command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_write_config_word(he_dev->pci_dev, PCI_COMMAND, command);
+ }
+
+ if (he_dev->membase) iounmap((void *) he_dev->membase);
+}
+
+static struct he_tpd *
+__alloc_tpd(struct he_dev *he_dev)
+{
+#ifdef USE_TPD_POOL
+ struct he_tpd *tpd;
+ dma_addr_t dma_handle;
+
+ tpd = pci_pool_alloc(he_dev->tpd_pool, SLAB_ATOMIC|SLAB_DMA, &dma_handle);
+ if (tpd == NULL)
+ return NULL;
+
+ tpd->status = TPD_ADDR(dma_handle);
+ tpd->reserved = 0;
+ tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0;
+ tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0;
+ tpd->iovec[2].addr = 0; tpd->iovec[2].len = 0;
+
+ return tpd;
+#else
+ int i;
+
+ for(i = 0; i < CONFIG_NUMTPDS; ++i)
+ {
+ ++he_dev->tpd_head;
+ if (he_dev->tpd_head > he_dev->tpd_end) {
+ he_dev->tpd_head = he_dev->tpd_base;
+ }
+
+ if (!he_dev->tpd_head->inuse) {
+ he_dev->tpd_head->inuse = 1;
+ he_dev->tpd_head->status &= TPD_MASK;
+ he_dev->tpd_head->iovec[0].addr = 0; he_dev->tpd_head->iovec[0].len = 0;
+ he_dev->tpd_head->iovec[1].addr = 0; he_dev->tpd_head->iovec[1].len = 0;
+ he_dev->tpd_head->iovec[2].addr = 0; he_dev->tpd_head->iovec[2].len = 0;
+ return he_dev->tpd_head;
+ }
+ }
+ hprintk("out of tpds -- increase CONFIG_NUMTPDS (%d)\n", CONFIG_NUMTPDS);
+ return NULL;
+#endif
+}
+
+#define AAL5_LEN(buf,len) \
+ ((((unsigned char *)(buf))[(len)-6]<<8) | \
+ (((unsigned char *)(buf))[(len)-5]))
+
+/* 2.10.1.2 receive
+ *
+ * aal5 packets can optionally return the tcp checksum in the lower
+ * 16 bits of the crc (RSR0_TCP_CKSUM)
+ */
+
+#define TCP_CKSUM(buf,len) \
+ ((((unsigned char *)(buf))[(len)-2]<<8) | \
+ (((unsigned char *)(buf))[(len-1)]))
+
+static int
+he_service_rbrq(struct he_dev *he_dev, int group)
+{
+ struct he_rbrq *rbrq_tail = (struct he_rbrq *)
+ ((unsigned long)he_dev->rbrq_base |
+ he_dev->hsp->group[group].rbrq_tail);
+ struct he_rbp *rbp = NULL;
+ unsigned cid, lastcid = -1;
+ unsigned buf_len = 0;
+ struct sk_buff *skb;
+ struct atm_vcc *vcc = NULL;
+ struct he_vcc *he_vcc;
+ struct iovec *iov;
+ int pdus_assembled = 0;
+ int updated = 0;
+
+ while (he_dev->rbrq_head != rbrq_tail)
+ {
+ ++updated;
+
+ HPRINTK("%p rbrq%d 0x%x len=%d cid=0x%x %s%s%s%s%s%s\n",
+ he_dev->rbrq_head, group,
+ RBRQ_ADDR(he_dev->rbrq_head),
+ RBRQ_BUFLEN(he_dev->rbrq_head),
+ RBRQ_CID(he_dev->rbrq_head),
+ RBRQ_CRC_ERR(he_dev->rbrq_head) ? " CRC_ERR" : "",
+ RBRQ_LEN_ERR(he_dev->rbrq_head) ? " LEN_ERR" : "",
+ RBRQ_END_PDU(he_dev->rbrq_head) ? " END_PDU" : "",
+ RBRQ_AAL5_PROT(he_dev->rbrq_head) ? " AAL5_PROT" : "",
+ RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "",
+ RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : "");
+
+#ifdef USE_RBPS
+ if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF)
+ rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
+ else
+#endif
+ rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
+
+ buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4;
+ cid = RBRQ_CID(he_dev->rbrq_head);
+
+#ifdef USE_HE_FIND_VCC
+ if (cid != lastcid)
+ vcc = he_find_vcc(he_dev, cid);
+ lastcid = cid;
+#else
+ vcc = HE_LOOKUP_VCC(he_dev, cid);
+#endif
+ if (vcc == NULL)
+ {
+ hprintk("vcc == NULL (cid 0x%x)\n", cid);
+ if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))
+ rbp->status &= ~RBP_LOANED;
+
+ goto next_rbrq_entry;
+ }
+
+ he_vcc = HE_VCC(vcc);
+ if (he_vcc == NULL)
+ {
+ hprintk("he_vcc == NULL (cid 0x%x)\n", cid);
+ if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))
+ rbp->status &= ~RBP_LOANED;
+ goto next_rbrq_entry;
+ }
+
+ if (RBRQ_HBUF_ERR(he_dev->rbrq_head))
+ {
+ hprintk("HBUF_ERR! (cid 0x%x)\n", cid);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+ ++vcc->stats->rx_drop;
+#else
+ atomic_inc(&vcc->stats->rx_drop);
+#endif
+ goto return_host_buffers;
+ }
+
+ he_vcc->iov_tail->iov_base = (void *) RBRQ_ADDR(he_dev->rbrq_head);
+ he_vcc->iov_tail->iov_len = buf_len;
+ he_vcc->pdu_len += buf_len;
+ ++he_vcc->iov_tail;
+
+ if (RBRQ_CON_CLOSED(he_dev->rbrq_head))
+ {
+ lastcid = -1;
+ HPRINTK("wake_up rx_waitq (cid 0x%x)\n", cid);
+ wake_up(&he_vcc->rx_waitq);
+ goto return_host_buffers;
+ }
+
+#ifdef notdef
+ if (he_vcc->iov_tail - he_vcc->iov_head > 32)
+ {
+ hprintk("iovec full! cid 0x%x\n", cid);
+ goto return_host_buffers;
+ }
+#endif
+ if (!RBRQ_END_PDU(he_dev->rbrq_head)) goto next_rbrq_entry;
+
+ if (RBRQ_LEN_ERR(he_dev->rbrq_head)
+ || RBRQ_CRC_ERR(he_dev->rbrq_head))
+ {
+ HPRINTK("%s%s (%d.%d)\n",
+ RBRQ_CRC_ERR(he_dev->rbrq_head)
+ ? "CRC_ERR " : "",
+ RBRQ_LEN_ERR(he_dev->rbrq_head)
+ ? "LEN_ERR" : "",
+ vcc->vpi, vcc->vci);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+ ++vcc->stats->rx_err;
+#else
+ atomic_inc(&vcc->stats->rx_err);
+#endif
+ goto return_host_buffers;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,15)
+ skb = atm_alloc_charge(vcc, he_vcc->pdu_len + rx_skb_reserve,
+ GFP_ATOMIC);
+#else
+ if (!atm_charge(vcc, atm_pdu2truesize(he_vcc->pdu_len + rx_skb_reserve)))
+ skb = NULL;
+ else
+ {
+ skb = alloc_skb(he_vcc->pdu_len + rx_skb_reserve, GFP_ATOMIC);
+ if (!skb) atm_return(vcc,
+ atm_pdu2truesize(he_vcc->pdu_len + rx_skb_reserve));
+ }
+#endif
+ if (!skb)
+ {
+ HPRINTK("charge failed (%d.%d)\n", vcc->vpi, vcc->vci);
+ goto return_host_buffers;
+ }
+
+ if (rx_skb_reserve > 0) skb_reserve(skb, rx_skb_reserve);
+
+ do_gettimeofday(&skb->stamp);
+
+ for(iov = he_vcc->iov_head;
+ iov < he_vcc->iov_tail; ++iov)
+ {
+#ifdef USE_RBPS
+ if ((u32)iov->iov_base & RBP_SMALLBUF)
+ memcpy(skb_put(skb, iov->iov_len),
+ he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);
+ else
+#endif
+ memcpy(skb_put(skb, iov->iov_len),
+ he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);
+ }
+
+ switch(vcc->qos.aal)
+ {
+ case ATM_AAL0:
+ /* 2.10.1.5 raw cell receive */
+ skb->len = ATM_AAL0_SDU;
+ skb->tail = skb->data + skb->len;
+ break;
+ case ATM_AAL5:
+ /* 2.10.1.2 aal5 receive */
+
+ skb->len = AAL5_LEN(skb->data, he_vcc->pdu_len);
+ skb->tail = skb->data + skb->len;
+#ifdef USE_CHECKSUM_HW
+ if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI)
+ {
+ skb->ip_summed = CHECKSUM_HW;
+ skb->csum = TCP_CKSUM(skb->data,
+ he_vcc->pdu_len);
+ }
+#endif
+ break;
+ }
+
+#ifdef should_never_happen
+ if (skb->len > vcc->qos.rxtp.max_sdu)
+ hprintk("pdu_len (%d) > vcc->qos.rxtp.max_sdu (%d)! cid 0x%x\n", skb->len, vcc->qos.rxtp.max_sdu, cid);
+#endif
+
+#ifdef notdef
+ ATM_SKB(skb)->vcc = vcc;
+#endif
+ vcc->push(vcc, skb);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+ ++vcc->stats->rx;
+#else
+ atomic_inc(&vcc->stats->rx);
+#endif
+
+return_host_buffers:
+ ++pdus_assembled;
+
+ for(iov = he_vcc->iov_head;
+ iov < he_vcc->iov_tail; ++iov)
+ {
+#ifdef USE_RBPS
+ if ((u32)iov->iov_base & RBP_SMALLBUF)
+ rbp = &he_dev->rbps_base[RBP_INDEX(iov->iov_base)];
+ else
+#endif
+ rbp = &he_dev->rbpl_base[RBP_INDEX(iov->iov_base)];
+
+ rbp->status &= ~RBP_LOANED;
+ }
+
+ he_vcc->iov_tail = he_vcc->iov_head;
+ he_vcc->pdu_len = 0;
+
+next_rbrq_entry:
+ he_dev->rbrq_head = (struct he_rbrq *)
+ ((unsigned long) he_dev->rbrq_base |
+ RBRQ_MASK(++he_dev->rbrq_head));
+
+ }
+
+ if (updated)
+ {
+ if (updated > he_dev->rbrq_peak) he_dev->rbrq_peak = updated;
+
+ he_writel(he_dev, RBRQ_MASK(he_dev->rbrq_head),
+ G0_RBRQ_H + (group * 16));
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl(he_dev, G0_RBRQ_H + (group * 16));
+#endif
+ }
+
+ return pdus_assembled;
+}
+
+static void
+he_service_tbrq(struct he_dev *he_dev, int group)
+{
+ struct he_tbrq *tbrq_tail = (struct he_tbrq *)
+ ((unsigned long)he_dev->tbrq_base |
+ he_dev->hsp->group[group].tbrq_tail);
+ struct he_tpd *tpd;
+ int slot, updated = 0;
+#ifdef USE_TPD_POOL
+ struct list_head *p;
+#endif
+
+ /* 2.1.6 transmit buffer return queue */
+
+ while (he_dev->tbrq_head != tbrq_tail)
+ {
+ ++updated;
+
+ HPRINTK("tbrq%d 0x%x%s%s\n",
+ group,
+ TBRQ_TPD(he_dev->tbrq_head),
+ TBRQ_EOS(he_dev->tbrq_head) ? " EOS" : "",
+ TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : "");
+#ifdef USE_TPD_POOL
+ tpd = NULL;
+ p = &he_dev->outstanding_tpds;
+ while ((p = p->next) != &he_dev->outstanding_tpds)
+ {
+ struct he_tpd *__tpd = list_entry(p, struct he_tpd, entry);
+ if (TPD_ADDR(__tpd->status) == TBRQ_TPD(he_dev->tbrq_head))
+ {
+ tpd = __tpd;
+ list_del(&__tpd->entry);
+ break;
+ }
+ }
+
+ if (tpd == NULL)
+ {
+ hprintk("unable to locate tpd for dma buffer %x\n",
+ TBRQ_TPD(he_dev->tbrq_head));
+ goto next_tbrq_entry;
+ }
+#else
+ tpd = &he_dev->tpd_base[ TPD_INDEX(TBRQ_TPD(he_dev->tbrq_head)) ];
+#endif
+
+ if (TBRQ_EOS(he_dev->tbrq_head))
+ {
+ HPRINTK("wake_up(tx_waitq) cid 0x%x\n",
+ he_mkcid(he_dev, tpd->vcc->vpi, tpd->vcc->vci));
+ if (tpd->vcc)
+ wake_up(&HE_VCC(tpd->vcc)->tx_waitq);
+
+ goto next_tbrq_entry;
+ }
+
+ for(slot = 0; slot < TPD_MAXIOV; ++slot)
+ {
+ if (tpd->iovec[slot].addr)
+ pci_unmap_single(he_dev->pci_dev,
+ tpd->iovec[slot].addr,
+ tpd->iovec[slot].len & TPD_LEN_MASK,
+ PCI_DMA_TODEVICE);
+ if (tpd->iovec[slot].len & TPD_LST) break;
+
+ }
+
+ if (tpd->skb) /* && !TBRQ_MULTIPLE(he_dev->tbrq_head) */
+ {
+ if (tpd->vcc && tpd->vcc->pop)
+ tpd->vcc->pop(tpd->vcc, tpd->skb);
+ else
+ dev_kfree_skb_any(tpd->skb);
+ }
+
+next_tbrq_entry:
+#ifdef USE_TPD_POOL
+ if (tpd) pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
+#else
+ tpd->inuse = 0;
+#endif
+ he_dev->tbrq_head = (struct he_tbrq *)
+ ((unsigned long) he_dev->tbrq_base |
+ TBRQ_MASK(++he_dev->tbrq_head));
+ }
+
+ if (updated)
+ {
+ if (updated > he_dev->tbrq_peak) he_dev->tbrq_peak = updated;
+
+ he_writel(he_dev, TBRQ_MASK(he_dev->tbrq_head),
+ G0_TBRQ_H + (group * 16));
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl(he_dev, G0_TBRQ_H + (group * 16));
+#endif
+ }
+}
+
+
+static void
+he_service_rbpl(struct he_dev *he_dev, int group)
+{
+ struct he_rbp *newtail;
+ struct he_rbp *rbpl_head;
+ int moved = 0;
+
+ rbpl_head = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
+ RBPL_MASK(he_readl(he_dev, G0_RBPL_S)));
+
+ for(;;)
+ {
+ newtail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
+ RBPL_MASK(he_dev->rbpl_tail+1));
+
+ /* table 3.42 -- rbpl_tail should never be set to rbpl_head */
+ if ((newtail == rbpl_head) || (newtail->status & RBP_LOANED))
+ break;
+
+ newtail->status |= RBP_LOANED;
+ he_dev->rbpl_tail = newtail;
+ ++moved;
+
+ }
+
+ if (moved) {
+ he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T);
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl(he_dev, G0_RBPL_T);
+#endif
+ }
+}
+
+#ifdef USE_RBPS
+static void
+he_service_rbps(struct he_dev *he_dev, int group)
+{
+ struct he_rbp *newtail;
+ struct he_rbp *rbps_head;
+ int moved = 0;
+
+ rbps_head = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
+ RBPS_MASK(he_readl(he_dev, G0_RBPS_S)));
+
+ for(;;)
+ {
+ newtail = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
+ RBPS_MASK(he_dev->rbps_tail+1));
+
+ /* table 3.42 -- rbps_tail should never be set to rbps_head */
+ if ((newtail == rbps_head) || (newtail->status & RBP_LOANED))
+ break;
+
+ newtail->status |= RBP_LOANED;
+ he_dev->rbps_tail = newtail;
+ ++moved;
+
+ }
+
+ if (moved) {
+ he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T);
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl(he_dev, G0_RBPS_T);
+#endif
+ }
+}
+#endif /* USE_RBPS */
+
+static void
+he_tasklet(unsigned long data)
+{
+ unsigned long flags;
+ struct he_dev *he_dev = (struct he_dev *) data;
+ int group, type;
+ int updated = 0;
+
+ HPRINTK("tasklet (0x%lx)\n", data);
+#ifdef USE_TASKLET
+ HE_SPIN_LOCK(he_dev, flags);
+#endif
+
+ while(he_dev->irq_head != he_dev->irq_tail)
+ {
+ ++updated;
+
+ type = ITYPE_TYPE(he_dev->irq_head->isw);
+ group = ITYPE_GROUP(he_dev->irq_head->isw);
+
+ switch (type)
+ {
+ case ITYPE_RBRQ_THRESH:
+ hprintk("rbrq%d threshold\n", group);
+ case ITYPE_RBRQ_TIMER:
+ if (he_service_rbrq(he_dev, group))
+ {
+ he_service_rbpl(he_dev, group);
+#ifdef USE_RBPS
+ he_service_rbps(he_dev, group);
+#endif /* USE_RBPS */
+ }
+ break;
+ case ITYPE_TBRQ_THRESH:
+ hprintk("tbrq%d threshold\n", group);
+ case ITYPE_TPD_COMPLETE:
+ he_service_tbrq(he_dev, group);
+ break;
+ case ITYPE_RBPL_THRESH:
+ he_service_rbpl(he_dev, group);
+ break;
+ case ITYPE_RBPS_THRESH:
+#ifdef USE_RBPS
+ he_service_rbps(he_dev, group);
+#endif /* USE_RBPS */
+ break;
+ case ITYPE_PHY:
+#ifdef CONFIG_ATM_HE_USE_SUNI
+ HE_SPIN_UNLOCK(he_dev, flags);
+ if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->interrupt)
+ he_dev->atm_dev->phy->interrupt(he_dev->atm_dev);
+ HE_SPIN_LOCK(he_dev, flags);
+#endif
+ HPRINTK1("phy interrupt\n");
+ break;
+ case ITYPE_OTHER:
+ switch (type|group)
+ {
+ case ITYPE_PARITY:
+ hprintk1("parity error\n");
+ break;
+ case ITYPE_ABORT:
+ hprintk("abort 0x%x\n", he_readl(he_dev, ABORT_ADDR));
+ break;
+ }
+ break;
+ default:
+ if (he_dev->irq_head->isw == ITYPE_INVALID)
+ {
+ /* see 8.1.1 -- check all queues */
+
+ HPRINTK("isw not updated 0x%x\n",
+ he_dev->irq_head->isw);
+
+ he_service_rbrq(he_dev, 0);
+ he_service_rbpl(he_dev, 0);
+#ifdef USE_RBPS
+ he_service_rbps(he_dev, 0);
+#endif /* USE_RBPS */
+ he_service_tbrq(he_dev, 0);
+ }
+ else
+ hprintk("bad isw = 0x%x?\n",
+ he_dev->irq_head->isw);
+ }
+
+ he_dev->irq_head->isw = ITYPE_INVALID;
+
+ he_dev->irq_head = (struct he_irq *) NEXT_ENTRY(he_dev->irq_base, he_dev->irq_head, IRQ_MASK);
+ }
+
+ if (updated)
+ {
+ if (updated > he_dev->irq_peak) he_dev->irq_peak = updated;
+
+ he_writel(he_dev,
+ IRQ_SIZE(CONFIG_IRQ_SIZE) |
+ IRQ_THRESH(CONFIG_IRQ_THRESH) |
+ IRQ_TAIL(he_dev->irq_tail), IRQ0_HEAD);
+ (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */
+ }
+#ifdef USE_TASKLET
+ HE_SPIN_UNLOCK(he_dev, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69)
+static irqreturn_t
+#else
+static void
+#endif
+he_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long flags;
+ struct he_dev *he_dev = (struct he_dev * )dev_id;
+ int handled = 0;
+
+ if (he_dev == NULL)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69)
+ return IRQ_NONE;
+#else
+ return;
+#endif
+
+ HE_SPIN_LOCK(he_dev, flags);
+
+ he_dev->irq_tail = (struct he_irq *) (((unsigned long)he_dev->irq_base) |
+ (*he_dev->irq_tailoffset << 2));
+
+ if (he_dev->irq_tail == he_dev->irq_head)
+ {
+ HPRINTK1("tailoffset not updated?\n");
+ he_dev->irq_tail = (struct he_irq *) ((unsigned long)he_dev->irq_base |
+ ((he_readl(he_dev, IRQ0_BASE) & IRQ_MASK) << 2));
+ (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */
+ }
+
+#ifdef DEBUG
+ if (he_dev->irq_head == he_dev->irq_tail /* && !IRQ_PENDING */)
+ hprintk1("spurious (or shared) interrupt?\n");
+#endif
+
+ if (he_dev->irq_head != he_dev->irq_tail)
+ {
+ handled = 1;
+#ifdef USE_TASKLET
+ tasklet_schedule(&he_dev->tasklet);
+#else
+ he_tasklet((unsigned long) he_dev);
+#endif
+ he_writel(he_dev, INT_CLEAR_A, INT_FIFO);
+ /* clear interrupt */
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl(he_dev, INT_FIFO);
+#endif
+ }
+ HE_SPIN_UNLOCK(he_dev, flags);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69)
+ return IRQ_RETVAL(handled);
+#else
+ return;
+#endif
+
+}
+
+static __inline__ void
+__enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid)
+{
+ struct he_tpdrq *new_tail;
+
+ HPRINTK("tpdrq %p cid 0x%x -> tpdrq_tail %p\n",
+ tpd, cid, he_dev->tpdrq_tail);
+
+ /* new_tail = he_dev->tpdrq_tail; */
+ new_tail = (struct he_tpdrq *) ((unsigned long) he_dev->tpdrq_base |
+ TPDRQ_MASK(he_dev->tpdrq_tail+1));
+
+ /*
+ * check to see if we are about to set the tail == head
+ * if true, update the head pointer from the adapter
+ * to see if this is really the case (reading the queue
+ * head for every enqueue would be unnecessarily slow)
+ */
+
+ if (new_tail == he_dev->tpdrq_head)
+ {
+ he_dev->tpdrq_head = (struct he_tpdrq *)
+ (((unsigned long)he_dev->tpdrq_base) |
+ TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H)));
+
+ if (new_tail == he_dev->tpdrq_head)
+ {
+ hprintk("tpdrq full (cid 0x%x)\n", cid);
+ /*
+ * FIXME
+ * push tpd onto a transmit backlog queue
+ * after service_tbrq, service the backlog
+ * for now, we just drop the pdu
+ */
+ if (tpd->skb)
+ {
+ if (tpd->vcc->pop)
+ tpd->vcc->pop(tpd->vcc, tpd->skb);
+ else
+ dev_kfree_skb_any(tpd->skb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+ ++tpd->vcc->stats->tx_err;
+#else
+ atomic_inc(&tpd->vcc->stats->tx_err);
+#endif
+ }
+#ifdef USE_TPD_POOL
+ pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
+#else
+ tpd->inuse = 0;
+#endif
+ return;
+ }
+ }
+
+ /* 2.1.5 transmit packet descriptor ready queue */
+#ifdef USE_TPD_POOL
+ list_add_tail(&tpd->entry, &he_dev->outstanding_tpds);
+ he_dev->tpdrq_tail->tpd = TPD_ADDR(tpd->status);
+#else
+ he_dev->tpdrq_tail->tpd = he_dev->tpd_base_phys +
+ (TPD_INDEX(tpd->status) * sizeof(struct he_tpd));
+#endif
+ he_dev->tpdrq_tail->cid = cid;
+ wmb();
+
+ he_dev->tpdrq_tail = new_tail;
+
+ he_writel(he_dev, TPDRQ_MASK(he_dev->tpdrq_tail), TPDRQ_T);
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl(he_dev, TPDRQ_T);
+#endif
+}
+
+static int
+he_open(struct atm_vcc *vcc, short vpi, int vci)
+{
+ unsigned long flags;
+ struct he_dev *he_dev = HE_DEV(vcc->dev);
+ struct he_vcc *he_vcc;
+ int err = 0;
+ unsigned cid, rsr0, rsr1, rsr4, tsr0, tsr0_aal, tsr4, period, reg, clock;
+
+
+ if ((err = atm_find_ci(vcc, &vpi, &vci)))
+ {
+ HPRINTK("atm_find_ci err = %d\n", err);
+ return err;
+ }
+ if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) return 0;
+ vcc->vpi = vpi;
+ vcc->vci = vci;
+
+ HPRINTK("open vcc %p %d.%d\n", vcc, vpi, vci);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+ vcc->flags |= ATM_VF_ADDR;
+#else
+ set_bit(ATM_VF_ADDR, &vcc->flags);
+#endif
+
+ cid = he_mkcid(he_dev, vpi, vci);
+
+ he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_ATOMIC);
+ if (he_vcc == NULL)
+ {
+ hprintk1("unable to allocate he_vcc during open\n");
+ return -ENOMEM;
+ }
+
+ he_vcc->iov_tail = he_vcc->iov_head;
+ he_vcc->pdu_len = 0;
+ he_vcc->rc_index = -1;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+ init_waitqueue(&he_vcc->rx_waitq);
+ init_waitqueue(&he_vcc->tx_waitq);
+#else
+ init_waitqueue_head(&he_vcc->rx_waitq);
+ init_waitqueue_head(&he_vcc->tx_waitq);
+#endif
+
+ HE_VCC(vcc) = he_vcc;
+
+ if (vcc->qos.txtp.traffic_class != ATM_NONE)
+ {
+ int pcr_goal;
+
+ pcr_goal = atm_pcr_goal(&vcc->qos.txtp);
+ if (pcr_goal == 0)
+ pcr_goal = he_dev->atm_dev->link_rate;
+ if (pcr_goal < 0) /* means round down, technically */
+ pcr_goal = -pcr_goal;
+
+ HPRINTK("open tx cid 0x%x pcr_goal %d\n", cid, pcr_goal);
+
+ switch (vcc->qos.aal)
+ {
+ case ATM_AAL5:
+ tsr0_aal = TSR0_AAL5;
+ tsr4 = TSR4_AAL5;
+ break;
+ case ATM_AAL0:
+ tsr0_aal = TSR0_AAL0_SDU;
+ tsr4 = TSR4_AAL0_SDU;
+ break;
+ default:
+ err = -EINVAL;
+ goto open_failed;
+ }
+
+ HE_SPIN_LOCK(he_dev, flags);
+ tsr0 = he_readl_tsr0(he_dev, cid);
+ HE_SPIN_UNLOCK(he_dev, flags);
+
+ if (TSR0_CONN_STATE(tsr0) != 0)
+ {
+ hprintk("cid 0x%x not idle (tsr0 = 0x%x)\n", cid, tsr0);
+ err = -EBUSY;
+ goto open_failed;
+ }
+
+ switch(vcc->qos.txtp.traffic_class)
+ {
+ case ATM_UBR:
+ /* 2.3.3.1 open connection ubr */
+
+ tsr0 = TSR0_UBR | TSR0_GROUP(0) | tsr0_aal |
+ TSR0_USE_WMIN | TSR0_UPDATE_GER;
+ break;
+
+ case ATM_CBR:
+ /* 2.3.3.2 open connection cbr */
+
+ /* 8.2.3 cbr scheduler wrap problem -- limit to 90% total link rate */
+ if ((he_dev->total_bw + pcr_goal)
+ > (he_dev->atm_dev->link_rate * 9 / 10))
+ {
+ err = -EBUSY;
+ goto open_failed;
+ }
+
+ HE_SPIN_LOCK(he_dev, flags); /* also protects he_dev->cs_stper[] */
+
+ /* find an unused cs_stper register */
+ for(reg = 0; reg < HE_NUM_CS_STPER; ++reg)
+ if (he_dev->cs_stper[reg].inuse == 0 ||
+ he_dev->cs_stper[reg].pcr == pcr_goal)
+ break;
+
+ if (reg == HE_NUM_CS_STPER)
+ {
+ err = -EBUSY;
+ HE_SPIN_UNLOCK(he_dev, flags);
+ goto open_failed;
+ }
+
+ he_dev->total_bw += pcr_goal;
+
+ he_vcc->rc_index = reg;
+ ++he_dev->cs_stper[reg].inuse;
+ he_dev->cs_stper[reg].pcr = pcr_goal;
+
+ clock = he_is622(he_dev) ? 66667000 : 50000000;
+ period = clock / pcr_goal;
+
+ HPRINTK("rc_index = %d period = %d\n",
+ reg, period);
+
+ he_writel_mbox(he_dev, rate_to_atmf(period/2),
+ CS_STPER0 + reg);
+ HE_SPIN_UNLOCK(he_dev, flags);
+
+ tsr0 = TSR0_CBR | TSR0_GROUP(0) | tsr0_aal |
+ TSR0_RC_INDEX(reg);
+
+ break;
+ default:
+ err = -EINVAL;
+ goto open_failed;
+ }
+
+ HE_SPIN_LOCK(he_dev, flags);
+
+ he_writel_tsr0(he_dev, tsr0, cid);
+ he_writel_tsr4(he_dev, tsr4 | 1, cid);
+ he_writel_tsr1(he_dev, TSR1_MCR(rate_to_atmf(0)) |
+ TSR1_PCR(rate_to_atmf(pcr_goal)), cid);
+ he_writel_tsr2(he_dev, TSR2_ACR(rate_to_atmf(pcr_goal)), cid);
+ he_writel_tsr9(he_dev, TSR9_OPEN_CONN, cid);
+
+ he_writel_tsr3(he_dev, 0x0, cid);
+ he_writel_tsr5(he_dev, 0x0, cid);
+ he_writel_tsr6(he_dev, 0x0, cid);
+ he_writel_tsr7(he_dev, 0x0, cid);
+ he_writel_tsr8(he_dev, 0x0, cid);
+ he_writel_tsr10(he_dev, 0x0, cid);
+ he_writel_tsr11(he_dev, 0x0, cid);
+ he_writel_tsr12(he_dev, 0x0, cid);
+ he_writel_tsr13(he_dev, 0x0, cid);
+ he_writel_tsr14(he_dev, 0x0, cid);
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl_tsr0(he_dev, cid);
+#endif
+ HE_SPIN_UNLOCK(he_dev, flags);
+ }
+
+ if (vcc->qos.rxtp.traffic_class != ATM_NONE)
+ {
+ unsigned aal;
+
+ HPRINTK("open rx cid 0x%x (rx_waitq %p)\n", cid,
+ &HE_VCC(vcc)->rx_waitq);
+
+ switch (vcc->qos.aal)
+ {
+ case ATM_AAL5:
+ aal = RSR0_AAL5;
+ break;
+ case ATM_AAL0:
+ aal = RSR0_RAWCELL;
+ break;
+ default:
+ err = -EINVAL;
+ goto open_failed;
+ }
+
+ HE_SPIN_LOCK(he_dev, flags);
+
+ rsr0 = he_readl_rsr0(he_dev, cid);
+ if (rsr0 & RSR0_OPEN_CONN)
+ {
+ HE_SPIN_UNLOCK(he_dev, flags);
+
+ hprintk("cid 0x%x not idle (rsr0 = 0x%x)\n", cid, rsr0);
+ err = -EBUSY;
+ goto open_failed;
+ }
+
+#ifdef USE_RBPS
+ rsr1 = RSR1_GROUP(0);
+ rsr4 = RSR4_GROUP(0);
+#else /* !USE_RBPS */
+ rsr1 = RSR1_GROUP(0)|RSR1_RBPL_ONLY;
+ rsr4 = RSR4_GROUP(0)|RSR4_RBPL_ONLY;
+#endif /* USE_RBPS */
+ rsr0 = vcc->qos.rxtp.traffic_class == ATM_UBR ?
+ (RSR0_EPD_ENABLE|RSR0_PPD_ENABLE) : 0;
+
+#ifdef USE_CHECKSUM_HW
+ if (vpi == 0 && vci >= ATM_NOT_RSV_VCI) rsr0 |= RSR0_TCP_CKSUM;
+#endif
+
+ he_writel_rsr4(he_dev, rsr4, cid);
+ he_writel_rsr1(he_dev, rsr1, cid);
+ /* 5.1.11 last parameter initialized should be
+ the open/closed indication in rsr0 */
+ he_writel_rsr0(he_dev,
+ rsr0 | RSR0_START_PDU | RSR0_OPEN_CONN | aal, cid);
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl_rsr0(he_dev, cid);
+#endif
+
+ HE_SPIN_UNLOCK(he_dev, flags);
+
+#ifndef USE_HE_FIND_VCC
+ HE_LOOKUP_VCC(he_dev, cid) = vcc;
+#endif
+ }
+
+open_failed:
+
+ if (err)
+ {
+ if (he_vcc) kfree(he_vcc);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+ vcc->flags &= ~ATM_VF_ADDR;
+#else
+ clear_bit(ATM_VF_ADDR, &vcc->flags);
+#endif
+ }
+ else
+ {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+ vcc->flags |= ATM_VF_READY;
+#else
+ set_bit(ATM_VF_READY, &vcc->flags);
+#endif
+ }
+
+ return err;
+}
+
+static void
+he_close(struct atm_vcc *vcc)
+{
+ unsigned long flags;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,1)
+ DECLARE_WAITQUEUE(wait, current);
+#else
+ struct wait_queue wait = { current, NULL };
+#endif
+ struct he_dev *he_dev = HE_DEV(vcc->dev);
+ struct he_tpd *tpd;
+ unsigned cid;
+ struct he_vcc *he_vcc = HE_VCC(vcc);
+#define MAX_RETRY 30
+ int retry = 0, sleep = 1, tx_inuse;
+
+ HPRINTK("close vcc %p %d.%d\n", vcc, vcc->vpi, vcc->vci);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+ vcc->flags &= ~ATM_VF_READY;
+#else
+ clear_bit(ATM_VF_READY, &vcc->flags);
+#endif
+ cid = he_mkcid(he_dev, vcc->vpi, vcc->vci);
+
+ if (vcc->qos.rxtp.traffic_class != ATM_NONE)
+ {
+ int timeout;
+
+ HPRINTK("close rx cid 0x%x\n", cid);
+
+ /* 2.7.2.2 close receive operation */
+
+ /* wait for previous close (if any) to finish */
+
+ HE_SPIN_LOCK(he_dev, flags);
+ while(he_readl(he_dev, RCC_STAT) & RCC_BUSY)
+ {
+ HPRINTK("close cid 0x%x RCC_BUSY\n", cid);
+ udelay(250);
+ }
+
+ add_wait_queue(&he_vcc->rx_waitq, &wait);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+
+ he_writel_rsr0(he_dev, RSR0_CLOSE_CONN, cid);
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl_rsr0(he_dev, cid);
+#endif
+ he_writel_mbox(he_dev, cid, RXCON_CLOSE);
+ HE_SPIN_UNLOCK(he_dev, flags);
+
+ timeout = schedule_timeout(30*HZ);
+
+ remove_wait_queue(&he_vcc->rx_waitq, &wait);
+ set_current_state(TASK_RUNNING);
+
+ if (timeout == 0)
+ hprintk("close rx timeout cid 0x%x\n", cid);
+
+#ifndef USE_HE_FIND_VCC
+ HE_LOOKUP_VCC(he_dev, cid) = NULL;
+#endif
+ HPRINTK("close rx cid 0x%x complete\n", cid);
+
+ }
+
+ if (vcc->qos.txtp.traffic_class != ATM_NONE)
+ {
+ volatile unsigned tsr4, tsr0;
+ int timeout;
+
+ HPRINTK("close tx cid 0x%x\n", cid);
+
+ /* 2.1.2
+ *
+ * ... the host must first stop queueing packets to the TPDRQ
+ * on the connection to be closed, then wait for all outstanding
+ * packets to be transmitted and their buffers returned to the
+ * TBRQ. When the last packet on the connection arrives in the
+ * TBRQ, the host issues the close command to the adapter.
+ */
+
+ while (((tx_inuse = atomic_read(&vcc->sk->wmem_alloc)) > 0)
+ && (retry < MAX_RETRY))
+ {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ (void) schedule_timeout(sleep);
+ set_current_state(TASK_RUNNING);
+ if (sleep < HZ) sleep = sleep * 2;
+
+ ++retry;
+ }
+
+ if (tx_inuse) hprintk("close tx cid 0x%x tx_inuse = %d\n",
+ cid, tx_inuse);
+
+ /* 2.3.1.1 generic close operations with flush */
+
+ HE_SPIN_LOCK(he_dev, flags);
+ he_writel_tsr4_upper(he_dev, TSR4_FLUSH_CONN, cid);
+ /* also clears TSR4_SESSION_ENDED */
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl_tsr4(he_dev, cid);
+#endif
+
+ switch(vcc->qos.txtp.traffic_class)
+ {
+ case ATM_UBR:
+ he_writel_tsr1(he_dev,
+ TSR1_MCR(rate_to_atmf(200000))
+ | TSR1_PCR(0), cid);
+ break;
+ case ATM_CBR:
+ he_writel_tsr14_upper(he_dev, TSR14_DELETE, cid);
+ break;
+ }
+
+
+ tpd = __alloc_tpd(he_dev);
+ if (tpd == NULL)
+ {
+ hprintk("close tx he_alloc_tpd failed cid 0x%x\n", cid);
+ goto close_tx_incomplete;
+ }
+ tpd->status |= TPD_EOS | TPD_INT;
+ tpd->skb = NULL;
+ tpd->vcc = vcc;
+ wmb();
+
+ add_wait_queue(&he_vcc->tx_waitq, &wait);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ __enqueue_tpd(he_dev, tpd, cid);
+ HE_SPIN_UNLOCK(he_dev, flags);
+
+ timeout = schedule_timeout(30*HZ);
+
+ remove_wait_queue(&he_vcc->tx_waitq, &wait);
+ set_current_state(TASK_RUNNING);
+
+ if (timeout == 0)
+ {
+ hprintk("close tx timeout cid 0x%x\n", cid);
+ goto close_tx_incomplete;
+ }
+
+ HE_SPIN_LOCK(he_dev, flags);
+ while (!((tsr4 = he_readl_tsr4(he_dev, cid))
+ & TSR4_SESSION_ENDED))
+ {
+ HPRINTK("close tx cid 0x%x !TSR4_SESSION_ENDED (tsr4 = 0x%x)\n", cid, tsr4);
+ udelay(250);
+ }
+
+ while (TSR0_CONN_STATE(tsr0 = he_readl_tsr0(he_dev, cid)) != 0)
+ {
+ HPRINTK("close tx cid 0x%x TSR0_CONN_STATE != 0 (tsr0 = 0x%x)\n", cid, tsr0);
+ udelay(250);
+ }
+
+close_tx_incomplete:
+
+ if (vcc->qos.txtp.traffic_class == ATM_CBR)
+ {
+ int reg = he_vcc->rc_index;
+
+ HPRINTK("cs_stper reg = %d\n", reg);
+
+ if (he_dev->cs_stper[reg].inuse == 0)
+ hprintk("cs_stper[%d].inuse = 0!\n", reg);
+ else
+ --he_dev->cs_stper[reg].inuse;
+
+ he_dev->total_bw -= he_dev->cs_stper[reg].pcr;
+ }
+ HE_SPIN_UNLOCK(he_dev, flags);
+
+ HPRINTK("close tx cid 0x%x complete\n", cid);
+ }
+
+ kfree(he_vcc);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+ vcc->flags &= ~ATM_VF_ADDR;
+#else
+ clear_bit(ATM_VF_ADDR, &vcc->flags);
+#endif
+}
+
+static int
+he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size)
+{
+#ifdef USE_SCATTERGATHER
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+static int
+he_send(struct atm_vcc *vcc, struct sk_buff *skb)
+{
+ unsigned long flags;
+ struct he_dev *he_dev = HE_DEV(vcc->dev);
+ unsigned cid = he_mkcid(he_dev, vcc->vpi, vcc->vci);
+ struct he_tpd *tpd;
+#ifdef USE_SCATTERGATHER
+ int i, slot = 0;
+#endif
+
+#define HE_TPD_BUFSIZE 0xffff
+
+ HPRINTK("send %d.%d\n", vcc->vpi, vcc->vci);
+
+ if ((skb->len > HE_TPD_BUFSIZE) ||
+ ((vcc->qos.aal == ATM_AAL0) && (skb->len != ATM_AAL0_SDU)))
+ {
+ hprintk("buffer too large (or small) -- %d bytes\n", skb->len );
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_any(skb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+ ++vcc->stats->tx_err;
+#else
+ atomic_inc(&vcc->stats->tx_err);
+#endif
+ return -EINVAL;
+ }
+
+#ifndef USE_SCATTERGATHER
+ if (skb_shinfo(skb)->nr_frags)
+ {
+ hprintk1("no scatter/gather support\n");
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_any(skb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+ ++vcc->stats->tx_err;
+#else
+ atomic_inc(&vcc->stats->tx_err);
+#endif
+ return -EINVAL;
+ }
+#endif
+ HE_SPIN_LOCK(he_dev, flags);
+
+ tpd = __alloc_tpd(he_dev);
+ if (tpd == NULL)
+ {
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_any(skb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+ ++vcc->stats->tx_err;
+#else
+ atomic_inc(&vcc->stats->tx_err);
+#endif
+ HE_SPIN_UNLOCK(he_dev, flags);
+ return -ENOMEM;
+ }
+
+ if (vcc->qos.aal == ATM_AAL5)
+ tpd->status |= TPD_CELLTYPE(TPD_USERCELL);
+ else
+ {
+ char *pti_clp = (void *) (skb->data + 3);
+ int clp, pti;
+
+ pti = (*pti_clp & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT;
+ clp = (*pti_clp & ATM_HDR_CLP);
+ tpd->status |= TPD_CELLTYPE(pti);
+ if (clp) tpd->status |= TPD_CLP;
+
+ skb_pull(skb, ATM_AAL0_SDU - ATM_CELL_PAYLOAD);
+ }
+
+#ifdef USE_SCATTERGATHER
+ tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev, skb->data,
+ skb->len - skb->data_len, PCI_DMA_TODEVICE);
+ tpd->iovec[slot].len = skb->len - skb->data_len;
+ ++slot;
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+ {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ if (slot == TPD_MAXIOV) /* send tpd; start new tpd */
+ {
+ tpd->vcc = vcc;
+ tpd->skb = NULL; /* not the last fragment
+ so dont ->push() yet */
+ wmb();
+
+ __enqueue_tpd(he_dev, tpd, cid);
+ tpd = __alloc_tpd(he_dev);
+ if (tpd == NULL)
+ {
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_any(skb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+ ++vcc->stats->tx_err;
+#else
+ atomic_inc(&vcc->stats->tx_err);
+ HE_SPIN_UNLOCK(he_dev, flags);
+#endif
+ return -ENOMEM;
+ }
+ tpd->status |= TPD_USERCELL;
+ slot = 0;
+ }
+
+ tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev,
+ (void *) page_address(frag->page) + frag->page_offset,
+ frag->size, PCI_DMA_TODEVICE);
+ tpd->iovec[slot].len = frag->size;
+ ++slot;
+
+ }
+
+ tpd->iovec[slot-1].len |= TPD_LST;
+#else
+ tpd->address0 = pci_map_single(he_dev->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
+ tpd->length0 = skb->len | TPD_LST;
+#endif
+ tpd->status |= TPD_INT;
+
+ tpd->vcc = vcc;
+ tpd->skb = skb;
+ wmb();
+ ATM_SKB(skb)->vcc = vcc;
+
+ __enqueue_tpd(he_dev, tpd, cid);
+ HE_SPIN_UNLOCK(he_dev, flags);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99)
+ ++vcc->stats->tx;
+#else
+ atomic_inc(&vcc->stats->tx);
+#endif
+
+ return 0;
+}
+
+static int
+he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void *arg)
+{
+ unsigned long flags;
+ struct he_dev *he_dev = HE_DEV(atm_dev);
+ struct he_ioctl_reg reg;
+ int err = 0;
+
+ switch (cmd)
+ {
+ case HE_GET_REG:
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
+
+ copy_from_user(&reg, (struct he_ioctl_reg *) arg,
+ sizeof(struct he_ioctl_reg));
+ HE_SPIN_LOCK(he_dev, flags);
+ switch (reg.type)
+ {
+ case HE_REGTYPE_PCI:
+ reg.val = he_readl(he_dev, reg.addr);
+ break;
+ case HE_REGTYPE_RCM:
+ reg.val =
+ he_readl_rcm(he_dev, reg.addr);
+ break;
+ case HE_REGTYPE_TCM:
+ reg.val =
+ he_readl_tcm(he_dev, reg.addr);
+ break;
+ case HE_REGTYPE_MBOX:
+ reg.val =
+ he_readl_mbox(he_dev, reg.addr);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ HE_SPIN_UNLOCK(he_dev, flags);
+ if (err == 0) copy_to_user((struct he_ioctl_reg *) arg, &reg,
+ sizeof(struct he_ioctl_reg));
+ break;
+ default:
+#ifdef CONFIG_ATM_HE_USE_SUNI
+ if (atm_dev->phy && atm_dev->phy->ioctl)
+ err = atm_dev->phy->ioctl(atm_dev, cmd, arg);
+#else /* CONFIG_ATM_HE_USE_SUNI */
+ return -EINVAL;
+#endif /* CONFIG_ATM_HE_USE_SUNI */
+ break;
+ }
+
+ return err;
+}
+
+static void
+he_phy_put(struct atm_dev *atm_dev, unsigned char val, unsigned long addr)
+{
+ unsigned long flags;
+ struct he_dev *he_dev = HE_DEV(atm_dev);
+
+ HPRINTK("phy_put(val 0x%x, addr 0x%lx)\n", val, addr);
+
+ HE_SPIN_LOCK(he_dev, flags);
+ he_writel(he_dev, val, FRAMER + (addr*4));
+#ifdef CONFIG_IA64_SGI_SN2
+ (void) he_readl(he_dev, FRAMER + (addr*4));
+#endif
+ HE_SPIN_UNLOCK(he_dev, flags);
+}
+
+
+static unsigned char
+he_phy_get(struct atm_dev *atm_dev, unsigned long addr)
+{
+ unsigned long flags;
+ struct he_dev *he_dev = HE_DEV(atm_dev);
+ unsigned reg;
+
+ HE_SPIN_LOCK(he_dev, flags);
+ reg = he_readl(he_dev, FRAMER + (addr*4));
+ HE_SPIN_UNLOCK(he_dev, flags);
+
+ HPRINTK("phy_get(addr 0x%lx) =0x%x\n", addr, reg);
+ return reg;
+}
+
+static int
+he_proc_read(struct atm_dev *dev, loff_t *pos, char *page)
+{
+ unsigned long flags;
+ struct he_dev *he_dev = HE_DEV(dev);
+ int left, i;
+#ifdef notdef
+ struct he_rbrq *rbrq_tail;
+ struct he_tpdrq *tpdrq_head;
+ int rbpl_head, rbpl_tail;
+#endif
+ static long mcc = 0, oec = 0, dcc = 0, cec = 0;
+
+
+ left = *pos;
+ if (!left--)
+ return sprintf(page, "%s\n", version);
+
+ if (!left--)
+ return sprintf(page, "%s%s\n\n",
+ he_dev->prod_id, he_dev->media & 0x40 ? "SM" : "MM");
+
+ if (!left--)
+ return sprintf(page, "Mismatched Cells VPI/VCI Not Open Dropped Cells RCM Dropped Cells\n");
+
+ HE_SPIN_LOCK(he_dev, flags);
+ mcc += he_readl(he_dev, MCC);
+ oec += he_readl(he_dev, OEC);
+ dcc += he_readl(he_dev, DCC);
+ cec += he_readl(he_dev, CEC);
+ HE_SPIN_UNLOCK(he_dev, flags);
+
+ if (!left--)
+ return sprintf(page, "%16ld %16ld %13ld %17ld\n\n",
+ mcc, oec, dcc, cec);
+
+ if (!left--)
+ return sprintf(page, "irq_size = %d inuse = ? peak = %d\n",
+ CONFIG_IRQ_SIZE, he_dev->irq_peak);
+
+ if (!left--)
+ return sprintf(page, "tpdrq_size = %d inuse = ?\n",
+ CONFIG_TPDRQ_SIZE);
+
+ if (!left--)
+ return sprintf(page, "rbrq_size = %d inuse = ? peak = %d\n",
+ CONFIG_RBRQ_SIZE, he_dev->rbrq_peak);
+
+ if (!left--)
+ return sprintf(page, "tbrq_size = %d peak = %d\n",
+ CONFIG_TBRQ_SIZE, he_dev->tbrq_peak);
+
+
+#ifdef notdef
+ rbpl_head = RBPL_MASK(he_readl(he_dev, G0_RBPL_S));
+ rbpl_tail = RBPL_MASK(he_readl(he_dev, G0_RBPL_T));
+
+ inuse = rbpl_head - rbpl_tail;
+ if (inuse < 0) inuse += CONFIG_RBPL_SIZE * sizeof(struct he_rbp);
+ inuse /= sizeof(struct he_rbp);
+
+ if (!left--)
+ return sprintf(page, "rbpl_size = %d inuse = %d\n\n",
+ CONFIG_RBPL_SIZE, inuse);
+#endif
+
+ if (!left--)
+ return sprintf(page, "rate controller periods (cbr)\n pcr #vc\n");
+
+ for (i = 0; i < HE_NUM_CS_STPER; ++i)
+ if (!left--)
+ return sprintf(page, "cs_stper%-2d %8ld %3d\n", i,
+ he_dev->cs_stper[i].pcr,
+ he_dev->cs_stper[i].inuse);
+
+ if (!left--)
+ return sprintf(page, "total bw (cbr): %d (limit %d)\n",
+ he_dev->total_bw, he_dev->atm_dev->link_rate * 10 / 9);
+
+ return 0;
+}
+
+/* eeprom routines -- see 4.7 */
+
+u8
+read_prom_byte(struct he_dev *he_dev, int addr)
+{
+ u32 val = 0, tmp_read = 0;
+ int i, j = 0;
+ u8 byte_read = 0;
+
+ val = readl(he_dev->membase + HOST_CNTL);
+ val &= 0xFFFFE0FF;
+
+ /* Turn on write enable */
+ val |= 0x800;
+ he_writel(he_dev, val, HOST_CNTL);
+
+ /* Send READ instruction */
+ for (i=0; i<sizeof(readtab)/sizeof(readtab[0]); i++) {
+ he_writel(he_dev, val | readtab[i], HOST_CNTL);
+ udelay(EEPROM_DELAY);
+ }
+
+ /* Next, we need to send the byte address to read from */
+ for (i=7; i>=0; i--) {
+ he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL);
+ udelay(EEPROM_DELAY);
+ he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL);
+ udelay(EEPROM_DELAY);
+ }
+
+ j=0;
+
+ val &= 0xFFFFF7FF; /* Turn off write enable */
+ he_writel(he_dev, val, HOST_CNTL);
+
+ /* Now, we can read data from the EEPROM by clocking it in */
+ for (i=7; i>=0; i--) {
+ he_writel(he_dev, val | clocktab[j++], HOST_CNTL);
+ udelay(EEPROM_DELAY);
+ tmp_read = he_readl(he_dev, HOST_CNTL);
+ byte_read |= (unsigned char)
+ ((tmp_read & ID_DOUT)
+ >> ID_DOFFSET << i);
+ he_writel(he_dev, val | clocktab[j++], HOST_CNTL);
+ udelay(EEPROM_DELAY);
+ }
+
+ he_writel(he_dev, val | ID_CS, HOST_CNTL);
+ udelay(EEPROM_DELAY);
+
+ return (byte_read);
+}
+
+MODULE_AUTHOR("chas williams <chas@cmf.nrl.navy.mil>");
+MODULE_DESCRIPTION("ForeRunnerHE ATM Adapter driver");
+MODULE_PARM(disable64, "h");
+MODULE_PARM_DESC(disable64, "disable 64-bit pci bus transfers");
+MODULE_PARM(nvpibits, "i");
+MODULE_PARM_DESC(nvpibits, "numbers of bits for vpi (default 0)");
+MODULE_PARM(nvcibits, "i");
+MODULE_PARM_DESC(nvcibits, "numbers of bits for vci (default 12)");
+MODULE_PARM(rx_skb_reserve, "i");
+MODULE_PARM_DESC(rx_skb_reserve, "padding for receive skb (default 16)");
+MODULE_PARM(irq_coalesce, "i");
+MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)");
+MODULE_PARM(sdh, "i");
+MODULE_PARM_DESC(sdh, "use SDH framing (default 0)");
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,1)
+static struct pci_device_id he_pci_tbl[] __devinitdata = {
+ { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_HE, PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, 0 },
+ { 0, }
+};
+
+static struct pci_driver he_driver = {
+ .name = "he",
+ .probe = he_init_one,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,9)
+ .remove = __devexit_p(he_remove_one),
+#else
+ .remove = he_remove_one,
+#endif
+ .id_table = he_pci_tbl,
+};
+
+static int __init he_init(void)
+{
+ return pci_module_init(&he_driver);
+}
+
+static void __exit he_cleanup(void)
+{
+ pci_unregister_driver(&he_driver);
+}
+
+module_init(he_init);
+module_exit(he_cleanup);
+#else
+static int __init
+he_init()
+{
+ if (!pci_present())
+ return -EIO;
+
+#ifdef CONFIG_ATM_HE_USE_SUNI_MODULE
+ /* request_module("suni"); */
+#endif
+
+ pci_dev = NULL;
+ while ((pci_dev = pci_find_device(PCI_VENDOR_ID_FORE,
+ PCI_DEVICE_ID_FORE_HE, pci_dev)) != NULL)
+ if (he_init_one(pci_dev, NULL) == 0)
+ ++ndevs;
+
+ return (ndevs ? 0 : -ENODEV);
+}
+
+static void __devexit
+he_cleanup(void)
+{
+ while (he_devs)
+ {
+ struct he_dev *next = he_devs->next;
+ he_stop(he_devs);
+ atm_dev_deregister(he_devs->atm_dev);
+ kfree(he_devs);
+
+ he_devs = next;
+ }
+
+}
+
+int init_module(void)
+{
+ return he_init();
+}
+
+void cleanup_module(void)
+{
+ he_cleanup();
+}
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,7)
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/atm/he.h b/drivers/atm/he.h
new file mode 100644
index 000000000000..a872d84f5e50
--- /dev/null
+++ b/drivers/atm/he.h
@@ -0,0 +1,935 @@
+/* $Id: he.h,v 1.4 2003/05/06 22:48:00 chas Exp $ */
+
+/*
+
+ he.h
+
+ ForeRunnerHE ATM Adapter driver for ATM on Linux
+ Copyright (C) 1999-2001 Naval Research Laboratory
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+/*
+
+ he.h
+
+ ForeRunnerHE ATM Adapter driver for ATM on Linux
+ Copyright (C) 1999-2000 Naval Research Laboratory
+
+ Permission to use, copy, modify and distribute this software and its
+ documentation is hereby granted, provided that both the copyright
+ notice and this permission notice appear in all copies of the software,
+ derivative works or modified versions, and any portions thereof, and
+ that both notices appear in supporting documentation.
+
+ NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
+ DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
+ RESULTING FROM THE USE OF THIS SOFTWARE.
+
+ */
+
+#ifndef _HE_H_
+#define _HE_H_
+
+#define DEV_LABEL "he"
+
+#define CONFIG_DEFAULT_VCIBITS 12
+#define CONFIG_DEFAULT_VPIBITS 0
+
+#define CONFIG_IRQ_SIZE 128
+#define CONFIG_IRQ_THRESH (CONFIG_IRQ_SIZE/2)
+
+#define CONFIG_NUMTPDS 256
+
+#define CONFIG_TPDRQ_SIZE 512
+#define TPDRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TPDRQ_SIZE<<3)-1))
+
+#define CONFIG_RBRQ_SIZE 512
+#define CONFIG_RBRQ_THRESH 400
+#define RBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_RBRQ_SIZE<<3)-1))
+
+#define CONFIG_TBRQ_SIZE 512
+#define CONFIG_TBRQ_THRESH 400
+#define TBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TBRQ_SIZE<<2)-1))
+
+#define CONFIG_RBPL_SIZE 512
+#define CONFIG_RBPL_THRESH 64
+#define CONFIG_RBPL_BUFSIZE 4096
+#define RBPL_MASK(x) (((unsigned long)(x))&((CONFIG_RBPL_SIZE<<3)-1))
+
+#define CONFIG_RBPS_SIZE 1024
+#define CONFIG_RBPS_THRESH 64
+#define CONFIG_RBPS_BUFSIZE 128
+#define RBPS_MASK(x) (((unsigned long)(x))&((CONFIG_RBPS_SIZE<<3)-1))
+
+/* 5.1.3 initialize connection memory */
+
+#define CONFIG_RSRA 0x00000
+#define CONFIG_RCMLBM 0x08000
+#define CONFIG_RCMABR 0x0d800
+#define CONFIG_RSRB 0x0e000
+
+#define CONFIG_TSRA 0x00000
+#define CONFIG_TSRB 0x08000
+#define CONFIG_TSRC 0x0c000
+#define CONFIG_TSRD 0x0e000
+#define CONFIG_TMABR 0x0f000
+#define CONFIG_TPDBA 0x10000
+
+#define HE_MAXCIDBITS 12
+
+/* 2.9.3.3 interrupt encodings */
+
+struct he_irq {
+ volatile u32 isw;
+};
+
+#define IRQ_ALIGNMENT 0x1000
+
+#define NEXT_ENTRY(base, tail, mask) \
+ (((unsigned long)base)|(((unsigned long)(tail+1))&mask))
+
+#define ITYPE_INVALID 0xffffffff
+#define ITYPE_TBRQ_THRESH (0<<3)
+#define ITYPE_TPD_COMPLETE (1<<3)
+#define ITYPE_RBPS_THRESH (2<<3)
+#define ITYPE_RBPL_THRESH (3<<3)
+#define ITYPE_RBRQ_THRESH (4<<3)
+#define ITYPE_RBRQ_TIMER (5<<3)
+#define ITYPE_PHY (6<<3)
+#define ITYPE_OTHER 0x80
+#define ITYPE_PARITY 0x81
+#define ITYPE_ABORT 0x82
+
+#define ITYPE_GROUP(x) (x & 0x7)
+#define ITYPE_TYPE(x) (x & 0xf8)
+
+#define HE_NUM_GROUPS 8
+
+/* 2.1.4 transmit packet descriptor */
+
+struct he_tpd {
+
+ /* read by the adapter */
+
+ volatile u32 status;
+ volatile u32 reserved;
+
+#define TPD_MAXIOV 3
+ struct {
+ u32 addr, len;
+ } iovec[TPD_MAXIOV];
+
+#define address0 iovec[0].addr
+#define length0 iovec[0].len
+
+ /* linux-atm extensions */
+
+ struct sk_buff *skb;
+ struct atm_vcc *vcc;
+
+#ifdef USE_TPD_POOL
+ struct list_head entry;
+#else
+ u32 inuse;
+ char padding[32 - sizeof(u32) - (2*sizeof(void*))];
+#endif
+};
+
+#define TPD_ALIGNMENT 64
+#define TPD_LEN_MASK 0xffff
+
+#define TPD_ADDR_SHIFT 6
+#define TPD_MASK 0xffffffc0
+#define TPD_ADDR(x) ((x) & TPD_MASK)
+#define TPD_INDEX(x) (TPD_ADDR(x) >> TPD_ADDR_SHIFT)
+
+
+/* table 2.3 transmit buffer return elements */
+
+struct he_tbrq {
+ volatile u32 tbre;
+};
+
+#define TBRQ_ALIGNMENT CONFIG_TBRQ_SIZE
+
+#define TBRQ_TPD(tbrq) ((tbrq)->tbre & 0xffffffc0)
+#define TBRQ_EOS(tbrq) ((tbrq)->tbre & (1<<3))
+#define TBRQ_MULTIPLE(tbrq) ((tbrq)->tbre & (1))
+
+/* table 2.21 receive buffer return queue element field organization */
+
+struct he_rbrq {
+ volatile u32 addr;
+ volatile u32 cidlen;
+};
+
+#define RBRQ_ALIGNMENT CONFIG_RBRQ_SIZE
+
+#define RBRQ_ADDR(rbrq) ((rbrq)->addr & 0xffffffc0)
+#define RBRQ_CRC_ERR(rbrq) ((rbrq)->addr & (1<<5))
+#define RBRQ_LEN_ERR(rbrq) ((rbrq)->addr & (1<<4))
+#define RBRQ_END_PDU(rbrq) ((rbrq)->addr & (1<<3))
+#define RBRQ_AAL5_PROT(rbrq) ((rbrq)->addr & (1<<2))
+#define RBRQ_CON_CLOSED(rbrq) ((rbrq)->addr & (1<<1))
+#define RBRQ_HBUF_ERR(rbrq) ((rbrq)->addr & 1)
+#define RBRQ_CID(rbrq) (((rbrq)->cidlen >> 16) & 0x1fff)
+#define RBRQ_BUFLEN(rbrq) ((rbrq)->cidlen & 0xffff)
+
+/* figure 2.3 transmit packet descriptor ready queue */
+
+struct he_tpdrq {
+ volatile u32 tpd;
+ volatile u32 cid;
+};
+
+#define TPDRQ_ALIGNMENT CONFIG_TPDRQ_SIZE
+
+/* table 2.30 host status page detail */
+
+#define HSP_ALIGNMENT 0x400 /* must align on 1k boundary */
+
+struct he_hsp {
+ struct he_hsp_entry {
+ volatile u32 tbrq_tail;
+ volatile u32 reserved1[15];
+ volatile u32 rbrq_tail;
+ volatile u32 reserved2[15];
+ } group[HE_NUM_GROUPS];
+};
+
+/* figure 2.9 receive buffer pools */
+
+struct he_rbp {
+ volatile u32 phys;
+ volatile u32 status;
+};
+
+/* NOTE: it is suggested that virt be the virtual address of the host
+ buffer. on a 64-bit machine, this would not work. Instead, we
+ store the real virtual address in another list, and store an index
+ (and buffer status) in the virt member.
+*/
+
+#define RBP_INDEX_OFF 6
+#define RBP_INDEX(x) (((long)(x) >> RBP_INDEX_OFF) & 0xffff)
+#define RBP_LOANED 0x80000000
+#define RBP_SMALLBUF 0x40000000
+
+struct he_virt {
+ void *virt;
+};
+
+#define RBPL_ALIGNMENT CONFIG_RBPL_SIZE
+#define RBPS_ALIGNMENT CONFIG_RBPS_SIZE
+
+#ifdef notyet
+struct he_group {
+ u32 rpbs_size, rpbs_qsize;
+ struct he_rbp rbps_ba;
+
+ u32 rpbl_size, rpbl_qsize;
+ struct he_rpb_entry *rbpl_ba;
+};
+#endif
+
+#define HE_LOOKUP_VCC(dev, cid) ((dev)->he_vcc_table[(cid)].vcc)
+
+struct he_vcc_table
+{
+ struct atm_vcc *vcc;
+};
+
+struct he_cs_stper
+{
+ long pcr;
+ int inuse;
+};
+
+#define HE_NUM_CS_STPER 16
+
+struct he_dev {
+ unsigned int number;
+ unsigned int irq;
+ unsigned long membase;
+
+ char prod_id[30];
+ char mac_addr[6];
+ int media; /*
+ * 0x26 = HE155 MM
+ * 0x27 = HE622 MM
+ * 0x46 = HE155 SM
+ * 0x47 = HE622 SM
+ */
+
+
+ unsigned int vcibits, vpibits;
+ unsigned int cells_per_row;
+ unsigned int bytes_per_row;
+ unsigned int cells_per_lbuf;
+ unsigned int r0_numrows, r0_startrow, r0_numbuffs;
+ unsigned int r1_numrows, r1_startrow, r1_numbuffs;
+ unsigned int tx_numrows, tx_startrow, tx_numbuffs;
+ unsigned int buffer_limit;
+
+ struct he_vcc_table *he_vcc_table;
+
+#ifdef notyet
+ struct he_group group[HE_NUM_GROUPS];
+#endif
+ struct he_cs_stper cs_stper[HE_NUM_CS_STPER];
+ unsigned total_bw;
+
+ dma_addr_t irq_phys;
+ struct he_irq *irq_base, *irq_head, *irq_tail;
+ volatile unsigned *irq_tailoffset;
+ int irq_peak;
+
+#ifdef USE_TASKLET
+ struct tasklet_struct tasklet;
+#endif
+#ifdef USE_TPD_POOL
+ struct pci_pool *tpd_pool;
+ struct list_head outstanding_tpds;
+#else
+ struct he_tpd *tpd_head, *tpd_base, *tpd_end;
+ dma_addr_t tpd_base_phys;
+#endif
+
+ dma_addr_t tpdrq_phys;
+ struct he_tpdrq *tpdrq_base, *tpdrq_tail, *tpdrq_head;
+
+ spinlock_t global_lock; /* 8.1.5 pci transaction ordering
+ error problem */
+ dma_addr_t rbrq_phys;
+ struct he_rbrq *rbrq_base, *rbrq_head;
+ int rbrq_peak;
+
+#ifdef USE_RBPL_POOL
+ struct pci_pool *rbpl_pool;
+#else
+ void *rbpl_pages;
+ dma_addr_t rbpl_pages_phys;
+#endif
+ dma_addr_t rbpl_phys;
+ struct he_rbp *rbpl_base, *rbpl_tail;
+ struct he_virt *rbpl_virt;
+ int rbpl_peak;
+
+#ifdef USE_RBPS
+#ifdef USE_RBPS_POOL
+ struct pci_pool *rbps_pool;
+#else
+ void *rbps_pages;
+ dma_addr_t rbps_pages_phys;
+#endif
+#endif
+ dma_addr_t rbps_phys;
+ struct he_rbp *rbps_base, *rbps_tail;
+ struct he_virt *rbps_virt;
+ int rbps_peak;
+
+ dma_addr_t tbrq_phys;
+ struct he_tbrq *tbrq_base, *tbrq_head;
+ int tbrq_peak;
+
+ dma_addr_t hsp_phys;
+ struct he_hsp *hsp;
+
+ struct pci_dev *pci_dev;
+ struct atm_dev *atm_dev;
+ struct he_dev *next;
+};
+
+struct he_vcc
+{
+ struct iovec iov_head[32];
+ struct iovec *iov_tail;
+ int pdu_len;
+
+ int rc_index;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
+ struct wait_queue *rx_waitq;
+ atruct wait_queue *tx_waitq;
+#else
+ wait_queue_head_t rx_waitq;
+ wait_queue_head_t tx_waitq;
+#endif
+};
+
+#define HE_VCC(vcc) ((struct he_vcc *)(vcc->dev_data))
+
+#define PCI_VENDOR_ID_FORE 0x1127
+#define PCI_DEVICE_ID_FORE_HE 0x400
+
+#define HE_DMA_MASK 0xffffffff
+
+#define GEN_CNTL_0 0x40
+#define INT_PROC_ENBL (1<<25)
+#define SLAVE_ENDIAN_MODE (1<<16)
+#define MRL_ENB (1<<5)
+#define MRM_ENB (1<<4)
+#define INIT_ENB (1<<2)
+#define IGNORE_TIMEOUT (1<<1)
+#define ENBL_64 (1<<0)
+
+#define MIN_PCI_LATENCY 32 /* errata 8.1.3 */
+
+#define HE_DEV(dev) ((struct he_dev *) (dev)->dev_data)
+
+#define he_is622(dev) ((dev)->media & 0x1)
+
+#define HE_REGMAP_SIZE 0x100000
+
+#define RESET_CNTL 0x80000
+#define BOARD_RST_STATUS (1<<6)
+
+#define HOST_CNTL 0x80004
+#define PCI_BUS_SIZE64 (1<<27)
+#define DESC_RD_STATIC_64 (1<<26)
+#define DATA_RD_STATIC_64 (1<<25)
+#define DATA_WR_STATIC_64 (1<<24)
+#define ID_CS (1<<12)
+#define ID_WREN (1<<11)
+#define ID_DOUT (1<<10)
+#define ID_DOFFSET 10
+#define ID_DIN (1<<9)
+#define ID_CLOCK (1<<8)
+#define QUICK_RD_RETRY (1<<7)
+#define QUICK_WR_RETRY (1<<6)
+#define OUTFF_ENB (1<<5)
+#define CMDFF_ENB (1<<4)
+#define PERR_INT_ENB (1<<2)
+#define IGNORE_INTR (1<<0)
+
+#define LB_SWAP 0x80008
+#define SWAP_RNUM_MAX(x) (x<<27)
+#define DATA_WR_SWAP (1<<20)
+#define DESC_RD_SWAP (1<<19)
+#define DATA_RD_SWAP (1<<18)
+#define INTR_SWAP (1<<17)
+#define DESC_WR_SWAP (1<<16)
+#define SDRAM_INIT (1<<15)
+#define BIG_ENDIAN_HOST (1<<14)
+#define XFER_SIZE (1<<7)
+
+#define LB_MEM_ADDR 0x8000c
+#define LB_MEM_DATA 0x80010
+
+#define LB_MEM_ACCESS 0x80014
+#define LB_MEM_HNDSHK (1<<30)
+#define LM_MEM_WRITE (0x7)
+#define LM_MEM_READ (0x3)
+
+#define SDRAM_CTL 0x80018
+#define LB_64_ENB (1<<3)
+#define LB_TWR (1<<2)
+#define LB_TRP (1<<1)
+#define LB_TRAS (1<<0)
+
+#define INT_FIFO 0x8001c
+#define INT_MASK_D (1<<15)
+#define INT_MASK_C (1<<14)
+#define INT_MASK_B (1<<13)
+#define INT_MASK_A (1<<12)
+#define INT_CLEAR_D (1<<11)
+#define INT_CLEAR_C (1<<10)
+#define INT_CLEAR_B (1<<9)
+#define INT_CLEAR_A (1<<8)
+
+#define ABORT_ADDR 0x80020
+
+#define IRQ0_BASE 0x80080
+#define IRQ_BASE(x) (x<<12)
+#define IRQ_MASK ((CONFIG_IRQ_SIZE<<2)-1) /* was 0x3ff */
+#define IRQ_TAIL(x) (((unsigned long)(x)) & IRQ_MASK)
+#define IRQ0_HEAD 0x80084
+#define IRQ_SIZE(x) (x<<22)
+#define IRQ_THRESH(x) (x<<12)
+#define IRQ_HEAD(x) (x<<2)
+/* #define IRQ_PENDING (1) conflict with linux/irq.h */
+#define IRQ0_CNTL 0x80088
+#define IRQ_ADDRSEL(x) (x<<2)
+#define IRQ_INT_A (0<<2)
+#define IRQ_INT_B (1<<2)
+#define IRQ_INT_C (2<<2)
+#define IRQ_INT_D (3<<2)
+#define IRQ_TYPE_ADDR 0x1
+#define IRQ_TYPE_LINE 0x0
+#define IRQ0_DATA 0x8008c
+
+#define IRQ1_BASE 0x80090
+#define IRQ1_HEAD 0x80094
+#define IRQ1_CNTL 0x80098
+#define IRQ1_DATA 0x8009c
+
+#define IRQ2_BASE 0x800a0
+#define IRQ2_HEAD 0x800a4
+#define IRQ2_CNTL 0x800a8
+#define IRQ2_DATA 0x800ac
+
+#define IRQ3_BASE 0x800b0
+#define IRQ3_HEAD 0x800b4
+#define IRQ3_CNTL 0x800b8
+#define IRQ3_DATA 0x800bc
+
+#define GRP_10_MAP 0x800c0
+#define GRP_32_MAP 0x800c4
+#define GRP_54_MAP 0x800c8
+#define GRP_76_MAP 0x800cc
+
+#define G0_RBPS_S 0x80400
+#define G0_RBPS_T 0x80404
+#define RBP_TAIL(x) ((x)<<3)
+#define RBP_MASK(x) ((x)|0x1fff)
+#define G0_RBPS_QI 0x80408
+#define RBP_QSIZE(x) ((x)<<14)
+#define RBP_INT_ENB (1<<13)
+#define RBP_THRESH(x) (x)
+#define G0_RBPS_BS 0x8040c
+#define G0_RBPL_S 0x80410
+#define G0_RBPL_T 0x80414
+#define G0_RBPL_QI 0x80418
+#define G0_RBPL_BS 0x8041c
+
+#define G1_RBPS_S 0x80420
+#define G1_RBPS_T 0x80424
+#define G1_RBPS_QI 0x80428
+#define G1_RBPS_BS 0x8042c
+#define G1_RBPL_S 0x80430
+#define G1_RBPL_T 0x80434
+#define G1_RBPL_QI 0x80438
+#define G1_RBPL_BS 0x8043c
+
+#define G2_RBPS_S 0x80440
+#define G2_RBPS_T 0x80444
+#define G2_RBPS_QI 0x80448
+#define G2_RBPS_BS 0x8044c
+#define G2_RBPL_S 0x80450
+#define G2_RBPL_T 0x80454
+#define G2_RBPL_QI 0x80458
+#define G2_RBPL_BS 0x8045c
+
+#define G3_RBPS_S 0x80460
+#define G3_RBPS_T 0x80464
+#define G3_RBPS_QI 0x80468
+#define G3_RBPS_BS 0x8046c
+#define G3_RBPL_S 0x80470
+#define G3_RBPL_T 0x80474
+#define G3_RBPL_QI 0x80478
+#define G3_RBPL_BS 0x8047c
+
+#define G4_RBPS_S 0x80480
+#define G4_RBPS_T 0x80484
+#define G4_RBPS_QI 0x80488
+#define G4_RBPS_BS 0x8048c
+#define G4_RBPL_S 0x80490
+#define G4_RBPL_T 0x80494
+#define G4_RBPL_QI 0x80498
+#define G4_RBPL_BS 0x8049c
+
+#define G5_RBPS_S 0x804a0
+#define G5_RBPS_T 0x804a4
+#define G5_RBPS_QI 0x804a8
+#define G5_RBPS_BS 0x804ac
+#define G5_RBPL_S 0x804b0
+#define G5_RBPL_T 0x804b4
+#define G5_RBPL_QI 0x804b8
+#define G5_RBPL_BS 0x804bc
+
+#define G6_RBPS_S 0x804c0
+#define G6_RBPS_T 0x804c4
+#define G6_RBPS_QI 0x804c8
+#define G6_RBPS_BS 0x804cc
+#define G6_RBPL_S 0x804d0
+#define G6_RBPL_T 0x804d4
+#define G6_RBPL_QI 0x804d8
+#define G6_RBPL_BS 0x804dc
+
+#define G7_RBPS_S 0x804e0
+#define G7_RBPS_T 0x804e4
+#define G7_RBPS_QI 0x804e8
+#define G7_RBPS_BS 0x804ec
+
+#define G7_RBPL_S 0x804f0
+#define G7_RBPL_T 0x804f4
+#define G7_RBPL_QI 0x804f8
+#define G7_RBPL_BS 0x804fc
+
+#define G0_RBRQ_ST 0x80500
+#define G0_RBRQ_H 0x80504
+#define G0_RBRQ_Q 0x80508
+#define RBRQ_THRESH(x) ((x)<<13)
+#define RBRQ_SIZE(x) (x)
+#define G0_RBRQ_I 0x8050c
+#define RBRQ_TIME(x) ((x)<<8)
+#define RBRQ_COUNT(x) (x)
+
+/* fill in 1 ... 7 later */
+
+#define G0_TBRQ_B_T 0x80600
+#define G0_TBRQ_H 0x80604
+#define G0_TBRQ_S 0x80608
+#define G0_TBRQ_THRESH 0x8060c
+#define TBRQ_THRESH(x) (x)
+
+/* fill in 1 ... 7 later */
+
+#define RH_CONFIG 0x805c0
+#define PHY_INT_ENB (1<<10)
+#define OAM_GID(x) (x<<7)
+#define PTMR_PRE(x) (x)
+
+#define G0_INMQ_S 0x80580
+#define G0_INMQ_L 0x80584
+#define G1_INMQ_S 0x80588
+#define G1_INMQ_L 0x8058c
+#define G2_INMQ_S 0x80590
+#define G2_INMQ_L 0x80594
+#define G3_INMQ_S 0x80598
+#define G3_INMQ_L 0x8059c
+#define G4_INMQ_S 0x805a0
+#define G4_INMQ_L 0x805a4
+#define G5_INMQ_S 0x805a8
+#define G5_INMQ_L 0x805ac
+#define G6_INMQ_S 0x805b0
+#define G6_INMQ_L 0x805b4
+#define G7_INMQ_S 0x805b8
+#define G7_INMQ_L 0x805bc
+
+#define TPDRQ_B_H 0x80680
+#define TPDRQ_T 0x80684
+#define TPDRQ_S 0x80688
+
+#define UBUFF_BA 0x8068c
+
+#define RLBF0_H 0x806c0
+#define RLBF0_T 0x806c4
+#define RLBF1_H 0x806c8
+#define RLBF1_T 0x806cc
+#define RLBC_H 0x806d0
+#define RLBC_T 0x806d4
+#define RLBC_H2 0x806d8
+#define TLBF_H 0x806e0
+#define TLBF_T 0x806e4
+#define RLBF0_C 0x806e8
+#define RLBF1_C 0x806ec
+#define RXTHRSH 0x806f0
+#define LITHRSH 0x806f4
+
+#define LBARB 0x80700
+#define SLICE_X(x) (x<<28)
+#define ARB_RNUM_MAX(x) (x<<23)
+#define TH_PRTY(x) (x<<21)
+#define RH_PRTY(x) (x<<19)
+#define TL_PRTY(x) (x<<17)
+#define RL_PRTY(x) (x<<15)
+#define BUS_MULTI(x) (x<<8)
+#define NET_PREF(x) (x)
+
+#define SDRAMCON 0x80704
+#define BANK_ON (1<<14)
+#define WIDE_DATA (1<<13)
+#define TWR_WAIT (1<<12)
+#define TRP_WAIT (1<<11)
+#define TRAS_WAIT (1<<10)
+#define REF_RATE(x) (x)
+
+#define LBSTAT 0x80708
+
+#define RCC_STAT 0x8070c
+#define RCC_BUSY (1)
+
+#define TCMCONFIG 0x80740
+#define TM_DESL2 (1<<10)
+#define TM_BANK_WAIT(x) (x<<6)
+#define TM_ADD_BANK4(x) (x<<4)
+#define TM_PAR_CHECK(x) (x<<3)
+#define TM_RW_WAIT(x) (x<<2)
+#define TM_SRAM_TYPE(x) (x)
+
+#define TSRB_BA 0x80744
+#define TSRC_BA 0x80748
+#define TMABR_BA 0x8074c
+#define TPD_BA 0x80750
+#define TSRD_BA 0x80758
+
+#define TX_CONFIG 0x80760
+#define DRF_THRESH(x) (x<<22)
+#define TX_UT_MODE(x) (x<<21)
+#define TX_VCI_MASK(x) (x<<17)
+#define LBFREE_CNT(x) (x)
+
+#define TXAAL5_PROTO 0x80764
+#define CPCS_UU(x) (x<<8)
+#define CPI(x) (x)
+
+#define RCMCONFIG 0x80780
+#define RM_DESL2(x) (x<<10)
+#define RM_BANK_WAIT(x) (x<<6)
+#define RM_ADD_BANK(x) (x<<4)
+#define RM_PAR_CHECK(x) (x<<3)
+#define RM_RW_WAIT(x) (x<<2)
+#define RM_SRAM_TYPE(x) (x)
+
+#define RCMRSRB_BA 0x80784
+#define RCMLBM_BA 0x80788
+#define RCMABR_BA 0x8078c
+
+#define RC_CONFIG 0x807c0
+#define UT_RD_DELAY(x) (x<<11)
+#define WRAP_MODE(x) (x<<10)
+#define RC_UT_MODE(x) (x<<9)
+#define RX_ENABLE (1<<8)
+#define RX_VALVP(x) (x<<4)
+#define RX_VALVC(x) (x)
+
+#define MCC 0x807c4
+#define OEC 0x807c8
+#define DCC 0x807cc
+#define CEC 0x807d0
+
+#define HSP_BA 0x807f0
+
+#define LB_CONFIG 0x807f4
+#define LB_SIZE(x) (x)
+
+#define CON_DAT 0x807f8
+#define CON_CTL 0x807fc
+#define CON_CTL_MBOX (2<<30)
+#define CON_CTL_TCM (1<<30)
+#define CON_CTL_RCM (0<<30)
+#define CON_CTL_WRITE (1<<29)
+#define CON_CTL_READ (0<<29)
+#define CON_CTL_BUSY (1<<28)
+#define CON_BYTE_DISABLE_3 (1<<22) /* 24..31 */
+#define CON_BYTE_DISABLE_2 (1<<21) /* 16..23 */
+#define CON_BYTE_DISABLE_1 (1<<20) /* 8..15 */
+#define CON_BYTE_DISABLE_0 (1<<19) /* 0..7 */
+#define CON_CTL_ADDR(x) (x)
+
+#define FRAMER 0x80800 /* to 0x80bfc */
+
+/* 3.3 network controller (internal) mailbox registers */
+
+#define CS_STPER0 0x0
+ /* ... */
+#define CS_STPER31 0x01f
+
+#define CS_STTIM0 0x020
+ /* ... */
+#define CS_STTIM31 0x03f
+
+#define CS_TGRLD0 0x040
+ /* ... */
+#define CS_TGRLD15 0x04f
+
+#define CS_ERTHR0 0x050
+#define CS_ERTHR1 0x051
+#define CS_ERTHR2 0x052
+#define CS_ERTHR3 0x053
+#define CS_ERTHR4 0x054
+#define CS_ERCTL0 0x055
+#define TX_ENABLE (1<<28)
+#define ER_ENABLE (1<<27)
+#define CS_ERCTL1 0x056
+#define CS_ERCTL2 0x057
+#define CS_ERSTAT0 0x058
+#define CS_ERSTAT1 0x059
+
+#define CS_RTCCT 0x060
+#define CS_RTFWC 0x061
+#define CS_RTFWR 0x062
+#define CS_RTFTC 0x063
+#define CS_RTATR 0x064
+
+#define CS_TFBSET 0x070
+#define CS_TFBADD 0x071
+#define CS_TFBSUB 0x072
+#define CS_WCRMAX 0x073
+#define CS_WCRMIN 0x074
+#define CS_WCRINC 0x075
+#define CS_WCRDEC 0x076
+#define CS_WCRCEIL 0x077
+#define CS_BWDCNT 0x078
+
+#define CS_OTPPER 0x080
+#define CS_OTWPER 0x081
+#define CS_OTTLIM 0x082
+#define CS_OTTCNT 0x083
+
+#define CS_HGRRT0 0x090
+ /* ... */
+#define CS_HGRRT7 0x097
+
+#define CS_ORPTRS 0x0a0
+
+#define RXCON_CLOSE 0x100
+
+
+#define RCM_MEM_SIZE 0x10000 /* 1M of 32-bit registers */
+#define TCM_MEM_SIZE 0x20000 /* 2M of 32-bit registers */
+
+/* 2.5 transmit connection memory registers */
+
+#define TSR0_CONN_STATE(x) ((x>>28) & 0x7)
+#define TSR0_USE_WMIN (1<<23)
+#define TSR0_GROUP(x) ((x & 0x7)<<18)
+#define TSR0_ABR (2<<16)
+#define TSR0_UBR (1<<16)
+#define TSR0_CBR (0<<16)
+#define TSR0_PROT (1<<15)
+#define TSR0_AAL0_SDU (2<<12)
+#define TSR0_AAL0 (1<<12)
+#define TSR0_AAL5 (0<<12)
+#define TSR0_HALT_ER (1<<11)
+#define TSR0_MARK_CI (1<<10)
+#define TSR0_MARK_ER (1<<9)
+#define TSR0_UPDATE_GER (1<<8)
+#define TSR0_RC_INDEX(x) (x & 0x1F)
+
+#define TSR1_PCR(x) ((x & 0x7FFF)<<16)
+#define TSR1_MCR(x) (x & 0x7FFF)
+
+#define TSR2_ACR(x) ((x & 0x7FFF)<<16)
+
+#define TSR3_NRM_CNT(x) ((x & 0xFF)<<24)
+#define TSR3_CRM_CNT(x) (x & 0xFFFF)
+
+#define TSR4_FLUSH_CONN (1<<31)
+#define TSR4_SESSION_ENDED (1<<30)
+#define TSR4_CRC10 (1<<28)
+#define TSR4_NULL_CRC10 (1<<27)
+#define TSR4_PROT (1<<26)
+#define TSR4_AAL0_SDU (2<<23)
+#define TSR4_AAL0 (1<<23)
+#define TSR4_AAL5 (0<<23)
+
+#define TSR9_OPEN_CONN (1<<20)
+
+#define TSR11_ICR(x) ((x & 0x7FFF)<<16)
+#define TSR11_TRM(x) ((x & 0x7)<<13)
+#define TSR11_NRM(x) ((x & 0x7)<<10)
+#define TSR11_ADTF(x) (x & 0x3FF)
+
+#define TSR13_RDF(x) ((x & 0xF)<<23)
+#define TSR13_RIF(x) ((x & 0xF)<<19)
+#define TSR13_CDF(x) ((x & 0x7)<<16)
+#define TSR13_CRM(x) (x & 0xFFFF)
+
+#define TSR14_DELETE (1<<31)
+#define TSR14_ABR_CLOSE (1<<16)
+
+/* 2.7.1 per connection receieve state registers */
+
+#define RSR0_START_PDU (1<<10)
+#define RSR0_OPEN_CONN (1<<6)
+#define RSR0_CLOSE_CONN (0<<6)
+#define RSR0_PPD_ENABLE (1<<5)
+#define RSR0_EPD_ENABLE (1<<4)
+#define RSR0_TCP_CKSUM (1<<3)
+#define RSR0_AAL5 (0)
+#define RSR0_AAL0 (1)
+#define RSR0_AAL0_SDU (2)
+#define RSR0_RAWCELL (3)
+#define RSR0_RAWCELL_CRC10 (4)
+
+#define RSR1_AQI_ENABLE (1<<20)
+#define RSR1_RBPL_ONLY (1<<19)
+#define RSR1_GROUP(x) ((x)<<16)
+
+#define RSR4_AQI_ENABLE (1<<30)
+#define RSR4_GROUP(x) ((x)<<27)
+#define RSR4_RBPL_ONLY (1<<26)
+
+/* 2.1.4 transmit packet descriptor */
+
+#define TPD_USERCELL 0x0
+#define TPD_SEGMENT_OAMF5 0x4
+#define TPD_END2END_OAMF5 0x5
+#define TPD_RMCELL 0x6
+#define TPD_CELLTYPE(x) (x<<3)
+#define TPD_EOS (1<<2)
+#define TPD_CLP (1<<1)
+#define TPD_INT (1<<0)
+#define TPD_LST (1<<31)
+
+/* table 4.3 serial eeprom information */
+
+#define PROD_ID 0x08 /* char[] */
+#define PROD_ID_LEN 30
+#define HW_REV 0x26 /* char[] */
+#define M_SN 0x3a /* integer */
+#define MEDIA 0x3e /* integer */
+#define HE155MM 0x26
+#define HE155SM 0x27
+#define HE622MM 0x46
+#define HE622SM 0x47
+#define MAC_ADDR 0x42 /* char[] */
+
+#define CS_LOW 0x0
+#define CS_HIGH ID_CS /* HOST_CNTL_ID_PROM_SEL */
+#define CLK_LOW 0x0
+#define CLK_HIGH ID_CLOCK /* HOST_CNTL_ID_PROM_CLOCK */
+#define SI_HIGH ID_DIN /* HOST_CNTL_ID_PROM_DATA_IN */
+#define EEPROM_DELAY 400 /* microseconds */
+
+/* Read from EEPROM = 0000 0011b */
+unsigned int readtab[] = {
+ CS_HIGH | CLK_HIGH,
+ CS_LOW | CLK_LOW,
+ CLK_HIGH, /* 0 */
+ CLK_LOW,
+ CLK_HIGH, /* 0 */
+ CLK_LOW,
+ CLK_HIGH, /* 0 */
+ CLK_LOW,
+ CLK_HIGH, /* 0 */
+ CLK_LOW,
+ CLK_HIGH, /* 0 */
+ CLK_LOW,
+ CLK_HIGH, /* 0 */
+ CLK_LOW | SI_HIGH,
+ CLK_HIGH | SI_HIGH, /* 1 */
+ CLK_LOW | SI_HIGH,
+ CLK_HIGH | SI_HIGH /* 1 */
+};
+
+/* Clock to read from/write to the EEPROM */
+unsigned int clocktab[] = {
+ CLK_LOW,
+ CLK_HIGH,
+ CLK_LOW,
+ CLK_HIGH,
+ CLK_LOW,
+ CLK_HIGH,
+ CLK_LOW,
+ CLK_HIGH,
+ CLK_LOW,
+ CLK_HIGH,
+ CLK_LOW,
+ CLK_HIGH,
+ CLK_LOW,
+ CLK_HIGH,
+ CLK_LOW,
+ CLK_HIGH,
+ CLK_LOW
+};
+
+
+#endif /* _HE_H_ */
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index 3aa68030218c..70dc69bb75ce 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -1008,11 +1008,8 @@ int slm_init( void )
devfs_mk_dir("slm");
for (i = 0; i < MAX_SLM; i++) {
- char name[16];
- sprintf(name, "slm/%d", i);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- ACSI_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR,
- &slm_fops, NULL);
+ devfs_mk_cdev(MKDEV(ACSI_MAJOR, i),
+ S_IFCHR|S_IRUSR|S_IWUSR, "slm/%d", i);
}
return 0;
}
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 84cdd1c6006b..ef225d2e6685 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -652,11 +652,8 @@ static int __init pg_init(void)
devfs_mk_dir ("pg");
for (unit=0; unit<PG_UNITS; unit++)
if (PG.present) {
- char name[16];
- sprintf(name, "pg/%u", unit);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- major, unit, S_IFCHR | S_IRUSR | S_IWUSR,
- &pg_fops, NULL);
+ devfs_mk_cdev(MKDEV(major, unit),
+ S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u", unit);
}
return 0;
}
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index fca579eb6ad0..c9541f651087 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -914,15 +914,12 @@ static int __init pt_init(void)
devfs_mk_dir ("pt");
for (unit=0;unit<PT_UNITS;unit++)
if (PT.present) {
- char name[16];
- sprintf(name, "pt/%d", unit);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- major, unit, S_IFCHR | S_IRUSR | S_IWUSR,
- &pt_fops, NULL);
- sprintf(name, "pt/%dn", unit);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- major, 128 + unit, S_IFCHR | S_IRUSR | S_IWUSR,
- &pt_fops, NULL);
+ devfs_mk_cdev(MKDEV(major, unit),
+ S_IFCHR | S_IRUSR | S_IWUSR,
+ "pt/%d", unit);
+ devfs_mk_cdev(MKDEV(major, unit + 128),
+ S_IFCHR | S_IRUSR | S_IWUSR,
+ "pt/%dn", unit);
}
return 0;
}
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 810ba628f075..c717872fad83 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1528,7 +1528,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
if (tty_hung_up_p(filp)) {
DBG_CNT("before DEC-hung");
- MOD_DEC_USE_COUNT;
local_irq_restore(flags);
return;
}
@@ -1555,7 +1554,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
}
if (state->count) {
DBG_CNT("before DEC-2");
- MOD_DEC_USE_COUNT;
local_irq_restore(flags);
return;
}
@@ -1615,7 +1613,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
- MOD_DEC_USE_COUNT;
local_irq_restore(flags);
}
@@ -1894,15 +1891,12 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
int retval, line;
unsigned long page;
- MOD_INC_USE_COUNT;
line = tty->index;
if ((line < 0) || (line >= NR_PORTS)) {
- MOD_DEC_USE_COUNT;
return -ENODEV;
}
retval = get_async_struct(line, &info);
if (retval) {
- MOD_DEC_USE_COUNT;
return retval;
}
tty->driver_data = info;
@@ -2116,6 +2110,7 @@ static int __init rs_init(void)
memset(&serial_driver, 0, sizeof(struct tty_driver));
serial_driver.magic = TTY_DRIVER_MAGIC;
+ serial_driver.owner = THIS_MODULE;
serial_driver.driver_name = "amiserial";
serial_driver.name = "ttyS";
serial_driver.major = TTY_MAJOR;
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index eb42b54d5646..3a3910c60aa1 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2579,15 +2579,12 @@ cy_open(struct tty_struct *tty, struct file * filp)
int retval, line;
unsigned long page;
- MOD_INC_USE_COUNT;
line = tty->index;
if ((line < 0) || (NR_PORTS <= line)){
- MOD_DEC_USE_COUNT;
return -ENODEV;
}
info = &cy_port[line];
if (info->line < 0){
- MOD_DEC_USE_COUNT;
return -ENODEV;
}
@@ -2607,7 +2604,6 @@ cy_open(struct tty_struct *tty, struct file * filp)
} else {
printk("cyc:Cyclades-Z firmware not yet loaded\n");
}
- MOD_DEC_USE_COUNT;
return -ENODEV;
}
#ifdef CONFIG_CYZ_INTR
@@ -2803,7 +2799,6 @@ cy_close(struct tty_struct *tty, struct file *filp)
CY_LOCK(info, flags);
/* If the TTY is being hung up, nothing to do */
if (tty_hung_up_p(filp)) {
- MOD_DEC_USE_COUNT;
CY_UNLOCK(info, flags);
return;
}
@@ -2834,7 +2829,6 @@ cy_close(struct tty_struct *tty, struct file *filp)
info->count = 0;
}
if (info->count) {
- MOD_DEC_USE_COUNT;
CY_UNLOCK(info, flags);
return;
}
@@ -2931,7 +2925,6 @@ cy_close(struct tty_struct *tty, struct file *filp)
printk(" cyc:cy_close done\n");
#endif
- MOD_DEC_USE_COUNT;
CY_UNLOCK(info, flags);
return;
} /* cy_close */
@@ -5494,6 +5487,7 @@ cy_init(void)
memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
cy_serial_driver.magic = TTY_DRIVER_MAGIC;
+ cy_serial_driver.owner = THIS_MODULE;
cy_serial_driver.driver_name = "cyclades";
cy_serial_driver.name = "ttyC";
cy_serial_driver.major = CYCLADES_MAJOR;
diff --git a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h
index 2ea8e6f431a5..4d38e7bcb06b 100644
--- a/drivers/char/drm/drm_drv.h
+++ b/drivers/char/drm/drm_drv.h
@@ -334,7 +334,6 @@ static int DRM(setup)( drm_device_t *dev )
dev->last_context = 0;
dev->last_switch = 0;
dev->last_checked = 0;
- init_timer( &dev->timer );
init_waitqueue_head( &dev->context_wait );
dev->ctx_start = 0;
@@ -590,6 +589,7 @@ static int __init drm_init( void )
dev = &(DRM(device)[i]);
memset( (void *)dev, 0, sizeof(*dev) );
dev->count_lock = SPIN_LOCK_UNLOCKED;
+ init_timer( &dev->timer );
sema_init( &dev->struct_sem, 1 );
if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 281b0cf0a5d6..6cc50669a385 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -903,8 +903,8 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
entry->busaddr[page_ofs]);
- DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n",
- entry->busaddr[page_ofs],
+ DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
+ (unsigned long) entry->busaddr[page_ofs],
entry->handle + tmp_ofs );
}
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 8695de8ed256..d9cf9097afeb 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -512,10 +512,9 @@ static int __init dsp56k_init_driver(void)
printk("DSP56k driver: Unable to register driver\n");
return -ENODEV;
}
- devfs_register(NULL, "dsp56k", DEVFS_FL_DEFAULT,
- DSP56K_MAJOR, 0,
- S_IFCHR | S_IRUSR | S_IWUSR,
- &dsp56k_fops, NULL);
+
+ devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
+ S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");
printk(banner);
return 0;
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index 6c839bd36437..a33423cea256 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -345,10 +345,9 @@ static int __init dtlk_init(void)
}
if (dtlk_dev_probe() == 0)
printk(", MAJOR %d\n", dtlk_major);
- devfs_register(NULL, "dtlk", DEVFS_FL_DEFAULT,
- dtlk_major, DTLK_MINOR,
- S_IFCHR | S_IRUSR | S_IWUSR,
- &dtlk_fops, NULL);
+
+ devfs_mk_cdev(MKDEV(dtlk_major, DTLK_MINOR),
+ S_IFCHR | S_IRUSR | S_IWUSR, "dtlk");
init_timer(&dtlk_timer);
dtlk_timer.function = dtlk_timer_tick;
diff --git a/drivers/char/dz.c b/drivers/char/dz.c
index 12a14689253f..cfaf302a5d0c 100644
--- a/drivers/char/dz.c
+++ b/drivers/char/dz.c
@@ -1332,6 +1332,7 @@ int __init dz_init(void)
memset(&serial_driver, 0, sizeof(struct tty_driver));
serial_driver.magic = TTY_DRIVER_MAGIC;
+ serial_driver.owner = THIS_MODULE;
#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
serial_driver.name = "ttyS";
#else
@@ -1425,8 +1426,8 @@ int __init dz_init(void)
printk("ttyS%02d at 0x%08x (irq = %d)\n", info->line,
info->port, SERIAL);
- tty_register_device(&serial_driver, info->line);
- tty_register_device(&callout_driver, info->line);
+ tty_register_device(&serial_driver, info->line, NULL);
+ tty_register_device(&callout_driver, info->line, NULL);
}
/* Reset the chip */
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 614ff9f1e782..24bd70aac2e9 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -643,9 +643,7 @@ static _INLINE_ void check_modem_status(struct esp_struct *info)
#ifdef SERIAL_DEBUG_OPEN
printk("scheduling hangup...");
#endif
- MOD_INC_USE_COUNT;
- if (schedule_task(&info->tqueue_hangup) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_task(&info->tqueue_hangup);
}
}
}
@@ -811,7 +809,6 @@ static void do_serial_hangup(void *private_)
tty = info->tty;
if (tty)
tty_hangup(tty);
- MOD_DEC_USE_COUNT;
}
/*
@@ -2132,7 +2129,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
-out: MOD_DEC_USE_COUNT;
+out:
restore_flags(flags);
}
@@ -2375,7 +2372,6 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
#ifdef SERIAL_DEBUG_OPEN
printk("esp_open %s, count = %d\n", tty->name, info->count);
#endif
- MOD_INC_USE_COUNT;
info->count++;
tty->driver_data = info;
info->tty = tty;
@@ -2551,6 +2547,7 @@ int __init espserial_init(void)
memset(&esp_driver, 0, sizeof(struct tty_driver));
esp_driver.magic = TTY_DRIVER_MAGIC;
+ esp_driver.owner = THIS_MODULE;
esp_driver.name = "ttyP";
esp_driver.major = ESP_IN_MAJOR;
esp_driver.minor_start = 0;
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
index 21214e71db87..f329f86a4dd1 100644
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ b/drivers/char/ftape/zftape/zftape-init.c
@@ -342,38 +342,24 @@ KERN_INFO
TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
for (i = 0; i < 4; i++) {
- char devname[9];
-
- sprintf (devname, "qft%i", i);
- devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
- QIC117_TAPE_MAJOR, i,
+ devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR,
- &zft_cdev, NULL);
- sprintf (devname, "nqft%i", i);
- devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
- QIC117_TAPE_MAJOR, i + 4,
+ "qft%i", i);
+ devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
S_IFCHR | S_IRUSR | S_IWUSR,
- &zft_cdev, NULL);
- sprintf (devname, "zqft%i", i);
- devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
- QIC117_TAPE_MAJOR, i + 16,
+ "nqft%i", i);
+ devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
S_IFCHR | S_IRUSR | S_IWUSR,
- &zft_cdev, NULL);
- sprintf (devname, "nzqft%i", i);
- devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
- QIC117_TAPE_MAJOR, i + 20,
+ "zqft%i", i);
+ devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
S_IFCHR | S_IRUSR | S_IWUSR,
- &zft_cdev, NULL);
- sprintf (devname, "rawqft%i", i);
- devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
- QIC117_TAPE_MAJOR, i + 32,
+ "nzqft%i", i);
+ devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
S_IFCHR | S_IRUSR | S_IWUSR,
- &zft_cdev, NULL);
- sprintf (devname, "nrawqft%i", i);
- devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
- QIC117_TAPE_MAJOR, i + 36,
+ "rawqft%i", i);
+ devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
S_IFCHR | S_IRUSR | S_IWUSR,
- &zft_cdev, NULL);
+ "nrawqft%i", i);
}
#ifdef CONFIG_ZFT_COMPRESSOR
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index d7a555153284..9a9f0d79e10c 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -257,6 +257,7 @@ int __init hvc_init(void)
memset(&hvc_driver, 0, sizeof(struct tty_driver));
hvc_driver.magic = TTY_DRIVER_MAGIC;
+ hvc_driver.owner = THIS_MODULE;
hvc_driver.driver_name = "hvc";
hvc_driver.name = "hvc/";
hvc_driver.major = HVC_MAJOR;
@@ -282,7 +283,7 @@ int __init hvc_init(void)
for (i = 0; i < hvc_driver.num; i++) {
hvc_struct[i].lock = SPIN_LOCK_UNLOCKED;
hvc_struct[i].index = i;
- tty_register_device(&hvc_driver, i);
+ tty_register_device(&hvc_driver, i, NULL);
}
if (tty_register_driver(&hvc_driver))
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index 249f4ed44cbb..0d3e2b30621f 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -793,6 +793,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
/* Initialise the relevant fields. */
ip2_tty_driver.magic = TTY_DRIVER_MAGIC;
+ ip2_tty_driver.owner = THIS_MODULE;
ip2_tty_driver.name = pcTty;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
ip2_tty_driver.driver_name = pcDriver_name;
@@ -869,29 +870,19 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
*/
for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-#ifdef CONFIG_DEVFS_FS
- char name[16];
-#endif
-
if ( 0 == ip2config.addr[i] ) {
continue;
}
#ifdef CONFIG_DEVFS_FS
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
- sprintf( name, "ip2/ipl%d", i );
- devfs_register(NULL, name,
- DEVFS_FL_DEFAULT,
- IP2_IPL_MAJOR, 4 * i,
+ devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
- &ip2_ipl, NULL);
+ "ip2/ipl%d", i);
- sprintf( name, "ip2/stat%d", i );
- devfs_register(NULL, name,
- DEVFS_FL_DEFAULT,
- IP2_IPL_MAJOR, 4 * i + 1,
+ devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
- &ip2_ipl, NULL);
+ "ip2/stat%d", i);
for ( box = 0; box < ABS_MAX_BOXES; ++box )
{
@@ -901,10 +892,10 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
{
tty_register_device(&ip2_tty_driver,
j + ABS_BIGGEST_BOX *
- (box+i*ABS_MAX_BOXES));
+ (box+i*ABS_MAX_BOXES), NULL);
tty_register_device(&ip2_callout_driver,
j + ABS_BIGGEST_BOX *
- (box+i*ABS_MAX_BOXES));
+ (box+i*ABS_MAX_BOXES), NULL);
}
}
}
@@ -1577,7 +1568,6 @@ ip2_open( PTTY tty, struct file *pFile )
/* Setup pointer links in device and tty structures */
pCh->pTTY = tty;
tty->driver_data = pCh;
- MOD_INC_USE_COUNT;
#ifdef IP2DEBUG_OPEN
printk(KERN_DEBUG \
@@ -1777,14 +1767,12 @@ ip2_close( PTTY tty, struct file *pFile )
#endif
if ( tty_hung_up_p ( pFile ) ) {
- MOD_DEC_USE_COUNT;
ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 );
return;
}
if ( tty->count > 1 ) { /* not the last close */
- MOD_DEC_USE_COUNT;
ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 );
@@ -1852,7 +1840,6 @@ ip2_close( PTTY tty, struct file *pFile )
DBG_CNT("ip2_close: after wakeups--");
#endif
- MOD_DEC_USE_COUNT;
ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 7d15f69ba8a4..0457f37d0a08 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -441,24 +441,17 @@ MODULE_PARM(ipmi_major, "i");
static void ipmi_new_smi(int if_num)
{
- char name[10];
-
- if (if_num > MAX_DEVICES)
- return;
-
- snprintf(name, sizeof(name), "ipmidev/%d", if_num);
-
- devfs_register(NULL, name, 0, ipmi_major, if_num,
- S_IFCHR | S_IRUSR | S_IWUSR,
- &ipmi_fops, NULL);
+ if (if_num <= MAX_DEVICES) {
+ devfs_mk_cdev(MKDEV(ipmi_major, if_num),
+ S_IFCHR | S_IRUSR | S_IWUSR,
+ "ipmidev/%d", if_num);
+ }
}
static void ipmi_smi_gone(int if_num)
{
- if (if_num > MAX_DEVICES)
- return;
-
- devfs_remove("ipmidev/%d", if_num);
+ if (if_num <= MAX_DEVICES)
+ devfs_remove("ipmidev/%d", if_num);
}
static struct ipmi_smi_watcher smi_watcher =
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 8e82ff0a6dce..6e3edc28f7e1 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -590,9 +590,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id,
port->status &= ~ISI_DCD;
if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
(port->flags & ASYNC_CALLOUT_NOHUP))) {
- MOD_INC_USE_COUNT;
- if (schedule_task(&port->hangup_tq) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_task(&port->hangup_tq);
}
}
}
@@ -846,7 +844,6 @@ static inline void isicom_setup_board(struct isi_board * bp)
#endif
bp->status |= BOARD_ACTIVE;
- MOD_INC_USE_COUNT;
return;
}
@@ -1104,7 +1101,6 @@ static inline void isicom_shutdown_board(struct isi_board * bp)
for(channel = 0; channel < bp->port_count; channel++, port++) {
drop_dtr_rts(port);
}
- MOD_DEC_USE_COUNT;
}
static void isicom_shutdown_port(struct isi_port * port)
@@ -1644,7 +1640,6 @@ static void do_isicom_hangup(void * data)
tty = port->tty;
if (tty)
tty_hangup(tty); /* FIXME: module removal race here - AKPM */
- MOD_DEC_USE_COUNT;
}
static void isicom_hangup(struct tty_struct * tty)
@@ -1715,6 +1710,7 @@ static int register_drivers(void)
/* tty driver structure initialization */
memset(&isicom_normal, 0, sizeof(struct tty_driver));
isicom_normal.magic = TTY_DRIVER_MAGIC;
+ isicom_normal.owner = THIS_MODULE;
isicom_normal.name = "ttyM";
isicom_normal.major = ISICOM_NMAJOR;
isicom_normal.minor_start = 0;
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index cde0672544c6..96b296654e36 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -1054,7 +1054,6 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
if (portp->devnr < 1)
return(-ENODEV);
- MOD_INC_USE_COUNT;
/*
* Check if this port is in the middle of closing. If so then wait
@@ -1170,14 +1169,12 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
save_flags(flags);
cli();
if (tty_hung_up_p(filp)) {
- MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
if ((tty->count == 1) && (portp->refcount != 1))
portp->refcount = 1;
if (portp->refcount-- > 1) {
- MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
@@ -1232,7 +1229,6 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
portp->flags &= ~(ASYNC_CALLOUT_ACTIVE | ASYNC_NORMAL_ACTIVE |
ASYNC_CLOSING);
wake_up_interruptible(&portp->close_wait);
- MOD_DEC_USE_COUNT;
restore_flags(flags);
}
@@ -2369,7 +2365,6 @@ static void stli_dohangup(void *arg)
tty_hangup(portp->tty);
}
}
- MOD_DEC_USE_COUNT;
}
/*****************************************************************************/
@@ -3004,9 +2999,7 @@ static inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) &&
(portp->flags & ASYNC_CALLOUT_NOHUP))) {
if (tty != (struct tty_struct *) NULL) {
- MOD_INC_USE_COUNT;
- if (schedule_task(&portp->tqhangup) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_task(&portp->tqhangup);
}
}
}
@@ -5336,12 +5329,9 @@ int __init stli_init(void)
devfs_mk_dir("staliomem");
for (i = 0; i < 4; i++) {
- char name[16];
- sprintf(name, "staliomem/%d", i);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- STL_SIOMEMMAJOR, i,
+ devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR,
- &stli_fsiomem, NULL);
+ "staliomem/%d", i);
}
/*
@@ -5350,6 +5340,7 @@ int __init stli_init(void)
*/
memset(&stli_serial, 0, sizeof(struct tty_driver));
stli_serial.magic = TTY_DRIVER_MAGIC;
+ stli_serial.owner = THIS_MODULE;
stli_serial.driver_name = stli_drvname;
stli_serial.name = stli_serialname;
stli_serial.major = STL_SERIALMAJOR;
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index dd9b1dd4e828..049d12f1a24a 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -1047,8 +1047,8 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
- if (keycode == KEY_SYSRQ && !rep) {
- sysrq_down = sysrq_alt && down;
+ if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
+ sysrq_down = down;
return;
}
if (sysrq_down && down && !rep) {
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 95dc6955cb94..6f3ba6d76be7 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -784,8 +784,6 @@ static int __init lp_setup (char *str)
static int lp_register(int nr, struct parport *port)
{
- char name[16];
-
lp_table[nr].dev = parport_register_device(port, "lp",
lp_preempt, NULL, NULL, 0,
(void *) &lp_table[nr]);
@@ -796,11 +794,8 @@ static int lp_register(int nr, struct parport *port)
if (reset)
lp_reset(nr);
- sprintf (name, "printers/%d", nr);
- devfs_register (NULL, name,
- DEVFS_FL_DEFAULT, LP_MAJOR, nr,
- S_IFCHR | S_IRUGO | S_IWUGO,
- &lp_fops, NULL);
+ devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
+ "printers/%d", nr);
printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name,
(port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 83a098708a74..e4fb4f44f599 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -660,15 +660,16 @@ static int memory_open(struct inode * inode, struct file * filp)
return 0;
}
-void __init memory_devfs_register (void)
-{
- /* These are never unregistered */
- static const struct {
- unsigned short minor;
- char *name;
- umode_t mode;
- struct file_operations *fops;
- } list[] = { /* list of minor devices */
+static struct file_operations memory_fops = {
+ .open = memory_open, /* just a selector for the real open */
+};
+
+static const struct {
+ unsigned int minor;
+ char *name;
+ umode_t mode;
+ struct file_operations *fops;
+} devlist[] = { /* list of minor devices */
{1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
{2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
{3, "null", S_IRUGO | S_IWUGO, &null_fops},
@@ -680,25 +681,20 @@ void __init memory_devfs_register (void)
{8, "random", S_IRUGO | S_IWUSR, &random_fops},
{9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops},
{11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops},
- };
- int i;
-
- for (i=0; i<(sizeof(list)/sizeof(*list)); i++)
- devfs_register (NULL, list[i].name, DEVFS_FL_NONE,
- MEM_MAJOR, list[i].minor,
- list[i].mode | S_IFCHR,
- list[i].fops, NULL);
-}
-
-static struct file_operations memory_fops = {
- .open = memory_open, /* just a selector for the real open */
};
-int __init chr_dev_init(void)
+static int __init chr_dev_init(void)
{
+ int i;
+
if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
- memory_devfs_register();
+
+ for (i = 0; i < ARRAY_SIZE(devlist); i++) {
+ devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor),
+ S_IFCHR | devlist[i].mode, devlist[i].name);
+ }
+
rand_initialize();
#if defined (CONFIG_FB)
fbmem_init();
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 1e1126d91fe8..56190ca4512c 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -200,8 +200,8 @@ int misc_register(struct miscdevice * misc)
"misc/%s", misc->name);
}
- devfs_register(NULL, misc->devfs_name, 0, MISC_MAJOR, misc->minor,
- S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->fops, NULL);
+ devfs_mk_cdev(MKDEV(MISC_MAJOR, misc->minor),
+ S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->devfs_name);
/*
* Add it to the front, so that later devices can "override"
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index e942e6ed978b..a098dd65294e 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -341,6 +341,7 @@ int moxa_init(void)
memset(&moxaDriver, 0, sizeof(struct tty_driver));
memset(&moxaCallout, 0, sizeof(struct tty_driver));
moxaDriver.magic = TTY_DRIVER_MAGIC;
+ moxaDriver.owner = THIS_MODULE;
moxaDriver.name = "ttya";
moxaDriver.major = ttymajor;
moxaDriver.minor_start = 0;
@@ -544,7 +545,6 @@ static void do_moxa_softint(void *private_)
ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
}
}
- MOD_DEC_USE_COUNT;
}
static int moxa_open(struct tty_struct *tty, struct file *filp)
@@ -556,7 +556,6 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
port = PORTNO(tty);
if (port == MAX_PORTS) {
- MOD_INC_USE_COUNT;
return (0);
}
if (!MoxaPortIsValid(port)) {
@@ -579,7 +578,6 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
}
up(&moxaBuffSem);
- MOD_INC_USE_COUNT;
ch = &moxaChannels[port];
ch->count++;
tty->driver_data = ch;
@@ -619,7 +617,6 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
port = PORTNO(tty);
if (port == MAX_PORTS) {
- MOD_DEC_USE_COUNT;
return;
}
if (!MoxaPortIsValid(port)) {
@@ -633,7 +630,6 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
return;
}
if (tty_hung_up_p(filp)) {
- MOD_DEC_USE_COUNT;
return;
}
ch = (struct moxa_str *) tty->driver_data;
@@ -649,7 +645,6 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
ch->count = 0;
}
if (ch->count) {
- MOD_DEC_USE_COUNT;
return;
}
ch->asyncflags |= ASYNC_CLOSING;
@@ -688,7 +683,6 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |
ASYNC_CLOSING);
wake_up_interruptible(&ch->close_wait);
- MOD_DEC_USE_COUNT;
}
static int moxa_write(struct tty_struct *tty, int from_user,
@@ -1024,9 +1018,7 @@ static void moxa_poll(unsigned long ignored)
wake_up_interruptible(&ch->open_wait);
else {
set_bit(MOXA_EVENT_HANGUP, &ch->event);
- MOD_DEC_USE_COUNT;
- if (schedule_work(&ch->tqueue) == 0)
- MOD_INC_USE_COUNT;
+ schedule_work(&ch->tqueue);
}
}
}
diff --git a/drivers/char/mwave/mwavedd.h b/drivers/char/mwave/mwavedd.h
index 0412b176818f..8eca61e0a19c 100644
--- a/drivers/char/mwave/mwavedd.h
+++ b/drivers/char/mwave/mwavedd.h
@@ -50,9 +50,11 @@
#define _LINUX_MWAVEDD_H
#include "3780i.h"
#include "tp3780i.h"
+#include "smapi.h"
#include "mwavepub.h"
#include <linux/ioctl.h>
#include <asm/uaccess.h>
+#include <linux/wait.h>
extern int mwave_debug;
extern int mwave_3780i_irq;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 7efe92eaf0d9..cd5b57bbbf7b 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -501,6 +501,7 @@ static int __init mxser_module_init(void)
memset(&mxvar_sdriver, 0, sizeof(struct tty_driver));
mxvar_sdriver.magic = TTY_DRIVER_MAGIC;
+ mxvar_sdriver.owner = THIS_MODULE;
mxvar_sdriver.name = "ttyM";
mxvar_sdriver.major = ttymajor;
mxvar_sdriver.minor_start = 0;
@@ -708,7 +709,6 @@ static void mxser_do_softint(void *private_)
tty_hangup(tty); /* FIXME: module removal race here - AKPM */
}
}
- MOD_DEC_USE_COUNT;
}
/*
@@ -767,8 +767,6 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
info->session = current->session;
info->pgrp = current->pgrp;
- MOD_INC_USE_COUNT;
-
return (0);
}
@@ -795,7 +793,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
if (tty_hung_up_p(filp)) {
restore_flags(flags);
- MOD_DEC_USE_COUNT;
return;
}
if ((tty->count == 1) && (info->count != 1)) {
@@ -817,7 +814,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
}
if (info->count) {
restore_flags(flags);
- MOD_DEC_USE_COUNT;
return;
}
info->flags |= ASYNC_CLOSING;
@@ -881,7 +877,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&info->close_wait);
restore_flags(flags);
- MOD_DEC_USE_COUNT;
}
static int mxser_write(struct tty_struct *tty, int from_user,
@@ -1492,9 +1487,7 @@ static inline void mxser_transmit_chars(struct mxser_struct *info)
if (info->xmit_cnt < WAKEUP_CHARS) {
set_bit(MXSER_EVENT_TXLOW, &info->event);
- MOD_INC_USE_COUNT;
- if (schedule_work(&info->tqueue) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_work(&info->tqueue);
}
if (info->xmit_cnt <= 0) {
info->IER &= ~UART_IER_THRI;
@@ -1523,9 +1516,7 @@ static inline void mxser_check_modem_status(struct mxser_struct *info,
else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
(info->flags & ASYNC_CALLOUT_NOHUP)))
set_bit(MXSER_EVENT_HANGUP, &info->event);
- MOD_INC_USE_COUNT;
- if (schedule_work(&info->tqueue) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_work(&info->tqueue);
}
if (info->flags & ASYNC_CTS_FLOW) {
if (info->tty->hw_stopped) {
@@ -1535,9 +1526,7 @@ static inline void mxser_check_modem_status(struct mxser_struct *info,
outb(info->IER, info->base + UART_IER);
set_bit(MXSER_EVENT_TXLOW, &info->event);
- MOD_INC_USE_COUNT;
- if (schedule_work(&info->tqueue) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_work(&info->tqueue);
}
} else {
if (!(status & UART_MSR_CTS)) {
diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c
index 1c18027b2494..a9b94161145b 100644
--- a/drivers/char/pcxx.c
+++ b/drivers/char/pcxx.c
@@ -431,8 +431,6 @@ int pcxe_open(struct tty_struct *tty, struct file * filp)
return(-ENODEV);
}
- /* flag the kernel that there is somebody using this guy */
- MOD_INC_USE_COUNT;
/*
* If the device is in the middle of being closed, then block
* until it's done, and then try again.
@@ -576,7 +574,6 @@ static void pcxe_close(struct tty_struct * tty, struct file * filp)
if(tty_hung_up_p(filp)) {
/* flag that somebody is done with this module */
- MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
@@ -594,7 +591,6 @@ static void pcxe_close(struct tty_struct * tty, struct file * filp)
}
if (info->count-- > 1) {
restore_flags(flags);
- MOD_DEC_USE_COUNT;
return;
}
if (info->count < 0) {
@@ -651,7 +647,6 @@ static void pcxe_close(struct tty_struct * tty, struct file * filp)
info->asyncflags &= ~(ASYNC_NORMAL_ACTIVE|
ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
- MOD_DEC_USE_COUNT;
restore_flags(flags);
}
}
@@ -1228,6 +1223,7 @@ int __init pcxe_init(void)
memset(&pcxe_driver, 0, sizeof(struct tty_driver));
pcxe_driver.magic = TTY_DRIVER_MAGIC;
+ pcxe_driver.owner = THIS_MODULE;
pcxe_driver.name = "ttyD";
pcxe_driver.major = DIGI_MAJOR;
pcxe_driver.minor_start = 0;
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 773f555dd989..b1e6721199e9 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -760,10 +760,8 @@ static int __init ppdev_init (void)
}
devfs_mk_dir("parports");
for (i = 0; i < PARPORT_MAX; i++) {
- char name[16];
- sprintf(name, "parports/%d", i);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT, PP_MAJOR, i,
- S_IFCHR | S_IRUGO | S_IWUGO, &pp_fops, NULL);
+ devfs_mk_cdev(MKDEV(PP_MAJOR, i),
+ S_IFCHR | S_IRUGO | S_IWUGO, "parports/%d", i);
}
printk (KERN_INFO PP_VERSION "\n");
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 6cd307819049..2278abad5f94 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1527,7 +1527,7 @@ random_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
* If we gave the user some bytes, update the access time.
*/
if (count != 0) {
- UPDATE_ATIME(file->f_dentry->d_inode);
+ update_atime(file->f_dentry->d_inode);
}
return (count ? count : retval);
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 08fd00d4fce4..3080b464e951 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -181,7 +181,7 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
}
if (rawdev->binding) {
bdput(rawdev->binding);
- MOD_DEC_USE_COUNT;
+ module_put(THIS_MODULE);
}
if (rq.block_major == 0 && rq.block_minor == 0) {
/* unbind */
@@ -191,7 +191,7 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
if (rawdev->binding == NULL)
err = -ENOMEM;
else
- try_module_get(THIS_MODULE);
+ __module_get(THIS_MODULE);
}
up(&raw_mutex);
} else {
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 29a076b73a97..346200367fca 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -389,29 +389,6 @@ void rio_udelay (int usecs)
udelay (usecs);
}
-
-void rio_inc_mod_count (void)
-{
-#ifdef MODULE
- func_enter ();
- rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_inc_mod_count\n");
- MOD_INC_USE_COUNT;
- func_exit ();
-#endif
-}
-
-
-void rio_dec_mod_count (void)
-{
-#ifdef MODULE
- func_enter ();
- rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_dec_mod_count\n");
- MOD_DEC_USE_COUNT;
- func_exit ();
-#endif
-}
-
-
static int rio_set_real_termios (void *ptr)
{
int rv, modem;
@@ -660,7 +637,6 @@ static void rio_hungup (void *ptr)
PortP = (struct Port *)ptr;
PortP->gs.tty = NULL;
- rio_dec_mod_count ();
func_exit ();
}
@@ -686,7 +662,6 @@ static void rio_close (void *ptr)
}
PortP->gs.tty = NULL;
- rio_dec_mod_count ();
func_exit ();
}
@@ -908,6 +883,7 @@ static int rio_init_drivers(void)
memset(&rio_driver, 0, sizeof(rio_driver));
rio_driver.magic = TTY_DRIVER_MAGIC;
+ rio_driver.owner = THIS_MODULE;
rio_driver.driver_name = "specialix_rio";
rio_driver.name = "ttySR";
rio_driver.major = RIO_NORMAL_MAJOR0;
diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h
index 7c71bfc7a147..1fba19d5b66a 100644
--- a/drivers/char/rio/rio_linux.h
+++ b/drivers/char/rio/rio_linux.h
@@ -87,9 +87,6 @@ struct vpd_prom {
#endif
-void rio_dec_mod_count (void);
-void rio_inc_mod_count (void);
-
/* Allow us to debug "in the field" without requiring clients to
recompile.... */
#if 1
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
index 4e4a268231d1..d851c86baf90 100644
--- a/drivers/char/rio/riotty.c
+++ b/drivers/char/rio/riotty.c
@@ -139,7 +139,6 @@ default_sg =
extern struct rio_info *p;
-extern void rio_inc_mod_count (void);
int
@@ -205,8 +204,6 @@ riotopen(struct tty_struct * tty, struct file * filp)
tty->driver_data = PortP;
PortP->gs.tty = tty;
- if (!PortP->gs.count)
- rio_inc_mod_count ();
PortP->gs.count++;
rio_dprintk (RIO_DEBUG_TTY, "%d bytes in tx buffer\n",
@@ -215,8 +212,6 @@ riotopen(struct tty_struct * tty, struct file * filp)
retval = gs_init_port (&PortP->gs);
if (retval) {
PortP->gs.count--;
- if (PortP->gs.count)
- rio_dec_mod_count ();
return -ENXIO;
}
/*
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index a8815eaa7576..1f8edac6d55d 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -552,9 +552,7 @@ static inline void rc_check_modem(struct riscom_board const * bp)
wake_up_interruptible(&port->open_wait);
else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
(port->flags & ASYNC_CALLOUT_NOHUP))) {
- MOD_INC_USE_COUNT;
- if (schedule_task(&port->tqueue_hangup) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_task(&port->tqueue_hangup);
}
}
@@ -676,7 +674,6 @@ static inline int rc_setup_board(struct riscom_board * bp)
IRQ_to_board[bp->irq] = bp;
bp->flags |= RC_BOARD_ACTIVE;
- MOD_INC_USE_COUNT;
return 0;
}
@@ -694,7 +691,6 @@ static inline void rc_shutdown_board(struct riscom_board *bp)
bp->DTR = ~0;
rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */
- MOD_DEC_USE_COUNT;
}
/*
@@ -1678,7 +1674,6 @@ static void do_rc_hangup(void *private_)
tty = port->tty;
if (tty)
tty_hangup(tty); /* FIXME: module removal race still here */
- MOD_DEC_USE_COUNT;
}
static void rc_hangup(struct tty_struct * tty)
@@ -1757,6 +1752,7 @@ static inline int rc_init_drivers(void)
memset(IRQ_to_board, 0, sizeof(IRQ_to_board));
memset(&riscom_driver, 0, sizeof(riscom_driver));
riscom_driver.magic = TTY_DRIVER_MAGIC;
+ riscom_driver.owner = THIS_MODULE;
riscom_driver.name = "ttyL";
riscom_driver.major = RISCOM8_NORMAL_MAJOR;
riscom_driver.num = RC_NBOARD * RC_NPORT;
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 98db9b9ed166..bf996ebad774 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -874,9 +874,6 @@ static int rp_open(struct tty_struct *tty, struct file * filp)
}
if (info->count++ == 0) {
-#ifdef MODULE
- MOD_INC_USE_COUNT;
-#endif
rp_num_ports_open++;
#ifdef ROCKET_DEBUG_OPEN
printk("rocket mod++ = %d...", rp_num_ports_open);
@@ -1071,9 +1068,6 @@ static void rp_close(struct tty_struct *tty, struct file * filp)
tty->closing = 0;
wake_up_interruptible(&info->close_wait);
-#ifdef MODULE
- MOD_DEC_USE_COUNT;
-#endif
rp_num_ports_open--;
#ifdef ROCKET_DEBUG_OPEN
printk("rocket mod-- = %d...", rp_num_ports_open);
@@ -1504,9 +1498,6 @@ static void rp_hangup(struct tty_struct *tty)
return;
}
if (info->count) {
-#ifdef MODULE
- MOD_DEC_USE_COUNT;
-#endif
rp_num_ports_open--;
}
@@ -2012,6 +2003,7 @@ int __init rp_init(void)
*/
memset(&rocket_driver, 0, sizeof(struct tty_driver));
rocket_driver.magic = TTY_DRIVER_MAGIC;
+ rocket_driver.owner = THIS_MODULE;
#ifdef CONFIG_DEVFS_FS
rocket_driver.name = "tts/R";
#else
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index cbc09d613e29..ff6dce969e03 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -272,7 +272,6 @@ static void a2232_shutdown_port(void *ptr)
not in "a2232_close()". See the comment in "sx.c", too.
If you run into problems, compile this driver into the
kernel instead of compiling it as a module. */
- MOD_DEC_USE_COUNT;
}
static int a2232_set_real_termios(void *ptr)
@@ -414,7 +413,6 @@ static void a2232_close(void *ptr)
a2232_disable_tx_interrupts(ptr);
a2232_disable_rx_interrupts(ptr);
/* see the comment in a2232_shutdown_port above. */
- /* MOD_DEC_USE_COUNT; */
}
static void a2232_hungup(void *ptr)
@@ -468,13 +466,9 @@ static int a2232_open(struct tty_struct * tty, struct file * filp)
return retval;
}
port->gs.flags |= GS_ACTIVE;
- if (port->gs.count == 1) {
- MOD_INC_USE_COUNT;
- }
retval = gs_block_til_ready(port, filp);
if (retval) {
- MOD_DEC_USE_COUNT;
port->gs.count--;
return retval;
}
@@ -711,6 +705,7 @@ static int a2232_init_drivers(void)
memset(&a2232_driver, 0, sizeof(a2232_driver));
a2232_driver.magic = TTY_DRIVER_MAGIC;
+ a2232_driver.owner = THIS_MODULE;
a2232_driver.driver_name = "commodore_a2232";
a2232_driver.name = "ttyY";
a2232_driver.major = A2232_NORMAL_MAJOR;
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index 61aa91704ae0..41ecc17b806d 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -2395,6 +2395,7 @@ scrn[1] = '\0';
memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
cy_serial_driver.magic = TTY_DRIVER_MAGIC;
+ cy_serial_driver.owner = THIS_MODULE;
#ifdef CONFIG_DEVFS_FS
cy_serial_driver.name = "tts/";
#else
diff --git a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c
index fa7ef4e2cd4c..190c8467f7e1 100644
--- a/drivers/char/serial_tx3912.c
+++ b/drivers/char/serial_tx3912.c
@@ -41,8 +41,6 @@ static int rs_get_CD (void * ptr);
static void rs_shutdown_port (void * ptr);
static int rs_set_real_termios (void *ptr);
static int rs_chars_in_buffer (void * ptr);
-static void rs_hungup (void *ptr);
-static void rs_close (void *ptr);
/*
* Used by generic serial driver to access hardware
@@ -56,8 +54,6 @@ static struct real_driver rs_real_driver = {
.shutdown_port = rs_shutdown_port,
.set_real_termios = rs_set_real_termios,
.chars_in_buffer = rs_chars_in_buffer,
- .close = rs_close,
- .hungup = rs_hungup,
};
/*
@@ -579,9 +575,6 @@ static int rs_open (struct tty_struct * tty, struct file * filp)
rs_dprintk (TX3912_UART_DEBUG_OPEN, "before inc_use_count (count=%d.\n",
port->gs.count);
- if (port->gs.count == 1) {
- MOD_INC_USE_COUNT;
- }
rs_dprintk (TX3912_UART_DEBUG_OPEN, "after inc_use_count\n");
/* Jim: Initialize port hardware here */
@@ -595,7 +588,6 @@ static int rs_open (struct tty_struct * tty, struct file * filp)
retval, port->gs.count);
if (retval) {
- MOD_DEC_USE_COUNT;
port->gs.count--;
return retval;
}
@@ -621,32 +613,6 @@ static int rs_open (struct tty_struct * tty, struct file * filp)
}
-
-static void rs_close (void *ptr)
-{
- func_enter ();
-
- /* Anything to do here? */
-
- MOD_DEC_USE_COUNT;
- func_exit ();
-}
-
-
-/* I haven't the foggiest why the decrement use count has to happen
- here. The whole linux serial drivers stuff needs to be redesigned.
- My guess is that this is a hack to minimize the impact of a bug
- elsewhere. Thinking about it some more. (try it sometime) Try
- running minicom on a serial port that is driven by a modularized
- driver. Have the modem hangup. Then remove the driver module. Then
- exit minicom. I expect an "oops". -- REW */
-static void rs_hungup (void *ptr)
-{
- func_enter ();
- MOD_DEC_USE_COUNT;
- func_exit ();
-}
-
static int rs_ioctl (struct tty_struct * tty, struct file * filp,
unsigned int cmd, unsigned long arg)
{
@@ -839,6 +805,7 @@ static int rs_init_drivers(void)
memset(&rs_driver, 0, sizeof(rs_driver));
rs_driver.magic = TTY_DRIVER_MAGIC;
+ rs_driver.owner = THIS_MODULE;
rs_driver.driver_name = "serial";
rs_driver.name = "ttyS";
rs_driver.major = TTY_MAJOR;
diff --git a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c
index df14c284900d..b0e9b743b50a 100644
--- a/drivers/char/sh-sci.c
+++ b/drivers/char/sh-sci.c
@@ -71,8 +71,6 @@ static void sci_enable_rx_interrupts(void *ptr);
static int sci_get_CD(void *ptr);
static void sci_shutdown_port(void *ptr);
static int sci_set_real_termios(void *ptr);
-static void sci_hungup(void *ptr);
-static void sci_close(void *ptr);
static int sci_chars_in_buffer(void *ptr);
static int sci_request_irq(struct sci_port *port);
static void sci_free_irq(struct sci_port *port);
@@ -216,8 +214,6 @@ static struct real_driver sci_real_driver = {
sci_shutdown_port,
sci_set_real_termios,
sci_chars_in_buffer,
- sci_close,
- sci_hungup,
NULL
};
@@ -838,12 +834,7 @@ static int sci_open(struct tty_struct * tty, struct file * filp)
sci_setsignals(port, 1,1);
if (port->gs.count == 1) {
- MOD_INC_USE_COUNT;
-
retval = sci_request_irq(port);
- if (retval) {
- goto failed_2;
- }
}
retval = gs_block_til_ready(port, filp);
@@ -878,23 +869,11 @@ static int sci_open(struct tty_struct * tty, struct file * filp)
failed_3:
sci_free_irq(port);
-failed_2:
- MOD_DEC_USE_COUNT;
failed_1:
port->gs.count--;
return retval;
}
-static void sci_hungup(void *ptr)
-{
- MOD_DEC_USE_COUNT;
-}
-
-static void sci_close(void *ptr)
-{
- MOD_DEC_USE_COUNT;
-}
-
static int sci_ioctl(struct tty_struct * tty, struct file * filp,
unsigned int cmd, unsigned long arg)
{
@@ -1019,6 +998,7 @@ static int sci_init_drivers(void)
memset(&sci_driver, 0, sizeof(sci_driver));
sci_driver.magic = TTY_DRIVER_MAGIC;
+ sci_driver.owner = THIS_MODULE;
sci_driver.driver_name = "sci";
#ifdef CONFIG_DEVFS_FS
sci_driver.name = "ttsc/";
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index d132207f5f6b..a0a5b022219a 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -833,9 +833,7 @@ static inline void sx_check_modem(struct specialix_board * bp)
#ifdef SPECIALIX_DEBUG
printk ( "Sending HUP.\n");
#endif
- MOD_INC_USE_COUNT;
- if (schedule_task(&port->tqueue_hangup) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_task(&port->tqueue_hangup);
} else {
#ifdef SPECIALIX_DEBUG
printk ( "Don't need to send HUP.\n");
@@ -980,7 +978,6 @@ static inline int sx_setup_board(struct specialix_board * bp)
turn_ints_on (bp);
bp->flags |= SX_BOARD_ACTIVE;
- MOD_INC_USE_COUNT;
return 0;
}
@@ -1000,7 +997,6 @@ static inline void sx_shutdown_board(struct specialix_board *bp)
turn_ints_off (bp);
- MOD_DEC_USE_COUNT;
}
@@ -2150,7 +2146,6 @@ static void do_sx_hangup(void *private_)
tty = port->tty;
if (tty)
tty_hangup(tty); /* FIXME: module removal race here */
- MOD_DEC_USE_COUNT;
}
@@ -2233,6 +2228,7 @@ static int sx_init_drivers(void)
init_bh(SPECIALIX_BH, do_specialix_bh);
memset(&specialix_driver, 0, sizeof(specialix_driver));
specialix_driver.magic = TTY_DRIVER_MAGIC;
+ specialix_driver.owner = THIS_MODULE;
specialix_driver.name = "ttyW";
specialix_driver.major = SPECIALIX_NORMAL_MAJOR;
specialix_driver.num = SX_NBOARD * SX_NPORT;
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 9506f50e5f5b..c50d4ac48e22 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1044,8 +1044,6 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
if (portp == (stlport_t *) NULL)
return(-ENODEV);
- MOD_INC_USE_COUNT;
-
/*
* On the first open of the device setup the port hardware, and
* initialize the per port data structure.
@@ -1207,14 +1205,12 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
save_flags(flags);
cli();
if (tty_hung_up_p(filp)) {
- MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
if ((tty->count == 1) && (portp->refcount != 1))
portp->refcount = 1;
if (portp->refcount-- > 1) {
- MOD_DEC_USE_COUNT;
restore_flags(flags);
return;
}
@@ -1267,7 +1263,6 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
portp->flags &= ~(ASYNC_CALLOUT_ACTIVE | ASYNC_NORMAL_ACTIVE |
ASYNC_CLOSING);
wake_up_interruptible(&portp->close_wait);
- MOD_DEC_USE_COUNT;
restore_flags(flags);
}
@@ -2241,11 +2236,11 @@ static void stl_offintr(void *private)
#endif
if (portp == (stlport_t *) NULL)
- goto out;
+ return;
tty = portp->tty;
if (tty == (struct tty_struct *) NULL)
- goto out;
+ return;
lock_kernel();
if (test_bit(ASYI_TXLOW, &portp->istate)) {
@@ -2270,8 +2265,6 @@ static void stl_offintr(void *private)
}
}
unlock_kernel();
-out:
- MOD_DEC_USE_COUNT;
}
/*****************************************************************************/
@@ -3216,13 +3209,11 @@ int __init stl_init(void)
if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
printk("STALLION: failed to register serial board device\n");
devfs_mk_dir("staliomem");
+
for (i = 0; i < 4; i++) {
- char name[16];
- sprintf(name, "staliomem/%d", i);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- STL_SIOMEMMAJOR, i,
- S_IFCHR | S_IRUSR | S_IWUSR,
- &stl_fsiomem, NULL);
+ devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
+ S_IFCHR|S_IRUSR|S_IWUSR,
+ &stl_fsiomem, NULL, "staliomem/%d", i);
}
/*
@@ -3231,6 +3222,7 @@ int __init stl_init(void)
*/
memset(&stl_serial, 0, sizeof(struct tty_driver));
stl_serial.magic = TTY_DRIVER_MAGIC;
+ stl_serial.owner = THIS_MODULE;
stl_serial.driver_name = stl_drvname;
stl_serial.name = stl_serialname;
stl_serial.major = STL_SERIALMAJOR;
@@ -4136,9 +4128,7 @@ static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr)
if ((len == 0) || ((len < STL_TXBUFLOW) &&
(test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
set_bit(ASYI_TXLOW, &portp->istate);
- MOD_INC_USE_COUNT;
- if (schedule_work(&portp->tqueue) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_work(&portp->tqueue);
}
if (len == 0) {
@@ -4318,9 +4308,7 @@ static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr)
misr = inb(ioaddr + EREG_DATA);
if (misr & MISR_DCD) {
set_bit(ASYI_DCDCHANGE, &portp->istate);
- MOD_INC_USE_COUNT;
- if (schedule_task(&portp->tqueue) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_task(&portp->tqueue);
portp->stats.modem++;
}
@@ -5117,9 +5105,7 @@ static void stl_sc26198txisr(stlport_t *portp)
if ((len == 0) || ((len < STL_TXBUFLOW) &&
(test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
set_bit(ASYI_TXLOW, &portp->istate);
- MOD_INC_USE_COUNT;
- if (schedule_task(&portp->tqueue) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_task(&portp->tqueue);
}
if (len == 0) {
@@ -5336,9 +5322,7 @@ static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack)
ipr = stl_sc26198getreg(portp, IPR);
if (ipr & IPR_DCDCHANGE) {
set_bit(ASYI_DCDCHANGE, &portp->istate);
- MOD_INC_USE_COUNT;
- if (schedule_task(&portp->tqueue) == 0)
- MOD_DEC_USE_COUNT;
+ schedule_task(&portp->tqueue);
portp->stats.modem++;
}
break;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index afd8b71f8c87..ea238b20a194 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -101,131 +101,19 @@ static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
{
machine_restart(NULL);
}
+
static struct sysrq_key_op sysrq_reboot_op = {
.handler = sysrq_handle_reboot,
.help_msg = "reBoot",
.action_msg = "Resetting",
};
-
-
-/* SYNC SYSRQ HANDLERS BLOCK */
-
-/* do_emergency_sync helper function */
-/* Guesses if the device is a local hard drive */
-static int is_local_disk(struct block_device *bdev)
-{
- switch (MAJOR(bdev->bd_dev)) {
- case IDE0_MAJOR:
- case IDE1_MAJOR:
- case IDE2_MAJOR:
- case IDE3_MAJOR:
- case IDE4_MAJOR:
- case IDE5_MAJOR:
- case IDE6_MAJOR:
- case IDE7_MAJOR:
- case IDE8_MAJOR:
- case IDE9_MAJOR:
- case SCSI_DISK0_MAJOR:
- case SCSI_DISK1_MAJOR:
- case SCSI_DISK2_MAJOR:
- case SCSI_DISK3_MAJOR:
- case SCSI_DISK4_MAJOR:
- case SCSI_DISK5_MAJOR:
- case SCSI_DISK6_MAJOR:
- case SCSI_DISK7_MAJOR:
- case XT_DISK_MAJOR:
- return 1;
- default:
- return 0;
- }
-}
-
-/* do_emergency_sync helper function */
-static void go_sync(struct super_block *sb, int remount_flag)
-{
- int orig_loglevel;
- orig_loglevel = console_loglevel;
- console_loglevel = 7;
- printk(KERN_INFO "%sing device %s ... ",
- remount_flag ? "Remount" : "Sync",
- sb->s_id);
-
- if (remount_flag) { /* Remount R/O */
- int ret, flags;
- struct file *file;
-
- if (sb->s_flags & MS_RDONLY) {
- printk("R/O\n");
- return;
- }
-
- file_list_lock();
- list_for_each_entry(file, &sb->s_files, f_list) {
- if (file->f_dentry && file_count(file)
- && S_ISREG(file->f_dentry->d_inode->i_mode))
- file->f_mode &= ~2;
- }
- file_list_unlock();
- DQUOT_OFF(sb);
- fsync_bdev(sb->s_bdev);
- flags = MS_RDONLY;
- if (sb->s_op && sb->s_op->remount_fs) {
- ret = sb->s_op->remount_fs(sb, &flags, NULL);
- if (ret)
- printk("error %d\n", ret);
- else {
- sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
- printk("OK\n");
- }
- } else
- printk("nothing to do\n");
- } else { /* Sync only */
- fsync_bdev(sb->s_bdev);
- printk("OK\n");
- }
- console_loglevel = orig_loglevel;
-}
-/*
- * Emergency Sync or Unmount. We cannot do it directly, so we set a special
- * flag and wake up the bdflush kernel thread which immediately calls this function.
- * We process all mounted hard drives first to recover from crashed experimental
- * block devices and malfunctional network filesystems.
- */
-
-int emergency_sync_scheduled;
-
-void do_emergency_sync(void) {
- struct super_block *sb;
- int remount_flag;
- int orig_loglevel;
-
- lock_kernel();
- remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT);
- emergency_sync_scheduled = 0;
-
- list_for_each_entry(sb, &super_blocks, s_list)
- if (sb->s_bdev && is_local_disk(sb->s_bdev))
- go_sync(sb, remount_flag);
-
- list_for_each_entry(sb, &super_blocks, s_list)
- if (sb->s_bdev && !is_local_disk(sb->s_bdev))
- go_sync(sb, remount_flag);
-
- unlock_kernel();
-
- orig_loglevel = console_loglevel;
- console_loglevel = 7;
- printk(KERN_INFO "Done.\n");
- console_loglevel = orig_loglevel;
-}
-
static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
- emergency_sync_scheduled = EMERG_SYNC;
- wakeup_bdflush(0);
+ emergency_sync();
}
+
static struct sysrq_key_op sysrq_sync_op = {
.handler = sysrq_handle_sync,
.help_msg = "Sync",
@@ -235,9 +123,9 @@ static struct sysrq_key_op sysrq_sync_op = {
static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
- emergency_sync_scheduled = EMERG_REMOUNT;
- wakeup_bdflush(0);
+ emergency_remount();
}
+
static struct sysrq_key_op sysrq_mountro_op = {
.handler = sysrq_handle_mountro,
.help_msg = "Unmount",
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index d1158a54336d..b88f7d0d4ddb 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -421,8 +421,6 @@ tipar_setup(char *str)
static int
tipar_register(int nr, struct parport *port)
{
- char name[32];
-
/* Register our module into parport */
table[nr].dev = parport_register_device(port, "tipar",
NULL, NULL, NULL, 0,
@@ -432,13 +430,9 @@ tipar_register(int nr, struct parport *port)
return 1;
/* Use devfs, tree: /dev/ticables/par/[0..2] */
- sprintf(name, "ticables/par/%d", nr);
- printk
- ("tipar: registering to devfs : major = %d, minor = %d, node = %s\n",
- TISER_MAJOR, (TIPAR_MINOR + nr), name);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT, TIPAR_MAJOR,
- TIPAR_MINOR + nr, S_IFCHR | S_IRUGO | S_IWUGO,
- &tipar_fops, NULL);
+ devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),
+ S_IFCHR | S_IRUGO | S_IWUGO,
+ "ticables/par/%d", nr);
/* Display informations */
printk(KERN_INFO "tipar%d: using %s (%s).\n", nr, port->name,
diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
index fead16bc852c..4429c89ac7c3 100644
--- a/drivers/char/tpqic02.c
+++ b/drivers/char/tpqic02.c
@@ -2694,38 +2694,27 @@ int __init qic02_tape_init(void)
#endif
return -ENODEV;
}
- devfs_register(NULL, "ntpqic11", DEVFS_FL_DEFAULT,
- QIC02_TAPE_MAJOR, 2,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- &qic02_tape_fops, NULL);
- devfs_register(NULL, "tpqic11", DEVFS_FL_DEFAULT,
- QIC02_TAPE_MAJOR, 3,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- &qic02_tape_fops, NULL);
- devfs_register(NULL, "ntpqic24", DEVFS_FL_DEFAULT,
- QIC02_TAPE_MAJOR, 4,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- &qic02_tape_fops, NULL);
- devfs_register(NULL, "tpqic24", DEVFS_FL_DEFAULT,
- QIC02_TAPE_MAJOR, 5,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- &qic02_tape_fops, NULL);
- devfs_register(NULL, "ntpqic120", DEVFS_FL_DEFAULT,
- QIC02_TAPE_MAJOR, 6,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- &qic02_tape_fops, NULL);
- devfs_register(NULL, "tpqic120", DEVFS_FL_DEFAULT,
- QIC02_TAPE_MAJOR, 7,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- &qic02_tape_fops, NULL);
- devfs_register(NULL, "ntpqic150", DEVFS_FL_DEFAULT,
- QIC02_TAPE_MAJOR, 8,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- &qic02_tape_fops, NULL);
- devfs_register(NULL, "tpqic150", DEVFS_FL_DEFAULT,
- QIC02_TAPE_MAJOR, 9,
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- &qic02_tape_fops, NULL);
+
+ devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 2),
+ S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic11");
+ devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 3),
+ S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic11");
+
+ devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 4),
+ S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic24");
+ devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 5),
+ S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic24");
+
+ devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 6),
+ S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic120");
+ devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 7),
+ S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic120");
+
+ devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 8),
+ S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic150");
+ devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 9),
+ S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic150");
+
init_waitqueue_head(&qic02_tape_transfer);
/* prepare timer */
TIMEROFF;
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 36a676873633..e90513aa2982 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2088,22 +2088,6 @@ static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
}
#ifdef CONFIG_DEVFS_FS
-static void tty_register_devfs(struct tty_driver *driver, unsigned index)
-{
- dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
- char buf[32];
-
- if (index >= driver->num) {
- printk(KERN_ERR "Attempt to register invalid tty line number "
- "with devfs (%d).\n", index);
- return;
- }
-
- tty_line_name(driver, index, buf);
- devfs_register(NULL, buf, 0, MAJOR(dev), MINOR(dev),
- S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL);
-}
-
static void tty_unregister_devfs(struct tty_driver *driver, int index)
{
char path[64];
@@ -2111,21 +2095,130 @@ static void tty_unregister_devfs(struct tty_driver *driver, int index)
devfs_remove(path);
}
#else
-# define tty_register_devfs(driver, index) do { } while (0)
# define tty_unregister_devfs(driver, index) do { } while (0)
#endif /* CONFIG_DEVFS_FS */
-/*
- * Register a tty device described by <driver>, with minor number <minor>.
+static struct class tty_class = {
+ .name = "tty",
+};
+
+struct tty_dev {
+ struct list_head node;
+ dev_t dev;
+ struct class_device class_dev;
+};
+#define to_tty_dev(d) container_of(d, struct tty_dev, class_dev)
+
+static LIST_HEAD(tty_dev_list);
+
+static ssize_t show_dev(struct class_device *class_dev, char *buf)
+{
+ struct tty_dev *tty_dev = to_tty_dev(class_dev);
+ return sprintf(buf, "%04x\n", tty_dev->dev);
+}
+static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
+
+static void tty_add_class_device(char *name, dev_t dev, struct device *device)
+{
+ struct tty_dev *tty_dev = NULL;
+ char *temp;
+ int retval;
+
+ tty_dev = kmalloc(sizeof(*tty_dev), GFP_KERNEL);
+ if (!tty_dev)
+ return;
+ memset(tty_dev, 0x00, sizeof(*tty_dev));
+
+ /* stupid '/' in tty name strings... */
+ temp = strchr(name, '/');
+ if (temp && (temp[1] != 0x00))
+ ++temp;
+ else
+ temp = name;
+
+ tty_dev->class_dev.dev = device;
+ tty_dev->class_dev.class = &tty_class;
+ snprintf(tty_dev->class_dev.class_id, BUS_ID_SIZE, "%s", temp);
+ retval = class_device_register(&tty_dev->class_dev);
+ if (retval)
+ goto error;
+ class_device_create_file (&tty_dev->class_dev, &class_device_attr_dev);
+ tty_dev->dev = dev;
+ list_add(&tty_dev->node, &tty_dev_list);
+ return;
+error:
+ kfree(tty_dev);
+}
+
+void tty_remove_class_device(dev_t dev)
+{
+ struct tty_dev *tty_dev = NULL;
+ struct list_head *tmp;
+ int found = 0;
+
+ list_for_each (tmp, &tty_dev_list) {
+ tty_dev = list_entry(tmp, struct tty_dev, node);
+ if ((MAJOR(tty_dev->dev) == MAJOR(dev)) &&
+ (MINOR(tty_dev->dev) == MINOR(dev))) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ list_del(&tty_dev->node);
+ class_device_unregister(&tty_dev->class_dev);
+ kfree(tty_dev);
+ }
+}
+
+/**
+ * tty_register_device - register a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
+ * @device: a struct device that is associated with this tty device.
+ * This field is optional, if there is no known struct device for this
+ * tty device it can be set to NULL safely.
+ *
+ * This call is required to be made to register an individual tty device if
+ * the tty driver's flags have the TTY_DRIVER_NO_DEVFS bit set. If that
+ * bit is not set, this function should not be called.
*/
-void tty_register_device(struct tty_driver *driver, unsigned index)
+void tty_register_device(struct tty_driver *driver, unsigned index,
+ struct device *device)
{
- tty_register_devfs(driver, index);
+ dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
+ char name[64];
+
+ if (index >= driver->num) {
+ printk(KERN_ERR "Attempt to register invalid tty line number "
+ " (%d).\n", index);
+ return;
+ }
+
+ tty_line_name(driver, index, name);
+ devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, name);
+
+ /* stupid console driver devfs names... change vc/X into ttyX */
+ if (driver->type == TTY_DRIVER_TYPE_CONSOLE)
+ sprintf(name, "tty%d", MINOR(dev));
+
+ /* we don't care about the ptys */
+ if (driver->type != TTY_DRIVER_TYPE_PTY)
+ tty_add_class_device (name, dev, device);
}
+/**
+ * tty_unregister_device - unregister a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
+ *
+ * If a tty device is registered with a call to tty_register_device() then
+ * this function must be made when the tty device is gone.
+ */
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{
tty_unregister_devfs(driver, index);
+ tty_remove_class_device(MKDEV(driver->major, driver->minor_start) + index);
}
EXPORT_SYMBOL(tty_register_device);
@@ -2207,7 +2300,7 @@ int tty_register_driver(struct tty_driver *driver)
if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) {
for(i = 0; i < driver->num; i++)
- tty_register_device(driver, i);
+ tty_register_device(driver, i, NULL);
}
proc_tty_register_driver(driver);
return error;
@@ -2288,10 +2381,6 @@ void __init console_init(void)
extern int vty_init(void);
#endif
-static struct class tty_class = {
- .name = "tty",
-};
-
static int __init tty_class_init(void)
{
return class_register(&tty_class);
@@ -2308,33 +2397,29 @@ void __init tty_init(void)
if (register_chrdev_region(TTYAUX_MAJOR, 0, 1,
"/dev/tty", &tty_fops) < 0)
panic("Couldn't register /dev/tty driver\n");
-
- devfs_register (NULL, "tty", 0, TTYAUX_MAJOR, 0,
- S_IFCHR | S_IRUGO | S_IWUGO, &tty_fops, NULL);
+ devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
+ tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL);
if (register_chrdev_region(TTYAUX_MAJOR, 1, 1,
"/dev/console", &tty_fops) < 0)
panic("Couldn't register /dev/console driver\n");
-
- devfs_register (NULL, "console", 0, TTYAUX_MAJOR, 1,
- S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL);
+ devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
+ tty_add_class_device ("console", MKDEV(TTYAUX_MAJOR, 1), NULL);
#ifdef CONFIG_UNIX98_PTYS
if (register_chrdev_region(TTYAUX_MAJOR, 2, 1,
"/dev/ptmx", &tty_fops) < 0)
panic("Couldn't register /dev/ptmx driver\n");
-
- devfs_register (NULL, "ptmx", 0, TTYAUX_MAJOR, 2,
- S_IFCHR | S_IRUGO | S_IWUGO, &tty_fops, NULL);
+ devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
+ tty_add_class_device ("ptmx", MKDEV(TTYAUX_MAJOR, 2), NULL);
#endif
#ifdef CONFIG_VT
if (register_chrdev_region(TTY_MAJOR, 0, 1,
"/dev/vc/0", &tty_fops) < 0)
panic("Couldn't register /dev/tty0 driver\n");
-
- devfs_register (NULL, "vc/0", 0, TTY_MAJOR, 0,
- S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL);
+ devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
+ tty_add_class_device ("tty0", MKDEV(TTY_MAJOR, 0), NULL);
vty_init();
#endif
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index 9e33415f8cdc..07e16dbdb4e0 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -469,40 +469,27 @@ static struct file_operations vcs_fops = {
.open = vcs_open,
};
-void vcs_make_devfs (unsigned int index, int unregister)
+void vcs_make_devfs(struct tty_struct *tty)
{
-#ifdef CONFIG_DEVFS_FS
-
- if (unregister) {
- devfs_remove("vcc/%u", index + 1);
- devfs_remove("vcc/a%u", index + 1);
- } else {
- char name[16];
- sprintf(name, "vcc/%u", index + 1);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- VCS_MAJOR, index + 1,
- S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
- sprintf(name, "vcc/a%u", index + 1);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- VCS_MAJOR, index + 129,
- S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
- }
-#endif /* CONFIG_DEVFS_FS */
+ devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 1),
+ S_IFCHR|S_IRUSR|S_IWUSR,
+ "vcc/%u", tty->index + 1);
+ devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
+ S_IFCHR|S_IRUSR|S_IWUSR,
+ "vcc/a%u", tty->index + 1);
+}
+void vcs_remove_devfs(struct tty_struct *tty)
+{
+ devfs_remove("vcc/%u", tty->index + 1);
+ devfs_remove("vcc/a%u", tty->index + 1);
}
int __init vcs_init(void)
{
- int error;
+ if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
+ panic("unable to get major %d for vcs device", VCS_MAJOR);
- error = register_chrdev(VCS_MAJOR, "vcs", &vcs_fops);
-
- if (error)
- printk("unable to get major %d for vcs device", VCS_MAJOR);
-
- devfs_register(NULL, "vcc/0", DEVFS_FL_DEFAULT, VCS_MAJOR, 0,
- S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
- devfs_register(NULL, "vcc/a", DEVFS_FL_DEFAULT, VCS_MAJOR, 128,
- S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL);
-
- return error;
+ devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
+ devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
+ return 0;
}
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index 93e654dc2f49..c2bed745cef4 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -129,6 +129,7 @@ static int scc_init_drivers(void)
memset(&scc_driver, 0, sizeof(scc_driver));
scc_driver.magic = TTY_DRIVER_MAGIC;
+ scc_driver.owner = THIS_MODULE;
scc_driver.driver_name = "scc";
#ifdef CONFIG_DEVFS_FS
scc_driver.name = "tts/";
@@ -795,7 +796,6 @@ static void scc_hungup(void *ptr)
{
scc_disable_tx_interrupts(ptr);
scc_disable_rx_interrupts(ptr);
- MOD_DEC_USE_COUNT;
}
@@ -803,7 +803,6 @@ static void scc_close(void *ptr)
{
scc_disable_tx_interrupts(ptr);
scc_disable_rx_interrupts(ptr);
- MOD_DEC_USE_COUNT;
}
@@ -938,13 +937,9 @@ static int scc_open (struct tty_struct * tty, struct file * filp)
return retval;
}
port->gs.flags |= GS_ACTIVE;
- if (port->gs.count == 1) {
- MOD_INC_USE_COUNT;
- }
retval = gs_block_til_ready(port, filp);
if (retval) {
- MOD_DEC_USE_COUNT;
port->gs.count--;
return retval;
}
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 8001d2e3d8c0..b30ff1af7033 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -124,7 +124,9 @@ const struct consw *conswitchp;
#define DEFAULT_BELL_PITCH 750
#define DEFAULT_BELL_DURATION (HZ/8)
-extern void vcs_make_devfs (unsigned int index, int unregister);
+extern void vcs_make_devfs(struct tty_struct *tty);
+extern void vcs_remove_devfs(struct tty_struct *tty);
+
extern void console_map_init(void);
#ifdef CONFIG_PROM_CONSOLE
extern void prom_con_init(void);
@@ -158,7 +160,6 @@ static void set_cursor(int currcons);
static void hide_cursor(int currcons);
static void unblank_screen_t(unsigned long dummy);
static void console_callback(void *ignored);
-static void __init con_init_devfs (void);
static int printable; /* Is console ready for printing? */
@@ -2410,7 +2411,7 @@ static int con_open(struct tty_struct *tty, struct file * filp)
tty->winsize.ws_col = video_num_columns;
}
if (tty->count == 1)
- vcs_make_devfs (currcons, 0);
+ vcs_make_devfs(tty);
return 0;
}
@@ -2418,10 +2419,10 @@ static void con_close(struct tty_struct *tty, struct file * filp)
{
struct vt_struct *vt;
- if (!tty)
+ if (!tty || tty->count != 1)
return;
- if (tty->count != 1) return;
- vcs_make_devfs (tty->index, 1);
+
+ vcs_remove_devfs(tty);
vt = (struct vt_struct*)tty->driver_data;
if (vt)
vc_cons[vt->vc_num].d->vc_tty = NULL;
@@ -2525,11 +2526,6 @@ int __init vty_init(void)
console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
console_driver.init_termios = tty_std_termios;
console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
- /* Tell tty_register_driver() to skip consoles because they are
- * registered before kmalloc() is ready. We'll patch them in later.
- * See comments at console_init(); see also con_init_devfs().
- */
- console_driver.flags |= TTY_DRIVER_NO_DEVFS;
console_driver.refcount = &console_refcount;
console_driver.table = console_table;
console_driver.termios = console_termios;
@@ -2562,7 +2558,6 @@ int __init vty_init(void)
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
fb_console_init();
#endif
- con_init_devfs();
vcs_init();
return 0;
}
@@ -2657,18 +2652,6 @@ static void set_vesa_blanking(unsigned long arg)
vesa_blank_mode = (mode < 4) ? mode : 0;
}
-/* We can't register the console with devfs during con_init(), because it
- * is called before kmalloc() works. This function is called later to
- * do the registration.
- */
-static void __init con_init_devfs (void)
-{
- int i;
-
- for (i = 0; i < console_driver.num; i++)
- tty_register_device (&console_driver, i);
-}
-
/*
* This is called by a timer handler
*/
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index a7aba262f11a..1a9cf92c8c75 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -372,16 +372,11 @@ static int i2cdev_release(struct inode *inode, struct file *file)
int i2cdev_attach_adapter(struct i2c_adapter *adap)
{
- char name[12];
int i;
i = i2c_adapter_id(adap);
- sprintf (name, "i2c/%d", i);
-
- devfs_register (NULL, name,
- DEVFS_FL_DEFAULT, I2C_MAJOR, i,
- S_IFCHR | S_IRUSR | S_IWUSR,
- &i2cdev_fops, NULL);
+ devfs_mk_cdev(MKDEV(I2C_MAJOR, i),
+ S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i);
dev_dbg(&adap->dev, "Registered as minor %d\n", i);
return 0;
}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 919dbbefe47c..696b32261f23 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -6292,11 +6292,9 @@ static int idetape_attach (ide_drive_t *drive)
devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor)
S_IFCHR | S_IRUGO | S_IWUGO,
- &idetape_fops, NULL,
"%s/mt", drive->devfs_name);
devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor + 128),
S_IFCHR | S_IRUGO | S_IWUGO,
- &idetape_fops, NULL,
"%s/mtn", drive->devfs_name);
drive->disk->number = devfs_register_tape(drive->devfs_name);
diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
index 4ba93358e952..5a559f66cbb4 100644
--- a/drivers/ieee1394/amdtp.c
+++ b/drivers/ieee1394/amdtp.c
@@ -1205,7 +1205,6 @@ static void amdtp_add_host(struct hpsb_host *host)
{
struct amdtp_host *ah;
int minor;
- char name[16];
if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME) != 0)
return;
@@ -1223,13 +1222,11 @@ static void amdtp_add_host(struct hpsb_host *host)
minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->ohci->id;
- sprintf(name, "amdtp/%d", ah->ohci->id);
-
INIT_LIST_HEAD(&ah->stream_list);
spin_lock_init(&ah->stream_list_lock);
- devfs_register(NULL, name, 0, IEEE1394_MAJOR, minor,
- S_IFCHR | S_IRUSR | S_IWUSR, &amdtp_fops, NULL);
+ devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
+ S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->ohci->id);
}
static void amdtp_remove_host(struct hpsb_host *host)
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index a5a2e682fbd6..12fdd2034c37 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2420,24 +2420,6 @@ static struct file_operations dv1394_fops=
};
-#ifdef CONFIG_DEVFS_FS
-static int dv1394_devfs_add_entry(struct video_card *video)
-{
- char buf[64];
-
- snprintf(buf, sizeof(buf), "ieee1394/dv/host%d/%s/%s",
- (video->id>>2),
- (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
- (video->mode == MODE_RECEIVE ? "in" : "out"));
-
- devfs_register(NULL, buf, 0, IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_DV1394*16 + video->id,
- S_IFCHR | S_IRUGO | S_IWUGO, &dv1394_fops, video);
- return 0;
-}
-#endif /* CONFIG_DEVFS_FS */
-
-
/*** HOTPLUG STUFF **********************************************************/
/*
* Export information about protocols/devices supported by this driver.
@@ -2536,10 +2518,14 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
list_add_tail(&video->list, &dv1394_cards);
spin_unlock_irqrestore(&dv1394_cards_lock, flags);
-#ifdef CONFIG_DEVFS_FS
- if (dv1394_devfs_add_entry(video) < 0)
+ if (devfs_mk_cdev(MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_DV1394*16 + video->id),
+ S_IFCHR|S_IRUGO|S_IWUGO,
+ "ieee1394/dv/host%d/%s/%s",
+ (video->id>>2),
+ (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
+ (video->mode == MODE_RECEIVE ? "in" : "out")) < 0)
goto err_free;
-#endif
debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id);
@@ -2562,9 +2548,7 @@ static void dv1394_un_init(struct video_card *video)
(video->mode == MODE_RECEIVE ? "in" : "out")
);
-#ifdef CONFIG_DEVFS_FS
devfs_remove("ieee1394/%s", buf);
-#endif
#ifdef CONFIG_PROC_FS
dv1394_procfs_del(buf);
#endif
@@ -2602,11 +2586,9 @@ static void dv1394_remove_host (struct hpsb_host *host)
n = (video->id >> 2);
-#ifdef CONFIG_DEVFS_FS
devfs_remove("ieee1394/dv/host%d/NTSC", n);
devfs_remove("ieee1394/dv/host%d/PAL", n);
devfs_remove("ieee1394/dv/host%d", n);
-#endif
#ifdef CONFIG_PROC_FS
snprintf(buf, sizeof(buf), "dv/host%d/NTSC", n);
@@ -2642,11 +2624,9 @@ static void dv1394_add_host (struct hpsb_host *host)
}
#endif
-#ifdef CONFIG_DEVFS_FS
devfs_mk_dir("ieee1394/dv/host%d", ohci->id);
devfs_mk_dir("ieee1394/dv/host%d/NTSC", ohci->id);
devfs_mk_dir("ieee1394/dv/host%d/PAL", ohci->id);
-#endif
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
@@ -2901,9 +2881,7 @@ static void __exit dv1394_exit_module(void)
hpsb_unregister_highlevel(&dv1394_highlevel);
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
-#ifdef CONFIG_DEVFS_FS
devfs_remove("ieee1394/dv");
-#endif
#ifdef CONFIG_PROC_FS
dv1394_procfs_del("dv");
#endif
@@ -2920,18 +2898,14 @@ static int __init dv1394_init_module(void)
return -EIO;
}
-#ifdef CONFIG_DEVFS_FS
devfs_mk_dir("ieee1394/dv");
-#endif
#ifdef CONFIG_PROC_FS
ret = dv1394_procfs_add_dir("dv",NULL,NULL);
if (ret < 0) {
printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n");
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
-#ifdef CONFIG_DEVFS_FS
devfs_remove("ieee1394/dv");
-#endif
return -ENOMEM;
}
#endif
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 72bafa9e1e9a..678c9959a9da 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -2531,9 +2531,8 @@ static int __init init_raw1394(void)
{
hpsb_register_highlevel(&raw1394_highlevel);
- devfs_register(NULL, RAW1394_DEVICE_NAME, 0,
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16,
- S_IFCHR | S_IRUSR | S_IWUSR, &file_ops, NULL);
+ devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
+ S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_RAW1394,
THIS_MODULE, &file_ops)) {
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index cbfa8f1fd32f..989f22e4a5f7 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1257,7 +1257,6 @@ static struct hpsb_protocol_driver video1394_driver = {
static void video1394_add_host (struct hpsb_host *host)
{
struct ti_ohci *ohci;
- char name[16];
int minor;
/* We only work with the OHCI-1394 driver */
@@ -1274,12 +1273,10 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo(&video1394_highlevel, host, ohci);
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->id);
- sprintf(name, "%s/%d", VIDEO1394_DRIVER_NAME, ohci->id);
- minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id;
- devfs_register(NULL, name, 0, IEEE1394_MAJOR, minor,
- S_IFCHR | S_IRUSR | S_IWUSR, &video1394_fops, NULL);
-
- return;
+ minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id;
+ devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
+ S_IFCHR | S_IRUSR | S_IWUSR,
+ "%s/%d", VIDEO1394_DRIVER_NAME, ohci->id);
}
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index c2310412d9b9..56db3b57f4cc 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/major.h>
#include <linux/smp_lock.h>
#include <linux/device.h>
#include <linux/devfs_fs_kernel.h>
@@ -400,7 +401,9 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
sprintf(evdev->name, "event%d", minor);
evdev_table[minor] = evdev;
- input_register_minor("input/event%d", minor, EVDEV_MINOR_BASE);
+
+ devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
+ S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
return &evdev->handle;
}
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 2005dfec2456..ee47231dc5e7 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -16,6 +16,7 @@
#include <linux/input.h>
#include <linux/module.h>
#include <linux/random.h>
+#include <linux/major.h>
#include <linux/pm.h>
#include <linux/proc_fs.h>
#include <linux/kmod.h>
@@ -32,7 +33,6 @@ EXPORT_SYMBOL(input_register_device);
EXPORT_SYMBOL(input_unregister_device);
EXPORT_SYMBOL(input_register_handler);
EXPORT_SYMBOL(input_unregister_handler);
-EXPORT_SYMBOL(input_register_minor);
EXPORT_SYMBOL(input_open_device);
EXPORT_SYMBOL(input_close_device);
EXPORT_SYMBOL(input_accept_process);
@@ -40,7 +40,6 @@ EXPORT_SYMBOL(input_flush_device);
EXPORT_SYMBOL(input_event);
EXPORT_SYMBOL(input_class);
-#define INPUT_MAJOR 13
#define INPUT_DEVICES 256
static LIST_HEAD(input_dev_list);
@@ -541,15 +540,6 @@ static struct file_operations input_fops = {
.open = input_open_file,
};
-void input_register_minor(char *name, int minor, int minor_base)
-{
- char devfs_name[16];
-
- sprintf(devfs_name, name, minor);
- devfs_register(NULL, devfs_name, 0, INPUT_MAJOR, minor_base + minor,
- S_IFCHR|S_IRUGO|S_IWUSR, &input_fops, NULL);
-}
-
#ifdef CONFIG_PROC_FS
#define SPRINTF_BIT_B(bit, name, max) \
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 0cc7e2b0e556..2f80d8222820 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -445,7 +445,9 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
}
joydev_table[minor] = joydev;
- input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
+
+ devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
+ S_IFCHR|S_IRUGO|S_IWUSR, "js%d", minor);
return &joydev->handle;
}
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 787229562046..e2fe3e3347c5 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -432,7 +432,9 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
input_open_device(&mousedev->handle);
mousedev_table[minor] = mousedev;
- input_register_minor("input/mouse%d", minor, MOUSEDEV_MINOR_BASE);
+
+ devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
+ S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
return &mousedev->handle;
}
@@ -502,7 +504,10 @@ static int __init mousedev_init(void)
mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
mousedev_mix.exist = 1;
mousedev_mix.minor = MOUSEDEV_MIX;
- input_register_minor("input/mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE);
+
+ devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
+ S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
+
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
if (!(mousedev_mix.misc = !misc_register(&psaux_mouse)))
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index b2f26c794c28..8d71554f28d9 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -62,6 +62,12 @@ static unsigned char i8042_last_e0;
static unsigned char i8042_mux_open;
struct timer_list i8042_timer;
+/*
+ * Shared IRQ's require a device pointer, but this driver doesn't support
+ * multiple devices
+ */
+#define i8042_request_irq_cookie (&i8042_timer)
+
static unsigned long i8042_unxlate_seen[256 / BITS_PER_LONG];
static unsigned char i8042_unxlate_table[128] = {
0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
@@ -235,7 +241,8 @@ static int i8042_open(struct serio *port)
if (i8042_mux_open++)
return 0;
- if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL)) {
+ if (request_irq(values->irq, i8042_interrupt,
+ SA_SHIRQ, "i8042", i8042_request_irq_cookie)) {
printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", values->irq, values->name);
values->exists = 0;
serio_unregister_port(port);
@@ -275,7 +282,7 @@ static void i8042_close(struct serio *port)
return;
}
- free_irq(values->irq, NULL);
+ free_irq(values->irq, i8042_request_irq_cookie);
i8042_flush();
}
@@ -572,9 +579,10 @@ static int __init i8042_check_mux(struct i8042_values *values)
* Check if AUX irq is available.
*/
- if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL))
+ if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ,
+ "i8042", i8042_request_irq_cookie))
return -1;
- free_irq(values->irq, NULL);
+ free_irq(values->irq, i8042_request_irq_cookie);
/*
* Get rid of bytes in the queue.
@@ -643,9 +651,10 @@ static int __init i8042_check_aux(struct i8042_values *values)
* in trying to detect AUX presence.
*/
- if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL))
+ if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ,
+ "i8042", i8042_request_irq_cookie))
return -1;
- free_irq(values->irq, NULL);
+ free_irq(values->irq, i8042_request_irq_cookie);
/*
* Get rid of bytes in the queue.
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 0d089b4683cb..99a567c7d522 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -36,6 +36,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/major.h>
#include <linux/config.h>
#include <linux/smp_lock.h>
#include <linux/random.h>
@@ -329,8 +330,9 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
tsdev->handle.private = tsdev;
tsdev_table[minor] = tsdev;
- input_register_minor("input/ts%d", minor, TSDEV_MINOR_BASE);
-
+
+ devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
+ S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
return &tsdev->handle;
}
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 0e9f6b3003fd..f8f49f0530bd 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -200,10 +200,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
unsigned int minor = 0;
unsigned long flags;
- MOD_INC_USE_COUNT;
mp = kmalloc(sizeof(*mp), GFP_ATOMIC);
if (!mp) {
- MOD_DEC_USE_COUNT;
printk(KERN_ERR "capi: can't alloc capiminor\n");
return 0;
}
@@ -249,7 +247,6 @@ static void capiminor_free(struct capiminor *mp)
skb_queue_purge(&mp->outqueue);
capiminor_del_all_ack(mp);
kfree(mp);
- MOD_DEC_USE_COUNT;
}
struct capiminor *capiminor_find(unsigned int minor)
@@ -1280,6 +1277,7 @@ static int capinc_tty_init(void)
memset(drv, 0, sizeof(struct tty_driver));
drv->magic = TTY_DRIVER_MAGIC;
+ drv->owner = THIS_MODULE;
drv->driver_name = "capi_nc";
drv->name = "capi/";
drv->major = capi_ttymajor;
@@ -1460,7 +1458,6 @@ static int __init capi_init(void)
char *p;
char *compileinfo;
- MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(rev, p + 2, sizeof(rev));
@@ -1472,19 +1469,17 @@ static int __init capi_init(void)
if (register_chrdev(capi_major, "capi20", &capi_fops)) {
printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
- MOD_DEC_USE_COUNT;
return -EIO;
}
- devfs_register (NULL, "isdn/capi20", DEVFS_FL_DEFAULT,
- capi_major, 0, S_IFCHR | S_IRUSR | S_IWUSR,
- &capi_fops, NULL);
+ devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR,
+ "isdn/capi20");
+
printk(KERN_NOTICE "capi20: started up with major %d\n", capi_major);
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
if (capinc_tty_init() < 0) {
unregister_chrdev(capi_major, "capi20");
- MOD_DEC_USE_COUNT;
return -ENOMEM;
}
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
@@ -1503,7 +1498,6 @@ static int __init capi_init(void)
printk(KERN_NOTICE "capi20: Rev %s: started up with major %d%s\n",
rev, capi_major, compileinfo);
- MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c
index 619c0d4742ce..1621299f3a96 100644
--- a/drivers/isdn/hardware/eicon/divamnt.c
+++ b/drivers/isdn/hardware/eicon/divamnt.c
@@ -420,10 +420,8 @@ static int DIVA_INIT_FUNCTION divas_maint_register_chrdev(void)
DRIVERLNAME);
return (0);
}
- devfs_register(NULL, "DivasMAINT", DEVFS_FL_DEFAULT, major, 0,
- S_IFCHR | S_IRUSR | S_IWUSR, &divas_maint_fops,
- NULL);
+ devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, DivasMAINT);
return (1);
}
diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c
index 6569f8edf24b..bce39cb91ce6 100644
--- a/drivers/isdn/hardware/eicon/divasi.c
+++ b/drivers/isdn/hardware/eicon/divasi.c
@@ -179,10 +179,8 @@ static int DIVA_INIT_FUNCTION divas_idi_register_chrdev(void)
DRIVERLNAME);
return (0);
}
- devfs_register(NULL, "DivasIDI", DEVFS_FL_DEFAULT, major, 0,
- S_IFCHR | S_IRUSR | S_IWUSR, &divas_idi_fops,
- NULL);
+ devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, "DivasIDI");
return (1);
}
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index 9ad1f2648722..e82a6546ff58 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -788,9 +788,8 @@ static int DIVA_INIT_FUNCTION divas_register_chrdev(void)
DRIVERLNAME);
return (0);
}
- devfs_register(NULL, "Divas", DEVFS_FL_DEFAULT, major, 0,
- S_IFCHR | S_IRUSR | S_IWUSR, &divas_fops, NULL);
+ devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, "Divas");
return (1);
}
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 0c11b691f33f..029058996e85 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -37,9 +37,6 @@ isdn_dev *dev;
static void isdn_lock_driver(struct isdn_driver *drv);
static void isdn_unlock_driver(struct isdn_driver *drv);
-static void isdn_register_devfs(int);
-static void isdn_unregister_devfs(int);
-
/* ====================================================================== */
/* Description of hardware-level-driver */
@@ -2157,86 +2154,38 @@ isdn_hard_header_len(void)
return max;
}
-/*
- *****************************************************************************
- * And now the modules code.
- *****************************************************************************
- */
-
-#ifdef CONFIG_DEVFS_FS
-
-static void isdn_register_devfs(int k)
-{
- char buf[16];
-
- sprintf (buf, "isdn/isdnctrl%d", k);
- devfs_register(NULL, buf, DEVFS_FL_DEFAULT,
- ISDN_MAJOR, ISDN_MINOR_CTRL + k, 0600 | S_IFCHR,
- &isdn_fops, NULL);
-}
-
-static void isdn_unregister_devfs(int k)
+static void isdn_init_devfs(void)
{
- devfs_remove("isdn/isdnctrl%d", k);
-}
+ devfs_mk_dir("isdn");
-static void isdn_init_devfs(void)
+#ifdef CONFIG_ISDN_PPP
{
-# ifdef CONFIG_ISDN_PPP
int i;
-# endif
- devfs_mk_dir("isdn");
-# ifdef CONFIG_ISDN_PPP
- for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- char buf[16];
-
- sprintf (buf, "isdn/ippp%d", i);
- devfs_register(NULL, buf, DEVFS_FL_DEFAULT,
- ISDN_MAJOR, ISDN_MINOR_PPP + i,
- 0600 | S_IFCHR, &isdn_fops, NULL);
- }
-# endif
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+ devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_PPP + i),
+ 0600 | S_IFCHR, "isdn/ippp%d", i);
+}
+#endif
- devfs_register(NULL, "isdn/isdninfo", DEVFS_FL_DEFAULT,
- ISDN_MAJOR, ISDN_MINOR_STATUS, 0600 | S_IFCHR,
- &isdn_fops, NULL);
- devfs_register(NULL, "isdn/isdnctrl", DEVFS_FL_DEFAULT,
- ISDN_MAJOR, ISDN_MINOR_CTRL, 0600 | S_IFCHR,
- &isdn_fops, NULL);
+ devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_STATUS),
+ 0600 | S_IFCHR, "isdn/isdninfo");
+ devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_CTRL),
+ 0600 | S_IFCHR, "isdn/isdnctrl");
}
static void isdn_cleanup_devfs(void)
{
-# ifdef CONFIG_ISDN_PPP
+#ifdef CONFIG_ISDN_PPP
int i;
for (i = 0; i < ISDN_MAX_CHANNELS; i++)
devfs_remove("isdn/ippp%d", i);
-# endif
+#endif
devfs_remove("isdn/isdninfo");
devfs_remove("isdn/isdnctrl");
devfs_remove("isdn");
}
-#else /* CONFIG_DEVFS_FS */
-static void isdn_register_devfs(int dummy)
-{
-}
-
-static void isdn_unregister_devfs(int dummy)
-{
-}
-
-static void isdn_init_devfs(void)
-{
-}
-
-static void isdn_cleanup_devfs(void)
-{
-}
-
-#endif /* CONFIG_DEVFS_FS */
-
/*
* Allocate and initialize all data, register modem-devices
*/
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index f4982f115dba..bc335b5f7379 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -896,8 +896,6 @@ adbdev_init(void)
if (register_chrdev(ADB_MAJOR, "adb", &adb_fops))
printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR);
else
- devfs_register (NULL, "adb", DEVFS_FL_DEFAULT,
- ADB_MAJOR, 0,
- S_IFCHR | S_IRUSR | S_IWUSR,
- &adb_fops, NULL);
+ devfs_mk_cdev(MKDEV(ADB_MAJOR, 0),
+ S_IFCHR | S_IRUSR | S_IWUSR, "adb");
}
diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
index 956559ee4714..06d0ac4950fa 100644
--- a/drivers/macintosh/macserial.c
+++ b/drivers/macintosh/macserial.c
@@ -1932,7 +1932,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
spin_lock_irqsave(&info->lock, flags);
if (tty_hung_up_p(filp)) {
- MOD_DEC_USE_COUNT;
spin_unlock_irqrestore(&info->lock, flags);
return;
}
@@ -1956,7 +1955,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info->count = 0;
}
if (info->count) {
- MOD_DEC_USE_COUNT;
spin_unlock_irqrestore(&info->lock, flags);
return;
}
@@ -2026,7 +2024,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE|
ZILOG_CLOSING);
wake_up_interruptible(&info->close_wait);
- MOD_DEC_USE_COUNT;
}
/*
@@ -2233,17 +2230,14 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
int retval, line;
unsigned long page;
- MOD_INC_USE_COUNT;
line = tty->index;
if ((line < 0) || (line >= zs_channels_found)) {
- MOD_DEC_USE_COUNT;
return -ENODEV;
}
info = zs_soft + line;
#ifdef CONFIG_KGDB
if (info->kgdb_channel) {
- MOD_DEC_USE_COUNT;
return -ENODEV;
}
#endif
@@ -2610,6 +2604,7 @@ no_dma:
memset(&serial_driver, 0, sizeof(struct tty_driver));
serial_driver.magic = TTY_DRIVER_MAGIC;
+ serial_driver.owner = THIS_MODULE;
serial_driver.driver_name = "macserial";
#ifdef CONFIG_DEVFS_FS
serial_driver.name = "tts/";
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 272bef26e781..9bf79c6cd39e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1111,8 +1111,10 @@ static void export_array(mddev_t *mddev)
static void print_desc(mdp_disk_t *desc)
{
+ char b[BDEVNAME_SIZE];
+
printk(" DISK<N:%d,%s(%d,%d),R:%d,S:%d>\n", desc->number,
- partition_name(MKDEV(desc->major,desc->minor)),
+ __bdevname(MKDEV(desc->major, desc->minor), b),
desc->major,desc->minor,desc->raid_disk,desc->state);
}
@@ -1294,6 +1296,7 @@ repeat:
*/
static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_minor)
{
+ char b[BDEVNAME_SIZE];
int err;
mdk_rdev_t *rdev;
sector_t size;
@@ -1301,7 +1304,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL);
if (!rdev) {
printk(KERN_ERR "md: could not alloc mem for %s!\n",
- partition_name(newdev));
+ __bdevname(newdev, b));
return ERR_PTR(-ENOMEM);
}
memset(rdev, 0, sizeof(*rdev));
@@ -1312,7 +1315,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
err = lock_rdev(rdev, newdev);
if (err) {
printk(KERN_ERR "md: could not lock %s.\n",
- partition_name(newdev));
+ __bdevname(newdev, b));
goto abort_free;
}
rdev->desc_nr = -1;
@@ -1840,6 +1843,7 @@ static void autorun_devices(void)
static int autostart_array(dev_t startdev)
{
+ char b[BDEVNAME_SIZE];
int err = -EINVAL, i;
mdp_super_t *sb = NULL;
mdk_rdev_t *start_rdev = NULL, *rdev;
@@ -1847,7 +1851,7 @@ static int autostart_array(dev_t startdev)
start_rdev = md_import_device(startdev, 0, 0);
if (IS_ERR(start_rdev)) {
printk(KERN_WARNING "md: could not import %s!\n",
- partition_name(startdev));
+ __bdevname(startdev, b));
return err;
}
@@ -1884,7 +1888,7 @@ static int autostart_array(dev_t startdev)
if (IS_ERR(rdev)) {
printk(KERN_WARNING "md: could not import %s,"
" trying to run array nevertheless.\n",
- partition_name(dev));
+ __bdevname(dev, b));
continue;
}
list_add(&rdev->same_set, &pending_raid_disks);
@@ -2116,6 +2120,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
static int hot_generate_error(mddev_t * mddev, dev_t dev)
{
+ char b[BDEVNAME_SIZE];
struct request_queue *q;
mdk_rdev_t *rdev;
@@ -2123,7 +2128,7 @@ static int hot_generate_error(mddev_t * mddev, dev_t dev)
return -ENODEV;
printk(KERN_INFO "md: trying to generate %s error in md%d ... \n",
- partition_name(dev), mdidx(mddev));
+ __bdevname(dev, b), mdidx(mddev));
rdev = find_rdev(mddev, dev);
if (!rdev) {
@@ -2151,13 +2156,14 @@ static int hot_generate_error(mddev_t * mddev, dev_t dev)
static int hot_remove_disk(mddev_t * mddev, dev_t dev)
{
+ char b[BDEVNAME_SIZE];
mdk_rdev_t *rdev;
if (!mddev->pers)
return -ENODEV;
printk(KERN_INFO "md: trying to remove %s from md%d ... \n",
- partition_name(dev), mdidx(mddev));
+ __bdevname(dev, b), mdidx(mddev));
rdev = find_rdev(mddev, dev);
if (!rdev)
@@ -2178,6 +2184,7 @@ busy:
static int hot_add_disk(mddev_t * mddev, dev_t dev)
{
+ char b[BDEVNAME_SIZE];
int err;
unsigned int size;
mdk_rdev_t *rdev;
@@ -2186,7 +2193,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
return -ENODEV;
printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n",
- partition_name(dev), mdidx(mddev));
+ __bdevname(dev, b), mdidx(mddev));
if (mddev->major_version != 0) {
printk(KERN_WARNING "md%d: HOT_ADD may only be used with"
@@ -2344,6 +2351,7 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)
static int md_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ char b[BDEVNAME_SIZE];
unsigned int minor;
int err = 0;
struct hd_geometry *loc = (struct hd_geometry *) arg;
@@ -2403,7 +2411,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
err = autostart_array(arg);
if (err) {
printk(KERN_WARNING "md: autostart %s failed!\n",
- partition_name(arg));
+ __bdevname(arg, b));
goto abort;
}
goto done;
@@ -3516,6 +3524,7 @@ void md_autodetect_dev(dev_t dev)
static void autostart_arrays(void)
{
+ char b[BDEVNAME_SIZE];
mdk_rdev_t *rdev;
int i;
@@ -3527,7 +3536,7 @@ static void autostart_arrays(void)
rdev = md_import_device(dev,0, 0);
if (IS_ERR(rdev)) {
printk(KERN_ALERT "md: could not import %s!\n",
- partition_name(dev));
+ __bdevname(dev, b));
continue;
}
if (rdev->faulty) {
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 6efdcdf7cd08..8e9a3e340228 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -189,7 +189,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
const struct dvb_device *template, void *priv, int type)
{
u32 id;
- char name [20];
struct dvb_device *dvbdev;
if (down_interruptible (&dvbdev_register_lock))
@@ -219,12 +218,12 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
list_add_tail (&dvbdev->list_head, &adap->device_list);
- sprintf(name, "dvb/adapter%d%s%d", adap->num, dnames[type], id);
- devfs_register(NULL, name, 0, DVB_MAJOR, nums2minor(adap->num, type, id),
- S_IFCHR | S_IRUSR | S_IWUSR, dvbdev->fops, dvbdev);
+ devfs_mk_cdev(MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
+ S_IFCHR | S_IRUSR | S_IWUSR,
+ "dvb/adapter%d/%s%d", adap->num, dnames[type], id);
- dprintk("DVB: register adapter%d/%s @ minor: %i (0x%02x)\n",
- adap->num, name, nums2minor(adap->num, type, id),
+ dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
+ adap->num, dnames[type], id, nums2minor(adap->num, type, id),
nums2minor(adap->num, type, id));
return 0;
@@ -234,7 +233,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
void dvb_unregister_device(struct dvb_device *dvbdev)
{
if (dvbdev) {
- devfs_remove("dvb/adapter%d%s%d", dvbdev->adapter->num,
+ devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num,
dnames[dvbdev->type], dvbdev->id);
list_del(&dvbdev->list_head);
kfree(dvbdev);
@@ -322,12 +321,12 @@ static
int __init init_dvbdev(void)
{
devfs_mk_dir("dvb");
-#ifndef CONFIG_DVB_DEVFS_ONLY
+
if(register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops)) {
printk("video_dev: unable to get major %d\n", DVB_MAJOR);
return -EIO;
}
-#endif
+
return 0;
}
@@ -335,9 +334,7 @@ int __init init_dvbdev(void)
static
void __exit exit_dvbdev(void)
{
-#ifndef CONFIG_DVB_DEVFS_ONLY
unregister_chrdev(DVB_MAJOR, "DVB");
-#endif
devfs_remove("dvb");
}
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 147ffe0866a5..1ba683ffc674 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -1409,12 +1409,10 @@ static void proc_cpia_create(void)
LOG("Unable to initialise /proc/cpia\n");
}
-#ifdef MODULE
-static void proc_cpia_destroy(void)
+static void __exit proc_cpia_destroy(void)
{
remove_proc_entry("cpia", 0);
}
-#endif /*MODULE*/
#endif /* CONFIG_PROC_FS */
/* ----------------------- debug functions ---------------------- */
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 497780674a58..46cf84769278 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -427,8 +427,8 @@ int video_register_device(struct video_device *vfd, int type, int nr)
up(&videodev_lock);
sprintf(vfd->devfs_name, "v4l/%s%d", name_base, i - base);
- devfs_register(NULL, vfd->devfs_name, 0, VIDEO_MAJOR, vfd->minor,
- S_IFCHR | S_IRUSR | S_IWUSR, &video_fops, NULL);
+ devfs_mk_cdev(MKDEV(VIDEO_MAJOR, vfd->minor),
+ S_IFCHR | S_IRUSR | S_IWUSR, vfd->devfs_name);
init_MUTEX(&vfd->lock);
#ifdef CONFIG_VIDEO_PROC_FS
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index f4d447229045..dc2d9fc18231 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -461,22 +461,12 @@ static struct file_operations mtd_fops = {
static void mtd_notify_add(struct mtd_info* mtd)
{
- char name[16];
-
if (!mtd)
return;
-
- sprintf(name, "mtd/%d", mtd->index);
- devfs_register(NULL, name,
- DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2,
- S_IFCHR | S_IRUGO | S_IWUGO,
- &mtd_fops, NULL);
-
- sprintf(name, "mtd/%dro", mtd->index);
- devfs_register(NULL, name,
- DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2+1,
- S_IFCHR | S_IRUGO | S_IWUGO,
- &mtd_fops, NULL);
+ devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+ S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%d", mtd->index);
+ devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
+ S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%dro", mtd->index);
}
static void mtd_notify_remove(struct mtd_info* mtd)
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 222ed67f4663..7c3eb5c15a16 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -159,7 +159,7 @@ static void media_check(unsigned long arg);
static int el3_config(struct net_device *dev, struct ifmap *map);
static int el3_open(struct net_device *dev);
static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void update_stats(struct net_device *dev);
static struct net_device_stats *el3_get_stats(struct net_device *dev);
static int el3_rx(struct net_device *dev);
@@ -816,15 +816,16 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
/* The EL3 interrupt handler. */
-static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct el3_private *lp = dev_id;
struct net_device *dev = &lp->dev;
ioaddr_t ioaddr, status;
- int i = 0;
+ int i = 0, handled = 1;
if (!netif_device_present(dev))
- return;
+ return IRQ_NONE;
+
ioaddr = dev->base_addr;
DEBUG(3, "%s: interrupt, status %4.4x.\n",
@@ -833,9 +834,9 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_lock(&lp->lock);
while ((status = inw(ioaddr + EL3_STATUS)) &
(IntLatch | RxComplete | StatsFull)) {
- if (!netif_device_present(dev) ||
- ((status & 0xe000) != 0x2000)) {
+ if ((status & 0xe000) != 0x2000) {
DEBUG(1, "%s: interrupt from dead card\n", dev->name);
+ handled = 0;
break;
}
@@ -897,7 +898,7 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock(&lp->lock);
DEBUG(3, "%s: exiting interrupt, status %4.4x.\n",
dev->name, inw(ioaddr + EL3_STATUS));
- return;
+ return IRQ_RETVAL(handled);
}
static void media_check(unsigned long arg)
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 1934b151751a..58924d49098e 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -107,7 +107,7 @@ static int fjn_config(struct net_device *dev, struct ifmap *map);
static int fjn_open(struct net_device *dev);
static int fjn_close(struct net_device *dev);
static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void fjn_rx(struct net_device *dev);
static void fjn_reset(struct net_device *dev);
static struct net_device_stats *fjn_get_stats(struct net_device *dev);
@@ -845,7 +845,7 @@ module_exit(exit_fmvj18x_cs);
/*====================================================================*/
-static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
local_info_t *lp = dev_id;
struct net_device *dev = &lp->dev;
@@ -855,7 +855,7 @@ static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (lp == NULL) {
printk(KERN_NOTICE "fjn_interrupt(): irq %d for "
"unknown device.\n", irq);
- return;
+ return IRQ_NONE;
}
ioaddr = dev->base_addr;
@@ -899,6 +899,7 @@ static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
outb(D_TX_INTR, ioaddr + TX_INTR);
outb(D_RX_INTR, ioaddr + RX_INTR);
+ return IRQ_HANDLED;
} /* fjn_interrupt */
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index 90909618fb4d..09a9c008ace7 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -127,7 +127,7 @@ static dev_link_t *dev_list;
extern int ibmtr_probe(struct net_device *dev);
extern int trdev_init(struct net_device *dev);
-extern void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t tok_interrupt (int irq, void *dev_id, struct pt_regs *regs);
/*====================================================================*/
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index bc29dd21b1df..eec7c7be4082 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -431,7 +431,7 @@ static int mace_open(struct net_device *dev);
static int mace_close(struct net_device *dev);
static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void mace_tx_timeout(struct net_device *dev);
-static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static struct net_device_stats *mace_get_stats(struct net_device *dev);
static int mace_rx(struct net_device *dev, unsigned char RxCnt);
static void restore_multicast_list(struct net_device *dev);
@@ -1143,7 +1143,7 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
mace_interrupt
The interrupt handler.
---------------------------------------------------------------------------- */
-static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
mace_private *lp = (mace_private *)dev_id;
struct net_device *dev = &lp->dev;
@@ -1154,7 +1154,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (dev == NULL) {
DEBUG(2, "mace_interrupt(): irq 0x%X for unknown device.\n",
irq);
- return;
+ return IRQ_NONE;
}
if (lp->tx_irq_disabled) {
@@ -1169,12 +1169,12 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
inb(ioaddr + AM2150_MACE_BASE + MACE_IMR)
);
/* WARNING: MACE_IR has been read! */
- return;
+ return IRQ_NONE;
}
if (!netif_device_present(dev)) {
DEBUG(2, "%s: interrupt from dead card\n", dev->name);
- goto exception;
+ return IRQ_NONE;
}
do {
@@ -1279,8 +1279,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
} while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt));
-exception:
- return;
+ return IRQ_HANDLED;
} /* mace_interrupt */
/* ----------------------------------------------------------------------------
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 502951f0aaf1..cff9659cc796 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -293,7 +293,7 @@ static int smc_close(struct net_device *dev);
static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void smc_tx_timeout(struct net_device *dev);
static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void smc_rx(struct net_device *dev);
static struct net_device_stats *smc_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
@@ -1574,16 +1574,18 @@ static void smc_eph_irq(struct net_device *dev)
/*====================================================================*/
-static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct smc_private *smc = dev_id;
struct net_device *dev = &smc->dev;
ioaddr_t ioaddr;
u_short saved_bank, saved_pointer, mask, status;
+ unsigned int handled = 1;
char bogus_cnt = INTR_WORK; /* Work we are willing to do. */
if (!netif_device_present(dev))
- return;
+ return IRQ_NONE;
+
ioaddr = dev->base_addr;
DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name,
@@ -1596,6 +1598,7 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
maybe it has been ejected. */
DEBUG(1, "%s: SMC91c92 interrupt %d for non-existent"
"/ejected device.\n", dev->name, irq);
+ handled = 0;
goto irq_done;
}
@@ -1609,9 +1612,11 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
status = inw(ioaddr + INTERRUPT) & 0xff;
DEBUG(3, "%s: Status is %#2.2x (mask %#2.2x).\n", dev->name,
status, mask);
- if ((status & mask) == 0)
+ if ((status & mask) == 0) {
+ if (bogus_cnt == INTR_WORK)
+ handled = 0;
break;
-
+ }
if (status & IM_RCV_INT) {
/* Got a packet(s). */
smc_rx(dev);
@@ -1683,6 +1688,7 @@ irq_done:
readb(smc->base+MEGAHERTZ_ISR);
}
#endif
+ return IRQ_RETVAL(handled);
}
/*====================================================================*/
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index c87270efc696..4e11f8805044 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -317,7 +317,7 @@ static void xirc2ps_detach(dev_link_t *);
* less on other parts of the kernel.
*/
-static void xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs);
/*
* The dev_info variable is the "key" that is used to match up this
@@ -1296,7 +1296,7 @@ xirc2ps_event(event_t event, int priority,
/****************
* This is the Interrupt service route.
*/
-static void
+static irqreturn_t
xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *)dev_id;
@@ -1305,14 +1305,14 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
u_char saved_page;
unsigned bytes_rcvd;
unsigned int_status, eth_status, rx_status, tx_status;
- unsigned rsr, pktlen;
+ unsigned rsr, pktlen, handled = 1;
ulong start_ticks = jiffies; /* fixme: jiffies rollover every 497 days
* is this something to worry about?
* -- on a laptop?
*/
if (!netif_device_present(dev))
- return;
+ return IRQ_NONE;
ioaddr = dev->base_addr;
if (lp->mohawk) { /* must disable the interrupt */
@@ -1330,6 +1330,7 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
loop_entry:
if (int_status == 0xff) { /* card may be ejected */
DEBUG(3, "%s: interrupt %d for dead card\n", dev->name, irq);
+ handled = 0;
goto leave;
}
eth_status = GetByte(XIRCREG_ESR);
@@ -1514,6 +1515,7 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* force an interrupt with this command:
* PutByte(XIRCREG_CR, EnableIntr|ForceIntr);
*/
+ return IRQ_RETVAL(handled);
} /* xirc2ps_interrupt */
/*====================================================================*/
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index aef18659ef72..542d0ff3f62c 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -784,11 +784,14 @@ int __init ppp_init(void)
printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
- if (err)
+ if (!err) {
+ err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0),
+ S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
+ }
+
+ if (!err)
printk(KERN_ERR "failed to register PPP device (%d)\n", err);
- devfs_register(NULL, "ppp", DEVFS_FL_DEFAULT, PPP_MAJOR, 0,
- S_IFCHR | S_IRUSR | S_IWUSR, &ppp_device_fops, NULL);
- return 0;
+ return err;
}
/*
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index b9166eecf26a..c6c95b0166c6 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -392,12 +392,9 @@ static int __init cosa_init(void)
}
devfs_mk_dir("cosa");
for (i=0; i<nr_cards; i++) {
- char name[16];
- sprintf(name, "cosa/%d", i);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- cosa_major, i,
- S_IFCHR | S_IRUSR | S_IWUSR,
- &cosa_fops, NULL);
+ devfs_mk_cdev(MKDEV(cosa_major, i),
+ S_IFCHR|S_IRUSR|S_IWUSR,
+ "cosa/%d", i);
}
return 0;
}
diff --git a/drivers/s390/char/tuball.c b/drivers/s390/char/tuball.c
index 638900dc13ab..7539ba0ac13a 100644
--- a/drivers/s390/char/tuball.c
+++ b/drivers/s390/char/tuball.c
@@ -468,9 +468,8 @@ tubmakemin(int irq, s390_dev_info_t *dp)
}
#endif /* CONFIG_TN3270_CONSOLE */
-#ifdef CONFIG_DEVFS_FS
- fs3270_devfs_register(tubp);
-#endif
+ devfs_mk_cdev(MKDEV(IBM_FS3270_MAJOR, tubp->minor),
+ S_IFCHR|S_IRUSR|S_IWUSR, "3270/tub%.4x");
TUBUNLOCK(tubp->irq, flags);
return minor;
@@ -492,9 +491,7 @@ tubfiniminors(void)
for (i = 0; i < TUBMAXMINS; i++) {
tubpp = &(*tubminors)[i];
if ((tubp = *tubpp)) {
-#ifdef CONFIG_DEVFS_FS
- fs3270_devfs_unregister(tubp);
-#endif
+ devfs_remove("3270/tub%.4x", tubp->devno);
tubdelbyirq(tubp, tubp->irq);
tty3270_rcl_fini(tubp);
kfree(tubp->tty_bcb.bc_buf);
diff --git a/drivers/s390/char/tubfs.c b/drivers/s390/char/tubfs.c
index 423ab8deb81e..b6ac0dde5507 100644
--- a/drivers/s390/char/tubfs.c
+++ b/drivers/s390/char/tubfs.c
@@ -23,9 +23,7 @@ static void fs3270_int(tub_t *tubp, devstat_t *dsp);
extern void tty3270_refresh(tub_t *);
static struct file_operations fs3270_fops = {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0))
.owner = THIS_MODULE, /* owner */
-#endif
.read = fs3270_read, /* read */
.write = fs3270_write, /* write */
.ioctl = fs3270_ioctl, /* ioctl */
@@ -33,27 +31,6 @@ static struct file_operations fs3270_fops = {
.release = fs3270_close, /* release */
};
-#ifdef CONFIG_DEVFS_FS
-void fs3270_devfs_register(tub_t *tubp)
-{
- char name[16];
-
- sprintf(name, "3270/tub%.4x", tubp->devno);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- IBM_FS3270_MAJOR, tubp->minor,
- S_IFCHR | S_IRUSR | S_IWUSR, &fs3270_fops, NULL);
- sprintf(name, "tty%.4x", tubp->devno);
- tty_register_devfs_name(&tty3270_driver, 0, tubp->minor,
- NULL, name);
-}
-
-void fs3270_devfs_unregister(tub_t *tubp)
-{
- devfs_remove("3270/tub%.4x", tubp->devno);
- devfs_remove("3270/tty%.4x", tubp->devno);
-}
-#endif
-
/*
* fs3270_init() -- Initialize fullscreen tubes
*/
@@ -69,10 +46,8 @@ fs3270_init(void)
return -1;
}
devfs_mk_dir("3270");
- devfs_register(NULL, "3270/tub", 0,
- IBM_FS3270_MAJOR, 0,
- S_IFCHR | S_IRUGO | S_IWUGO,
- &fs3270_fops, NULL);
+ devfs_mk_cdev(MKDEV(IBM_FS3270_MAJOR, 0),
+ S_IFCHR|S_IRUGO|S_IWUGO, "3270/tub");
fs3270_major = IBM_FS3270_MAJOR;
return 0;
}
diff --git a/drivers/s390/char/tubio.h b/drivers/s390/char/tubio.h
index 62b36b9a5b5a..24fc1fa0c2c5 100644
--- a/drivers/s390/char/tubio.h
+++ b/drivers/s390/char/tubio.h
@@ -337,10 +337,6 @@ extern int tty3270_major;
extern int tty3270_proc_misc;
extern enum tubwhat tty3270_proc_what;
extern struct tty_driver tty3270_driver;
-#ifdef CONFIG_DEVFS_FS
-extern void fs3270_devfs_register(tub_t *);
-extern void fs3270_devfs_unregister(tub_t *);
-#endif
#ifndef spin_trylock_irqsave
#define spin_trylock_irqsave(lock, flags) \
diff --git a/drivers/s390/char/tubtty.c b/drivers/s390/char/tubtty.c
index 9853e174a191..a79e289c282c 100644
--- a/drivers/s390/char/tubtty.c
+++ b/drivers/s390/char/tubtty.c
@@ -90,9 +90,7 @@ tty3270_init(void)
td->subtype = SYSTEM_TYPE_TTY;
td->init_termios = tty_std_termios;
td->flags = TTY_DRIVER_RESET_TERMIOS;
-#ifdef CONFIG_DEVFS_FS
td->flags |= TTY_DRIVER_NO_DEVFS;
-#endif
td->refcount = &tty3270_refcount;
td->table = tty3270_table;
td->termios = tty3270_termios;
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index be544f551a81..fc49372e52c4 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -1051,11 +1051,8 @@ static int __init bpp_init(void)
}
devfs_mk_dir("bpp");
for (idx = 0; idx < BPP_NO; idx++) {
- char name[16];
- sprintf(name, "bpp/%d", idx);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT,
- BPP_MAJOR, idx, S_IFCHR | S_IRUSR | S_IWUSR,
- &bpp_fops, NULL);
+ devfs_mk_cdev(MKDEV(BPP_MAJOR, idx),
+ S_IFCHR | S_IRUSR | S_IWUSR, "bpp/%d", idx);
}
return 0;
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 1f2d749843dd..d778964a586b 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -143,8 +143,6 @@ int init_vfc_devstruct(struct vfc_dev *dev, int instance)
int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance)
{
- char devname[16];
-
if(dev == NULL) {
printk(KERN_ERR "VFC: Bogus pointer passed\n");
return -ENOMEM;
@@ -167,11 +165,9 @@ int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance)
if (init_vfc_hw(dev))
return -EIO;
- sprintf (devname, "vfc/%d", instance);
- dev->de = devfs_register (NULL, devname, DEVFS_FL_DEFAULT,
- VFC_MAJOR, instance,
- S_IFCHR | S_IRUSR | S_IWUSR,
- &vfc_fops, NULL);
+ devfs_mk_cdev(MKDEV(VFC_MAJOR, instance),
+ S_IFCHR | S_IRUSR | S_IWUSR,
+ "vfc/%d", instance);
return 0;
}
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index a11b5ba064fb..654d96c314c7 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -5527,11 +5527,10 @@ static int osst_attach(Scsi_Device * SDp)
write_unlock(&os_scsi_tapes_lock);
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
- char name[8], devfs_name[64];
+ char name[8];
/* Rewind entry */
sprintf(name, "ot%s", osst_formats[mode]);
- sprintf(devfs_name, "%s/ot%s", SDp->devfs_name, osst_formats[mode]);
sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s",
SDp->sdev_driverfs_dev.bus_id, name);
@@ -5545,13 +5544,13 @@ static int osst_attach(Scsi_Device * SDp)
device_create_file(&tpnt->driverfs_dev_r[mode],
&dev_attr_type);
device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev);
- devfs_register(NULL, devfs_name, 0,
- OSST_MAJOR, dev_num + (mode << 5),
- S_IFCHR | S_IRUGO | S_IWUGO,
- &osst_fops, NULL);
+
+ devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)),
+ S_IFCHR | S_IRUGO | S_IWUGO,
+ "%s/ot%s", SDp->devfs_name, osst_formats[mode]);
+
/* No-rewind entry */
sprintf (name, "ot%sn", osst_formats[mode]);
- sprintf(devfs_name, "%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s",
SDp->sdev_driverfs_dev.bus_id, name);
@@ -5566,10 +5565,10 @@ static int osst_attach(Scsi_Device * SDp)
&dev_attr_type);
device_create_file(&tpnt->driverfs_dev_n[mode],
&dev_attr_kdev);
- devfs_register(NULL, devfs_name, 0,
- OSST_MAJOR, dev_num + (mode << 5) + 128,
- S_IFCHR | S_IRUGO | S_IWUGO,
- &osst_fops, NULL);
+
+ devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128),
+ S_IFCHR | S_IRUGO | S_IWUGO,
+ "%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
}
drive->number = devfs_register_tape(SDp->devfs_name);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 5cc11cb29c03..9990fcf08cee 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1350,7 +1350,6 @@ sg_attach(Scsi_Device * scsidp)
struct gendisk *disk;
Sg_device *sdp = NULL;
unsigned long iflags;
- char devfs_name[64];
int k, error;
disk = alloc_disk(1);
@@ -1449,11 +1448,9 @@ find_empty_slot:
device_create_file(&sdp->sg_driverfs_dev, &dev_attr_type);
device_create_file(&sdp->sg_driverfs_dev, &dev_attr_kdev);
- sprintf(devfs_name, "%s/generic", scsidp->devfs_name);
- devfs_register(NULL, devfs_name, 0,
- SCSI_GENERIC_MAJOR, k,
+ devfs_mk_cdev(MKDEV(SCSI_GENERIC_MAJOR, k),
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
- &sg_fops, sdp);
+ "%s/generic", scsidp->devfs_name);
switch (scsidp->type) {
case TYPE_DISK:
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index ba81dc7f682e..e7f2b7c6bc46 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3865,11 +3865,10 @@ static int st_attach(Scsi_Device * SDp)
write_unlock(&st_dev_arr_lock);
for (mode = 0; mode < ST_NBR_MODES; ++mode) {
- char name[8], devfs_name[64];
+ char name[8];
/* Rewind entry */
sprintf(name, "mt%s", st_formats[mode]);
- sprintf(devfs_name, "%s/mt%s", SDp->devfs_name, st_formats[mode]);
sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s",
SDp->sdev_driverfs_dev.bus_id, name);
@@ -3883,13 +3882,12 @@ static int st_attach(Scsi_Device * SDp)
device_create_file(&tpnt->driverfs_dev_r[mode],
&dev_attr_type);
device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev);
- devfs_register(NULL, devfs_name, 0,
- SCSI_TAPE_MAJOR, dev_num + (mode << 5),
+ devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5)),
S_IFCHR | S_IRUGO | S_IWUGO,
- &st_fops, NULL);
+ "%s/mt%s", SDp->devfs_name, st_formats[mode]);
+
/* No-rewind entry */
sprintf (name, "mt%sn", st_formats[mode]);
- sprintf(devfs_name, "%s/mt%sn", SDp->devfs_name, st_formats[mode]);
sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s",
SDp->sdev_driverfs_dev.bus_id, name);
@@ -3904,10 +3902,9 @@ static int st_attach(Scsi_Device * SDp)
&dev_attr_type);
device_create_file(&tpnt->driverfs_dev_n[mode],
&dev_attr_kdev);
- devfs_register(NULL, devfs_name, 0,
- SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128,
+ devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128),
S_IFCHR | S_IRUGO | S_IWUGO,
- &st_fops, NULL);
+ "%s/mt%sn", SDp->devfs_name, st_formats[mode]);
}
disk->number = devfs_register_tape(SDp->devfs_name);
diff --git a/drivers/serial/core.c b/drivers/serial/core.c
index 0d8c7601af30..7122b3932a01 100644
--- a/drivers/serial/core.c
+++ b/drivers/serial/core.c
@@ -2242,7 +2242,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
* Register the port whether it's detected or not. This allows
* setserial to be used to alter this ports parameters.
*/
- tty_register_device(drv->tty_driver, port->line);
+ tty_register_device(drv->tty_driver, port->line, NULL);
out:
up(&port_sem);
diff --git a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c
index 40501a59cfce..09b7845dd8fc 100644
--- a/drivers/sgi/char/sgiserial.c
+++ b/drivers/sgi/char/sgiserial.c
@@ -1867,6 +1867,7 @@ int rs_init(void)
memset(&serial_driver, 0, sizeof(struct tty_driver));
serial_driver.magic = TTY_DRIVER_MAGIC;
+ serial_driver.owner = THIS_MODULE;
serial_driver.name = "ttyS";
serial_driver.major = TTY_MAJOR;
serial_driver.minor_start = 64;
diff --git a/drivers/sgi/char/shmiq.c b/drivers/sgi/char/shmiq.c
index a058c65893cf..8259ed117134 100644
--- a/drivers/sgi/char/shmiq.c
+++ b/drivers/sgi/char/shmiq.c
@@ -470,9 +470,8 @@ shmiq_init (void)
printk ("SHMIQ setup\n");
register_chrdev(SHMIQ_MAJOR, "shmiq", &shmiq_fops);
for (i = 0; i < 3; i++) {
- devfs_register (NULL, names[i], DEVFS_FL_DEFAULT,
- SHMIQ_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR,
- &shmiq_fops, NULL);
+ devfs_mk_cdev(MKDEV(SHMIQ_MAJOR, i),
+ S_IFCHR | S_IRUSR | S_IWUSR, names[i]);
}
}
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 2f0dc74de41c..0a3d80add119 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -1872,6 +1872,7 @@ int __init zs_init(void)
memset(&serial_driver, 0, sizeof(struct tty_driver));
serial_driver.magic = TTY_DRIVER_MAGIC;
+ serial_driver.owner = THIS_MODULE;
#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
serial_driver.name = "tts/";
#else
@@ -1970,8 +1971,8 @@ int __init zs_init(void)
printk("ttyS%02d at 0x%08x (irq = %d)", info->line,
info->port, info->irq);
printk(" is a Z85C30 SCC\n");
- tty_register_device(&serial_driver, info->line);
- tty_register_device(&callout_driver, info->line);
+ tty_register_device(&serial_driver, info->line, NULL);
+ tty_register_device(&callout_driver, info->line, NULL);
}
diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
index 54a7f8082c2f..3e55a8f446e0 100644
--- a/drivers/usb/class/bluetty.c
+++ b/drivers/usb/class/bluetty.c
@@ -1198,7 +1198,7 @@ static int usb_bluetooth_probe (struct usb_interface *intf,
bluetooth, endpoint->bInterval);
/* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */
- tty_register_device (&bluetooth_tty_driver, minor);
+ tty_register_device (&bluetooth_tty_driver, minor, &intf->dev);
info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor);
bluetooth_table[minor] = bluetooth;
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 3600377b3306..64789f0e8469 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -653,7 +653,7 @@ static int acm_probe (struct usb_interface *intf,
usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
- tty_register_device(&acm_tty_driver, minor);
+ tty_register_device(&acm_tty_driver, minor, &intf->dev);
acm_table[minor] = acm;
usb_set_intfdata (intf, acm);
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 639a9a9e3d50..3eceae10c504 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -160,8 +160,7 @@ int usb_register_dev(struct usb_interface *intf,
/* handle the devfs registration */
snprintf(name, DEVICE_ID_SIZE, class_driver->name, minor - minor_base);
- devfs_register(NULL, name, 0, USB_MAJOR, minor, class_driver->mode,
- class_driver->fops, NULL);
+ devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name);
/* create a usb class device for this usb interface */
memset(&intf->class_dev, 0x00, sizeof(struct class_device));
diff --git a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
index 80d01df3e3e1..7fff7d0740c9 100644
--- a/drivers/usb/misc/tiglusb.c
+++ b/drivers/usb/misc/tiglusb.c
@@ -327,7 +327,6 @@ tiglusb_probe (struct usb_interface *intf,
int minor = -1;
int i;
ptiglusb_t s;
- char name[32];
dbg ("probing vendor id 0x%x, device id 0x%x",
dev->descriptor.idVendor, dev->descriptor.idProduct);
@@ -371,12 +370,9 @@ tiglusb_probe (struct usb_interface *intf,
up (&s->mutex);
dbg ("bound to interface");
- sprintf (name, "ticables/usb/%d", s->minor);
- dbg ("registering to devfs : major = %d, minor = %d, node = %s",
- TIUSB_MAJOR, (TIUSB_MINOR + s->minor), name);
- devfs_register(NULL, name, DEVFS_FL_DEFAULT, TIUSB_MAJOR,
- TIUSB_MINOR + s->minor, S_IFCHR | S_IRUGO | S_IWUGO,
- &tiglusb_fops, NULL);
+ devfs_mk_cdev(MKDEV(TIUSB_MAJOR, TIUSB_MINOR) + s->minor,
+ S_IFCHR | S_IRUGO | S_IWUGO,
+ "ticables/usb/%d", s->minor);
/* Display firmware version */
info ("firmware revision %i.%02x",
@@ -390,8 +386,6 @@ tiglusb_probe (struct usb_interface *intf,
static void
tiglusb_disconnect (struct usb_interface *intf)
{
- char name[32];
-
ptiglusb_t s = usb_get_intfdata (intf);
usb_set_intfdata (intf, NULL);
@@ -408,7 +402,7 @@ tiglusb_disconnect (struct usb_interface *intf)
s->dev = NULL;
s->opened = 0;
- devfs_remove (name, "ticables/usb/%d", s->minor);
+ devfs_remove("ticables/usb/%d", s->minor);
info ("device %d removed", s->minor);
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 26f35b9f1cc8..2234b161efb1 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -23,18 +23,6 @@
#include "usb-serial.h"
-static ssize_t show_dev (struct device *dev, char *buf)
-{
- struct usb_serial_port *port= to_usb_serial_port(dev);
- dev_t base;
-
- port = to_usb_serial_port(dev);
-
- base = MKDEV(SERIAL_TTY_MAJOR, port->number);
- return sprintf(buf, "%04x\n", base);
-}
-static DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
{
struct usb_serial_device_type *driver;
@@ -88,10 +76,7 @@ static int usb_serial_device_probe (struct device *dev)
}
minor = port->number;
-
- tty_register_device (&usb_serial_tty_driver, minor);
- device_create_file (dev, &dev_attr_dev);
-
+ tty_register_device (&usb_serial_tty_driver, minor, dev);
dev_info(&port->serial->dev->dev,
"%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)\n",
driver->name, minor, minor);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 3e57dd0018ff..b0ac9d9ddf3d 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1214,7 +1214,6 @@ static struct file_operations fb_fops = {
int
register_framebuffer(struct fb_info *fb_info)
{
- char name_buf[12];
int i;
if (num_registered_fb == FB_MAX)
@@ -1242,10 +1241,9 @@ register_framebuffer(struct fb_info *fb_info)
spin_lock_init(&fb_info->pixmap.lock);
registered_fb[i] = fb_info;
- sprintf(name_buf, "fb/%d", i);
- devfs_register(NULL, name_buf, DEVFS_FL_DEFAULT,
- FB_MAJOR, i, S_IFCHR | S_IRUGO | S_IWUGO,
- &fb_fops, NULL);
+
+ devfs_mk_cdev(MKDEV(FB_MAJOR, i),
+ S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i);
return 0;
}
diff --git a/fs/Kconfig b/fs/Kconfig
index 7de0d9f56da7..5102d45e6466 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -73,6 +73,18 @@ config EXT2_FS_POSIX_ACL
If you don't know what Access Control Lists are, say N
+config EXT2_FS_SECURITY
+ bool "Ext2 Security Labels"
+ depends on EXT2_FS_XATTR
+ help
+ Security labels support alternative access control models
+ implemented by security modules like SELinux. This option
+ enables an extended attribute handler for file security
+ labels in the ext2 filesystem.
+
+ If you are not using a security module that requires using
+ extended attributes for file security labels, say N.
+
config EXT3_FS
tristate "Ext3 journalling file system support"
help
@@ -131,6 +143,18 @@ config EXT3_FS_POSIX_ACL
If you don't know what Access Control Lists are, say N
+config EXT3_FS_SECURITY
+ bool "Ext3 Security Labels"
+ depends on EXT3_FS_XATTR
+ help
+ Security labels support alternative access control models
+ implemented by security modules like SELinux. This option
+ enables an extended attribute handler for file security
+ labels in the ext3 filesystem.
+
+ If you are not using a security module that requires using
+ extended attributes for file security labels, say N.
+
config JBD
# CONFIG_JBD could be its own option (even modular), but until there are
# other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 6c245691bb13..386f5fff4a77 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -65,7 +65,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
brelse(bh);
}
- UPDATE_ATIME(dir);
+ update_atime(dir);
unlock_kernel();
return 0;
}
diff --git a/fs/buffer.c b/fs/buffer.c
index 5ed6a8e2918f..f380aa531352 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -244,18 +244,28 @@ int fsync_bdev(struct block_device *bdev)
* sync everything. Start out by waking pdflush, because that writes back
* all queues in parallel.
*/
-asmlinkage long sys_sync(void)
+static void do_sync(unsigned long wait)
{
wakeup_bdflush(0);
sync_inodes(0); /* All mappings, inodes and their blockdevs */
DQUOT_SYNC(NULL);
sync_supers(); /* Write the superblocks */
sync_filesystems(0); /* Start syncing the filesystems */
- sync_filesystems(1); /* Waitingly sync the filesystems */
- sync_inodes(1); /* Mappings, inodes and blockdevs, again. */
+ sync_filesystems(wait); /* Waitingly sync the filesystems */
+ sync_inodes(wait); /* Mappings, inodes and blockdevs, again. */
+}
+
+asmlinkage long sys_sync(void)
+{
+ do_sync(1);
return 0;
}
+void emergency_sync(void)
+{
+ pdflush_operation(do_sync, 0);
+}
+
/*
* Generic function to fsync a file.
*
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 365184198f87..691a14f27724 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -373,16 +373,10 @@ static int init_coda_psdev(void)
}
devfs_mk_dir ("coda");
for (i = 0; i < MAX_CODADEVS; i++) {
- char name[16];
- sprintf(name, "coda/%d", i);
- devfs_register(NULL, name, DEVFS_FL_NONE,
- CODA_PSDEV_MAJOR, i,
- S_IFCHR | S_IRUSR | S_IWUSR,
- &coda_psdev_fops, NULL);
+ devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i),
+ S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i);
}
-
coda_sysctl_init();
-
return 0;
}
diff --git a/fs/dcache.c b/fs/dcache.c
index 9eec20e0ab20..33e861853287 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -770,12 +770,12 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
void d_instantiate(struct dentry *entry, struct inode * inode)
{
if (!list_empty(&entry->d_alias)) BUG();
- security_d_instantiate(entry, inode);
spin_lock(&dcache_lock);
if (inode)
list_add(&entry->d_alias, &inode->i_dentry);
entry->d_inode = inode;
spin_unlock(&dcache_lock);
+ security_d_instantiate(entry, inode);
}
/**
@@ -903,12 +903,12 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
struct dentry *new = NULL;
if (inode && S_ISDIR(inode->i_mode)) {
- security_d_instantiate(dentry, inode);
spin_lock(&dcache_lock);
if (!list_empty(&inode->i_dentry)) {
new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
__dget_locked(new);
spin_unlock(&dcache_lock);
+ security_d_instantiate(dentry, inode);
d_rehash(dentry);
d_move(new, dentry);
iput(inode);
@@ -917,6 +917,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
list_add(&dentry->d_alias, &inode->i_dentry);
dentry->d_inode = inode;
spin_unlock(&dcache_lock);
+ security_d_instantiate(dentry, inode);
d_rehash(dentry);
}
} else
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 30efb7302ec6..fa63dc1820a5 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -1562,6 +1562,52 @@ int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...)
EXPORT_SYMBOL(devfs_mk_bdev);
+int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
+{
+ struct devfs_entry *dir = NULL, *de;
+ char buf[64];
+ va_list args;
+ int error, n;
+
+ if (!S_ISCHR(mode)) {
+ printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
+ __FUNCTION__, mode, buf);
+ return -EINVAL;
+ }
+
+ va_start(args, fmt);
+ n = vsnprintf(buf, 64, fmt, args);
+ if (n >= 64 || !buf[0]) {
+ printk(KERN_WARNING "%s: invalid format string\n",
+ __FUNCTION__);
+ return -EINVAL;
+ }
+
+ de = _devfs_prepare_leaf(&dir, buf, mode);
+ if (!de) {
+ printk(KERN_WARNING "%s: could not prepare leaf for %s\n",
+ __FUNCTION__, buf);
+ return -ENOMEM; /* could be more accurate... */
+ }
+
+ de->u.cdev.dev = dev;
+
+ error = _devfs_append_entry(dir, de, NULL);
+ if (error) {
+ printk(KERN_WARNING "%s: could not append to parent for %s\n",
+ __FUNCTION__, buf);
+ goto out;
+ }
+
+ devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED);
+ out:
+ devfs_put(dir);
+ return error;
+}
+
+EXPORT_SYMBOL(devfs_mk_cdev);
+
+
/**
* _devfs_unhook - Unhook a device entry from its parents list
* @de: The entry to unhook.
diff --git a/fs/ext2/Makefile b/fs/ext2/Makefile
index 0307254ae990..891d1bfa772f 100644
--- a/fs/ext2/Makefile
+++ b/fs/ext2/Makefile
@@ -14,3 +14,7 @@ endif
ifeq ($(CONFIG_EXT2_FS_POSIX_ACL),y)
ext2-objs += acl.o
endif
+
+ifeq ($(CONFIG_EXT2_FS_SECURITY),y)
+ext2-objs += xattr_security.o
+endif
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 2cc4c11bcd1a..78bc2cd92cf3 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -310,7 +310,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
done:
filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
filp->f_version = inode->i_version;
- UPDATE_ATIME(inode);
+ update_atime(inode);
return 0;
}
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 01e94a68c13e..ed2d1d4e6671 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -1102,22 +1102,33 @@ init_ext2_xattr(void)
&ext2_xattr_trusted_handler);
if (err)
goto out;
+#ifdef CONFIG_EXT2_FS_SECURITY
+ err = ext2_xattr_register(EXT2_XATTR_INDEX_SECURITY,
+ &ext2_xattr_security_handler);
+ if (err)
+ goto out1;
+#endif
#ifdef CONFIG_EXT2_FS_POSIX_ACL
err = init_ext2_acl();
if (err)
- goto out1;
+ goto out2;
#endif
ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
sizeof(struct mb_cache_entry) +
sizeof(struct mb_cache_entry_index), 1, 6);
if (!ext2_xattr_cache) {
err = -ENOMEM;
- goto out2;
+ goto out3;
}
return 0;
-out2:
+out3:
#ifdef CONFIG_EXT2_FS_POSIX_ACL
exit_ext2_acl();
+out2:
+#endif
+#ifdef CONFIG_EXT2_FS_SECURITY
+ ext2_xattr_unregister(EXT2_XATTR_INDEX_SECURITY,
+ &ext2_xattr_security_handler);
out1:
#endif
ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED,
@@ -1135,6 +1146,10 @@ exit_ext2_xattr(void)
#ifdef CONFIG_EXT2_FS_POSIX_ACL
exit_ext2_acl();
#endif
+#ifdef CONFIG_EXT2_FS_SECURITY
+ ext2_xattr_unregister(EXT2_XATTR_INDEX_SECURITY,
+ &ext2_xattr_security_handler);
+#endif
ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED,
&ext2_xattr_trusted_handler);
ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h
index 1fdb6f970b66..a57b9da2306d 100644
--- a/fs/ext2/xattr.h
+++ b/fs/ext2/xattr.h
@@ -22,6 +22,7 @@
#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
#define EXT2_XATTR_INDEX_TRUSTED 4
+#define EXT2_XATTR_INDEX_SECURITY 6
struct ext2_xattr_header {
__u32 h_magic; /* magic number for identification */
@@ -134,4 +135,5 @@ exit_ext2_xattr(void)
extern struct ext2_xattr_handler ext2_xattr_user_handler;
extern struct ext2_xattr_handler ext2_xattr_trusted_handler;
+extern struct ext2_xattr_handler ext2_xattr_security_handler;
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
new file mode 100644
index 000000000000..65a97edcefce
--- /dev/null
+++ b/fs/ext2/xattr_security.c
@@ -0,0 +1,54 @@
+/*
+ * linux/fs/ext2/xattr_security.c
+ * Handler for storing security labels as extended attributes.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ext2_fs.h>
+#include "xattr.h"
+
+#define XATTR_SECURITY_PREFIX "security."
+
+static size_t
+ext2_xattr_security_list(char *list, struct inode *inode,
+ const char *name, int name_len)
+{
+ const int prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
+
+ if (list) {
+ memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
+ memcpy(list+prefix_len, name, name_len);
+ list[prefix_len + name_len] = '\0';
+ }
+ return prefix_len + name_len + 1;
+}
+
+static int
+ext2_xattr_security_get(struct inode *inode, const char *name,
+ void *buffer, size_t size)
+{
+ if (strcmp(name, "") == 0)
+ return -EINVAL;
+ return ext2_xattr_get(inode, EXT2_XATTR_INDEX_SECURITY, name,
+ buffer, size);
+}
+
+static int
+ext2_xattr_security_set(struct inode *inode, const char *name,
+ const void *value, size_t size, int flags)
+{
+ if (strcmp(name, "") == 0)
+ return -EINVAL;
+ return ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, name,
+ value, size, flags);
+}
+
+struct ext2_xattr_handler ext2_xattr_security_handler = {
+ .prefix = XATTR_SECURITY_PREFIX,
+ .list = ext2_xattr_security_list,
+ .get = ext2_xattr_security_get,
+ .set = ext2_xattr_security_set,
+};
diff --git a/fs/ext3/Makefile b/fs/ext3/Makefile
index ed09a066c8d9..e1872684be41 100644
--- a/fs/ext3/Makefile
+++ b/fs/ext3/Makefile
@@ -14,3 +14,7 @@ endif
ifeq ($(CONFIG_EXT3_FS_POSIX_ACL),y)
ext3-objs += acl.o
endif
+
+ifeq ($(CONFIG_EXT3_FS_SECURITY),y)
+ext3-objs += xattr_security.o
+endif
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index cc27d4082571..1b5fae0032f2 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -216,7 +216,7 @@ revalidate:
offset = 0;
brelse (bh);
}
- UPDATE_ATIME(inode);
+ update_atime(inode);
out:
return ret;
}
@@ -489,7 +489,7 @@ static int ext3_dx_readdir(struct file * filp,
}
finished:
info->last_pos = filp->f_pos;
- UPDATE_ATIME(inode);
+ update_atime(inode);
return 0;
}
diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
index cdf736d4b867..0888abcd9757 100644
--- a/fs/ext3/fsync.c
+++ b/fs/ext3/fsync.c
@@ -27,8 +27,6 @@
#include <linux/jbd.h>
#include <linux/ext3_fs.h>
#include <linux/ext3_jbd.h>
-#include <linux/jbd.h>
-#include <linux/smp_lock.h>
/*
* akpm: A new design for ext3_sync_file().
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 46863b4ff8df..cd8cb24a3441 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -1142,22 +1142,33 @@ init_ext3_xattr(void)
&ext3_xattr_trusted_handler);
if (err)
goto out;
+#ifdef CONFIG_EXT3_FS_SECURITY
+ err = ext3_xattr_register(EXT3_XATTR_INDEX_SECURITY,
+ &ext3_xattr_security_handler);
+ if (err)
+ goto out1;
+#endif
#ifdef CONFIG_EXT3_FS_POSIX_ACL
err = init_ext3_acl();
if (err)
- goto out1;
+ goto out2;
#endif
ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
sizeof(struct mb_cache_entry) +
sizeof(struct mb_cache_entry_index), 1, 6);
if (!ext3_xattr_cache) {
err = -ENOMEM;
- goto out2;
+ goto out3;
}
return 0;
-out2:
+out3:
#ifdef CONFIG_EXT3_FS_POSIX_ACL
exit_ext3_acl();
+out2:
+#endif
+#ifdef CONFIG_EXT3_FS_SECURITY
+ ext3_xattr_unregister(EXT3_XATTR_INDEX_SECURITY,
+ &ext3_xattr_security_handler);
out1:
#endif
ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED,
@@ -1177,6 +1188,10 @@ exit_ext3_xattr(void)
#ifdef CONFIG_EXT3_FS_POSIX_ACL
exit_ext3_acl();
#endif
+#ifdef CONFIG_EXT3_FS_SECURITY
+ ext3_xattr_unregister(EXT3_XATTR_INDEX_SECURITY,
+ &ext3_xattr_security_handler);
+#endif
ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED,
&ext3_xattr_trusted_handler);
ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index ff3e10d8d701..8de7046ed175 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -21,6 +21,7 @@
#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
#define EXT3_XATTR_INDEX_TRUSTED 4
+#define EXT3_XATTR_INDEX_SECURITY 6
struct ext3_xattr_header {
__u32 h_magic; /* magic number for identification */
@@ -141,3 +142,4 @@ exit_ext3_xattr(void)
extern struct ext3_xattr_handler ext3_xattr_user_handler;
extern struct ext3_xattr_handler ext3_xattr_trusted_handler;
+extern struct ext3_xattr_handler ext3_xattr_security_handler;
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
new file mode 100644
index 000000000000..f7488fc63400
--- /dev/null
+++ b/fs/ext3/xattr_security.c
@@ -0,0 +1,55 @@
+/*
+ * linux/fs/ext3/xattr_security.c
+ * Handler for storing security labels as extended attributes.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ext3_jbd.h>
+#include <linux/ext3_fs.h>
+#include "xattr.h"
+
+#define XATTR_SECURITY_PREFIX "security."
+
+static size_t
+ext3_xattr_security_list(char *list, struct inode *inode,
+ const char *name, int name_len)
+{
+ const int prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
+
+ if (list) {
+ memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
+ memcpy(list+prefix_len, name, name_len);
+ list[prefix_len + name_len] = '\0';
+ }
+ return prefix_len + name_len + 1;
+}
+
+static int
+ext3_xattr_security_get(struct inode *inode, const char *name,
+ void *buffer, size_t size)
+{
+ if (strcmp(name, "") == 0)
+ return -EINVAL;
+ return ext3_xattr_get(inode, EXT3_XATTR_INDEX_SECURITY, name,
+ buffer, size);
+}
+
+static int
+ext3_xattr_security_set(struct inode *inode, const char *name,
+ const void *value, size_t size, int flags)
+{
+ if (strcmp(name, "") == 0)
+ return -EINVAL;
+ return ext3_xattr_set(inode, EXT3_XATTR_INDEX_SECURITY, name,
+ value, size, flags);
+}
+
+struct ext3_xattr_handler ext3_xattr_security_handler = {
+ .prefix = XATTR_SECURITY_PREFIX,
+ .list = ext3_xattr_security_list,
+ .get = ext3_xattr_security_get,
+ .set = ext3_xattr_security_set,
+};
diff --git a/fs/file_table.c b/fs/file_table.c
index 526c0dabc7b1..6762d46ceaa0 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -141,7 +141,7 @@ void close_private_file(struct file *file)
security_file_free(file);
}
-void fput(struct file * file)
+void fput(struct file *file)
{
if (atomic_dec_and_test(&file->f_count))
__fput(file);
@@ -190,6 +190,34 @@ struct file *fget(unsigned int fd)
return file;
}
+/*
+ * Lightweight file lookup - no refcnt increment if fd table isn't shared.
+ * You can use this only if it is guranteed that the current task already
+ * holds a refcnt to that file. That check has to be done at fget() only
+ * and a flag is returned to be passed to the corresponding fput_light().
+ * There must not be a cloning between an fget_light/fput_light pair.
+ */
+struct file *fget_light(unsigned int fd, int *fput_needed)
+{
+ struct file *file;
+ struct files_struct *files = current->files;
+
+ *fput_needed = 0;
+ if (likely((atomic_read(&files->count) == 1))) {
+ file = fcheck(fd);
+ } else {
+ spin_lock(&files->file_lock);
+ file = fcheck(fd);
+ if (file) {
+ get_file(file);
+ *fput_needed = 1;
+ }
+ spin_unlock(&files->file_lock);
+ }
+ return file;
+}
+
+
void put_filp(struct file *file)
{
if (atomic_dec_and_test(&file->f_count)) {
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 9e10da9fc332..db0e1597caa3 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -62,7 +62,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
down(&inode->i_sem);
- UPDATE_ATIME(inode);
+ update_atime(inode);
vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
vma->vm_ops = &hugetlb_vm_ops;
ret = hugetlb_prefault(mapping, vma);
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index a131cdc247d1..8aa973d7a734 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -127,7 +127,7 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
done:
filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
- UPDATE_ATIME(inode);
+ update_atime(inode);
unlock_kernel();
return 0;
}
diff --git a/fs/namei.c b/fs/namei.c
index 93ac080e69dd..89ff3016754b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -405,7 +405,7 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
goto loop;
current->link_count++;
current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
+ update_atime(dentry->d_inode);
err = dentry->d_inode->i_op->follow_link(dentry, nd);
current->link_count--;
return err;
@@ -1327,7 +1327,7 @@ do_link:
error = security_inode_follow_link(dentry, nd);
if (error)
goto exit_dput;
- UPDATE_ATIME(dentry->d_inode);
+ update_atime(dentry->d_inode);
error = dentry->d_inode->i_op->follow_link(dentry, nd);
dput(dentry);
if (error)
diff --git a/fs/namespace.c b/fs/namespace.c
index 2dc2a5f73976..91cfd2ce3825 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -24,7 +24,6 @@
#include <asm/uaccess.h>
extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
-extern int do_remount_sb(struct super_block *sb, int flags, void * data);
extern int __init init_rootfs(void);
extern int __init fs_subsys_init(void);
@@ -326,7 +325,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
down_write(&sb->s_umount);
if (!(sb->s_flags & MS_RDONLY)) {
lock_kernel();
- retval = do_remount_sb(sb, MS_RDONLY, 0);
+ retval = do_remount_sb(sb, MS_RDONLY, 0, 0);
unlock_kernel();
}
up_write(&sb->s_umount);
@@ -555,7 +554,7 @@ static int do_remount(struct nameidata *nd,int flags,int mnt_flags,void *data)
return -EINVAL;
down_write(&sb->s_umount);
- err = do_remount_sb(sb, flags, data);
+ err = do_remount_sb(sb, flags, data, 0);
if (!err)
nd->mnt->mnt_flags=mnt_flags;
up_write(&sb->s_umount);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 712717913231..a0569d609554 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -682,7 +682,7 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
* such as stat(2) */
inode->i_ino = hash;
- /* We can't support UPDATE_ATIME(), since the server will reset it */
+ /* We can't support update_atime(), since the server will reset it */
inode->i_flags |= S_NOATIME;
inode->i_mode = fattr->mode;
/* Why so? Because we want revalidate for devices/FIFOs, and
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 0334d92e5305..05541f7f9ef4 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1124,7 +1124,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
if (!inode->i_op || !inode->i_op->readlink)
goto out;
- UPDATE_ATIME(inode);
+ update_atime(inode);
/* N.B. Why does this call need a get_fs()??
* Remove the set_fs and watch the fireworks:-) --okir
*/
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index cb4f82cfb522..fc1c2dbff040 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -1736,7 +1736,7 @@ err_out:
* @vi: inode to mark dirty
*
* This is called from fs/inode.c::__mark_inode_dirty(), when the inode itself
- * is being marked dirty. An example is when UPDATE_ATIME() is invoked.
+ * is being marked dirty. An example is when update_atime() is invoked.
*
* We mark the inode dirty by setting both the page in which the mft record
* resides and the buffer heads in that page which correspond to the mft record
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 0c2ef6854f47..514a0f2f803a 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -96,19 +96,6 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) =
char *disk_name(struct gendisk *hd, int part, char *buf)
{
-#ifdef CONFIG_DEVFS_FS
- if (hd->devfs_name[0] != '\0') {
- if (part)
- snprintf(buf, BDEVNAME_SIZE, "%s/part%d",
- hd->devfs_name, part);
- else if (hd->minors != 1)
- snprintf(buf, BDEVNAME_SIZE, "%s/disc", hd->devfs_name);
- else
- snprintf(buf, BDEVNAME_SIZE, "%s", hd->devfs_name);
- return buf;
- }
-#endif
-
if (!part)
snprintf(buf, BDEVNAME_SIZE, "%s", hd->disk_name);
else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1]))
@@ -443,53 +430,3 @@ void del_gendisk(struct gendisk *disk)
}
kobject_del(&disk->kobj);
}
-
-struct dev_name {
- struct list_head list;
- dev_t dev;
- char namebuf[BDEVNAME_SIZE];
- char *name;
-};
-
-static LIST_HEAD(device_names);
-
-char *partition_name(dev_t dev)
-{
- struct gendisk *hd;
- static char nomem [] = "<nomem>";
- char b[BDEVNAME_SIZE];
- struct dev_name *dname;
- struct list_head *tmp;
- int part;
-
- list_for_each(tmp, &device_names) {
- dname = list_entry(tmp, struct dev_name, list);
- if (dname->dev == dev)
- return dname->name;
- }
-
- dname = kmalloc(sizeof(*dname), GFP_KERNEL);
-
- if (!dname)
- return nomem;
- /*
- * ok, add this new device name to the list
- */
- hd = get_gendisk(dev, &part);
- dname->name = NULL;
- if (hd) {
- dname->name = disk_name(hd, part, dname->namebuf);
- module_put(hd->fops->owner);
- put_disk(hd);
- }
- if (!dname->name) {
- sprintf(dname->namebuf, "[dev %s]", __bdevname(dev, b));
- dname->name = dname->namebuf;
- }
-
- dname->dev = dev;
- list_add(&dname->list, &device_names);
-
- return dname->name;
-}
-
diff --git a/fs/pipe.c b/fs/pipe.c
index 3d7e2cc23c91..39f8a0ce3877 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -121,7 +121,7 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
}
if (ret > 0)
- UPDATE_ATIME(inode);
+ update_atime(inode);
return ret;
}
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index 1486349050c9..77da4bd212f3 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -76,7 +76,7 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
brelse(bh);
}
- UPDATE_ATIME(inode);
+ update_atime(inode);
out:
unlock_kernel();
diff --git a/fs/read_write.c b/fs/read_write.c
index ae48047d849c..8fc33ddb597f 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -115,9 +115,10 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
{
off_t retval;
struct file * file;
+ int fput_needed;
retval = -EBADF;
- file = fget(fd);
+ file = fget_light(fd, &fput_needed);
if (!file)
goto bad;
@@ -128,7 +129,7 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
if (res != (loff_t)retval)
retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */
}
- fput(file);
+ fput_light(file, fput_needed);
bad:
return retval;
}
@@ -141,9 +142,10 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
int retval;
struct file * file;
loff_t offset;
+ int fput_needed;
retval = -EBADF;
- file = fget(fd);
+ file = fget_light(fd, &fput_needed);
if (!file)
goto bad;
@@ -161,7 +163,7 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
retval = 0;
}
out_putf:
- fput(file);
+ fput_light(file, fput_needed);
bad:
return retval;
}
@@ -251,11 +253,12 @@ asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)
{
struct file *file;
ssize_t ret = -EBADF;
+ int fput_needed;
- file = fget(fd);
+ file = fget_light(fd, &fput_needed);
if (file) {
ret = vfs_read(file, buf, count, &file->f_pos);
- fput(file);
+ fput_light(file, fput_needed);
}
return ret;
@@ -265,11 +268,12 @@ asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t co
{
struct file *file;
ssize_t ret = -EBADF;
+ int fput_needed;
- file = fget(fd);
+ file = fget_light(fd, &fput_needed);
if (file) {
ret = vfs_write(file, buf, count, &file->f_pos);
- fput(file);
+ fput_light(file, fput_needed);
}
return ret;
@@ -280,14 +284,15 @@ asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf,
{
struct file *file;
ssize_t ret = -EBADF;
+ int fput_needed;
if (pos < 0)
return -EINVAL;
- file = fget(fd);
+ file = fget_light(fd, &fput_needed);
if (file) {
ret = vfs_read(file, buf, count, &pos);
- fput(file);
+ fput_light(file, fput_needed);
}
return ret;
@@ -298,14 +303,15 @@ asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf,
{
struct file *file;
ssize_t ret = -EBADF;
+ int fput_needed;
if (pos < 0)
return -EINVAL;
- file = fget(fd);
+ file = fget_light(fd, &fput_needed);
if (file) {
ret = vfs_write(file, buf, count, &pos);
- fput(file);
+ fput_light(file, fput_needed);
}
return ret;
@@ -479,11 +485,12 @@ sys_readv(unsigned long fd, const struct iovec __user *vec, unsigned long vlen)
{
struct file *file;
ssize_t ret = -EBADF;
+ int fput_needed;
- file = fget(fd);
+ file = fget_light(fd, &fput_needed);
if (file) {
ret = vfs_readv(file, vec, vlen, &file->f_pos);
- fput(file);
+ fput_light(file, fput_needed);
}
return ret;
@@ -494,11 +501,12 @@ sys_writev(unsigned long fd, const struct iovec __user *vec, unsigned long vlen)
{
struct file *file;
ssize_t ret = -EBADF;
+ int fput_needed;
- file = fget(fd);
+ file = fget_light(fd, &fput_needed);
if (file) {
ret = vfs_writev(file, vec, vlen, &file->f_pos);
- fput(file);
+ fput_light(file, fput_needed);
}
return ret;
@@ -511,12 +519,13 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
struct inode * in_inode, * out_inode;
loff_t pos;
ssize_t retval;
+ int fput_needed_in, fput_needed_out;
/*
* Get input file, and verify that it is ok..
*/
retval = -EBADF;
- in_file = fget(in_fd);
+ in_file = fget_light(in_fd, &fput_needed_in);
if (!in_file)
goto out;
if (!(in_file->f_mode & FMODE_READ))
@@ -539,7 +548,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
* Get output file, and verify that it is ok..
*/
retval = -EBADF;
- out_file = fget(out_fd);
+ out_file = fget_light(out_fd, &fput_needed_out);
if (!out_file)
goto fput_in;
if (!(out_file->f_mode & FMODE_WRITE))
@@ -579,9 +588,9 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
retval = -EOVERFLOW;
fput_out:
- fput(out_file);
+ fput_light(out_file, fput_needed_out);
fput_in:
- fput(in_file);
+ fput_light(in_file, fput_needed_in);
out:
return retval;
}
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index a83102b50546..a779d856d6bc 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -185,7 +185,7 @@ static int reiserfs_readdir (struct file * filp, void * dirent, filldir_t filldi
filp->f_pos = next_pos;
pathrelse (&path_to_entry);
reiserfs_check_path(&path_to_entry) ;
- UPDATE_ATIME(inode) ;
+ update_atime(inode) ;
out:
reiserfs_write_unlock(inode->i_sb);
return ret;
diff --git a/fs/select.c b/fs/select.c
index 631d41bea36e..079155c57a14 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -176,7 +176,7 @@ int do_select(int n, fd_set_bits *fds, long *timeout)
{
struct poll_wqueues table;
poll_table *wait;
- int retval, i, off;
+ int retval, i;
long __timeout = *timeout;
spin_lock(&current->files->file_lock);
@@ -193,38 +193,58 @@ int do_select(int n, fd_set_bits *fds, long *timeout)
wait = NULL;
retval = 0;
for (;;) {
+ unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
+
set_current_state(TASK_INTERRUPTIBLE);
- for (i = 0 ; i < n; i++) {
- unsigned long bit = BIT(i);
- unsigned long mask;
- struct file *file;
- off = i / __NFDBITS;
- if (!(bit & BITS(fds, off)))
+ inp = fds->in; outp = fds->out; exp = fds->ex;
+ rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex;
+
+ for (i = 0; i < n; ++rinp, ++routp, ++rexp) {
+ unsigned long in, out, ex, all_bits, bit = 1, mask, j;
+ unsigned long res_in = 0, res_out = 0, res_ex = 0;
+ struct file_operations *f_op = NULL;
+ struct file *file = NULL;
+
+ in = *inp++; out = *outp++; ex = *exp++;
+ all_bits = in | out | ex;
+ if (all_bits == 0) {
+ i += __NFDBITS;
continue;
- file = fget(i);
- mask = POLLNVAL;
- if (file) {
- mask = DEFAULT_POLLMASK;
- if (file->f_op && file->f_op->poll)
- mask = file->f_op->poll(file, wait);
- fput(file);
- }
- if ((mask & POLLIN_SET) && ISSET(bit, __IN(fds,off))) {
- SET(bit, __RES_IN(fds,off));
- retval++;
- wait = NULL;
}
- if ((mask & POLLOUT_SET) && ISSET(bit, __OUT(fds,off))) {
- SET(bit, __RES_OUT(fds,off));
- retval++;
- wait = NULL;
- }
- if ((mask & POLLEX_SET) && ISSET(bit, __EX(fds,off))) {
- SET(bit, __RES_EX(fds,off));
- retval++;
- wait = NULL;
+
+ for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) {
+ if (i >= n)
+ break;
+ if (!(bit & all_bits))
+ continue;
+ file = fget(i);
+ if (file) {
+ f_op = file->f_op;
+ mask = DEFAULT_POLLMASK;
+ if (f_op && f_op->poll)
+ mask = (*f_op->poll)(file, retval ? NULL : wait);
+ fput(file);
+ if ((mask & POLLIN_SET) && (in & bit)) {
+ res_in |= bit;
+ retval++;
+ }
+ if ((mask & POLLOUT_SET) && (out & bit)) {
+ res_out |= bit;
+ retval++;
+ }
+ if ((mask & POLLEX_SET) && (ex & bit)) {
+ res_ex |= bit;
+ retval++;
+ }
+ }
}
+ if (res_in)
+ *rinp = res_in;
+ if (res_out)
+ *routp = res_out;
+ if (res_ex)
+ *rexp = res_ex;
}
wait = NULL;
if (retval || !__timeout || signal_pending(current))
diff --git a/fs/stat.c b/fs/stat.c
index 66ed3db3061f..7c412de971c3 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -244,7 +244,7 @@ asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bu
if (inode->i_op && inode->i_op->readlink) {
error = security_inode_readlink(nd.dentry);
if (!error) {
- UPDATE_ATIME(inode);
+ update_atime(inode);
error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
}
}
diff --git a/fs/super.c b/fs/super.c
index b2a02451eda5..58f90ef3a2b9 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -31,6 +31,7 @@
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/vfs.h>
+#include <linux/writeback.h> /* for the emergency remount stuff */
#include <asm/uaccess.h>
@@ -431,6 +432,18 @@ out:
return err;
}
+static void mark_files_ro(struct super_block *sb)
+{
+ struct file *f;
+
+ file_list_lock();
+ list_for_each_entry(f, &sb->s_files, f_list) {
+ if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f))
+ f->f_mode &= ~FMODE_WRITE;
+ }
+ file_list_unlock();
+}
+
/**
* do_remount_sb - asks filesystem to change mount options.
* @sb: superblock in question
@@ -439,21 +452,25 @@ out:
*
* Alters the mount options of a mounted file system.
*/
-int do_remount_sb(struct super_block *sb, int flags, void *data)
+int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
{
int retval;
if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev))
return -EACCES;
- /*flags |= MS_RDONLY;*/
if (flags & MS_RDONLY)
acct_auto_close(sb);
shrink_dcache_sb(sb);
fsync_super(sb);
+
/* If we are remounting RDONLY, make sure there are no rw files open */
- if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
- if (!fs_may_remount_ro(sb))
+ if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) {
+ if (force)
+ mark_files_ro(sb);
+ else if (!fs_may_remount_ro(sb))
return -EBUSY;
+ }
+
if (sb->s_op->remount_fs) {
lock_super(sb);
retval = sb->s_op->remount_fs(sb, &flags, data);
@@ -465,6 +482,28 @@ int do_remount_sb(struct super_block *sb, int flags, void *data)
return 0;
}
+static void do_emergency_remount(unsigned long foo)
+{
+ struct super_block *sb;
+
+ spin_lock(&sb_lock);
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ down_read(&sb->s_umount);
+ if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY))
+ do_remount_sb(sb, MS_RDONLY, NULL, 1);
+ drop_super(sb);
+ spin_lock(&sb_lock);
+ }
+ spin_unlock(&sb_lock);
+}
+
+void emergency_remount(void)
+{
+ pdflush_operation(do_emergency_remount, 0);
+}
+
/*
* Unnamed block devices are dummy devices used by virtual
* filesystems which don't use real block-devices. -- jrs
@@ -618,7 +657,7 @@ struct super_block *get_sb_single(struct file_system_type *fs_type,
}
s->s_flags |= MS_ACTIVE;
}
- do_remount_sb(s, flags, data);
+ do_remount_sb(s, flags, data, 0);
return s;
}
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 417e20a5d1ec..7d6f0e6199d0 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -116,7 +116,7 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
done:
filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
- UPDATE_ATIME(inode);
+ update_atime(inode);
unlock_kernel();
return 0;
}
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index 748d63e1a2a9..b1aae2f47919 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -98,7 +98,7 @@ int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
result = do_udf_readdir(dir, filp, filldir, dirent);
- UPDATE_ATIME(dir);
+ update_atime(dir);
unlock_kernel();
return result;
}
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 55e81f6b5b83..463c4bca0b62 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -166,7 +166,7 @@ revalidate:
offset = 0;
brelse (bh);
}
- UPDATE_ATIME(inode);
+ update_atime(inode);
unlock_kernel();
return 0;
}
diff --git a/fs/xattr.c b/fs/xattr.c
index 9463c877bcb2..2a2b6d53af1e 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -79,15 +79,16 @@ setxattr(struct dentry *d, char *name, void *value, size_t size, int flags)
error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
+ down(&d->d_inode->i_sem);
error = security_inode_setxattr(d, kname, kvalue, size, flags);
if (error)
goto out;
- down(&d->d_inode->i_sem);
error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
+ if (!error)
+ security_inode_post_setxattr(d, kname, kvalue, size, flags);
+out:
up(&d->d_inode->i_sem);
}
-
-out:
xattr_free(kvalue, size);
return error;
}
diff --git a/include/asm-i386/apicdef.h b/include/asm-i386/apicdef.h
index 485c1d8a8db5..c689554ad5b9 100644
--- a/include/asm-i386/apicdef.h
+++ b/include/asm-i386/apicdef.h
@@ -11,13 +11,6 @@
#define APIC_DEFAULT_PHYS_BASE 0xfee00000
#define APIC_ID 0x20
-#ifdef CONFIG_X86_SUMMIT
- #define APIC_ID_MASK (0xFF<<24)
- #define GET_APIC_ID(x) (((x)>>24)&0xFF)
-#else
- #define APIC_ID_MASK (0x0F<<24)
- #define GET_APIC_ID(x) (((x)>>24)&0x0F)
-#endif
#define APIC_LVR 0x30
#define APIC_LVR_MASK 0xFF00FF
#define GET_APIC_VERSION(x) ((x)&0xFF)
diff --git a/include/asm-i386/edd.h b/include/asm-i386/edd.h
index 061373b28782..66f7246dd13c 100644
--- a/include/asm-i386/edd.h
+++ b/include/asm-i386/edd.h
@@ -141,7 +141,7 @@ struct edd_device_params {
u32 array_number;
u32 reserved1;
u64 reserved2;
- } __attribute((packed)) raid;
+ } __attribute__ ((packed)) raid;
struct {
u8 device;
u8 reserved1;
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 40373cd7a163..6570d0d65e02 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -60,7 +60,7 @@ enum fixed_addresses {
#ifdef CONFIG_X86_F00F_BUG
FIX_F00F_IDT, /* Virtual mapping for IDT */
#endif
-#ifdef CONFIG_X86_SUMMIT
+#ifdef CONFIG_X86_CYCLONE_TIMER
FIX_CYCLONE_TIMER, /*cyclone timer register*/
#endif
#ifdef CONFIG_HIGHMEM
diff --git a/include/asm-i386/genapic.h b/include/asm-i386/genapic.h
new file mode 100644
index 000000000000..d6d94d5436b0
--- /dev/null
+++ b/include/asm-i386/genapic.h
@@ -0,0 +1,106 @@
+#ifndef _ASM_GENAPIC_H
+#define _ASM_GENAPIC_H 1
+
+/*
+ * Generic APIC driver interface.
+ *
+ * An straight forward mapping of the APIC related parts of the
+ * x86 subarchitecture interface to a dynamic object.
+ *
+ * This is used by the "generic" x86 subarchitecture.
+ *
+ * Copyright 2003 Andi Kleen, SuSE Labs.
+ */
+
+struct mpc_config_translation;
+struct mpc_config_bus;
+struct mp_config_table;
+struct mpc_config_processor;
+
+struct genapic {
+ char *name;
+ int (*probe)(void);
+
+ int (*apic_id_registered)(void);
+ unsigned long (*target_cpus)(void);
+ int int_delivery_mode;
+ int int_dest_mode;
+ int apic_broadcast_id;
+ int esr_disable;
+ unsigned long (*check_apicid_used)(unsigned long bitmap, int apicid);
+ unsigned long (*check_apicid_present)(int apicid);
+ int no_balance_irq;
+ void (*init_apic_ldr)(void);
+ unsigned long (*ioapic_phys_id_map)(unsigned long map);
+
+ void (*clustered_apic_check)(void);
+ int (*multi_timer_check)(int apic, int irq);
+ int (*apicid_to_node)(int logical_apicid);
+ int (*cpu_to_logical_apicid)(int cpu);
+ int (*cpu_present_to_apicid)(int mps_cpu);
+ unsigned long (*apicid_to_cpu_present)(int phys_apicid);
+ int (*mpc_apic_id)(struct mpc_config_processor *m,
+ struct mpc_config_translation *t);
+ void (*setup_portio_remap)(void);
+ int (*check_phys_apicid_present)(int boot_cpu_physical_apicid);
+
+ /* mpparse */
+ void (*mpc_oem_bus_info)(struct mpc_config_bus *, char *,
+ struct mpc_config_translation *);
+ void (*mpc_oem_pci_bus)(struct mpc_config_bus *,
+ struct mpc_config_translation *);
+
+ /* When one of the next two hooks returns 1 the genapic
+ is switched to this. Essentially they are additional probe
+ functions. */
+ int (*mps_oem_check)(struct mp_config_table *mpc, char *oem,
+ char *productid);
+ int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
+
+ unsigned (*get_apic_id)(unsigned long x);
+ unsigned long apic_id_mask;
+
+ /* ipi */
+ void (*send_IPI_mask)(int mask, int vector);
+ void (*send_IPI_allbutself)(int vector);
+ void (*send_IPI_all)(int vector);
+};
+
+#define APICFUNC(x) .x = x
+
+#define APIC_INIT(aname, aprobe) { \
+ .name = aname, \
+ .probe = aprobe, \
+ .int_delivery_mode = INT_DELIVERY_MODE, \
+ .int_dest_mode = INT_DEST_MODE, \
+ .apic_broadcast_id = APIC_BROADCAST_ID, \
+ .no_balance_irq = NO_BALANCE_IRQ, \
+ APICFUNC(apic_id_registered), \
+ APICFUNC(target_cpus), \
+ APICFUNC(check_apicid_used), \
+ APICFUNC(check_apicid_present), \
+ APICFUNC(init_apic_ldr), \
+ APICFUNC(ioapic_phys_id_map), \
+ APICFUNC(clustered_apic_check), \
+ APICFUNC(multi_timer_check), \
+ APICFUNC(apicid_to_node), \
+ APICFUNC(cpu_to_logical_apicid), \
+ APICFUNC(cpu_present_to_apicid), \
+ APICFUNC(apicid_to_cpu_present), \
+ APICFUNC(mpc_apic_id), \
+ APICFUNC(setup_portio_remap), \
+ APICFUNC(check_phys_apicid_present), \
+ APICFUNC(mpc_oem_bus_info), \
+ APICFUNC(mpc_oem_pci_bus), \
+ APICFUNC(mps_oem_check), \
+ APICFUNC(get_apic_id), \
+ .apic_id_mask = APIC_ID_MASK, \
+ APICFUNC(acpi_madt_oem_check), \
+ APICFUNC(send_IPI_mask), \
+ APICFUNC(send_IPI_allbutself), \
+ APICFUNC(send_IPI_all), \
+ }
+
+extern struct genapic *genapic;
+
+#endif
diff --git a/include/asm-i386/kmap_types.h b/include/asm-i386/kmap_types.h
index dda910c4f1ba..a117c0ade4d0 100644
--- a/include/asm-i386/kmap_types.h
+++ b/include/asm-i386/kmap_types.h
@@ -3,7 +3,7 @@
#include <linux/config.h>
-#if CONFIG_DEBUG_HIGHMEM
+#ifdef CONFIG_DEBUG_HIGHMEM
# define D(n) __KM_FENCE_##n ,
#else
# define D(n)
diff --git a/include/asm-i386/mach-bigsmp/mach_apic.h b/include/asm-i386/mach-bigsmp/mach_apic.h
index b6d7c5e946a3..93972fcd768f 100644
--- a/include/asm-i386/mach-bigsmp/mach_apic.h
+++ b/include/asm-i386/mach-bigsmp/mach_apic.h
@@ -15,18 +15,28 @@
static inline int apic_id_registered(void)
{
- return (1);
+ return (1);
}
#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
-#define TARGET_CPUS ((cpu_online_map < 0xf)?cpu_online_map:0xf)
+static inline unsigned long target_cpus(void)
+{
+ return ((cpu_online_map < 0xf)?cpu_online_map:0xf);
+}
+#define TARGET_CPUS (target_cpus())
#define INT_DELIVERY_MODE dest_LowestPrio
#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */
#define APIC_BROADCAST_ID (0x0f)
-#define check_apicid_used(bitmap, apicid) (0)
-#define check_apicid_present(bit) (phys_cpu_present_map & (1 << bit))
+static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid)
+{
+ return 0;
+}
+static inline unsigned long check_apicid_present(int bit)
+{
+ return (phys_cpu_present_map & (1 << bit));
+}
static inline unsigned long calculate_ldr(unsigned long old)
{
@@ -115,4 +125,13 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
return (1);
}
+#define APIC_ID_MASK (0x0F<<24)
+
+static inline unsigned get_apic_id(unsigned long x)
+{
+ return (((x)>>24)&0x0F);
+}
+
+#define GET_APIC_ID(x) get_apic_id(x)
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-bigsmp/mach_ipi.h b/include/asm-i386/mach-bigsmp/mach_ipi.h
index e0866134e624..87bd9fc4add8 100644
--- a/include/asm-i386/mach-bigsmp/mach_ipi.h
+++ b/include/asm-i386/mach-bigsmp/mach_ipi.h
@@ -1,7 +1,7 @@
#ifndef __ASM_MACH_IPI_H
#define __ASM_MACH_IPI_H
-static inline void send_IPI_mask_sequence(int mask, int vector);
+inline void send_IPI_mask_sequence(int mask, int vector);
static inline void send_IPI_mask(int mask, int vector)
{
diff --git a/include/asm-i386/mach-default/mach_apic.h b/include/asm-i386/mach-default/mach_apic.h
index 8a1311d6df7b..e865f01f5167 100644
--- a/include/asm-i386/mach-default/mach_apic.h
+++ b/include/asm-i386/mach-default/mach_apic.h
@@ -3,11 +3,15 @@
#define APIC_DFR_VALUE (APIC_DFR_FLAT)
+static inline unsigned long target_cpus(void)
+{
#ifdef CONFIG_SMP
- #define TARGET_CPUS (cpu_online_map)
+ return cpu_online_map;
#else
- #define TARGET_CPUS 0x01
+ return 1;
#endif
+}
+#define TARGET_CPUS (target_cpus())
#define NO_BALANCE_IRQ (0)
#define esr_disable (0)
@@ -16,13 +20,15 @@
#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */
#define APIC_BROADCAST_ID 0x0F
-#define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid))
-#define check_apicid_present(bit) (phys_cpu_present_map & (1 << bit))
-static inline int apic_id_registered(void)
+static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid)
+{
+ return (bitmap & (1UL << apicid));
+}
+
+static inline unsigned long check_apicid_present(int bit)
{
- return (test_bit(GET_APIC_ID(apic_read(APIC_ID)),
- &phys_cpu_present_map));
+ return (phys_cpu_present_map & (1UL << bit));
}
/*
@@ -42,7 +48,7 @@ static inline void init_apic_ldr(void)
apic_write_around(APIC_LDR, val);
}
-static inline ulong ioapic_phys_id_map(ulong phys_map)
+static inline unsigned long ioapic_phys_id_map(unsigned long phys_map)
{
return phys_map;
}
@@ -99,4 +105,19 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
return test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map);
}
+#define APIC_ID_MASK (0xF<<24)
+
+static inline unsigned get_apic_id(unsigned long x)
+{
+ return (((x)>>24)&0xF);
+}
+
+#define GET_APIC_ID(x) get_apic_id(x)
+
+static inline int apic_id_registered(void)
+{
+ return (test_bit(GET_APIC_ID(apic_read(APIC_ID)),
+ &phys_cpu_present_map));
+}
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-default/mach_ipi.h b/include/asm-i386/mach-default/mach_ipi.h
index 481692a7b885..43d78f307db5 100644
--- a/include/asm-i386/mach-default/mach_ipi.h
+++ b/include/asm-i386/mach-default/mach_ipi.h
@@ -1,8 +1,8 @@
#ifndef __ASM_MACH_IPI_H
#define __ASM_MACH_IPI_H
-static inline void send_IPI_mask_bitmask(int mask, int vector);
-static inline void __send_IPI_shortcut(unsigned int shortcut, int vector);
+inline void send_IPI_mask_bitmask(int mask, int vector);
+inline void __send_IPI_shortcut(unsigned int shortcut, int vector);
static inline void send_IPI_mask(int mask, int vector)
{
diff --git a/include/asm-i386/mach-default/mach_mpparse.h b/include/asm-i386/mach-default/mach_mpparse.h
index 3b399a3bcd11..1d3832482580 100644
--- a/include/asm-i386/mach-default/mach_mpparse.h
+++ b/include/asm-i386/mach-default/mach_mpparse.h
@@ -12,14 +12,16 @@ static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
{
}
-static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
+static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
char *productid)
{
+ return 0;
}
/* Hook from generic ACPI tables.c */
-static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
+ return 0;
}
diff --git a/include/asm-i386/mach-generic/mach_apic.h b/include/asm-i386/mach-generic/mach_apic.h
new file mode 100644
index 000000000000..9adab2c3f2fc
--- /dev/null
+++ b/include/asm-i386/mach-generic/mach_apic.h
@@ -0,0 +1,30 @@
+#ifndef __ASM_MACH_APIC_H
+#define __ASM_MACH_APIC_H
+
+#include <asm/genapic.h>
+
+#define esr_disable (genapic->esr_disable)
+#define NO_BALANCE_IRQ (genapic->no_balance_irq)
+#define APIC_BROADCAST_ID (genapic->apic_broadcast_id)
+#define INT_DELIVERY_MODE (genapic->int_delivery_mode)
+#define INT_DEST_MODE (genapic->int_dest_mode)
+#define TARGET_CPUS (genapic->target_cpus())
+#define apic_id_registered (genapic->apic_id_registered)
+#define apic_id_registered (genapic->apic_id_registered)
+#define init_apic_ldr (genapic->init_apic_ldr)
+#define ioapic_phys_id_map (genapic->ioapic_phys_id_map)
+#define clustered_apic_check (genapic->clustered_apic_check)
+#define multi_timer_check (genapic->multi_timer_check)
+#define apicid_to_node (genapic->apicid_to_node)
+#define cpu_to_logical_apicid (genapic->cpu_to_logical_apicid)
+#define cpu_present_to_apicid (genapic->cpu_present_to_apicid)
+#define apicid_to_cpu_present (genapic->apicid_to_cpu_present)
+#define mpc_apic_id (genapic->mpc_apic_id)
+#define setup_portio_remap (genapic->setup_portio_remap)
+#define check_apicid_present (genapic->check_apicid_present)
+#define check_phys_apicid_present (genapic->check_phys_apicid_present)
+#define check_apicid_used (genapic->check_apicid_used)
+#define GET_APIC_ID (genapic->get_apic_id)
+#define APIC_ID_MASK (genapic->apic_id_mask)
+
+#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-generic/mach_ipi.h b/include/asm-i386/mach-generic/mach_ipi.h
new file mode 100644
index 000000000000..441b0fe3ed1d
--- /dev/null
+++ b/include/asm-i386/mach-generic/mach_ipi.h
@@ -0,0 +1,10 @@
+#ifndef _MACH_IPI_H
+#define _MACH_IPI_H 1
+
+#include <asm/genapic.h>
+
+#define send_IPI_mask (genapic->send_IPI_mask)
+#define send_IPI_allbutself (genapic->send_IPI_allbutself)
+#define send_IPI_all (genapic->send_IPI_all)
+
+#endif
diff --git a/include/asm-i386/mach-generic/mach_mpparse.h b/include/asm-i386/mach-generic/mach_mpparse.h
new file mode 100644
index 000000000000..dbd9fce54f4d
--- /dev/null
+++ b/include/asm-i386/mach-generic/mach_mpparse.h
@@ -0,0 +1,12 @@
+#ifndef _MACH_MPPARSE_H
+#define _MACH_MPPARSE_H 1
+
+#include <asm/genapic.h>
+
+#define mpc_oem_bus_info (genapic->mpc_oem_bus_info)
+#define mpc_oem_pci_bus (genapic->mpc_oem_pci_bus)
+
+int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid);
+int acpi_madt_oem_check(char *oem_id, char *oem_table_id);
+
+#endif
diff --git a/include/asm-i386/mach-numaq/mach_apic.h b/include/asm-i386/mach-numaq/mach_apic.h
index 1b322209306e..54a7c97fe8d1 100644
--- a/include/asm-i386/mach-numaq/mach_apic.h
+++ b/include/asm-i386/mach-numaq/mach_apic.h
@@ -1,6 +1,9 @@
#ifndef __ASM_MACH_APIC_H
#define __ASM_MACH_APIC_H
+#include <asm/io.h>
+#include <linux/mmzone.h>
+
#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
#define TARGET_CPUS (0xf)
@@ -103,4 +106,13 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
return (1);
}
+#define APIC_ID_MASK (0xF<<24)
+
+static inline unsigned get_apic_id(unsigned long x)
+{
+ return (((x)>>24)&0x0F);
+}
+
+#define GET_APIC_ID(x) get_apic_id(x)
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index 988e40647378..ae58d629c9ba 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -1,7 +1,13 @@
#ifndef __ASM_MACH_APIC_H
#define __ASM_MACH_APIC_H
+#include <linux/config.h>
+
+#ifdef CONFIG_X86_GENERICARCH
+#define x86_summit 1 /* must be an constant expressiona for generic arch */
+#else
extern int x86_summit;
+#endif
#define esr_disable (x86_summit ? 1 : 0)
#define NO_BALANCE_IRQ (0)
@@ -9,20 +15,34 @@ extern int x86_summit;
#define XAPIC_DEST_CPUS_MASK 0x0Fu
#define XAPIC_DEST_CLUSTER_MASK 0xF0u
-#define xapic_phys_to_log_apicid(phys_apic) ( (1ul << ((phys_apic) & 0x3)) |\
- ((phys_apic) & XAPIC_DEST_CLUSTER_MASK) )
+static inline unsigned long xapic_phys_to_log_apicid(int phys_apic)
+{
+ return ( (1ul << ((phys_apic) & 0x3)) |
+ ((phys_apic) & XAPIC_DEST_CLUSTER_MASK) );
+}
#define APIC_DFR_VALUE (x86_summit ? APIC_DFR_CLUSTER : APIC_DFR_FLAT)
-#define TARGET_CPUS (x86_summit ? XAPIC_DEST_CPUS_MASK : cpu_online_map)
+
+static inline unsigned long target_cpus(void)
+{
+ return (x86_summit ? XAPIC_DEST_CPUS_MASK : cpu_online_map);
+}
+#define TARGET_CPUS (target_cpus())
#define INT_DELIVERY_MODE (x86_summit ? dest_Fixed : dest_LowestPrio)
#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */
-#define APIC_BROADCAST_ID (x86_summit ? 0xFF : 0x0F)
-#define check_apicid_used(bitmap, apicid) (x86_summit ? 0 : (bitmap & (1 << apicid)))
+#define APIC_BROADCAST_ID (0x0F)
+static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid)
+{
+ return (x86_summit ? 0 : (bitmap & (1 << apicid)));
+}
/* we don't use the phys_cpu_present_map to indicate apicid presence */
-#define check_apicid_present(bit) (x86_summit ? 1 : (phys_cpu_present_map & (1 << bit)))
+static inline unsigned long check_apicid_present(int bit)
+{
+ return (x86_summit ? 1 : (phys_cpu_present_map & (1 << bit)));
+}
extern u8 bios_cpu_apicid[];
@@ -113,4 +133,13 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
return test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map);
}
+#define APIC_ID_MASK (0xFF<<24)
+
+static inline unsigned get_apic_id(unsigned long x)
+{
+ return (((x)>>24)&0xFF);
+}
+
+#define GET_APIC_ID(x) get_apic_id(x)
+
#endif /* __ASM_MACH_APIC_H */
diff --git a/include/asm-i386/mach-summit/mach_ipi.h b/include/asm-i386/mach-summit/mach_ipi.h
index e0866134e624..87bd9fc4add8 100644
--- a/include/asm-i386/mach-summit/mach_ipi.h
+++ b/include/asm-i386/mach-summit/mach_ipi.h
@@ -1,7 +1,7 @@
#ifndef __ASM_MACH_IPI_H
#define __ASM_MACH_IPI_H
-static inline void send_IPI_mask_sequence(int mask, int vector);
+inline void send_IPI_mask_sequence(int mask, int vector);
static inline void send_IPI_mask(int mask, int vector)
{
diff --git a/include/asm-i386/mach-summit/mach_mpparse.h b/include/asm-i386/mach-summit/mach_mpparse.h
index d34f3df6468d..3a6d53c10afc 100644
--- a/include/asm-i386/mach-summit/mach_mpparse.h
+++ b/include/asm-i386/mach-summit/mach_mpparse.h
@@ -14,26 +14,34 @@ static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
{
}
-static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
+static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
char *productid)
{
if (!strncmp(oem, "IBM ENSW", 8) &&
(!strncmp(productid, "VIGIL SMP", 9)
|| !strncmp(productid, "EXA", 3)
|| !strncmp(productid, "RUTHLESS SMP", 12))){
+#ifndef CONFIG_X86_GENERICARCH
x86_summit = 1;
+#endif
use_cyclone = 1; /*enable cyclone-timer*/
+ return 1;
}
+ return 0;
}
/* Hook from generic ACPI tables.c */
-static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
if (!strncmp(oem_id, "IBM", 3) &&
(!strncmp(oem_table_id, "SERVIGIL", 8)
|| !strncmp(oem_table_id, "EXA", 3))){
+#ifndef CONFIG_X86_GENERICARCH
x86_summit = 1;
+#endif
use_cyclone = 1; /*enable cyclone-timer*/
+ return 1;
}
+ return 0;
}
#endif /* __ASM_MACH_MPPARSE_H */
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
index 257bfa929428..b6138f07c309 100644
--- a/include/asm-i386/mmzone.h
+++ b/include/asm-i386/mmzone.h
@@ -120,7 +120,7 @@ static inline struct pglist_data *pfn_to_pgdat(unsigned long pfn)
#ifdef CONFIG_X86_NUMAQ
#include <asm/numaq.h>
-#elif CONFIG_X86_SUMMIT
+#elif CONFIG_NUMA /* summit or generic arch */
#include <asm/srat.h>
#elif CONFIG_X86_PC
#define get_memcfg_numa get_memcfg_numa_flat
diff --git a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h
index bdb208ca961c..ea4023a0bc61 100644
--- a/include/asm-i386/mpspec.h
+++ b/include/asm-i386/mpspec.h
@@ -16,7 +16,7 @@
/*
* a maximum of 16 APICs with the current APIC ID architecture.
*/
-#if defined(CONFIG_X86_NUMAQ) || defined (CONFIG_X86_SUMMIT)
+#if defined(CONFIG_X86_NUMAQ) || defined (CONFIG_X86_SUMMIT) || defined(CONFIG_X86_GENERICARCH)
#define MAX_APICS 256
#else
#define MAX_APICS 16
diff --git a/include/asm-i386/numnodes.h b/include/asm-i386/numnodes.h
index 8d14f4ad7ef3..1b7443f748a5 100644
--- a/include/asm-i386/numnodes.h
+++ b/include/asm-i386/numnodes.h
@@ -5,7 +5,7 @@
#ifdef CONFIG_X86_NUMAQ
#include <asm/numaq.h>
-#elif CONFIG_X86_SUMMIT
+#elif CONFIG_NUMA
#include <asm/srat.h>
#else
#define MAX_NUMNODES 1
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 6bbb21e6e205..9e9e07de8f9e 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -536,7 +536,7 @@ static inline void rep_nop(void)
#define ASM_NOP6 K8_NOP6
#define ASM_NOP7 K8_NOP7
#define ASM_NOP8 K8_NOP8
-#elif CONFIG_MK7
+#elif defined(CONFIG_MK7)
#define ASM_NOP1 K7_NOP1
#define ASM_NOP2 K7_NOP2
#define ASM_NOP3 K7_NOP3
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index 57521b90c548..67a5353fdb59 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -87,11 +87,17 @@ extern inline int any_online_cpu(unsigned int mask)
return -1;
}
#ifdef CONFIG_X86_LOCAL_APIC
-static __inline int hard_smp_processor_id(void)
+
+#ifdef APIC_DEFINITION
+extern int hard_smp_processor_id(void);
+#else
+#include <mach_apic.h>
+static inline int hard_smp_processor_id(void)
{
/* we don't want to mark this access volatile - bad code generation */
return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
}
+#endif
static __inline int logical_smp_processor_id(void)
{
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index 379d278686f0..15aa2e7ef765 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -62,8 +62,6 @@ int __verify_write(const void *, unsigned long);
:"1" (addr),"g" ((int)(size)),"g" (current_thread_info()->addr_limit.seg)); \
flag; })
-#ifdef CONFIG_X86_WP_WORKS_OK
-
/**
* access_ok: - Checks if a user space pointer is valid
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that
@@ -85,14 +83,6 @@ int __verify_write(const void *, unsigned long);
*/
#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
-#else
-
-#define access_ok(type,addr,size) ( (__range_ok(addr,size) == 0) && \
- ((type) == VERIFY_READ || boot_cpu_data.wp_works_ok || \
- __verify_write((void *)(addr),(size))))
-
-#endif
-
/**
* verify_area: - Obsolete, use access_ok()
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
@@ -191,14 +181,8 @@ extern void __get_user_4(void);
__ret_gu; \
})
-extern void __put_user_1(void);
-extern void __put_user_2(void);
-extern void __put_user_4(void);
-extern void __put_user_8(void);
-
extern void __put_user_bad(void);
-
/**
* put_user: - Write a simple value into user space.
* @x: Value to copy to user space.
@@ -299,6 +283,8 @@ extern void __put_user_bad(void);
: "=r"(err) \
: "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))
+#ifdef CONFIG_X86_WP_WORKS_OK
+
#define __put_user_size(x,ptr,size,retval,errret) \
do { \
retval = 0; \
@@ -311,6 +297,18 @@ do { \
} \
} while (0)
+#else
+
+#define __put_user_size(x,ptr,size,retval,errret) \
+do { \
+ __typeof__(*(ptr)) __pus_tmp = x; \
+ retval = 0; \
+ \
+ if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp, size) != 0)) \
+ retval = errret; \
+} while (0)
+
+#endif
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index e0f4fd1f8ce0..84d35a14522e 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -399,6 +399,8 @@ static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
+#ifndef cond_syscall
#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#endif
#endif /* _ASM_I386_UNISTD_H_ */
diff --git a/include/linux/atm_he.h b/include/linux/atm_he.h
new file mode 100644
index 000000000000..2a7713b597cf
--- /dev/null
+++ b/include/linux/atm_he.h
@@ -0,0 +1,20 @@
+/* atm_he.h */
+
+#ifndef LINUX_ATM_HE_H
+#define LINUX_ATM_HE_H
+
+#include <linux/atmioc.h>
+
+#define HE_GET_REG _IOW('a', ATMIOC_SARPRV, struct atmif_sioc)
+
+#define HE_REGTYPE_PCI 1
+#define HE_REGTYPE_RCM 2
+#define HE_REGTYPE_TCM 3
+#define HE_REGTYPE_MBOX 4
+
+struct he_ioctl_reg {
+ unsigned addr, val;
+ char type;
+};
+
+#endif /* LINUX_ATM_HE_H */
diff --git a/include/linux/atmbr2684.h b/include/linux/atmbr2684.h
new file mode 100644
index 000000000000..7981b733f1ef
--- /dev/null
+++ b/include/linux/atmbr2684.h
@@ -0,0 +1,101 @@
+#ifndef _LINUX_ATMBR2684_H
+#define _LINUX_ATMBR2684_H
+
+#include <linux/atm.h>
+#include <linux/if.h> /* For IFNAMSIZ */
+
+/*
+ * Type of media we're bridging (ethernet, token ring, etc) Currently only
+ * ethernet is supported
+ */
+#define BR2684_MEDIA_ETHERNET (0) /* 802.3 */
+#define BR2684_MEDIA_802_4 (1) /* 802.4 */
+#define BR2684_MEDIA_TR (2) /* 802.5 - token ring */
+#define BR2684_MEDIA_FDDI (3)
+#define BR2684_MEDIA_802_6 (4) /* 802.6 */
+
+/*
+ * Is there FCS inbound on this VC? This currently isn't supported.
+ */
+#define BR2684_FCSIN_NO (0)
+#define BR2684_FCSIN_IGNORE (1)
+#define BR2684_FCSIN_VERIFY (2)
+
+/*
+ * Is there FCS outbound on this VC? This currently isn't supported.
+ */
+#define BR2684_FCSOUT_NO (0)
+#define BR2684_FCSOUT_SENDZERO (1)
+#define BR2684_FCSOUT_GENERATE (2)
+
+/*
+ * Does this VC include LLC encapsulation?
+ */
+#define BR2684_ENCAPS_VC (0) /* VC-mux */
+#define BR2684_ENCAPS_LLC (1)
+#define BR2684_ENCAPS_AUTODETECT (2) /* Unsuported */
+
+/*
+ * This is for the ATM_NEWBACKENDIF call - these are like socket families:
+ * the first element of the structure is the backend number and the rest
+ * is per-backend specific
+ */
+struct atm_newif_br2684 {
+ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
+ int media; /* BR2684_MEDIA_* */
+ char ifname[IFNAMSIZ];
+ int mtu;
+};
+
+/*
+ * This structure is used to specify a br2684 interface - either by a
+ * positive integer (returned by ATM_NEWBACKENDIF) or the interfaces name
+ */
+#define BR2684_FIND_BYNOTHING (0)
+#define BR2684_FIND_BYNUM (1)
+#define BR2684_FIND_BYIFNAME (2)
+struct br2684_if_spec {
+ int method; /* BR2684_FIND_* */
+ union {
+ char ifname[IFNAMSIZ];
+ int devnum;
+ } spec;
+};
+
+/*
+ * This is for the ATM_SETBACKEND call - these are like socket families:
+ * the first element of the structure is the backend number and the rest
+ * is per-backend specific
+ */
+struct atm_backend_br2684 {
+ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
+ struct br2684_if_spec ifspec;
+ int fcs_in; /* BR2684_FCSIN_* */
+ int fcs_out; /* BR2684_FCSOUT_* */
+ int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */
+ int encaps; /* BR2684_ENCAPS_* */
+ int has_vpiid; /* 1: use vpn_id - Unsupported */
+ __u8 vpn_id[7];
+ int send_padding; /* unsupported */
+ int min_size; /* we will pad smaller packets than this */
+};
+
+/*
+ * The BR2684_SETFILT ioctl is an experimental mechanism for folks
+ * terminating a large number of IP-only vcc's. When netfilter allows
+ * efficient per-if in/out filters, this support will be removed
+ */
+struct br2684_filter {
+ __u32 prefix; /* network byte order */
+ __u32 netmask; /* 0 = disable filter */
+};
+
+struct br2684_filter_set {
+ struct br2684_if_spec ifspec;
+ struct br2684_filter filter;
+};
+
+#define BR2684_SETFILT _IOW( 'a', ATMIOC_BACKEND + 0, \
+ struct br2684_filter_set)
+
+#endif /* _LINUX_ATMBR2684_H */
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index d6dce90537bf..d564eb34e7ce 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -96,6 +96,8 @@ struct atm_dev_stats {
/* enable or disable single-copy */
#define ATM_SETBACKEND _IOW('a',ATMIOC_SPECIAL+2,atm_backend_t)
/* set backend handler */
+#define ATM_NEWBACKENDIF _IOW('a',ATMIOC_SPECIAL+3,atm_backend_t)
+ /* use backend to make new if */
/*
* These are backend handkers that can be set via the ATM_SETBACKEND call
@@ -104,7 +106,7 @@ struct atm_dev_stats {
*/
#define ATM_BACKEND_RAW 0
#define ATM_BACKEND_PPP 1 /* PPPoATM - RFC2364 */
-#define ATM_BACKEND_BR_2684 2 /* Bridged RFC1483/2684 */
+#define ATM_BACKEND_BR2684 2 /* Bridged RFC1483/2684 */
/* for ATM_GETTYPE */
#define ATM_ITFTYP_LEN 8 /* maximum length of interface type name */
@@ -304,9 +306,6 @@ struct atm_vcc {
struct sockaddr_atmsvc local;
struct sockaddr_atmsvc remote;
void (*callback)(struct atm_vcc *vcc);
- struct sk_buff_head listenq;
- int backlog_quota; /* number of connection requests we */
- /* can still accept */
int reply; /* also used by ATMTCP */
/* Multipoint part ------------------------------------------------- */
struct atm_vcc *session; /* session VCC descriptor */
diff --git a/include/linux/blkpg.h b/include/linux/blkpg.h
index 571618972e30..15b61f7bf0b5 100644
--- a/include/linux/blkpg.h
+++ b/include/linux/blkpg.h
@@ -54,10 +54,4 @@ struct blkpg_partition {
char volname[BLKPG_VOLNAMELTH]; /* volume label */
};
-#ifdef __KERNEL__
-
-extern char * partition_name(dev_t dev);
-
-#endif /* __KERNEL__ */
-
#endif /* _LINUX_BLKPG_H */
diff --git a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h
index 8ee76799308c..34ebe93c6194 100644
--- a/include/linux/devfs_fs_kernel.h
+++ b/include/linux/devfs_fs_kernel.h
@@ -27,6 +27,8 @@ extern devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
umode_t mode, void *ops, void *info);
extern int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...)
__attribute__((format (printf, 3, 4)));
+extern int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
+ __attribute__((format (printf, 3, 4)));
extern int devfs_mk_symlink(const char *name, const char *link);
extern int devfs_mk_dir(const char *fmt, ...)
__attribute__((format (printf, 1, 2)));
@@ -51,6 +53,10 @@ static inline int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...)
{
return 0;
}
+static inline int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
+{
+ return 0;
+}
static inline int devfs_mk_symlink (const char *name, const char *link)
{
return 0;
diff --git a/include/linux/file.h b/include/linux/file.h
index 6fbd27f755d5..a488f738f9f0 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -35,7 +35,15 @@ struct files_struct {
extern void FASTCALL(__fput(struct file *));
extern void FASTCALL(fput(struct file *));
+
+static inline void fput_light(struct file *file, int fput_needed)
+{
+ if (unlikely(fput_needed))
+ fput(file);
+}
+
extern struct file * FASTCALL(fget(unsigned int fd));
+extern struct file * FASTCALL(fget_light(unsigned int fd, int *fput_needed));
extern void FASTCALL(set_close_on_exec(unsigned int fd, int flag));
extern void put_filp(struct file *);
extern int get_unused_fd(void);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b9b2cf5b69e8..8d618555e772 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -206,8 +206,8 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
#include <asm/semaphore.h>
#include <asm/byteorder.h>
+/* Used to be a macro which just called the function, now just a function */
extern void update_atime (struct inode *);
-#define UPDATE_ATIME(inode) update_atime (inode)
extern void inode_init(unsigned long);
extern void mnt_init(unsigned long);
@@ -1113,6 +1113,10 @@ extern int filemap_flush(struct address_space *);
extern int filemap_fdatawait(struct address_space *);
extern void sync_supers(void);
extern void sync_filesystems(int wait);
+extern void emergency_sync(void);
+extern void emergency_remount(void);
+extern int do_remount_sb(struct super_block *sb, int flags,
+ void *data, int force);
extern sector_t bmap(struct inode *, sector_t);
extern int setattr_mask(unsigned int);
extern int notify_change(struct dentry *, struct iattr *);
diff --git a/include/linux/input.h b/include/linux/input.h
index 9df2e226a1f2..ae71e3ea453e 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -894,9 +894,6 @@ void input_close_device(struct input_handle *);
int input_accept_process(struct input_handle *handle, struct file *file);
int input_flush_device(struct input_handle* handle, struct file* file);
-/* will go away once devfs_register gets sanitized */
-void input_register_minor(char *name, int minor, int minor_base);
-
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
#define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c))
diff --git a/include/linux/major.h b/include/linux/major.h
index 200e3653181b..0e2d112c89e5 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -27,6 +27,7 @@
#define MUX_MAJOR 11 /* PA-RISC only */
#define QIC02_TAPE_MAJOR 12
#define XT_DISK_MAJOR 13
+#define INPUT_MAJOR 13
#define SOUND_MAJOR 14
#define CDU31A_CDROM_MAJOR 15
#define JOYSTICK_MAJOR 15
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index 02ff30e5a187..98f0d1e27c4c 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -61,9 +61,20 @@
#define MD_MINOR_VERSION 90
#define MD_PATCHLEVEL_VERSION 0
-extern inline char * bdev_partition_name (struct block_device *bdev)
+/*
+ * XXX(hch): This function is broken. Someone who understands the md
+ * code needs to go through all callers, check whether bdev could
+ * be NULL and replace it with direct calls to bdevmame.
+ *
+ * This would also fix the returns buffer on stack issue nicely :)
+ */
+static inline const char *bdev_partition_name (struct block_device *bdev)
{
- return partition_name(bdev ? bdev->bd_dev : 0);
+ char b[BDEVNAME_SIZE];
+
+ if (!bdev)
+ return __bdevname(0, b);
+ return bdevname(bdev, b);
}
extern int register_md_personality (int p_num, mdk_personality_t *p);
extern int unregister_md_personality (int p_num);
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 64b443d136a9..36573ba3c202 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -78,7 +78,7 @@ struct rtattr
/******************************************************************************
- * Definitions used in routing table administation.
+ * Definitions used in routing table administration.
****/
struct rtmsg
@@ -129,14 +129,14 @@ enum
#define RTPROT_STATIC 4 /* Route installed by administrator */
/* Values of protocol >= RTPROT_STATIC are not interpreted by kernel;
- they just passed from user and back as is.
+ they are just passed from user and back as is.
It will be used by hypothetical multiple routing daemons.
Note that protocol values should be standardized in order to
avoid conflicts.
*/
#define RTPROT_GATED 8 /* Apparently, GateD */
-#define RTPROT_RA 9 /* RDISC/ND router advertisments */
+#define RTPROT_RA 9 /* RDISC/ND router advertisements */
#define RTPROT_MRT 10 /* Merit MRT */
#define RTPROT_ZEBRA 11 /* Zebra */
#define RTPROT_BIRD 12 /* BIRD */
@@ -210,8 +210,8 @@ enum rtattr_type_t
/* RTM_MULTIPATH --- array of struct rtnexthop.
*
- * "struct rtnexthop" describres all necessary nexthop information,
- * i.e. parameters of path to a destination via this nextop.
+ * "struct rtnexthop" describes all necessary nexthop information,
+ * i.e. parameters of path to a destination via this nexthop.
*
* At the moment it is impossible to set different prefsrc, mtu, window
* and rtt for different paths from multipath.
@@ -485,7 +485,7 @@ enum
Comments:
- Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
- - If neiher of these three flags are set;
+ - If neither of these three flags are set;
the interface is NBMA.
- IFF_MULTICAST does not mean anything special:
diff --git a/include/linux/sched.h b/include/linux/sched.h
index ca3c22f974c2..01ea66352c74 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -294,6 +294,7 @@ extern struct user_struct root_user;
typedef struct prio_array prio_array_t;
struct backing_dev_info;
+struct reclaim_state;
/* POSIX.1b interval timer structure. */
struct k_itimer {
@@ -433,6 +434,10 @@ struct task_struct {
/* journalling filesystem info */
void *journal_info;
+
+/* VM state */
+ struct reclaim_state *reclaim_state;
+
struct dentry *proc_dentry;
struct backing_dev_info *backing_dev_info;
diff --git a/include/linux/security.h b/include/linux/security.h
index 6a98cb692bf8..4d052ad9759d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -361,6 +361,9 @@ struct swap_info_struct;
* Check permission before setting the extended attributes
* @value identified by @name for @dentry.
* Return 0 if permission is granted.
+ * @inode_post_setxattr:
+ * Update inode security field after successful setxattr operation.
+ * @value identified by @name for @dentry.
* @inode_getxattr:
* Check permission before obtaining the extended attributes
* identified by @name for @dentry.
@@ -1036,6 +1039,8 @@ struct security_operations {
void (*inode_delete) (struct inode *inode);
int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
size_t size, int flags);
+ void (*inode_post_setxattr) (struct dentry *dentry, char *name, void *value,
+ size_t size, int flags);
int (*inode_getxattr) (struct dentry *dentry, char *name);
int (*inode_listxattr) (struct dentry *dentry);
int (*inode_removexattr) (struct dentry *dentry, char *name);
@@ -1464,6 +1469,12 @@ static inline int security_inode_setxattr (struct dentry *dentry, char *name,
return security_ops->inode_setxattr (dentry, name, value, size, flags);
}
+static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
+ void *value, size_t size, int flags)
+{
+ security_ops->inode_post_setxattr (dentry, name, value, size, flags);
+}
+
static inline int security_inode_getxattr (struct dentry *dentry, char *name)
{
return security_ops->inode_getxattr (dentry, name);
@@ -2063,6 +2074,10 @@ static inline int security_inode_setxattr (struct dentry *dentry, char *name,
return 0;
}
+static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
+ void *value, size_t size, int flags)
+{ }
+
static inline int security_inode_getxattr (struct dentry *dentry, char *name)
{
return 0;
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 49374df2d450..b2b6f0498e2a 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -49,7 +49,6 @@ typedef struct kmem_cache_s kmem_cache_t;
/* prototypes */
extern void kmem_cache_init(void);
-extern void kmem_cache_sizes_init(void);
extern kmem_cache_t *kmem_find_general_cachep(size_t, int gfpflags);
extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 6553637b70ee..09f7d54052eb 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -176,8 +176,10 @@ static inline int svc_take_page(struct svc_rqst *rqstp)
{
if (rqstp->rq_arghi <= rqstp->rq_argused)
return -ENOMEM;
- rqstp->rq_respages[rqstp->rq_resused++] =
- rqstp->rq_argpages[--rqstp->rq_arghi];
+ rqstp->rq_arghi--;
+ rqstp->rq_respages[rqstp->rq_resused] =
+ rqstp->rq_argpages[rqstp->rq_arghi];
+ rqstp->rq_resused++;
return 0;
}
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 50f651d752cc..147e5bf40cbf 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -66,6 +66,14 @@ typedef struct {
unsigned long val;
} swp_entry_t;
+/*
+ * current->reclaim_state points to one of these when a task is running
+ * memory reclaim
+ */
+struct reclaim_state {
+ unsigned long reclaimed_slab;
+};
+
#ifdef __KERNEL__
struct address_space;
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
index ee340cd26eaf..1acdb0bd4689 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -92,21 +92,3 @@ static inline int __reterr(void)
#define unregister_sysrq_key(ig,nore) __reterr()
#endif
-
-
-/* Deferred actions */
-
-extern int emergency_sync_scheduled;
-
-#define EMERG_SYNC 1
-#define EMERG_REMOUNT 2
-
-void do_emergency_sync(void);
-
-#ifdef CONFIG_MAGIC_SYSRQ
-#define CHECK_EMERGENCY_SYNC \
- if (emergency_sync_scheduled) \
- do_emergency_sync();
-#else
-#define CHECK_EMERGENCY_SYNC
-#endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index d7948e7ad0eb..fa5529ad5c6e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -243,6 +243,7 @@ struct tty_flip_buffer {
#define L_PENDIN(tty) _L_FLAG((tty),PENDIN)
#define L_IEXTEN(tty) _L_FLAG((tty),IEXTEN)
+struct device;
/*
* Where all of the state associated with a tty is kept while the tty
* is open. Since the termios state should be kept even if the tty
@@ -380,7 +381,7 @@ extern void start_tty(struct tty_struct * tty);
extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
extern int tty_register_driver(struct tty_driver *driver);
extern int tty_unregister_driver(struct tty_driver *driver);
-extern void tty_register_device(struct tty_driver *driver, unsigned index);
+extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev);
extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
int buflen);
diff --git a/init/main.c b/init/main.c
index edb701549dff..74e083a3fcf5 100644
--- a/init/main.c
+++ b/init/main.c
@@ -417,7 +417,6 @@ asmlinkage void __init start_kernel(void)
*/
console_init();
profile_init();
- kmem_cache_init();
local_irq_enable();
calibrate_delay();
#ifdef CONFIG_BLK_DEV_INITRD
@@ -430,7 +429,7 @@ asmlinkage void __init start_kernel(void)
#endif
page_address_init();
mem_init();
- kmem_cache_sizes_init();
+ kmem_cache_init();
pidmap_init();
pgtable_cache_init();
pte_chain_init();
diff --git a/ipc/shm.c b/ipc/shm.c
index 19c06135b184..29684c056882 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -149,7 +149,7 @@ static void shm_close (struct vm_area_struct *shmd)
static int shm_mmap(struct file * file, struct vm_area_struct * vma)
{
- UPDATE_ATIME(file->f_dentry->d_inode);
+ update_atime(file->f_dentry->d_inode);
vma->vm_ops = &shm_vm_ops;
shm_inc(file->f_dentry->d_inode->i_ino);
return 0;
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index 6e9dcc34fccf..fcd14e808045 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -580,8 +580,6 @@ EXPORT_SYMBOL(fs_overflowgid);
EXPORT_SYMBOL(fasync_helper);
EXPORT_SYMBOL(kill_fasync);
-EXPORT_SYMBOL(partition_name);
-
/* binfmt_aout */
EXPORT_SYMBOL(get_write_access);
diff --git a/kernel/panic.c b/kernel/panic.c
index 66a22b5d9c77..80c582d13d4f 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -96,9 +96,8 @@ NORET_TYPE void panic(const char * fmt, ...)
disabled_wait(caller);
#endif
local_irq_enable();
- for(;;) {
- CHECK_EMERGENCY_SYNC
- }
+ for (;;)
+ ;
}
/**
diff --git a/lib/inflate.c b/lib/inflate.c
index a0f9f1b7e507..98ff41833ea3 100644
--- a/lib/inflate.c
+++ b/lib/inflate.c
@@ -271,14 +271,15 @@ STATIC const int dbits = 6; /* bits in base distance lookup table */
STATIC unsigned hufts; /* track memory usage */
-STATIC int huft_build(b, n, s, d, e, t, m)
-unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
-unsigned n; /* number of codes (assumed <= N_MAX) */
-unsigned s; /* number of simple-valued codes (0..s-1) */
-const ush *d; /* list of base values for non-simple codes */
-const ush *e; /* list of extra bits for non-simple codes */
-struct huft **t; /* result: starting table */
-int *m; /* maximum lookup bits, returns actual */
+STATIC int huft_build(
+ unsigned *b, /* code lengths in bits (all assumed <= BMAX) */
+ unsigned n, /* number of codes (assumed <= N_MAX) */
+ unsigned s, /* number of simple-valued codes (0..s-1) */
+ const ush *d, /* list of base values for non-simple codes */
+ const ush *e, /* list of extra bits for non-simple codes */
+ struct huft **t, /* result: starting table */
+ int *m /* maximum lookup bits, returns actual */
+ )
/* Given a list of code lengths and a maximum table size, make a set of
tables to decode that set of codes. Return zero on success, one if
the given code set is incomplete (the tables are still built in this
@@ -489,8 +490,9 @@ DEBG("huft7 ");
-STATIC int huft_free(t)
-struct huft *t; /* table to free */
+STATIC int huft_free(
+ struct huft *t /* table to free */
+ )
/* Free the malloc'ed tables built by huft_build(), which makes a linked
list of the tables it made, with the links in a dummy first entry of
each table. */
@@ -510,9 +512,12 @@ struct huft *t; /* table to free */
}
-STATIC int inflate_codes(tl, td, bl, bd)
-struct huft *tl, *td; /* literal/length and distance decoder tables */
-int bl, bd; /* number of bits decoded by tl[] and td[] */
+STATIC int inflate_codes(
+ struct huft *tl, /* literal/length decoder tables */
+ struct huft *td, /* distance decoder tables */
+ int bl, /* number of bits decoded by tl[] */
+ int bd /* number of bits decoded by td[] */
+ )
/* inflate (decompress) the codes in a deflated (compressed) block.
Return an error code or zero if it all goes ok. */
{
@@ -619,7 +624,7 @@ int bl, bd; /* number of bits decoded by tl[] and td[] */
-STATIC int inflate_stored()
+STATIC int inflate_stored(void)
/* "decompress" an inflated type 0 (stored) block. */
{
unsigned n; /* number of bytes in block */
@@ -675,7 +680,7 @@ DEBG("<stor");
-STATIC int inflate_fixed()
+STATIC int inflate_fixed(void)
/* decompress an inflated type 1 (fixed Huffman codes) block. We should
either replace this with a custom decoder, or at least precompute the
Huffman tables. */
@@ -729,7 +734,7 @@ DEBG("<fix");
-STATIC int inflate_dynamic()
+STATIC int inflate_dynamic(void)
/* decompress an inflated type 2 (dynamic Huffman codes) block. */
{
int i; /* temporary variables */
@@ -907,8 +912,9 @@ DEBG("dyn7 ");
-STATIC int inflate_block(e)
-int *e; /* last block flag */
+STATIC int inflate_block(
+ int *e /* last block flag */
+ )
/* decompress an inflated block */
{
unsigned t; /* block type */
@@ -954,7 +960,7 @@ int *e; /* last block flag */
-STATIC int inflate()
+STATIC int inflate(void)
/* decompress an inflated entry */
{
int e; /* last block flag */
diff --git a/mm/filemap.c b/mm/filemap.c
index 40008f8f3626..6135e0b145d3 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -681,7 +681,7 @@ no_cached_page:
*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
if (cached_page)
page_cache_release(cached_page);
- UPDATE_ATIME(inode);
+ update_atime(inode);
}
int file_read_actor(read_descriptor_t *desc, struct page *page,
@@ -774,7 +774,7 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
if (retval > 0)
*ppos = pos + retval;
}
- UPDATE_ATIME(filp->f_dentry->d_inode);
+ update_atime(filp->f_dentry->d_inode);
goto out;
}
@@ -1259,7 +1259,7 @@ int generic_file_mmap(struct file * file, struct vm_area_struct * vma)
if (!mapping->a_ops->readpage)
return -ENOEXEC;
- UPDATE_ATIME(inode);
+ update_atime(inode);
vma->vm_ops = &generic_file_vm_ops;
return 0;
}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index c33c6a207426..589c8be70ff1 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -20,7 +20,6 @@
#include <linux/pagemap.h>
#include <linux/writeback.h>
#include <linux/init.h>
-#include <linux/sysrq.h>
#include <linux/backing-dev.h>
#include <linux/blkdev.h>
#include <linux/mpage.h>
@@ -237,7 +236,6 @@ static void background_writeout(unsigned long _min_pages)
.nonblocking = 1,
};
- CHECK_EMERGENCY_SYNC
for ( ; ; ) {
struct page_state ps;
long background_thresh;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index bff7db2296ae..d428bf605104 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -537,6 +537,7 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
int i;
int cold;
int do_retry;
+ struct reclaim_state reclaim_state;
if (wait)
might_sleep();
@@ -608,7 +609,12 @@ rebalance:
goto nopage;
current->flags |= PF_MEMALLOC;
+ reclaim_state.reclaimed_slab = 0;
+ current->reclaim_state = &reclaim_state;
+
try_to_free_pages(classzone, gfp_mask, order);
+
+ current->reclaim_state = NULL;
current->flags &= ~PF_MEMALLOC;
/* go through the zonelist yet one more time */
diff --git a/mm/shmem.c b/mm/shmem.c
index ea9ca8795beb..513ccb5761f3 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1013,7 +1013,7 @@ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
ops = &shmem_vm_ops;
if (!inode->i_sb || !S_ISREG(inode->i_mode))
return -EACCES;
- UPDATE_ATIME(inode);
+ update_atime(inode);
vma->vm_ops = ops;
return 0;
}
@@ -1307,7 +1307,7 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
}
*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
- UPDATE_ATIME(inode);
+ update_atime(inode);
}
static ssize_t shmem_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
diff --git a/mm/slab.c b/mm/slab.c
index 332837c15d62..bd15798dfeaf 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -76,6 +76,7 @@
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/mm.h>
+#include <linux/swap.h>
#include <linux/cache.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -567,11 +568,40 @@ static inline struct array_cache *ac_data(kmem_cache_t *cachep)
return cachep->array[smp_processor_id()];
}
-/* Initialisation - setup the `cache' cache. */
+/* Initialisation.
+ * Called after the gfp() functions have been enabled, and before smp_init().
+ */
void __init kmem_cache_init(void)
{
size_t left_over;
+ struct cache_sizes *sizes;
+ struct cache_names *names;
+ /*
+ * Fragmentation resistance on low memory - only use bigger
+ * page orders on machines with more than 32MB of memory.
+ */
+ if (num_physpages > (32 << 20) >> PAGE_SHIFT)
+ slab_break_gfp_order = BREAK_GFP_ORDER_HI;
+
+
+ /* Bootstrap is tricky, because several objects are allocated
+ * from caches that do not exist yet:
+ * 1) initialize the cache_cache cache: it contains the kmem_cache_t
+ * structures of all caches, except cache_cache itself: cache_cache
+ * is statically allocated.
+ * Initially an __init data area is used for the head array, it's
+ * replaced with a kmalloc allocated array at the end of the bootstrap.
+ * 2) Create the first kmalloc cache.
+ * The kmem_cache_t for the new cache is allocated normally. An __init
+ * data area is used for the head array.
+ * 3) Create the remaining kmalloc caches, with minimally sized head arrays.
+ * 4) Replace the __init data head arrays for cache_cache and the first
+ * kmalloc cache with kmalloc allocated arrays.
+ * 5) Resize the head arrays of the kmalloc caches to their final sizes.
+ */
+
+ /* 1) create the cache_cache */
init_MUTEX(&cache_chain_sem);
INIT_LIST_HEAD(&cache_chain);
list_add(&cache_cache.next, &cache_chain);
@@ -585,27 +615,10 @@ void __init kmem_cache_init(void)
cache_cache.colour = left_over/cache_cache.colour_off;
cache_cache.colour_next = 0;
- /* Register a cpu startup notifier callback
- * that initializes ac_data for all new cpus
- */
- register_cpu_notifier(&cpucache_notifier);
-}
-
-/* Initialisation - setup remaining internal and general caches.
- * Called after the gfp() functions have been enabled, and before smp_init().
- */
-void __init kmem_cache_sizes_init(void)
-{
- struct cache_sizes *sizes = malloc_sizes;
- struct cache_names *names = cache_names;
-
- /*
- * Fragmentation resistance on low memory - only use bigger
- * page orders on machines with more than 32MB of memory.
- */
- if (num_physpages > (32 << 20) >> PAGE_SHIFT)
- slab_break_gfp_order = BREAK_GFP_ORDER_HI;
+ /* 2+3) create the kmalloc caches */
+ sizes = malloc_sizes;
+ names = cache_names;
while (sizes->cs_size) {
/* For performance, all the general caches are L1 aligned.
@@ -634,10 +647,7 @@ void __init kmem_cache_sizes_init(void)
sizes++;
names++;
}
- /*
- * The generic caches are running - time to kick out the
- * bootstrap cpucaches.
- */
+ /* 4) Replace the bootstrap head arrays */
{
void * ptr;
@@ -656,29 +666,42 @@ void __init kmem_cache_sizes_init(void)
malloc_sizes[0].cs_cachep->array[smp_processor_id()] = ptr;
local_irq_enable();
}
+
+ /* 5) resize the head arrays to their final sizes */
+ {
+ kmem_cache_t *cachep;
+ down(&cache_chain_sem);
+ list_for_each_entry(cachep, &cache_chain, next)
+ enable_cpucache(cachep);
+ up(&cache_chain_sem);
+ }
+
+ /* Done! */
+ g_cpucache_up = FULL;
+
+ /* Register a cpu startup notifier callback
+ * that initializes ac_data for all new cpus
+ */
+ register_cpu_notifier(&cpucache_notifier);
+
+
+ /* The reap timers are started later, with a module init call:
+ * That part of the kernel is not yet operational.
+ */
}
int __init cpucache_init(void)
{
- kmem_cache_t *cachep;
int cpu;
- down(&cache_chain_sem);
- g_cpucache_up = FULL;
-
- list_for_each_entry(cachep, &cache_chain, next)
- enable_cpucache(cachep);
-
/*
* Register the timers that return unneeded
* pages to gfp.
*/
-
for (cpu = 0; cpu < NR_CPUS; cpu++) {
if (cpu_online(cpu))
start_cpu_timer(cpu);
}
- up(&cache_chain_sem);
return 0;
}
@@ -712,6 +735,7 @@ static inline void kmem_freepages (kmem_cache_t *cachep, void *addr)
{
unsigned long i = (1<<cachep->gfporder);
struct page *page = virt_to_page(addr);
+ const unsigned long nr_freed = i;
/* free_pages() does not clear the type bit - we do that.
* The pages have been unlinked from their cache-slab,
@@ -720,9 +744,11 @@ static inline void kmem_freepages (kmem_cache_t *cachep, void *addr)
*/
while (i--) {
ClearPageSlab(page);
- dec_page_state(nr_slab);
page++;
}
+ sub_page_state(nr_slab, nr_freed);
+ if (current->reclaim_state)
+ current->reclaim_state->reclaimed_slab += nr_freed;
free_pages((unsigned long)addr, cachep->gfporder);
}
@@ -914,12 +940,19 @@ kmem_cache_create (const char *name, size_t size, size_t offset,
}
#if FORCED_DEBUG
- if ((size < (PAGE_SIZE>>3)) && !(flags & SLAB_MUST_HWCACHE_ALIGN))
- /*
- * do not red zone large object, causes severe
- * fragmentation.
- */
+ /*
+ * Enable redzoning and last user accounting, except
+ * - for caches with forced alignment: redzoning would violate the
+ * alignment
+ * - for caches with large objects, if the increased size would
+ * increase the object size above the next power of two: caches
+ * with object sizes just above a power of two have a significant
+ * amount of internal fragmentation
+ */
+ if ((size < (PAGE_SIZE>>3) || fls(size-1) == fls(size-1+3*BYTES_PER_WORD))
+ && !(flags & SLAB_MUST_HWCACHE_ALIGN)) {
flags |= SLAB_RED_ZONE|SLAB_STORE_USER;
+ }
flags |= SLAB_POISON;
#endif
#endif
@@ -1756,10 +1789,12 @@ __free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
slabp = GET_PAGE_SLAB(virt_to_page(objp));
list_del(&slabp->list);
objnr = (objp - slabp->s_mem) / cachep->objsize;
+ check_slabp(cachep, slabp);
slab_bufctl(slabp)[objnr] = slabp->free;
slabp->free = objnr;
STATS_DEC_ACTIVE(cachep);
slabp->inuse--;
+ check_slabp(cachep, slabp);
/* fixup slab chains */
if (slabp->inuse == 0) {
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 48ffb627914d..55b2de7bca97 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -886,6 +886,10 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
* requirements, they are simply tossed out - we will never use those blocks
* for swapping.
*
+ * For S_ISREG swapfiles we hold i_sem across the life of the swapon. This
+ * prevents root from shooting her foot off by ftruncating an in-use swapfile,
+ * which will scribble on the fs.
+ *
* The amount of disk space which a single swap extent represents varies.
* Typically it is in the 1-4 megabyte range. So we can have hundreds of
* extents in the list. To avoid much list walking, we cache the previous
@@ -1095,6 +1099,8 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
bdev = swap_file->f_dentry->d_inode->i_bdev;
set_blocksize(bdev, p->old_block_size);
bd_release(bdev);
+ } else {
+ up(&swap_file->f_dentry->d_inode->i_mapping->host->i_sem);
}
filp_close(swap_file, NULL);
err = 0;
@@ -1228,6 +1234,8 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
int swapfilesize;
unsigned short *swap_map;
struct page *page = NULL;
+ struct inode *inode;
+ struct inode *downed_inode = NULL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -1274,39 +1282,42 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
}
p->swap_file = swap_file;
+ inode = swap_file->f_dentry->d_inode;
+ mapping = swap_file->f_dentry->d_inode->i_mapping;
+
+ error = -EBUSY;
+ for (i = 0; i < nr_swapfiles; i++) {
+ struct swap_info_struct *q = &swap_info[i];
+
+ if (i == type || !q->swap_file)
+ continue;
+ if (mapping == q->swap_file->f_dentry->d_inode->i_mapping)
+ goto bad_swap;
+ }
error = -EINVAL;
- if (S_ISBLK(swap_file->f_dentry->d_inode->i_mode)) {
- bdev = swap_file->f_dentry->d_inode->i_bdev;
+ if (S_ISBLK(inode->i_mode)) {
+ bdev = inode->i_bdev;
error = bd_claim(bdev, sys_swapon);
if (error < 0) {
bdev = NULL;
goto bad_swap;
}
p->old_block_size = block_size(bdev);
- error = set_blocksize(swap_file->f_dentry->d_inode->i_bdev,
- PAGE_SIZE);
+ error = set_blocksize(inode->i_bdev, PAGE_SIZE);
if (error < 0)
goto bad_swap;
p->bdev = bdev;
- } else if (S_ISREG(swap_file->f_dentry->d_inode->i_mode)) {
- p->bdev = swap_file->f_dentry->d_inode->i_sb->s_bdev;
+ } else if (S_ISREG(inode->i_mode)) {
+ p->bdev = inode->i_sb->s_bdev;
+ downed_inode = mapping->host;
+ down(&downed_inode->i_sem);
} else {
goto bad_swap;
}
- mapping = swap_file->f_dentry->d_inode->i_mapping;
swapfilesize = mapping->host->i_size >> PAGE_SHIFT;
- error = -EBUSY;
- for (i = 0 ; i < nr_swapfiles ; i++) {
- struct swap_info_struct *q = &swap_info[i];
- if (i == type || !q->swap_file)
- continue;
- if (mapping == q->swap_file->f_dentry->d_inode->i_mapping)
- goto bad_swap;
- }
-
/*
* Read the swap header.
*/
@@ -1452,6 +1463,8 @@ out:
}
if (name)
putname(name);
+ if (error && downed_inode)
+ up(&downed_inode->i_sem);
return error;
}
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index f6ce2378b721..962850e3f4be 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -97,8 +97,7 @@ static int map_area_pte(pte_t *pte, unsigned long address,
do {
struct page *page = **pages;
- if (!pte_none(*pte))
- printk(KERN_ERR "alloc_area_pte: page already exists\n");
+ WARN_ON(!pte_none(*pte));
if (!page)
return -ENOMEM;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 56b89071bfb9..c21d19b912ac 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -817,12 +817,14 @@ shrink_caches(struct zone *classzone, int priority, int *total_scanned,
* excessive rotation of the inactive list, which is _supposed_ to be an LRU,
* yes?
*/
-int try_to_free_pages(struct zone *classzone,
+int try_to_free_pages(struct zone *cz,
unsigned int gfp_mask, unsigned int order)
{
int priority;
+ int ret = 0;
const int nr_pages = SWAP_CLUSTER_MAX;
int nr_reclaimed = 0;
+ struct reclaim_state *reclaim_state = current->reclaim_state;
inc_page_state(allocstall);
@@ -831,11 +833,12 @@ int try_to_free_pages(struct zone *classzone,
struct page_state ps;
get_page_state(&ps);
- nr_reclaimed += shrink_caches(classzone, priority,
- &total_scanned, gfp_mask,
- nr_pages, &ps);
- if (nr_reclaimed >= nr_pages)
- return 1;
+ nr_reclaimed += shrink_caches(cz, priority, &total_scanned,
+ gfp_mask, nr_pages, &ps);
+ if (nr_reclaimed >= nr_pages) {
+ ret = 1;
+ goto out;
+ }
if (!(gfp_mask & __GFP_FS))
break; /* Let the caller handle it */
/*
@@ -847,12 +850,18 @@ int try_to_free_pages(struct zone *classzone,
/* Take a nap, wait for some writeback to complete */
blk_congestion_wait(WRITE, HZ/10);
- if (classzone - classzone->zone_pgdat->node_zones < ZONE_HIGHMEM)
+ if (cz - cz->zone_pgdat->node_zones < ZONE_HIGHMEM) {
shrink_slab(total_scanned, gfp_mask);
+ if (reclaim_state) {
+ nr_reclaimed += reclaim_state->reclaimed_slab;
+ reclaim_state->reclaimed_slab = 0;
+ }
+ }
}
if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY))
out_of_memory();
- return 0;
+out:
+ return ret;
}
/*
@@ -878,6 +887,7 @@ static int balance_pgdat(pg_data_t *pgdat, int nr_pages, struct page_state *ps)
int to_free = nr_pages;
int priority;
int i;
+ struct reclaim_state *reclaim_state = current->reclaim_state;
inc_page_state(pageoutrun);
@@ -908,8 +918,11 @@ static int balance_pgdat(pg_data_t *pgdat, int nr_pages, struct page_state *ps)
max_scan = SWAP_CLUSTER_MAX;
to_free -= shrink_zone(zone, max_scan, GFP_KERNEL,
to_reclaim, &nr_mapped, ps, priority);
- if (i < ZONE_HIGHMEM)
+ if (i < ZONE_HIGHMEM) {
+ reclaim_state->reclaimed_slab = 0;
shrink_slab(max_scan + nr_mapped, GFP_KERNEL);
+ to_free += reclaim_state->reclaimed_slab;
+ }
if (zone->all_unreclaimable)
continue;
if (zone->pages_scanned > zone->present_pages * 2)
@@ -940,10 +953,14 @@ int kswapd(void *p)
pg_data_t *pgdat = (pg_data_t*)p;
struct task_struct *tsk = current;
DEFINE_WAIT(wait);
+ struct reclaim_state reclaim_state = {
+ .reclaimed_slab = 0,
+ };
daemonize("kswapd%d", pgdat->node_id);
set_cpus_allowed(tsk, node_to_cpumask(pgdat->node_id));
-
+ current->reclaim_state = &reclaim_state;
+
/*
* Tell the memory management that we're a "memory allocator",
* and that if we need more memory we should get access to it
diff --git a/net/Kconfig b/net/Kconfig
index 46d78d92b4d6..be43497b173c 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -266,6 +266,23 @@ config ATM_MPOA
subnetwork boundaries. These shortcut connections bypass routers
enhancing overall network performance.
+config ATM_BR2684
+ tristate "RFC1483/2684 Bridged protocols"
+ depends on ATM && INET
+ help
+ ATM PVCs can carry ethernet PDUs according to rfc2684 (formerly 1483)
+ This device will act like an ethernet from the kernels point of view,
+ with the traffic being carried by ATM PVCs (currently 1 PVC/device).
+ This is sometimes used over DSL lines. If in doubt, say N.
+
+config ATM_BR2684_IPFILTER
+ bool "Per-VC IP filter kludge"
+ depends on ATM_BR2684
+ help
+ This is an experimental mechanism for users who need to terminating a
+ large number of IP-only vcc's. Do not enable this unless you are sure
+ you know what you are doing.
+
config VLAN_8021Q
tristate "802.1Q VLAN Support"
diff --git a/net/atm/Makefile b/net/atm/Makefile
index a3027195a738..84d28dfe5b0b 100644
--- a/net/atm/Makefile
+++ b/net/atm/Makefile
@@ -7,6 +7,7 @@ mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o
obj-$(CONFIG_ATM) := addr.o pvc.o signaling.o svc.o common.o atm_misc.o raw.o resources.o
obj-$(CONFIG_ATM_CLIP) += clip.o ipcommon.o
+obj-$(CONFIG_ATM_BR2684) += br2684.o ipcommon.o
obj-$(CONFIG_NET_SCH_ATM) += ipcommon.o
obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
new file mode 100644
index 000000000000..a2964ef87a36
--- /dev/null
+++ b/net/atm/br2684.c
@@ -0,0 +1,803 @@
+/*
+Experimental ethernet netdevice using ATM AAL5 as underlying carrier
+(RFC1483 obsoleted by RFC2684) for Linux 2.4
+Author: Marcell GAL, 2000, XDSL Ltd, Hungary
+*/
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/ip.h>
+#include <asm/uaccess.h>
+#include <net/arp.h>
+
+#include <linux/atmbr2684.h>
+
+#include "ipcommon.h"
+
+/*
+ * Define this to use a version of the code which interacts with the higher
+ * layers in a more intellegent way, by always reserving enough space for
+ * our header at the begining of the packet. However, there may still be
+ * some problems with programs like tcpdump. In 2.5 we'll sort out what
+ * we need to do to get this perfect. For now we just will copy the packet
+ * if we need space for the header
+ */
+/* #define FASTER_VERSION */
+
+#ifdef DEBUG
+#define DPRINTK(format, args...) printk(KERN_DEBUG "br2684: " format, ##args)
+#else
+#define DPRINTK(format, args...)
+#endif
+
+#ifdef SKB_DEBUG
+static void skb_debug(const struct sk_buff *skb)
+{
+#define NUM2PRINT 50
+ char buf[NUM2PRINT * 3 + 1]; /* 3 chars per byte */
+ int i = 0;
+ for (i = 0; i < skb->len && i < NUM2PRINT; i++) {
+ sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
+ }
+ printk(KERN_DEBUG "br2684: skb: %s\n", buf);
+}
+#else
+#define skb_debug(skb) do {} while (0)
+#endif
+
+static unsigned char llc_oui_pid_pad[] =
+ { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 };
+#define PADLEN (2)
+
+enum br2684_encaps {
+ e_vc = BR2684_ENCAPS_VC,
+ e_llc = BR2684_ENCAPS_LLC,
+};
+
+struct br2684_vcc {
+ struct atm_vcc *atmvcc;
+ struct br2684_dev *brdev;
+ /* keep old push,pop functions for chaining */
+ void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
+ /* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */
+ enum br2684_encaps encaps;
+ struct list_head brvccs;
+#ifdef CONFIG_ATM_BR2684_IPFILTER
+ struct br2684_filter filter;
+#endif /* CONFIG_ATM_BR2684_IPFILTER */
+#ifndef FASTER_VERSION
+ unsigned copies_needed, copies_failed;
+#endif /* FASTER_VERSION */
+};
+
+struct br2684_dev {
+ struct net_device net_dev;
+ struct list_head br2684_devs;
+ int number;
+ struct list_head brvccs; /* one device <=> one vcc (before xmas) */
+ struct net_device_stats stats;
+ int mac_was_set;
+};
+
+/*
+ * This lock should be held for writing any time the list of devices or
+ * their attached vcc's could be altered. It should be held for reading
+ * any time these are being queried. Note that we sometimes need to
+ * do read-locking under interrupt context, so write locking must block
+ * the current CPU's interrupts
+ */
+static rwlock_t devs_lock = RW_LOCK_UNLOCKED;
+
+static LIST_HEAD(br2684_devs);
+
+static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev)
+{
+ return (struct br2684_dev *) ((char *) (net_dev) -
+ (unsigned long) (&((struct br2684_dev *) 0)->net_dev));
+}
+
+static inline struct br2684_dev *list_entry_brdev(const struct list_head *le)
+{
+ return list_entry(le, struct br2684_dev, br2684_devs);
+}
+
+static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc)
+{
+ return (struct br2684_vcc *) (atmvcc->user_back);
+}
+
+static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le)
+{
+ return list_entry(le, struct br2684_vcc, brvccs);
+}
+
+/* Caller should hold read_lock(&devs_lock) */
+static struct br2684_dev *br2684_find_dev(const struct br2684_if_spec *s)
+{
+ struct list_head *lh;
+ struct br2684_dev *brdev;
+ switch (s->method) {
+ case BR2684_FIND_BYNUM:
+ list_for_each(lh, &br2684_devs) {
+ brdev = list_entry_brdev(lh);
+ if (brdev->number == s->spec.devnum)
+ return brdev;
+ }
+ break;
+ case BR2684_FIND_BYIFNAME:
+ list_for_each(lh, &br2684_devs) {
+ brdev = list_entry_brdev(lh);
+ if (!strncmp(brdev->net_dev.name, s->spec.ifname,
+ sizeof brdev->net_dev.name))
+ return brdev;
+ }
+ break;
+ }
+ return NULL;
+}
+
+/*
+ * Send a packet out a particular vcc. Not to useful right now, but paves
+ * the way for multiple vcc's per itf. Returns true if we can send,
+ * otherwise false
+ */
+static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
+ struct br2684_vcc *brvcc)
+{
+ struct atm_vcc *atmvcc;
+#ifdef FASTER_VERSION
+ if (brvcc->encaps == e_llc)
+ memcpy(skb_push(skb, 8), llc_oui_pid_pad, 8);
+ /* last 2 bytes of llc_oui_pid_pad are managed by header routines;
+ yes, you got it: 8 + 2 = sizeof(llc_oui_pid_pad)
+ */
+#else
+ int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2;
+ if (skb_headroom(skb) < minheadroom) {
+ struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
+ brvcc->copies_needed++;
+ dev_kfree_skb(skb);
+ if (skb2 == NULL) {
+ brvcc->copies_failed++;
+ return 0;
+ }
+ skb = skb2;
+ }
+ skb_push(skb, minheadroom);
+ if (brvcc->encaps == e_llc)
+ memcpy(skb->data, llc_oui_pid_pad, 10);
+ else
+ memset(skb->data, 0, 2);
+#endif /* FASTER_VERSION */
+ skb_debug(skb);
+
+ ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
+ DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
+ if (!atm_may_send(atmvcc, skb->truesize)) {
+ /* we free this here for now, because we cannot know in a higher
+ layer whether the skb point it supplied wasn't freed yet.
+ now, it always is.
+ */
+ dev_kfree_skb(skb);
+ return 0;
+ }
+ atomic_add(skb->truesize, &atmvcc->sk->wmem_alloc);
+ ATM_SKB(skb)->atm_options = atmvcc->atm_options;
+ brdev->stats.tx_packets++;
+ brdev->stats.tx_bytes += skb->len;
+ atmvcc->send(atmvcc, skb);
+ return 1;
+}
+
+static inline struct br2684_vcc *pick_outgoing_vcc(struct sk_buff *skb,
+ struct br2684_dev *brdev)
+{
+ return list_empty(&brdev->brvccs) ? NULL :
+ list_entry_brvcc(brdev->brvccs.next); /* 1 vcc/dev right now */
+}
+
+static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct br2684_dev *brdev = BRPRIV(dev);
+ struct br2684_vcc *brvcc;
+
+ DPRINTK("br2684_start_xmit, skb->dst=%p\n", skb->dst);
+ read_lock(&devs_lock);
+ brvcc = pick_outgoing_vcc(skb, brdev);
+ if (brvcc == NULL) {
+ DPRINTK("no vcc attached to dev %s\n", dev->name);
+ brdev->stats.tx_errors++;
+ brdev->stats.tx_carrier_errors++;
+ /* netif_stop_queue(dev); */
+ dev_kfree_skb(skb);
+ read_unlock(&devs_lock);
+ return -EUNATCH;
+ }
+ if (!br2684_xmit_vcc(skb, brdev, brvcc)) {
+ /*
+ * We should probably use netif_*_queue() here, but that
+ * involves added complication. We need to walk before
+ * we can run
+ */
+ /* don't free here! this pointer might be no longer valid!
+ dev_kfree_skb(skb);
+ */
+ brdev->stats.tx_errors++;
+ brdev->stats.tx_fifo_errors++;
+ }
+ read_unlock(&devs_lock);
+ return 0;
+}
+
+static struct net_device_stats *br2684_get_stats(struct net_device *dev)
+{
+ DPRINTK("br2684_get_stats\n");
+ return &BRPRIV(dev)->stats;
+}
+
+#ifdef FASTER_VERSION
+/*
+ * These mirror eth_header and eth_header_cache. They are not usually
+ * exported for use in modules, so we grab them from net_device
+ * after ether_setup() is done with it. Bit of a hack.
+ */
+static int (*my_eth_header)(struct sk_buff *, struct net_device *,
+ unsigned short, void *, void *, unsigned);
+static int (*my_eth_header_cache)(struct neighbour *, struct hh_cache *);
+
+static int
+br2684_header(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, void *daddr, void *saddr, unsigned len)
+{
+ u16 *pad_before_eth;
+ int t = my_eth_header(skb, dev, type, daddr, saddr, len);
+ if (t > 0) {
+ pad_before_eth = (u16 *) skb_push(skb, 2);
+ *pad_before_eth = 0;
+ return dev->hard_header_len; /* or return 16; ? */
+ } else
+ return t;
+}
+
+static int
+br2684_header_cache(struct neighbour *neigh, struct hh_cache *hh)
+{
+/* hh_data is 16 bytes long. if encaps is ether-llc we need 24, so
+xmit will add the additional header part in that case */
+ u16 *pad_before_eth = (u16 *)(hh->hh_data);
+ int t = my_eth_header_cache(neigh, hh);
+ DPRINTK("br2684_header_cache, neigh=%p, hh_cache=%p\n", neigh, hh);
+ if (t < 0)
+ return t;
+ else {
+ *pad_before_eth = 0;
+ hh->hh_len = PADLEN + ETH_HLEN;
+ }
+ return 0;
+}
+
+/*
+ * This is similar to eth_type_trans, which cannot be used because of
+ * our dev->hard_header_len
+ */
+static inline unsigned short br_type_trans(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct ethhdr *eth;
+ unsigned char *rawp;
+ eth = skb->mac.ethernet;
+
+ if (*eth->h_dest & 1) {
+ if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
+ skb->pkt_type = PACKET_BROADCAST;
+ else
+ skb->pkt_type = PACKET_MULTICAST;
+ }
+
+ else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+ skb->pkt_type = PACKET_OTHERHOST;
+
+ if (ntohs(eth->h_proto) >= 1536)
+ return eth->h_proto;
+
+ rawp = skb->data;
+
+ /*
+ * This is a magic hack to spot IPX packets. Older Novell breaks
+ * the protocol design and runs IPX over 802.3 without an 802.2 LLC
+ * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
+ * won't work for fault tolerant netware but does for the rest.
+ */
+ if (*(unsigned short *) rawp == 0xFFFF)
+ return htons(ETH_P_802_3);
+
+ /*
+ * Real 802.2 LLC
+ */
+ return htons(ETH_P_802_2);
+}
+#endif /* FASTER_VERSION */
+
+/*
+ * We remember when the MAC gets set, so we don't override it later with
+ * the ESI of the ATM card of the first VC
+ */
+static int (*my_eth_mac_addr)(struct net_device *, void *);
+static int br2684_mac_addr(struct net_device *dev, void *p)
+{
+ int err = my_eth_mac_addr(dev, p);
+ if (!err)
+ BRPRIV(dev)->mac_was_set = 1;
+ return err;
+}
+
+#ifdef CONFIG_ATM_BR2684_IPFILTER
+/* this IOCTL is experimental. */
+static int br2684_setfilt(struct atm_vcc *atmvcc, unsigned long arg)
+{
+ struct br2684_vcc *brvcc;
+ struct br2684_filter_set fs;
+
+ if (copy_from_user(&fs, (void *) arg, sizeof fs))
+ return -EFAULT;
+ if (fs.ifspec.method != BR2684_FIND_BYNOTHING) {
+ /*
+ * This is really a per-vcc thing, but we can also search
+ * by device
+ */
+ struct br2684_dev *brdev;
+ read_lock(&devs_lock);
+ brdev = br2684_find_dev(&fs.ifspec);
+ if (brdev == NULL || list_empty(&brdev->brvccs) ||
+ brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */
+ brvcc = NULL;
+ else
+ brvcc = list_entry_brvcc(brdev->brvccs.next);
+ read_unlock(&devs_lock);
+ if (brvcc == NULL)
+ return -ESRCH;
+ } else
+ brvcc = BR2684_VCC(atmvcc);
+ memcpy(&brvcc->filter, &fs.filter, sizeof(brvcc->filter));
+ return 0;
+}
+
+/* Returns 1 if packet should be dropped */
+static inline int
+packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
+{
+ if (brvcc->filter.netmask == 0)
+ return 0; /* no filter in place */
+ if (type == __constant_htons(ETH_P_IP) &&
+ (((struct iphdr *) (skb->data))->daddr & brvcc->filter.
+ netmask) == brvcc->filter.prefix)
+ return 0;
+ if (type == __constant_htons(ETH_P_ARP))
+ return 0;
+ /* TODO: we should probably filter ARPs too.. don't want to have
+ * them returning values that don't make sense, or is that ok?
+ */
+ return 1; /* drop */
+}
+#endif /* CONFIG_ATM_BR2684_IPFILTER */
+
+static void br2684_close_vcc(struct br2684_vcc *brvcc)
+{
+ DPRINTK("removing VCC %p from dev %p\n", brvcc, brvcc->brdev);
+ write_lock_irq(&devs_lock);
+ list_del(&brvcc->brvccs);
+ write_unlock_irq(&devs_lock);
+ brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */
+ brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */
+ kfree(brvcc);
+ MOD_DEC_USE_COUNT;
+}
+
+/* when AAL5 PDU comes in: */
+static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
+{
+ struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
+ struct br2684_dev *brdev = brvcc->brdev;
+ int plen = sizeof(llc_oui_pid_pad) + ETH_HLEN;
+
+ DPRINTK("br2684_push\n");
+
+ if (skb == NULL) { /* skb==NULL means VCC is being destroyed */
+ br2684_close_vcc(brvcc);
+ if (list_empty(&brdev->brvccs)) {
+ read_lock(&devs_lock);
+ list_del(&brdev->br2684_devs);
+ read_unlock(&devs_lock);
+ unregister_netdev(&brdev->net_dev);
+ kfree(brdev);
+ }
+ return;
+ }
+
+ skb_debug(skb);
+ atm_return(atmvcc, skb->truesize);
+ DPRINTK("skb from brdev %p\n", brdev);
+ if (brvcc->encaps == e_llc) {
+ /* let us waste some time for checking the encapsulation.
+ Note, that only 7 char is checked so frames with a valid FCS
+ are also accepted (but FCS is not checked of course) */
+ if (memcmp(skb->data, llc_oui_pid_pad, 7)) {
+ brdev->stats.rx_errors++;
+ dev_kfree_skb(skb);
+ return;
+ }
+ } else {
+ plen = PADLEN + ETH_HLEN; /* pad, dstmac,srcmac, ethtype */
+ /* first 2 chars should be 0 */
+ if (*((u16 *) (skb->data)) != 0) {
+ brdev->stats.rx_errors++;
+ dev_kfree_skb(skb);
+ return;
+ }
+ }
+ if (skb->len < plen) {
+ brdev->stats.rx_errors++;
+ dev_kfree_skb(skb); /* dev_ not needed? */
+ return;
+ }
+
+#ifdef FASTER_VERSION
+ /* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier,
+ than should be. What else should I set? */
+ skb_pull(skb, plen);
+ skb->mac.raw = ((char *) (skb->data)) - ETH_HLEN;
+ skb->pkt_type = PACKET_HOST;
+#ifdef CONFIG_BR2684_FAST_TRANS
+ skb->protocol = ((u16 *) skb->data)[-1];
+#else /* some protocols might require this: */
+ skb->protocol = br_type_trans(skb, &brdev->net_dev);
+#endif /* CONFIG_BR2684_FAST_TRANS */
+#else
+ skb_pull(skb, plen - ETH_HLEN);
+ skb->protocol = eth_type_trans(skb, &brdev->net_dev);
+#endif /* FASTER_VERSION */
+#ifdef CONFIG_ATM_BR2684_IPFILTER
+ if (packet_fails_filter(skb->protocol, brvcc, skb)) {
+ brdev->stats.rx_dropped++;
+ dev_kfree_skb(skb);
+ return;
+ }
+#endif /* CONFIG_ATM_BR2684_IPFILTER */
+ skb->dev = &brdev->net_dev;
+ ATM_SKB(skb)->vcc = atmvcc; /* needed ? */
+ DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol));
+ skb_debug(skb);
+ if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */
+ brdev->stats.rx_dropped++;
+ dev_kfree_skb(skb);
+ return;
+ }
+ brdev->stats.rx_packets++;
+ brdev->stats.rx_bytes += skb->len;
+ netif_rx(skb);
+}
+
+static int br2684_regvcc(struct atm_vcc *atmvcc, unsigned long arg)
+{
+/* assign a vcc to a dev
+Note: we do not have explicit unassign, but look at _push()
+*/
+ int err;
+ struct br2684_vcc *brvcc;
+ struct sk_buff_head copy;
+ struct sk_buff *skb;
+ struct br2684_dev *brdev;
+ struct atm_backend_br2684 be;
+
+ MOD_INC_USE_COUNT;
+ if (copy_from_user(&be, (void *) arg, sizeof be)) {
+ MOD_DEC_USE_COUNT;
+ return -EFAULT;
+ }
+ write_lock_irq(&devs_lock);
+ brdev = br2684_find_dev(&be.ifspec);
+ if (brdev == NULL) {
+ printk(KERN_ERR
+ "br2684: tried to attach to non-existant device\n");
+ err = -ENXIO;
+ goto error;
+ }
+ if (atmvcc->push == NULL) {
+ err = -EBADFD;
+ goto error;
+ }
+ if (!list_empty(&brdev->brvccs)) { /* Only 1 VCC/dev right now */
+ err = -EEXIST;
+ goto error;
+ }
+ if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO ||
+ be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps !=
+ BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) ||
+ be.min_size != 0) {
+ err = -EINVAL;
+ goto error;
+ }
+ brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
+ if (!brvcc) {
+ err = -ENOMEM;
+ goto error;
+ }
+ memset(brvcc, 0, sizeof(struct br2684_vcc));
+ DPRINTK("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps,
+ brvcc);
+ if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) {
+ unsigned char *esi = atmvcc->dev->esi;
+ if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5])
+ memcpy(brdev->net_dev.dev_addr, esi,
+ brdev->net_dev.addr_len);
+ else
+ brdev->net_dev.dev_addr[2] = 1;
+ }
+ list_add(&brvcc->brvccs, &brdev->brvccs);
+ write_unlock_irq(&devs_lock);
+ brvcc->brdev = brdev;
+ brvcc->atmvcc = atmvcc;
+ atmvcc->user_back = brvcc;
+ brvcc->encaps = (enum br2684_encaps) be.encaps;
+ brvcc->old_push = atmvcc->push;
+ barrier();
+ atmvcc->push = br2684_push;
+ skb_queue_head_init(&copy);
+ skb_migrate(&atmvcc->sk->receive_queue, &copy);
+ while ((skb = skb_dequeue(&copy))) {
+ BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
+ BRPRIV(skb->dev)->stats.rx_packets--;
+ br2684_push(atmvcc, skb);
+ }
+ return 0;
+ error:
+ write_unlock_irq(&devs_lock);
+ MOD_DEC_USE_COUNT;
+ return err;
+}
+
+static int br2684_create(unsigned long arg)
+{
+ int err;
+ struct br2684_dev *brdev;
+ struct atm_newif_br2684 ni;
+
+ DPRINTK("br2684_create\n");
+ /*
+ * We track module use by vcc's NOT the devices they're on. We're
+ * protected here against module death by the kernel_lock, but if
+ * we need to sleep we should make sure that the module doesn't
+ * disappear under us.
+ */
+ MOD_INC_USE_COUNT;
+ if (copy_from_user(&ni, (void *) arg, sizeof ni)) {
+ MOD_DEC_USE_COUNT;
+ return -EFAULT;
+ }
+ if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) {
+ MOD_DEC_USE_COUNT;
+ return -EINVAL;
+ }
+ if ((brdev = kmalloc(sizeof(struct br2684_dev), GFP_KERNEL)) == NULL) {
+ MOD_DEC_USE_COUNT;
+ return -ENOMEM;
+ }
+ memset(brdev, 0, sizeof(struct br2684_dev));
+ INIT_LIST_HEAD(&brdev->brvccs);
+
+ write_lock_irq(&devs_lock);
+ brdev->number = list_empty(&br2684_devs) ? 1 :
+ list_entry_brdev(br2684_devs.prev)->number + 1;
+ list_add_tail(&brdev->br2684_devs, &br2684_devs);
+ write_unlock_irq(&devs_lock);
+
+ if (ni.ifname[0] != '\0') {
+ memcpy(brdev->net_dev.name, ni.ifname,
+ sizeof(brdev->net_dev.name));
+ brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] = '\0';
+ } else
+ sprintf(brdev->net_dev.name, "nas%d", brdev->number);
+ DPRINTK("registered netdev %s\n", brdev->net_dev.name);
+ ether_setup(&brdev->net_dev);
+ brdev->mac_was_set = 0;
+#ifdef FASTER_VERSION
+ my_eth_header = brdev->net_dev.hard_header;
+ brdev->net_dev.hard_header = br2684_header;
+ my_eth_header_cache = brdev->net_dev.hard_header_cache;
+ brdev->net_dev.hard_header_cache = br2684_header_cache;
+ brdev->net_dev.hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN; /* 10 + 14 */
+#endif
+ my_eth_mac_addr = brdev->net_dev.set_mac_address;
+ brdev->net_dev.set_mac_address = br2684_mac_addr;
+ brdev->net_dev.hard_start_xmit = br2684_start_xmit;
+ brdev->net_dev.get_stats = br2684_get_stats;
+
+ /* open, stop, do_ioctl ? */
+ err = register_netdev(&brdev->net_dev);
+ MOD_DEC_USE_COUNT;
+ if (err < 0) {
+ printk(KERN_ERR "br2684_create: register_netdev failed\n");
+ write_lock_irq(&devs_lock);
+ list_del(&brdev->br2684_devs);
+ write_unlock_irq(&devs_lock);
+ kfree(brdev);
+ return err;
+ }
+ return 0;
+}
+
+/*
+ * This handles ioctls actually performed on our vcc - we must return
+ * -ENOIOCTLCMD for any unrecognized ioctl
+ */
+static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd,
+ unsigned long arg)
+{
+ int err;
+ switch(cmd) {
+ case ATM_SETBACKEND:
+ case ATM_NEWBACKENDIF: {
+ atm_backend_t b;
+ MOD_INC_USE_COUNT;
+ err = get_user(b, (atm_backend_t *) arg);
+ MOD_DEC_USE_COUNT;
+ if (err)
+ return -EFAULT;
+ if (b != ATM_BACKEND_BR2684)
+ return -ENOIOCTLCMD;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (cmd == ATM_SETBACKEND)
+ return br2684_regvcc(atmvcc, arg);
+ else
+ return br2684_create(arg);
+ }
+#ifdef CONFIG_ATM_BR2684_IPFILTER
+ case BR2684_SETFILT:
+ if (atmvcc->push != br2684_push)
+ return -ENOIOCTLCMD;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ MOD_INC_USE_COUNT;
+ err = br2684_setfilt(atmvcc, arg);
+ MOD_DEC_USE_COUNT;
+ return err;
+#endif /* CONFIG_ATM_BR2684_IPFILTER */
+ }
+ return -ENOIOCTLCMD;
+}
+
+/* Never put more than 256 bytes in at once */
+static int br2684_proc_engine(loff_t pos, char *buf)
+{
+ struct list_head *lhd, *lhc;
+ struct br2684_dev *brdev;
+ struct br2684_vcc *brvcc;
+ list_for_each(lhd, &br2684_devs) {
+ brdev = list_entry_brdev(lhd);
+ if (pos-- == 0)
+ return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:"
+ "%02X:%02X:%02X:%02X (%s)\n", brdev->net_dev.name,
+ brdev->number,
+ brdev->net_dev.dev_addr[0],
+ brdev->net_dev.dev_addr[1],
+ brdev->net_dev.dev_addr[2],
+ brdev->net_dev.dev_addr[3],
+ brdev->net_dev.dev_addr[4],
+ brdev->net_dev.dev_addr[5],
+ brdev->mac_was_set ? "set" : "auto");
+ list_for_each(lhc, &brdev->brvccs) {
+ brvcc = list_entry_brvcc(lhc);
+ if (pos-- == 0)
+ return sprintf(buf, " vcc %d.%d.%d: encaps=%s"
+#ifndef FASTER_VERSION
+ ", failed copies %u/%u"
+#endif /* FASTER_VERSION */
+ "\n", brvcc->atmvcc->dev->number,
+ brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
+ (brvcc->encaps == e_llc) ? "LLC" : "VC"
+#ifndef FASTER_VERSION
+ , brvcc->copies_failed
+ , brvcc->copies_needed
+#endif /* FASTER_VERSION */
+ );
+#ifdef CONFIG_ATM_BR2684_IPFILTER
+#define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte]
+#define bs(var) b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3)
+ if (brvcc->filter.netmask != 0 && pos-- == 0)
+ return sprintf(buf, " filter=%d.%d.%d.%d/"
+ "%d.%d.%d.%d\n", bs(prefix), bs(netmask));
+#undef bs
+#undef b1
+#endif /* CONFIG_ATM_BR2684_IPFILTER */
+ }
+ }
+ return 0;
+}
+
+static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count,
+ loff_t *pos)
+{
+ unsigned long page;
+ int len = 0, x, left;
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ left = PAGE_SIZE - 256;
+ if (count < left)
+ left = count;
+ read_lock(&devs_lock);
+ for (;;) {
+ x = br2684_proc_engine(*pos, &((char *) page)[len]);
+ if (x == 0)
+ break;
+ if (x > left)
+ /*
+ * This should only happen if the user passed in
+ * a "count" too small for even one line
+ */
+ x = -EINVAL;
+ if (x < 0) {
+ len = x;
+ break;
+ }
+ len += x;
+ left -= x;
+ (*pos)++;
+ if (left < 256)
+ break;
+ }
+ read_unlock(&devs_lock);
+ if (len > 0 && copy_to_user(buf, (char *) page, len))
+ len = -EFAULT;
+ free_page(page);
+ return len;
+}
+
+static struct file_operations br2684_proc_operations = {
+ read: br2684_proc_read,
+};
+
+extern struct proc_dir_entry *atm_proc_root; /* from proc.c */
+
+extern int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
+
+/* the following avoids some spurious warnings from the compiler */
+#define UNUSED __attribute__((unused))
+
+static int __init UNUSED br2684_init(void)
+{
+ struct proc_dir_entry *p;
+ if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)
+ return -ENOMEM;
+ p->proc_fops = &br2684_proc_operations;
+ br2684_ioctl_hook = br2684_ioctl;
+ return 0;
+}
+
+static void __exit UNUSED br2684_exit(void)
+{
+ struct br2684_dev *brdev;
+ br2684_ioctl_hook = NULL;
+ remove_proc_entry("br2684", atm_proc_root);
+ while (!list_empty(&br2684_devs)) {
+ brdev = list_entry_brdev(br2684_devs.next);
+ unregister_netdev(&brdev->net_dev);
+ list_del(&brdev->br2684_devs);
+ kfree(brdev);
+ }
+}
+
+module_init(br2684_init);
+module_exit(br2684_exit);
+
+MODULE_AUTHOR("Marcell GAL");
+MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5");
+MODULE_LICENSE("GPL");
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 0cdcb555c54a..8d6e9ad617ec 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -127,6 +127,8 @@ static void idle_timer_check(unsigned long dummy)
struct atmarp_entry *entry = NEIGH2ENTRY(n);
struct clip_vcc *clip_vcc;
+ write_lock(&n->lock);
+
for (clip_vcc = entry->vccs; clip_vcc;
clip_vcc = clip_vcc->next)
if (clip_vcc->idle_timeout &&
@@ -141,6 +143,7 @@ static void idle_timer_check(unsigned long dummy)
if (entry->vccs ||
time_before(jiffies, entry->expires)) {
np = &n->next;
+ write_unlock(&n->lock);
continue;
}
if (atomic_read(&n->refcnt) > 1) {
@@ -152,11 +155,13 @@ static void idle_timer_check(unsigned long dummy)
NULL)
dev_kfree_skb(skb);
np = &n->next;
+ write_unlock(&n->lock);
continue;
}
*np = n->next;
DPRINTK("expired neigh %p\n",n);
n->dead = 1;
+ write_unlock(&n->lock);
neigh_release(n);
}
}
diff --git a/net/atm/common.c b/net/atm/common.c
index addb78f2bc28..a9835c3c997a 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -62,6 +62,13 @@ int (*pppoatm_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
EXPORT_SYMBOL(pppoatm_ioctl_hook);
#endif
+#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
+int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
+#ifdef CONFIG_ATM_BR2684_MODULE
+EXPORT_SYMBOL(br2684_ioctl_hook);
+#endif
+#endif
+
#include "resources.h" /* atm_find_dev */
#include "common.h" /* prototypes */
#include "protocols.h" /* atm_init_<transport> */
@@ -120,7 +127,6 @@ int atm_create(struct socket *sock,int protocol,int family)
vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
vcc->atm_options = vcc->aal_options = 0;
init_waitqueue_head(&vcc->sleep);
- skb_queue_head_init(&vcc->listenq);
sk->sleep = &vcc->sleep;
sock->sk = sk;
return 0;
@@ -489,7 +495,7 @@ unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait)
vcc = ATM_SD(sock);
poll_wait(file,&vcc->sleep,wait);
mask = 0;
- if (skb_peek(&vcc->sk->receive_queue) || skb_peek(&vcc->listenq))
+ if (skb_peek(&vcc->sk->receive_queue))
mask |= POLLIN | POLLRDNORM;
if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
test_bit(ATM_VF_CLOSE,&vcc->flags))
@@ -785,6 +791,13 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
goto done;
}
#endif
+#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
+ if (br2684_ioctl_hook) {
+ ret_val = br2684_ioctl_hook(vcc, cmd, arg);
+ if (ret_val != -ENOIOCTLCMD)
+ goto done;
+ }
+#endif
if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) {
ret_val = -EFAULT;
goto done;
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 9a603769bb4c..596f8b2197cf 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -302,7 +302,7 @@ lec_send_packet(struct sk_buff *skb, struct net_device *dev)
#endif
min_frame_size = LEC_MINIMUM_8023_SIZE;
if (skb->len < min_frame_size) {
- if (skb->truesize < min_frame_size) {
+ if ((skb->len + skb_tailroom(skb)) < min_frame_size) {
skb2 = skb_copy_expand(skb, 0,
min_frame_size - skb->truesize, GFP_ATOMIC);
dev_kfree_skb(skb);
diff --git a/net/atm/signaling.c b/net/atm/signaling.c
index 90ae9360e672..dd44aaf45bcf 100644
--- a/net/atm/signaling.c
+++ b/net/atm/signaling.c
@@ -129,12 +129,12 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
case as_indicate:
vcc = *(struct atm_vcc **) &msg->listen_vcc;
DPRINTK("as_indicate!!!\n");
- if (!vcc->backlog_quota) {
+ if (vcc->sk->ack_backlog == vcc->sk->max_ack_backlog) {
sigd_enq(0,as_reject,vcc,NULL,NULL);
return 0;
}
- vcc->backlog_quota--;
- skb_queue_tail(&vcc->listenq,skb);
+ vcc->sk->ack_backlog++;
+ skb_queue_tail(&vcc->sk->receive_queue,skb);
if (vcc->callback) {
DPRINTK("waking vcc->sleep 0x%p\n",
&vcc->sleep);
diff --git a/net/atm/svc.c b/net/atm/svc.c
index 823e5417ad6e..fef1906c8821 100644
--- a/net/atm/svc.c
+++ b/net/atm/svc.c
@@ -74,7 +74,7 @@ static void svc_disconnect(struct atm_vcc *vcc)
}
/* beware - socket is still in use by atmsigd until the last
as_indicate has been answered */
- while ((skb = skb_dequeue(&vcc->listenq))) {
+ while ((skb = skb_dequeue(&vcc->sk->receive_queue))) {
DPRINTK("LISTEN REL\n");
sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0);
dev_kfree_skb(skb);
@@ -253,7 +253,7 @@ static int svc_listen(struct socket *sock,int backlog)
remove_wait_queue(&vcc->sleep,&wait);
if (!sigd) return -EUNATCH;
set_bit(ATM_VF_LISTEN,&vcc->flags);
- vcc->backlog_quota = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
+ vcc->sk->max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
return vcc->reply;
}
@@ -277,7 +277,7 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
DECLARE_WAITQUEUE(wait,current);
add_wait_queue(&old_vcc->sleep,&wait);
- while (!(skb = skb_dequeue(&old_vcc->listenq)) && sigd) {
+ while (!(skb = skb_dequeue(&old_vcc->sk->receive_queue)) && sigd) {
if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break;
if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) {
error = old_vcc->reply;
@@ -306,7 +306,7 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
error = atm_connect(newsock,msg->pvc.sap_addr.itf,
msg->pvc.sap_addr.vpi,msg->pvc.sap_addr.vci);
dev_kfree_skb(skb);
- old_vcc->backlog_quota++;
+ old_vcc->sk->ack_backlog--;
if (error) {
sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL,
&old_vcc->qos,error);
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 68ea878ac7a5..5cff59086aab 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -143,6 +143,9 @@ int br_handle_frame(struct sk_buff *skb)
return -1;
}
+ if (!memcmp(p->br->dev.dev_addr, dest, ETH_ALEN))
+ skb->pkt_type = PACKET_HOST;
+
NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
br_handle_frame_finish);
rcu_read_unlock();
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index c6d5e32b6a5b..cccc6d75bdc9 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -126,9 +126,6 @@ struct sk_buff *alloc_skb(unsigned int size, int gfp_mask)
struct sk_buff *skb;
u8 *data;
- if (gfp_mask & __GFP_WAIT)
- might_sleep();
-
/* Get the HEAD */
skb = kmem_cache_alloc(skbuff_head_cache,
gfp_mask & ~__GFP_DMA);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index eb97374a3d85..69cfc1691f4a 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -926,6 +926,7 @@ struct proto_ops inet_dgram_ops = {
struct net_proto_family inet_family_ops = {
.family = PF_INET,
.create = inet_create,
+ .owner = THIS_MODULE,
};
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 99883006c28d..bc68ff57db9b 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -115,9 +115,9 @@ struct net_device * ip_dev_find(u32 addr)
if (res.type != RTN_LOCAL)
goto out;
dev = FIB_RES_DEV(res);
- if (dev)
- atomic_inc(&dev->refcnt);
+ if (dev)
+ dev_hold(dev);
out:
fib_res_put(&res);
return dev;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index eadf463b7112..c1b6060df3f1 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -406,7 +406,7 @@ static int fib_check_nh(const struct rtmsg *r, struct fib_info *fi, struct fib_n
if (!(dev->flags&IFF_UP))
return -ENETDOWN;
nh->nh_dev = dev;
- atomic_inc(&dev->refcnt);
+ dev_hold(dev);
nh->nh_scope = RT_SCOPE_LINK;
return 0;
}
@@ -429,7 +429,7 @@ static int fib_check_nh(const struct rtmsg *r, struct fib_info *fi, struct fib_n
nh->nh_oif = FIB_RES_OIF(res);
if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL)
goto out;
- atomic_inc(&nh->nh_dev->refcnt);
+ dev_hold(nh->nh_dev);
err = -ENETDOWN;
if (!(nh->nh_dev->flags & IFF_UP))
goto out;
@@ -451,7 +451,7 @@ out:
return -ENETDOWN;
}
nh->nh_dev = in_dev->dev;
- atomic_inc(&nh->nh_dev->refcnt);
+ dev_hold(nh->nh_dev);
nh->nh_scope = RT_SCOPE_HOST;
in_dev_put(in_dev);
}
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 1bf1edc09f64..547dfa233a0f 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -444,6 +444,8 @@ static void SMP_TIMER_NAME(tcp_twkill)(unsigned long dummy)
while((tw = tcp_tw_death_row[tcp_tw_death_row_slot]) != NULL) {
tcp_tw_death_row[tcp_tw_death_row_slot] = tw->next_death;
+ if (tw->next_death)
+ tw->next_death->pprev_death = tw->pprev_death;
tw->pprev_death = NULL;
spin_unlock(&tw_death_lock);
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 788ecf555be1..8ae2dfaba7a5 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -535,6 +535,7 @@ struct proto_ops inet6_dgram_ops = {
struct net_proto_family inet6_family_ops = {
.family = PF_INET6,
.create = inet6_create,
+ .owner = THIS_MODULE,
};
#ifdef MODULE
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 69fe439d49c1..f2f7277dd931 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -593,7 +593,7 @@ out:
#ifdef CONFIG_IPV6_SUBTREES
/* Subtree creation failed, probably main tree node
- is orphan. If it is, shot it.
+ is orphan. If it is, shoot it.
*/
st_failure:
if (fn && !(fn->fn_flags&RTN_RTINFO|RTN_ROOT))
@@ -953,7 +953,7 @@ int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh)
#if RT6_DEBUG >= 2
if (rt->u.dst.obsolete>0) {
- BUG_TRAP(fn==NULL || rt->u.dst.obsolete<=0);
+ BUG_TRAP(fn==NULL);
return -ENOENT;
}
#endif
@@ -979,7 +979,7 @@ int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh)
}
/*
- * Tree transversal function.
+ * Tree traversal function.
*
* Certainly, it is not interrupt safe.
* However, it is internally reenterable wrt itself and fib6_add/fib6_del.
@@ -1179,14 +1179,14 @@ static int fib6_age(struct rt6_info *rt, void *arg)
*/
if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) {
- if ((long)(now - rt->rt6i_expires) > 0) {
+ if (time_after(now, rt->rt6i_expires)) {
RT6_TRACE("expiring %p\n", rt);
return -1;
}
gc_args.more++;
} else if (rt->rt6i_flags & RTF_CACHE) {
if (atomic_read(&rt->u.dst.__refcnt) == 0 &&
- (long)(now - rt->u.dst.lastuse) >= gc_args.timeout) {
+ time_after_eq(now, rt->u.dst.lastuse + gc_args.timeout)) {
RT6_TRACE("aging clone %p\n", rt);
return -1;
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index fe7a02ba617c..17c0d9497ccb 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -39,6 +39,7 @@
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#endif
#include <net/snmp.h>
@@ -564,7 +565,7 @@ static int ip6_dst_gc()
static unsigned long last_gc;
unsigned long now = jiffies;
- if ((long)(now - last_gc) < ip6_rt_gc_min_interval &&
+ if (time_after(last_gc + ip6_rt_gc_min_interval, now) &&
atomic_read(&ip6_dst_ops.entries) <= ip6_rt_max_size)
goto out;
@@ -1751,27 +1752,28 @@ static int rt6_proc_info(char *buffer, char **start, off_t offset, int length)
extern struct rt6_statistics rt6_stats;
-static int rt6_proc_stats(char *buffer, char **start, off_t offset, int length)
+static int rt6_stats_seq_show(struct seq_file *seq, void *v)
{
- int len;
-
- len = sprintf(buffer, "%04x %04x %04x %04x %04x %04x\n",
+ seq_printf(seq, "%04x %04x %04x %04x %04x %04x\n",
rt6_stats.fib_nodes, rt6_stats.fib_route_nodes,
rt6_stats.fib_rt_alloc, rt6_stats.fib_rt_entries,
rt6_stats.fib_rt_cache,
atomic_read(&ip6_dst_ops.entries));
- len -= offset;
-
- if (len > length)
- len = length;
- if(len < 0)
- len = 0;
-
- *start = buffer + offset;
+ return 0;
+}
- return len;
+static int rt6_stats_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, rt6_stats_seq_show, NULL);
}
+
+static struct file_operations rt6_stats_seq_fops = {
+ .open = rt6_stats_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_SYSCTL
@@ -1877,6 +1879,8 @@ ctl_table ipv6_route_table[] = {
void __init ip6_route_init(void)
{
+ struct proc_dir_entry *p;
+
ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache",
sizeof(struct rt6_info),
0, SLAB_HWCACHE_ALIGN,
@@ -1884,7 +1888,9 @@ void __init ip6_route_init(void)
fib6_init();
#ifdef CONFIG_PROC_FS
proc_net_create("ipv6_route", 0, rt6_proc_info);
- proc_net_create("rt6_stats", 0, rt6_proc_stats);
+ p = create_proc_entry("rt6_stats", S_IRUGO, proc_net);
+ if (p)
+ p->proc_fops = &rt6_stats_seq_fops;
#endif
xfrm6_init();
}
@@ -1894,7 +1900,7 @@ void ip6_route_cleanup(void)
{
#ifdef CONFIG_PROC_FS
proc_net_remove("ipv6_route");
- proc_net_remove("rt6_stats");
+ remove_proc_entry("rt6_stats", proc_net);
#endif
xfrm6_fini();
rt6_ifdown(NULL);
diff --git a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c
index 70d000f8f06a..94c99613890c 100644
--- a/net/netlink/netlink_dev.c
+++ b/net/netlink/netlink_dev.c
@@ -220,14 +220,6 @@ static struct {
},
};
-static void __init make_devfs_entries (const char *name, int minor)
-{
- devfs_register (NULL, name, DEVFS_FL_DEFAULT,
- NETLINK_MAJOR, minor,
- S_IFCHR | S_IRUSR | S_IWUSR,
- &netlink_fops, NULL);
-}
-
int __init init_netlink(void)
{
int i;
@@ -236,18 +228,20 @@ int __init init_netlink(void)
printk(KERN_ERR "netlink: unable to get major %d\n", NETLINK_MAJOR);
return -EIO;
}
+
devfs_mk_dir("netlink");
+
/* Someone tell me the official names for the uppercase ones */
for (i = 0; i < sizeof(entries)/sizeof(entries[0]); i++) {
- char name[20];
- sprintf(name, "netlink/%s", entries[i].name);
- make_devfs_entries(name, entries[i].minor);
+ devfs_mk_cdev(MKDEV(NETLINK_MAJOR, entries[i].minor),
+ S_IFCHR|S_IRUSR|S_IWUSR, "netlink/%s", entries[i].name);
}
+
for (i = 0; i < 16; i++) {
- char name[20];
- sprintf(name, "netlink/tap%d", i);
- make_devfs_entries(name, i + 16);
+ devfs_mk_cdev(MKDEV(NETLINK_MAJOR, i + 16),
+ S_IFCHR|S_IRUSR|S_IWUSR, "netlink/tap%d", i);
}
+
return 0;
}
diff --git a/net/socket.c b/net/socket.c
index 9e49a7bd82f1..b626aeff4aaf 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1280,26 +1280,26 @@ asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_a
* We don't need try_module_get here, as the listening socket (sock)
* has the protocol module (sock->ops->owner) held.
*/
- __module_get(sock->ops->owner);
+ __module_get(newsock->ops->owner);
err = sock->ops->accept(sock, newsock, sock->file->f_flags);
if (err < 0)
- goto out_module_put;
+ goto out_release;
if (upeer_sockaddr) {
if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {
err = -ECONNABORTED;
- goto out_module_put;
+ goto out_release;
}
err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);
if (err < 0)
- goto out_module_put;
+ goto out_release;
}
/* File flags are not inherited via accept() unlike another OSes. */
if ((err = sock_map_fd(newsock)) < 0)
- goto out_module_put;
+ goto out_release;
security_socket_post_accept(sock, newsock);
@@ -1307,8 +1307,6 @@ out_put:
sockfd_put(sock);
out:
return err;
-out_module_put:
- module_put(sock->ops->owner);
out_release:
sock_release(newsock);
goto out_put;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 0955346cc477..e1f2d615b084 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -625,7 +625,7 @@ static unix_socket *unix_find_other(struct sockaddr_un *sunname, int len,
goto put_fail;
if (u->type == type)
- UPDATE_ATIME(nd.dentry->d_inode);
+ update_atime(nd.dentry->d_inode);
path_release(&nd);
@@ -641,7 +641,7 @@ static unix_socket *unix_find_other(struct sockaddr_un *sunname, int len,
struct dentry *dentry;
dentry = unix_sk(u)->dentry;
if (dentry)
- UPDATE_ATIME(dentry->d_inode);
+ update_atime(dentry->d_inode);
} else
goto fail;
}
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 4f3f9e3346a9..21d1a162b519 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -66,6 +66,12 @@ __build: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(extra-y)) \
$(subdir-ym) $(always)
@:
+# Linus's kernel sanity checking tool
+ifneq ($(KBUILD_CHECKSRC),0)
+quiet_cmd_checksrc = CHECK $<
+ cmd_checksrc = $(CHECK) $(CFLAGS) $< ;
+endif
+
# Module versioning
# ---------------------------------------------------------------------------
@@ -91,6 +97,8 @@ quiet_cmd_vcc_o_c = CC $(quiet_modtag) $@
cmd_vcc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
define rule_vcc_o_c
+ $(if $($(quiet)cmd_checksrc),echo ' $($(quiet)cmd_checksrc)';) \
+ $(cmd_checksrc) \
$(if $($(quiet)cmd_vcc_o_c),echo ' $($(quiet)cmd_vcc_o_c)';) \
$(cmd_vcc_o_c); \
\
@@ -158,6 +166,15 @@ cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $<
quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
+define rule_cc_o_c
+ $(if $($(quiet)cmd_checksrc),echo ' $($(quiet)cmd_checksrc)';) \
+ $(cmd_checksrc) \
+ $(if $($(quiet)cmd_cc_o_c),echo ' $($(quiet)cmd_cc_o_c)';) \
+ $(cmd_cc_o_c); \
+ scripts/fixdep $(depfile) $@ '$(cmd_cc_o_c)' > $(@D)/.$(@F).tmp; \
+ rm -f $(depfile); \
+ mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
+endef
# Built-in and composite module parts
@@ -165,7 +182,7 @@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
ifdef CONFIG_MODVERSIONS
$(call if_changed_rule,vcc_o_c)
else
- $(call if_changed_dep,cc_o_c)
+ $(call if_changed_rule,cc_o_c)
endif
# Single-part modules are special since we need to mark them in $(MODVERDIR)
@@ -174,7 +191,7 @@ $(single-used-m): %.o: %.c FORCE
ifdef CONFIG_MODVERSIONS
$(call if_changed_rule,vcc_o_c)
else
- $(call if_changed_dep,cc_o_c)
+ $(call if_changed_rule,cc_o_c)
endif
$(touch-module)
diff --git a/security/dummy.c b/security/dummy.c
index 062ae9a7fa2b..d12442182a94 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -334,6 +334,11 @@ static int dummy_inode_setxattr (struct dentry *dentry, char *name, void *value,
return 0;
}
+static void dummy_inode_post_setxattr (struct dentry *dentry, char *name, void *value,
+ size_t size, int flags)
+{
+}
+
static int dummy_inode_getxattr (struct dentry *dentry, char *name)
{
return 0;
@@ -803,6 +808,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, inode_getattr);
set_to_dummy_if_null(ops, inode_delete);
set_to_dummy_if_null(ops, inode_setxattr);
+ set_to_dummy_if_null(ops, inode_post_setxattr);
set_to_dummy_if_null(ops, inode_getxattr);
set_to_dummy_if_null(ops, inode_listxattr);
set_to_dummy_if_null(ops, inode_removexattr);
diff --git a/sound/core/info.c b/sound/core/info.c
index 0ea9e88a6673..335b5f8fcd4e 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -1079,15 +1079,9 @@ snd_info_entry_t *snd_info_create_device(const char *name, unsigned int number,
p->data = (void *) entry;
entry->p = p;
up(&info_mutex);
-#ifdef CONFIG_DEVFS_FS
- if (strncmp(name, "controlC", 8)) { /* created in sound.c */
- char dname[32];
- sprintf(dname, "snd/%s", name);
- devfs_register(NULL, dname, DEVFS_FL_DEFAULT,
- _major, minor, mode,
- &snd_fops, NULL);
- }
-#endif
+
+ if (strncmp(name, "controlC", 8) == 0) /* created in sound.c */
+ devfs_mk_cdev(MKDEV(_major, minor), mode, "snd/%s", name);
return entry;
}
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 92ccff035ee8..1736889131bd 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -323,13 +323,8 @@ int __exit snd_minor_info_done(void)
static int __init alsa_sound_init(void)
{
-#ifdef CONFIG_DEVFS_FS
short controlnum;
- char controlname[24];
-#endif
-#ifdef CONFIG_SND_OSSEMUL
- int err;
-#endif
+ int err = 0;
int card;
snd_ecards_limit = cards_limit;
@@ -356,21 +351,19 @@ static int __init alsa_sound_init(void)
#ifdef CONFIG_SND_OSSEMUL
snd_info_minor_register();
#endif
-#ifdef CONFIG_DEVFS_FS
+
for (controlnum = 0; controlnum < cards_limit; controlnum++) {
- sprintf(controlname, "snd/controlC%d", controlnum);
- devfs_register(NULL, controlname, DEVFS_FL_DEFAULT,
- major, controlnum<<5, device_mode | S_IFCHR,
- &snd_fops, NULL);
+ devfs_mk_cdev(MKDEV(major, controlnum<<5),
+ device_mode | S_IFCHR, "snd/controlC%d", controlnum);
}
-#endif
+
#ifndef MODULE
printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n");
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_APM)
pm_init();
#endif
- return 0;
+ return err;
}
static void __exit alsa_sound_exit(void)
diff --git a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c
index 06026da6a9dd..90b6299092f7 100644
--- a/sound/oss/opl3sa2.c
+++ b/sound/oss/opl3sa2.c
@@ -353,7 +353,8 @@ static void opl3sa2_mixer_reset(opl3sa2_state_t* devc)
}
}
-
+/* Currently only used for power management */
+#ifdef CONFIG_PM
static void opl3sa2_mixer_restore(opl3sa2_state_t* devc)
{
if (devc) {
@@ -366,7 +367,7 @@ static void opl3sa2_mixer_restore(opl3sa2_state_t* devc)
}
}
}
-
+#endif
static inline void arg_to_vol_mono(unsigned int vol, int* value)
{
@@ -961,7 +962,6 @@ static int opl3sa2_resume(struct pm_dev *pdev)
spin_unlock_irqrestore(&opl3sa2_lock,flags);
return 0;
}
-#endif /* CONFIG_PM */
static int opl3sa2_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data)
{
@@ -976,6 +976,7 @@ static int opl3sa2_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *dat
}
return 0;
}
+#endif /* CONFIG_PM */
/*
* Install OPL3-SA2 based card(s).
@@ -1127,10 +1128,11 @@ static void __exit cleanup_opl3sa2(void)
int card;
for(card = 0; card < opl3sa2_cards_num; card++) {
+#ifdef CONFIG_PM
if (opl3sa2_state[card].pmdev)
pm_unregister(opl3sa2_state[card].pmdev);
-
- if(opl3sa2_state[card].cfg_mpu.slots[1] != -1) {
+#endif
+ if (opl3sa2_state[card].cfg_mpu.slots[1] != -1) {
unload_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu);
}
unload_opl3sa2_mss(&opl3sa2_state[card].cfg_mss);
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 1d0eee922c98..496041a51f88 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -549,7 +549,6 @@ MODULE_PARM(dmabug, "i");
static int __init oss_init(void)
{
int err;
- char name_buf[32];
int i, j;
/* drag in sound_syms.o */
@@ -573,19 +572,18 @@ static int __init oss_init(void)
sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
- sprintf(name_buf, "sound/%s", dev_list[i].name);
- devfs_register (NULL, name_buf, DEVFS_FL_NONE,
- SOUND_MAJOR, dev_list[i].minor,
- S_IFCHR | dev_list[i].mode,
- &oss_sound_fops, NULL);
+ devfs_mk_cdev(MKDEV(SOUND_MAJOR, dev_list[i].minor),
+ S_IFCHR | dev_list[i].mode,
+ "sound/%s", dev_list[i].name);
+
if (!dev_list[i].num)
continue;
+
for (j = 1; j < *dev_list[i].num; j++) {
- sprintf(name_buf, "sound/%s%d", dev_list[i].name, j);
- devfs_register (NULL, name_buf, DEVFS_FL_NONE,
- SOUND_MAJOR, dev_list[i].minor + (j * 0x10),
- S_IFCHR | dev_list[i].mode,
- &oss_sound_fops, NULL);
+ devfs_mk_cdev(MKDEV(SOUND_MAJOR,
+ dev_list[i].minor + (j*0x10)),
+ S_IFCHR | dev_list[i].mode,
+ "sound/%s%d", dev_list[i].name, j);
}
}
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 614a2c222a64..0107b3a13e24 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -168,8 +168,8 @@ static int sound_insert_unit(struct sound_unit **list, struct file_operations *f
else
sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
- devfs_register(NULL, s->name, 0, SOUND_MAJOR, s->unit_minor,
- S_IFCHR | mode, fops, NULL);
+ devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor),
+ S_IFCHR | mode, s->name);
return r;
fail: