aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavem <davem>2002-01-24 14:07:51 +0000
committerdavem <davem>2002-01-24 14:07:51 +0000
commitdfc969f06995d2388f9e4d737a48ec69483dcb71 (patch)
tree83f8ec02278d45c7299b4bf96f4500dde94efa83
parent07e4431dbcc277e8d75afa4c49efb2a07de67afa (diff)
downloadnetdev-vger-cvs-dfc969f06995d2388f9e4d737a48ec69483dcb71.tar.gz
Quick untested merge to 2.5.3-pre4
-rw-r--r--Documentation/Configure.help10
-rw-r--r--Makefile2
-rw-r--r--arch/alpha/vmlinux.lds.in10
-rw-r--r--arch/arm/kernel/ecard.c2
-rw-r--r--arch/arm/vmlinux-armo.lds.in8
-rw-r--r--arch/arm/vmlinux-armv.lds.in8
-rw-r--r--arch/cris/cris.ld8
-rw-r--r--arch/i386/kernel/mca.c2
-rw-r--r--arch/i386/vmlinux.lds10
-rw-r--r--arch/ia64/vmlinux.lds.S12
-rw-r--r--arch/m68k/vmlinux-sun3.lds10
-rw-r--r--arch/m68k/vmlinux.lds10
-rw-r--r--arch/mips/ld.script.in10
-rw-r--r--arch/mips64/ld.script.elf32.S10
-rw-r--r--arch/mips64/ld.script.elf6410
-rw-r--r--arch/parisc/vmlinux.lds10
-rw-r--r--arch/ppc/kernel/setup.c2
-rw-r--r--arch/ppc/vmlinux.lds10
-rw-r--r--arch/s390/vmlinux-shared.lds10
-rw-r--r--arch/s390/vmlinux.lds10
-rw-r--r--arch/s390x/vmlinux-shared.lds10
-rw-r--r--arch/s390x/vmlinux.lds10
-rw-r--r--arch/sh/vmlinux.lds.S10
-rw-r--r--arch/sparc/vmlinux.lds10
-rw-r--r--arch/sparc64/vmlinux.lds10
-rw-r--r--drivers/char/joystick/iforce.c63
-rw-r--r--drivers/dio/dio.c2
-rw-r--r--drivers/nubus/nubus.c2
-rw-r--r--drivers/pci/pci.c38
-rw-r--r--drivers/pcmcia/ds.c7
-rw-r--r--drivers/pnp/isapnp.c7
-rw-r--r--drivers/sbus/sbus.c4
-rw-r--r--drivers/scsi/README.st24
-rw-r--r--drivers/scsi/st.c331
-rw-r--r--drivers/scsi/st.h1
-rw-r--r--drivers/scsi/st_options.h4
-rw-r--r--drivers/sound/cmpci.c10
-rw-r--r--drivers/sound/ymfpci.c25
-rw-r--r--drivers/tc/tc.c2
-rw-r--r--drivers/usb/CDCEther.c46
-rw-r--r--drivers/usb/CDCEther.h2
-rw-r--r--drivers/usb/audio.c227
-rw-r--r--drivers/usb/catc.c56
-rw-r--r--drivers/usb/devio.c71
-rw-r--r--drivers/usb/dsbr100.c2
-rw-r--r--drivers/usb/hpusbscsi.c35
-rw-r--r--drivers/usb/hpusbscsi.h4
-rw-r--r--drivers/usb/inode.c13
-rw-r--r--drivers/usb/microtek.c15
-rw-r--r--drivers/usb/microtek.h2
-rw-r--r--drivers/usb/pegasus.c89
-rw-r--r--drivers/usb/pegasus.h7
-rw-r--r--drivers/usb/scanner.c14
-rw-r--r--drivers/usb/scanner.h2
-rw-r--r--drivers/usb/usb-uhci.c34
-rw-r--r--drivers/usb/usbkbd.c38
-rw-r--r--drivers/usb/usbmouse.c19
-rw-r--r--drivers/usb/vicam.c15
-rw-r--r--drivers/usb/vicam.h2
-rw-r--r--drivers/usb/wacom.c19
-rw-r--r--drivers/video/Config.in15
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/S3triofb.c2
-rw-r--r--drivers/video/acornfb.c2
-rw-r--r--drivers/video/amifb.c2
-rw-r--r--drivers/video/atafb.c2
-rw-r--r--drivers/video/aty128fb.c2
-rw-r--r--drivers/video/chipsfb.c2
-rw-r--r--drivers/video/clgenfb.c2
-rw-r--r--drivers/video/controlfb.c2
-rw-r--r--drivers/video/cyberfb.c2
-rw-r--r--drivers/video/dn_cfb4.c2
-rw-r--r--drivers/video/dn_cfb8.c2
-rw-r--r--drivers/video/dnfb.c2
-rw-r--r--drivers/video/epson1355fb.c2
-rw-r--r--drivers/video/fbmem.c5
-rw-r--r--drivers/video/fm2fb.c2
-rw-r--r--drivers/video/g364fb.c2
-rw-r--r--drivers/video/hgafb.c2
-rw-r--r--drivers/video/hitfb.c2
-rw-r--r--drivers/video/hpfb.c2
-rw-r--r--drivers/video/igafb.c2
-rw-r--r--drivers/video/imsttfb.c2
-rw-r--r--drivers/video/macfb.c2
-rw-r--r--drivers/video/maxinefb.c2
-rw-r--r--drivers/video/neofb.c2421
-rw-r--r--drivers/video/neofb.h294
-rw-r--r--drivers/video/offb.c2
-rw-r--r--drivers/video/platinumfb.c2
-rw-r--r--drivers/video/pmag-ba-fb.c2
-rw-r--r--drivers/video/pmagb-b-fb.c2
-rw-r--r--drivers/video/pvr2fb.c2
-rw-r--r--drivers/video/q40fb.c2
-rw-r--r--drivers/video/radeonfb.c2
-rw-r--r--drivers/video/retz3fb.c2
-rw-r--r--drivers/video/sgivwfb.c2
-rw-r--r--drivers/video/skeletonfb.c2
-rw-r--r--drivers/video/sstfb.c2
-rw-r--r--drivers/video/stifb.c2
-rw-r--r--drivers/video/sun3fb.c2
-rw-r--r--drivers/video/tdfxfb.c2
-rw-r--r--drivers/video/tgafb.c2
-rw-r--r--drivers/video/tx3912fb.c2
-rw-r--r--drivers/video/valkyriefb.c2
-rw-r--r--drivers/video/vfb.c2
-rw-r--r--drivers/video/vga16fb.c2
-rw-r--r--drivers/video/virgefb.c2
-rw-r--r--drivers/zorro/zorro.c1
-rw-r--r--fs/Config.in5
-rw-r--r--fs/coda/inode.c4
-rw-r--r--fs/driverfs/inode.c112
-rw-r--r--fs/minix/bitmap.c1
-rw-r--r--fs/minix/inode.c69
-rw-r--r--fs/minix/itree_v1.c2
-rw-r--r--fs/minix/itree_v2.c2
-rw-r--r--fs/namespace.c25
-rw-r--r--fs/ncpfs/inode.c63
-rw-r--r--fs/reiserfs/bitmap.c60
-rw-r--r--fs/reiserfs/buffer2.c8
-rw-r--r--fs/reiserfs/file.c6
-rw-r--r--fs/reiserfs/inode.c32
-rw-r--r--fs/reiserfs/ioctl.c6
-rw-r--r--fs/reiserfs/journal.c12
-rw-r--r--fs/reiserfs/stree.c6
-rw-r--r--fs/reiserfs/super.c69
-rw-r--r--fs/reiserfs/tail_conversion.c4
-rw-r--r--fs/super.c6
-rw-r--r--fs/sysv/ChangeLog30
-rw-r--r--fs/sysv/dir.c4
-rw-r--r--fs/sysv/ialloc.c3
-rw-r--r--fs/sysv/inode.c61
-rw-r--r--fs/sysv/itree.c4
-rw-r--r--fs/sysv/super.c27
-rw-r--r--fs/sysv/symlink.c5
-rw-r--r--fs/udf/ialloc.c5
-rw-r--r--fs/udf/inode.c14
-rw-r--r--fs/udf/super.c58
-rw-r--r--fs/udf/udf_i.h6
-rw-r--r--include/asm-i386/mmu_context.h9
-rw-r--r--include/linux/device.h12
-rw-r--r--include/linux/driverfs_fs.h18
-rw-r--r--include/linux/fb.h12
-rw-r--r--include/linux/fs.h14
-rw-r--r--include/linux/init.h32
-rw-r--r--include/linux/minix_fs.h7
-rw-r--r--include/linux/minix_fs_i.h1
-rw-r--r--include/linux/ncp_fs.h6
-rw-r--r--include/linux/ncp_fs_i.h12
-rw-r--r--include/linux/pci.h6
-rw-r--r--include/linux/reiserfs_fs.h21
-rw-r--r--include/linux/reiserfs_fs_i.h1
-rw-r--r--include/linux/sysv_fs.h9
-rw-r--r--include/linux/sysv_fs_i.h1
-rw-r--r--include/linux/udf_fs_i.h1
-rw-r--r--init/main.c68
-rw-r--r--kernel/device.c428
-rw-r--r--net/irda/af_irda.c9
157 files changed, 4425 insertions, 1218 deletions
diff --git a/Documentation/Configure.help b/Documentation/Configure.help
index 63b6f6056..59657c82a 100644
--- a/Documentation/Configure.help
+++ b/Documentation/Configure.help
@@ -4166,6 +4166,16 @@ CONFIG_FB_L7200
This driver supports the L7200 Color LCD.
Say Y if you want graphics support.
+NeoMagic display support (EXPERIMENTAL)
+CONFIG_FB_NEOMAGIC
+ This driver supports notebooks with NeoMagic PCI chips.
+ Say Y if you have such a graphics card.
+
+ The driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want). The
+ module will be called neofb.o. If you want to compile it as a
+ module, say M here and read Documentation/modules.txt.
+
PowerMac "control" frame buffer device support
CONFIG_FB_CONTROL
This driver supports a frame buffer for the graphics adapter in the
diff --git a/Makefile b/Makefile
index e4a9258e6..9b4a307d9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 3
-EXTRAVERSION =-pre3
+EXTRAVERSION =-pre4
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff --git a/arch/alpha/vmlinux.lds.in b/arch/alpha/vmlinux.lds.in
index ba7ad8f9f..ee7a7e245 100644
--- a/arch/alpha/vmlinux.lds.in
+++ b/arch/alpha/vmlinux.lds.in
@@ -41,7 +41,15 @@ SECTIONS
. = ALIGN(8);
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(2*8192); /* Align double page for init_task_union */
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index c60ca78c6..63121715e 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -1097,6 +1097,8 @@ void __init ecard_init(void)
ecard_proc_init();
}
+subsys_initcall(ecard_init);
+
EXPORT_SYMBOL(ecard_startfind);
EXPORT_SYMBOL(ecard_find);
EXPORT_SYMBOL(ecard_readchunk);
diff --git a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
index 4581c2a0b..c83777929 100644
--- a/arch/arm/vmlinux-armo.lds.in
+++ b/arch/arm/vmlinux-armo.lds.in
@@ -27,7 +27,13 @@ SECTIONS
*(.setup.init)
__setup_end = .;
__initcall_start = .;
- *(.initcall.init)
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
__initcall_end = .;
. = ALIGN(32768);
__init_end = .;
diff --git a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
index 6585b766d..618d9f28f 100644
--- a/arch/arm/vmlinux-armv.lds.in
+++ b/arch/arm/vmlinux-armv.lds.in
@@ -26,7 +26,13 @@ SECTIONS
*(.setup.init)
__setup_end = .;
__initcall_start = .;
- *(.initcall.init)
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/cris/cris.ld b/arch/cris/cris.ld
index 66e797309..d0d2af1f8 100644
--- a/arch/cris/cris.ld
+++ b/arch/cris/cris.ld
@@ -63,7 +63,13 @@ SECTIONS
__setup_end = .;
.initcall.init : {
__initcall_start = .;
- *(.initcall.init);
+ *(.initcall1.init);
+ *(.initcall2.init);
+ *(.initcall3.init);
+ *(.initcall4.init);
+ *(.initcall5.init);
+ *(.initcall6.init);
+ *(.initcall7.init);
__initcall_end = .;
/* We fill to the next page, so we can discard all init
diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c
index 104ae9e9e..dc7db1cdc 100644
--- a/arch/i386/kernel/mca.c
+++ b/arch/i386/kernel/mca.c
@@ -311,6 +311,8 @@ void __init mca_init(void)
#endif
}
+subsys_initcall(mca_init);
+
/*--------------------------------------------------------------------*/
static void mca_handle_nmi_slot(int slot, int check_flag)
diff --git a/arch/i386/vmlinux.lds b/arch/i386/vmlinux.lds
index ce14066f4..1a7da033d 100644
--- a/arch/i386/vmlinux.lds
+++ b/arch/i386/vmlinux.lds
@@ -48,7 +48,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S
index 727e44ba2..d496ad104 100644
--- a/arch/ia64/vmlinux.lds.S
+++ b/arch/ia64/vmlinux.lds.S
@@ -104,8 +104,16 @@ SECTIONS
{ *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : AT(ADDR(.initcall.init) - PAGE_OFFSET)
- { *(.initcall.init) }
+ .initcall.init : AT(ADDR(.initcall1.init) - PAGE_OFFSET)
+ {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(PAGE_SIZE);
__init_end = .;
diff --git a/arch/m68k/vmlinux-sun3.lds b/arch/m68k/vmlinux-sun3.lds
index 4848631fe..164b11ac4 100644
--- a/arch/m68k/vmlinux-sun3.lds
+++ b/arch/m68k/vmlinux-sun3.lds
@@ -43,7 +43,15 @@ __init_begin = .;
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(8192);
__init_end = .;
diff --git a/arch/m68k/vmlinux.lds b/arch/m68k/vmlinux.lds
index f24a564db..3b9eb25b5 100644
--- a/arch/m68k/vmlinux.lds
+++ b/arch/m68k/vmlinux.lds
@@ -47,7 +47,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(8192);
__init_end = .;
diff --git a/arch/mips/ld.script.in b/arch/mips/ld.script.in
index b8cbfd6e6..72151b124 100644
--- a/arch/mips/ld.script.in
+++ b/arch/mips/ld.script.in
@@ -44,7 +44,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(4096); /* Align double page for init_task_union */
__init_end = .;
diff --git a/arch/mips64/ld.script.elf32.S b/arch/mips64/ld.script.elf32.S
index 3a00edf0a..4ffd13a3b 100644
--- a/arch/mips64/ld.script.elf32.S
+++ b/arch/mips64/ld.script.elf32.S
@@ -40,7 +40,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(4096); /* Align double page for init_task_union */
__init_end = .;
diff --git a/arch/mips64/ld.script.elf64 b/arch/mips64/ld.script.elf64
index d7c3c9453..5b3554371 100644
--- a/arch/mips64/ld.script.elf64
+++ b/arch/mips64/ld.script.elf64
@@ -49,7 +49,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(4096); /* Align double page for init_task_union */
__init_end = .;
diff --git a/arch/parisc/vmlinux.lds b/arch/parisc/vmlinux.lds
index b06a86f16..77ed20596 100644
--- a/arch/parisc/vmlinux.lds
+++ b/arch/parisc/vmlinux.lds
@@ -51,7 +51,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
__init_end = .;
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 7d0fd4246..a8765201c 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -535,6 +535,8 @@ void __init ppc_init(void)
}
}
+subsys_initcall(ppc_init);
+
/* Warning, IO base is not yet inited */
void __init setup_arch(char **cmdline_p)
{
diff --git a/arch/ppc/vmlinux.lds b/arch/ppc/vmlinux.lds
index 564c95485..3549b03f4 100644
--- a/arch/ppc/vmlinux.lds
+++ b/arch/ppc/vmlinux.lds
@@ -94,7 +94,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/s390/vmlinux-shared.lds b/arch/s390/vmlinux-shared.lds
index d42574bf7..4956b7c7e 100644
--- a/arch/s390/vmlinux-shared.lds
+++ b/arch/s390/vmlinux-shared.lds
@@ -55,7 +55,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/s390/vmlinux.lds b/arch/s390/vmlinux.lds
index 2bf285009..1b53d5baf 100644
--- a/arch/s390/vmlinux.lds
+++ b/arch/s390/vmlinux.lds
@@ -53,7 +53,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/s390x/vmlinux-shared.lds b/arch/s390x/vmlinux-shared.lds
index 8eb5b04f4..8f6d74e69 100644
--- a/arch/s390x/vmlinux-shared.lds
+++ b/arch/s390x/vmlinux-shared.lds
@@ -55,7 +55,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/s390x/vmlinux.lds b/arch/s390x/vmlinux.lds
index f8dd0265b..2cc3355c8 100644
--- a/arch/s390x/vmlinux.lds
+++ b/arch/s390x/vmlinux.lds
@@ -53,7 +53,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S
index c8df952e0..fcbc7bd32 100644
--- a/arch/sh/vmlinux.lds.S
+++ b/arch/sh/vmlinux.lds.S
@@ -63,7 +63,15 @@ SECTIONS
.setup.init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
__machvec_start = .;
.machvec.init : { *(.machvec.init) }
diff --git a/arch/sparc/vmlinux.lds b/arch/sparc/vmlinux.lds
index bd177538e..ed00b4f28 100644
--- a/arch/sparc/vmlinux.lds
+++ b/arch/sparc/vmlinux.lds
@@ -45,7 +45,15 @@ SECTIONS
.setup_init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(4096);
__init_end = .;
diff --git a/arch/sparc64/vmlinux.lds b/arch/sparc64/vmlinux.lds
index 343fbee58..a6975bc8b 100644
--- a/arch/sparc64/vmlinux.lds
+++ b/arch/sparc64/vmlinux.lds
@@ -46,7 +46,15 @@ SECTIONS
.setup_init : { *(.setup.init) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : { *(.initcall.init) }
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
__initcall_end = .;
. = ALIGN(8192);
__init_end = .;
diff --git a/drivers/char/joystick/iforce.c b/drivers/char/joystick/iforce.c
index 4998a1a7b..d967c3725 100644
--- a/drivers/char/joystick/iforce.c
+++ b/drivers/char/joystick/iforce.c
@@ -133,7 +133,7 @@ struct iforce {
#endif
#ifdef IFORCE_USB
struct usb_device *usbdev; /* USB transfer */
- struct urb irq, out, ctrl;
+ struct urb *irq, *out, *ctrl;
struct usb_ctrlrequest dr;
#endif
/* Force Feedback */
@@ -196,28 +196,28 @@ static void send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
DECLARE_WAITQUEUE(wait, current);
int timeout = HZ; /* 1 second */
- memcpy(iforce->out.transfer_buffer + 1, data, LO(cmd));
- ((char*)iforce->out.transfer_buffer)[0] = HI(cmd);
- iforce->out.transfer_buffer_length = LO(cmd) + 2;
- iforce->out.dev = iforce->usbdev;
+ memcpy(iforce->out->transfer_buffer + 1, data, LO(cmd));
+ ((char*)iforce->out->transfer_buffer)[0] = HI(cmd);
+ iforce->out->transfer_buffer_length = LO(cmd) + 2;
+ iforce->out->dev = iforce->usbdev;
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&iforce->wait, &wait);
- if (usb_submit_urb(&iforce->out)) {
+ if (usb_submit_urb(iforce->out)) {
set_current_state(TASK_RUNNING);
remove_wait_queue(&iforce->wait, &wait);
return;
}
- while (timeout && iforce->out.status == -EINPROGRESS)
+ while (timeout && iforce->out->status == -EINPROGRESS)
timeout = schedule_timeout(timeout);
set_current_state(TASK_RUNNING);
remove_wait_queue(&iforce->wait, &wait);
if (!timeout)
- usb_unlink_urb(&iforce->out);
+ usb_unlink_urb(iforce->out);
return;
}
@@ -284,25 +284,25 @@ static int get_id_packet(struct iforce *iforce, char *packet)
case IFORCE_USB:
iforce->dr.bRequest = packet[0];
- iforce->ctrl.dev = iforce->usbdev;
+ iforce->ctrl->dev = iforce->usbdev;
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&iforce->wait, &wait);
- if (usb_submit_urb(&iforce->ctrl)) {
+ if (usb_submit_urb(iforce->ctrl)) {
set_current_state(TASK_RUNNING);
remove_wait_queue(&iforce->wait, &wait);
return -1;
}
- while (timeout && iforce->ctrl.status == -EINPROGRESS)
+ while (timeout && iforce->ctrl->status == -EINPROGRESS)
timeout = schedule_timeout(timeout);
set_current_state(TASK_RUNNING);
remove_wait_queue(&iforce->wait, &wait);
if (!timeout) {
- usb_unlink_urb(&iforce->ctrl);
+ usb_unlink_urb(iforce->ctrl);
return -1;
}
@@ -344,8 +344,8 @@ static int iforce_open(struct input_dev *dev)
case IFORCE_USB:
if (iforce->open++)
break;
- iforce->irq.dev = iforce->usbdev;
- if (usb_submit_urb(&iforce->irq))
+ iforce->irq->dev = iforce->usbdev;
+ if (usb_submit_urb(iforce->irq))
return -EIO;
break;
#endif
@@ -361,7 +361,7 @@ static void iforce_close(struct input_dev *dev)
#ifdef IFORCE_USB
case IFORCE_USB:
if (!--iforce->open)
- usb_unlink_urb(&iforce->irq);
+ usb_unlink_urb(iforce->irq);
break;
#endif
}
@@ -1024,6 +1024,25 @@ static void *iforce_usb_probe(struct usb_device *dev, unsigned int ifnum,
if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL))) return NULL;
memset(iforce, 0, sizeof(struct iforce));
+ iforce->irq = usb_alloc_urb(0);
+ if (!iforce->irq) {
+ kfree(iforce);
+ return NULL;
+ }
+ iforce->out = usb_alloc_urb(0);
+ if (!iforce->out) {
+ usb_free_urb(iforce->irq);
+ kfree(iforce);
+ return NULL;
+ }
+ iforce->ctrl = usb_alloc_urb(0);
+ if (!iforce->ctrl) {
+ usb_free_urb(iforce->out);
+ usb_free_urb(iforce->irq);
+ kfree(iforce);
+ return NULL;
+ }
+
iforce->bus = IFORCE_USB;
iforce->usbdev = dev;
@@ -1031,16 +1050,19 @@ static void *iforce_usb_probe(struct usb_device *dev, unsigned int ifnum,
iforce->dr.wIndex = 0;
iforce->dr.wLength = 16;
- FILL_INT_URB(&iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress),
+ FILL_INT_URB(iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress),
iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval);
- FILL_BULK_URB(&iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress),
+ FILL_BULK_URB(iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress),
iforce + 1, 32, iforce_usb_out, iforce);
- FILL_CONTROL_URB(&iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
+ FILL_CONTROL_URB(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
(void*) &iforce->dr, iforce->edata, 16, iforce_usb_ctrl, iforce);
if (iforce_init_device(iforce)) {
+ usb_free_urb(iforce->ctrl);
+ usb_free_urb(iforce->out);
+ usb_free_urb(iforce->irq);
kfree(iforce);
return NULL;
}
@@ -1055,8 +1077,11 @@ static void *iforce_usb_probe(struct usb_device *dev, unsigned int ifnum,
static void iforce_usb_disconnect(struct usb_device *dev, void *ptr)
{
struct iforce *iforce = ptr;
- usb_unlink_urb(&iforce->irq);
+ usb_unlink_urb(iforce->irq);
input_unregister_device(&iforce->dev);
+ usb_free_urb(iforce->ctrl);
+ usb_free_urb(iforce->out);
+ usb_free_urb(iforce->irq);
kfree(iforce);
}
diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c
index bf8468cfa..2ddffd21d 100644
--- a/drivers/dio/dio.c
+++ b/drivers/dio/dio.c
@@ -208,6 +208,8 @@ void __init dio_init(void)
}
}
+subsys_initcall(dio_init);
+
/* Bear in mind that this is called in the very early stages of initialisation
* in order to get the virtual address of the serial port for the console...
*/
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 735c0d17e..766376671 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -1039,3 +1039,5 @@ void __init nubus_init(void)
nubus_proc_init();
#endif
}
+
+subsys_initcall(nubus_init);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 471ae4bb3..03ce2466b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1064,6 +1064,7 @@ static struct pci_bus * __devinit pci_alloc_bus(void)
memset(b, 0, sizeof(*b));
INIT_LIST_HEAD(&b->children);
INIT_LIST_HEAD(&b->devices);
+ iobus_init(&b->iobus);
}
return b;
}
@@ -1085,6 +1086,13 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de
child->ops = parent->ops;
child->sysdata = parent->sysdata;
+ /* init generic fields */
+ child->iobus.self = &dev->dev;
+ child->iobus.parent = &parent->iobus;
+ dev->dev.subordinate = &child->iobus;
+
+ strcpy(child->iobus.name,dev->dev.name);
+
/*
* Set up the primary, secondary and subordinate
* bus numbers.
@@ -1180,6 +1188,7 @@ static int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev,
pci_write_config_word(dev, PCI_COMMAND, cr);
}
sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
+
return max;
}
@@ -1288,13 +1297,22 @@ struct pci_dev * __devinit pci_scan_device(struct pci_dev *temp)
dev->vendor = l & 0xffff;
dev->device = (l >> 16) & 0xffff;
+ /* make sure generic fields are setup properly */
+ device_init_dev(&dev->dev);
+
/* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
set this higher, assuming the system even supports it. */
dev->dma_mask = 0xffffffff;
if (pci_setup_device(dev) < 0) {
kfree(dev);
- dev = NULL;
+ return NULL;
}
+
+ /* now put in global tree */
+ strcpy(dev->dev.name,dev->name);
+ strcpy(dev->dev.bus_id,dev->slot_name);
+
+ device_register(&dev->dev);
return dev;
}
@@ -1345,10 +1363,17 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
DBG("Scanning bus %02x\n", bus->number);
max = bus->secondary;
+ /* we should know for sure what the bus number is, so set the bus ID
+ * for the bus and make sure it's registered in the device tree */
+ sprintf(bus->iobus.bus_id,"pci%d",bus->number);
+ iobus_register(&bus->iobus);
+
/* Create a device template */
memset(&dev0, 0, sizeof(dev0));
+ device_init_dev(&dev0.dev);
dev0.bus = bus;
dev0.sysdata = bus->sysdata;
+ dev0.dev.parent = &bus->iobus;
/* Go find them, Rover! */
for (devfn = 0; devfn < 0x100; devfn += 8) {
@@ -1403,8 +1428,14 @@ struct pci_bus * __devinit pci_alloc_primary_bus(int bus)
}
b = pci_alloc_bus();
+ if (!b)
+ return NULL;
list_add_tail(&b->node, &pci_root_buses);
+ sprintf(b->iobus.bus_id,"pci%d",bus);
+ strcpy(b->iobus.name,"Host/PCI Bridge");
+ iobus_register(&b->iobus);
+
b->number = b->secondary = bus;
b->resource[0] = &ioport_resource;
b->resource[1] = &iomem_resource;
@@ -1929,7 +1960,7 @@ pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma)
}
-void __devinit pci_init(void)
+static int __devinit pci_init(void)
{
struct pci_dev *dev;
@@ -1942,6 +1973,7 @@ void __devinit pci_init(void)
#ifdef CONFIG_PM
pm_register(PM_PCI_DEV, 0, pci_pm_callback);
#endif
+ return 0;
}
static int __devinit pci_setup(char *str)
@@ -1959,6 +1991,8 @@ static int __devinit pci_setup(char *str)
return 1;
}
+subsys_initcall(pci_init);
+
__setup("pci=", pci_setup);
EXPORT_SYMBOL(pci_read_config_byte);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index d27aa6f63..d843e9e4f 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -966,12 +966,9 @@ int __init init_pcmcia_ds(void)
return 0;
}
-#ifdef MODULE
+late_initcall(init_pcmcia_ds);
-int __init init_module(void)
-{
- return init_pcmcia_ds();
-}
+#ifdef MODULE
void __exit cleanup_module(void)
{
diff --git a/drivers/pnp/isapnp.c b/drivers/pnp/isapnp.c
index 17efd6482..250e8dc4f 100644
--- a/drivers/pnp/isapnp.c
+++ b/drivers/pnp/isapnp.c
@@ -2356,12 +2356,9 @@ int __init isapnp_init(void)
return 0;
}
-#ifdef MODULE
+subsys_initcall(isapnp_init);
-int init_module(void)
-{
- return isapnp_init();
-}
+#ifdef MODULE
void cleanup_module(void)
{
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index 561d07b73..54b480a3b 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.98 2002-01-05 01:13:43 davem Exp $
+/* $Id: sbus.c,v 1.99 2002-01-24 14:07:52 davem Exp $
* sbus.c: SBus support routines.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -509,3 +509,5 @@ void __init sbus_init(void)
}
#endif
}
+
+subsys_initcall(sbus_init);
diff --git a/drivers/scsi/README.st b/drivers/scsi/README.st
index 1fa617468..e06a21597 100644
--- a/drivers/scsi/README.st
+++ b/drivers/scsi/README.st
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
The driver is currently maintained by Kai M{kisara (email
Kai.Makisara@metla.fi)
-Last modified: Thu Nov 1 22:41:59 2001 by makisara@kai.makisara.local
+Last modified: Tue Jan 22 21:08:57 2002 by makisara
BASICS
@@ -86,6 +86,11 @@ returning zero bytes for two consecutive reads.
The compile options are defined in the file linux/drivers/scsi/st_options.h.
+4. If the open option O_NONBLOCK is used, open succeeds even if the
+drive is not ready. If O_NONBLOCK is not used, the driver waits for
+the drive to become ready. If this does not happen in ST_BLOCK_SECONDS
+seconds, open fails with the errno value EIO.
+
BSD AND SYS V SEMANTICS
@@ -327,12 +332,19 @@ MTSETDRVBUFFER
0xffffff means that the default is not used any more.
MT_ST_DEF_DENSITY
MT_ST_DEF_DRVBUFFER
+ Used to set or clear the density (8 bits), and drive buffer
+ state (3 bits). If the value is MT_ST_CLEAR_DEFAULT
+ (0xfffff) the default will not be used any more. Otherwise
+ the lowermost bits of the value contain the new value of
+ the parameter.
MT_ST_DEF_COMPRESSION
- Used to set or clear the density (8 bits), drive buffer
- state (3 bits), and compression (single bit). If the value is
- MT_ST_CLEAR_DEFAULT (0xfffff), the default will not be used
- any more. Otherwise the lower-most bits of the value contain
- the new value of the parameter.
+ The compression default will not be used if the value of
+ the lowermost byte is 0xff. Otherwise the lowermost bit
+ contains the new default. If the bits 8-15 are set to a
+ non-zero number, and this number is not 0xff, the number is
+ used as the compression algorithm. The value
+ MT_ST_CLEAR_DEFAULT can be used to clear the compression
+ default.
MT_ST_SET_TIMEOUT
Set the normal timeout in seconds for this device. The
default is 900 seconds (15 minutes). The timeout should be
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index a8292a04e..dde07870e 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -9,19 +9,16 @@
Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
Michael Schaefer, J"org Weule, and Eric Youngdale.
- Copyright 1992 - 2001 Kai Makisara
+ Copyright 1992 - 2002 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Sat Nov 3 19:30:55 2001 by makisara@kai.makisara.local
+ Last modified: Wed Jan 23 20:22:42 2002 by makisara
Some small formal changes - aeb, 950809
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
-
- Reminder: write_lock_irqsave() can be replaced by write_lock() when the old SCSI
- error handling will be discarded.
*/
-static char *verstr = "20011103";
+static char *verstr = "20020123";
#include <linux/module.h>
@@ -160,21 +157,19 @@ static void normalize_buffer(ST_buffer *);
static int append_to_buffer(const char *, ST_buffer *, int);
static int from_buffer(ST_buffer *, char *, int);
-static int st_init(void);
static int st_attach(Scsi_Device *);
static int st_detect(Scsi_Device *);
static void st_detach(Scsi_Device *);
-static struct Scsi_Device_Template st_template =
-{
- name:"tape",
- tag:"st",
- scsi_type:TYPE_TAPE,
- major:SCSI_TAPE_MAJOR,
- detect:st_detect,
- init:st_init,
- attach:st_attach,
- detach:st_detach
+static struct Scsi_Device_Template st_template = {
+ module: THIS_MODULE,
+ name: "tape",
+ tag: "st",
+ scsi_type: TYPE_TAPE,
+ major: SCSI_TAPE_MAJOR,
+ detect: st_detect,
+ attach: st_attach,
+ detach: st_detach
};
static int st_compression(Scsi_Tape *, int);
@@ -239,7 +234,7 @@ static int st_chk_result(Scsi_Tape *STp, Scsi_Request * SRpnt)
return 0;
}
- if (driver_byte(result) & DRIVER_SENSE)
+ if ((driver_byte(result) & DRIVER_MASK) == DRIVER_SENSE)
scode = sense[2] & 0x0f;
else {
sense[0] = 0;
@@ -638,20 +633,96 @@ static int set_mode_densblk(Scsi_Tape * STp, ST_mode * STm)
return 0;
}
+/* Test if the drive is ready. Returns either one of the codes below or a negative system
+ error code. */
+#define CHKRES_READY 0
+#define CHKRES_NEW_SESSION 1
+#define CHKRES_NOT_READY 2
+#define CHKRES_NO_TAPE 3
+
+#define MAX_ATTENTIONS 10
+
+static int test_ready(Scsi_Tape *STp, int do_wait)
+{
+ int attentions, waits, max_wait, scode;
+ int retval = CHKRES_READY, new_session = FALSE;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ Scsi_Request *SRpnt = NULL;
+
+ max_wait = do_wait ? ST_BLOCK_SECONDS : 0;
+
+ for (attentions=waits=0; ; ) {
+ memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
+ cmd[0] = TEST_UNIT_READY;
+ SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
+ STp->long_timeout, MAX_READY_RETRIES, TRUE);
+
+ if (!SRpnt) {
+ retval = (STp->buffer)->syscall_result;
+ break;
+ }
+
+ if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70) {
+
+ scode = (SRpnt->sr_sense_buffer[2] & 0x0f);
+
+ if (scode == UNIT_ATTENTION) { /* New media? */
+ new_session = TRUE;
+ if (attentions < MAX_ATTENTIONS) {
+ attentions++;
+ continue;
+ }
+ else {
+ retval = (-EIO);
+ break;
+ }
+ }
+
+ if (scode == NOT_READY) {
+ if (waits < max_wait) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ if (signal_pending(current)) {
+ retval = (-EINTR);
+ break;
+ }
+ waits++;
+ continue;
+ }
+ else {
+ if ((STp->device)->scsi_level >= SCSI_2 &&
+ SRpnt->sr_sense_buffer[12] == 0x3a) /* Check ASC */
+ retval = CHKRES_NO_TAPE;
+ else
+ retval = CHKRES_NOT_READY;
+ break;
+ }
+ }
+ }
+
+ retval = (STp->buffer)->syscall_result;
+ if (!retval)
+ retval = new_session ? CHKRES_NEW_SESSION : CHKRES_READY;
+ break;
+ }
+
+ if (SRpnt != NULL)
+ scsi_release_request(SRpnt);
+ return retval;
+}
+
+
/* See if the drive is ready and gather information about the tape. Return values:
< 0 negative error code from errno.h
0 drive ready
1 drive not ready (possibly no tape)
*/
-#define CHKRES_READY 0
-#define CHKRES_NOT_READY 1
-
static int check_tape(Scsi_Tape *STp, struct file *filp)
{
- int i, retval, new_session = FALSE;
+ int i, retval, new_session = FALSE, do_wait;
unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning;
unsigned short st_flags = filp->f_flags;
- Scsi_Request *SRpnt;
+ Scsi_Request *SRpnt = NULL;
ST_mode *STm;
ST_partstat *STps;
int dev = TAPE_NR(STp->devt);
@@ -668,32 +739,16 @@ static int check_tape(Scsi_Tape *STp, struct file *filp)
}
STm = &(STp->modes[STp->current_mode]);
- memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
- cmd[0] = TEST_UNIT_READY;
-
saved_cleaning = STp->cleaning_req;
STp->cleaning_req = 0;
- SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->long_timeout,
- MAX_READY_RETRIES, TRUE);
- if (!SRpnt) {
- retval = (STp->buffer)->syscall_result;
- goto err_out;
- }
- if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
- (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
+ do_wait = ((filp->f_flags & O_NONBLOCK) == 0);
+ retval = test_ready(STp, do_wait);
- /* Flush the queued UNIT ATTENTION sense data */
- for (i=0; i < 10; i++) {
- memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
- cmd[0] = TEST_UNIT_READY;
- SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
- STp->long_timeout, MAX_READY_RETRIES, TRUE);
- if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
- (SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
- break;
- }
+ if (retval < 0)
+ goto err_out;
+ if (retval == CHKRES_NEW_SESSION) {
(STp->device)->was_reset = 0;
STp->partition = STp->new_partition = 0;
if (STp->can_partitions)
@@ -710,26 +765,23 @@ static int check_tape(Scsi_Tape *STp, struct file *filp)
}
new_session = TRUE;
}
- else
+ else {
STp->cleaning_req |= saved_cleaning;
- if ((STp->buffer)->syscall_result != 0) {
- if ((STp->device)->scsi_level >= SCSI_2 &&
- (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
- (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
- SRpnt->sr_sense_buffer[12] == 0x3a) { /* Check ASC */
- STp->ready = ST_NO_TAPE;
- } else
- STp->ready = ST_NOT_READY;
- scsi_release_request(SRpnt);
- SRpnt = NULL;
- STp->density = 0; /* Clear the erroneous "residue" */
- STp->write_prot = 0;
- STp->block_size = 0;
- STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
- STp->partition = STp->new_partition = 0;
- STp->door_locked = ST_UNLOCKED;
- return CHKRES_NOT_READY;
+ if (retval == CHKRES_NOT_READY || retval == CHKRES_NO_TAPE) {
+ if (retval == CHKRES_NO_TAPE)
+ STp->ready = ST_NO_TAPE;
+ else
+ STp->ready = ST_NOT_READY;
+
+ STp->density = 0; /* Clear the erroneous "residue" */
+ STp->write_prot = 0;
+ STp->block_size = 0;
+ STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
+ STp->partition = STp->new_partition = 0;
+ STp->door_locked = ST_UNLOCKED;
+ return CHKRES_NOT_READY;
+ }
}
if (STp->omit_blklims)
@@ -740,6 +792,10 @@ static int check_tape(Scsi_Tape *STp, struct file *filp)
SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, SCSI_DATA_READ, STp->timeout,
MAX_READY_RETRIES, TRUE);
+ if (!SRpnt) {
+ retval = (STp->buffer)->syscall_result;
+ goto err_out;
+ }
if (!SRpnt->sr_result && !SRpnt->sr_sense_buffer[0]) {
STp->max_block = ((STp->buffer)->b_data[1] << 16) |
@@ -763,6 +819,10 @@ static int check_tape(Scsi_Tape *STp, struct file *filp)
SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, SCSI_DATA_READ, STp->timeout,
MAX_READY_RETRIES, TRUE);
+ if (!SRpnt) {
+ retval = (STp->buffer)->syscall_result;
+ goto err_out;
+ }
if ((STp->buffer)->syscall_result != 0) {
DEBC(printk(ST_DEB_MSG "st%d: No Mode Sense.\n", dev));
@@ -862,22 +922,21 @@ static int st_open(struct inode *inode, struct file *filp)
Scsi_Tape *STp;
ST_partstat *STps;
int dev = TAPE_NR(inode->i_rdev);
- unsigned long flags;
- write_lock_irqsave(&st_dev_arr_lock, flags);
+ write_lock(&st_dev_arr_lock);
STp = scsi_tapes[dev];
if (dev >= st_template.dev_max || STp == NULL) {
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
return (-ENXIO);
}
if (STp->in_use) {
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
DEB( printk(ST_DEB_MSG "st%d: Device already in use.\n", dev); )
return (-EBUSY);
}
STp->in_use = 1;
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
STp->rew_at_close = STp->autorew_dev = (minor(inode->i_rdev) & 0x80) == 0;
if (STp->device->host->hostt->module)
@@ -891,7 +950,7 @@ static int st_open(struct inode *inode, struct file *filp)
/* Allocate a buffer for this user */
need_dma_buffer = STp->restr_dma;
- write_lock_irqsave(&st_dev_arr_lock, flags);
+ write_lock(&st_dev_arr_lock);
for (i = 0; i < st_nbr_buffers; i++)
if (!st_buffers[i]->in_use &&
(!need_dma_buffer || st_buffers[i]->dma)) {
@@ -899,7 +958,7 @@ static int st_open(struct inode *inode, struct file *filp)
(STp->buffer)->in_use = 1;
break;
}
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
if (i >= st_nbr_buffers) {
STp->buffer = new_tape_buffer(FALSE, need_dma_buffer, TRUE);
if (STp->buffer == NULL) {
@@ -935,6 +994,11 @@ static int st_open(struct inode *inode, struct file *filp)
retval = check_tape(STp, filp);
if (retval < 0)
goto err_out;
+ if ((filp->f_flags & O_NONBLOCK) == 0 &&
+ retval != CHKRES_READY) {
+ retval = (-EIO);
+ goto err_out;
+ }
return 0;
err_out:
@@ -1076,7 +1140,6 @@ static int st_release(struct inode *inode, struct file *filp)
{
int result = 0;
Scsi_Tape *STp;
- unsigned long flags;
kdev_t devt = inode->i_rdev;
int dev;
@@ -1091,16 +1154,16 @@ static int st_release(struct inode *inode, struct file *filp)
if (STp->buffer != NULL) {
normalize_buffer(STp->buffer);
- write_lock_irqsave(&st_dev_arr_lock, flags);
+ write_lock(&st_dev_arr_lock);
(STp->buffer)->in_use = 0;
STp->buffer = NULL;
}
else {
- write_lock_irqsave(&st_dev_arr_lock, flags);
+ write_lock(&st_dev_arr_lock);
}
STp->in_use = 0;
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
STp->device->access_count--;
if (STp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
@@ -1944,6 +2007,10 @@ static int st_set_options(Scsi_Tape *STp, long options)
STm->default_blksize = value;
printk(KERN_INFO "st%d: Default block size set to %d bytes.\n",
dev, STm->default_blksize);
+ if (STp->ready == ST_READY) {
+ STp->blksize_changed = FALSE;
+ set_mode_densblk(STp, STm);
+ }
}
} else if (code == MT_ST_TIMEOUTS) {
value = (options & ~MT_ST_OPTIONS);
@@ -1979,6 +2046,10 @@ static int st_set_options(Scsi_Tape *STp, long options)
STm->default_density = value & 0xff;
printk(KERN_INFO "st%d: Density default set to %x\n",
dev, STm->default_density);
+ if (STp->ready == ST_READY) {
+ STp->density_changed = FALSE;
+ set_mode_densblk(STp, STm);
+ }
}
} else if (code == MT_ST_DEF_DRVBUFFER) {
if (value == MT_ST_CLEAR_DEFAULT) {
@@ -1990,6 +2061,8 @@ static int st_set_options(Scsi_Tape *STp, long options)
printk(KERN_INFO
"st%d: Drive buffer default set to %x\n",
dev, STp->default_drvbuffer);
+ if (STp->ready == ST_READY)
+ st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer);
}
} else if (code == MT_ST_DEF_COMPRESSION) {
if (value == MT_ST_CLEAR_DEFAULT) {
@@ -1997,9 +2070,20 @@ static int st_set_options(Scsi_Tape *STp, long options)
printk(KERN_INFO
"st%d: Compression default disabled.\n", dev);
} else {
- STm->default_compression = (value & 1 ? ST_YES : ST_NO);
- printk(KERN_INFO "st%d: Compression default set to %x\n",
- dev, (value & 1));
+ if ((value & 0xff00) != 0) {
+ STp->c_algo = (value & 0xff00) >> 8;
+ printk(KERN_INFO "st%d: Compression algorithm set to 0x%x.\n",
+ dev, STp->c_algo);
+ }
+ if ((value & 0xff) != 0xff) {
+ STm->default_compression = (value & 1 ? ST_YES : ST_NO);
+ printk(KERN_INFO "st%d: Compression default set to %x\n",
+ dev, (value & 1));
+ if (STp->ready == ST_READY) {
+ STp->compression_changed = FALSE;
+ st_compression(STp, (STm->default_compression == ST_YES));
+ }
+ }
}
}
} else
@@ -2087,6 +2171,7 @@ static int write_mode_page(Scsi_Tape *STp, int page)
#define COMPRESSION_PAGE_LENGTH 16
#define CP_OFF_DCE_DCC 2
+#define CP_OFF_C_ALGO 7
#define DCE_MASK 0x80
#define DCC_MASK 0x40
@@ -2122,16 +2207,22 @@ static int st_compression(Scsi_Tape * STp, int state)
(b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0)));
/* Check if compression can be changed */
- if ((b_data[mpoffs + 2] & DCC_MASK) == 0) {
+ if ((b_data[mpoffs + CP_OFF_DCE_DCC] & DCC_MASK) == 0) {
DEBC(printk(ST_DEB_MSG "st%d: Compression not supported.\n", dev));
return (-EIO);
}
/* Do the change */
- if (state)
+ if (state) {
b_data[mpoffs + CP_OFF_DCE_DCC] |= DCE_MASK;
- else
+ if (STp->c_algo != 0)
+ b_data[mpoffs + CP_OFF_C_ALGO] = STp->c_algo;
+ }
+ else {
b_data[mpoffs + CP_OFF_DCE_DCC] &= ~DCE_MASK;
+ if (STp->c_algo != 0)
+ b_data[mpoffs + CP_OFF_C_ALGO] = 0; /* no compression */
+ }
retval = write_mode_page(STp, COMPRESSION_PAGE);
if (retval) {
@@ -2171,7 +2262,7 @@ static int do_load_unload(Scsi_Tape *STp, struct file *filp, int load_code)
*/
if (load_code >= 1 + MT_ST_HPLOADER_OFFSET
&& load_code <= 6 + MT_ST_HPLOADER_OFFSET) {
- DEBC(printk(ST_DEB_MSG "st%d: Enhanced %sload slot %2ld.\n",
+ DEBC(printk(ST_DEB_MSG "st%d: Enhanced %sload slot %2d.\n",
dev, (cmd[4]) ? "" : "un",
load_code - MT_ST_HPLOADER_OFFSET));
cmd[3] = load_code - MT_ST_HPLOADER_OFFSET; /* MediaID field of C1553A */
@@ -2202,12 +2293,12 @@ static int do_load_unload(Scsi_Tape *STp, struct file *filp, int load_code)
if (!load_code)
STp->rew_at_close = 0;
- else
+ else {
STp->rew_at_close = STp->autorew_dev;
-
- retval = check_tape(STp, filp);
- if (retval > 0)
- retval = 0;
+ retval = check_tape(STp, filp);
+ if (retval > 0)
+ retval = 0;
+ }
}
else {
STps = &(STp->ps[STp->partition]);
@@ -3286,7 +3377,6 @@ static ST_buffer *
new_tape_buffer(int from_initialization, int need_dma, int in_use)
{
int i, priority, b_size, order, got = 0, segs = 0;
- unsigned long flags;
ST_buffer *tb;
read_lock(&st_dev_arr_lock);
@@ -3378,9 +3468,9 @@ static ST_buffer *
tb->buffer_size = got;
tb->writing = 0;
- write_lock_irqsave(&st_dev_arr_lock, flags);
+ write_lock(&st_dev_arr_lock);
st_buffers[st_nbr_buffers++] = tb;
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
return tb;
}
@@ -3607,7 +3697,6 @@ static int st_attach(Scsi_Device * SDp)
ST_mode *STm;
ST_partstat *STps;
int i, mode, target_nbr, dev_num;
- unsigned long flags = 0;
char *stp;
if (SDp->type != TYPE_TAPE)
@@ -3620,7 +3709,7 @@ static int st_attach(Scsi_Device * SDp)
return 1;
}
- write_lock_irqsave(&st_dev_arr_lock, flags);
+ write_lock(&st_dev_arr_lock);
if (st_template.nr_dev >= st_template.dev_max) {
Scsi_Tape **tmp_da;
ST_buffer **tmp_ba;
@@ -3631,7 +3720,7 @@ static int st_attach(Scsi_Device * SDp)
tmp_dev_max = ST_MAX_TAPES;
if (tmp_dev_max <= st_template.nr_dev) {
SDp->attached--;
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
printk(KERN_ERR "st: Too many tape devices (max. %d).\n",
ST_MAX_TAPES);
return 1;
@@ -3645,7 +3734,7 @@ static int st_attach(Scsi_Device * SDp)
if (tmp_ba != NULL)
kfree(tmp_ba);
SDp->attached--;
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
printk(KERN_ERR "st: Can't extend device array.\n");
return 1;
}
@@ -3678,7 +3767,7 @@ static int st_attach(Scsi_Device * SDp)
tpnt = kmalloc(sizeof(Scsi_Tape), GFP_ATOMIC);
if (tpnt == NULL) {
SDp->attached--;
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
printk(KERN_ERR "st: Can't allocate device descriptor.\n");
return 1;
}
@@ -3766,7 +3855,7 @@ static int st_attach(Scsi_Device * SDp)
init_MUTEX(&tpnt->lock);
st_template.nr_dev++;
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
printk(KERN_WARNING
"Attached scsi tape st%d at scsi%d, channel %d, id %d, lun %d\n",
dev_num, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
@@ -3794,45 +3883,12 @@ static int st_detect(Scsi_Device * SDp)
return 1;
}
-static int st_registered = 0;
-
-/* Driver initialization (not __init because may be called later) */
-static int st_init()
-{
- unsigned long flags;
-
- if (st_template.dev_noticed == 0 || st_registered)
- return 0;
-
- printk(KERN_INFO
- "st: Version %s, bufsize %d, wrt %d, max init. bufs %d, s/g segs %d\n",
- verstr, st_buffer_size, st_write_threshold, st_max_buffers, st_max_sg_segs);
-
- write_lock_irqsave(&st_dev_arr_lock, flags);
- if (!st_registered) {
- if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops)) {
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
- printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",
- MAJOR_NR);
- return 1;
- }
- st_registered++;
- }
-
- st_template.dev_max = 0;
- st_nbr_buffers = 0;
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
-
- return 0;
-}
-
static void st_detach(Scsi_Device * SDp)
{
Scsi_Tape *tpnt;
int i, mode;
- unsigned long flags;
- write_lock_irqsave(&st_dev_arr_lock, flags);
+ write_lock(&st_dev_arr_lock);
for (i = 0; i < st_template.dev_max; i++) {
tpnt = scsi_tapes[i];
if (tpnt != NULL && tpnt->device == SDp) {
@@ -3848,22 +3904,30 @@ static void st_detach(Scsi_Device * SDp)
SDp->attached--;
st_template.nr_dev--;
st_template.dev_noticed--;
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
return;
}
}
- write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ write_unlock(&st_dev_arr_lock);
return;
}
-
static int __init init_st(void)
{
validate_options();
- st_template.module = THIS_MODULE;
- return scsi_register_device(&st_template);
+ printk(KERN_INFO
+ "st: Version %s, bufsize %d, wrt %d, "
+ "max init. bufs %d, s/g segs %d\n",
+ verstr, st_buffer_size, st_write_threshold,
+ st_max_buffers, st_max_sg_segs);
+
+ if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0)
+ return scsi_register_device(&st_template);
+
+ printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", MAJOR_NR);
+ return 1;
}
static void __exit exit_st(void)
@@ -3872,7 +3936,6 @@ static void __exit exit_st(void)
scsi_unregister_device(&st_template);
devfs_unregister_chrdev(SCSI_TAPE_MAJOR, "st");
- st_registered--;
if (scsi_tapes != NULL) {
for (i=0; i < st_template.dev_max; ++i)
if (scsi_tapes[i])
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 2ffb381fc..7fcd055b5 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -83,6 +83,7 @@ typedef struct {
unsigned char cln_sense_value;
unsigned char cln_sense_mask;
unsigned char use_pf; /* Set Page Format bit in all mode selects? */
+ unsigned char c_algo; /* compression algorithm */
int tape_type;
int write_threshold;
int timeout; /* timeout for normal commands */
diff --git a/drivers/scsi/st_options.h b/drivers/scsi/st_options.h
index 846e29917..325bd3cb5 100644
--- a/drivers/scsi/st_options.h
+++ b/drivers/scsi/st_options.h
@@ -3,7 +3,7 @@
Copyright 1995-2000 Kai Makisara.
- Last modified: Sat Apr 22 14:47:02 2000 by makisara@kai.makisara.local
+ Last modified: Tue Jan 22 21:52:34 2002 by makisara
*/
#ifndef _ST_OPTIONS_H
@@ -99,5 +99,7 @@
The default is BSD semantics. */
#define ST_SYSV 0
+/* Time to wait for the drive to become ready if blocking open */
+#define ST_BLOCK_SECONDS 120
#endif
diff --git a/drivers/sound/cmpci.c b/drivers/sound/cmpci.c
index 35574d752..0b7fefb36 100644
--- a/drivers/sound/cmpci.c
+++ b/drivers/sound/cmpci.c
@@ -1440,7 +1440,7 @@ static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg)
static int cm_open_mixdev(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct cm_state *s = devs;
while (s && s->dev_mixer != minor)
@@ -2190,7 +2190,7 @@ static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
static int cm_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct cm_state *s = devs;
unsigned char fmtm = ~0, fmts = 0;
@@ -2445,7 +2445,7 @@ static unsigned int cm_midi_poll(struct file *file, struct poll_table_struct *wa
static int cm_midi_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct cm_state *s = devs;
unsigned long flags;
@@ -2662,7 +2662,7 @@ static int cm_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int cm
static int cm_dmfm_open(struct inode *inode, struct file *file)
{
- int minor = MINOR(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct cm_state *s = devs;
while (s && s->dev_dmfm != minor)
@@ -2861,7 +2861,9 @@ void initialize_chip(struct pci_dev *pcidev)
struct cm_state *s;
mm_segment_t fs;
int i, val;
+#if defined(CONFIG_SOUND_CMPCI_MIDI) || defined(CONFIG_SOUND_CMPCI_FM)
unsigned char reg_mask = 0;
+#endif
struct {
unsigned short deviceid;
char *devicename;
diff --git a/drivers/sound/ymfpci.c b/drivers/sound/ymfpci.c
index 209c40f61..0b372c810 100644
--- a/drivers/sound/ymfpci.c
+++ b/drivers/sound/ymfpci.c
@@ -832,7 +832,14 @@ static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
u32 lpfK = ymfpci_calc_lpfK(rate);
ymfpci_playback_bank_t *bank;
int nbank;
- unsigned le_0x40000000 = cpu_to_le32(0x40000000);
+
+ /*
+ * The gain is a floating point number. According to the manual,
+ * bit 31 indicates a sign bit, bit 30 indicates an integer part,
+ * and bits [29:15] indicate a decimal fraction part. Thus,
+ * for a gain of 1.0 the constant of 0x40000000 is loaded.
+ */
+ unsigned default_gain = cpu_to_le32(0x40000000);
format = (stereo ? 0x00010000 : 0) | (w_16 ? 0 : 0x80000000);
if (stereo)
@@ -847,7 +854,7 @@ static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
bank->loop_start = 0;
bank->loop_end = cpu_to_le32(end);
bank->loop_frac = 0;
- bank->eg_gain_end = le_0x40000000;
+ bank->eg_gain_end = default_gain;
bank->lpfQ = cpu_to_le32(lpfQ);
bank->status = 0;
bank->num_of_frames = 0;
@@ -858,7 +865,7 @@ static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
bank->delta_end = cpu_to_le32(delta);
bank->lpfK =
bank->lpfK_end = cpu_to_le32(lpfK);
- bank->eg_gain = le_0x40000000;
+ bank->eg_gain = default_gain;
bank->lpfD1 =
bank->lpfD2 = 0;
@@ -878,31 +885,31 @@ static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
bank->left_gain =
bank->right_gain =
bank->left_gain_end =
- bank->right_gain_end = le_0x40000000;
+ bank->right_gain_end = default_gain;
} else {
bank->eff2_gain =
bank->eff2_gain_end =
bank->eff3_gain =
- bank->eff3_gain_end = le_0x40000000;
+ bank->eff3_gain_end = default_gain;
}
} else {
if (!spdif) {
if ((voice->number & 1) == 0) {
bank->left_gain =
- bank->left_gain_end = le_0x40000000;
+ bank->left_gain_end = default_gain;
} else {
bank->format |= cpu_to_le32(1);
bank->right_gain =
- bank->right_gain_end = le_0x40000000;
+ bank->right_gain_end = default_gain;
}
} else {
if ((voice->number & 1) == 0) {
bank->eff2_gain =
- bank->eff2_gain_end = le_0x40000000;
+ bank->eff2_gain_end = default_gain;
} else {
bank->format |= cpu_to_le32(1);
bank->eff3_gain =
- bank->eff3_gain_end = le_0x40000000;
+ bank->eff3_gain_end = default_gain;
}
}
}
diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c
index 36965ed83..066170aab 100644
--- a/drivers/tc/tc.c
+++ b/drivers/tc/tc.c
@@ -236,6 +236,8 @@ void __init tc_init(void)
}
}
+subsys_initcall(tc_init);
+
EXPORT_SYMBOL(search_tc_card);
EXPORT_SYMBOL(claim_tc_card);
EXPORT_SYMBOL(release_tc_card);
diff --git a/drivers/usb/CDCEther.c b/drivers/usb/CDCEther.c
index f8eda80f0..defae1cd4 100644
--- a/drivers/usb/CDCEther.c
+++ b/drivers/usb/CDCEther.c
@@ -125,14 +125,14 @@ static void read_bulk_callback( struct urb *urb )
goon:
// Prep the USB to wait for another frame
- FILL_BULK_URB( &ether_dev->rx_urb, ether_dev->usb,
+ FILL_BULK_URB( ether_dev->rx_urb, ether_dev->usb,
usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
ether_dev->rx_buff, ether_dev->wMaxSegmentSize,
read_bulk_callback, ether_dev );
// Give this to the USB subsystem so it can tell us
// when more data arrives.
- if ( (res = usb_submit_urb(&ether_dev->rx_urb)) ) {
+ if ( (res = usb_submit_urb(ether_dev->rx_urb)) ) {
warn( __FUNCTION__ " failed submint rx_urb %d", res);
}
@@ -259,8 +259,8 @@ static void CDCEther_tx_timeout( struct net_device *net )
warn("%s: Tx timed out.", net->name);
// Tear the waiting frame off the list
- ether_dev->tx_urb.transfer_flags |= USB_ASYNC_UNLINK;
- usb_unlink_urb( &ether_dev->tx_urb );
+ ether_dev->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
+ usb_unlink_urb( ether_dev->tx_urb );
// Update statistics
ether_dev->stats.tx_errors++;
@@ -293,16 +293,16 @@ static int CDCEther_start_xmit( struct sk_buff *skb, struct net_device *net )
memcpy(ether_dev->tx_buff, skb->data, skb->len);
// Fill in the URB for shipping it out.
- FILL_BULK_URB( &ether_dev->tx_urb, ether_dev->usb,
+ FILL_BULK_URB( ether_dev->tx_urb, ether_dev->usb,
usb_sndbulkpipe(ether_dev->usb, ether_dev->data_ep_out),
ether_dev->tx_buff, ether_dev->wMaxSegmentSize,
write_bulk_callback, ether_dev );
// Tell the URB how much it will be transporting today
- ether_dev->tx_urb.transfer_buffer_length = count;
+ ether_dev->tx_urb->transfer_buffer_length = count;
// Send the URB on its merry way.
- if ((res = usb_submit_urb(&ether_dev->tx_urb))) {
+ if ((res = usb_submit_urb(ether_dev->tx_urb))) {
// Hmm... It didn't go. Tell someone...
warn("failed tx_urb %d", res);
// update some stats...
@@ -344,13 +344,13 @@ static int CDCEther_open(struct net_device *net)
}
// Prep a receive URB
- FILL_BULK_URB( &ether_dev->rx_urb, ether_dev->usb,
+ FILL_BULK_URB( ether_dev->rx_urb, ether_dev->usb,
usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
ether_dev->rx_buff, ether_dev->wMaxSegmentSize,
read_bulk_callback, ether_dev );
// Put it out there so the device can send us stuff
- if ( (res = usb_submit_urb(&ether_dev->rx_urb)) )
+ if ( (res = usb_submit_urb(ether_dev->rx_urb)) )
{
// Hmm... Okay...
warn( __FUNCTION__ " failed rx_urb %d", res );
@@ -383,9 +383,9 @@ static int CDCEther_close( struct net_device *net )
}
// We don't need the URBs anymore.
- usb_unlink_urb( &ether_dev->rx_urb );
- usb_unlink_urb( &ether_dev->tx_urb );
- usb_unlink_urb( &ether_dev->intr_urb );
+ usb_unlink_urb( ether_dev->rx_urb );
+ usb_unlink_urb( ether_dev->tx_urb );
+ usb_unlink_urb( ether_dev->intr_urb );
// That's it. I'm done.
return 0;
@@ -1144,6 +1144,25 @@ static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,
// Zero everything out.
memset(ether_dev, 0, sizeof(ether_dev_t));
+ ether_dev->rx_urb = usb_alloc_urb(0);
+ if (!ether_dev->rx_urb) {
+ kfree(ether_dev);
+ return NULL;
+ }
+ ether_dev->tx_urb = usb_alloc_urb(0);
+ if (!ether_dev->tx_urb) {
+ usb_free_urb(ether_dev->rx_urb);
+ kfree(ether_dev);
+ return NULL;
+ }
+ ether_dev->intr_urb = usb_alloc_urb(0);
+ if (!ether_dev->intr_urb) {
+ usb_free_urb(ether_dev->tx_urb);
+ usb_free_urb(ether_dev->rx_urb);
+ kfree(ether_dev);
+ return NULL;
+ }
+
// Let's see if we can find a configuration we can use.
rc = find_valid_configuration( usb, ether_dev );
if (rc) {
@@ -1290,6 +1309,9 @@ static void CDCEther_disconnect( struct usb_device *usb, void *ptr )
&(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]) );
// No more tied up kernel memory
+ usb_free_urb(ether_dev->intr_urb);
+ usb_free_urb(ether_dev->rx_urb);
+ usb_free_urb(ether_dev->rx_urb);
kfree( ether_dev );
// This does no good, but it looks nice!
diff --git a/drivers/usb/CDCEther.h b/drivers/usb/CDCEther.h
index 068a0147b..e91c2115a 100644
--- a/drivers/usb/CDCEther.h
+++ b/drivers/usb/CDCEther.h
@@ -83,7 +83,7 @@ typedef struct _ether_dev_t {
__u16 wNumberMCFilters;
__u8 bNumberPowerFilters;
int intr_interval;
- struct urb rx_urb, tx_urb, intr_urb;
+ struct urb *rx_urb, *tx_urb, *intr_urb;
unsigned char ALIGN(rx_buff[CDC_ETHER_MAX_MTU]);
unsigned char ALIGN(tx_buff[CDC_ETHER_MAX_MTU]);
unsigned char ALIGN(intr_buff[8]);
diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c
index 281b769fd..a1d114942 100644
--- a/drivers/usb/audio.c
+++ b/drivers/usb/audio.c
@@ -297,12 +297,12 @@ struct usb_audio_state;
#define FLG_CONNECTED 32
struct my_data_urb {
- struct urb urb;
+ struct urb *urb;
struct usb_iso_packet_descriptor isoframe[DESCFRAMES];
};
struct my_sync_urb {
- struct urb urb;
+ struct urb *urb;
struct usb_iso_packet_descriptor isoframe[SYNCFRAMES];
};
@@ -648,27 +648,27 @@ static void usbin_stop(struct usb_audiodev *as)
spin_unlock_irqrestore(&as->lock, flags);
if (notkilled && signal_pending(current)) {
if (i & FLG_URB0RUNNING)
- usb_unlink_urb(&u->durb[0].urb);
+ usb_unlink_urb(u->durb[0].urb);
if (i & FLG_URB1RUNNING)
- usb_unlink_urb(&u->durb[1].urb);
+ usb_unlink_urb(u->durb[1].urb);
if (i & FLG_SYNC0RUNNING)
- usb_unlink_urb(&u->surb[0].urb);
+ usb_unlink_urb(u->surb[0].urb);
if (i & FLG_SYNC1RUNNING)
- usb_unlink_urb(&u->surb[1].urb);
+ usb_unlink_urb(u->surb[1].urb);
notkilled = 0;
}
}
set_current_state(TASK_RUNNING);
- if (u->durb[0].urb.transfer_buffer)
- kfree(u->durb[0].urb.transfer_buffer);
- if (u->durb[1].urb.transfer_buffer)
- kfree(u->durb[1].urb.transfer_buffer);
- if (u->surb[0].urb.transfer_buffer)
- kfree(u->surb[0].urb.transfer_buffer);
- if (u->surb[1].urb.transfer_buffer)
- kfree(u->surb[1].urb.transfer_buffer);
- u->durb[0].urb.transfer_buffer = u->durb[1].urb.transfer_buffer =
- u->surb[0].urb.transfer_buffer = u->surb[1].urb.transfer_buffer = NULL;
+ if (u->durb[0].urb->transfer_buffer)
+ kfree(u->durb[0].urb->transfer_buffer);
+ if (u->durb[1].urb->transfer_buffer)
+ kfree(u->durb[1].urb->transfer_buffer);
+ if (u->surb[0].urb->transfer_buffer)
+ kfree(u->surb[0].urb->transfer_buffer);
+ if (u->surb[1].urb->transfer_buffer)
+ kfree(u->surb[1].urb->transfer_buffer);
+ u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer =
+ u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL;
}
static inline void usbin_release(struct usb_audiodev *as)
@@ -904,9 +904,9 @@ static void usbin_completed(struct urb *urb)
#if 0
printk(KERN_DEBUG "usbin_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
#endif
- if (urb == &u->durb[0].urb)
+ if (urb == u->durb[0].urb)
mask = FLG_URB0RUNNING;
- else if (urb == &u->durb[1].urb)
+ else if (urb == u->durb[1].urb)
mask = FLG_URB1RUNNING;
else {
mask = 0;
@@ -969,9 +969,9 @@ static void usbin_sync_completed(struct urb *urb)
#if 0
printk(KERN_DEBUG "usbin_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
#endif
- if (urb == &u->surb[0].urb)
+ if (urb == u->surb[0].urb)
mask = FLG_SYNC0RUNNING;
- else if (urb == &u->surb[1].urb)
+ else if (urb == u->surb[1].urb)
mask = FLG_SYNC1RUNNING;
else {
mask = 0;
@@ -1017,26 +1017,26 @@ static int usbin_start(struct usb_audiodev *as)
u->phase = 0;
maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format));
bufsz = DESCFRAMES * maxsze;
- if (u->durb[0].urb.transfer_buffer)
- kfree(u->durb[0].urb.transfer_buffer);
- u->durb[0].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
- u->durb[0].urb.transfer_buffer_length = bufsz;
- if (u->durb[1].urb.transfer_buffer)
- kfree(u->durb[1].urb.transfer_buffer);
- u->durb[1].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
- u->durb[1].urb.transfer_buffer_length = bufsz;
+ if (u->durb[0].urb->transfer_buffer)
+ kfree(u->durb[0].urb->transfer_buffer);
+ u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
+ u->durb[0].urb->transfer_buffer_length = bufsz;
+ if (u->durb[1].urb->transfer_buffer)
+ kfree(u->durb[1].urb->transfer_buffer);
+ u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
+ u->durb[1].urb->transfer_buffer_length = bufsz;
if (u->syncpipe) {
- if (u->surb[0].urb.transfer_buffer)
- kfree(u->surb[0].urb.transfer_buffer);
- u->surb[0].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
- u->surb[0].urb.transfer_buffer_length = 3*SYNCFRAMES;
- if (u->surb[1].urb.transfer_buffer)
- kfree(u->surb[1].urb.transfer_buffer);
- u->surb[1].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
- u->surb[1].urb.transfer_buffer_length = 3*SYNCFRAMES;
- }
- if (!u->durb[0].urb.transfer_buffer || !u->durb[1].urb.transfer_buffer ||
- (u->syncpipe && (!u->surb[0].urb.transfer_buffer || !u->surb[1].urb.transfer_buffer))) {
+ if (u->surb[0].urb->transfer_buffer)
+ kfree(u->surb[0].urb->transfer_buffer);
+ u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
+ u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES;
+ if (u->surb[1].urb->transfer_buffer)
+ kfree(u->surb[1].urb->transfer_buffer);
+ u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
+ u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES;
+ }
+ if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer ||
+ (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) {
printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum);
return 0;
}
@@ -1048,7 +1048,7 @@ static int usbin_start(struct usb_audiodev *as)
}
u->flags |= FLG_RUNNING;
if (!(u->flags & FLG_URB0RUNNING)) {
- urb = &u->durb[0].urb;
+ urb = u->durb[0].urb;
urb->dev = dev;
urb->pipe = u->datapipe;
urb->transfer_flags = USB_ISO_ASAP;
@@ -1061,7 +1061,7 @@ static int usbin_start(struct usb_audiodev *as)
u->flags &= ~FLG_RUNNING;
}
if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) {
- urb = &u->durb[1].urb;
+ urb = u->durb[1].urb;
urb->dev = dev;
urb->pipe = u->datapipe;
urb->transfer_flags = USB_ISO_ASAP;
@@ -1075,7 +1075,7 @@ static int usbin_start(struct usb_audiodev *as)
}
if (u->syncpipe) {
if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) {
- urb = &u->surb[0].urb;
+ urb = u->surb[0].urb;
urb->dev = dev;
urb->pipe = u->syncpipe;
urb->transfer_flags = USB_ISO_ASAP;
@@ -1089,7 +1089,7 @@ static int usbin_start(struct usb_audiodev *as)
u->flags &= ~FLG_RUNNING;
}
if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) {
- urb = &u->surb[1].urb;
+ urb = u->surb[1].urb;
urb->dev = dev;
urb->pipe = u->syncpipe;
urb->transfer_flags = USB_ISO_ASAP;
@@ -1125,27 +1125,27 @@ static void usbout_stop(struct usb_audiodev *as)
spin_unlock_irqrestore(&as->lock, flags);
if (notkilled && signal_pending(current)) {
if (i & FLG_URB0RUNNING)
- usb_unlink_urb(&u->durb[0].urb);
+ usb_unlink_urb(u->durb[0].urb);
if (i & FLG_URB1RUNNING)
- usb_unlink_urb(&u->durb[1].urb);
+ usb_unlink_urb(u->durb[1].urb);
if (i & FLG_SYNC0RUNNING)
- usb_unlink_urb(&u->surb[0].urb);
+ usb_unlink_urb(u->surb[0].urb);
if (i & FLG_SYNC1RUNNING)
- usb_unlink_urb(&u->surb[1].urb);
+ usb_unlink_urb(u->surb[1].urb);
notkilled = 0;
}
}
set_current_state(TASK_RUNNING);
- if (u->durb[0].urb.transfer_buffer)
- kfree(u->durb[0].urb.transfer_buffer);
- if (u->durb[1].urb.transfer_buffer)
- kfree(u->durb[1].urb.transfer_buffer);
- if (u->surb[0].urb.transfer_buffer)
- kfree(u->surb[0].urb.transfer_buffer);
- if (u->surb[1].urb.transfer_buffer)
- kfree(u->surb[1].urb.transfer_buffer);
- u->durb[0].urb.transfer_buffer = u->durb[1].urb.transfer_buffer =
- u->surb[0].urb.transfer_buffer = u->surb[1].urb.transfer_buffer = NULL;
+ if (u->durb[0].urb->transfer_buffer)
+ kfree(u->durb[0].urb->transfer_buffer);
+ if (u->durb[1].urb->transfer_buffer)
+ kfree(u->durb[1].urb->transfer_buffer);
+ if (u->surb[0].urb->transfer_buffer)
+ kfree(u->surb[0].urb->transfer_buffer);
+ if (u->surb[1].urb->transfer_buffer)
+ kfree(u->surb[1].urb->transfer_buffer);
+ u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer =
+ u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL;
}
static inline void usbout_release(struct usb_audiodev *as)
@@ -1262,9 +1262,9 @@ static void usbout_completed(struct urb *urb)
#if 0
printk(KERN_DEBUG "usbout_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
#endif
- if (urb == &u->durb[0].urb)
+ if (urb == u->durb[0].urb)
mask = FLG_URB0RUNNING;
- else if (urb == &u->durb[1].urb)
+ else if (urb == u->durb[1].urb)
mask = FLG_URB1RUNNING;
else {
mask = 0;
@@ -1334,9 +1334,9 @@ static void usbout_sync_completed(struct urb *urb)
#if 0
printk(KERN_DEBUG "usbout_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
#endif
- if (urb == &u->surb[0].urb)
+ if (urb == u->surb[0].urb)
mask = FLG_SYNC0RUNNING;
- else if (urb == &u->surb[1].urb)
+ else if (urb == u->surb[1].urb)
mask = FLG_SYNC1RUNNING;
else {
mask = 0;
@@ -1382,26 +1382,26 @@ static int usbout_start(struct usb_audiodev *as)
u->phase = 0;
maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format));
bufsz = DESCFRAMES * maxsze;
- if (u->durb[0].urb.transfer_buffer)
- kfree(u->durb[0].urb.transfer_buffer);
- u->durb[0].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
- u->durb[0].urb.transfer_buffer_length = bufsz;
- if (u->durb[1].urb.transfer_buffer)
- kfree(u->durb[1].urb.transfer_buffer);
- u->durb[1].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
- u->durb[1].urb.transfer_buffer_length = bufsz;
+ if (u->durb[0].urb->transfer_buffer)
+ kfree(u->durb[0].urb->transfer_buffer);
+ u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
+ u->durb[0].urb->transfer_buffer_length = bufsz;
+ if (u->durb[1].urb->transfer_buffer)
+ kfree(u->durb[1].urb->transfer_buffer);
+ u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
+ u->durb[1].urb->transfer_buffer_length = bufsz;
if (u->syncpipe) {
- if (u->surb[0].urb.transfer_buffer)
- kfree(u->surb[0].urb.transfer_buffer);
- u->surb[0].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
- u->surb[0].urb.transfer_buffer_length = 3*SYNCFRAMES;
- if (u->surb[1].urb.transfer_buffer)
- kfree(u->surb[1].urb.transfer_buffer);
- u->surb[1].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
- u->surb[1].urb.transfer_buffer_length = 3*SYNCFRAMES;
- }
- if (!u->durb[0].urb.transfer_buffer || !u->durb[1].urb.transfer_buffer ||
- (u->syncpipe && (!u->surb[0].urb.transfer_buffer || !u->surb[1].urb.transfer_buffer))) {
+ if (u->surb[0].urb->transfer_buffer)
+ kfree(u->surb[0].urb->transfer_buffer);
+ u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
+ u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES;
+ if (u->surb[1].urb->transfer_buffer)
+ kfree(u->surb[1].urb->transfer_buffer);
+ u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
+ u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES;
+ }
+ if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer ||
+ (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) {
printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum);
return 0;
}
@@ -1413,7 +1413,7 @@ static int usbout_start(struct usb_audiodev *as)
}
u->flags |= FLG_RUNNING;
if (!(u->flags & FLG_URB0RUNNING)) {
- urb = &u->durb[0].urb;
+ urb = u->durb[0].urb;
urb->dev = dev;
urb->pipe = u->datapipe;
urb->transfer_flags = USB_ISO_ASAP;
@@ -1426,7 +1426,7 @@ static int usbout_start(struct usb_audiodev *as)
u->flags &= ~FLG_RUNNING;
}
if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) {
- urb = &u->durb[1].urb;
+ urb = u->durb[1].urb;
urb->dev = dev;
urb->pipe = u->datapipe;
urb->transfer_flags = USB_ISO_ASAP;
@@ -1440,7 +1440,7 @@ static int usbout_start(struct usb_audiodev *as)
}
if (u->syncpipe) {
if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) {
- urb = &u->surb[0].urb;
+ urb = u->surb[0].urb;
urb->dev = dev;
urb->pipe = u->syncpipe;
urb->transfer_flags = USB_ISO_ASAP;
@@ -1454,7 +1454,7 @@ static int usbout_start(struct usb_audiodev *as)
u->flags &= ~FLG_RUNNING;
}
if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) {
- urb = &u->surb[1].urb;
+ urb = u->surb[1].urb;
urb->dev = dev;
urb->pipe = u->syncpipe;
urb->transfer_flags = USB_ISO_ASAP;
@@ -1921,6 +1921,14 @@ static void release(struct usb_audio_state *s)
usbout_release(as);
dmabuf_release(&as->usbin.dma);
dmabuf_release(&as->usbout.dma);
+ usb_free_urb(as->usbin.durb[0].urb);
+ usb_free_urb(as->usbin.durb[1].urb);
+ usb_free_urb(as->usbin.surb[0].urb);
+ usb_free_urb(as->usbin.surb[1].urb);
+ usb_free_urb(as->usbout.durb[0].urb);
+ usb_free_urb(as->usbout.durb[1].urb);
+ usb_free_urb(as->usbout.surb[0].urb);
+ usb_free_urb(as->usbout.surb[1].urb);
kfree(as);
}
while (!list_empty(&s->mixerlist)) {
@@ -2821,14 +2829,33 @@ static void usb_audio_parsestreaming(struct usb_audio_state *s, unsigned char *b
init_waitqueue_head(&as->usbin.dma.wait);
init_waitqueue_head(&as->usbout.dma.wait);
spin_lock_init(&as->lock);
- spin_lock_init(&as->usbin.durb[0].urb.lock);
- spin_lock_init(&as->usbin.durb[1].urb.lock);
- spin_lock_init(&as->usbin.surb[0].urb.lock);
- spin_lock_init(&as->usbin.surb[1].urb.lock);
- spin_lock_init(&as->usbout.durb[0].urb.lock);
- spin_lock_init(&as->usbout.durb[1].urb.lock);
- spin_lock_init(&as->usbout.surb[0].urb.lock);
- spin_lock_init(&as->usbout.surb[1].urb.lock);
+ as->usbin.durb[0].urb = usb_alloc_urb(0);
+ as->usbin.durb[1].urb = usb_alloc_urb(0);
+ as->usbin.surb[0].urb = usb_alloc_urb(0);
+ as->usbin.surb[1].urb = usb_alloc_urb(0);
+ as->usbout.durb[0].urb = usb_alloc_urb(0);
+ as->usbout.durb[1].urb = usb_alloc_urb(0);
+ as->usbout.surb[0].urb = usb_alloc_urb(0);
+ as->usbout.surb[1].urb = usb_alloc_urb(0);
+ if ((!as->usbin.durb[0].urb) ||
+ (!as->usbin.durb[1].urb) ||
+ (!as->usbin.surb[0].urb) ||
+ (!as->usbin.surb[1].urb) ||
+ (!as->usbout.durb[0].urb) ||
+ (!as->usbout.durb[1].urb) ||
+ (!as->usbout.surb[0].urb) ||
+ (!as->usbout.surb[1].urb)) {
+ usb_free_urb(as->usbin.durb[0].urb);
+ usb_free_urb(as->usbin.durb[1].urb);
+ usb_free_urb(as->usbin.surb[0].urb);
+ usb_free_urb(as->usbin.surb[1].urb);
+ usb_free_urb(as->usbout.durb[0].urb);
+ usb_free_urb(as->usbout.durb[1].urb);
+ usb_free_urb(as->usbout.surb[0].urb);
+ usb_free_urb(as->usbout.surb[1].urb);
+ kfree(as);
+ return;
+ }
as->state = s;
as->usbin.interface = asifin;
as->usbout.interface = asifout;
@@ -2997,11 +3024,27 @@ static void usb_audio_parsestreaming(struct usb_audio_state *s, unsigned char *b
}
}
if (as->numfmtin == 0 && as->numfmtout == 0) {
+ usb_free_urb(as->usbin.durb[0].urb);
+ usb_free_urb(as->usbin.durb[1].urb);
+ usb_free_urb(as->usbin.surb[0].urb);
+ usb_free_urb(as->usbin.surb[1].urb);
+ usb_free_urb(as->usbout.durb[0].urb);
+ usb_free_urb(as->usbout.durb[1].urb);
+ usb_free_urb(as->usbout.surb[0].urb);
+ usb_free_urb(as->usbout.surb[1].urb);
kfree(as);
return;
}
if ((as->dev_audio = register_sound_dsp(&usb_audio_fops, -1)) < 0) {
printk(KERN_ERR "usbaudio: cannot register dsp\n");
+ usb_free_urb(as->usbin.durb[0].urb);
+ usb_free_urb(as->usbin.durb[1].urb);
+ usb_free_urb(as->usbin.surb[0].urb);
+ usb_free_urb(as->usbin.surb[1].urb);
+ usb_free_urb(as->usbout.durb[0].urb);
+ usb_free_urb(as->usbout.durb[1].urb);
+ usb_free_urb(as->usbout.surb[0].urb);
+ usb_free_urb(as->usbout.surb[1].urb);
kfree(as);
return;
}
diff --git a/drivers/usb/catc.c b/drivers/usb/catc.c
index cc1486170..0667997ff 100644
--- a/drivers/usb/catc.c
+++ b/drivers/usb/catc.c
@@ -179,7 +179,7 @@ struct catc {
void (*callback)(struct catc *catc, struct ctrl_queue *q);
} ctrl_queue[CTRL_QUEUE];
- struct urb tx_urb, rx_urb, irq_urb, ctrl_urb;
+ struct urb *tx_urb, *rx_urb, *irq_urb, *ctrl_urb;
};
/*
@@ -256,8 +256,8 @@ static void catc_irq_done(struct urb *urb)
}
if ((data[1] & 0x80) && !test_and_set_bit(RX_RUNNING, &catc->flags)) {
- catc->rx_urb.dev = catc->usbdev;
- if ((status = usb_submit_urb(&catc->rx_urb)) < 0) {
+ catc->rx_urb->dev = catc->usbdev;
+ if ((status = usb_submit_urb(catc->rx_urb)) < 0) {
err("submit(rx_urb) status %d", status);
return;
}
@@ -282,11 +282,11 @@ static void catc_tx_run(struct catc *catc)
{
int status;
- catc->tx_urb.transfer_buffer_length = catc->tx_ptr;
- catc->tx_urb.transfer_buffer = catc->tx_buf[catc->tx_idx];
- catc->tx_urb.dev = catc->usbdev;
+ catc->tx_urb->transfer_buffer_length = catc->tx_ptr;
+ catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx];
+ catc->tx_urb->dev = catc->usbdev;
- if ((status = usb_submit_urb(&catc->tx_urb)) < 0)
+ if ((status = usb_submit_urb(catc->tx_urb)) < 0)
err("submit(tx_urb), status %d", status);
catc->tx_idx = !catc->tx_idx;
@@ -363,8 +363,8 @@ static void catc_tx_timeout(struct net_device *netdev)
struct catc *catc = netdev->priv;
warn("Transmit timed out.");
- catc->tx_urb.transfer_flags |= USB_ASYNC_UNLINK;
- usb_unlink_urb(&catc->tx_urb);
+ catc->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
+ usb_unlink_urb(catc->tx_urb);
}
/*
@@ -383,7 +383,7 @@ static void catc_ctrl_run(struct catc *catc)
{
struct ctrl_queue *q = catc->ctrl_queue + catc->ctrl_tail;
struct usb_device *usbdev = catc->usbdev;
- struct urb *urb = &catc->ctrl_urb;
+ struct urb *urb = catc->ctrl_urb;
struct usb_ctrlrequest *dr = &catc->ctrl_dr;
int status;
@@ -402,7 +402,7 @@ static void catc_ctrl_run(struct catc *catc)
if (!q->dir && q->buf && q->len)
memcpy(catc->ctrl_buf, q->buf, q->len);
- if ((status = usb_submit_urb(&catc->ctrl_urb)))
+ if ((status = usb_submit_urb(catc->ctrl_urb)))
err("submit(ctrl_urb) status %d", status);
}
@@ -624,8 +624,8 @@ static int catc_open(struct net_device *netdev)
struct catc *catc = netdev->priv;
int status;
- catc->irq_urb.dev = catc->usbdev;
- if ((status = usb_submit_urb(&catc->irq_urb)) < 0) {
+ catc->irq_urb->dev = catc->usbdev;
+ if ((status = usb_submit_urb(catc->irq_urb)) < 0) {
err("submit(irq_urb) status %d", status);
return -1;
}
@@ -645,10 +645,10 @@ static int catc_stop(struct net_device *netdev)
del_timer_sync(&catc->timer);
- usb_unlink_urb(&catc->rx_urb);
- usb_unlink_urb(&catc->tx_urb);
- usb_unlink_urb(&catc->irq_urb);
- usb_unlink_urb(&catc->ctrl_urb);
+ usb_unlink_urb(catc->rx_urb);
+ usb_unlink_urb(catc->tx_urb);
+ usb_unlink_urb(catc->irq_urb);
+ usb_unlink_urb(catc->ctrl_urb);
return 0;
}
@@ -694,16 +694,26 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
catc->timer.data = (long) catc;
catc->timer.function = catc_stats_timer;
- FILL_CONTROL_URB(&catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),
+ catc->ctrl_urb = usb_alloc_urb(0);
+ catc->tx_urb = usb_alloc_urb(0);
+ catc->rx_urb = usb_alloc_urb(0);
+ catc->irq_urb = usb_alloc_urb(0);
+ if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
+ (!catc->rx_urb) || (!catc->irq_urb)) {
+ err("No free urbs available.");
+ return NULL;
+ }
+
+ FILL_CONTROL_URB(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),
NULL, NULL, 0, catc_ctrl_done, catc);
- FILL_BULK_URB(&catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1),
+ FILL_BULK_URB(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1),
NULL, 0, catc_tx_done, catc);
- FILL_BULK_URB(&catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
+ FILL_BULK_URB(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
catc->rx_buf, RX_MAX_BURST * (PKT_SZ + 2), catc_rx_done, catc);
- FILL_INT_URB(&catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
+ FILL_INT_URB(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
catc->irq_buf, 2, catc_irq_done, catc, 1);
dbg("Checking memory size\n");
@@ -772,6 +782,10 @@ static void catc_disconnect(struct usb_device *usbdev, void *dev_ptr)
{
struct catc *catc = dev_ptr;
unregister_netdev(catc->netdev);
+ usb_free_urb(catc->ctrl_urb);
+ usb_free_urb(catc->tx_urb);
+ usb_free_urb(catc->rx_urb);
+ usb_free_urb(catc->irq_urb);
kfree(catc->netdev);
kfree(catc);
}
diff --git a/drivers/usb/devio.c b/drivers/usb/devio.c
index d75364cff..c7883b376 100644
--- a/drivers/usb/devio.c
+++ b/drivers/usb/devio.c
@@ -53,7 +53,7 @@ struct async {
unsigned int signr;
void *userbuffer;
void *userurb;
- struct urb urb;
+ struct urb *urb;
};
static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
@@ -175,17 +175,21 @@ static struct async *alloc_async(unsigned int numisoframes)
if (!as)
return NULL;
memset(as, 0, assize);
- as->urb.number_of_packets = numisoframes;
- spin_lock_init(&as->urb.lock);
+ as->urb = usb_alloc_urb(numisoframes);
+ if (!as->urb) {
+ kfree(as);
+ return NULL;
+ }
return as;
}
static void free_async(struct async *as)
{
- if (as->urb.transfer_buffer)
- kfree(as->urb.transfer_buffer);
- if (as->urb.setup_packet)
- kfree(as->urb.setup_packet);
+ if (as->urb->transfer_buffer)
+ kfree(as->urb->transfer_buffer);
+ if (as->urb->setup_packet)
+ kfree(as->urb->setup_packet);
+ usb_free_urb(as->urb);
kfree(as);
}
@@ -259,7 +263,7 @@ static void async_completed(struct urb *urb)
wake_up(&ps->wait);
if (as->signr) {
sinfo.si_signo = as->signr;
- sinfo.si_errno = as->urb.status;
+ sinfo.si_errno = as->urb->status;
sinfo.si_code = SI_ASYNCIO;
sinfo.si_addr = as->userurb;
send_sig_info(as->signr, &sinfo, as->task);
@@ -278,7 +282,7 @@ static void destroy_all_async(struct dev_state *ps)
INIT_LIST_HEAD(&as->asynclist);
spin_unlock_irqrestore(&ps->lock, flags);
/* usb_unlink_urb calls the completion handler with status == -ENOENT */
- usb_unlink_urb(&as->urb);
+ usb_unlink_urb(as->urb);
spin_lock_irqsave(&ps->lock, flags);
}
spin_unlock_irqrestore(&ps->lock, flags);
@@ -862,7 +866,7 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
kfree(dr);
return -ENOMEM;
}
- if (!(as->urb.transfer_buffer = kmalloc(uurb.buffer_length, GFP_KERNEL))) {
+ if (!(as->urb->transfer_buffer = kmalloc(uurb.buffer_length, GFP_KERNEL))) {
if (isopkt)
kfree(isopkt);
if (dr)
@@ -870,19 +874,19 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
free_async(as);
return -ENOMEM;
}
- as->urb.next = NULL;
- as->urb.dev = ps->dev;
- as->urb.pipe = (uurb.type << 30) | __create_pipe(ps->dev, uurb.endpoint & 0xf) | (uurb.endpoint & USB_DIR_IN);
- as->urb.transfer_flags = uurb.flags;
- as->urb.transfer_buffer_length = uurb.buffer_length;
- as->urb.setup_packet = (unsigned char*)dr;
- as->urb.start_frame = uurb.start_frame;
- as->urb.number_of_packets = uurb.number_of_packets;
- as->urb.context = as;
- as->urb.complete = async_completed;
+ as->urb->next = NULL;
+ as->urb->dev = ps->dev;
+ as->urb->pipe = (uurb.type << 30) | __create_pipe(ps->dev, uurb.endpoint & 0xf) | (uurb.endpoint & USB_DIR_IN);
+ as->urb->transfer_flags = uurb.flags;
+ as->urb->transfer_buffer_length = uurb.buffer_length;
+ as->urb->setup_packet = (unsigned char*)dr;
+ as->urb->start_frame = uurb.start_frame;
+ as->urb->number_of_packets = uurb.number_of_packets;
+ as->urb->context = as;
+ as->urb->complete = async_completed;
for (totlen = u = 0; u < uurb.number_of_packets; u++) {
- as->urb.iso_frame_desc[u].offset = totlen;
- as->urb.iso_frame_desc[u].length = isopkt[u].length;
+ as->urb->iso_frame_desc[u].offset = totlen;
+ as->urb->iso_frame_desc[u].length = isopkt[u].length;
totlen += isopkt[u].length;
}
if (isopkt)
@@ -896,13 +900,13 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
as->signr = uurb.signr;
as->task = current;
if (!(uurb.endpoint & USB_DIR_IN)) {
- if (copy_from_user(as->urb.transfer_buffer, uurb.buffer, as->urb.transfer_buffer_length)) {
+ if (copy_from_user(as->urb->transfer_buffer, uurb.buffer, as->urb->transfer_buffer_length)) {
free_async(as);
return -EFAULT;
}
}
async_newpending(as);
- if ((ret = usb_submit_urb(&as->urb))) {
+ if ((ret = usb_submit_urb(as->urb))) {
printk(KERN_DEBUG "usbdevfs: usb_submit_urb returned %d\n", ret);
async_removepending(as);
free_async(as);
@@ -918,34 +922,35 @@ static int proc_unlinkurb(struct dev_state *ps, void *arg)
as = async_getpending(ps, arg);
if (!as)
return -EINVAL;
- usb_unlink_urb(&as->urb);
+ usb_unlink_urb(as->urb);
return 0;
}
static int processcompl(struct async *as)
{
+ struct urb *urb = as->urb;
unsigned int i;
if (as->userbuffer)
- if (copy_to_user(as->userbuffer, as->urb.transfer_buffer, as->urb.transfer_buffer_length))
+ if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
return -EFAULT;
- if (put_user(as->urb.status,
+ if (put_user(urb->status,
&((struct usbdevfs_urb *)as->userurb)->status))
return -EFAULT;
- if (put_user(as->urb.actual_length,
+ if (put_user(urb->actual_length,
&((struct usbdevfs_urb *)as->userurb)->actual_length))
return -EFAULT;
- if (put_user(as->urb.error_count,
+ if (put_user(urb->error_count,
&((struct usbdevfs_urb *)as->userurb)->error_count))
return -EFAULT;
- if (!(usb_pipeisoc(as->urb.pipe)))
+ if (!(usb_pipeisoc(urb->pipe)))
return 0;
- for (i = 0; i < as->urb.number_of_packets; i++) {
- if (put_user(as->urb.iso_frame_desc[i].actual_length,
+ for (i = 0; i < urb->number_of_packets; i++) {
+ if (put_user(urb->iso_frame_desc[i].actual_length,
&((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length))
return -EFAULT;
- if (put_user(as->urb.iso_frame_desc[i].status,
+ if (put_user(urb->iso_frame_desc[i].status,
&((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status))
return -EFAULT;
}
diff --git a/drivers/usb/dsbr100.c b/drivers/usb/dsbr100.c
index 406249ea1..0a5a98173 100644
--- a/drivers/usb/dsbr100.c
+++ b/drivers/usb/dsbr100.c
@@ -90,7 +90,7 @@ static int radio_nr = -1;
MODULE_PARM(radio_nr, "i");
typedef struct
-{ struct urb readurb,writeurb;
+{
struct usb_device *dev;
unsigned char transfer_buffer[TB_LEN];
int curfreq;
diff --git a/drivers/usb/hpusbscsi.c b/drivers/usb/hpusbscsi.c
index 95b3394d3..71e60ef6a 100644
--- a/drivers/usb/hpusbscsi.c
+++ b/drivers/usb/hpusbscsi.c
@@ -56,8 +56,17 @@ hpusbscsi_usb_probe (struct usb_device *dev, unsigned int interface,
return NULL;
DEBUG ("Allocated memory\n");
memset (new, 0, sizeof (struct hpusbscsi));
- spin_lock_init (&new->dataurb.lock);
- spin_lock_init (&new->controlurb.lock);
+ new->dataurb = usb_alloc_urb(0);
+ if (!new->dataurb) {
+ kfree (new);
+ return NULL;
+ }
+ new->controlurb = usb_alloc_urb(0);
+ if (!new->controlurb) {
+ usb_free_urb (new->dataurb);
+ kfree (new);
+ return NULL;
+ }
new->dev = dev;
init_waitqueue_head (&new->pending);
init_waitqueue_head (&new->deathrow);
@@ -126,6 +135,8 @@ hpusbscsi_usb_probe (struct usb_device *dev, unsigned int interface,
return new;
err_out:
+ usb_free_urb (new->controlurb);
+ usb_free_urb (new->dataurb);
kfree (new);
return NULL;
}
@@ -133,7 +144,7 @@ hpusbscsi_usb_probe (struct usb_device *dev, unsigned int interface,
static void
hpusbscsi_usb_disconnect (struct usb_device *dev, void *ptr)
{
- usb_unlink_urb(&(((struct hpusbscsi *) ptr)->controlurb));
+ usb_unlink_urb((((struct hpusbscsi *) ptr)->controlurb));
((struct hpusbscsi *) ptr)->dev = NULL;
}
@@ -184,8 +195,10 @@ hpusbscsi_exit (void)
old = tmp;
tmp = tmp->next;
o = (struct hpusbscsi *)old;
- usb_unlink_urb(&o->controlurb);
+ usb_unlink_urb(o->controlurb);
scsi_unregister_host(&o->ctempl);
+ usb_free_urb(o->controlurb);
+ usb_free_urb(o->dataurb);
kfree(old);
}
@@ -222,7 +235,7 @@ hpusbscsi_scsi_detect (struct SHT *sht)
sht->proc_dir = NULL;
/* build and submit an interrupt URB for status byte handling */
- FILL_INT_URB(&desc->controlurb,
+ FILL_INT_URB(desc->controlurb,
desc->dev,
usb_rcvintpipe(desc->dev,desc->ep_int),
&desc->scsi_state_byte,
@@ -232,7 +245,7 @@ hpusbscsi_scsi_detect (struct SHT *sht)
desc->interrupt_interval
);
- if ( 0 > usb_submit_urb(&desc->controlurb)) {
+ if ( 0 > usb_submit_urb(desc->controlurb)) {
kfree(sht->proc_name);
return 0;
}
@@ -241,7 +254,7 @@ hpusbscsi_scsi_detect (struct SHT *sht)
desc->host = scsi_register (sht, sizeof (desc));
if (desc->host == NULL) {
kfree (sht->proc_name);
- usb_unlink_urb(&desc->controlurb);
+ usb_unlink_urb(desc->controlurb);
return 0;
}
desc->host->hostdata[0] = (unsigned long) desc;
@@ -297,7 +310,7 @@ static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
/* We prepare the urb for writing out the scsi command */
FILL_BULK_URB(
- &hpusbscsi->dataurb,
+ hpusbscsi->dataurb,
hpusbscsi->dev,
usb_sndbulkpipe(hpusbscsi->dev,hpusbscsi->ep_out),
srb->cmnd,
@@ -308,7 +321,7 @@ static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
hpusbscsi->scallback = callback;
hpusbscsi->srb = srb;
- res = usb_submit_urb(&hpusbscsi->dataurb);
+ res = usb_submit_urb(hpusbscsi->dataurb);
if (unlikely(res)) {
hpusbscsi->state = HP_STATE_FREE;
TRACE_STATE;
@@ -340,8 +353,8 @@ static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb)
struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
printk(KERN_DEBUG"Requested is canceled.\n");
- usb_unlink_urb(&hpusbscsi->dataurb);
- usb_unlink_urb(&hpusbscsi->controlurb);
+ usb_unlink_urb(hpusbscsi->dataurb);
+ usb_unlink_urb(hpusbscsi->controlurb);
hpusbscsi->state = HP_STATE_FREE;
return SCSI_ABORT_PENDING;
diff --git a/drivers/usb/hpusbscsi.h b/drivers/usb/hpusbscsi.h
index 0daa39708..30d0524a7 100644
--- a/drivers/usb/hpusbscsi.h
+++ b/drivers/usb/hpusbscsi.h
@@ -26,8 +26,8 @@ struct hpusbscsi
wait_queue_head_t pending;
wait_queue_head_t deathrow;
- struct urb dataurb;
- struct urb controlurb;
+ struct urb *dataurb;
+ struct urb *controlurb;
int fragment;
int state;
diff --git a/drivers/usb/inode.c b/drivers/usb/inode.c
index a73a209dc..53716ae85 100644
--- a/drivers/usb/inode.c
+++ b/drivers/usb/inode.c
@@ -678,6 +678,8 @@ void usbfs_remove_bus(struct usb_bus *bus)
void usbfs_add_device(struct usb_device *dev)
{
char name[8];
+ int i;
+ int i_size;
sprintf (name, "%03d", dev->devnum);
dev->dentry = fs_create_file (name,
@@ -688,6 +690,17 @@ void usbfs_add_device(struct usb_device *dev)
if (dev->dentry == NULL)
return;
+ /* Set the size of the device's file to be
+ * equal to the size of the device descriptors. */
+ i_size = sizeof (struct usb_device_descriptor);
+ for (i = 0; i < dev->descriptor.bNumConfigurations; ++i) {
+ struct usb_config_descriptor *config =
+ (struct usb_config_descriptor *)dev->rawdescriptors[i];
+ i_size += le16_to_cpu (config->wTotalLength);
+ }
+ if (dev->dentry->d_inode)
+ dev->dentry->d_inode->i_size = i_size;
+
usbfs_update_special();
usbdevfs_conn_disc_event();
}
diff --git a/drivers/usb/microtek.c b/drivers/usb/microtek.c
index d74b70273..ff190dcd7 100644
--- a/drivers/usb/microtek.c
+++ b/drivers/usb/microtek.c
@@ -324,7 +324,7 @@ static inline void mts_urb_abort(struct mts_desc* desc) {
MTS_DEBUG_GOT_HERE();
mts_debug_dump(desc);
- usb_unlink_urb( &desc->urb );
+ usb_unlink_urb( desc->urb );
}
static struct mts_desc * mts_list; /* list of active scanners */
@@ -365,6 +365,7 @@ void mts_remove_nolock( struct mts_desc* to_remove )
scsi_unregister_host(&to_remove->ctempl);
unlock_kernel();
+ usb_free_urb(to_remove->urb);
kfree( to_remove );
}
@@ -706,7 +707,7 @@ int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
}
- FILL_BULK_URB(&desc->urb,
+ FILL_BULK_URB(desc->urb,
desc->usb_dev,
usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
srb->cmnd,
@@ -719,7 +720,7 @@ int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
mts_build_transfer_context( srb, desc );
desc->context.final_callback = callback;
- res=usb_submit_urb(&desc->urb);
+ res=usb_submit_urb(desc->urb);
if(unlikely(res)){
MTS_ERROR("error %d submitting URB\n",(int)res);
@@ -933,10 +934,12 @@ static void * mts_usb_probe (struct usb_device *dev, unsigned int interface,
return NULL;
}
- /* As done by usb_alloc_urb */
memset( new_desc, 0, sizeof(*new_desc) );
- spin_lock_init(&new_desc->urb.lock);
-
+ new_desc->urb = usb_alloc_urb(0);
+ if (!new_desc->urb) {
+ kfree(new_desc);
+ return NULL;
+ }
/* initialising that descriptor */
new_desc->usb_dev = dev;
diff --git a/drivers/usb/microtek.h b/drivers/usb/microtek.h
index c5d3f174b..7ab7cb3f2 100644
--- a/drivers/usb/microtek.h
+++ b/drivers/usb/microtek.h
@@ -46,7 +46,7 @@ struct mts_desc {
struct semaphore lock;
- struct urb urb;
+ struct urb *urb;
struct mts_transfer_context context;
};
diff --git a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c
index ce187fb48..ef89fc6a8 100644
--- a/drivers/usb/pegasus.c
+++ b/drivers/usb/pegasus.c
@@ -147,9 +147,9 @@ static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
pegasus->dr.wValue = cpu_to_le16 (0);
pegasus->dr.wIndex = cpu_to_le16p(&indx);
pegasus->dr.wLength = cpu_to_le16p(&size);
- pegasus->ctrl_urb.transfer_buffer_length = size;
+ pegasus->ctrl_urb->transfer_buffer_length = size;
- FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
+ FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
usb_rcvctrlpipe(pegasus->usb,0),
(char *)&pegasus->dr,
buffer, size, ctrl_callback, pegasus );
@@ -157,7 +157,7 @@ static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
add_wait_queue( &pegasus->ctrl_wait, &wait );
set_current_state( TASK_UNINTERRUPTIBLE );
- if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) {
+ if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) ) {
err( __FUNCTION__ " BAD CTRLs %d", ret);
goto out;
}
@@ -197,9 +197,9 @@ static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
pegasus->dr.wValue = cpu_to_le16 (0);
pegasus->dr.wIndex = cpu_to_le16p( &indx );
pegasus->dr.wLength = cpu_to_le16p( &size );
- pegasus->ctrl_urb.transfer_buffer_length = size;
+ pegasus->ctrl_urb->transfer_buffer_length = size;
- FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
+ FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
usb_sndctrlpipe(pegasus->usb,0),
(char *)&pegasus->dr,
buffer, size, ctrl_callback, pegasus );
@@ -207,7 +207,7 @@ static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
add_wait_queue( &pegasus->ctrl_wait, &wait );
set_current_state( TASK_UNINTERRUPTIBLE );
- if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) {
+ if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) ) {
err( __FUNCTION__ " BAD CTRL %d", ret);
goto out;
}
@@ -247,9 +247,9 @@ static int set_register( pegasus_t *pegasus, __u16 indx, __u8 data )
pegasus->dr.wValue = cpu_to_le16p( &dat);
pegasus->dr.wIndex = cpu_to_le16p( &indx );
pegasus->dr.wLength = cpu_to_le16( 1 );
- pegasus->ctrl_urb.transfer_buffer_length = 1;
+ pegasus->ctrl_urb->transfer_buffer_length = 1;
- FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
+ FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
usb_sndctrlpipe(pegasus->usb,0),
(char *)&pegasus->dr,
buffer, 1, ctrl_callback, pegasus );
@@ -257,7 +257,7 @@ static int set_register( pegasus_t *pegasus, __u16 indx, __u8 data )
add_wait_queue( &pegasus->ctrl_wait, &wait );
set_current_state( TASK_UNINTERRUPTIBLE );
- if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) {
+ if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) ) {
err( __FUNCTION__ " BAD CTRL %d", ret);
goto out;
}
@@ -280,14 +280,14 @@ static int update_eth_regs_async( pegasus_t *pegasus )
pegasus->dr.wValue = 0;
pegasus->dr.wIndex = cpu_to_le16(EthCtrl0);
pegasus->dr.wLength = cpu_to_le16(3);
- pegasus->ctrl_urb.transfer_buffer_length = 3;
+ pegasus->ctrl_urb->transfer_buffer_length = 3;
- FILL_CONTROL_URB( &pegasus->ctrl_urb, pegasus->usb,
+ FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
usb_sndctrlpipe(pegasus->usb,0),
(char *)&pegasus->dr,
pegasus->eth_regs, 3, ctrl_callback, pegasus );
- if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) )
+ if ( (ret = usb_submit_urb( pegasus->ctrl_urb )) )
err( __FUNCTION__ " BAD CTRL %d, flags %x",ret,pegasus->flags );
return ret;
@@ -569,11 +569,11 @@ static void read_bulk_callback( struct urb *urb )
pegasus->stats.rx_bytes += pkt_len;
goon:
- FILL_BULK_URB( &pegasus->rx_urb, pegasus->usb,
+ FILL_BULK_URB( pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1),
pegasus->rx_buff, PEGASUS_MAX_MTU,
read_bulk_callback, pegasus );
- if ( (res = usb_submit_urb(&pegasus->rx_urb)) )
+ if ( (res = usb_submit_urb(pegasus->rx_urb)) )
warn( __FUNCTION__ " failed submint rx_urb %d", res);
pegasus->flags &= ~PEGASUS_RX_BUSY;
}
@@ -639,8 +639,8 @@ static void pegasus_tx_timeout( struct net_device *net )
return;
warn("%s: Tx timed out.", net->name);
- pegasus->tx_urb.transfer_flags |= USB_ASYNC_UNLINK;
- usb_unlink_urb( &pegasus->tx_urb );
+ pegasus->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
+ usb_unlink_urb( pegasus->tx_urb );
pegasus->stats.tx_errors++;
}
@@ -656,12 +656,12 @@ static int pegasus_start_xmit( struct sk_buff *skb, struct net_device *net )
((__u16 *)pegasus->tx_buff)[0] = cpu_to_le16( l16 );
memcpy(pegasus->tx_buff+2, skb->data, skb->len);
- FILL_BULK_URB( &pegasus->tx_urb, pegasus->usb,
+ FILL_BULK_URB( pegasus->tx_urb, pegasus->usb,
usb_sndbulkpipe(pegasus->usb, 2),
pegasus->tx_buff, PEGASUS_MAX_MTU,
write_bulk_callback, pegasus );
- pegasus->tx_urb.transfer_buffer_length = count;
- if ((res = usb_submit_urb(&pegasus->tx_urb))) {
+ pegasus->tx_urb->transfer_buffer_length = count;
+ if ((res = usb_submit_urb(pegasus->tx_urb))) {
warn("failed tx_urb %d", res);
pegasus->stats.tx_errors++;
netif_start_queue( net );
@@ -717,18 +717,18 @@ static int pegasus_open(struct net_device *net)
err("can't enable_net_traffic() - %d", res);
return -EIO;
}
- FILL_BULK_URB( &pegasus->rx_urb, pegasus->usb,
+ FILL_BULK_URB( pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1),
pegasus->rx_buff, PEGASUS_MAX_MTU,
read_bulk_callback, pegasus );
- if ( (res = usb_submit_urb(&pegasus->rx_urb)) )
+ if ( (res = usb_submit_urb(pegasus->rx_urb)) )
warn( __FUNCTION__ " failed rx_urb %d", res );
#ifdef PEGASUS_USE_INTR
- FILL_INT_URB( &pegasus->intr_urb, pegasus->usb,
+ FILL_INT_URB( pegasus->intr_urb, pegasus->usb,
usb_rcvintpipe(pegasus->usb, 3),
pegasus->intr_buff, sizeof(pegasus->intr_buff),
intr_callback, pegasus, pegasus->intr_interval );
- if ( (res = usb_submit_urb(&pegasus->intr_urb)) )
+ if ( (res = usb_submit_urb(pegasus->intr_urb)) )
warn( __FUNCTION__ " failed intr_urb %d", res);
#endif
netif_start_queue( net );
@@ -747,11 +747,11 @@ static int pegasus_close( struct net_device *net )
if ( !(pegasus->flags & PEGASUS_UNPLUG) )
disable_net_traffic( pegasus );
- usb_unlink_urb( &pegasus->rx_urb );
- usb_unlink_urb( &pegasus->tx_urb );
- usb_unlink_urb( &pegasus->ctrl_urb );
+ usb_unlink_urb( pegasus->rx_urb );
+ usb_unlink_urb( pegasus->tx_urb );
+ usb_unlink_urb( pegasus->ctrl_urb );
#ifdef PEGASUS_USE_INTR
- usb_unlink_urb( &pegasus->intr_urb );
+ usb_unlink_urb( pegasus->intr_urb );
#endif
return 0;
@@ -800,7 +800,7 @@ static void pegasus_set_multicast( struct net_device *net )
}
pegasus->flags |= ETH_REGS_CHANGE;
- ctrl_callback( &pegasus->ctrl_urb );
+ ctrl_callback( pegasus->ctrl_urb );
netif_wake_queue(net);
}
@@ -856,6 +856,33 @@ static void * pegasus_probe( struct usb_device *dev, unsigned int ifnum,
pegasus->dev_index = dev_index;
init_waitqueue_head( &pegasus->ctrl_wait );
+ pegasus->ctrl_urb = usb_alloc_urb(0);
+ if (!pegasus->ctrl_urb) {
+ kfree (pegasus);
+ return NULL;
+ }
+ pegasus->rx_urb = usb_alloc_urb(0);
+ if (!pegasus->rx_urb) {
+ usb_free_urb (pegasus->ctrl_urb);
+ kfree (pegasus);
+ return NULL;
+ }
+ pegasus->tx_urb = usb_alloc_urb(0);
+ if (!pegasus->tx_urb) {
+ usb_free_urb (pegasus->rx_urb);
+ usb_free_urb (pegasus->ctrl_urb);
+ kfree (pegasus);
+ return NULL;
+ }
+ pegasus->intr_urb = usb_alloc_urb(0);
+ if (!pegasus->intr_urb) {
+ usb_free_urb (pegasus->tx_urb);
+ usb_free_urb (pegasus->rx_urb);
+ usb_free_urb (pegasus->ctrl_urb);
+ kfree (pegasus);
+ return NULL;
+ }
+
net = init_etherdev( NULL, 0 );
if ( !net ) {
kfree( pegasus );
@@ -883,6 +910,7 @@ static void * pegasus_probe( struct usb_device *dev, unsigned int ifnum,
if ( reset_mac(pegasus) ) {
err("can't reset MAC");
unregister_netdev( pegasus->net );
+ kfree(pegasus->net);
kfree(pegasus);
pegasus = NULL;
return NULL;
@@ -919,6 +947,11 @@ static void pegasus_disconnect( struct usb_device *dev, void *ptr )
pegasus->flags |= PEGASUS_UNPLUG;
unregister_netdev( pegasus->net );
usb_dec_dev_use( dev );
+ usb_free_urb (pegasus->intr_urb);
+ usb_free_urb (pegasus->tx_urb);
+ usb_free_urb (pegasus->rx_urb);
+ usb_free_urb (pegasus->ctrl_urb);
+ kfree( pegasus->net );
kfree( pegasus );
pegasus = NULL;
}
diff --git a/drivers/usb/pegasus.h b/drivers/usb/pegasus.h
index ccb80c2d3..0b4f82319 100644
--- a/drivers/usb/pegasus.h
+++ b/drivers/usb/pegasus.h
@@ -107,7 +107,7 @@ typedef struct pegasus {
unsigned features;
int dev_index;
int intr_interval;
- struct urb ctrl_urb, rx_urb, tx_urb, intr_urb;
+ struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb;
struct usb_ctrlrequest dr;
wait_queue_head_t ctrl_wait;
struct semaphore ctrl_sem;
@@ -145,6 +145,7 @@ struct usb_eth_dev {
#define VENDOR_SMARTBRIDGES 0x08d1
#define VENDOR_SMC 0x0707
#define VENDOR_SOHOWARE 0x15e8
+#define VENDOR_SIEMENS 0x067c
#else /* PEGASUS_DEV */
@@ -173,6 +174,8 @@ PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x200c,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046,
DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
+ DEFAULT_GPIO_RESET )
PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
VENDOR_ADMTEK, 0x8511,
DEFAULT_GPIO_RESET | PEGASUS_II )
@@ -245,6 +248,8 @@ PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
+ DEFAULT_GPIO_RESET )
#endif /* PEGASUS_DEV */
diff --git a/drivers/usb/scanner.c b/drivers/usb/scanner.c
index 4c147cf50..8dac42ff2 100644
--- a/drivers/usb/scanner.c
+++ b/drivers/usb/scanner.c
@@ -972,6 +972,13 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum,
}
memset (scn, 0, sizeof(struct scn_usb_data));
+ scn->scn_irq = usb_alloc_urb(0);
+ if (!scn->scn_irq) {
+ kfree(scn);
+ up(&scn_mutex);
+ return NULL;
+ }
+
init_MUTEX(&(scn->sem)); /* Initializes to unlocked */
dbg ("probe_scanner(%d): Address of scn:%p", scn_minor, scn);
@@ -979,13 +986,13 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum,
/* Ok, if we detected an interrupt EP, setup a handler for it */
if (have_intr) {
dbg("probe_scanner(%d): Configuring IRQ handler for intr EP:%d", scn_minor, have_intr);
- FILL_INT_URB(&scn->scn_irq, dev,
+ FILL_INT_URB(scn->scn_irq, dev,
usb_rcvintpipe(dev, have_intr),
&scn->button, 1, irq_scanner, scn,
// endpoint[(int)have_intr].bInterval);
250);
- if (usb_submit_urb(&scn->scn_irq)) {
+ if (usb_submit_urb(scn->scn_irq)) {
err("probe_scanner(%d): Unable to allocate INT URB.", scn_minor);
kfree(scn);
up(&scn_mutex);
@@ -1067,7 +1074,7 @@ disconnect_scanner(struct usb_device *dev, void *ptr)
if(scn->intr_ep) {
dbg("disconnect_scanner(%d): Unlinking IRQ URB", scn->scn_minor);
- usb_unlink_urb(&scn->scn_irq);
+ usb_unlink_urb(scn->scn_irq);
}
usb_driver_release_interface(&scanner_driver,
&scn->scn_dev->actconfig->interface[scn->ifnum]);
@@ -1078,6 +1085,7 @@ disconnect_scanner(struct usb_device *dev, void *ptr)
dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
devfs_unregister(scn->devfs);
p_scn_table[scn->scn_minor] = NULL;
+ usb_free_urb(scn->scn_irq);
up (&(scn->sem));
kfree (scn);
up (&scn_mutex);
diff --git a/drivers/usb/scanner.h b/drivers/usb/scanner.h
index eb899bb4d..be6c26ac1 100644
--- a/drivers/usb/scanner.h
+++ b/drivers/usb/scanner.h
@@ -241,7 +241,7 @@ static DECLARE_MUTEX (scn_mutex); /* Initializes to unlocked */
struct scn_usb_data {
struct usb_device *scn_dev;
devfs_handle_t devfs; /* devfs device */
- struct urb scn_irq;
+ struct urb *scn_irq;
unsigned int ifnum; /* Interface number of the USB device */
int scn_minor; /* Scanner minor - used in disconnect() */
unsigned char button; /* Front panel buffer */
diff --git a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c
index 16009c8e5..228051285 100644
--- a/drivers/usb/usb-uhci.c
+++ b/drivers/usb/usb-uhci.c
@@ -16,7 +16,7 @@
* (C) Copyright 1999 Randy Dunlap
* (C) Copyright 1999 Gregory P. Smith
*
- * $Id: usb-uhci.c,v 1.268 2001/08/29 14:08:43 acher Exp $
+ * $Id: usb-uhci.c,v 1.275 2002/01/19 20:57:33 acher Exp $
*/
#include <linux/config.h>
@@ -34,6 +34,7 @@
#include <linux/init.h>
#include <linux/version.h>
#include <linux/pm.h>
+#include <linux/timer.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -52,7 +53,7 @@
/* This enables an extra UHCI slab for memory debugging */
#define DEBUG_SLAB
-#define VERSTR "$Revision: 1.268 $ time " __TIME__ " " __DATE__
+#define VERSTR "$Revision: 1.275 $ time " __TIME__ " " __DATE__
#include <linux/usb.h>
#include "usb-uhci.h"
@@ -61,7 +62,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.268"
+#define DRIVER_VERSION "v1.275"
#define DRIVER_AUTHOR "Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
#define DRIVER_DESC "USB Universal Host Controller Interface driver"
@@ -71,6 +72,9 @@
#define DEBUG_SYMBOLS
#ifdef DEBUG_SYMBOLS
#define _static
+ #ifndef EXPORT_SYMTAB
+ #define EXPORT_SYMTAB
+ #endif
#else
#define _static static
#endif
@@ -1179,6 +1183,7 @@ _static int uhci_unlink_urb_sync (uhci_t *s, struct urb *urb)
// cleanup the rest
switch (usb_pipetype (urb->pipe)) {
+ case PIPE_INTERRUPT:
case PIPE_ISOCHRONOUS:
uhci_wait_ms(1);
uhci_clean_iso_step2(s, urb_priv);
@@ -1776,17 +1781,15 @@ _static void uhci_check_timeouts(uhci_t *s)
type = usb_pipetype (urb->pipe);
hcpriv = (urb_priv_t*)urb->hcpriv;
-
- if ( urb->timeout &&
- ((hcpriv->started + urb->timeout) < jiffies)) {
+
+ if ( urb->timeout && time_after(jiffies, hcpriv->started + urb->timeout)) {
urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK;
async_dbg("uhci_check_timeout: timeout for %p",urb);
uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB);
}
#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
else if (((type == PIPE_BULK) || (type == PIPE_CONTROL)) &&
- (hcpriv->use_loop) &&
- ((hcpriv->started + IDLE_TIMEOUT) < jiffies))
+ (hcpriv->use_loop) && time_after(jiffies, hcpriv->started + IDLE_TIMEOUT))
disable_desc_loop(s, urb);
#endif
@@ -2442,7 +2445,7 @@ _static int process_interrupt (uhci_t *s, struct urb *urb)
break;
}
- if (!desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC)) {
+ if (!(desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC))) {
// do not process one-shot TDs, no recycling
break;
}
@@ -2506,6 +2509,8 @@ _static int process_interrupt (uhci_t *s, struct urb *urb)
}
else {
uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB);
+ // correct toggle after unlink
+ usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
clr_td_ioc(desc); // inactivate TD
}
}
@@ -2735,7 +2740,7 @@ _static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
if (status != 1) {
// Avoid too much error messages at a time
- if ((jiffies - s->last_error_time > ERROR_SUPPRESSION_TIME)) {
+ if (time_after(jiffies, s->last_error_time + ERROR_SUPPRESSION_TIME)) {
warn("interrupt, status %x, frame# %i", status,
UHCI_GET_CURRENT_FRAME(s));
s->last_error_time = jiffies;
@@ -2783,7 +2788,7 @@ restart:
break;
}
}
- if ((jiffies - s->timeout_check) > (HZ/30))
+ if (time_after(jiffies, s->timeout_check + (HZ/30)))
uhci_check_timeouts(s);
clean_descs(s, CLEAN_NOT_FORCED);
@@ -2812,7 +2817,7 @@ _static void reset_hc (uhci_t *s)
_static void start_hc (uhci_t *s)
{
unsigned int io_addr = s->io_addr;
- int timeout = 1000;
+ int timeout = 10;
/*
* Reset the HC - this will force us to get a
@@ -2827,6 +2832,7 @@ _static void start_hc (uhci_t *s)
err("USBCMD_HCRESET timed out!");
break;
}
+ udelay(1);
}
/* Turn on all interrupts */
@@ -2842,7 +2848,8 @@ _static void start_hc (uhci_t *s)
s->running = 1;
}
-_static void __devexit
+/* No __devexit, since it maybe called from alloc_uhci() */
+_static void
uhci_pci_remove (struct pci_dev *dev)
{
uhci_t *s = pci_get_drvdata(dev);
@@ -3127,4 +3134,3 @@ module_exit (uhci_hcd_cleanup);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
-
diff --git a/drivers/usb/usbkbd.c b/drivers/usb/usbkbd.c
index 5085dab3b..9d57df368 100644
--- a/drivers/usb/usbkbd.c
+++ b/drivers/usb/usbkbd.c
@@ -73,7 +73,7 @@ struct usb_kbd {
struct usb_device *usbdev;
unsigned char new[8];
unsigned char old[8];
- struct urb irq, led;
+ struct urb *irq, *led;
struct usb_ctrlrequest dr;
unsigned char leds, newleds;
char name[128];
@@ -121,15 +121,15 @@ int usb_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, i
(!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) |
(!!test_bit(LED_NUML, dev->led));
- if (kbd->led.status == -EINPROGRESS)
+ if (kbd->led->status == -EINPROGRESS)
return 0;
if (kbd->leds == kbd->newleds)
return 0;
kbd->leds = kbd->newleds;
- kbd->led.dev = kbd->usbdev;
- if (usb_submit_urb(&kbd->led))
+ kbd->led->dev = kbd->usbdev;
+ if (usb_submit_urb(kbd->led))
err("usb_submit_urb(leds) failed");
return 0;
@@ -146,8 +146,8 @@ static void usb_kbd_led(struct urb *urb)
return;
kbd->leds = kbd->newleds;
- kbd->led.dev = kbd->usbdev;
- if (usb_submit_urb(&kbd->led))
+ kbd->led->dev = kbd->usbdev;
+ if (usb_submit_urb(kbd->led))
err("usb_submit_urb(leds) failed");
}
@@ -158,8 +158,8 @@ static int usb_kbd_open(struct input_dev *dev)
if (kbd->open++)
return 0;
- kbd->irq.dev = kbd->usbdev;
- if (usb_submit_urb(&kbd->irq))
+ kbd->irq->dev = kbd->usbdev;
+ if (usb_submit_urb(kbd->irq))
return -EIO;
return 0;
@@ -170,7 +170,7 @@ static void usb_kbd_close(struct input_dev *dev)
struct usb_kbd *kbd = dev->private;
if (!--kbd->open)
- usb_unlink_urb(&kbd->irq);
+ usb_unlink_urb(kbd->irq);
}
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
@@ -201,6 +201,18 @@ static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
memset(kbd, 0, sizeof(struct usb_kbd));
+ kbd->irq = usb_alloc_urb(0);
+ if (!kbd->irq) {
+ kfree(kbd);
+ return NULL;
+ }
+ kbd->led = usb_alloc_urb(0);
+ if (!kbd->led) {
+ usb_free_urb(kbd->irq);
+ kfree(kbd);
+ return NULL;
+ }
+
kbd->usbdev = dev;
kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
@@ -215,7 +227,7 @@ static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
kbd->dev.open = usb_kbd_open;
kbd->dev.close = usb_kbd_close;
- FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
+ FILL_INT_URB(kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
usb_kbd_irq, kbd, endpoint->bInterval);
kbd->dr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
@@ -248,7 +260,7 @@ static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
kfree(buf);
- FILL_CONTROL_URB(&kbd->led, dev, usb_sndctrlpipe(dev, 0),
+ FILL_CONTROL_URB(kbd->led, dev, usb_sndctrlpipe(dev, 0),
(void*) &kbd->dr, &kbd->leds, 1, usb_kbd_led, kbd);
input_register_device(&kbd->dev);
@@ -262,8 +274,10 @@ static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
{
struct usb_kbd *kbd = ptr;
- usb_unlink_urb(&kbd->irq);
+ usb_unlink_urb(kbd->irq);
input_unregister_device(&kbd->dev);
+ usb_free_urb(kbd->irq);
+ usb_free_urb(kbd->led);
kfree(kbd);
}
diff --git a/drivers/usb/usbmouse.c b/drivers/usb/usbmouse.c
index ff4ee6676..db2e61f82 100644
--- a/drivers/usb/usbmouse.c
+++ b/drivers/usb/usbmouse.c
@@ -54,7 +54,7 @@ struct usb_mouse {
char name[128];
struct usb_device *usbdev;
struct input_dev dev;
- struct urb irq;
+ struct urb *irq;
int open;
};
@@ -84,8 +84,8 @@ static int usb_mouse_open(struct input_dev *dev)
if (mouse->open++)
return 0;
- mouse->irq.dev = mouse->usbdev;
- if (usb_submit_urb(&mouse->irq))
+ mouse->irq->dev = mouse->usbdev;
+ if (usb_submit_urb(mouse->irq))
return -EIO;
return 0;
@@ -96,7 +96,7 @@ static void usb_mouse_close(struct input_dev *dev)
struct usb_mouse *mouse = dev->private;
if (!--mouse->open)
- usb_unlink_urb(&mouse->irq);
+ usb_unlink_urb(mouse->irq);
}
static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum,
@@ -126,6 +126,12 @@ static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum,
if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL;
memset(mouse, 0, sizeof(struct usb_mouse));
+ mouse->irq = usb_alloc_urb(0);
+ if (!mouse->irq) {
+ kfree(mouse);
+ return NULL;
+ }
+
mouse->usbdev = dev;
mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
@@ -162,7 +168,7 @@ static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum,
kfree(buf);
- FILL_INT_URB(&mouse->irq, dev, pipe, mouse->data, maxp > 8 ? 8 : maxp,
+ FILL_INT_URB(mouse->irq, dev, pipe, mouse->data, maxp > 8 ? 8 : maxp,
usb_mouse_irq, mouse, endpoint->bInterval);
input_register_device(&mouse->dev);
@@ -176,8 +182,9 @@ static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum,
static void usb_mouse_disconnect(struct usb_device *dev, void *ptr)
{
struct usb_mouse *mouse = ptr;
- usb_unlink_urb(&mouse->irq);
+ usb_unlink_urb(mouse->irq);
input_unregister_device(&mouse->dev);
+ usb_free_urb(mouse->irq);
kfree(mouse);
}
diff --git a/drivers/usb/vicam.c b/drivers/usb/vicam.c
index 82eef90a5..069383fac 100644
--- a/drivers/usb/vicam.c
+++ b/drivers/usb/vicam.c
@@ -344,7 +344,7 @@ static void params_changed(struct usb_vicam *vicam)
synchronize(vicam);
mdelay(10);
vicam_parameters(vicam);
- printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb));
+ printk("Submiting urb: %d\n", usb_submit_urb(vicam->readurb));
#endif
}
@@ -841,9 +841,9 @@ static int vicam_init(struct usb_vicam *vicam)
vicam_parameters(vicam);
- FILL_BULK_URB(&vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),
+ FILL_BULK_URB(vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),
buf, 0x1e480, vicam_bulk, vicam);
- printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb));
+ printk("Submiting urb: %d\n", usb_submit_urb(vicam->readurb));
return 0;
error:
@@ -877,7 +877,13 @@ static void * __devinit vicam_probe(struct usb_device *udev, unsigned int ifnum,
return NULL;
}
memset(vicam, 0, sizeof(*vicam));
-
+
+ vicam->readurb = usb_alloc_urb(0);
+ if (!vicam->readurb) {
+ kfree(vicam);
+ return NULL;
+ }
+
vicam->udev = udev;
vicam->camera_name = camera_name;
vicam->win.brightness = 128;
@@ -925,6 +931,7 @@ static void vicam_disconnect(struct usb_device *udev, void *ptr)
if (!vicam->open_count) {
/* Other random junk */
+ usb_free_urb(vicam->readurb);
kfree(vicam);
vicam = NULL;
}
diff --git a/drivers/usb/vicam.h b/drivers/usb/vicam.h
index b483befbf..4527d8e64 100644
--- a/drivers/usb/vicam.h
+++ b/drivers/usb/vicam.h
@@ -75,7 +75,7 @@ struct usb_vicam
int maxframesize;
struct picture_parm win;
struct proc_dir_entry *proc_entry; /* /proc/se401/videoX */
- struct urb readurb;
+ struct urb *readurb;
};
#endif
diff --git a/drivers/usb/wacom.c b/drivers/usb/wacom.c
index 0ed344eff..9f3433a8a 100644
--- a/drivers/usb/wacom.c
+++ b/drivers/usb/wacom.c
@@ -100,7 +100,7 @@ struct wacom {
signed char data[10];
struct input_dev dev;
struct usb_device *usbdev;
- struct urb irq;
+ struct urb *irq;
struct wacom_features *features;
int tool[2];
int open;
@@ -335,8 +335,8 @@ static int wacom_open(struct input_dev *dev)
if (wacom->open++)
return 0;
- wacom->irq.dev = wacom->usbdev;
- if (usb_submit_urb(&wacom->irq))
+ wacom->irq->dev = wacom->usbdev;
+ if (usb_submit_urb(wacom->irq))
return -EIO;
return 0;
@@ -347,7 +347,7 @@ static void wacom_close(struct input_dev *dev)
struct wacom *wacom = dev->private;
if (!--wacom->open)
- usb_unlink_urb(&wacom->irq);
+ usb_unlink_urb(wacom->irq);
}
static void *wacom_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
@@ -358,6 +358,12 @@ static void *wacom_probe(struct usb_device *dev, unsigned int ifnum, const struc
if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) return NULL;
memset(wacom, 0, sizeof(struct wacom));
+ wacom->irq = usb_alloc_urb(0);
+ if (!wacom->irq) {
+ kfree(wacom);
+ return NULL;
+ }
+
wacom->features = wacom_features + id->driver_info;
wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC) | wacom->features->evbit;
@@ -397,7 +403,7 @@ static void *wacom_probe(struct usb_device *dev, unsigned int ifnum, const struc
endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
- FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+ FILL_INT_URB(wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
wacom->data, wacom->features->pktlen, wacom->features->irq, wacom, endpoint->bInterval);
input_register_device(&wacom->dev);
@@ -411,8 +417,9 @@ static void *wacom_probe(struct usb_device *dev, unsigned int ifnum, const struc
static void wacom_disconnect(struct usb_device *dev, void *ptr)
{
struct wacom *wacom = ptr;
- usb_unlink_urb(&wacom->irq);
+ usb_unlink_urb(wacom->irq);
input_unregister_device(&wacom->dev);
+ usb_free_urb(wacom->irq);
kfree(wacom);
}
diff --git a/drivers/video/Config.in b/drivers/video/Config.in
index ffb3a7160..1d92c99c2 100644
--- a/drivers/video/Config.in
+++ b/drivers/video/Config.in
@@ -143,6 +143,7 @@ if [ "$CONFIG_FB" = "y" ]; then
bool ' SIS 630/540/730 support' CONFIG_FB_SIS_300
bool ' SIS 315H/315 support' CONFIG_FB_SIS_315
fi
+ tristate ' NeoMagic display support (EXPERIMENTAL)' CONFIG_FB_NEOMAGIC
tristate ' 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX
tristate ' 3Dfx Voodoo Graphics (sst1) support (EXPERIMENTAL)' CONFIG_FB_VOODOO1
fi
@@ -268,7 +269,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \
"$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \
"$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_TX3912" = "y" -o \
- "$CONFIG_FB_SIS" = "y" ]; then
+ "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" ]; then
define_tristate CONFIG_FBCON_CFB8 y
else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
@@ -288,7 +289,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_PMAG_BA" = "m" -o "$CONFIG_FB_PMAGB_B" = "m" -o \
"$CONFIG_FB_MAXINE" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
- "$CONFIG_FB_TX3912" = "m" ]; then
+ "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_NEOMAGIC" = "m" ]; then
define_tristate CONFIG_FBCON_CFB8 m
fi
fi
@@ -304,7 +305,8 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
- "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" ]; then
+ "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \
+ "$CONFIG_FB_NEOMAGIC" = "y" ]; then
define_tristate CONFIG_FBCON_CFB16 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
@@ -319,7 +321,8 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
- "$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_VOODOO1" = "m" ]; then
+ "$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_VOODOO1" = "m" -o \
+ "$CONFIG_FB_NEOMAGIC" = "m" ]; then
define_tristate CONFIG_FBCON_CFB16 m
fi
fi
@@ -328,7 +331,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
"$CONFIG_FB_ATY128" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \
- "$CONFIG_FB_VOODOO1" = "y" ]; then
+ "$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" ]; then
define_tristate CONFIG_FBCON_CFB24 y
else
if [ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
@@ -336,7 +339,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
"$CONFIG_FB_ATY128" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_PVR2" = "m" -o \
- "$CONFIG_FB_VOODOO1" = "m" ]; then
+ "$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_NEOMAGIC" = "y" ]; then
define_tristate CONFIG_FBCON_CFB24 m
fi
fi
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index f3d69708b..c08b4ea75 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_FB_Q40) += q40fb.o
obj-$(CONFIG_FB_ATARI) += atafb.o
obj-$(CONFIG_FB_ATY128) += aty128fb.o
obj-$(CONFIG_FB_RADEON) += radeonfb.o
+obj-$(CONFIG_FB_NEOMAGIC) += neofb.o
obj-$(CONFIG_FB_IGA) += igafb.o
obj-$(CONFIG_FB_CONTROL) += controlfb.o
obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c
index 7bb2b5122..39d964687 100644
--- a/drivers/video/S3triofb.c
+++ b/drivers/video/S3triofb.c
@@ -554,7 +554,7 @@ static void __init s3triofb_of_init(struct device_node *dp)
strcpy(fb_info.modename, "Trio64 ");
strncat(fb_info.modename, dp->full_name, sizeof(fb_info.modename));
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &s3trio_ops;
#if 0
fb_info.fbvar_num = 1;
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 8a9a1a889..332e52863 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -1318,7 +1318,7 @@ acornfb_init_fbinfo(void)
strcpy(fb_info.modename, "Acorn");
strcpy(fb_info.fontname, "Acorn8x8");
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &acornfb_ops;
fb_info.disp = &global_disp;
fb_info.changevar = NULL;
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index cab58a763..fadb7f0a8 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -1730,7 +1730,7 @@ default_chipset:
strcpy(fb_info.modename, amifb_name);
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &amifb_ops;
fb_info.disp = &disp;
fb_info.switch_con = &amifbcon_switch;
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 8db29f44a..73339ab4c 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -2828,7 +2828,7 @@ int __init atafb_init(void)
strcpy(fb_info.modename, "Atari Builtin ");
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &atafb_ops;
fb_info.disp = &disp;
fb_info.switch_con = &atafb_switch;
diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c
index 7168d0dff..77ebcf9e6 100644
--- a/drivers/video/aty128fb.c
+++ b/drivers/video/aty128fb.c
@@ -1704,7 +1704,7 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
/* fill in info */
strcpy(info->fb_info.modename, aty128fb_name);
- info->fb_info.node = -1;
+ info->fb_info.node = NODEV;
info->fb_info.fbops = &aty128fb_ops;
info->fb_info.disp = &info->disp;
strcpy(info->fb_info.fontname, fontname);
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index d1db4fb29..fedcdc15e 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -578,7 +578,7 @@ static void __init init_chips(struct fb_info_chips *p)
p->disp.scrollmode = SCROLL_YREDRAW;
strcpy(p->info.modename, p->fix.id);
- p->info.node = -1;
+ p->info.node = NODEV;
p->info.fbops = &chipsfb_ops;
p->info.disp = &p->disp;
p->info.fontname[0] = 0;
diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c
index 46808a559..5a48f270a 100644
--- a/drivers/video/clgenfb.c
+++ b/drivers/video/clgenfb.c
@@ -2758,7 +2758,7 @@ int __init clgenfb_init(void)
sizeof (fb_info->gen.info.modename));
fb_info->gen.info.modename [sizeof (fb_info->gen.info.modename) - 1] = 0;
- fb_info->gen.info.node = -1;
+ fb_info->gen.info.node = NODEV;
fb_info->gen.info.fbops = &clgenfb_ops;
fb_info->gen.info.disp = &disp;
fb_info->gen.info.changevar = NULL;
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 3b42d082a..0193fff5a 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -1376,7 +1376,7 @@ static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_c
static void __init control_init_info(struct fb_info *info, struct fb_info_control *p)
{
strcpy(info->modename, "control");
- info->node = -1; /* ??? danj */
+ info->node = NODEV;
info->fbops = &controlfb_ops;
info->disp = &p->display;
strcpy(info->fontname, fontname);
diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c
index f7925485b..d0133f694 100644
--- a/drivers/video/cyberfb.c
+++ b/drivers/video/cyberfb.c
@@ -1085,7 +1085,7 @@ int __init cyberfb_init(void)
strcpy(fb_info.modename, cyberfb_name);
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &cyberfb_ops;
fb_info.disp = &disp;
fb_info.switch_con = &Cyberfb_switch;
diff --git a/drivers/video/dn_cfb4.c b/drivers/video/dn_cfb4.c
index 3d1f98b41..f4b18798e 100644
--- a/drivers/video/dn_cfb4.c
+++ b/drivers/video/dn_cfb4.c
@@ -305,7 +305,7 @@ printk("dn_fb_init\n");
fb_info.switch_con=&dnfbcon_switch;
fb_info.updatevar=&dnfbcon_updatevar;
fb_info.blank=&dnfbcon_blank;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &dn_fb_ops;
fb_info.flags = FBINFO_FLAG_DEFAULT;
diff --git a/drivers/video/dn_cfb8.c b/drivers/video/dn_cfb8.c
index 6b51230a8..b0601ea39 100644
--- a/drivers/video/dn_cfb8.c
+++ b/drivers/video/dn_cfb8.c
@@ -292,7 +292,7 @@ printk("dn_fb_init\n");
fb_info.switch_con=&dnfbcon_switch;
fb_info.updatevar=&dnfbcon_updatevar;
fb_info.blank=&dnfbcon_blank;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &dn_fb_ops;
printk("dn_fb_init: register\n");
diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c
index 27c380707..8da6c0a0e 100644
--- a/drivers/video/dnfb.c
+++ b/drivers/video/dnfb.c
@@ -307,7 +307,7 @@ unsigned long __init dnfb_init(unsigned long mem_start) {
fb_info.switch_con=&dnfbcon_switch;
fb_info.updatevar=&dnfbcon_updatevar;
fb_info.blank=&dnfbcon_blank;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &dn_fb_ops;
dn_fb_get_var(&disp[0].var,0, &fb_info);
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index 059389c23..2da7098c1 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -500,7 +500,7 @@ int __init e1355fb_init(void)
fb_info.gen.fbhw->detect();
strcpy(fb_info.gen.info.modename, "SED1355");
fb_info.gen.info.changevar = NULL;
- fb_info.gen.info.node = -1;
+ fb_info.gen.info.node = NODEV;
fb_info.gen.info.fbops = &e1355fb_ops;
fb_info.gen.info.disp = &disp;
fb_info.gen.parsize = sizeof(struct e1355_par);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 0caef8f0d..2fa789475 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -73,6 +73,8 @@ extern int atyfb_init(void);
extern int atyfb_setup(char*);
extern int aty128fb_init(void);
extern int aty128fb_setup(char*);
+extern int neofb_init(void);
+extern int neofb_setup(char*);
extern int igafb_init(void);
extern int igafb_setup(char*);
extern int imsttfb_init(void);
@@ -173,6 +175,9 @@ static struct {
#ifdef CONFIG_FB_ATY128
{ "aty128fb", aty128fb_init, aty128fb_setup },
#endif
+#ifdef CONFIG_FB_NEOMAGIC
+ { "neo", neofb_init, neofb_setup },
+#endif
#ifdef CONFIG_FB_VIRGE
{ "virge", virgefb_init, virgefb_setup },
#endif
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
index 1f4883c78..c8f31e2c4 100644
--- a/drivers/video/fm2fb.c
+++ b/drivers/video/fm2fb.c
@@ -401,7 +401,7 @@ int __init fm2fb_init(void)
disp.scrollmode = SCROLL_YREDRAW;
strcpy(fb_info.modename, fb_fix.id);
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &fm2fb_ops;
fb_info.disp = &disp;
fb_info.fontname[0] = '\0';
diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c
index 0ea7aa5f5..87e55ed53 100644
--- a/drivers/video/g364fb.c
+++ b/drivers/video/g364fb.c
@@ -378,7 +378,7 @@ int __init g364fb_init(void)
disp.dispsw = &fbcon_g364cfb8;
strcpy(fb_info.modename, fb_fix.id);
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &g364fb_ops;
fb_info.disp = &disp;
fb_info.fontname[0] = '\0';
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index 61b6ce730..34d662135 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -742,7 +742,7 @@ int __init hgafb_init(void)
disp.scrollmode = SCROLL_YREDRAW;
strcpy (fb_info.modename, hga_fix.id);
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.flags = FBINFO_FLAG_DEFAULT;
/* fb_info.open = ??? */
fb_info.var = hga_default_var;
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 2f0dbf0f1..2ce31c836 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -344,7 +344,7 @@ static struct fb_ops hitfb_ops = {
int __init hitfb_init(void)
{
strcpy(fb_info.gen.info.modename, "Hitachi HD64461");
- fb_info.gen.info.node = -1;
+ fb_info.gen.info.node = NODEV;
fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
fb_info.gen.info.fbops = &hitfb_ops;
fb_info.gen.info.disp = &fb_info.disp;
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index bddf068ab..e39cd2466 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -328,7 +328,7 @@ int __init hpfb_init_one(unsigned long base)
*/
strcpy(fb_info.modename, "Topcat");
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &hpfb_ops;
fb_info.disp = &disp;
fb_info.switch_con = &hpfb_switch;
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 8daf36364..ec14056ac 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -568,7 +568,7 @@ static int __init iga_init(struct fb_info_iga *info)
}
strcpy(info->fb_info.modename, igafb_name);
- info->fb_info.node = -1;
+ info->fb_info.node = NODEV;
info->fb_info.fbops = &igafb_ops;
info->fb_info.disp = &info->disp;
strcpy(info->fb_info.fontname, fontname);
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 2030ab596..b3ef1541d 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -1866,7 +1866,7 @@ init_imstt(struct fb_info_imstt *p)
strcpy(p->info.modename, p->fix.id);
strcpy(p->info.fontname, fontname);
- p->info.node = -1;
+ p->info.node = NODEV;
p->info.fbops = &imsttfb_ops;
p->info.disp = &p->disp;
p->info.changevar = 0;
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index df9602d53..b80f26565 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -1221,7 +1221,7 @@ void __init macfb_init(void)
}
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &macfb_ops;
fb_info.disp = &disp;
fb_info.switch_con = &macfb_switch;
diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c
index 099ac0cda..614d051c6 100644
--- a/drivers/video/maxinefb.c
+++ b/drivers/video/maxinefb.c
@@ -358,7 +358,7 @@ int __init maxinefb_init(void)
strcpy(fb_info.modename, "Maxine onboard graphics 1024x768x8");
/* fb_info.modename: maximum of 39 characters + trailing nullbyte, KM */
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &maxinefb_ops;
fb_info.disp = &disp;
fb_info.switch_con = &maxinefb_switch;
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
new file mode 100644
index 000000000..43a48ca80
--- /dev/null
+++ b/drivers/video/neofb.c
@@ -0,0 +1,2421 @@
+/*
+ * linux/drivers/video/neofb.c -- NeoMagic Framebuffer Driver
+ *
+ * Copyright (c) 2001 Denis Oliver Kropp <dok@convergence.de>
+ *
+ *
+ * Card specific code is based on XFree86's neomagic driver.
+ * Framebuffer framework code is based on code of cyber2000fb.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ *
+ * 0.3.1
+ * - added module license (dok)
+ *
+ * 0.3
+ * - hardware accelerated clear and move for 2200 and above (dok)
+ * - maximum allowed dotclock is handled now (dok)
+ *
+ * 0.2.1
+ * - correct panning after X usage (dok)
+ * - added module and kernel parameters (dok)
+ * - no stretching if external display is enabled (dok)
+ *
+ * 0.2
+ * - initial version (dok)
+ *
+ *
+ * TODO
+ * - ioctl for internal/external switching
+ * - blanking
+ * - 32bit depth support, maybe impossible
+ * - disable pan-on-sync, need specs
+ *
+ * BUGS
+ * - white margin on bootup like with tdfxfb (colormap problem?)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
+#include "neofb.h"
+
+
+#define NEOFB_VERSION "0.3.1"
+
+/* --------------------------------------------------------------------- */
+
+static int disabled = 0;
+static int internal = 0;
+static int external = 0;
+static int nostretch = 0;
+static int nopciburst = 0;
+
+
+#ifdef MODULE
+
+MODULE_AUTHOR("(c) 2001-2002 Denis Oliver Kropp <dok@convergence.de>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips");
+MODULE_PARM(disabled, "i");
+MODULE_PARM_DESC(disabled, "Disable this driver's initialization.");
+MODULE_PARM(internal, "i");
+MODULE_PARM_DESC(internal, "Enable output on internal LCD Display.");
+MODULE_PARM(external, "i");
+MODULE_PARM_DESC(external, "Enable output on external CRT.");
+MODULE_PARM(nostretch, "i");
+MODULE_PARM_DESC(nostretch, "Disable stretching of modes smaller than LCD.");
+MODULE_PARM(nopciburst, "i");
+MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");
+
+#endif
+
+
+/* --------------------------------------------------------------------- */
+
+static biosMode bios8[] = {
+ { 320, 240, 0x40 },
+ { 300, 400, 0x42 },
+ { 640, 400, 0x20 },
+ { 640, 480, 0x21 },
+ { 800, 600, 0x23 },
+ { 1024, 768, 0x25 },
+};
+
+static biosMode bios16[] = {
+ { 320, 200, 0x2e },
+ { 320, 240, 0x41 },
+ { 300, 400, 0x43 },
+ { 640, 480, 0x31 },
+ { 800, 600, 0x34 },
+ { 1024, 768, 0x37 },
+};
+
+static biosMode bios24[] = {
+ { 640, 480, 0x32 },
+ { 800, 600, 0x35 },
+ { 1024, 768, 0x38 }
+};
+
+#ifdef NO_32BIT_SUPPORT_YET
+/* FIXME: guessed values, wrong */
+static biosMode bios32[] = {
+ { 640, 480, 0x33 },
+ { 800, 600, 0x36 },
+ { 1024, 768, 0x39 }
+ };
+#endif
+
+static int neoFindMode (int xres, int yres, int depth)
+{
+ int xres_s;
+ int i, size;
+ biosMode *mode;
+
+ switch (depth)
+ {
+ case 8:
+ size = sizeof(bios8) / sizeof(biosMode);
+ mode = bios8;
+ break;
+ case 16:
+ size = sizeof(bios16) / sizeof(biosMode);
+ mode = bios16;
+ break;
+ case 24:
+ size = sizeof(bios24) / sizeof(biosMode);
+ mode = bios24;
+ break;
+#ifdef NO_32BIT_SUPPORT_YET
+ case 32:
+ size = sizeof(bios32) / sizeof(biosMode);
+ mode = bios32;
+ break;
+#endif
+ default:
+ return 0;
+ }
+
+ for (i = 0; i < size; i++)
+ {
+ if (xres <= mode[i].x_res)
+ {
+ xres_s = mode[i].x_res;
+ for (; i < size; i++)
+ {
+ if (mode[i].x_res != xres_s)
+ return mode[i-1].mode;
+ if (yres <= mode[i].y_res)
+ return mode[i].mode;
+ }
+ }
+ }
+ return mode[size - 1].mode;
+}
+
+/* -------------------- Hardware specific routines ------------------------- */
+
+/*
+ * Hardware Acceleration for Neo2200+
+ */
+static inline void neo2200_wait_idle (struct neofb_info *fb)
+{
+ int waitcycles;
+
+ while (fb->neo2200->bltStat & 1)
+ waitcycles++;
+}
+
+static inline void neo2200_wait_fifo (struct neofb_info *fb,
+ int requested_fifo_space)
+{
+ // ndev->neo.waitfifo_calls++;
+ // ndev->neo.waitfifo_sum += requested_fifo_space;
+
+ /* FIXME: does not work
+ if (neo_fifo_space < requested_fifo_space)
+ {
+ neo_fifo_waitcycles++;
+
+ while (1)
+ {
+ neo_fifo_space = (neo2200->bltStat >> 8);
+ if (neo_fifo_space >= requested_fifo_space)
+ break;
+ }
+ }
+ else
+ {
+ neo_fifo_cache_hits++;
+ }
+
+ neo_fifo_space -= requested_fifo_space;
+ */
+
+ neo2200_wait_idle (fb);
+}
+
+static inline void neo2200_accel_init (struct neofb_info *fb,
+ struct fb_var_screeninfo *var)
+{
+ Neo2200 *neo2200 = fb->neo2200;
+ u32 bltMod, pitch;
+
+ neo2200_wait_idle (fb);
+
+ switch (var->bits_per_pixel)
+ {
+ case 8:
+ bltMod = NEO_MODE1_DEPTH8;
+ pitch = var->xres_virtual;
+ break;
+ case 15:
+ case 16:
+ bltMod = NEO_MODE1_DEPTH16;
+ pitch = var->xres_virtual * 2;
+ break;
+ default:
+ printk( KERN_ERR "neofb: neo2200_accel_init: unexpected bits per pixel!\n" );
+ return;
+ }
+
+ neo2200->bltStat = bltMod << 16;
+ neo2200->pitch = (pitch << 16) | pitch;
+}
+
+static void neo2200_accel_setup (struct display *p)
+{
+ struct neofb_info *fb = (struct neofb_info *)p->fb_info;
+ struct fb_var_screeninfo *var = &p->fb_info->var;
+
+ fb->dispsw->setup(p);
+
+ neo2200_accel_init (fb, var);
+}
+
+static void
+neo2200_accel_bmove (struct display *p, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+ struct neofb_info *fb = (struct neofb_info *)p->fb_info;
+ struct fb_var_screeninfo *var = &p->fb_info->var;
+ Neo2200 *neo2200 = fb->neo2200;
+ u_long src, dst;
+ int bpp, pitch, inc_y;
+ u_int fh, fw;
+
+ /* setting blitting direction does not work, so this case is unaccelerated */
+ if (sx != dx)
+ {
+ neo2200_wait_idle (fb);
+ fb->dispsw->bmove(p, sy, sx, dy, dx, height, width);
+ return;
+ }
+
+ bpp = (var->bits_per_pixel+7) / 8;
+ pitch = var->xres_virtual * bpp;
+
+ fw = fontwidth(p);
+ sx *= fw * bpp;
+ dx *= fw * bpp;
+ width *= fw;
+
+ fh = fontheight(p);
+ sy *= fh;
+ dy *= fh;
+
+ if (sy > dy)
+ inc_y = fh;
+ else
+ {
+ inc_y = -fh;
+ sy += (height - 1) * fh;
+ dy += (height - 1) * fh;
+ }
+
+ neo2200_wait_fifo (fb, 1);
+
+ /* set blt control */
+ neo2200->bltCntl = NEO_BC3_FIFO_EN |
+ NEO_BC3_SKIP_MAPPING | 0x0c0000;
+
+ /* looks silly, but setting the blitting direction did not work */
+ while (height--)
+ {
+ src = sx + sy * pitch;
+ dst = dx + dy * pitch;
+
+ neo2200_wait_fifo (fb, 3);
+
+ neo2200->srcStart = src;
+ neo2200->dstStart = dst;
+ neo2200->xyExt = (fh << 16) | (width & 0xffff);
+
+ sy += inc_y;
+ dy += inc_y;
+ }
+}
+
+static void
+neo2200_accel_clear (struct vc_data *conp, struct display *p, int sy, int sx,
+ int height, int width)
+{
+ struct neofb_info *fb = (struct neofb_info *)p->fb_info;
+ struct fb_var_screeninfo *var = &p->fb_info->var;
+ Neo2200 *neo2200 = fb->neo2200;
+ u_long dst;
+ u_int fw, fh;
+ u32 bgx = attr_bgcol_ec(p, conp);
+
+ fw = fontwidth(p);
+ fh = fontheight(p);
+
+ dst = sx * fw + sy * var->xres_virtual * fh;
+ width = width * fw;
+ height = height * fh;
+
+ neo2200_wait_fifo (fb, 4);
+
+ /* set blt control */
+ neo2200->bltCntl = NEO_BC3_FIFO_EN |
+ NEO_BC0_SRC_IS_FG |
+ NEO_BC3_SKIP_MAPPING | 0x0c0000;
+
+ switch (var->bits_per_pixel)
+ {
+ case 8:
+ neo2200->fgColor = bgx;
+ break;
+ case 16:
+ neo2200->fgColor = ((u16 *)(p->fb_info)->pseudo_palette)[bgx];
+ break;
+ }
+
+ neo2200->dstStart = dst * ((var->bits_per_pixel+7) / 8);
+
+ neo2200->xyExt = (height << 16) | (width & 0xffff);
+}
+
+static void
+neo2200_accel_putc (struct vc_data *conp, struct display *p, int c,
+ int yy, int xx)
+{
+ struct neofb_info *fb = (struct neofb_info *)p->fb_info;
+
+ neo2200_wait_idle (fb);
+ fb->dispsw->putc(conp, p, c, yy, xx);
+}
+
+static void
+neo2200_accel_putcs (struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count, int yy, int xx)
+{
+ struct neofb_info *fb = (struct neofb_info *)p->fb_info;
+
+ neo2200_wait_idle (fb);
+ fb->dispsw->putcs(conp, p, s, count, yy, xx);
+}
+
+static void neo2200_accel_revc (struct display *p, int xx, int yy)
+{
+ struct neofb_info *fb = (struct neofb_info *)p->fb_info;
+
+ neo2200_wait_idle (fb);
+ fb->dispsw->revc (p, xx, yy);
+}
+
+static void
+neo2200_accel_clear_margins (struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ struct neofb_info *fb = (struct neofb_info *)p->fb_info;
+
+ fb->dispsw->clear_margins (conp, p, bottom_only);
+}
+
+static struct display_switch fbcon_neo2200_accel = {
+ setup: neo2200_accel_setup,
+ bmove: neo2200_accel_bmove,
+ clear: neo2200_accel_clear,
+ putc: neo2200_accel_putc,
+ putcs: neo2200_accel_putcs,
+ revc: neo2200_accel_revc,
+ clear_margins: neo2200_accel_clear_margins,
+ fontwidthmask: FONTWIDTH(8)|FONTWIDTH(16)
+};
+
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Set a single color register. Return != 0 for invalid regno.
+ */
+static int neo_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *fb)
+{
+ struct neofb_info *info = (struct neofb_info *)fb;
+
+ if (regno >= NR_PALETTE)
+ return -EINVAL;
+
+ info->palette[regno].red = red;
+ info->palette[regno].green = green;
+ info->palette[regno].blue = blue;
+ info->palette[regno].transp = transp;
+
+ switch (fb->var.bits_per_pixel)
+ {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ outb(regno, 0x3c8);
+
+ outb(red >> 10, 0x3c9);
+ outb(green >> 10, 0x3c9);
+ outb(blue >> 10, 0x3c9);
+ break;
+#endif
+
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ if (regno < 16)
+ ((u16 *)fb->pseudo_palette)[regno] = ((red & 0xf800) ) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11);
+ break;
+#endif
+
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ if (regno < 16)
+ ((u32 *)fb->pseudo_palette)[regno] = ((red & 0xff00) << 8) |
+ ((green & 0xff00) ) |
+ ((blue & 0xff00) >> 8);
+ break;
+#endif
+
+#ifdef NO_32BIT_SUPPORT_YET
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ if (regno < 16)
+ ((u32 *)fb->pseudo_palette)[regno] = ((transp & 0xff00) << 16) |
+ ((red & 0xff00) << 8) |
+ ((green & 0xff00) ) |
+ ((blue & 0xff00) >> 8);
+ break;
+#endif
+#endif
+
+ default:
+ return 1;
+ }
+
+ return 0;
+}
+
+static void vgaHWLock (void)
+{
+ /* Protect CRTC[0-7] */
+ VGAwCR (0x11, VGArCR (0x11) | 0x80);
+}
+
+static void vgaHWUnlock (void)
+{
+ /* Unprotect CRTC[0-7] */
+ VGAwCR (0x11, VGArCR (0x11) & ~0x80);
+}
+
+static void neoLock (void)
+{
+ VGAwGR (0x09, 0x00);
+ vgaHWLock();
+}
+
+static void neoUnlock (void)
+{
+ vgaHWUnlock();
+ VGAwGR (0x09, 0x26);
+}
+
+/*
+ * vgaHWSeqReset
+ * perform a sequencer reset.
+ */
+void
+vgaHWSeqReset(int start)
+{
+ if (start)
+ VGAwSEQ (0x00, 0x01); /* Synchronous Reset */
+ else
+ VGAwSEQ (0x00, 0x03); /* End Reset */
+}
+
+void
+vgaHWProtect(int on)
+{
+ unsigned char tmp;
+
+ if (on)
+ {
+ /*
+ * Turn off screen and disable sequencer.
+ */
+ tmp = VGArSEQ (0x01);
+
+ vgaHWSeqReset (1); /* start synchronous reset */
+ VGAwSEQ (0x01, tmp | 0x20); /* disable the display */
+
+ VGAenablePalette();
+ }
+ else
+ {
+ /*
+ * Reenable sequencer, then turn on screen.
+ */
+
+ tmp = VGArSEQ (0x01);
+
+ VGAwSEQ (0x01, tmp & ~0x20); /* reenable display */
+ vgaHWSeqReset (0); /* clear synchronousreset */
+
+ VGAdisablePalette();
+ }
+}
+
+static void vgaHWRestore (const struct neofb_info *info,
+ const struct neofb_par *par)
+{
+ int i;
+
+ VGAwMISC (par->MiscOutReg);
+
+ for (i = 1; i < 5; i++)
+ VGAwSEQ (i, par->Sequencer[i]);
+
+ /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
+ VGAwCR (17, par->CRTC[17] & ~0x80);
+
+ for (i = 0; i < 25; i++)
+ VGAwCR (i, par->CRTC[i]);
+
+ for (i = 0; i < 9; i++)
+ VGAwGR (i, par->Graphics[i]);
+
+ VGAenablePalette();
+
+ for (i = 0; i < 21; i++)
+ VGAwATTR (i, par->Attribute[i]);
+
+ VGAdisablePalette();
+}
+
+static void neofb_set_par (struct neofb_info *info,
+ const struct neofb_par *par)
+{
+ unsigned char temp;
+ int i;
+ int clock_hi = 0;
+
+ DBG("neofb_set_par");
+
+ neoUnlock();
+
+ vgaHWProtect (1); /* Blank the screen */
+
+ /* linear colormap for non palettized modes */
+ switch (par->depth)
+ {
+ case 8:
+ break;
+ case 16:
+ for (i=0; i<64; i++)
+ {
+ outb(i, 0x3c8);
+
+ outb(i << 1, 0x3c9);
+ outb(i, 0x3c9);
+ outb(i << 1, 0x3c9);
+ }
+ break;
+ case 24:
+#ifdef NO_32BIT_SUPPORT_YET
+ case 32:
+#endif
+ for (i=0; i<256; i++)
+ {
+ outb(i, 0x3c8);
+
+ outb(i, 0x3c9);
+ outb(i, 0x3c9);
+ outb(i, 0x3c9);
+ }
+ break;
+ }
+
+ /* alread unlocked above */
+ /* BOGUS VGAwGR (0x09, 0x26);*/
+
+ /* don't know what this is, but it's 0 from bootup anyway */
+ VGAwGR (0x15, 0x00);
+
+ /* was set to 0x01 by my bios in text and vesa modes */
+ VGAwGR (0x0A, par->GeneralLockReg);
+
+ /*
+ * The color mode needs to be set before calling vgaHWRestore
+ * to ensure the DAC is initialized properly.
+ *
+ * NOTE: Make sure we don't change bits make sure we don't change
+ * any reserved bits.
+ */
+ temp = VGArGR(0x90);
+ switch (info->accel)
+ {
+ case FB_ACCEL_NEOMAGIC_NM2070:
+ temp &= 0xF0; /* Save bits 7:4 */
+ temp |= (par->ExtColorModeSelect & ~0xF0);
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2090:
+ case FB_ACCEL_NEOMAGIC_NM2093:
+ case FB_ACCEL_NEOMAGIC_NM2097:
+ case FB_ACCEL_NEOMAGIC_NM2160:
+ case FB_ACCEL_NEOMAGIC_NM2200:
+ case FB_ACCEL_NEOMAGIC_NM2230:
+ case FB_ACCEL_NEOMAGIC_NM2360:
+ case FB_ACCEL_NEOMAGIC_NM2380:
+ temp &= 0x70; /* Save bits 6:4 */
+ temp |= (par->ExtColorModeSelect & ~0x70);
+ break;
+ }
+
+ VGAwGR(0x90,temp);
+
+ /*
+ * In some rare cases a lockup might occur if we don't delay
+ * here. (Reported by Miles Lane)
+ */
+ //mdelay(200);
+
+ /*
+ * Disable horizontal and vertical graphics and text expansions so
+ * that vgaHWRestore works properly.
+ */
+ temp = VGArGR(0x25);
+ temp &= 0x39;
+ VGAwGR (0x25, temp);
+
+ /*
+ * Sleep for 200ms to make sure that the two operations above have
+ * had time to take effect.
+ */
+ mdelay(200);
+
+ /*
+ * This function handles restoring the generic VGA registers. */
+ vgaHWRestore (info, par);
+
+
+ VGAwGR(0x0E, par->ExtCRTDispAddr);
+ VGAwGR(0x0F, par->ExtCRTOffset);
+ temp = VGArGR(0x10);
+ temp &= 0x0F; /* Save bits 3:0 */
+ temp |= (par->SysIfaceCntl1 & ~0x0F); /* VESA Bios sets bit 1! */
+ VGAwGR(0x10, temp);
+
+ VGAwGR(0x11, par->SysIfaceCntl2);
+ VGAwGR(0x15, 0 /*par->SingleAddrPage*/);
+ VGAwGR(0x16, 0 /*par->DualAddrPage*/);
+
+ temp = VGArGR(0x20);
+ switch (info->accel)
+ {
+ case FB_ACCEL_NEOMAGIC_NM2070:
+ temp &= 0xFC; /* Save bits 7:2 */
+ temp |= (par->PanelDispCntlReg1 & ~0xFC);
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2090:
+ case FB_ACCEL_NEOMAGIC_NM2093:
+ case FB_ACCEL_NEOMAGIC_NM2097:
+ case FB_ACCEL_NEOMAGIC_NM2160:
+ temp &= 0xDC; /* Save bits 7:6,4:2 */
+ temp |= (par->PanelDispCntlReg1 & ~0xDC);
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2200:
+ case FB_ACCEL_NEOMAGIC_NM2230:
+ case FB_ACCEL_NEOMAGIC_NM2360:
+ case FB_ACCEL_NEOMAGIC_NM2380:
+ temp &= 0x98; /* Save bits 7,4:3 */
+ temp |= (par->PanelDispCntlReg1 & ~0x98);
+ break;
+ }
+ VGAwGR(0x20, temp);
+
+ temp = VGArGR(0x25);
+ temp &= 0x38; /* Save bits 5:3 */
+ temp |= (par->PanelDispCntlReg2 & ~0x38);
+ VGAwGR(0x25, temp);
+
+ if (info->accel != FB_ACCEL_NEOMAGIC_NM2070)
+ {
+ temp = VGArGR(0x30);
+ temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */
+ temp |= (par->PanelDispCntlReg3 & ~0xEF);
+ VGAwGR(0x30, temp);
+ }
+
+ VGAwGR(0x28, par->PanelVertCenterReg1);
+ VGAwGR(0x29, par->PanelVertCenterReg2);
+ VGAwGR(0x2a, par->PanelVertCenterReg3);
+
+ if (info->accel != FB_ACCEL_NEOMAGIC_NM2070)
+ {
+ VGAwGR(0x32, par->PanelVertCenterReg4);
+ VGAwGR(0x33, par->PanelHorizCenterReg1);
+ VGAwGR(0x34, par->PanelHorizCenterReg2);
+ VGAwGR(0x35, par->PanelHorizCenterReg3);
+ }
+
+ if (info->accel == FB_ACCEL_NEOMAGIC_NM2160)
+ VGAwGR(0x36, par->PanelHorizCenterReg4);
+
+ if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 ||
+ info->accel == FB_ACCEL_NEOMAGIC_NM2230 ||
+ info->accel == FB_ACCEL_NEOMAGIC_NM2360 ||
+ info->accel == FB_ACCEL_NEOMAGIC_NM2380)
+ {
+ VGAwGR(0x36, par->PanelHorizCenterReg4);
+ VGAwGR(0x37, par->PanelVertCenterReg5);
+ VGAwGR(0x38, par->PanelHorizCenterReg5);
+
+ clock_hi = 1;
+ }
+
+ /* Program VCLK3 if needed. */
+ if (par->ProgramVCLK
+ && ((VGArGR(0x9B) != par->VCLK3NumeratorLow)
+ || (VGArGR(0x9F) != par->VCLK3Denominator)
+ || (clock_hi && ((VGArGR(0x8F) & ~0x0f)
+ != (par->VCLK3NumeratorHigh & ~0x0F)))))
+ {
+ VGAwGR(0x9B, par->VCLK3NumeratorLow);
+ if (clock_hi)
+ {
+ temp = VGArGR(0x8F);
+ temp &= 0x0F; /* Save bits 3:0 */
+ temp |= (par->VCLK3NumeratorHigh & ~0x0F);
+ VGAwGR(0x8F, temp);
+ }
+ VGAwGR(0x9F, par->VCLK3Denominator);
+ }
+
+ if (par->biosMode)
+ VGAwCR(0x23, par->biosMode);
+
+ VGAwGR (0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */
+
+ /* Program vertical extension register */
+ if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 ||
+ info->accel == FB_ACCEL_NEOMAGIC_NM2230 ||
+ info->accel == FB_ACCEL_NEOMAGIC_NM2360 ||
+ info->accel == FB_ACCEL_NEOMAGIC_NM2380)
+ {
+ VGAwCR(0x70, par->VerticalExt);
+ }
+
+
+ vgaHWProtect (0); /* Turn on screen */
+
+ /* Calling this also locks offset registers required in update_start */
+ neoLock();
+}
+
+static void neofb_update_start (struct neofb_info *info, struct fb_var_screeninfo *var)
+{
+ int oldExtCRTDispAddr;
+ int Base;
+
+ DBG("neofb_update_start");
+
+ Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2;
+ Base *= (var->bits_per_pixel + 7) / 8;
+
+ neoUnlock();
+
+ /*
+ * These are the generic starting address registers.
+ */
+ VGAwCR(0x0C, (Base & 0x00FF00) >> 8);
+ VGAwCR(0x0D, (Base & 0x00FF));
+
+ /*
+ * Make sure we don't clobber some other bits that might already
+ * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
+ * be needed.
+ */
+ oldExtCRTDispAddr = VGArGR(0x0E);
+ VGAwGR(0x0E,(((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
+
+ neoLock();
+}
+
+/*
+ * Set the Colormap
+ */
+static int neofb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *fb)
+{
+ struct neofb_info *info = (struct neofb_info *)fb;
+ struct display* disp = (con < 0) ? fb->disp : (fb_display + con);
+ struct fb_cmap *dcmap = &disp->cmap;
+ int err = 0;
+
+ /* no colormap allocated? */
+ if (!dcmap->len)
+ {
+ int size;
+
+ if (fb->var.bits_per_pixel == 8)
+ size = NR_PALETTE;
+ else
+ size = 32;
+
+ err = fb_alloc_cmap (dcmap, size, 0);
+ }
+
+ /*
+ * we should be able to remove this test once fbcon has been
+ * "improved" --rmk
+ */
+ if (!err && con == info->currcon)
+ {
+ err = fb_set_cmap (cmap, kspc, neo_setcolreg, fb);
+ dcmap = &fb->cmap;
+ }
+
+ if (!err)
+ fb_copy_cmap (cmap, dcmap, kspc ? 0 : 1);
+
+ return err;
+}
+
+/*
+ * neoCalcVCLK --
+ *
+ * Determine the closest clock frequency to the one requested.
+ */
+#define REF_FREQ 14.31818
+#define MAX_N 127
+#define MAX_D 31
+#define MAX_F 1
+
+static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, long freq)
+{
+ int n, d, f;
+ double f_out;
+ double f_diff;
+ int n_best = 0, d_best = 0, f_best = 0;
+ double f_best_diff = 999999.0;
+ double f_target = freq/1000.0;
+
+ for (f = 0; f <= MAX_F; f++)
+ for (n = 0; n <= MAX_N; n++)
+ for (d = 0; d <= MAX_D; d++)
+ {
+ f_out = (n+1.0)/((d+1.0)*(1<<f))*REF_FREQ;
+ f_diff = abs(f_out-f_target);
+ if (f_diff < f_best_diff)
+ {
+ f_best_diff = f_diff;
+ n_best = n;
+ d_best = d;
+ f_best = f;
+ }
+ }
+
+ if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 ||
+ info->accel == FB_ACCEL_NEOMAGIC_NM2230 ||
+ info->accel == FB_ACCEL_NEOMAGIC_NM2360 ||
+ info->accel == FB_ACCEL_NEOMAGIC_NM2380)
+ {
+ /* NOT_DONE: We are trying the full range of the 2200 clock.
+ We should be able to try n up to 2047 */
+ par->VCLK3NumeratorLow = n_best;
+ par->VCLK3NumeratorHigh = (f_best << 7);
+ }
+ else
+ par->VCLK3NumeratorLow = n_best | (f_best << 7);
+
+ par->VCLK3Denominator = d_best;
+
+#ifdef NEOFB_DEBUG
+ printk ("neoVCLK: f:%f NumLow=%d NumHi=%d Den=%d Df=%f\n",
+ f_target,
+ par->VCLK3NumeratorLow,
+ par->VCLK3NumeratorHigh,
+ par->VCLK3Denominator,
+ f_best_diff);
+#endif
+}
+
+/*
+ * vgaHWInit --
+ * Handle the initialization, etc. of a screen.
+ * Return FALSE on failure.
+ */
+
+static int vgaHWInit (const struct fb_var_screeninfo *var,
+ const struct neofb_info *info,
+ struct neofb_par *par,
+ struct xtimings *timings)
+{
+ par->MiscOutReg = 0x23;
+
+ if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
+ par->MiscOutReg |= 0x40;
+
+ if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
+ par->MiscOutReg |= 0x80;
+
+ /*
+ * Time Sequencer
+ */
+ par->Sequencer[0] = 0x00;
+ par->Sequencer[1] = 0x01;
+ par->Sequencer[2] = 0x0F;
+ par->Sequencer[3] = 0x00; /* Font select */
+ par->Sequencer[4] = 0x0E; /* Misc */
+
+ /*
+ * CRTC Controller
+ */
+ par->CRTC[0] = (timings->HTotal >> 3) - 5;
+ par->CRTC[1] = (timings->HDisplay >> 3) - 1;
+ par->CRTC[2] = (timings->HDisplay >> 3) - 1;
+ par->CRTC[3] = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80;
+ par->CRTC[4] = (timings->HSyncStart >> 3);
+ par->CRTC[5] = ((((timings->HTotal >> 3) - 1) & 0x20) << 2)
+ | (((timings->HSyncEnd >> 3)) & 0x1F);
+ par->CRTC[6] = (timings->VTotal - 2) & 0xFF;
+ par->CRTC[7] = (((timings->VTotal - 2) & 0x100) >> 8)
+ | (((timings->VDisplay - 1) & 0x100) >> 7)
+ | ((timings->VSyncStart & 0x100) >> 6)
+ | (((timings->VDisplay - 1) & 0x100) >> 5)
+ | 0x10
+ | (((timings->VTotal - 2) & 0x200) >> 4)
+ | (((timings->VDisplay - 1) & 0x200) >> 3)
+ | ((timings->VSyncStart & 0x200) >> 2);
+ par->CRTC[8] = 0x00;
+ par->CRTC[9] = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40;
+
+ if (timings->dblscan)
+ par->CRTC[9] |= 0x80;
+
+ par->CRTC[10] = 0x00;
+ par->CRTC[11] = 0x00;
+ par->CRTC[12] = 0x00;
+ par->CRTC[13] = 0x00;
+ par->CRTC[14] = 0x00;
+ par->CRTC[15] = 0x00;
+ par->CRTC[16] = timings->VSyncStart & 0xFF;
+ par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20;
+ par->CRTC[18] = (timings->VDisplay - 1) & 0xFF;
+ par->CRTC[19] = var->xres_virtual >> 4;
+ par->CRTC[20] = 0x00;
+ par->CRTC[21] = (timings->VDisplay - 1) & 0xFF;
+ par->CRTC[22] = (timings->VTotal - 1) & 0xFF;
+ par->CRTC[23] = 0xC3;
+ par->CRTC[24] = 0xFF;
+
+ /*
+ * are these unnecessary?
+ * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
+ * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
+ */
+
+ /*
+ * Graphics Display Controller
+ */
+ par->Graphics[0] = 0x00;
+ par->Graphics[1] = 0x00;
+ par->Graphics[2] = 0x00;
+ par->Graphics[3] = 0x00;
+ par->Graphics[4] = 0x00;
+ par->Graphics[5] = 0x40;
+ par->Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */
+ par->Graphics[7] = 0x0F;
+ par->Graphics[8] = 0xFF;
+
+
+ par->Attribute[0] = 0x00; /* standard colormap translation */
+ par->Attribute[1] = 0x01;
+ par->Attribute[2] = 0x02;
+ par->Attribute[3] = 0x03;
+ par->Attribute[4] = 0x04;
+ par->Attribute[5] = 0x05;
+ par->Attribute[6] = 0x06;
+ par->Attribute[7] = 0x07;
+ par->Attribute[8] = 0x08;
+ par->Attribute[9] = 0x09;
+ par->Attribute[10] = 0x0A;
+ par->Attribute[11] = 0x0B;
+ par->Attribute[12] = 0x0C;
+ par->Attribute[13] = 0x0D;
+ par->Attribute[14] = 0x0E;
+ par->Attribute[15] = 0x0F;
+ par->Attribute[16] = 0x41;
+ par->Attribute[17] = 0xFF;
+ par->Attribute[18] = 0x0F;
+ par->Attribute[19] = 0x00;
+ par->Attribute[20] = 0x00;
+
+ return 0;
+}
+
+static int neofb_decode_var (struct fb_var_screeninfo *var,
+ const struct neofb_info *info,
+ struct neofb_par *par)
+{
+ struct xtimings timings;
+ int lcd_stretch;
+ int hoffset, voffset;
+ int memlen, vramlen;
+ int mode_ok = 0;
+ unsigned int pixclock = var->pixclock;
+
+ DBG("neofb_decode_var");
+
+ if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */
+ timings.pixclock = 1000000000 / pixclock;
+ if (timings.pixclock < 1) timings.pixclock = 1;
+ timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
+ timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
+ timings.HDisplay = var->xres;
+ timings.HSyncStart = timings.HDisplay + var->right_margin;
+ timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
+ timings.HTotal = timings.HSyncEnd + var->left_margin;
+ timings.VDisplay = var->yres;
+ timings.VSyncStart = timings.VDisplay + var->lower_margin;
+ timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
+ timings.VTotal = timings.VSyncEnd + var->upper_margin;
+ timings.sync = var->sync;
+
+ if (timings.pixclock > info->maxClock)
+ return -EINVAL;
+
+ /* Is the mode larger than the LCD panel? */
+ if ((var->xres > info->NeoPanelWidth) ||
+ (var->yres > info->NeoPanelHeight))
+ {
+ printk (KERN_INFO "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",
+ var->xres,
+ var->yres,
+ info->NeoPanelWidth,
+ info->NeoPanelHeight);
+ return -EINVAL;
+ }
+
+ /* Is the mode one of the acceptable sizes? */
+ switch (var->xres)
+ {
+ case 1280:
+ if (var->yres == 1024)
+ mode_ok = 1;
+ break;
+ case 1024:
+ if (var->yres == 768)
+ mode_ok = 1;
+ break;
+ case 800:
+ if (var->yres == 600)
+ mode_ok = 1;
+ break;
+ case 640:
+ if (var->yres == 480)
+ mode_ok = 1;
+ break;
+ }
+
+ if (!mode_ok)
+ {
+ printk (KERN_INFO "Mode (%dx%d) won't display properly on LCD\n",
+ var->xres, var->yres);
+ return -EINVAL;
+ }
+
+
+ switch (var->bits_per_pixel)
+ {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ break;
+#endif
+
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ break;
+#endif
+
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ break;
+#endif
+
+#ifdef NO_32BIT_SUPPORT_YET
+# ifdef FBCON_HAS_CFB32
+ case 32:
+ break;
+# endif
+#endif
+
+ default:
+ return -EINVAL;
+ }
+
+ par->depth = var->bits_per_pixel;
+
+ vramlen = info->video.len;
+ if (vramlen > 4*1024*1024)
+ vramlen = 4*1024*1024;
+
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+
+ memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
+ if (memlen > vramlen)
+ {
+ var->yres_virtual = vramlen * 8 / (var->xres_virtual * var->bits_per_pixel);
+ memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
+ }
+
+ /* we must round yres/xres down, we already rounded y/xres_virtual up
+ if it was possible. We should return -EINVAL, but I disagree */
+ if (var->yres_virtual < var->yres)
+ var->yres = var->yres_virtual;
+ if (var->xres_virtual < var->xres)
+ var->xres = var->xres_virtual;
+ if (var->xoffset + var->xres > var->xres_virtual)
+ var->xoffset = var->xres_virtual - var->xres;
+ if (var->yoffset + var->yres > var->yres_virtual)
+ var->yoffset = var->yres_virtual - var->yres;
+
+
+ /*
+ * This will allocate the datastructure and initialize all of the
+ * generic VGA registers.
+ */
+
+ if (vgaHWInit (var, info, par, &timings))
+ return -EINVAL;
+
+ /*
+ * The default value assigned by vgaHW.c is 0x41, but this does
+ * not work for NeoMagic.
+ */
+ par->Attribute[16] = 0x01;
+
+ switch (var->bits_per_pixel)
+ {
+ case 8:
+ par->CRTC[0x13] = var->xres_virtual >> 3;
+ par->ExtCRTOffset = var->xres_virtual >> 11;
+ par->ExtColorModeSelect = 0x11;
+ break;
+ case 16:
+ par->CRTC[0x13] = var->xres_virtual >> 2;
+ par->ExtCRTOffset = var->xres_virtual >> 10;
+ par->ExtColorModeSelect = 0x13;
+ break;
+ case 24:
+ par->CRTC[0x13] = (var->xres_virtual * 3) >> 3;
+ par->ExtCRTOffset = (var->xres_virtual * 3) >> 11;
+ par->ExtColorModeSelect = 0x14;
+ break;
+#ifdef NO_32BIT_SUPPORT_YET
+ case 32: /* FIXME: guessed values */
+ par->CRTC[0x13] = var->xres_virtual >> 1;
+ par->ExtCRTOffset = var->xres_virtual >> 9;
+ par->ExtColorModeSelect = 0x15;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ par->ExtCRTDispAddr = 0x10;
+
+ /* Vertical Extension */
+ par->VerticalExt = (((timings.VTotal -2) & 0x400) >> 10 )
+ | (((timings.VDisplay -1) & 0x400) >> 9 )
+ | (((timings.VSyncStart) & 0x400) >> 8 )
+ | (((timings.VSyncStart) & 0x400) >> 7 );
+
+ /* Fast write bursts on unless disabled. */
+ if (info->pci_burst)
+ par->SysIfaceCntl1 = 0x30;
+ else
+ par->SysIfaceCntl1 = 0x00;
+
+ par->SysIfaceCntl2 = 0xc0; /* VESA Bios sets this to 0x80! */
+
+ /* Enable any user specified display devices. */
+ par->PanelDispCntlReg1 = 0x00;
+ if (info->internal_display)
+ par->PanelDispCntlReg1 |= 0x02;
+ if (info->external_display)
+ par->PanelDispCntlReg1 |= 0x01;
+
+ /* If the user did not specify any display devices, then... */
+ if (par->PanelDispCntlReg1 == 0x00) {
+ /* Default to internal (i.e., LCD) only. */
+ par->PanelDispCntlReg1 |= 0x02;
+ }
+
+ /* If we are using a fixed mode, then tell the chip we are. */
+ switch (var->xres)
+ {
+ case 1280:
+ par->PanelDispCntlReg1 |= 0x60;
+ break;
+ case 1024:
+ par->PanelDispCntlReg1 |= 0x40;
+ break;
+ case 800:
+ par->PanelDispCntlReg1 |= 0x20;
+ break;
+ case 640:
+ default:
+ break;
+ }
+
+ /* Setup shadow register locking. */
+ switch (par->PanelDispCntlReg1 & 0x03)
+ {
+ case 0x01: /* External CRT only mode: */
+ par->GeneralLockReg = 0x00;
+ /* We need to program the VCLK for external display only mode. */
+ par->ProgramVCLK = 1;
+ break;
+ case 0x02: /* Internal LCD only mode: */
+ case 0x03: /* Simultaneous internal/external (LCD/CRT) mode: */
+ par->GeneralLockReg = 0x01;
+ /* Don't program the VCLK when using the LCD. */
+ par->ProgramVCLK = 0;
+ break;
+ }
+
+ /*
+ * If the screen is to be stretched, turn on stretching for the
+ * various modes.
+ *
+ * OPTION_LCD_STRETCH means stretching should be turned off!
+ */
+ par->PanelDispCntlReg2 = 0x00;
+ par->PanelDispCntlReg3 = 0x00;
+
+ if (info->lcd_stretch &&
+ (par->PanelDispCntlReg1 == 0x02) && /* LCD only */
+ (var->xres != info->NeoPanelWidth))
+ {
+ switch (var->xres)
+ {
+ case 320: /* Needs testing. KEM -- 24 May 98 */
+ case 400: /* Needs testing. KEM -- 24 May 98 */
+ case 640:
+ case 800:
+ case 1024:
+ lcd_stretch = 1;
+ par->PanelDispCntlReg2 |= 0xC6;
+ break;
+ default:
+ lcd_stretch = 0;
+ /* No stretching in these modes. */
+ }
+ }
+ else
+ lcd_stretch = 0;
+
+ /*
+ * If the screen is to be centerd, turn on the centering for the
+ * various modes.
+ */
+ par->PanelVertCenterReg1 = 0x00;
+ par->PanelVertCenterReg2 = 0x00;
+ par->PanelVertCenterReg3 = 0x00;
+ par->PanelVertCenterReg4 = 0x00;
+ par->PanelVertCenterReg5 = 0x00;
+ par->PanelHorizCenterReg1 = 0x00;
+ par->PanelHorizCenterReg2 = 0x00;
+ par->PanelHorizCenterReg3 = 0x00;
+ par->PanelHorizCenterReg4 = 0x00;
+ par->PanelHorizCenterReg5 = 0x00;
+
+
+ if (par->PanelDispCntlReg1 & 0x02)
+ {
+ if (var->xres == info->NeoPanelWidth)
+ {
+ /*
+ * No centering required when the requested display width
+ * equals the panel width.
+ */
+ }
+ else
+ {
+ par->PanelDispCntlReg2 |= 0x01;
+ par->PanelDispCntlReg3 |= 0x10;
+
+ /* Calculate the horizontal and vertical offsets. */
+ if (!lcd_stretch)
+ {
+ hoffset = ((info->NeoPanelWidth - var->xres) >> 4) - 1;
+ voffset = ((info->NeoPanelHeight - var->yres) >> 1) - 2;
+ }
+ else
+ {
+ /* Stretched modes cannot be centered. */
+ hoffset = 0;
+ voffset = 0;
+ }
+
+ switch (var->xres)
+ {
+ case 320: /* Needs testing. KEM -- 24 May 98 */
+ par->PanelHorizCenterReg3 = hoffset;
+ par->PanelVertCenterReg2 = voffset;
+ break;
+ case 400: /* Needs testing. KEM -- 24 May 98 */
+ par->PanelHorizCenterReg4 = hoffset;
+ par->PanelVertCenterReg1 = voffset;
+ break;
+ case 640:
+ par->PanelHorizCenterReg1 = hoffset;
+ par->PanelVertCenterReg3 = voffset;
+ break;
+ case 800:
+ par->PanelHorizCenterReg2 = hoffset;
+ par->PanelVertCenterReg4 = voffset;
+ break;
+ case 1024:
+ par->PanelHorizCenterReg5 = hoffset;
+ par->PanelVertCenterReg5 = voffset;
+ break;
+ case 1280:
+ default:
+ /* No centering in these modes. */
+ break;
+ }
+ }
+ }
+
+ par->biosMode = neoFindMode (var->xres, var->yres, var->bits_per_pixel);
+
+ /*
+ * Calculate the VCLK that most closely matches the requested dot
+ * clock.
+ */
+ neoCalcVCLK (info, par, timings.pixclock);
+
+ /* Since we program the clocks ourselves, always use VCLK3. */
+ par->MiscOutReg |= 0x0C;
+
+ return 0;
+}
+
+static int neofb_set_var (struct fb_var_screeninfo *var, int con,
+ struct fb_info *fb)
+{
+ struct neofb_info *info = (struct neofb_info *)fb;
+ struct display *display;
+ struct neofb_par par;
+ int err, chgvar = 0;
+
+ DBG("neofb_set_var");
+
+ err = neofb_decode_var (var, info, &par);
+ if (err)
+ return err;
+
+ if (var->activate & FB_ACTIVATE_TEST)
+ return 0;
+
+ if (con < 0)
+ {
+ display = fb->disp;
+ chgvar = 0;
+ }
+ else
+ {
+ display = fb_display + con;
+
+ if (fb->var.xres != var->xres)
+ chgvar = 1;
+ if (fb->var.yres != var->yres)
+ chgvar = 1;
+ if (fb->var.xres_virtual != var->xres_virtual)
+ chgvar = 1;
+ if (fb->var.yres_virtual != var->yres_virtual)
+ chgvar = 1;
+ if (fb->var.bits_per_pixel != var->bits_per_pixel)
+ chgvar = 1;
+ }
+
+ if (!info->neo2200)
+ var->accel_flags &= ~FB_ACCELF_TEXT;
+
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+
+ switch (var->bits_per_pixel)
+ {
+#ifdef FBCON_HAS_CFB8
+ case 8: /* PSEUDOCOLOUR, 256 */
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 0;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+
+ fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ info->dispsw = &fbcon_cfb8;
+ display->dispsw_data = NULL;
+ display->next_line = var->xres_virtual;
+ break;
+#endif
+
+#ifdef FBCON_HAS_CFB16
+ case 16: /* DIRECTCOLOUR, 64k */
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+
+ fb->fix.visual = FB_VISUAL_DIRECTCOLOR;
+ info->dispsw = &fbcon_cfb16;
+ display->dispsw_data = fb->pseudo_palette;
+ display->next_line = var->xres_virtual * 2;
+ break;
+#endif
+
+#ifdef FBCON_HAS_CFB24
+ case 24: /* TRUECOLOUR, 16m */
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+
+ fb->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->dispsw = &fbcon_cfb24;
+ display->dispsw_data = fb->pseudo_palette;
+ display->next_line = var->xres_virtual * 3;
+
+ var->accel_flags &= ~FB_ACCELF_TEXT;
+ break;
+#endif
+
+#ifdef NO_32BIT_SUPPORT_YET
+# ifdef FBCON_HAS_CFB32
+ case 32: /* TRUECOLOUR, 16m */
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+
+ fb->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->dispsw = &fbcon_cfb32;
+ display->dispsw_data = fb->pseudo_palette;
+ display->next_line = var->xres_virtual * 4;
+
+ var->accel_flags &= ~FB_ACCELF_TEXT;
+ break;
+# endif
+#endif
+
+ default:
+ printk (KERN_WARNING "neofb: no support for %dbpp\n", var->bits_per_pixel);
+ info->dispsw = &fbcon_dummy;
+ var->accel_flags &= ~FB_ACCELF_TEXT;
+ break;
+ }
+
+ if (var->accel_flags & FB_ACCELF_TEXT)
+ display->dispsw = &fbcon_neo2200_accel;
+ else
+ display->dispsw = info->dispsw;
+
+ fb->fix.line_length = display->next_line;
+
+ display->screen_base = fb->screen_base;
+ display->line_length = fb->fix.line_length;
+ display->visual = fb->fix.visual;
+ display->type = fb->fix.type;
+ display->type_aux = fb->fix.type_aux;
+ display->ypanstep = fb->fix.ypanstep;
+ display->ywrapstep = fb->fix.ywrapstep;
+ display->can_soft_blank = 1;
+ display->inverse = 0;
+
+ fb->var = *var;
+ fb->var.activate &= ~FB_ACTIVATE_ALL;
+
+ /*
+ * Update the old var. The fbcon drivers still use this.
+ * Once they are using cfb->fb.var, this can be dropped.
+ * --rmk
+ */
+ display->var = fb->var;
+
+ /*
+ * If we are setting all the virtual consoles, also set the
+ * defaults used to create new consoles.
+ */
+ if (var->activate & FB_ACTIVATE_ALL)
+ fb->disp->var = fb->var;
+
+ if (chgvar && fb && fb->changevar)
+ fb->changevar (con);
+
+ if (con == info->currcon)
+ {
+ if (chgvar || con < 0)
+ neofb_set_par (info, &par);
+
+ neofb_update_start (info, var);
+ fb_set_cmap (&fb->cmap, 1, neo_setcolreg, fb);
+
+ if (var->accel_flags & FB_ACCELF_TEXT)
+ neo2200_accel_init (info, var);
+ }
+
+ return 0;
+}
+
+/*
+ * Pan or Wrap the Display
+ */
+static int neofb_pan_display (struct fb_var_screeninfo *var, int con,
+ struct fb_info *fb)
+{
+ struct neofb_info *info = (struct neofb_info *)fb;
+ u_int y_bottom;
+
+ y_bottom = var->yoffset;
+
+ if (!(var->vmode & FB_VMODE_YWRAP))
+ y_bottom += var->yres;
+
+ if (var->xoffset > (var->xres_virtual - var->xres))
+ return -EINVAL;
+ if (y_bottom > fb->var.yres_virtual)
+ return -EINVAL;
+
+ neofb_update_start (info, var);
+
+ fb->var.xoffset = var->xoffset;
+ fb->var.yoffset = var->yoffset;
+
+ if (var->vmode & FB_VMODE_YWRAP)
+ fb->var.vmode |= FB_VMODE_YWRAP;
+ else
+ fb->var.vmode &= ~FB_VMODE_YWRAP;
+
+ return 0;
+}
+
+
+/*
+ * Update the `var' structure (called by fbcon.c)
+ *
+ * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
+ * Since it's called by a kernel driver, no range checking is done.
+ */
+static int neofb_updatevar (int con, struct fb_info *fb)
+{
+ struct neofb_info *info = (struct neofb_info *)fb;
+
+ neofb_update_start (info, &fb_display[con].var);
+
+ return 0;
+}
+
+static int neofb_switch (int con, struct fb_info *fb)
+{
+ struct neofb_info *info = (struct neofb_info *)fb;
+ struct display *disp;
+ struct fb_cmap *cmap;
+
+ if (info->currcon >= 0)
+ {
+ disp = fb_display + info->currcon;
+
+ /*
+ * Save the old colormap and video mode.
+ */
+ disp->var = fb->var;
+ if (disp->cmap.len)
+ fb_copy_cmap(&fb->cmap, &disp->cmap, 0);
+ }
+
+ info->currcon = con;
+ disp = fb_display + con;
+
+ /*
+ * Install the new colormap and change the video mode. By default,
+ * fbcon sets all the colormaps and video modes to the default
+ * values at bootup.
+ *
+ * Really, we want to set the colourmap size depending on the
+ * depth of the new video mode. For now, we leave it at its
+ * default 256 entry.
+ */
+ if (disp->cmap.len)
+ cmap = &disp->cmap;
+ else
+ cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
+
+ fb_copy_cmap(cmap, &fb->cmap, 0);
+
+ disp->var.activate = FB_ACTIVATE_NOW;
+ neofb_set_var(&disp->var, con, fb);
+
+ return 0;
+}
+
+/*
+ * (Un)Blank the display.
+ */
+static void neofb_blank (int blank, struct fb_info *fb)
+{
+ // struct neofb_info *info = (struct neofb_info *)fb;
+
+ /*
+ * Blank the screen if blank_mode != 0, else unblank. If
+ * blank == NULL then the caller blanks by setting the CLUT
+ * (Color Look Up Table) to all black. Return 0 if blanking
+ * succeeded, != 0 if un-/blanking failed due to e.g. a
+ * video mode which doesn't support it. Implements VESA
+ * suspend and powerdown modes on hardware that supports
+ * disabling hsync/vsync:
+ * blank_mode == 2: suspend vsync
+ * blank_mode == 3: suspend hsync
+ * blank_mode == 4: powerdown
+ *
+ * wms...Enable VESA DMPS compatible powerdown mode
+ * run "setterm -powersave powerdown" to take advantage
+ */
+
+ switch (blank)
+ {
+ case 4: /* powerdown - both sync lines down */
+ break;
+ case 3: /* hsync off */
+ break;
+ case 2: /* vsync off */
+ break;
+ case 1: /* just software blanking of screen */
+ break;
+ default: /* case 0, or anything else: unblank */
+ break;
+ }
+}
+
+/*
+ * Get the currently displayed virtual consoles colormap.
+ */
+static int gen_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *fb)
+{
+ fb_copy_cmap (&fb->cmap, cmap, kspc ? 0 : 2);
+ return 0;
+}
+
+/*
+ * Get the currently displayed virtual consoles fixed part of the display.
+ */
+static int gen_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *fb)
+{
+ *fix = fb->fix;
+ return 0;
+}
+
+/*
+ * Get the current user defined part of the display.
+ */
+static int gen_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *fb)
+{
+ *var = fb->var;
+ return 0;
+}
+
+static struct fb_ops neofb_ops = {
+ owner: THIS_MODULE,
+ fb_set_var: neofb_set_var,
+ fb_set_cmap: neofb_set_cmap,
+ fb_pan_display: neofb_pan_display,
+ fb_get_fix: gen_get_fix,
+ fb_get_var: gen_get_var,
+ fb_get_cmap: gen_get_cmap,
+};
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo __devinitdata neofb_var640x480x8 = {
+ accel_flags: FB_ACCELF_TEXT,
+ xres: 640,
+ yres: 480,
+ xres_virtual: 640,
+ yres_virtual: 30000,
+ bits_per_pixel: 8,
+ pixclock: 39722,
+ left_margin: 48,
+ right_margin: 16,
+ upper_margin: 33,
+ lower_margin: 10,
+ hsync_len: 96,
+ vsync_len: 2,
+ sync: 0,
+ vmode: FB_VMODE_NONINTERLACED
+};
+
+static struct fb_var_screeninfo __devinitdata neofb_var800x600x8 = {
+ accel_flags: FB_ACCELF_TEXT,
+ xres: 800,
+ yres: 600,
+ xres_virtual: 800,
+ yres_virtual: 30000,
+ bits_per_pixel: 8,
+ pixclock: 25000,
+ left_margin: 88,
+ right_margin: 40,
+ upper_margin: 23,
+ lower_margin: 1,
+ hsync_len: 128,
+ vsync_len: 4,
+ sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ vmode: FB_VMODE_NONINTERLACED
+};
+
+static struct fb_var_screeninfo __devinitdata neofb_var1024x768x8 = {
+ accel_flags: FB_ACCELF_TEXT,
+ xres: 1024,
+ yres: 768,
+ xres_virtual: 1024,
+ yres_virtual: 30000,
+ bits_per_pixel: 8,
+ pixclock: 15385,
+ left_margin: 160,
+ right_margin: 24,
+ upper_margin: 29,
+ lower_margin: 3,
+ hsync_len: 136,
+ vsync_len: 6,
+ sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ vmode: FB_VMODE_NONINTERLACED
+};
+
+#ifdef NOT_DONE
+static struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8 = {
+ accel_flags: FB_ACCELF_TEXT,
+ xres: 1280,
+ yres: 1024,
+ xres_virtual: 1280,
+ yres_virtual: 30000,
+ bits_per_pixel: 8,
+ pixclock: 9260,
+ left_margin: 248,
+ right_margin: 48,
+ upper_margin: 38,
+ lower_margin: 1,
+ hsync_len: 112,
+ vsync_len: 3,
+ sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ vmode: FB_VMODE_NONINTERLACED
+};
+#endif
+
+static struct fb_var_screeninfo *neofb_var = NULL;
+
+
+static int __devinit neo_map_mmio (struct neofb_info *info)
+{
+ DBG("neo_map_mmio");
+
+ info->mmio.pbase = pci_resource_start (info->pcidev, 1);
+ info->mmio.len = MMIO_SIZE;
+
+ if (!request_mem_region (info->mmio.pbase, MMIO_SIZE, "memory mapped I/O"))
+ {
+ printk ("neofb: memory mapped IO in use\n");
+ return -EBUSY;
+ }
+
+ info->mmio.vbase = ioremap (info->mmio.pbase, MMIO_SIZE);
+ if (!info->mmio.vbase)
+ {
+ printk ("neofb: unable to map memory mapped IO\n");
+ release_mem_region (info->mmio.pbase, info->mmio.len);
+ return -ENOMEM;
+ }
+ else
+ printk (KERN_INFO "neofb: mapped io at %p\n", info->mmio.vbase);
+
+ info->fb.fix.mmio_start = info->mmio.pbase;
+ info->fb.fix.mmio_len = info->mmio.len;
+
+ return 0;
+}
+
+static void __devinit neo_unmap_mmio (struct neofb_info *info)
+{
+ DBG("neo_unmap_mmio");
+
+ if (info->mmio.vbase)
+ {
+ iounmap (info->mmio.vbase);
+ info->mmio.vbase = NULL;
+
+ release_mem_region (info->mmio.pbase, info->mmio.len);
+ }
+}
+
+static int __devinit neo_map_video (struct neofb_info *info, int video_len)
+{
+ DBG("neo_map_video");
+
+ info->video.pbase = pci_resource_start (info->pcidev, 0);
+ info->video.len = video_len;
+
+ if (!request_mem_region (info->video.pbase, info->video.len, "frame buffer"))
+ {
+ printk ("neofb: frame buffer in use\n");
+ return -EBUSY;
+ }
+
+ info->video.vbase = ioremap (info->video.pbase, info->video.len);
+ if (!info->video.vbase)
+ {
+ printk ("neofb: unable to map screen memory\n");
+ release_mem_region (info->video.pbase, info->video.len);
+ return -ENOMEM;
+ }
+ else
+ printk (KERN_INFO "neofb: mapped framebuffer at %p\n", info->video.vbase);
+
+ info->fb.fix.smem_start = info->video.pbase;
+ info->fb.fix.smem_len = info->video.len;
+ info->fb.screen_base = info->video.vbase;
+
+#ifdef CONFIG_MTRR
+ info->video.mtrr = mtrr_add (info->video.pbase, pci_resource_len (info->pcidev, 0), MTRR_TYPE_WRCOMB, 1);
+#endif
+
+ /* Clear framebuffer, it's all white in memory after boot */
+ memset (info->video.vbase, 0, info->video.len);
+
+ return 0;
+}
+
+static void __devinit neo_unmap_video (struct neofb_info *info)
+{
+ DBG("neo_unmap_video");
+
+ if (info->video.vbase)
+ {
+#ifdef CONFIG_MTRR
+ mtrr_del (info->video.mtrr, info->video.pbase, info->video.len);
+#endif
+
+ iounmap (info->video.vbase);
+ info->video.vbase = NULL;
+ info->fb.screen_base = NULL;
+
+ release_mem_region (info->video.pbase, info->video.len);
+ }
+}
+
+static int __devinit neo_init_hw (struct neofb_info *info)
+{
+ int videoRam = 896;
+ int maxClock = 65000;
+ int CursorMem = 1024;
+ int CursorOff = 0x100;
+ int linearSize = 1024;
+ int maxWidth = 1024;
+ int maxHeight = 1024;
+ unsigned char type, display;
+ int w;
+
+ DBG("neo_init_hw");
+
+ neoUnlock();
+
+#if 0
+ printk (KERN_DEBUG "--- Neo extended register dump ---\n");
+ for (w=0; w<0x85; w++)
+ printk (KERN_DEBUG "CR %p: %p\n", (void*)w, (void*)VGArCR (w));
+ for (w=0; w<0xC7; w++)
+ printk (KERN_DEBUG "GR %p: %p\n", (void*)w, (void*)VGArGR (w));
+#endif
+
+ /* Determine the panel type */
+ VGAwGR(0x09,0x26);
+ type = VGArGR(0x21);
+ display = VGArGR(0x20);
+
+ /* Determine panel width -- used in NeoValidMode. */
+ w = VGArGR(0x20);
+ VGAwGR(0x09,0x00);
+ switch ((w & 0x18) >> 3)
+ {
+ case 0x00:
+ info->NeoPanelWidth = 640;
+ info->NeoPanelHeight = 480;
+ neofb_var = &neofb_var640x480x8;
+ break;
+ case 0x01:
+ info->NeoPanelWidth = 800;
+ info->NeoPanelHeight = 600;
+ neofb_var = &neofb_var800x600x8;
+ break;
+ case 0x02:
+ info->NeoPanelWidth = 1024;
+ info->NeoPanelHeight = 768;
+ neofb_var = &neofb_var1024x768x8;
+ break;
+ case 0x03:
+ /* 1280x1024 panel support needs to be added */
+#ifdef NOT_DONE
+ info->NeoPanelWidth = 1280;
+ info->NeoPanelHeight = 1024;
+ neofb_var = &neofb_var1280x1024x8;
+ break;
+#else
+ printk (KERN_ERR "neofb: Only 640x480, 800x600 and 1024x768 panels are currently supported\n");
+ return -1;
+#endif
+ default:
+ info->NeoPanelWidth = 640;
+ info->NeoPanelHeight = 480;
+ neofb_var = &neofb_var640x480x8;
+ break;
+ }
+
+ printk (KERN_INFO "Panel is a %dx%d %s %s display\n",
+ info->NeoPanelWidth,
+ info->NeoPanelHeight,
+ (type & 0x02) ? "color" : "monochrome",
+ (type & 0x10) ? "TFT" : "dual scan");
+
+ switch (info->accel)
+ {
+ case FB_ACCEL_NEOMAGIC_NM2070:
+ videoRam = 896;
+ maxClock = 65000;
+ CursorMem = 2048;
+ CursorOff = 0x100;
+ linearSize = 1024;
+ maxWidth = 1024;
+ maxHeight = 1024;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2090:
+ case FB_ACCEL_NEOMAGIC_NM2093:
+ videoRam = 1152;
+ maxClock = 80000;
+ CursorMem = 2048;
+ CursorOff = 0x100;
+ linearSize = 2048;
+ maxWidth = 1024;
+ maxHeight = 1024;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2097:
+ videoRam = 1152;
+ maxClock = 80000;
+ CursorMem = 1024;
+ CursorOff = 0x100;
+ linearSize = 2048;
+ maxWidth = 1024;
+ maxHeight = 1024;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2160:
+ videoRam = 2048;
+ maxClock = 90000;
+ CursorMem = 1024;
+ CursorOff = 0x100;
+ linearSize = 2048;
+ maxWidth = 1024;
+ maxHeight = 1024;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2200:
+ videoRam = 2560;
+ maxClock = 110000;
+ CursorMem = 1024;
+ CursorOff = 0x1000;
+ linearSize = 4096;
+ maxWidth = 1280;
+ maxHeight = 1024; /* ???? */
+
+ info->neo2200 = (Neo2200*) info->mmio.vbase;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2230:
+ videoRam = 3008;
+ maxClock = 110000;
+ CursorMem = 1024;
+ CursorOff = 0x1000;
+ linearSize = 4096;
+ maxWidth = 1280;
+ maxHeight = 1024; /* ???? */
+
+ info->neo2200 = (Neo2200*) info->mmio.vbase;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2360:
+ videoRam = 4096;
+ maxClock = 110000;
+ CursorMem = 1024;
+ CursorOff = 0x1000;
+ linearSize = 4096;
+ maxWidth = 1280;
+ maxHeight = 1024; /* ???? */
+
+ info->neo2200 = (Neo2200*) info->mmio.vbase;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2380:
+ videoRam = 6144;
+ maxClock = 110000;
+ CursorMem = 1024;
+ CursorOff = 0x1000;
+ linearSize = 8192;
+ maxWidth = 1280;
+ maxHeight = 1024; /* ???? */
+
+ info->neo2200 = (Neo2200*) info->mmio.vbase;
+ break;
+ }
+
+ info->maxClock = maxClock;
+
+ return videoRam * 1024;
+}
+
+
+static struct neofb_info * __devinit neo_alloc_fb_info (struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ struct neofb_info *info;
+
+ info = kmalloc (sizeof(struct neofb_info) + sizeof(struct display) +
+ sizeof(u32) * 16, GFP_KERNEL);
+
+ if (!info)
+ return NULL;
+
+ memset (info, 0, sizeof(struct neofb_info) + sizeof(struct display));
+
+ info->currcon = -1;
+ info->pcidev = dev;
+ info->accel = id->driver_data;
+
+ info->pci_burst = !nopciburst;
+ info->lcd_stretch = !nostretch;
+
+ if (!internal && !external)
+ {
+ info->internal_display = 1;
+ info->external_display = 0;
+ }
+ else
+ {
+ info->internal_display = internal;
+ info->external_display = external;
+ }
+
+ switch (info->accel)
+ {
+ case FB_ACCEL_NEOMAGIC_NM2070:
+ sprintf (info->fb.fix.id, "MagicGraph 128");
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2090:
+ sprintf (info->fb.fix.id, "MagicGraph 128V");
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2093:
+ sprintf (info->fb.fix.id, "MagicGraph 128ZV");
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2097:
+ sprintf (info->fb.fix.id, "MagicGraph 128ZV+");
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2160:
+ sprintf (info->fb.fix.id, "MagicGraph 128XD");
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2200:
+ sprintf (info->fb.fix.id, "MagicGraph 256AV");
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2230:
+ sprintf (info->fb.fix.id, "MagicGraph 256AV+");
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2360:
+ sprintf (info->fb.fix.id, "MagicGraph 256ZX");
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2380:
+ sprintf (info->fb.fix.id, "MagicGraph 256XL+");
+ break;
+ }
+
+ info->fb.fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fb.fix.type_aux = 0;
+ info->fb.fix.xpanstep = 0;
+ info->fb.fix.ypanstep = 4;
+ info->fb.fix.ywrapstep = 0;
+ info->fb.fix.accel = id->driver_data;
+
+ info->fb.var.nonstd = 0;
+ info->fb.var.activate = FB_ACTIVATE_NOW;
+ info->fb.var.height = -1;
+ info->fb.var.width = -1;
+ info->fb.var.accel_flags = 0;
+
+ strcpy (info->fb.modename, info->fb.fix.id);
+
+ info->fb.fbops = &neofb_ops;
+ info->fb.changevar = NULL;
+ info->fb.switch_con = neofb_switch;
+ info->fb.updatevar = neofb_updatevar;
+ info->fb.blank = neofb_blank;
+ info->fb.flags = FBINFO_FLAG_DEFAULT;
+ info->fb.disp = (struct display *)(info + 1);
+ info->fb.pseudo_palette = (void *)(info->fb.disp + 1);
+
+ fb_alloc_cmap (&info->fb.cmap, NR_PALETTE, 0);
+
+ return info;
+}
+
+static void __devinit neo_free_fb_info (struct neofb_info *info)
+{
+ if (info)
+ {
+ /*
+ * Free the colourmap
+ */
+ fb_alloc_cmap (&info->fb.cmap, 0, 0);
+
+ kfree (info);
+ }
+}
+
+/* --------------------------------------------------------------------- */
+
+static int __devinit neofb_probe (struct pci_dev* dev, const struct pci_device_id* id)
+{
+ struct neofb_info *info;
+ u_int h_sync, v_sync;
+ int err;
+ int video_len;
+
+ DBG("neofb_probe");
+
+ err = pci_enable_device (dev);
+ if (err)
+ return err;
+
+ err = -ENOMEM;
+ info = neo_alloc_fb_info (dev, id);
+ if (!info)
+ goto failed;
+
+ err = neo_map_mmio (info);
+ if (err)
+ goto failed;
+
+ video_len = neo_init_hw (info);
+ if (video_len < 0)
+ {
+ err = video_len;
+ goto failed;
+ }
+
+ err = neo_map_video (info, video_len);
+ if (err)
+ goto failed;
+
+ neofb_set_var (neofb_var, -1, &info->fb);
+
+ /*
+ * Calculate the hsync and vsync frequencies. Note that
+ * we split the 1e12 constant up so that we can preserve
+ * the precision and fit the results into 32-bit registers.
+ * (1953125000 * 512 = 1e12)
+ */
+ h_sync = 1953125000 / info->fb.var.pixclock;
+ h_sync = h_sync * 512 / (info->fb.var.xres + info->fb.var.left_margin +
+ info->fb.var.right_margin + info->fb.var.hsync_len);
+ v_sync = h_sync / (info->fb.var.yres + info->fb.var.upper_margin +
+ info->fb.var.lower_margin + info->fb.var.vsync_len);
+
+ printk(KERN_INFO "neofb v" NEOFB_VERSION ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+ info->fb.fix.smem_len >> 10,
+ info->fb.var.xres, info->fb.var.yres,
+ h_sync / 1000, h_sync % 1000, v_sync);
+
+
+ err = register_framebuffer (&info->fb);
+ if (err < 0)
+ goto failed;
+
+ printk (KERN_INFO "fb%d: %s frame buffer device\n",
+ GET_FB_IDX(info->fb.node), info->fb.modename);
+
+ /*
+ * Our driver data
+ */
+ dev->driver_data = info;
+
+ return 0;
+
+failed:
+ neo_unmap_video (info);
+ neo_unmap_mmio (info);
+ neo_free_fb_info (info);
+
+ return err;
+}
+
+static void __devexit neofb_remove (struct pci_dev *dev)
+{
+ struct neofb_info *info = (struct neofb_info *)dev->driver_data;
+
+ DBG("neofb_remove");
+
+ if (info)
+ {
+ /*
+ * If unregister_framebuffer fails, then
+ * we will be leaving hooks that could cause
+ * oopsen laying around.
+ */
+ if (unregister_framebuffer (&info->fb))
+ printk (KERN_WARNING "neofb: danger danger! Oopsen imminent!\n");
+
+ neo_unmap_video (info);
+ neo_unmap_mmio (info);
+ neo_free_fb_info (info);
+
+ /*
+ * Ensure that the driver data is no longer
+ * valid.
+ */
+ dev->driver_data = NULL;
+ }
+}
+
+static struct pci_device_id neofb_devices[] __devinitdata = {
+ {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2070,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2070},
+
+ {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090},
+
+ {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093},
+
+ {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097},
+
+ {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160},
+
+ {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200},
+
+ {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230},
+
+ {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360},
+
+ {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380},
+
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, neofb_devices);
+
+static struct pci_driver neofb_driver = {
+ name: "neofb",
+ id_table: neofb_devices,
+ probe: neofb_probe,
+ remove: neofb_remove
+};
+
+/* **************************** init-time only **************************** */
+
+static void __init neo_init (void)
+{
+ DBG("neo_init");
+ pci_register_driver (&neofb_driver);
+}
+
+/* **************************** exit-time only **************************** */
+
+static void __exit neo_done (void)
+{
+ DBG("neo_done");
+ pci_unregister_driver (&neofb_driver);
+}
+
+
+#ifndef MODULE
+
+/* ************************* init in-kernel code ************************** */
+
+int __init neofb_setup (char *options)
+{
+ char *this_opt;
+
+ DBG("neofb_setup");
+
+ if (!options || !*options)
+ return 0;
+
+ for (this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,","))
+ {
+ if (!*this_opt) continue;
+
+ if (!strncmp(this_opt, "disabled", 8))
+ disabled = 1;
+ if (!strncmp(this_opt, "internal", 8))
+ internal = 1;
+ if (!strncmp(this_opt, "external", 8))
+ external = 1;
+ if (!strncmp(this_opt, "nostretch", 9))
+ nostretch = 1;
+ if (!strncmp(this_opt, "nopciburst", 10))
+ nopciburst = 1;
+ }
+
+ return 0;
+}
+
+static int __init initialized = 0;
+
+int __init neofb_init(void)
+{
+ DBG("neofb_init");
+
+ if (disabled)
+ return -ENXIO;
+
+ if (!initialized)
+ {
+ initialized = 1;
+ neo_init();
+ }
+
+ /* never return failure, user can hotplug card later... */
+ return 0;
+}
+
+#else
+
+/* *************************** init module code **************************** */
+
+int __init init_module(void)
+{
+ DBG("init_module");
+
+ if (disabled)
+ return -ENXIO;
+
+ neo_init();
+
+ /* never return failure; user can hotplug card later... */
+ return 0;
+}
+
+#endif /* MODULE */
+
+module_exit(neo_done);
diff --git a/drivers/video/neofb.h b/drivers/video/neofb.h
new file mode 100644
index 000000000..1034311b5
--- /dev/null
+++ b/drivers/video/neofb.h
@@ -0,0 +1,294 @@
+/*
+ * linux/drivers/video/neofb.h -- NeoMagic Framebuffer Driver
+ *
+ * Copyright (c) 2001 Denis Oliver Kropp <dok@convergence.de>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+
+#ifdef NEOFB_DEBUG
+# define DBG(x) printk (KERN_DEBUG "neofb: %s\n", (x));
+#else
+# define DBG(x)
+#endif
+
+
+#define PCI_CHIP_NM2070 0x0001
+#define PCI_CHIP_NM2090 0x0002
+#define PCI_CHIP_NM2093 0x0003
+#define PCI_CHIP_NM2097 0x0083
+#define PCI_CHIP_NM2160 0x0004
+#define PCI_CHIP_NM2200 0x0005
+#define PCI_CHIP_NM2230 0x0025
+#define PCI_CHIP_NM2360 0x0006
+#define PCI_CHIP_NM2380 0x0016
+
+
+struct xtimings {
+ unsigned int pixclock;
+ unsigned int HDisplay;
+ unsigned int HSyncStart;
+ unsigned int HSyncEnd;
+ unsigned int HTotal;
+ unsigned int VDisplay;
+ unsigned int VSyncStart;
+ unsigned int VSyncEnd;
+ unsigned int VTotal;
+ unsigned int sync;
+ int dblscan;
+ int interlaced;
+};
+
+
+/* --------------------------------------------------------------------- */
+
+typedef volatile struct {
+ __u32 bltStat;
+ __u32 bltCntl;
+ __u32 xpColor;
+ __u32 fgColor;
+ __u32 bgColor;
+ __u32 pitch;
+ __u32 clipLT;
+ __u32 clipRB;
+ __u32 srcBitOffset;
+ __u32 srcStart;
+ __u32 reserved0;
+ __u32 dstStart;
+ __u32 xyExt;
+
+ __u32 reserved1[19];
+
+ __u32 pageCntl;
+ __u32 pageBase;
+ __u32 postBase;
+ __u32 postPtr;
+ __u32 dataPtr;
+} Neo2200;
+
+#define NR_PALETTE 256
+
+#define MMIO_SIZE 0x200000
+
+#define NEO_EXT_CR_MAX 0x85
+#define NEO_EXT_GR_MAX 0xC7
+
+struct neofb_par {
+
+ int depth;
+
+ unsigned char MiscOutReg; /* Misc */
+ unsigned char CRTC[25]; /* Crtc Controller */
+ unsigned char Sequencer[5]; /* Video Sequencer */
+ unsigned char Graphics[9]; /* Video Graphics */
+ unsigned char Attribute[21]; /* Video Atribute */
+
+ unsigned char GeneralLockReg;
+ unsigned char ExtCRTDispAddr;
+ unsigned char ExtCRTOffset;
+ unsigned char SysIfaceCntl1;
+ unsigned char SysIfaceCntl2;
+ unsigned char ExtColorModeSelect;
+ unsigned char biosMode;
+
+ unsigned char PanelDispCntlReg1;
+ unsigned char PanelDispCntlReg2;
+ unsigned char PanelDispCntlReg3;
+ unsigned char PanelVertCenterReg1;
+ unsigned char PanelVertCenterReg2;
+ unsigned char PanelVertCenterReg3;
+ unsigned char PanelVertCenterReg4;
+ unsigned char PanelVertCenterReg5;
+ unsigned char PanelHorizCenterReg1;
+ unsigned char PanelHorizCenterReg2;
+ unsigned char PanelHorizCenterReg3;
+ unsigned char PanelHorizCenterReg4;
+ unsigned char PanelHorizCenterReg5;
+
+ int ProgramVCLK;
+ unsigned char VCLK3NumeratorLow;
+ unsigned char VCLK3NumeratorHigh;
+ unsigned char VCLK3Denominator;
+ unsigned char VerticalExt;
+};
+
+struct neofb_info {
+
+ struct fb_info fb;
+ struct display_switch *dispsw;
+
+ struct pci_dev *pcidev;
+
+ int currcon;
+
+ int accel;
+ char *name;
+
+ struct {
+ u8 *vbase;
+ u32 pbase;
+ u32 len;
+#ifdef CONFIG_MTRR
+ int mtrr;
+#endif
+ } video;
+
+ struct {
+ u8 *vbase;
+ u32 pbase;
+ u32 len;
+ } mmio;
+
+ Neo2200 *neo2200;
+
+ /* Panels size */
+ int NeoPanelWidth;
+ int NeoPanelHeight;
+
+ int maxClock;
+
+ int pci_burst;
+ int lcd_stretch;
+ int internal_display;
+ int external_display;
+
+ struct {
+ u16 red, green, blue, transp;
+ } palette[NR_PALETTE];
+};
+
+
+typedef struct {
+ int x_res;
+ int y_res;
+ int mode;
+} biosMode;
+
+
+/* vga IO functions */
+static inline u8 VGArCR (u8 index)
+{
+ outb (index, 0x3d4);
+ return inb (0x3d5);
+}
+
+static inline void VGAwCR (u8 index, u8 val)
+{
+ outb (index, 0x3d4);
+ outb (val, 0x3d5);
+}
+
+static inline u8 VGArGR (u8 index)
+{
+ outb (index, 0x3ce);
+ return inb (0x3cf);
+}
+
+static inline void VGAwGR (u8 index, u8 val)
+{
+ outb (index, 0x3ce);
+ outb (val, 0x3cf);
+}
+
+static inline u8 VGArSEQ (u8 index)
+{
+ outb (index, 0x3c4);
+ return inb (0x3c5);
+}
+
+static inline void VGAwSEQ (u8 index, u8 val)
+{
+ outb (index, 0x3c4);
+ outb (val, 0x3c5);
+}
+
+
+static int paletteEnabled = 0;
+
+static inline void VGAenablePalette (void)
+{
+ u8 tmp;
+
+ tmp = inb (0x3da);
+ outb (0x00, 0x3c0);
+ paletteEnabled = 1;
+}
+
+static inline void VGAdisablePalette (void)
+{
+ u8 tmp;
+
+ tmp = inb (0x3da);
+ outb (0x20, 0x3c0);
+ paletteEnabled = 0;
+}
+
+static inline void VGAwATTR (u8 index, u8 value)
+{
+ u8 tmp;
+
+ if (paletteEnabled)
+ index &= ~0x20;
+ else
+ index |= 0x20;
+
+ tmp = inb (0x3da);
+ outb (index, 0x3c0);
+ outb (value, 0x3c0);
+}
+
+static inline void VGAwMISC (u8 value)
+{
+ outb (value, 0x3c2);
+}
+
+
+#define NEO_BS0_BLT_BUSY 0x00000001
+#define NEO_BS0_FIFO_AVAIL 0x00000002
+#define NEO_BS0_FIFO_PEND 0x00000004
+
+#define NEO_BC0_DST_Y_DEC 0x00000001
+#define NEO_BC0_X_DEC 0x00000002
+#define NEO_BC0_SRC_TRANS 0x00000004
+#define NEO_BC0_SRC_IS_FG 0x00000008
+#define NEO_BC0_SRC_Y_DEC 0x00000010
+#define NEO_BC0_FILL_PAT 0x00000020
+#define NEO_BC0_SRC_MONO 0x00000040
+#define NEO_BC0_SYS_TO_VID 0x00000080
+
+#define NEO_BC1_DEPTH8 0x00000100
+#define NEO_BC1_DEPTH16 0x00000200
+#define NEO_BC1_X_320 0x00000400
+#define NEO_BC1_X_640 0x00000800
+#define NEO_BC1_X_800 0x00000c00
+#define NEO_BC1_X_1024 0x00001000
+#define NEO_BC1_X_1152 0x00001400
+#define NEO_BC1_X_1280 0x00001800
+#define NEO_BC1_X_1600 0x00001c00
+#define NEO_BC1_DST_TRANS 0x00002000
+#define NEO_BC1_MSTR_BLT 0x00004000
+#define NEO_BC1_FILTER_Z 0x00008000
+
+#define NEO_BC2_WR_TR_DST 0x00800000
+
+#define NEO_BC3_SRC_XY_ADDR 0x01000000
+#define NEO_BC3_DST_XY_ADDR 0x02000000
+#define NEO_BC3_CLIP_ON 0x04000000
+#define NEO_BC3_FIFO_EN 0x08000000
+#define NEO_BC3_BLT_ON_ADDR 0x10000000
+#define NEO_BC3_SKIP_MAPPING 0x80000000
+
+#define NEO_MODE1_DEPTH8 0x0100
+#define NEO_MODE1_DEPTH16 0x0200
+#define NEO_MODE1_DEPTH24 0x0300
+#define NEO_MODE1_X_320 0x0400
+#define NEO_MODE1_X_640 0x0800
+#define NEO_MODE1_X_800 0x0c00
+#define NEO_MODE1_X_1024 0x1000
+#define NEO_MODE1_X_1152 0x1400
+#define NEO_MODE1_X_1280 0x1800
+#define NEO_MODE1_X_1600 0x1c00
+#define NEO_MODE1_BLT_ON_ADDR 0x2000
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 80621868b..3188c5425 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -566,7 +566,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
strcpy(info->info.modename, "OFfb ");
strncat(info->info.modename, full_name, sizeof(info->info.modename));
- info->info.node = -1;
+ info->info.node = NODEV;
info->info.fbops = &offb_ops;
info->info.disp = disp;
info->info.fontname[0] = '\0';
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index b558e0d42..af6aad704 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -591,7 +591,7 @@ static int __init init_platinum(struct fb_info_platinum *info)
disp = &info->disp;
strcpy(info->fb_info.modename, "platinum");
- info->fb_info.node = -1;
+ info->fb_info.node = NODEV;
info->fb_info.fbops = &platinumfb_ops;
info->fb_info.disp = disp;
strcpy(info->fb_info.fontname, fontname);
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index 6a42bec21..368b07c28 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -386,7 +386,7 @@ int __init pmagbafb_init_one(int slot)
*/
strcpy(ip->info.modename, "PMAG-BA");
ip->info.changevar = NULL;
- ip->info.node = -1;
+ ip->info.node = NODEV;
ip->info.fbops = &pmagbafb_ops;
ip->info.disp = &disp;
ip->info.switch_con = &pmagbafb_switch;
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 2c3f7e7b1..7e531eb6b 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -389,7 +389,7 @@ int __init pmagbbfb_init_one(int slot)
*/
strcpy(ip->info.modename, "PMAGB-BA");
ip->info.changevar = NULL;
- ip->info.node = -1;
+ ip->info.node = NODEV;
ip->info.fbops = &pmagbbfb_ops;
ip->info.disp = &disp;
ip->info.switch_con = &pmagbbfb_switch;
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 9fd9f0cc2..ea328df69 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -1034,7 +1034,7 @@ int __init pvr2fb_init(void)
strcpy(fb_info.modename, pvr2fb_name);
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &pvr2fb_ops;
fb_info.disp = &disp;
fb_info.switch_con = &pvr2fbcon_switch;
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index 458ff5d5a..43fde5bc5 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -331,7 +331,7 @@ int __init q40fb_init(void)
fb_info.switch_con=&q40con_switch;
fb_info.updatevar=&q40con_updatevar;
fb_info.blank=&q40con_blank;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &q40fb_ops;
fb_info.flags = FBINFO_FLAG_DEFAULT; /* not as module for now */
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index 30db837cb..d89cdb282 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -1305,7 +1305,7 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
info = &rinfo->info;
strcpy (info->modename, rinfo->name);
- info->node = -1;
+ info->node = NODEV;
info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &radeon_fb_ops;
info->display_fg = NULL;
diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c
index 335015cdc..e893c6504 100644
--- a/drivers/video/retz3fb.c
+++ b/drivers/video/retz3fb.c
@@ -1422,7 +1422,7 @@ int __init retz3fb_init(void)
strcpy(fb_info->modename, retz3fb_name);
fb_info->changevar = NULL;
- fb_info->node = -1;
+ fb_info->node = NODEV;
fb_info->fbops = &retz3fb_ops;
fb_info->disp = &zinfo->disp;
fb_info->switch_con = &z3fb_switch;
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index 89f8a67f5..8dc9c920c 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -890,7 +890,7 @@ int __init sgivwfb_init(void)
strcpy(fb_info.modename, sgivwfb_name);
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &sgivwfb_ops;
fb_info.disp = &disp;
fb_info.switch_con = &sgivwfbcon_switch;
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 74d3c1634..a15f462c4 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -306,7 +306,7 @@ int __init xxxfb_init(void)
fb_info.gen.fbhw->detect();
strcpy(fb_info.gen.info.modename, "XXX");
fb_info.gen.info.changevar = NULL;
- fb_info.gen.info.node = -1;
+ fb_info.gen.info.node = NODEV;
fb_info.gen.info.fbops = &xxxfb_ops;
fb_info.gen.info.disp = &disp;
fb_info.gen.info.switch_con = &xxxfb_switch;
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 843b0b15c..8d02da31d 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -1797,7 +1797,7 @@ int __init sstfb_init(void)
f_ddprintk("membase_phys: %#lx\n", fb_info.video.base);
f_ddprintk("fbbase_virt: %#lx\n", fb_info.video.vbase);
- fb_info.info.node = -1 ;
+ fb_info.info.node = NODEV;
fb_info.info.flags = FBINFO_FLAG_DEFAULT;
fb_info.info.fbops = &sstfb_ops;
fb_info.info.disp = &disp;
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index 27a28f10c..d4280cf27 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -166,7 +166,7 @@ stifb_init(void)
if ((fb_info.sti = sti_init_roms()) == NULL)
return -ENXIO;
- fb_info.gen.info.node = -1;
+ fb_info.gen.info.node = NODEV;
fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
fb_info.gen.info.fbops = &stifb_ops;
fb_info.gen.info.disp = &disp;
diff --git a/drivers/video/sun3fb.c b/drivers/video/sun3fb.c
index 9ed344b43..59e08a433 100644
--- a/drivers/video/sun3fb.c
+++ b/drivers/video/sun3fb.c
@@ -573,7 +573,7 @@ sizechange:
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_PSEUDOCOLOR;
- fb->info.node = -1;
+ fb->info.node = NODEV;
fb->info.fbops = &sun3fb_ops;
fb->info.disp = disp;
strcpy(fb->info.fontname, fontname);
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 11c93e737..68b8ed57a 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -1975,7 +1975,7 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
strcpy(fb_info.fb_info.modename, "3Dfx ");
strcat(fb_info.fb_info.modename, name);
fb_info.fb_info.changevar = NULL;
- fb_info.fb_info.node = -1;
+ fb_info.fb_info.node = NODEV;
fb_info.fb_info.fbops = &tdfxfb_ops;
fb_info.fb_info.disp = &fb_info.disp;
strcpy(fb_info.fb_info.fontname, fontname);
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index a98c62c7e..3c7b0ed6d 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -937,7 +937,7 @@ int __init tgafb_init(void)
/* setup framebuffer */
- fb_info.gen.info.node = -1;
+ fb_info.gen.info.node = NODEV;
fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
fb_info.gen.info.fbops = &tgafb_ops;
fb_info.gen.info.disp = &disp;
diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c
index 8f102a833..b7b7ff514 100644
--- a/drivers/video/tx3912fb.c
+++ b/drivers/video/tx3912fb.c
@@ -397,7 +397,7 @@ int __init tx3912fb_init(void)
strcpy(fb_info.modename, TX3912FB_NAME);
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &tx3912fb_ops;
fb_info.disp = &global_disp;
fb_info.switch_con = &tx3912fbcon_switch;
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
index 1af28c8af..295d62606 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/valkyriefb.c
@@ -779,7 +779,7 @@ static void valkyrie_par_to_display(struct fb_par_valkyrie *par,
static void __init valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p)
{
strcpy(info->modename, p->fix.id);
- info->node = -1; /* ??? danj */
+ info->node = NODEV;
info->fbops = &valkyriefb_ops;
info->disp = &p->disp;
strcpy(info->fontname, fontname);
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index a8ef9a54a..3462fb935 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -404,7 +404,7 @@ int __init vfb_init(void)
strcpy(fb_info.modename, vfb_name);
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &vfb_ops;
fb_info.disp = &disp;
fb_info.switch_con = &vfbcon_switch;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 3a6572c6a..a69a7f846 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -926,7 +926,7 @@ int __init vga16fb_init(void)
/* name should not depend on EGA/VGA */
strcpy(vga16fb.fb_info.modename, "VGA16 VGA");
vga16fb.fb_info.changevar = NULL;
- vga16fb.fb_info.node = -1;
+ vga16fb.fb_info.node = NODEV;
vga16fb.fb_info.fbops = &vga16fb_ops;
vga16fb.fb_info.disp=&disp;
vga16fb.fb_info.switch_con=&vga16fb_switch;
diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c
index 9a0a69dd7..4128cab5e 100644
--- a/drivers/video/virgefb.c
+++ b/drivers/video/virgefb.c
@@ -1168,7 +1168,7 @@ int __init virgefb_init(void)
strcpy(fb_info.modename, virgefb_name);
fb_info.changevar = NULL;
- fb_info.node = -1;
+ fb_info.node = NODEV;
fb_info.fbops = &virgefb_ops;
fb_info.disp = &disp;
fb_info.switch_con = &Cyberfb_switch;
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index ec77dc7e9..1c4d618aa 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -170,6 +170,7 @@ void __init zorro_init(void)
m68k_memory[i].addr+m68k_memory[i].size, 0);
}
+subsys_initcall(zorro_init);
EXPORT_SYMBOL(zorro_find_device);
EXPORT_SYMBOL(zorro_unused_z2ram);
diff --git a/fs/Config.in b/fs/Config.in
index cf54dfdc9..e39a91ca1 100644
--- a/fs/Config.in
+++ b/fs/Config.in
@@ -31,7 +31,10 @@ dep_mbool ' JBD (ext3) debugging support' CONFIG_JBD_DEBUG $CONFIG_JBD
# msdos file systems
tristate 'DOS FAT fs support' CONFIG_FAT_FS
dep_tristate ' MSDOS fs support' CONFIG_MSDOS_FS $CONFIG_FAT_FS
-dep_tristate ' UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
+#dep_tristate ' UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
+# UMSDOS is temprory broken
+define_bool CONFIG_UMSDOS_FS n
+
dep_tristate ' VFAT (Windows-95) fs support' CONFIG_VFAT_FS $CONFIG_FAT_FS
dep_tristate 'EFS file system support (read only) (EXPERIMENTAL)' CONFIG_EFS_FS $CONFIG_EXPERIMENTAL
dep_tristate 'Journalling Flash File System (JFFS) support' CONFIG_JFFS_FS $CONFIG_MTD
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 365fb633e..350a648ee 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -45,6 +45,8 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
{
struct coda_inode_info *ei;
ei = (struct coda_inode_info *)kmem_cache_alloc(coda_inode_cachep, SLAB_KERNEL);
+ if (!ei)
+ return NULL;
memset(&ei->c_fid, 0, sizeof(struct ViceFid));
ei->c_flags = 0;
INIT_LIST_HEAD(&ei->c_cilist);
@@ -52,8 +54,6 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
ei->c_contcount = 0;
memset(&ei->c_cached_cred, 0, sizeof(struct coda_cred));
ei->c_cached_perm = 0;
- if (!ei)
- return NULL;
return &ei->vfs_inode;
}
diff --git a/fs/driverfs/inode.c b/fs/driverfs/inode.c
index c8d9f4143..1658a0580 100644
--- a/fs/driverfs/inode.c
+++ b/fs/driverfs/inode.c
@@ -31,7 +31,7 @@
#include <linux/dcache.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/driverfs_fs.h>
+#include <linux/device.h>
#include <asm/uaccess.h>
@@ -232,6 +232,7 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
struct driver_file_entry * entry;
unsigned char *page;
ssize_t retval = 0;
+ struct device * dev;
entry = (struct driver_file_entry *)file->private_data;
if (!entry) {
@@ -239,10 +240,13 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
return -ENOENT;
}
- if (!entry->ops || !entry->ops->read) {
- DBG("%s: no read callback\n",__FUNCTION__);
- return -ENOENT;
- }
+ dev = list_entry(entry->parent,struct device, dir);
+
+ if (!valid_device(dev))
+ return -EFAULT;
+
+ if (!entry->show)
+ goto done;
page = (unsigned char*)__get_free_page(GFP_KERNEL);
if (!page) {
@@ -253,7 +257,7 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
while (count > 0) {
ssize_t len;
- len = entry->ops->read(page,count,*ppos,entry->data);
+ len = entry->show(dev,page,count,*ppos);
if (len <= 0) {
if (len < 0)
@@ -274,6 +278,7 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
free_page((unsigned long)page);
done:
+ put_device(dev);
return retval;
}
@@ -294,6 +299,7 @@ static ssize_t
driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
struct driver_file_entry * entry;
+ struct device * dev;
ssize_t retval = 0;
entry = (struct driver_file_entry *)file->private_data;
@@ -302,16 +308,18 @@ driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *pp
return -ENOENT;
}
- if (!entry->ops || !entry->ops->write) {
- DBG("%s: no write callback\n",__FUNCTION__);
- retval = -ENOENT;
+ dev = list_entry(entry->parent,struct device, dir);
+
+ if (!valid_device(dev))
+ return -EFAULT;
+
+ if (!entry->store)
goto done;
- }
while (count > 0) {
ssize_t len;
- len = entry->ops->write(buf,count,*ppos,entry->data);
+ len = entry->store(dev,buf,count,*ppos);
if (len <= 0) {
if (len < 0)
@@ -323,8 +331,8 @@ driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *pp
*ppos += len;
buf += len;
}
-
done:
+ put_device(dev);
return retval;
}
@@ -378,18 +386,6 @@ static int driverfs_d_delete_file (struct dentry * dentry)
return 0;
}
-/* Similar to above - if this dentry goes away, free the
- * driver_dir_entry associated with it..
- */
-static int driverfs_d_delete_dir (struct dentry * dentry)
-{
- struct driver_dir_entry * entry;
- entry = (struct driver_dir_entry *)dentry->d_fsdata;
- if (entry)
- kfree(entry);
- return 0;
-}
-
static struct address_space_operations driverfs_aops = {
};
@@ -425,10 +421,6 @@ static struct dentry_operations driverfs_dentry_file_ops = {
d_delete: driverfs_d_delete_file,
};
-static struct dentry_operations driverfs_dentry_dir_ops = {
- d_delete: driverfs_d_delete_dir,
-};
-
static struct super_operations driverfs_ops = {
statfs: driverfs_statfs,
put_inode: force_delete,
@@ -546,33 +538,6 @@ MODULE_DESCRIPTION("The device driver filesystem");
MODULE_LICENSE("GPL");
/**
- * driverfs_create_dir_entry - allocate and initialise directory entry
- * @name: name of the directory
- * @mode: permissions of the dir
- */
-struct driver_dir_entry *
-driverfs_create_dir_entry(const char * name, mode_t mode)
-{
- struct driver_dir_entry * entry;
- int size = sizeof(struct driver_dir_entry) + strlen(name) + 1;
-
-
- entry = kmalloc(size, GFP_KERNEL);
- if (!entry)
- return NULL;
-
- memset(entry, 0, size);
- strcpy((char *)entry + sizeof(struct driver_dir_entry), name);
-
- entry->name = (char *)entry + sizeof(struct driver_dir_entry);
-
- INIT_LIST_HEAD(&entry->files);
- entry->mode = mode;
-
- return entry;
-}
-
-/**
* driverfs_create_dir - create a directory in the filesystem
* @entry: directory entry
* @parent: parent directory entry
@@ -672,6 +637,7 @@ driverfs_create_file(struct driver_file_entry * entry,
dentry->d_inode->u.generic_ip = (void *)entry;
entry->dentry = dentry;
+ entry->parent = parent;
list_add_tail(&entry->node,&parent->files);
}
@@ -784,39 +750,3 @@ void driverfs_remove_dir(struct driver_dir_entry * dir)
done:
put_mount();
}
-
-/**
- * driverfs_create_entry - allocate and initialise a struct driver_file_entry
- * @name: name of the file
- * @mode: permissions of the file
- * @ops: Operations for the file
- * @data: data that will be passed back to the callback
- *
- */
-struct driver_file_entry *
-driverfs_create_entry (const char * name, mode_t mode,
- struct driverfs_operations * ops, void * data)
-{
- struct driver_file_entry * entry;
- int size;
-
- size = sizeof(struct driver_file_entry) + strlen(name) + 1;
-
- entry = kmalloc(size,GFP_KERNEL);
- if (!entry)
- return NULL;
-
- memset(entry, 0, size);
- strcpy((char *)entry + sizeof(struct driver_file_entry), name);
-
- entry->name = (char *)entry + sizeof(struct driver_file_entry);
-
- INIT_LIST_HEAD(&entry->node);
-
- entry->mode = mode;
- entry->ops = ops;
- entry->data = data;
-
- return entry;
-}
-
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 9d273604a..f58731211 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -261,6 +261,7 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
inode->i_ino = j;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = inode->i_blksize = 0;
+ memset(&minix_i(inode)->u, 0, sizeof(minix_i(inode)->u));
insert_inode_hash(inode);
mark_inode_dirty(inode);
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 7cd92b2d6..1b4886e41 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -75,7 +75,51 @@ static void minix_put_super(struct super_block *sb)
return;
}
+static kmem_cache_t * minix_inode_cachep;
+
+static struct inode *minix_alloc_inode(struct super_block *sb)
+{
+ struct minix_inode_info *ei;
+ ei = (struct minix_inode_info *)kmem_cache_alloc(minix_inode_cachep, SLAB_KERNEL);
+ if (!ei)
+ return NULL;
+ return &ei->vfs_inode;
+}
+
+static void minix_destroy_inode(struct inode *inode)
+{
+ kmem_cache_free(minix_inode_cachep, minix_i(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+ struct minix_inode_info *ei = (struct minix_inode_info *) foo;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR)
+ inode_init_once(&ei->vfs_inode);
+}
+
+static int init_inodecache(void)
+{
+ minix_inode_cachep = kmem_cache_create("minix_inode_cache",
+ sizeof(struct minix_inode_info),
+ 0, SLAB_HWCACHE_ALIGN,
+ init_once, NULL);
+ if (minix_inode_cachep == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static void destroy_inodecache(void)
+{
+ if (kmem_cache_destroy(minix_inode_cachep))
+ printk(KERN_INFO "minix_inode_cache: not all structures were freed\n");
+}
+
static struct super_operations minix_sops = {
+ alloc_inode: minix_alloc_inode,
+ destroy_inode: minix_destroy_inode,
read_inode: minix_read_inode,
write_inode: minix_write_inode,
delete_inode: minix_delete_inode,
@@ -344,6 +388,7 @@ static void V1_minix_read_inode(struct inode * inode)
{
struct buffer_head * bh;
struct minix_inode * raw_inode;
+ struct minix_inode_info *minix_inode = minix_i(inode);
int i;
raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
@@ -359,7 +404,7 @@ static void V1_minix_read_inode(struct inode * inode)
inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
inode->i_blocks = inode->i_blksize = 0;
for (i = 0; i < 9; i++)
- inode->u.minix_i.u.i1_data[i] = raw_inode->i_zone[i];
+ minix_inode->u.i1_data[i] = raw_inode->i_zone[i];
minix_set_inode(inode, raw_inode->i_zone[0]);
brelse(bh);
}
@@ -371,6 +416,7 @@ static void V2_minix_read_inode(struct inode * inode)
{
struct buffer_head * bh;
struct minix2_inode * raw_inode;
+ struct minix_inode_info *minix_inode = minix_i(inode);
int i;
raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh);
@@ -388,7 +434,7 @@ static void V2_minix_read_inode(struct inode * inode)
inode->i_ctime = raw_inode->i_ctime;
inode->i_blocks = inode->i_blksize = 0;
for (i = 0; i < 10; i++)
- inode->u.minix_i.u.i2_data[i] = raw_inode->i_zone[i];
+ minix_inode->u.i2_data[i] = raw_inode->i_zone[i];
minix_set_inode(inode, raw_inode->i_zone[0]);
brelse(bh);
}
@@ -411,6 +457,7 @@ static struct buffer_head * V1_minix_update_inode(struct inode * inode)
{
struct buffer_head * bh;
struct minix_inode * raw_inode;
+ struct minix_inode_info *minix_inode = minix_i(inode);
int i;
raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
@@ -425,7 +472,7 @@ static struct buffer_head * V1_minix_update_inode(struct inode * inode)
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
else for (i = 0; i < 9; i++)
- raw_inode->i_zone[i] = inode->u.minix_i.u.i1_data[i];
+ raw_inode->i_zone[i] = minix_inode->u.i1_data[i];
mark_buffer_dirty(bh);
return bh;
}
@@ -437,6 +484,7 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode)
{
struct buffer_head * bh;
struct minix2_inode * raw_inode;
+ struct minix_inode_info *minix_inode = minix_i(inode);
int i;
raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh);
@@ -453,7 +501,7 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode)
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
else for (i = 0; i < 10; i++)
- raw_inode->i_zone[i] = inode->u.minix_i.u.i2_data[i];
+ raw_inode->i_zone[i] = minix_inode->u.i2_data[i];
mark_buffer_dirty(bh);
return bh;
}
@@ -514,12 +562,23 @@ static DECLARE_FSTYPE_DEV(minix_fs_type,"minix",minix_read_super);
static int __init init_minix_fs(void)
{
- return register_filesystem(&minix_fs_type);
+ int err = init_inodecache();
+ if (err)
+ goto out1;
+ err = register_filesystem(&minix_fs_type);
+ if (err)
+ goto out;
+ return 0;
+out:
+ destroy_inodecache();
+out1:
+ return err;
}
static void __exit exit_minix_fs(void)
{
unregister_filesystem(&minix_fs_type);
+ destroy_inodecache();
}
EXPORT_NO_SYMBOLS;
diff --git a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c
index 990dddd0d..31d85c109 100644
--- a/fs/minix/itree_v1.c
+++ b/fs/minix/itree_v1.c
@@ -19,7 +19,7 @@ static inline block_t cpu_to_block(unsigned long n)
static inline block_t *i_data(struct inode *inode)
{
- return (block_t *)inode->u.minix_i.u.i1_data;
+ return (block_t *)minix_i(inode)->u.i1_data;
}
static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c
index bbff60d85..5a3c8192a 100644
--- a/fs/minix/itree_v2.c
+++ b/fs/minix/itree_v2.c
@@ -19,7 +19,7 @@ static inline block_t cpu_to_block(unsigned long n)
static inline block_t *i_data(struct inode *inode)
{
- return (block_t *)inode->u.minix_i.u.i2_data;
+ return (block_t *)minix_i(inode)->u.i2_data;
}
static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
diff --git a/fs/namespace.c b/fs/namespace.c
index 093ed8ef6..fdcc369fb 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -38,7 +38,7 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
return tmp & hash_mask;
}
-struct vfsmount *alloc_vfsmnt(void)
+struct vfsmount *alloc_vfsmnt(char *name)
{
struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL);
if (mnt) {
@@ -48,6 +48,14 @@ struct vfsmount *alloc_vfsmnt(void)
INIT_LIST_HEAD(&mnt->mnt_child);
INIT_LIST_HEAD(&mnt->mnt_mounts);
INIT_LIST_HEAD(&mnt->mnt_list);
+ if (name) {
+ int size = strlen(name)+1;
+ char * newname = kmalloc(size, GFP_KERNEL);
+ if (newname) {
+ memcpy(newname, name, size);
+ mnt->mnt_devname = newname;
+ }
+ }
}
return mnt;
}
@@ -59,18 +67,6 @@ void free_vfsmnt(struct vfsmount *mnt)
kmem_cache_free(mnt_cache, mnt);
}
-void set_devname(struct vfsmount *mnt, const char *name)
-{
- if (name) {
- int size = strlen(name)+1;
- char * newname = kmalloc(size, GFP_KERNEL);
- if (newname) {
- memcpy(newname, name, size);
- mnt->mnt_devname = newname;
- }
- }
-}
-
struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
{
struct list_head * head = mount_hashtable + hash(mnt, dentry);
@@ -138,11 +134,10 @@ static struct vfsmount *
clone_mnt(struct vfsmount *old, struct dentry *root)
{
struct super_block *sb = old->mnt_sb;
- struct vfsmount *mnt = alloc_vfsmnt();
+ struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname);
if (mnt) {
mnt->mnt_flags = old->mnt_flags;
- set_devname(mnt, old->mnt_devname);
atomic_inc(&sb->s_active);
mnt->mnt_sb = sb;
mnt->mnt_root = dget(root);
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 4054697f6..32e089bd5 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -36,8 +36,54 @@ static void ncp_delete_inode(struct inode *);
static void ncp_put_super(struct super_block *);
static int ncp_statfs(struct super_block *, struct statfs *);
+static kmem_cache_t * ncp_inode_cachep;
+
+static struct inode *ncp_alloc_inode(struct super_block *sb)
+{
+ struct ncp_inode_info *ei;
+ ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, SLAB_KERNEL);
+ if (!ei)
+ return NULL;
+ return &ei->vfs_inode;
+}
+
+static void ncp_destroy_inode(struct inode *inode)
+{
+ kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+ struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR) {
+ init_MUTEX(&ei->open_sem);
+ inode_init_once(&ei->vfs_inode);
+ }
+}
+
+static int init_inodecache(void)
+{
+ ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
+ sizeof(struct ncp_inode_info),
+ 0, SLAB_HWCACHE_ALIGN,
+ init_once, NULL);
+ if (ncp_inode_cachep == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static void destroy_inodecache(void)
+{
+ if (kmem_cache_destroy(ncp_inode_cachep))
+ printk(KERN_INFO "ncp_inode_cache: not all structures were freed\n");
+}
+
static struct super_operations ncp_sops =
{
+ alloc_inode: ncp_alloc_inode,
+ destroy_inode: ncp_destroy_inode,
put_inode: force_delete,
delete_inode: ncp_delete_inode,
put_super: ncp_put_super,
@@ -61,6 +107,8 @@ void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
#ifdef CONFIG_NCPFS_STRONG
NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
+#else
+ NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
#endif
NCP_FINFO(inode)->access = nwinfo->access;
NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
@@ -216,7 +264,6 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
inode = new_inode(sb);
if (inode) {
- init_MUTEX(&NCP_FINFO(inode)->open_sem);
atomic_set(&NCP_FINFO(inode)->opened, info->opened);
inode->i_ino = info->ino;
@@ -707,19 +754,31 @@ static DECLARE_FSTYPE(ncp_fs_type, "ncpfs", ncp_read_super, 0);
static int __init init_ncp_fs(void)
{
+ int err;
DPRINTK("ncpfs: init_module called\n");
#ifdef DEBUG_NCP_MALLOC
ncp_malloced = 0;
ncp_current_malloced = 0;
#endif
- return register_filesystem(&ncp_fs_type);
+ err = init_inodecache();
+ if (err)
+ goto out1;
+ err = register_filesystem(&ncp_fs_type);
+ if (err)
+ goto out;
+ return 0;
+out:
+ destroy_inodecache();
+out1:
+ return err;
}
static void __exit exit_ncp_fs(void)
{
DPRINTK("ncpfs: cleanup_module called\n");
unregister_filesystem(&ncp_fs_type);
+ destroy_inodecache();
#ifdef DEBUG_NCP_MALLOC
PRINTK("ncp_malloced: %d\n", ncp_malloced);
PRINTK("ncp_current_malloced: %d\n", ncp_current_malloced);
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index a426e4f84..9b19cc7dd 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -466,6 +466,7 @@ int reiserfs_new_unf_blocknrs2 (struct reiserfs_transaction_handle *th,
unsigned long * free_blocknrs,
unsigned long search_start)
{
+ struct reiserfs_inode_info *ei = REISERFS_I(p_s_inode);
int ret=0, blks_gotten=0;
unsigned long border = 0;
unsigned long bstart = 0;
@@ -550,13 +551,13 @@ int reiserfs_new_unf_blocknrs2 (struct reiserfs_transaction_handle *th,
}
/* take a block off the prealloc list and return it -Hans */
- if (p_s_inode->u.reiserfs_i.i_prealloc_count > 0) {
- p_s_inode->u.reiserfs_i.i_prealloc_count--;
- *free_blocknrs = p_s_inode->u.reiserfs_i.i_prealloc_block++;
+ if (ei->i_prealloc_count > 0) {
+ ei->i_prealloc_count--;
+ *free_blocknrs = ei->i_prealloc_block++;
/* if no more preallocated blocks, remove inode from list */
- if (! p_s_inode->u.reiserfs_i.i_prealloc_count) {
- list_del(&p_s_inode->u.reiserfs_i.i_prealloc_list);
+ if (! ei->i_prealloc_count) {
+ list_del_init(&ei->i_prealloc_list);
}
return ret;
@@ -567,8 +568,8 @@ int reiserfs_new_unf_blocknrs2 (struct reiserfs_transaction_handle *th,
/* this uses the last preallocated block as the search_start. discard
** prealloc does not zero out this number.
*/
- if (search_start <= p_s_inode->u.reiserfs_i.i_prealloc_block) {
- search_start = p_s_inode->u.reiserfs_i.i_prealloc_block;
+ if (search_start <= ei->i_prealloc_block) {
+ search_start = ei->i_prealloc_block;
}
/* doing the compare again forces search_start to be >= the border,
@@ -611,18 +612,18 @@ int reiserfs_new_unf_blocknrs2 (struct reiserfs_transaction_handle *th,
}
#endif
if (blks_gotten==0) {
- p_s_inode->u.reiserfs_i.i_prealloc_block = *free_blocknrs;
+ ei->i_prealloc_block = *free_blocknrs;
}
search_start = *free_blocknrs;
*free_blocknrs = 0;
}
- p_s_inode->u.reiserfs_i.i_prealloc_count = blks;
- *free_blocknrs = p_s_inode->u.reiserfs_i.i_prealloc_block;
- p_s_inode->u.reiserfs_i.i_prealloc_block++;
+ ei->i_prealloc_count = blks;
+ *free_blocknrs = ei->i_prealloc_block;
+ ei->i_prealloc_block++;
/* if inode has preallocated blocks, link him to list */
- if (p_s_inode->u.reiserfs_i.i_prealloc_count) {
- list_add(&p_s_inode->u.reiserfs_i.i_prealloc_list,
+ if (ei->i_prealloc_count) {
+ list_add(&ei->i_prealloc_list,
&SB_JOURNAL(th->t_super)->j_prealloc_list);
}
/* we did actually manage to get 1 block */
@@ -657,42 +658,43 @@ int reiserfs_new_unf_blocknrs2 (struct reiserfs_transaction_handle *th,
// analog. You should be able to tell which portion by looking at the
// ext2 code and comparing.
static void __discard_prealloc (struct reiserfs_transaction_handle * th,
- struct inode * inode)
+ struct reiserfs_inode_info *ei)
{
- while (inode->u.reiserfs_i.i_prealloc_count > 0) {
- reiserfs_free_block(th,inode->u.reiserfs_i.i_prealloc_block);
- inode->u.reiserfs_i.i_prealloc_block++;
- inode->u.reiserfs_i.i_prealloc_count --;
+ while (ei->i_prealloc_count > 0) {
+ reiserfs_free_block(th,ei->i_prealloc_block);
+ ei->i_prealloc_block++;
+ ei->i_prealloc_count --;
}
- list_del (&(inode->u.reiserfs_i.i_prealloc_list));
+ list_del_init(&(ei->i_prealloc_list));
}
void reiserfs_discard_prealloc (struct reiserfs_transaction_handle *th,
struct inode * inode)
{
+ struct reiserfs_inode_info *ei = REISERFS_I(inode);
#ifdef CONFIG_REISERFS_CHECK
- if (inode->u.reiserfs_i.i_prealloc_count < 0)
+ if (ei->i_prealloc_count < 0)
reiserfs_warning("zam-4001:" __FUNCTION__ ": inode has negative prealloc blocks count.\n");
#endif
- if (inode->u.reiserfs_i.i_prealloc_count > 0) {
- __discard_prealloc(th, inode);
+ if (ei->i_prealloc_count > 0) {
+ __discard_prealloc(th, ei);
}
}
void reiserfs_discard_all_prealloc (struct reiserfs_transaction_handle *th)
{
struct list_head * plist = &SB_JOURNAL(th->t_super)->j_prealloc_list;
- struct inode * inode;
while (!list_empty(plist)) {
- inode = list_entry(plist->next, struct inode, u.reiserfs_i.i_prealloc_list);
+ struct reiserfs_inode_info *ei;
+ ei = list_entry(plist->next, struct reiserfs_inode_info, i_prealloc_list);
#ifdef CONFIG_REISERFS_CHECK
- if (!inode->u.reiserfs_i.i_prealloc_count) {
- reiserfs_warning("zam-4001:" __FUNCTION__ ": inode is in prealloc list but has no preallocated blocks.\n");
- }
-#endif
- __discard_prealloc(th, inode);
+ if (!ei->i_prealloc_count) {
+ reiserfs_warning("zam-4001:" __FUNCTION__ ": inode is in prealloc list but has no preallocated blocks.\n");
+ }
+#endif
+ __discard_prealloc(th, ei);
}
}
#endif
diff --git a/fs/reiserfs/buffer2.c b/fs/reiserfs/buffer2.c
index 7e854531e..c94034092 100644
--- a/fs/reiserfs/buffer2.c
+++ b/fs/reiserfs/buffer2.c
@@ -186,7 +186,7 @@ inline int get_last_unformatted_node_blocknr_of_file( struct key * p_s_key_to_s
copy_key(&unf_key_to_search,p_s_key_to_search);
unf_key_to_search.k_uniqueness = TYPE_INDIRECT;
- unf_key_to_search.k_offset = p_s_inode->u.reiserfs_i.i_first_direct_byte - 1;
+ unf_key_to_search.k_offset = REISERFS_I(p_s_inode)->i_first_direct_byte - 1;
/* p_s_key_to_search->k_offset - MAX_ITEM_LEN(p_s_sb->s_blocksize); */
if (search_for_position_by_key (p_s_sb, &unf_key_to_search, p_unf_search_path, &n_pos_in_item) == POSITION_FOUND)
@@ -218,16 +218,16 @@ static int get_buffer_near_last_unf ( struct super_block * p_s_sb, struct key *
unf_key_to_search.k_uniqueness = TYPE_INDIRECT;
if (
- (p_s_inode->u.reiserfs_i.i_first_direct_byte > 4095) /* i_first_direct_byte gets used for all sorts of
+ (REISERFS_I(p_s_inode)->i_first_direct_byte > 4095) /* i_first_direct_byte gets used for all sorts of
crap other than what the name indicates, thus
testing to see if it is 0 is not enough */
- && (p_s_inode->u.reiserfs_i.i_first_direct_byte < MAX_KEY_OFFSET) /* if there is no direct item then
+ && (REISERFS_I(p_s_inode)->i_first_direct_byte < MAX_KEY_OFFSET) /* if there is no direct item then
i_first_direct_byte = MAX_KEY_OFFSET */
)
{
/* actually, we don't want the last unformatted node, we want the last unformatted node
which is before the current file offset */
- unf_key_to_search.k_offset = ((p_s_inode->u.reiserfs_i.i_first_direct_byte -1) < unf_key_to_search.k_offset) ? p_s_inode->u.reiserfs_i.i_first_direct_byte -1 : unf_key_to_search.k_offset;
+ unf_key_to_search.k_offset = ((REISERFS_I(p_s_inode)->i_first_direct_byte -1) < unf_key_to_search.k_offset) ? REISERFS_I(p_s_inode)->i_first_direct_byte -1 : unf_key_to_search.k_offset;
while (unf_key_to_search.k_offset > -1)
{
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 3a41dc5f4..d68564b04 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -33,9 +33,9 @@ static int reiserfs_file_release (struct inode * inode, struct file * filp)
/* fast out for when nothing needs to be done */
if ((atomic_read(&inode->i_count) > 1 ||
- !inode->u.reiserfs_i.i_pack_on_close ||
+ REISERFS_I(inode)->i_pack_on_close ||
!tail_has_to_be_packed(inode)) &&
- inode->u.reiserfs_i.i_prealloc_count <= 0) {
+ REISERFS_I(inode)->i_prealloc_count <= 0) {
return 0;
}
@@ -50,7 +50,7 @@ static int reiserfs_file_release (struct inode * inode, struct file * filp)
journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3) ;
if (atomic_read(&inode->i_count) <= 1 &&
- inode->u.reiserfs_i.i_pack_on_close &&
+ REISERFS_I(inode)->i_pack_on_close &&
tail_has_to_be_packed (inode)) {
/* if regular file is released by last holder and it has been
appended (we append by unformatted node only) or its direct
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index f9748aac8..7b760ac02 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -69,7 +69,7 @@ static void _make_cpu_key (struct cpu_key * key, int version, __u32 dirid, __u32
/* take base of inode_key (it comes from inode always) (dirid, objectid) and version from an inode, set
offset and type of key */
-void make_cpu_key (struct cpu_key * key, const struct inode * inode, loff_t offset,
+void make_cpu_key (struct cpu_key * key, struct inode * inode, loff_t offset,
int type, int length )
{
_make_cpu_key (key, inode_items_version (inode), le32_to_cpu (INODE_PKEY (inode)->k_dir_id),
@@ -559,7 +559,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
return ret;
}
- inode->u.reiserfs_i.i_pack_on_close = 1 ;
+ REISERFS_I(inode)->i_pack_on_close = 1 ;
windex = push_journal_writer("reiserfs_get_block") ;
@@ -868,8 +868,6 @@ static void init_inode (struct inode * inode, struct path * path)
copy_key (INODE_PKEY (inode), &(ih->ih_key));
inode->i_blksize = PAGE_SIZE;
- INIT_LIST_HEAD(&inode->u.reiserfs_i.i_prealloc_list) ;
-
if (stat_data_v1 (ih)) {
struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
unsigned long blocks;
@@ -898,7 +896,7 @@ static void init_inode (struct inode * inode, struct path * path)
}
rdev = sd_v1_rdev(sd);
- inode->u.reiserfs_i.i_first_direct_byte = sd_v1_first_direct_byte(sd);
+ REISERFS_I(inode)->i_first_direct_byte = sd_v1_first_direct_byte(sd);
} else {
// new stat data found, but object may have old items
// (directories and symlinks)
@@ -926,10 +924,15 @@ static void init_inode (struct inode * inode, struct path * path)
inode_items_version (inode) = ITEM_VERSION_1;
else
inode_items_version (inode) = ITEM_VERSION_2;
+ REISERFS_I(inode)->i_first_direct_byte = 0;
}
-
+ REISERFS_I(inode)->i_pack_on_close = 0;
+ REISERFS_I(inode)->i_prealloc_block = 0;
+ REISERFS_I(inode)->i_prealloc_count = 0;
+ REISERFS_I(inode)->i_trans_id = 0;
+ REISERFS_I(inode)->i_trans_index = 0;
/* nopack = 0, by default */
- inode->u.reiserfs_i.nopack = 0;
+ REISERFS_I(inode)->nopack = 0;
pathrelse (path);
if (S_ISREG (inode->i_mode)) {
@@ -993,7 +996,7 @@ static void inode2sd_v1 (void * sd, struct inode * inode)
set_sd_v1_blocks(sd_v1, inode->i_blocks );
// Sigh. i_first_direct_byte is back
- set_sd_v1_first_direct_byte(sd_v1, inode->u.reiserfs_i.i_first_direct_byte);
+ set_sd_v1_first_direct_byte(sd_v1, REISERFS_I(inode)->i_first_direct_byte);
}
@@ -1331,7 +1334,7 @@ int reiserfs_sync_inode (struct reiserfs_transaction_handle *th, struct inode *
containing "." and ".." entries */
static int reiserfs_new_directory (struct reiserfs_transaction_handle *th,
struct item_head * ih, struct path * path,
- const struct inode * dir)
+ struct inode * dir)
{
struct super_block * sb = th->t_super;
char empty_dir [EMPTY_DIR_SIZE];
@@ -1419,7 +1422,7 @@ static int reiserfs_new_symlink (struct reiserfs_transaction_handle *th,
directory) or reiserfs_new_symlink (to insert symlink body if new
object is symlink) or nothing (if new object is regular file) */
struct inode * reiserfs_new_inode (struct reiserfs_transaction_handle *th,
- const struct inode * dir, int mode,
+ struct inode * dir, int mode,
const char * symname,
int i_size, /* 0 for regular, EMTRY_DIR_SIZE for dirs,
strlen (symname) for symlinks)*/
@@ -1501,10 +1504,15 @@ struct inode * reiserfs_new_inode (struct reiserfs_transaction_handle *th,
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_size = i_size;
inode->i_blocks = (inode->i_size + 511) >> 9;
- inode->u.reiserfs_i.i_first_direct_byte = S_ISLNK(mode) ? 1 :
+ REISERFS_I(inode)->i_first_direct_byte = S_ISLNK(mode) ? 1 :
U32_MAX/*NO_BYTES_IN_DIRECT_ITEM*/;
- INIT_LIST_HEAD(&inode->u.reiserfs_i.i_prealloc_list) ;
+ REISERFS_I(inode)->i_pack_on_close = 0;
+ REISERFS_I(inode)->i_prealloc_block = 0;
+ REISERFS_I(inode)->i_prealloc_count = 0;
+ REISERFS_I(inode)->nopack = 0;
+ REISERFS_I(inode)->i_trans_id = 0;
+ REISERFS_I(inode)->i_trans_index = 0;
if (old_format_only (sb))
inode2sd_v1 (&sd, inode);
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index d142a322c..2d0f172dc 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -46,7 +46,7 @@ int reiserfs_unpack (struct inode * inode, struct file * filp)
return -EINVAL ;
}
/* ioctl already done */
- if (inode->u.reiserfs_i.nopack) {
+ if (REISERFS_I(inode)->nopack) {
return 0 ;
}
lock_kernel();
@@ -59,7 +59,7 @@ int reiserfs_unpack (struct inode * inode, struct file * filp)
write_from = inode->i_size & (blocksize - 1) ;
/* if we are on a block boundary, we are already unpacked. */
if ( write_from == 0) {
- inode->u.reiserfs_i.nopack = 1;
+ REISERFS_I(inode)->nopack = 1;
goto out ;
}
@@ -79,7 +79,7 @@ int reiserfs_unpack (struct inode * inode, struct file * filp)
/* conversion can change page contents, must flush */
flush_dcache_page(page) ;
- inode->u.reiserfs_i.nopack = 1;
+ REISERFS_I(inode)->nopack = 1;
kunmap(page) ; /* mapped by prepare_write */
out_unlock:
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 1c9dc427c..fe718c7cd 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2613,14 +2613,14 @@ int journal_mark_freed(struct reiserfs_transaction_handle *th, struct super_bloc
void reiserfs_update_inode_transaction(struct inode *inode) {
- inode->u.reiserfs_i.i_trans_index = SB_JOURNAL_LIST_INDEX(inode->i_sb);
+ REISERFS_I(inode)->i_trans_index = SB_JOURNAL_LIST_INDEX(inode->i_sb);
- inode->u.reiserfs_i.i_trans_id = SB_JOURNAL(inode->i_sb)->j_trans_id ;
+ REISERFS_I(inode)->i_trans_id = SB_JOURNAL(inode->i_sb)->j_trans_id ;
}
static int reiserfs_inode_in_this_transaction(struct inode *inode) {
- if (inode->u.reiserfs_i.i_trans_id == SB_JOURNAL(inode->i_sb)->j_trans_id ||
- inode->u.reiserfs_i.i_trans_id == 0) {
+ if (REISERFS_I(inode)->i_trans_id == SB_JOURNAL(inode->i_sb)->j_trans_id ||
+ REISERFS_I(inode)->i_trans_id == 0) {
return 1;
}
return 0 ;
@@ -2631,14 +2631,14 @@ void reiserfs_commit_for_inode(struct inode *inode) {
struct reiserfs_transaction_handle th ;
struct super_block *sb = inode->i_sb ;
- jl = SB_JOURNAL_LIST(sb) + inode->u.reiserfs_i.i_trans_index ;
+ jl = SB_JOURNAL_LIST(sb) + REISERFS_I(inode)->i_trans_index ;
/* is it from the current transaction, or from an unknown transaction? */
if (reiserfs_inode_in_this_transaction(inode)) {
journal_join(&th, sb, 1) ;
reiserfs_update_inode_transaction(inode) ;
journal_end_sync(&th, sb, 1) ;
- } else if (jl->j_trans_id == inode->u.reiserfs_i.i_trans_id) {
+ } else if (jl->j_trans_id == REISERFS_I(inode)->i_trans_id) {
flush_commit_list(sb, jl, 1) ;
}
/* if the transaction id does not match, this list is long since flushed
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 482b03d94..defc862b7 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -1489,7 +1489,7 @@ static int maybe_indirect_to_direct (struct reiserfs_transaction_handle *th,
*/
if (atomic_read(&p_s_inode->i_count) > 1 ||
!tail_has_to_be_packed (p_s_inode) ||
- !page || p_s_inode->u.reiserfs_i.nopack) {
+ !page || REISERFS_I(p_s_inode)->nopack) {
// leave tail in an unformatted node
*p_c_mode = M_SKIP_BALANCING;
cut_bytes = n_block_size - (n_new_file_size & (n_block_size - 1));
@@ -1654,7 +1654,7 @@ int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
/* we delete first part of tail which was stored in direct
item(s) */
// FIXME: this is to keep 3.5 happy
- p_s_inode->u.reiserfs_i.i_first_direct_byte = U32_MAX;
+ REISERFS_I(p_s_inode)->i_first_direct_byte = U32_MAX;
p_s_inode->i_blocks -= p_s_sb->s_blocksize / 512;
}
}
@@ -1691,7 +1691,7 @@ int reiserfs_cut_from_item (struct reiserfs_transaction_handle *th,
** be flushed before the transaction commits, so we don't need to
** deal with it here.
*/
- p_s_inode->u.reiserfs_i.i_pack_on_close = 0 ;
+ REISERFS_I(p_s_inode)->i_pack_on_close = 0 ;
}
return n_ret_value;
}
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 4281c39ee..65d6d90d8 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -124,8 +124,54 @@ void reiserfs_put_super (struct super_block * s)
return;
}
+static kmem_cache_t * reiserfs_inode_cachep;
+
+static struct inode *reiserfs_alloc_inode(struct super_block *sb)
+{
+ struct reiserfs_inode_info *ei;
+ ei = (struct reiserfs_inode_info *)kmem_cache_alloc(reiserfs_inode_cachep, SLAB_KERNEL);
+ if (!ei)
+ return NULL;
+ return &ei->vfs_inode;
+}
+
+static void reiserfs_destroy_inode(struct inode *inode)
+{
+ kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+ struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *) foo;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR) {
+ INIT_LIST_HEAD(&ei->i_prealloc_list) ;
+ inode_init_once(&ei->vfs_inode);
+ }
+}
+
+static int init_inodecache(void)
+{
+ reiserfs_inode_cachep = kmem_cache_create("reiserfs_inode_cache",
+ sizeof(struct reiserfs_inode_info),
+ 0, SLAB_HWCACHE_ALIGN,
+ init_once, NULL);
+ if (reiserfs_inode_cachep == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static void destroy_inodecache(void)
+{
+ if (kmem_cache_destroy(reiserfs_inode_cachep))
+ printk(KERN_INFO "reiserfs_inode_cache: not all structures were freed\n");
+}
+
struct super_operations reiserfs_sops =
{
+ alloc_inode: reiserfs_alloc_inode,
+ destroy_inode: reiserfs_destroy_inode,
read_inode: reiserfs_read_inode,
read_inode2: reiserfs_read_inode2,
write_inode: reiserfs_write_inode,
@@ -365,7 +411,7 @@ static int read_super_block (struct super_block * s, int offset)
bh = sb_bread (s, offset / s->s_blocksize);
if (!bh) {
printk ("read_super_block: "
- "bread failed (dev %s, block %d, size %d)\n",
+ "bread failed (dev %s, block %ld, size %ld)\n",
s->s_id, offset / s->s_blocksize, s->s_blocksize);
return 1;
}
@@ -373,7 +419,7 @@ static int read_super_block (struct super_block * s, int offset)
rs = (struct reiserfs_super_block *)bh->b_data;
if (!is_reiserfs_magic_string (rs)) {
printk ("read_super_block: "
- "can't find a reiserfs filesystem on (dev %s, block %lu, size %d)\n",
+ "can't find a reiserfs filesystem on (dev %s, block %lu, size %ld)\n",
s->s_id, bh->b_blocknr, s->s_blocksize);
brelse (bh);
return 1;
@@ -389,7 +435,7 @@ static int read_super_block (struct super_block * s, int offset)
bh = reiserfs_bread (s, offset / s->s_blocksize);
if (!bh) {
printk("read_super_block: "
- "bread failed (dev %s, block %d, size %d)\n",
+ "bread failed (dev %s, block %ld, size %ld)\n",
s->s_id, offset / s->s_blocksize, s->s_blocksize);
return 1;
}
@@ -397,7 +443,7 @@ static int read_super_block (struct super_block * s, int offset)
rs = (struct reiserfs_super_block *)bh->b_data;
if (!is_reiserfs_magic_string (rs) || sb_blocksize(rs) != s->s_blocksize) {
printk ("read_super_block: "
- "can't find a reiserfs filesystem on (dev %s, block %lu, size %d)\n",
+ "can't find a reiserfs filesystem on (dev %s, block %lu, size %ld)\n",
s->s_id, bh->b_blocknr, s->s_blocksize);
brelse (bh);
printk ("read_super_block: can't find a reiserfs filesystem on dev %s.\n", s->s_id);
@@ -803,10 +849,22 @@ static DECLARE_FSTYPE_DEV(reiserfs_fs_type,"reiserfs",reiserfs_read_super);
//
static int __init init_reiserfs_fs (void)
{
+ int err = init_inodecache();
+ if (err)
+ goto out1;
reiserfs_proc_info_global_init();
reiserfs_proc_register_global( "version",
reiserfs_global_version_in_proc );
- return register_filesystem(&reiserfs_fs_type);
+ err = register_filesystem(&reiserfs_fs_type);
+ if (err)
+ goto out;
+ return 0;
+out:
+ reiserfs_proc_unregister_global( "version" );
+ reiserfs_proc_info_global_done();
+ destroy_inodecache();
+out1:
+ return err;
}
MODULE_DESCRIPTION("ReiserFS journaled filesystem");
@@ -822,6 +880,7 @@ static void __exit exit_reiserfs_fs(void)
reiserfs_proc_unregister_global( "version" );
reiserfs_proc_info_global_done();
unregister_filesystem(&reiserfs_fs_type);
+ destroy_inodecache();
}
module_init(init_reiserfs_fs) ;
diff --git a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
index 5648d0985..8f433ebce 100644
--- a/fs/reiserfs/tail_conversion.c
+++ b/fs/reiserfs/tail_conversion.c
@@ -125,7 +125,7 @@ int direct2indirect (struct reiserfs_transaction_handle *th, struct inode * inod
memset(page_address(unbh->b_page) + pgoff, 0, n_blk_size - total_tail) ;
}
- inode->u.reiserfs_i.i_first_direct_byte = U32_MAX;
+ REISERFS_I(inode)->i_first_direct_byte = U32_MAX;
return 0;
}
@@ -285,7 +285,7 @@ int indirect2direct (struct reiserfs_transaction_handle *th,
/* we store position of first direct item in the in-core inode */
//mark_file_with_tail (p_s_inode, pos1 + 1);
- p_s_inode->u.reiserfs_i.i_first_direct_byte = pos1 + 1;
+ REISERFS_I(p_s_inode)->i_first_direct_byte = pos1 + 1;
return n_block_size - round_tail_len;
}
diff --git a/fs/super.c b/fs/super.c
index 14f9a9a9a..fb7060279 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -408,9 +408,8 @@ static void remove_super(struct super_block *s)
put_anon_dev(dev);
}
-struct vfsmount *alloc_vfsmnt(void);
+struct vfsmount *alloc_vfsmnt(char *name);
void free_vfsmnt(struct vfsmount *mnt);
-void set_devname(struct vfsmount *mnt, const char *name);
static inline struct super_block * find_super(kdev_t dev)
{
@@ -790,10 +789,9 @@ do_kern_mount(const char *fstype, int flags, char *name, void *data)
if (!type)
return ERR_PTR(-ENODEV);
- mnt = alloc_vfsmnt();
+ mnt = alloc_vfsmnt(name);
if (!mnt)
goto out;
- set_devname(mnt, name);
if (type->fs_flags & FS_REQUIRES_DEV)
sb = get_sb_bdev(type, flags, name, data);
else if (type->fs_flags & FS_SINGLE)
diff --git a/fs/sysv/ChangeLog b/fs/sysv/ChangeLog
index 38525d6ce..f379adc79 100644
--- a/fs/sysv/ChangeLog
+++ b/fs/sysv/ChangeLog
@@ -1,3 +1,33 @@
+Mon Jan 21 2001 Alexander Viro <viro@math.psu.edu>
+ * ialloc.c (sysv_new_inode): zero SYSV_I(inode)->i_data out.
+ * i_vnode renamed to vfs_inode. Sorry, but let's keep that
+ consistent.
+
+Sat Jan 19 2001 Christoph Hellwig <hch@infradead.org>
+
+ * include/linux/sysv_fs.h (SYSV_I): Get fs-private inode data using
+ list_entry() instead of inode->u.
+ * include/linux/sysv_fs_i.h: Add 'struct inode i_vnode' field to
+ sysv_inode_info structure.
+ * inode.c: Include <linux/slab.h>, implement alloc_inode/destroy_inode
+ sop methods, add infrastructure for per-fs inode slab cache.
+ * super.c (init_sysv_fs): Initialize inode cache, recover properly
+ in the case of failed register_filesystem for V7.
+ (exit_sysv_fs): Destroy inode cache.
+
+Sat Jan 19 2001 Christoph Hellwig <hch@infradead.org>
+
+ * include/linux/sysv_fs.h: Include <linux/sysv_fs_i.h>, declare SYSV_I().
+ * dir.c (sysv_find_entry): Use SYSV_I() instead of ->u.sysv_i to
+ access fs-private inode data.
+ * ialloc.c (sysv_new_inode): Likewise.
+ * inode.c (sysv_read_inode): Likewise.
+ (sysv_update_inode): Likewise.
+ * itree.c (get_branch): Likewise.
+ (sysv_truncate): Likewise.
+ * symlink.c (sysv_readlink): Likewise.
+ (sysv_follow_link): Likewise.
+
Fri Jan 4 2001 Alexander Viro <viro@math.psu.edu>
* ialloc.c (sysv_free_inode): Use sb->s_id instead of bdevname().
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index db0b23354..99cd28465 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -145,7 +145,7 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_
*res_page = NULL;
- start = dir->u.sysv_i.i_dir_start_lookup;
+ start = SYSV_I(dir)->i_dir_start_lookup;
if (start >= npages)
start = 0;
n = start;
@@ -174,7 +174,7 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_
return NULL;
found:
- dir->u.sysv_i.i_dir_start_lookup = n;
+ SYSV_I(dir)->i_dir_start_lookup = n;
*res_page = page;
return de;
}
diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
index 4e20e5e98..361e8965b 100644
--- a/fs/sysv/ialloc.c
+++ b/fs/sysv/ialloc.c
@@ -165,7 +165,8 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
inode->i_ino = fs16_to_cpu(sb, ino);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = inode->i_blksize = 0;
- inode->u.sysv_i.i_dir_start_lookup = 0;
+ memset(SYSV_I(inode)->i_data, 0, sizeof(SYSV_I(inode)->i_data));
+ SYSV_I(inode)->i_dir_start_lookup = 0;
insert_inode_hash(inode);
mark_inode_dirty(inode);
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 15b8b321b..c554f1d46 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -26,6 +26,7 @@
#include <linux/locks.h>
#include <linux/smp_lock.h>
#include <linux/highuid.h>
+#include <linux/slab.h>
#include <asm/byteorder.h>
/* This is only called on sync() and umount(), when s_dirt=1. */
@@ -144,6 +145,7 @@ static void sysv_read_inode(struct inode *inode)
struct super_block * sb = inode->i_sb;
struct buffer_head * bh;
struct sysv_inode * raw_inode;
+ struct sysv_inode_info * si;
unsigned int block, ino;
dev_t rdev = 0;
@@ -169,13 +171,15 @@ static void sysv_read_inode(struct inode *inode)
inode->i_mtime = fs32_to_cpu(sb, raw_inode->i_mtime);
inode->i_ctime = fs32_to_cpu(sb, raw_inode->i_ctime);
inode->i_blocks = inode->i_blksize = 0;
+
+ si = SYSV_I(inode);
for (block = 0; block < 10+1+1+1; block++)
read3byte(sb, &raw_inode->i_a.i_addb[3*block],
- (unsigned char*)&inode->u.sysv_i.i_data[block]);
+ (unsigned char*)&si->i_data[block]);
brelse(bh);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- rdev = (u16)fs32_to_cpu(sb, inode->u.sysv_i.i_data[0]);
- inode->u.sysv_i.i_dir_start_lookup = 0;
+ rdev = (u16)fs32_to_cpu(sb, si->i_data[0]);
+ si->i_dir_start_lookup = 0;
sysv_set_inode(inode, rdev);
return;
@@ -189,6 +193,7 @@ static struct buffer_head * sysv_update_inode(struct inode * inode)
struct super_block * sb = inode->i_sb;
struct buffer_head * bh;
struct sysv_inode * raw_inode;
+ struct sysv_inode_info * si;
unsigned int ino, block;
ino = inode->i_ino;
@@ -211,11 +216,12 @@ static struct buffer_head * sysv_update_inode(struct inode * inode)
raw_inode->i_atime = cpu_to_fs32(sb, inode->i_atime);
raw_inode->i_mtime = cpu_to_fs32(sb, inode->i_mtime);
raw_inode->i_ctime = cpu_to_fs32(sb, inode->i_ctime);
+
+ si = SYSV_I(inode);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- inode->u.sysv_i.i_data[0] =
- cpu_to_fs32(sb, kdev_t_to_nr(inode->i_rdev));
+ si->i_data[0] = cpu_to_fs32(sb, kdev_t_to_nr(inode->i_rdev));
for (block = 0; block < 10+1+1+1; block++)
- write3byte(sb, (unsigned char*)&inode->u.sysv_i.i_data[block],
+ write3byte(sb, (unsigned char*)&si->i_data[block],
&raw_inode->i_a.i_addb[3*block]);
mark_buffer_dirty(bh);
return bh;
@@ -260,7 +266,35 @@ static void sysv_delete_inode(struct inode *inode)
unlock_kernel();
}
+static kmem_cache_t *sysv_inode_cachep;
+
+static struct inode *sysv_alloc_inode(struct super_block *sb)
+{
+ struct sysv_inode_info *si;
+
+ si = kmem_cache_alloc(sysv_inode_cachep, SLAB_KERNEL);
+ if (!si)
+ return NULL;
+ return &si->vfs_inode;
+}
+
+static void sysv_destroy_inode(struct inode *inode)
+{
+ kmem_cache_free(sysv_inode_cachep, SYSV_I(inode));
+}
+
+static void init_once(void *p, kmem_cache_t *cachep, unsigned long flags)
+{
+ struct sysv_inode_info *si = (struct sysv_inode_info *)p;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR)
+ inode_init_once(&si->vfs_inode);
+}
+
struct super_operations sysv_sops = {
+ alloc_inode: sysv_alloc_inode,
+ destroy_inode: sysv_destroy_inode,
read_inode: sysv_read_inode,
write_inode: sysv_write_inode,
delete_inode: sysv_delete_inode,
@@ -268,3 +302,18 @@ struct super_operations sysv_sops = {
write_super: sysv_write_super,
statfs: sysv_statfs,
};
+
+int __init sysv_init_icache(void)
+{
+ sysv_inode_cachep = kmem_cache_create("sysv_inode_cache",
+ sizeof(struct sysv_inode_info), 0,
+ SLAB_HWCACHE_ALIGN, init_once, NULL);
+ if (!sysv_inode_cachep)
+ return -ENOMEM;
+ return 0;
+}
+
+void sysv_destroy_icache(void)
+{
+ kmem_cache_destroy(sysv_inode_cachep);
+}
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index b88cc4325..4ff94df7a 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -91,7 +91,7 @@ static Indirect *get_branch(struct inode *inode,
struct buffer_head *bh;
*err = 0;
- add_chain (chain, NULL, inode->u.sysv_i.i_data + *offsets);
+ add_chain (chain, NULL, SYSV_I(inode)->i_data + *offsets);
if (!p->key)
goto no_block;
while (--depth) {
@@ -348,7 +348,7 @@ static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
void sysv_truncate (struct inode * inode)
{
- u32 *i_data = inode->u.sysv_i.i_data;
+ u32 *i_data = SYSV_I(inode)->i_data;
int offsets[DEPTH];
Indirect chain[DEPTH];
Indirect *partial;
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index 7c9c82932..1e853dd27 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -479,18 +479,37 @@ failed:
static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super);
static DECLARE_FSTYPE_DEV(v7_fs_type, "v7", v7_read_super);
+extern int sysv_init_icache(void) __init;
+extern void sysv_destroy_icache(void);
+
static int __init init_sysv_fs(void)
{
- int err = register_filesystem(&sysv_fs_type);
- if (!err)
- err = register_filesystem(&v7_fs_type);
- return err;
+ int error;
+
+ error = sysv_init_icache();
+ if (error)
+ goto out;
+ error = register_filesystem(&sysv_fs_type);
+ if (error)
+ goto destroy_icache;
+ error = register_filesystem(&v7_fs_type);
+ if (error)
+ goto unregister;
+ return 0;
+
+unregister:
+ unregister_filesystem(&sysv_fs_type);
+destroy_icache:
+ sysv_destroy_icache();
+out:
+ return error;
}
static void __exit exit_sysv_fs(void)
{
unregister_filesystem(&sysv_fs_type);
unregister_filesystem(&v7_fs_type);
+ sysv_destroy_icache();
}
EXPORT_NO_SYMBOLS;
diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c
index d68403177..3335bb130 100644
--- a/fs/sysv/symlink.c
+++ b/fs/sysv/symlink.c
@@ -6,16 +6,17 @@
*/
#include <linux/fs.h>
+#include <linux/sysv_fs.h>
static int sysv_readlink(struct dentry *dentry, char *buffer, int buflen)
{
- char *s = (char *)dentry->d_inode->u.sysv_i.i_data;
+ char *s = (char *)SYSV_I(dentry->d_inode)->i_data;
return vfs_readlink(dentry, buffer, buflen, s);
}
static int sysv_follow_link(struct dentry *dentry, struct nameidata *nd)
{
- char *s = (char *)dentry->d_inode->u.sysv_i.i_data;
+ char *s = (char *)SYSV_I(dentry->d_inode)->i_data;
return vfs_follow_link(nd, s);
}
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index 7d44903b1..e560827b0 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -95,6 +95,11 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
}
lock_super(sb);
+ UDF_I_UNIQUE(inode) = 0;
+ UDF_I_LENEXTENTS(inode) = 0;
+ UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
+ UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
+ UDF_I_STRAT4096(inode) = 0;
if (UDF_SB_LVIDBH(sb))
{
struct LogicalVolHeaderDesc *lvhd;
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index edd94ec5b..2f5737451 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -945,7 +945,6 @@ __udf_read_inode(struct inode *inode)
* i_nlink = 1
* i_op = NULL;
*/
-
inode->i_blksize = PAGE_SIZE;
bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
@@ -1042,6 +1041,16 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
UDF_I_STRAT4096(inode) = 1;
UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICB_FLAG_ALLOC_MASK;
+ UDF_I_UMTIME(inode) = 0;
+ UDF_I_UCTIME(inode) = 0;
+ UDF_I_CRTIME(inode) = 0;
+ UDF_I_UCRTIME(inode) = 0;
+ UDF_I_UNIQUE(inode) = 0;
+ UDF_I_LENEATTR(inode) = 0;
+ UDF_I_LENEXTENTS(inode) = 0;
+ UDF_I_LENALLOC(inode) = 0;
+ UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
+ UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
if (fe->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY)
UDF_I_EXTENDED_FE(inode) = 1;
else if (fe->descTag.tagIdent == TID_FILE_ENTRY)
@@ -1070,9 +1079,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
inode->i_mode = udf_convert_permissions(fe);
inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;
- UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
- UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
-
if (UDF_I_EXTENDED_FE(inode) == 0)
{
inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 7a06f1d27..a4984734a 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -98,8 +98,52 @@ static int udf_statfs(struct super_block *, struct statfs *);
/* UDF filesystem type */
static DECLARE_FSTYPE_DEV(udf_fstype, "udf", udf_read_super);
+static kmem_cache_t * udf_inode_cachep;
+
+static struct inode *udf_alloc_inode(struct super_block *sb)
+{
+ struct udf_inode_info *ei;
+ ei = (struct udf_inode_info *)kmem_cache_alloc(udf_inode_cachep, SLAB_KERNEL);
+ if (!ei)
+ return NULL;
+ return &ei->vfs_inode;
+}
+
+static void udf_destroy_inode(struct inode *inode)
+{
+ kmem_cache_free(udf_inode_cachep, UDF_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+ struct udf_inode_info *ei = (struct udf_inode_info *) foo;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR)
+ inode_init_once(&ei->vfs_inode);
+}
+
+static int init_inodecache(void)
+{
+ udf_inode_cachep = kmem_cache_create("udf_inode_cache",
+ sizeof(struct udf_inode_info),
+ 0, SLAB_HWCACHE_ALIGN,
+ init_once, NULL);
+ if (udf_inode_cachep == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static void destroy_inodecache(void)
+{
+ if (kmem_cache_destroy(udf_inode_cachep))
+ printk(KERN_INFO "udf_inode_cache: not all structures were freed\n");
+}
+
/* Superblock operations */
static struct super_operations udf_sb_ops = {
+ alloc_inode: udf_alloc_inode,
+ destroy_inode: udf_destroy_inode,
read_inode: udf_read_inode,
write_inode: udf_write_inode,
put_inode: udf_put_inode,
@@ -130,14 +174,26 @@ struct udf_options
static int __init init_udf_fs(void)
{
+ int err;
printk(KERN_NOTICE "udf: registering filesystem\n");
- return register_filesystem(&udf_fstype);
+ err = init_inodecache();
+ if (err)
+ goto out1;
+ err = register_filesystem(&udf_fstype);
+ if (err)
+ goto out;
+ return 0;
+out:
+ destroy_inodecache();
+out1:
+ return err;
}
static void __exit exit_udf_fs(void)
{
printk(KERN_NOTICE "udf: unregistering filesystem\n");
unregister_filesystem(&udf_fstype);
+ destroy_inodecache();
}
EXPORT_NO_SYMBOLS;
diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h
index 8ffa2f316..7f6275436 100644
--- a/fs/udf/udf_i.h
+++ b/fs/udf/udf_i.h
@@ -1,7 +1,11 @@
#ifndef __LINUX_UDF_I_H
#define __LINUX_UDF_I_H
-#define UDF_I(X) (&((X)->u.udf_i))
+#include <linux/udf_fs_i.h>
+static inline struct udf_inode_info *UDF_I(struct inode *inode)
+{
+ return list_entry(inode, struct udf_inode_info, vfs_inode);
+}
#define UDF_I_LOCATION(X) ( UDF_I(X)->i_location )
#define UDF_I_LENEATTR(X) ( UDF_I(X)->i_lenEAttr )
diff --git a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h
index 2f7605859..6525a4b66 100644
--- a/include/asm-i386/mmu_context.h
+++ b/include/asm-i386/mmu_context.h
@@ -1,5 +1,5 @@
-#ifndef __I386_MMU_CONTEXT_H
-#define __I386_MMU_CONTEXT_H
+#ifndef __I386_SCHED_H
+#define __I386_SCHED_H
#include <linux/config.h>
#include <asm/desc.h>
@@ -16,14 +16,13 @@
# error update this function.
#endif
-static inline int sched_find_first_zero_bit(char *bitmap)
+static inline int sched_find_first_zero_bit(unsigned long *b)
{
- unsigned int *b = (unsigned int *)bitmap;
unsigned int rt;
rt = b[0] & b[1] & b[2] & b[3];
if (unlikely(rt != 0xffffffff))
- return find_first_zero_bit(bitmap, MAX_RT_PRIO);
+ return find_first_zero_bit(b, MAX_RT_PRIO);
if (b[4] != ~0)
return ffz(b[4]) + MAX_RT_PRIO;
diff --git a/include/linux/device.h b/include/linux/device.h
index 32a2fed4d..e0c55821f 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -80,7 +80,7 @@ struct device {
atomic_t refcount; /* refcount to make sure the device
* persists for the right amount of time */
- struct driver_dir_entry * dir;
+ struct driver_dir_entry dir;
struct device_driver *driver; /* which driver has allocated this
device */
@@ -123,7 +123,7 @@ struct iobus {
struct list_head devices; /* children devices */
struct device *self; /* pointer to controlling device */
- struct driver_dir_entry * dir; /* driverfs directory */
+ struct driver_dir_entry dir; /* driverfs directory */
char name[DEVICE_NAME_SIZE];
char bus_id[BUS_ID_SIZE];
@@ -154,15 +154,9 @@ extern int iobus_register(struct iobus * iobus);
extern struct iobus * iobus_alloc(void);
extern void iobus_init(struct iobus * iobus);
-extern int device_create_file(struct device *device, const char * name, mode_t mode,
- struct driverfs_operations * ops, void * data);
+extern int device_create_file(struct device *device, struct driver_file_entry * entry);
extern void device_remove_file(struct device * dev, const char * name);
-extern int iobus_create_file(struct iobus *bus, const char * name, mode_t mode,
- struct driverfs_operations * ops, void * data);
-extern void iobus_remove_file(struct iobus * iobus, const char * name);
-
-
/*
* Platform "fixup" functions - allow the platform to have their say
* about devices and actions that the general device layer doesn't
diff --git a/include/linux/driverfs_fs.h b/include/linux/driverfs_fs.h
index 90a603430..8141302ef 100644
--- a/include/linux/driverfs_fs.h
+++ b/include/linux/driverfs_fs.h
@@ -26,11 +26,6 @@
#ifndef _DRIVER_FS_H_
#define _DRIVER_FS_H_
-struct driverfs_operations {
- ssize_t (*read) (char *, size_t, loff_t, void *);
- ssize_t (*write)(const char *, size_t, loff_t, void*);
-};
-
struct driver_dir_entry {
char * name;
struct dentry * dentry;
@@ -38,6 +33,8 @@ struct driver_dir_entry {
struct list_head files;
};
+struct device;
+
struct driver_file_entry {
struct driver_dir_entry * parent;
struct list_head node;
@@ -45,11 +42,10 @@ struct driver_file_entry {
mode_t mode;
struct dentry * dentry;
void * data;
- struct driverfs_operations * ops;
-};
-extern struct driver_dir_entry *
-driverfs_create_dir_entry(const char * name, mode_t mode);
+ ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
+ ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
+};
extern int
driverfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);
@@ -57,10 +53,6 @@ driverfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);
extern void
driverfs_remove_dir(struct driver_dir_entry * entry);
-extern struct driver_file_entry *
-driverfs_create_entry (const char * name, mode_t mode,
- struct driverfs_operations * ops, void * data);
-
extern int
driverfs_create_file(struct driver_file_entry * entry,
struct driver_dir_entry * parent);
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 357878b65..2fffbbfae 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -94,6 +94,18 @@
#define FB_ACCEL_IGS_CYBER5000 35 /* CyberPro 5000 */
#define FB_ACCEL_SIS_GLAMOUR 36 /* SiS 300/630/540 */
+
+#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */
+#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */
+#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */
+#define FB_ACCEL_NEOMAGIC_NM2097 93 /* NeoMagic NM2097 */
+#define FB_ACCEL_NEOMAGIC_NM2160 94 /* NeoMagic NM2160 */
+#define FB_ACCEL_NEOMAGIC_NM2200 95 /* NeoMagic NM2200 */
+#define FB_ACCEL_NEOMAGIC_NM2230 96 /* NeoMagic NM2230 */
+#define FB_ACCEL_NEOMAGIC_NM2360 97 /* NeoMagic NM2360 */
+#define FB_ACCEL_NEOMAGIC_NM2380 98 /* NeoMagic NM2380 */
+
+
struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6bda17aed..c4d612367 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -287,20 +287,15 @@ extern void set_bh_page(struct buffer_head *bh, struct page *page, unsigned long
#include <linux/pipe_fs_i.h>
-#include <linux/minix_fs_i.h>
#include <linux/ntfs_fs_i.h>
#include <linux/msdos_fs_i.h>
-#include <linux/umsdos_fs_i.h>
+/* #include <linux/umsdos_fs_i.h> */
#include <linux/iso_fs_i.h>
-#include <linux/sysv_fs_i.h>
#include <linux/romfs_fs_i.h>
#include <linux/smb_fs_i.h>
#include <linux/hfs_fs_i.h>
#include <linux/adfs_fs_i.h>
-#include <linux/reiserfs_fs_i.h>
#include <linux/bfs_fs_i.h>
-#include <linux/udf_fs_i.h>
-#include <linux/ncp_fs_i.h>
#include <linux/proc_fs_i.h>
#include <linux/jffs2_fs_i.h>
#include <linux/cramfs_fs_sb.h>
@@ -466,20 +461,15 @@ struct inode {
unsigned int i_attr_flags;
__u32 i_generation;
union {
- struct minix_inode_info minix_i;
struct ntfs_inode_info ntfs_i;
struct msdos_inode_info msdos_i;
- struct umsdos_inode_info umsdos_i;
+ /* struct umsdos_inode_info umsdos_i; */
struct iso_inode_info isofs_i;
- struct sysv_inode_info sysv_i;
struct romfs_inode_info romfs_i;
struct smb_inode_info smbfs_i;
struct hfs_inode_info hfs_i;
struct adfs_inode_info adfs_i;
- struct reiserfs_inode_info reiserfs_i;
struct bfs_inode_info bfs_i;
- struct udf_inode_info udf_i;
- struct ncp_inode_info ncpfs_i;
struct proc_inode_info proc_i;
struct socket socket_i;
struct jffs2_inode_info jffs2_i;
diff --git a/include/linux/init.h b/include/linux/init.h
index f0644ca30..0a9c2eba8 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -50,8 +50,26 @@ typedef void (*exitcall_t)(void);
extern initcall_t __initcall_start, __initcall_end;
-#define __initcall(fn) \
- static initcall_t __initcall_##fn __init_call = fn
+/* initcalls are now grouped by functionality into separate
+ * subsections. Ordering inside the subsections is determined
+ * by link order.
+ * For backwards compatability, initcall() puts the call in
+ * the device init subsection.
+ */
+
+#define __define_initcall(level,fn) \
+ static initcall_t __initcall_##fn __attribute__ ((unused,__section__ (".initcall" level ".init"))) = fn
+
+#define early_arch_initcall(fn) __define_initcall("1",fn)
+#define mem_initcall(fn) __define_initcall("2",fn)
+#define subsys_initcall(fn) __define_initcall("3",fn)
+#define arch_initcall(fn) __define_initcall("4",fn)
+#define fs_initcall(fn) __define_initcall("5",fn)
+#define device_initcall(fn) __define_initcall("6",fn)
+#define late_initcall(fn) __define_initcall("7",fn)
+
+#define __initcall(fn) device_initcall(fn)
+
#define __exitcall(fn) \
static exitcall_t __exitcall_##fn __exit_call = fn
@@ -80,7 +98,7 @@ extern struct kernel_param __setup_start, __setup_end;
#define __initdata __attribute__ ((__section__ (".data.init")))
#define __exitdata __attribute__ ((unused, __section__ (".data.exit")))
#define __initsetup __attribute__ ((unused,__section__ (".setup.init")))
-#define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
+#define __init_call(level) __attribute__ ((unused,__section__ (".initcall" level ".init")))
#define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit")))
/* For assembly routines */
@@ -141,6 +159,14 @@ typedef void (*__cleanup_module_func_t)(void);
#define __setup(str,func) /* nothing */
+#define early_arch_initcall(fn) module_init(fn)
+#define mem_initcall(fn) module_init(fn)
+#define subsys_initcall(fn) module_init(fn)
+#define arch_initcall(fn) module_init(fn)
+#define fs_initcall(fn) module_init(fn)
+#define device_initcall(fn) module_init(fn)
+#define late_initcall(fn) module_init(fn)
+
#endif
#ifdef CONFIG_HOTPLUG
diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h
index cfa7eab9c..c767d1ff8 100644
--- a/include/linux/minix_fs.h
+++ b/include/linux/minix_fs.h
@@ -89,6 +89,8 @@ struct minix_dir_entry {
#ifdef __KERNEL__
+#include <linux/minix_fs_i.h>
+
/*
* change the define below to 0 if you want names > info->s_namelen chars to be
* truncated. Else they will be disallowed (ENAMETOOLONG).
@@ -129,6 +131,11 @@ extern struct file_operations minix_file_operations;
extern struct file_operations minix_dir_operations;
extern struct dentry_operations minix_dentry_operations;
+static inline struct minix_inode_info *minix_i(struct inode *inode)
+{
+ return list_entry(inode, struct minix_inode_info, vfs_inode);
+}
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/minix_fs_i.h b/include/linux/minix_fs_i.h
index c3711e522..1ffd85ed4 100644
--- a/include/linux/minix_fs_i.h
+++ b/include/linux/minix_fs_i.h
@@ -9,6 +9,7 @@ struct minix_inode_info {
__u16 i1_data[16];
__u32 i2_data[16];
} u;
+ struct inode vfs_inode;
};
#endif
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 919fc654a..0f285d517 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -12,6 +12,7 @@
#include <linux/in.h>
#include <linux/types.h>
+#include <linux/ncp_fs_i.h>
#include <linux/ipx.h>
#include <linux/ncp_no.h>
@@ -192,7 +193,10 @@ struct ncp_entry_info {
#define NCP_SBP(sb) (&((sb)->u.ncpfs_sb))
#define NCP_SERVER(inode) NCP_SBP((inode)->i_sb)
-#define NCP_FINFO(inode) (&((inode)->u.ncpfs_i))
+static inline struct ncp_inode_info *NCP_FINFO(struct inode *inode)
+{
+ return list_entry(inode, struct ncp_inode_info, vfs_inode);
+}
#ifdef DEBUG_NCP_MALLOC
diff --git a/include/linux/ncp_fs_i.h b/include/linux/ncp_fs_i.h
index ffdf49f4c..528fc633a 100644
--- a/include/linux/ncp_fs_i.h
+++ b/include/linux/ncp_fs_i.h
@@ -15,16 +15,16 @@
* all the information we need to work with an inode after creation.
*/
struct ncp_inode_info {
- __u32 dirEntNum __attribute__((packed));
- __u32 DosDirNum __attribute__((packed));
- __u32 volNumber __attribute__((packed));
+ __u32 dirEntNum;
+ __u32 DosDirNum;
+ __u32 volNumber;
__u32 nwattr;
struct semaphore open_sem;
atomic_t opened;
int access;
- __u32 server_file_handle __attribute__((packed));
- __u8 open_create_action __attribute__((packed));
- __u8 file_handle[6] __attribute__((packed));
+ __u32 server_file_handle;
+ __u8 file_handle[6];
+ struct inode vfs_inode;
};
#endif /* __KERNEL__ */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 4971fa3c3..6c9bd9e3f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -301,6 +301,7 @@
#include <linux/ioport.h>
#include <linux/list.h>
#include <linux/errno.h>
+#include <linux/device.h>
/* File state for mmap()s on /proc/bus/pci/X/Y */
enum pci_mmap_state {
@@ -363,6 +364,8 @@ struct pci_dev {
this is D0-D3, D0 being fully functional,
and D3 being off. */
+ struct device dev; /* Generic device interface */
+
/* device is compatible with these IDs */
unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE];
unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE];
@@ -429,6 +432,8 @@ struct pci_bus {
unsigned char productver; /* product version */
unsigned char checksum; /* if zero - checksum passed */
unsigned char pad1;
+
+ struct iobus iobus; /* Generic device interface */
};
#define pci_bus_b(n) list_entry(n, struct pci_bus, node)
@@ -525,7 +530,6 @@ int pcibios_find_device (unsigned short vendor, unsigned short dev_id,
/* Generic PCI functions used internally */
-void pci_init(void);
int pci_bus_exists(const struct list_head *list, int nr);
struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
struct pci_bus *pci_alloc_primary_bus(int bus);
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 1c4cec479..f9f74b6d7 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -20,6 +20,7 @@
#include <asm/unaligned.h>
#include <linux/bitops.h>
#include <linux/proc_fs.h>
+#include <linux/reiserfs_fs_i.h>
#endif
/*
@@ -204,9 +205,13 @@ struct unfm_nodeinfo {
*/
#define MIN_PACK_ON_CLOSE 512
+static inline struct reiserfs_inode_info *REISERFS_I(struct inode *inode)
+{
+ return list_entry(inode, struct reiserfs_inode_info, vfs_inode);
+}
// this says about version of all items (but stat data) the object
// consists of
-#define inode_items_version(inode) ((inode)->u.reiserfs_i.i_version)
+#define inode_items_version(inode) (REISERFS_I(inode)->i_version)
/* This is an aggressive tail suppression policy, I am hoping it
@@ -1257,10 +1262,10 @@ struct path var = {ILLEGAL_PATH_ELEMENT_OFFSET, }
#define UNFM_P_SIZE (sizeof(unp_t))
// in in-core inode key is stored on le form
-#define INODE_PKEY(inode) ((struct key *)((inode)->u.reiserfs_i.i_key))
-//#define mark_tail_converted(inode) (atomic_set(&((inode)->u.reiserfs_i.i_converted),1))
-//#define unmark_tail_converted(inode) (atomic_set(&((inode)->u.reiserfs_i.i_converted), 0))
-//#define is_tail_converted(inode) (atomic_read(&((inode)->u.reiserfs_i.i_converted)))
+#define INODE_PKEY(inode) ((struct key *)(REISERFS_I(inode)->i_key))
+//#define mark_tail_converted(inode) (atomic_set(&(REISERFS_I(inode)->i_converted),1))
+//#define unmark_tail_converted(inode) (REISERFS_I(inode)->i_converted), 0))
+//#define is_tail_converted(inode) (REISERFS_I(inode)->i_converted)))
@@ -1272,7 +1277,7 @@ struct path var = {ILLEGAL_PATH_ELEMENT_OFFSET, }
// reiserfs version 2 has max offset 60 bits. Version 1 - 32 bit offset
#define U32_MAX (~(__u32)0)
-static inline loff_t max_reiserfs_offset (const struct inode * inode)
+static inline loff_t max_reiserfs_offset (struct inode * inode)
{
if (inode_items_version (inode) == ITEM_VERSION_1)
return (loff_t)U32_MAX;
@@ -1848,7 +1853,7 @@ void padd_item (char * item, int total_length, int length);
int reiserfs_prepare_write(struct file *, struct page *, unsigned, unsigned) ;
void reiserfs_truncate_file(struct inode *, int update_timestamps) ;
-void make_cpu_key (struct cpu_key * cpu_key, const struct inode * inode, loff_t offset,
+void make_cpu_key (struct cpu_key * cpu_key, struct inode * inode, loff_t offset,
int type, int key_length);
void make_le_item_head (struct item_head * ih, const struct cpu_key * key,
int version,
@@ -1873,7 +1878,7 @@ int reiserfs_dentry_to_fh(struct dentry *, __u32 *fh, int *lenp, int need_parent
void reiserfs_dirty_inode (struct inode * inode) ;
struct inode * reiserfs_new_inode (struct reiserfs_transaction_handle *th,
- const struct inode * dir, int mode,
+ struct inode * dir, int mode,
const char * symname, int item_len,
struct dentry *dentry, struct inode *inode, int * err);
int reiserfs_sync_inode (struct reiserfs_transaction_handle *th, struct inode * inode);
diff --git a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
index 08445c120..6b7a94ece 100644
--- a/include/linux/reiserfs_fs_i.h
+++ b/include/linux/reiserfs_fs_i.h
@@ -46,6 +46,7 @@ struct reiserfs_inode_info {
*/
unsigned long i_trans_id ;
unsigned long i_trans_index ;
+ struct inode vfs_inode;
};
diff --git a/include/linux/sysv_fs.h b/include/linux/sysv_fs.h
index 104de0a08..91e1e1e86 100644
--- a/include/linux/sysv_fs.h
+++ b/include/linux/sysv_fs.h
@@ -21,6 +21,15 @@
#include <linux/sched.h> /* declares wake_up() */
#include <linux/sysv_fs_sb.h> /* defines the sv_... shortcuts */
+/* temporary hack. */
+#include <linux/sysv_fs_i.h>
+static inline struct sysv_inode_info *SYSV_I(struct inode *inode)
+{
+ /* I think list_entry should have a more descriptive name.. --hch */
+ return list_entry(inode, struct sysv_inode_info, vfs_inode);
+}
+/* end temporary hack. */
+
/* Layout on disk */
/* ============== */
diff --git a/include/linux/sysv_fs_i.h b/include/linux/sysv_fs_i.h
index 084173ad8..77679676a 100644
--- a/include/linux/sysv_fs_i.h
+++ b/include/linux/sysv_fs_i.h
@@ -11,6 +11,7 @@ struct sysv_inode_info {
* then 1 triple indirection block.
*/
u32 i_dir_start_lookup;
+ struct inode vfs_inode;
};
#endif
diff --git a/include/linux/udf_fs_i.h b/include/linux/udf_fs_i.h
index 3d48fced7..8e26831b6 100644
--- a/include/linux/udf_fs_i.h
+++ b/include/linux/udf_fs_i.h
@@ -47,6 +47,7 @@ struct udf_inode_info
unsigned i_strat_4096 : 1;
unsigned i_new_inode : 1;
unsigned reserved : 26;
+ struct inode vfs_inode;
};
#endif
diff --git a/init/main.c b/init/main.c
index 0f5ea3ee4..0a71a18bc 100644
--- a/init/main.c
+++ b/init/main.c
@@ -38,35 +38,10 @@
#include <asm/ccwcache.h>
#endif
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-#endif
-
-#ifdef CONFIG_DIO
-#include <linux/dio.h>
-#endif
-
-#ifdef CONFIG_ZORRO
-#include <linux/zorro.h>
-#endif
-
#ifdef CONFIG_MTRR
# include <asm/mtrr.h>
#endif
-#ifdef CONFIG_NUBUS
-#include <linux/nubus.h>
-#endif
-
-#ifdef CONFIG_ISAPNP
-#include <linux/isapnp.h>
-#endif
-
-#ifdef CONFIG_IRDA
-extern int irda_proto_init(void);
-extern int irda_device_init(void);
-#endif
-
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/smp.h>
#endif
@@ -92,10 +67,8 @@ extern void sock_init(void);
extern void fork_init(unsigned long);
extern void mca_init(void);
extern void sbus_init(void);
-extern void ppc_init(void);
extern void sysctl_init(void);
extern void signals_init(void);
-extern int init_pcmcia_ds(void);
extern void free_initmem(void);
@@ -103,8 +76,6 @@ extern void free_initmem(void);
extern void tc_init(void);
#endif
-extern void ecard_init(void);
-
#if defined(CONFIG_SYSVIPC)
extern void ipc_init(void);
#endif
@@ -492,50 +463,11 @@ static void __init do_basic_setup(void)
/* bring up the device tree */
device_driver_init();
-#ifdef CONFIG_PCI
- pci_init();
-#endif
-#ifdef CONFIG_SBUS
- sbus_init();
-#endif
-#if defined(CONFIG_PPC)
- ppc_init();
-#endif
-#ifdef CONFIG_MCA
- mca_init();
-#endif
-#ifdef CONFIG_ARCH_ACORN
- ecard_init();
-#endif
-#ifdef CONFIG_ZORRO
- zorro_init();
-#endif
-#ifdef CONFIG_DIO
- dio_init();
-#endif
-#ifdef CONFIG_NUBUS
- nubus_init();
-#endif
-#ifdef CONFIG_ISAPNP
- isapnp_init();
-#endif
-#ifdef CONFIG_TC
- tc_init();
-#endif
-
/* Networking initialization needs a process context */
sock_init();
start_context_thread();
do_initcalls();
-
-#ifdef CONFIG_IRDA
- irda_proto_init();
- irda_device_init(); /* Must be done after protocol initialization */
-#endif
-#ifdef CONFIG_PCMCIA
- init_pcmcia_ds(); /* Do this last */
-#endif
}
extern void prepare_namespace(void);
diff --git a/kernel/device.c b/kernel/device.c
index 8b7c9e47e..aac19836f 100644
--- a/kernel/device.c
+++ b/kernel/device.c
@@ -51,46 +51,37 @@ int (*platform_notify_remove)(struct device * dev) = NULL;
static spinlock_t device_lock;
-static ssize_t device_read_status(char *, size_t, loff_t, void *);
-static ssize_t device_write_status(const char *, size_t, loff_t, void *);
-
-static struct driverfs_operations device_status_ops = {
- read: device_read_status,
- write: device_write_status,
-};
-
-static ssize_t device_read_power(char *, size_t, loff_t, void *);
-static ssize_t device_write_power(const char *, size_t, loff_t, void *);
-
-static struct driverfs_operations device_power_ops = {
- read: device_read_power,
- write: device_write_power,
+static ssize_t device_read_status(struct device *, char *, size_t, loff_t);
+static ssize_t device_write_status(struct device *,const char *, size_t, loff_t);
+
+static struct driver_file_entry device_status_entry = {
+ name: "status",
+ mode: S_IWUSR | S_IRUGO,
+ show: device_read_status,
+ store: device_write_status,
};
-static ssize_t iobus_read_status(char *, size_t, loff_t, void *);
-static ssize_t iobus_write_status(const char *, size_t, loff_t, void *);
+static ssize_t device_read_power(struct device *, char *, size_t, loff_t);
+static ssize_t device_write_power(struct device *, const char *, size_t, loff_t);
-static struct driverfs_operations iobus_status_ops = {
- read: iobus_read_status,
- write: iobus_write_status,
+static struct driver_file_entry device_power_entry = {
+ name: "power",
+ mode: S_IWUSR | S_IRUGO,
+ show: device_read_power,
+ store: device_write_power,
};
-
/**
* device_create_file - create a driverfs file for a device
* @dev: device requesting file
- * @name: name of file
- * @mode: permissions of file
- * @ops: operations for the file
- * @data: private data for the file
+ * @entry: entry describing file
*
- * Create a driverfs entry, then create the actual file the entry describes.
+ * Allocate space for file entry, copy descriptor, and create.
*/
-int device_create_file(struct device * dev, const char * name, mode_t mode,
- struct driverfs_operations * ops, void * data)
+int device_create_file(struct device * dev, struct driver_file_entry * entry)
{
- int error = -EFAULT;
- struct driver_file_entry * entry;
+ struct driver_file_entry * new_entry;
+ int error = -ENOMEM;
if (!dev)
return -EINVAL;
@@ -98,10 +89,15 @@ int device_create_file(struct device * dev, const char * name, mode_t mode,
if (!valid_device(dev))
return -EFAULT;
- entry = driverfs_create_entry(name,mode,ops,data);
- if (entry)
- error = driverfs_create_file(entry,dev->dir);
+ new_entry = kmalloc(sizeof(*new_entry),GFP_KERNEL);
+ if (!new_entry)
+ goto done;
+ memcpy(new_entry,entry,sizeof(*entry));
+ error = driverfs_create_file(new_entry,&dev->dir);
+ if (error)
+ kfree(new_entry);
+ done:
put_device(dev);
return error;
}
@@ -120,7 +116,7 @@ void device_remove_file(struct device * dev, const char * name)
if (!valid_device(dev))
return;
- driverfs_remove_file(dev->dir,name);
+ driverfs_remove_file(&dev->dir,name);
put_device(dev);
}
@@ -131,18 +127,8 @@ void device_remove_file(struct device * dev, const char * name)
*/
void device_remove_dir(struct device * dev)
{
- struct driver_dir_entry * dir;
-
- if (!dev)
- return;
-
- lock_device(dev);
- dir = dev->dir;
- dev->dir = NULL;
- unlock_device(dev);
-
- if (dir)
- driverfs_remove_dir(dir);
+ if (dev)
+ driverfs_remove_dir(&dev->dir);
}
/**
@@ -159,128 +145,52 @@ void device_remove_dir(struct device * dev)
*/
static int device_make_dir(struct device * dev)
{
- struct driver_dir_entry * entry;
+ struct driver_dir_entry * parent = NULL;
int error;
- entry = driverfs_create_dir_entry(dev->bus_id,(S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO));
- if (!entry)
- return -EFAULT;
+ INIT_LIST_HEAD(&dev->dir.files);
+ dev->dir.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
+ dev->dir.name = dev->bus_id;
- error = driverfs_create_dir(entry,dev->parent->dir);
+ if (dev->parent)
+ parent = &dev->parent->dir;
- if (error) {
- kfree(entry);
- return error;
- }
+ error = driverfs_create_dir(&dev->dir,parent);
- lock_device(dev);
- dev->dir = entry;
- unlock_device(dev);
+ if (error)
+ return error;
- /* first the status file */
- error = device_create_file(dev, "status", S_IRUGO | S_IWUSR,
- &device_status_ops, (void *) dev);
+ error = device_create_file(dev,&device_status_entry);
if (error) {
device_remove_dir(dev);
goto done;
}
-
- /* now the power file */
- error = device_create_file(dev,"power",S_IRUGO | S_IWUSR,
- &device_power_ops, (void *) dev);
- if (error)
+ error = device_create_file(dev,&device_power_entry);
+ if (error)
device_remove_dir(dev);
-
done:
return error;
}
-/* iobus interface.
- * For practical purposes, it's exactly the same as the device interface above.
- * Even below, the two are almost identical, only taking different pointer
- * types.
- * I have fantasized about removing struct iobus completely. It would reduce
- * this file by about 30%, and make life much easier. However, it will take some
- * time to really work everything out..
- */
-
-int iobus_create_file(struct iobus * iobus, const char * name, mode_t mode,
- struct driverfs_operations * ops, void * data)
-{
- int error = -EFAULT;
- struct driver_file_entry * entry;
-
- if (!iobus)
- return -EINVAL;
-
- if (!valid_iobus(iobus))
- return -EFAULT;
-
- entry = driverfs_create_entry(name,mode,ops,data);
- if (entry)
- error = driverfs_create_file(entry,iobus->dir);
-
- put_iobus(iobus);
- return error;
-}
-
-void iobus_remove_file(struct iobus * iobus, const char * name)
-{
- if (!iobus)
- return;
-
- if (!valid_iobus(iobus))
- return;
-
- driverfs_remove_file(iobus->dir,name);
-
- put_iobus(iobus);
-}
-
void iobus_remove_dir(struct iobus * iobus)
{
- struct driver_dir_entry * dir;
-
- if (!iobus)
- return;
-
- lock_iobus(iobus);
- dir = iobus->dir;
- iobus->dir = NULL;
- unlock_iobus(iobus);
-
- if (dir)
- driverfs_remove_dir(dir);
+ if (iobus)
+ driverfs_remove_dir(&iobus->dir);
}
static int iobus_make_dir(struct iobus * iobus)
{
- struct driver_dir_entry * entry;
struct driver_dir_entry * parent = NULL;
int error;
- entry = driverfs_create_dir_entry(iobus->bus_id,(S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO));
- if (!entry)
- return -EFAULT;
+ INIT_LIST_HEAD(&iobus->dir.files);
+ iobus->dir.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
+ iobus->dir.name = iobus->bus_id;
if (iobus->parent)
- parent = iobus->parent->dir;
-
- error = driverfs_create_dir(entry,parent);
- if (error) {
- kfree(entry);
- return error;
- }
-
- lock_iobus(iobus);
- iobus->dir = entry;
- unlock_iobus(iobus);
-
- error = iobus_create_file(iobus, "status", S_IRUGO | S_IWUSR,
- &iobus_status_ops, (void *)iobus);
- if (error)
- iobus_remove_dir(iobus);
+ parent = &iobus->parent->dir;
+ error = driverfs_create_dir(&iobus->dir,parent);
return error;
}
@@ -304,6 +214,9 @@ int device_register(struct device *dev)
dev->parent = &device_root;
parent = dev->parent;
+ DBG("DEV: registering device: ID = '%s', name = %s, parent = %s\n",
+ dev->bus_id, dev->name, parent->bus_id);
+
if (valid_iobus(parent)) {
if (!valid_device(dev)) {
put_iobus(parent);
@@ -327,15 +240,10 @@ int device_register(struct device *dev)
list_add_tail(&dev->node, &parent->devices);
unlock_iobus(parent);
- DBG("DEV: registering device: ID = '%s', name = %s, parent = %s\n",
- dev->bus_id, dev->name, parent->bus_id);
-
/* notify platform of device entry */
if (platform_notify)
platform_notify(dev);
- return 0;
-
register_done:
put_device(dev);
put_iobus(parent);
@@ -430,8 +338,6 @@ int iobus_register(struct iobus *bus)
list_add_tail(&bus->node,&parent->children);
unlock_iobus(parent);
- return 0;
-
register_done_put:
put_iobus(bus);
put_iobus(parent);
@@ -533,45 +439,6 @@ struct iobus *iobus_alloc(void)
return bus;
}
-static int do_device_suspend(struct device * dev, u32 state)
-{
- int error = 0;
-
- if (!dev->driver->suspend)
- return error;
-
- error = dev->driver->suspend(dev,state,SUSPEND_NOTIFY);
-
- if (error)
- return error;
-
- error = dev->driver->suspend(dev,state,SUSPEND_SAVE_STATE);
- if (error) {
- if (dev->driver->resume)
- dev->driver->resume(dev,RESUME_RESTORE_STATE);
- return error;
- }
- error = dev->driver->suspend(dev,state,SUSPEND_POWER_DOWN);
- if (error) {
- if (dev->driver->resume)
- dev->driver->resume(dev,RESUME_RESTORE_STATE);
- }
- return error;
-}
-
-static int do_device_resume(struct device * dev)
-{
- int error = 0;
-
- if (!dev->driver->resume)
- return 0;
- error = dev->driver->resume(dev,RESUME_POWER_ON);
- if (error)
- return error;
- error = dev->driver->resume(dev,RESUME_RESTORE_STATE);
- return error;
-}
-
/**
* device_read_status - report some device information
* @page: page-sized buffer to write into
@@ -582,37 +449,17 @@ static int do_device_resume(struct device * dev)
* Report some human-readable information about the device.
* This includes the name, the bus id, and the current power state.
*/
-static ssize_t device_read_status(char * page, size_t count,
- loff_t off, void * data)
+static ssize_t device_read_status(struct device * dev, char * page, size_t count, loff_t off)
{
char *str = page;
- struct device *dev = (struct device*)data;
- ssize_t len = 0;
-
- if (!dev)
- return -EINVAL;
-
- if (!valid_device(dev))
- return -EFAULT;
if (off)
- goto done;
+ return 0;
str += sprintf(str,"Name: %s\n",dev->name);
str += sprintf(str,"Bus ID: %s\n",dev->bus_id);
- len = str - page;
-
- if (len > count)
- len = count;
-
- if (len < 0)
- len = 0;
-
- done:
- put_device(dev);
-
- return len;
+ return (str - page);
}
/**
@@ -631,31 +478,24 @@ static ssize_t device_read_status(char * page, size_t count,
* (See Documentation/driver-model.txt for the theory of an n-stage
* suspend sequence).
*/
-static ssize_t device_write_status(const char* buf, size_t count, loff_t off, void *data)
+static ssize_t device_write_status(struct device * dev, const char* buf, size_t count, loff_t off)
{
char command[20];
- struct device *dev = (struct device *)data;
int num;
int arg = 0;
int error = 0;
- if (!dev)
- return 0;
-
- if (!valid_device(dev))
- return -EFAULT;
-
if (off)
- goto done_put;
+ return 0;
/* everything involves dealing with the driver. */
if (!dev->driver)
- goto done_put;
+ return 0;
num = sscanf(buf,"%10s %d",command,&arg);
if (!num)
- goto done_put;
+ return 0;
if (!strcmp(command,"probe")) {
if (dev->driver->probe)
@@ -666,50 +506,25 @@ static ssize_t device_write_status(const char* buf, size_t count, loff_t off, vo
error = dev->driver->remove(dev,REMOVE_NOTIFY);
} else
error = -EFAULT;
-
- done_put:
- put_device(dev);
return error < 0 ? error : count;
}
static ssize_t
-device_read_power(char * page, size_t count, loff_t off, void * data)
+device_read_power(struct device * dev, char * page, size_t count, loff_t off)
{
char * str = page;
- struct device * dev = (struct device *)data;
- ssize_t len = 0;
-
- if (!dev)
- return 0;
- if (!valid_device(dev))
+ if (off)
return 0;
str += sprintf(str,"State: %d\n",dev->current_state);
- len = str - page;
-
- if (off) {
- if (len < off) {
- len = 0;
- goto done;
- }
- str += off;
- len -= off;
- }
-
- if (len > count)
- len = count;
-
- done:
- put_device(dev);
- return len;
+ return (str - page);
}
static ssize_t
-device_write_power(const char * buf, size_t count, loff_t off, void * data)
+device_write_power(struct device * dev, const char * buf, size_t count, loff_t off)
{
- struct device * dev = (struct device *)data;
char str_command[20];
char str_stage[20];
int num_args;
@@ -717,14 +532,9 @@ device_write_power(const char * buf, size_t count, loff_t off, void * data)
u32 int_stage;
int error = 0;
- if (!dev)
+ if (off)
return 0;
- if (!valid_device(dev))
- return -EFAULT;
-
- if (off)
- goto done;
if (!dev->driver)
goto done;
@@ -772,107 +582,6 @@ device_write_power(const char * buf, size_t count, loff_t off, void * data)
error = 0;
}
done:
- put_device(dev);
-
- DBG("%s: returning %d\n",__FUNCTION__,error);
-
- return error < 0 ? error : count;
-}
-
-/**
- * bus_read_status - report human readable information
- * @page: page-sized buffer to write into
- * @count: number of bytes requested
- * @off: offset into buffer to start at
- * @data: bus-specific data
- */
-static ssize_t iobus_read_status(char *page, size_t count,
- loff_t off, void *data)
-{
- char *str = page;
- struct iobus *bus = (struct iobus*)data;
- ssize_t len = 0;
-
- if (!bus)
- return -EINVAL;
-
- if (!valid_iobus(bus))
- return -EFAULT;
-
- if (off)
- goto done;
-
- str += sprintf(str,"Name: %s\n",bus->name);
- str += sprintf(str,"Bus ID: %s\n",bus->bus_id);
-
- if (bus->driver)
- str += sprintf(str,"Type: %s\n",bus->driver->name);
-
- len = str - page;
- if (len < off)
- len = 0;
- if (len > count)
- len = count;
- if (len < 0)
- len = 0;
-
- done:
- put_iobus(bus);
- return len;
-}
-
-/**
- * bus_write_status - forward a command to a bus
- * @buf: string encoded command
- * @count: number of bytes requested
- * @off: offset into buffer to start at
- * @data: bus-specific data
- *
- * Like device_write_status, this sends a command to a bus driver.
- * Supported actions are:
- * scan - scan a bus for devices
- * add_device <id> - add a child device
- */
-static ssize_t iobus_write_status(const char *buf, size_t count, loff_t off, void *data)
-{
- char command[10];
- char which[15];
- char id[10];
- struct iobus *bus = (struct iobus*)data;
- int num;
- int error = -EINVAL;
-
- if (!bus)
- return -EINVAL;
-
- if (!valid_iobus(bus))
- return -EFAULT;
-
- if (!bus->driver)
- goto done;
-
- num = sscanf(buf,"%10s %15s %10s",command,which,id);
-
- if (!num)
- goto done;
-
- if (!strnicmp(command,"scan",4)) {
- if (bus->driver->scan)
- error = bus->driver->scan(bus);
- } else if (!strnicmp(command,"add",3) && num == 2) {
- error = bus->driver->add_device(bus,id);
- } else if (!strnicmp(command, "suspend",7)) {
- u32 state = simple_strtoul(which,NULL,0);
- if (state > 0)
- error = do_device_suspend(bus->self,state);
-
- } else if (!strnicmp(command,"resume",6)) {
- error = do_device_resume(bus->self);
-
- }
-
- done:
- put_iobus(bus);
return error < 0 ? error : count;
}
@@ -885,9 +594,7 @@ static int __init device_init_root(void)
* needs to do is create the root directory. Easier
* to just do it here than special case it elsewhere..
*/
- iobus_make_dir(&device_root);
-
- return (device_root.dir ? 0 : -EFAULT);
+ return iobus_make_dir(&device_root);
}
int __init device_driver_init(void)
@@ -938,7 +645,4 @@ EXPORT_SYMBOL(iobus_register);
EXPORT_SYMBOL(iobus_alloc);
EXPORT_SYMBOL(iobus_init);
-EXPORT_SYMBOL(iobus_create_file);
-EXPORT_SYMBOL(iobus_remove_file);
-
EXPORT_SYMBOL(device_driver_init);
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index da456b250..d4b7b21f5 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -2590,14 +2590,11 @@ int __init irda_proto_init(void)
register_netdevice_notifier(&irda_dev_notifier);
irda_init();
-#ifdef MODULE
- irda_device_init(); /* Called by init/main.c when non-modular */
-#endif
+ irda_device_init();
return 0;
}
-#ifdef MODULE
-module_init(irda_proto_init); /* If non-module, called from init/main.c */
-#endif
+
+late_initcall(irda_proto_init);
/*
* Function irda_proto_cleanup (void)