## Automatically generated incremental diff ## From: linux-2.4.19-pre5 ## To: linux-2.4.19-pre6 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.4.19-pre5/CREDITS linux-2.4.19-pre6/CREDITS --- linux-2.4.19-pre5/CREDITS Thu Apr 4 22:04:19 2002 +++ linux-2.4.19-pre6/CREDITS Thu Apr 4 22:04:30 2002 @@ -1910,6 +1910,7 @@ N: Petko Manolov E: petkan@users.sourceforge.net D: USB ethernet pegasus/pegasus-II driver +D: USB ethernet rtl8150 driver D: i[45]86 optimized string routines D: i386 task switching hacks S: 482 Shadowgraph Dr. diff -urN linux-2.4.19-pre5/Documentation/Configure.help linux-2.4.19-pre6/Documentation/Configure.help --- linux-2.4.19-pre5/Documentation/Configure.help Thu Apr 4 22:04:19 2002 +++ linux-2.4.19-pre6/Documentation/Configure.help Thu Apr 4 22:04:30 2002 @@ -12815,18 +12815,6 @@ of debug messages to the system log. Select this if you are having a problem with USB support and want to see more of what is going on. -USB fetch large config -CONFIG_USB_LARGE_CONFIG - This option changes the initial request for a config descriptor so - that some poorly designed devices will still work. Some APC UPSes - need it. Basically, the usb subsystem sends a request for a short - (8 byte) config, just to find out how large the real config is. - Incorrectly implemented devices may choke on this small config - request. This option make the initial request for a quite large - config (1009 bytes), and things just work. - - If you have an APC UPS, say Y; otherwise say N. - USB long timeout for slow-responding devices (some MGE Ellipse UPSes) CONFIG_USB_LONG_TIMEOUT This option makes the standard time out a bit longer. Basically, @@ -12922,9 +12910,13 @@ CONFIG_USB_HID Say Y here if you want full HID support to connect keyboards, mice, joysticks, graphic tablets, or any other HID based devices - to your computer via USB. You can't use this driver and the - HIDBP (Boot Protocol) keyboard and mouse drivers at the same time. - More information is available: . + to your computer via USB. You also need to select HID Input layer + support (below) if you want to use keyboards, mice, joysticks and + the like. + + You can't use this driver and the HIDBP (Boot Protocol) keyboard + and mouse drivers at the same time. More information is available: + . If unsure, say Y. @@ -12933,6 +12925,14 @@ The module will be called hid.o. If you want to compile it as a module, say M here and read . +USB HID Input layer support +CONFIG_USB_HIDINPUT + Say Y here if you want to use a USB keyboard, mouse or joystick, + or any other HID input device. You also need Input layer support, + (CONFIG_INPUT) which you select under "Input core support". + + If unsure, say Y. + /dev/usb/hiddev raw HID device support CONFIG_USB_HIDDEV Say Y here if you want to support HID devices (from the USB @@ -12943,33 +12943,37 @@ event interface on /dev/usb/hiddevX (char 180:96 to 180:111). This driver requires CONFIG_USB_HID. - If unsure, say N. + If unsure, say Y. USB HIDBP Keyboard (basic) support CONFIG_USB_KBD - Say Y here if you don't want to use the generic HID driver for your - USB keyboard and prefer to use the keyboard in its limited Boot - Protocol mode instead. This driver is much smaller than the HID one. + Say Y here only if you are absolutely sure that you don't want + to use the generic HID driver for your USB keyboard and prefer + to use the keyboard in its limited Boot Protocol mode instead. + + This is almost certainly not what you want. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called usbkbd.o. If you want to compile it as a module, say M here and read . - If unsure, say N. + If even remotely unsure, say N. USB HIDBP Mouse (basic) support CONFIG_USB_MOUSE - Say Y here if you don't want to use the generic HID driver for your - USB mouse and prefer to use the mouse in its limited Boot Protocol - mode instead. This driver is much smaller than the HID one. + Say Y here only if you are absolutely sure that you don't want + to use the generic HID driver for your USB keyboard and prefer + to use the keyboard in its limited Boot Protocol mode instead. + + This is almost certainly not what you want. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called usbmouse.o. If you want to compile it as a module, say M here and read . - If unsure, say N. + If even remotely unsure, say N. Wacom Intuos/Graphire tablet support CONFIG_USB_WACOM @@ -13475,6 +13479,7 @@ * Motorola (DM100 and SB4100) * Broadcom Cable Modem (reference design) * Toshiba PCX1100U and possibly other cable modems + * Sharp Zaurus SL-5000D The device creates a network device (ethX, where X depends on what other networking devices you have in use), as for a normal PCI @@ -13574,12 +13579,23 @@ If your particular adapter is not in the list and you are _sure_ it is Pegasus or Pegasus-II based then send me (pmanolov@users.sourceforge.net) vendor and device IDs. - + This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called pegasus.o. If you want to compile it as a module, say M here and read . +Realtek RTL8150 based USB-Ethernet device support +CONFIG_USB_RTL8150 + Say Y here if you have RTL8150 based usb-ethernet adapter. + Send me (petkan@users.sourceforge.net) any comments you may have. + You can also check for updates at http://pegasus2.sourceforge.net/ + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called rtl8150.o. If you want to compile it as a + module, say M here and read . + USB KLSI KL5USB101-based Ethernet device support CONFIG_USB_KAWETH Say Y here if you want to use one of the following 10Mbps only diff -urN linux-2.4.19-pre5/Documentation/DocBook/kernel-hacking.tmpl linux-2.4.19-pre6/Documentation/DocBook/kernel-hacking.tmpl --- linux-2.4.19-pre5/Documentation/DocBook/kernel-hacking.tmpl Mon Feb 25 11:37:51 2002 +++ linux-2.4.19-pre6/Documentation/DocBook/kernel-hacking.tmpl Thu Apr 4 22:04:30 2002 @@ -1026,7 +1026,7 @@ Similar to EXPORT_SYMBOL() except that the symbols exported by EXPORT_SYMBOL_GPL() can only be seen by modules with a - MODULE_LICENCE() that specifies a GPL + MODULE_LICENSE() that specifies a GPL compatible license. diff -urN linux-2.4.19-pre5/Documentation/filesystems/devfs/ChangeLog linux-2.4.19-pre6/Documentation/filesystems/devfs/ChangeLog --- linux-2.4.19-pre5/Documentation/filesystems/devfs/ChangeLog Mon Feb 25 11:37:51 2002 +++ linux-2.4.19-pre6/Documentation/filesystems/devfs/ChangeLog Thu Apr 4 22:04:30 2002 @@ -1880,3 +1880,33 @@ - Updated README from master HTML file - Fixed kdev_none macro in include/linux/kdev_t.h +=============================================================================== +Changes for patch v199.9 + +- Added KERN_* to remaining messages + +- Cleaned up declaration of + +- Updated README from master HTML file +=============================================================================== +Changes for patch v199.10 + +- Changed to allow later additions if not yet empty + +- Added calls to in drivers/block/blkpc.c + and + +- Updated README from master HTML file + +- Fixed bug in : was clearing beyond + bitfield + +- Fixed bitfield data type for + +- Made major bitfield type and initialiser 64 bit safe +=============================================================================== +Changes for patch v199.11 + +- Ported to kernel 2.4.19-pre5 + +- Updated README from master HTML file diff -urN linux-2.4.19-pre5/Documentation/filesystems/devfs/README linux-2.4.19-pre6/Documentation/filesystems/devfs/README --- linux-2.4.19-pre5/Documentation/filesystems/devfs/README Mon Feb 25 11:37:51 2002 +++ linux-2.4.19-pre6/Documentation/filesystems/devfs/README Thu Apr 4 22:04:30 2002 @@ -3,7 +3,7 @@ Linux Devfs (Device File System) FAQ Richard Gooch -20-JAN-2002 +29-MAR-2002 Document languages: @@ -803,12 +803,19 @@ add the following lines to your /etc/devfsd.conf file: -REGISTER ^pt[sy]/.* IGNORE -CHANGE ^pt[sy]/.* IGNORE +REGISTER ^pt[sy] IGNORE +CREATE ^pt[sy] IGNORE +CHANGE ^pt[sy] IGNORE +DELETE ^pt[sy] IGNORE REGISTER .* COPY /dev-state/$devname $devpath -CHANGE .* COPY $devpath /dev-state/$devname CREATE .* COPY $devpath /dev-state/$devname +CHANGE .* COPY $devpath /dev-state/$devname +DELETE .* CFUNCTION GLOBAL unlink /dev-state/$devname +RESTORE /dev-state +Note that the sample devfsd.conf file contains these lines, +as well as other sample configurations you may find useful. See the +devfsd distribution reboot. @@ -872,7 +879,8 @@ (for example, by starting with /etc/fstab), and then limiting the compatibility entries that devfsd creates. -MAKE SURE YOU INSTALL DEVFSD BEFORE YOU BOOT A DEVFS-ENABLED KERNEL! +IF YOU CONFIGURE TO MOUNT DEVFS AT BOOT, MAKE SURE YOU INSTALL DEVFSD +BEFORE YOU BOOT A DEVFS-ENABLED KERNEL! Now that devfs has gone into the 2.3.46 kernel, I'm getting a lot of reports back. Many of these are because people are trying to run @@ -1565,6 +1573,24 @@ the existence of the entry should be relied upon. +When I start devfsd, I see the error: +Error opening file: ".devfsd" No such file or directory? + +This means that devfs is not mounted. Make sure you have devfs mounted. + + +How do I mount devfs? + +First make sure you have devfs compiled into your kernel (see +above). Then you will either need to: + +set CONFIG_DEVFS_MOUNT=y in your kernel config +pass devfs=mount to your boot loader +mount devfs manually in your boot scripts with: +mount -t none devfs /dev + + + @@ -1925,11 +1951,7 @@ A Korean translation by viatoris@nownuri.net is available at -http://home.nownuri.net/~viatoris/devfs/devfs.html - -A newer version is under construcation at - -http://viatoris.new21.org/devfs/devfs.html +http://your.destiny.pe.kr/devfs/devfs.html diff -urN linux-2.4.19-pre5/Documentation/sonypi.txt linux-2.4.19-pre6/Documentation/sonypi.txt --- linux-2.4.19-pre5/Documentation/sonypi.txt Mon Feb 25 11:37:51 2002 +++ linux-2.4.19-pre6/Documentation/sonypi.txt Thu Apr 4 22:04:30 2002 @@ -43,7 +43,7 @@ to /etc/modules.conf file, when the driver is compiled as a module or by adding the following to the kernel command line (in your bootloader): - sonypi=minor[[[[,camera],fnkeyinit],verbose],compat] + sonypi=minor[[[[[,camera],fnkeyinit],verbose],compat],nojogdial] where: @@ -71,6 +71,9 @@ (prior to version 1.5) and does not work anymore, add this option and report to the author. + nojogdial: gives more accurate PKEY events on those Vaio models + which don't have a jogdial (like the FX series). + Module use: ----------- diff -urN linux-2.4.19-pre5/MAINTAINERS linux-2.4.19-pre6/MAINTAINERS --- linux-2.4.19-pre5/MAINTAINERS Thu Apr 4 22:04:19 2002 +++ linux-2.4.19-pre6/MAINTAINERS Thu Apr 4 22:04:30 2002 @@ -1395,6 +1395,13 @@ M: mingo@redhat.com S: Maintained +SIS 5513 IDE CONTROLLER DRIVER +P: Lionel Bouton +M: Lionel.Bouton@inet6.fr +W: http://inet6.dyn.dhs.org/sponsoring/sis5513/index.html +W: http://gyver.homeip.net/sis5513/index.html +S: Maintained + SIS 900/7016 FAST ETHERNET DRIVER P: Ollie Lho M: ollie@sis.com.tw @@ -1509,12 +1516,10 @@ S: Maintained TLAN NETWORK DRIVER -P: Torben Mathiasen -M: torben.mathiasen@compaq.com -M: torben@kernel.dk -L: tlan@vuser.vu.union.edu -L: linux-net@vger.kernel.org -W: http://tlan.kernel.dk +P: Samuel Chessman +M: chessman@tux.org +L: tlan-devel@lists.sourceforge.net +W: http://sourceforge.net/projects/tlan/ S: Maintained TOKEN-RING NETWORK DRIVER diff -urN linux-2.4.19-pre5/Makefile linux-2.4.19-pre6/Makefile --- linux-2.4.19-pre5/Makefile Thu Apr 4 22:04:19 2002 +++ linux-2.4.19-pre6/Makefile Thu Apr 4 22:04:30 2002 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 19 -EXTRAVERSION = -pre5 +EXTRAVERSION = -pre6 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -89,7 +89,10 @@ CPPFLAGS := -D__KERNEL__ -I$(HPATH) CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ - -fomit-frame-pointer -fno-strict-aliasing -fno-common + -fno-strict-aliasing -fno-common +ifndef CONFIG_FRAME_POINTER +CFLAGS += -fomit-frame-pointer +endif AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) # @@ -243,6 +246,16 @@ include arch/$(ARCH)/Makefile +# Extra cflags for kbuild 2.4. The default is to forbid includes by kernel code +# from user space headers. Some UML code requires user space headers, in the +# UML Makefiles add 'kbuild_2_4_nostdinc :=' before include Rules.make. No +# other kernel code should include user space headers, if you need +# 'kbuild_2_4_nostdinc :=' or -I/usr/include for kernel code and you are not UML +# then your code is broken! KAO. + +kbuild_2_4_nostdinc := -nostdinc $(shell $(CC) -print-search-dirs | sed -ne 's/install: \(.*\)/-I \1include/gp') +export kbuild_2_4_nostdinc + export CPPFLAGS CFLAGS CFLAGS_KERNEL AFLAGS AFLAGS_KERNEL export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS diff -urN linux-2.4.19-pre5/Rules.make linux-2.4.19-pre6/Rules.make --- linux-2.4.19-pre5/Rules.make Thu Apr 4 22:04:19 2002 +++ linux-2.4.19-pre6/Rules.make Thu Apr 4 22:04:30 2002 @@ -32,6 +32,7 @@ unexport subdir- comma := , +EXTRA_CFLAGS_nostdinc := $(EXTRA_CFLAGS) $(kbuild_2_4_nostdinc) # # Get things started. @@ -50,15 +51,15 @@ # %.s: %.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@ + $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@ %.i: %.c - $(CPP) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $< > $@ + $(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $< > $@ %.o: %.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $< + $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $< @ ( \ - echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@))))' ; \ + echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@))))' ; \ echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \ echo 'endif' \ ) > $(dir $@)/.$(notdir $@).flags @@ -81,7 +82,7 @@ endif %.lst: %.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -g -c -o $*.o $< + $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@) -g -c -o $*.o $< $(TOPDIR)/scripts/makelst $* $(TOPDIR) $(OBJDUMP) # # @@ -125,7 +126,7 @@ # This make dependencies quickly # fastdep: dummy - $(TOPDIR)/scripts/mkdep $(CFLAGS) $(EXTRA_CFLAGS) -- $(wildcard *.[chS]) > .depend + $(TOPDIR)/scripts/mkdep $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -- $(wildcard *.[chS]) > .depend ifdef ALL_SUB_DIRS $(MAKE) $(patsubst %,_sfdep_%,$(ALL_SUB_DIRS)) _FASTDEP_ALL_SUB_DIRS="$(ALL_SUB_DIRS)" endif @@ -224,9 +225,9 @@ $(MODINCL)/%.ver: %.c @if [ ! -r $(MODINCL)/$*.stamp -o $(MODINCL)/$*.stamp -ot $< ]; then \ - echo '$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $<'; \ + echo '$(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -E -D__GENKSYMS__ $<'; \ echo '| $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp'; \ - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $< \ + $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -E -D__GENKSYMS__ $< \ | $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp; \ if [ -r $@ ] && cmp -s $@ $@.tmp; then echo $@ is unchanged; rm -f $@.tmp; \ else echo mv $@.tmp $@; mv -f $@.tmp $@; fi; \ @@ -272,9 +273,9 @@ ifneq "$(strip $(export-objs))" "" $(export-objs): $(export-objs:.o=.c) $(TOPDIR)/include/linux/modversions.h - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c) + $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c) @ ( \ - echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -DEXPORT_SYMTAB)),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@) -DEXPORT_SYMTAB)))' ; \ + echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@) -DEXPORT_SYMTAB)),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@) -DEXPORT_SYMTAB)))' ; \ echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \ echo 'endif' \ ) > $(dir $@)/.$(notdir $@).flags diff -urN linux-2.4.19-pre5/arch/alpha/kernel/setup.c linux-2.4.19-pre6/arch/alpha/kernel/setup.c --- linux-2.4.19-pre5/arch/alpha/kernel/setup.c Fri Nov 16 18:38:39 2001 +++ linux-2.4.19-pre6/arch/alpha/kernel/setup.c Thu Apr 4 22:04:30 2002 @@ -440,12 +440,6 @@ return MKDEV(TTY_MAJOR, 64 + c->index); } -static int srm_console_wait_key(struct console *co) -{ - /* Huh? */ - return 1; -} - static int __init srm_console_setup(struct console *co, char *options) { return 1; @@ -455,7 +449,6 @@ name: "srm0", write: srm_console_write, device: srm_console_device, - wait_key: srm_console_wait_key, setup: srm_console_setup, flags: CON_PRINTBUFFER | CON_ENABLED, /* fake it out */ index: -1, diff -urN linux-2.4.19-pre5/arch/i386/config.in linux-2.4.19-pre6/arch/i386/config.in --- linux-2.4.19-pre5/arch/i386/config.in Thu Apr 4 22:04:20 2002 +++ linux-2.4.19-pre6/arch/i386/config.in Thu Apr 4 22:04:30 2002 @@ -424,6 +424,7 @@ bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK + bool ' Compile the kernel with frame pointers' CONFIG_FRAME_POINTER fi endmenu diff -urN linux-2.4.19-pre5/arch/i386/kernel/semaphore.c linux-2.4.19-pre6/arch/i386/kernel/semaphore.c --- linux-2.4.19-pre5/arch/i386/kernel/semaphore.c Fri Nov 9 13:58:02 2001 +++ linux-2.4.19-pre6/arch/i386/kernel/semaphore.c Thu Apr 4 22:04:31 2002 @@ -182,6 +182,10 @@ ".align 4\n" ".globl __down_failed\n" "__down_failed:\n\t" +#if defined(CONFIG_FRAME_POINTER) + "pushl %ebp\n\t" + "movl %esp,%ebp\n\t" +#endif "pushl %eax\n\t" "pushl %edx\n\t" "pushl %ecx\n\t" @@ -189,6 +193,10 @@ "popl %ecx\n\t" "popl %edx\n\t" "popl %eax\n\t" +#if defined(CONFIG_FRAME_POINTER) + "movl %ebp,%esp\n\t" + "popl %ebp\n\t" +#endif "ret" ); @@ -197,11 +205,19 @@ ".align 4\n" ".globl __down_failed_interruptible\n" "__down_failed_interruptible:\n\t" +#if defined(CONFIG_FRAME_POINTER) + "pushl %ebp\n\t" + "movl %esp,%ebp\n\t" +#endif "pushl %edx\n\t" "pushl %ecx\n\t" "call __down_interruptible\n\t" "popl %ecx\n\t" "popl %edx\n\t" +#if defined(CONFIG_FRAME_POINTER) + "movl %ebp,%esp\n\t" + "popl %ebp\n\t" +#endif "ret" ); @@ -210,11 +226,19 @@ ".align 4\n" ".globl __down_failed_trylock\n" "__down_failed_trylock:\n\t" +#if defined(CONFIG_FRAME_POINTER) + "pushl %ebp\n\t" + "movl %esp,%ebp\n\t" +#endif "pushl %edx\n\t" "pushl %ecx\n\t" "call __down_trylock\n\t" "popl %ecx\n\t" "popl %edx\n\t" +#if defined(CONFIG_FRAME_POINTER) + "movl %ebp,%esp\n\t" + "popl %ebp\n\t" +#endif "ret" ); diff -urN linux-2.4.19-pre5/arch/i386/kernel/smp.c linux-2.4.19-pre6/arch/i386/kernel/smp.c --- linux-2.4.19-pre5/arch/i386/kernel/smp.c Fri Dec 21 09:41:53 2001 +++ linux-2.4.19-pre6/arch/i386/kernel/smp.c Thu Apr 4 22:04:31 2002 @@ -301,8 +301,7 @@ */ static void inline leave_mm (unsigned long cpu) { - if (cpu_tlbstate[cpu].state == TLBSTATE_OK) - BUG(); + BUG_ON(cpu_tlbstate[cpu].state == TLBSTATE_OK); clear_bit(cpu, &cpu_tlbstate[cpu].active_mm->cpu_vm_mask); } diff -urN linux-2.4.19-pre5/arch/ia64/hp/hpsim_console.c linux-2.4.19-pre6/arch/ia64/hp/hpsim_console.c --- linux-2.4.19-pre5/arch/ia64/hp/hpsim_console.c Thu Oct 12 14:20:48 2000 +++ linux-2.4.19-pre6/arch/ia64/hp/hpsim_console.c Thu Apr 4 22:04:31 2002 @@ -24,14 +24,12 @@ static int simcons_init (struct console *, char *); static void simcons_write (struct console *, const char *, unsigned); -static int simcons_wait_key (struct console *); static kdev_t simcons_console_device (struct console *); struct console hpsim_cons = { name: "simcons", write: simcons_write, device: simcons_console_device, - wait_key: simcons_wait_key, setup: simcons_init, flags: CON_PRINTBUFFER, index: -1, @@ -56,17 +54,6 @@ } } -static int -simcons_wait_key (struct console *cons) -{ - char ch; - - do { - ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR); - } while (ch == '\0'); - return ch; -} - static kdev_t simcons_console_device (struct console *c) { diff -urN linux-2.4.19-pre5/arch/m68k/amiga/config.c linux-2.4.19-pre6/arch/m68k/amiga/config.c --- linux-2.4.19-pre5/arch/m68k/amiga/config.c Thu Sep 13 15:21:32 2001 +++ linux-2.4.19-pre6/arch/m68k/amiga/config.c Thu Apr 4 22:04:31 2002 @@ -98,7 +98,6 @@ extern void amiga_floppy_setup(char *, int *); #endif static void amiga_reset (void); -static int amiga_wait_key (struct console *co); extern void amiga_init_sound(void); static void amiga_savekmsg_init(void); static void amiga_mem_console_write(struct console *co, const char *b, @@ -112,7 +111,6 @@ static struct console amiga_console_driver = { name: "debug", - wait_key: amiga_wait_key, flags: CON_PRINTBUFFER, index: -1, }; @@ -742,33 +740,6 @@ return 0; } -static int amiga_wait_key (struct console *co) -{ - int i; - - while (1) { - while (ciaa.pra & 0x40); - - /* debounce */ - for (i = 0; i < 1000; i++); - - if (!(ciaa.pra & 0x40)) - break; - } - - /* wait for button up */ - while (1) { - while (!(ciaa.pra & 0x40)); - - /* debounce */ - for (i = 0; i < 1000; i++); - - if (ciaa.pra & 0x40) - break; - } - return 0; -} - static NORET_TYPE void amiga_reset( void ) ATTRIB_NORET; diff -urN linux-2.4.19-pre5/arch/m68k/kernel/setup.c linux-2.4.19-pre6/arch/m68k/kernel/setup.c --- linux-2.4.19-pre5/arch/m68k/kernel/setup.c Thu Apr 4 22:04:20 2002 +++ linux-2.4.19-pre6/arch/m68k/kernel/setup.c Thu Apr 4 22:04:31 2002 @@ -94,7 +94,6 @@ long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ #if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) void (*mach_floppy_setup) (char *, int *) __initdata = NULL; -void (*mach_floppy_eject) (void) = NULL; #endif #ifdef CONFIG_HEARTBEAT void (*mach_heartbeat) (int) = NULL; @@ -534,11 +533,6 @@ mach_floppy_setup (str, ints); } -void floppy_eject(void) -{ - if (mach_floppy_eject) - mach_floppy_eject(); -} #endif /* for "kbd-reset" cmdline param */ diff -urN linux-2.4.19-pre5/arch/m68k/mac/debug.c linux-2.4.19-pre6/arch/m68k/mac/debug.c --- linux-2.4.19-pre5/arch/m68k/mac/debug.c Mon Jun 11 19:15:27 2001 +++ linux-2.4.19-pre6/arch/m68k/mac/debug.c Thu Apr 4 22:04:31 2002 @@ -235,32 +235,6 @@ } } -#if defined(CONFIG_SERIAL_CONSOLE) || defined(DEBUG_SERIAL) -int mac_sccb_console_wait_key(struct console *co) -{ - int i; - do { - for( i = uSEC; i > 0; --i ) - barrier(); - } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */ - for( i = uSEC; i > 0; --i ) - barrier(); - return( scc.cha_b_data ); -} - -int mac_scca_console_wait_key(struct console *co) -{ - int i; - do { - for( i = uSEC; i > 0; --i ) - barrier(); - } while( !(scc.cha_a_ctrl & 0x01) ); /* wait for rx buf filled */ - for( i = uSEC; i > 0; --i ) - barrier(); - return( scc.cha_a_data ); -} -#endif - /* The following two functions do a quick'n'dirty initialization of the MFP or * SCC serial ports. They're used by the debugging interface, kgdb, and the * serial console code. */ @@ -395,18 +369,12 @@ /* Mac modem port */ mac_init_scc_port( B9600|CS8, 0 ); mac_console_driver.write = mac_scca_console_write; -#ifdef CONFIG_SERIAL_CONSOLE - mac_console_driver.wait_key = mac_scca_console_wait_key; -#endif scc_port = 0; } else if (!strcmp( m68k_debug_device, "ser2" )) { /* Mac printer port */ mac_init_scc_port( B9600|CS8, 1 ); mac_console_driver.write = mac_sccb_console_write; -#ifdef CONFIG_SERIAL_CONSOLE - mac_console_driver.wait_key = mac_sccb_console_wait_key; -#endif scc_port = 1; } #endif diff -urN linux-2.4.19-pre5/arch/m68k/mvme147/config.c linux-2.4.19-pre6/arch/m68k/mvme147/config.c --- linux-2.4.19-pre5/arch/m68k/mvme147/config.c Mon Jun 11 19:15:27 2001 +++ linux-2.4.19-pre6/arch/m68k/mvme147/config.c Thu Apr 4 22:04:32 2002 @@ -241,31 +241,7 @@ restore_flags(flags); } - -static int m147_scc_wait_key (struct console *co) -{ - volatile unsigned char *p = (volatile char *)M147_SCC_A_ADDR; - unsigned long flags; - int c; - - /* wait for rx buf filled */ - while ((*p & 0x01) == 0) - ; - - save_flags(flags); - cli(); - - *p = 8; - scc_delay(); - c = *p; - - restore_flags(flags); - return c; -} - - void mvme147_init_console_port (struct console *co, int cflag) { co->write = m147_scc_write; - co->wait_key = m147_scc_wait_key; } diff -urN linux-2.4.19-pre5/arch/m68k/q40/config.c linux-2.4.19-pre6/arch/m68k/q40/config.c --- linux-2.4.19-pre5/arch/m68k/q40/config.c Mon Jun 11 19:15:27 2001 +++ linux-2.4.19-pre6/arch/m68k/q40/config.c Thu Apr 4 22:04:32 2002 @@ -36,7 +36,6 @@ #include #include -extern void floppy_eject(void); extern void floppy_setup(char *str, int *ints); extern int q40kbd_translate(unsigned char scancode, unsigned char *keycode, @@ -73,10 +72,8 @@ extern int ql_ticks; -static int q40_wait_key(struct console *co){return 0;} static struct console q40_console_driver = { name: "debug", - wait_key: q40_wait_key, flags: CON_PRINTBUFFER, index: -1, }; diff -urN linux-2.4.19-pre5/arch/m68k/sun3x/prom.c linux-2.4.19-pre6/arch/m68k/sun3x/prom.c --- linux-2.4.19-pre5/arch/m68k/sun3x/prom.c Mon Jun 11 19:15:27 2001 +++ linux-2.4.19-pre6/arch/m68k/sun3x/prom.c Thu Apr 4 22:04:32 2002 @@ -96,7 +96,6 @@ sun3x_prom_write, /* write */ NULL, /* read */ NULL, /* device */ - NULL, /* wait_key */ NULL, /* unblank */ NULL, /* setup */ CON_PRINTBUFFER, diff -urN linux-2.4.19-pre5/arch/mips/au1000/common/serial.c linux-2.4.19-pre6/arch/mips/au1000/common/serial.c --- linux-2.4.19-pre5/arch/mips/au1000/common/serial.c Thu Apr 4 22:04:20 2002 +++ linux-2.4.19-pre6/arch/mips/au1000/common/serial.c Thu Apr 4 22:04:32 2002 @@ -2933,35 +2933,6 @@ serial_out(info, UART_IER, ier); } -/* - * Receive character from the serial port - */ -static int serial_console_wait_key(struct console *co) -{ - static struct async_struct *info; - int ier, c; - - info = &async_sercons; - - /* - * First save the IER then disable the interrupts so - * that the real driver for the port does not get the - * character. - */ - ier = serial_in(info, UART_IER); - serial_out(info, UART_IER, 0x00); - - while ((serial_in(info, UART_LSR) & UART_LSR_DR) == 0); - c = serial_in(info, UART_RX); - - /* - * Restore the interrupts - */ - serial_out(info, UART_IER, ier); - - return c; -} - static kdev_t serial_console_device(struct console *c) { return MKDEV(TTY_MAJOR, 64 + c->index); @@ -3086,7 +3057,6 @@ name: "ttyS", write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/arch/mips/baget/vacserial.c linux-2.4.19-pre6/arch/mips/baget/vacserial.c --- linux-2.4.19-pre5/arch/mips/baget/vacserial.c Thu Apr 4 22:04:20 2002 +++ linux-2.4.19-pre6/arch/mips/baget/vacserial.c Thu Apr 4 22:04:32 2002 @@ -2622,43 +2622,6 @@ serial_outp(&scr_info, VAC_UART_INT_MASK, ier); } -/* - * Receive character from the serial port - */ -static int serial_console_wait_key(struct console *co) -{ - struct serial_state *ser; - int ier; - int lsr; - int c; - struct async_struct scr_info; /* serial_{in,out} because HUB6 */ - - ser = rs_table + co->index; - scr_info.magic = SERIAL_MAGIC; - scr_info.port = ser->port; - scr_info.flags = ser->flags; - - /* - * First save the IER then disable the interrupts so - * that the real driver for the port does not get the - * character. - */ - ier = serial_inp(&scr_info, VAC_UART_INT_MASK); - serial_outp(&scr_info, VAC_UART_INT_MASK, 0x00); - - do { - lsr = serial_inp(&scr_info, VAC_UART_INT_STATUS); - } while (!(lsr & VAC_UART_STATUS_RX_READY)); - c = serial_inp(&scr_info, VAC_UART_RX); - - /* - * Restore the interrupts - */ - serial_outp(&scr_info, VAC_UART_INT_MASK, ier); - - return c; -} - static kdev_t serial_console_device(struct console *c) { return MKDEV(TTY_MAJOR, 64 + c->index); @@ -2812,7 +2775,6 @@ name: "ttyS", write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/arch/mips/dec/promcon.c linux-2.4.19-pre6/arch/mips/dec/promcon.c --- linux-2.4.19-pre5/arch/mips/dec/promcon.c Thu Oct 12 14:20:48 2000 +++ linux-2.4.19-pre6/arch/mips/dec/promcon.c Thu Apr 4 22:04:32 2002 @@ -30,11 +30,6 @@ } } -static int prom_console_wait_key(struct console *co) -{ - return prom_getchar(); -} - static int __init prom_console_setup(struct console *co, char *options) { return 0; @@ -50,7 +45,6 @@ name: "ttyS", write: prom_console_write, device: prom_console_device, - wait_key: prom_console_wait_key, setup: prom_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/arch/mips64/arc/arc_con.c linux-2.4.19-pre6/arch/mips64/arc/arc_con.c --- linux-2.4.19-pre5/arch/mips64/arc/arc_con.c Thu Apr 4 22:04:20 2002 +++ linux-2.4.19-pre6/arch/mips64/arc/arc_con.c Thu Apr 4 22:04:34 2002 @@ -39,11 +39,6 @@ } } -static int prom_console_wait_key(struct console *co) -{ - return 0; -} - static kdev_t prom_console_device(struct console *c) { return MKDEV(TTY_MAJOR, 64 + c->index); @@ -53,7 +48,6 @@ name: "ttyS", write: prom_console_write, device: prom_console_device, - wait_key: prom_console_wait_key, flags: CON_PRINTBUFFER, index: -1, }; diff -urN linux-2.4.19-pre5/arch/parisc/kernel/pdc_cons.c linux-2.4.19-pre6/arch/parisc/kernel/pdc_cons.c --- linux-2.4.19-pre5/arch/parisc/kernel/pdc_cons.c Sun Sep 16 21:23:15 2001 +++ linux-2.4.19-pre6/arch/parisc/kernel/pdc_cons.c Thu Apr 4 22:04:35 2002 @@ -105,10 +105,6 @@ static struct console pdc_cons = { name: "ttyB", write: pdc_console_write, - read: NULL, - device: NULL, - wait_key: pdc_console_wait_key, - unblank: NULL, setup: pdc_console_setup, flags: CON_PRINTBUFFER|CON_ENABLED, // |CON_CONSDEV, index: -1, diff -urN linux-2.4.19-pre5/arch/ppc/8260_io/uart.c linux-2.4.19-pre6/arch/ppc/8260_io/uart.c --- linux-2.4.19-pre5/arch/ppc/8260_io/uart.c Mon Feb 25 11:37:53 2002 +++ linux-2.4.19-pre6/arch/ppc/8260_io/uart.c Thu Apr 4 22:04:35 2002 @@ -2216,54 +2216,6 @@ info->tx_cur = (cbd_t *)bdp; } -/* - * Receive character from the serial port. This only works well - * before the port is initialize for real use. - */ -static int serial_console_wait_key(struct console *co) -{ - struct serial_state *ser; - u_char c, *cp; - ser_info_t *info; - volatile cbd_t *bdp; - volatile smc_uart_t *up; - - ser = rs_table + co->index; - - /* Pointer to UART in parameter ram. - */ - up = (smc_uart_t *)&immr->im_dprambase[ser->port]; - - /* Get the address of the host memory buffer. - * If the port has been initialized for general use, we must - * use information from the port structure. - */ - if ((info = (ser_info_t *)ser->info)) - bdp = info->rx_cur; - else - bdp = (cbd_t *)&immr->im_dprambase[up->smc_rbase]; - - /* - * We need to gracefully shut down the receiver, disable - * interrupts, then read the input. - */ - while (bdp->cbd_sc & BD_SC_EMPTY); /* Wait for a character */ - cp = __va(bdp->cbd_bufaddr); - - if (info) { - if (bdp->cbd_sc & BD_SC_WRAP) { - bdp = info->rx_bd_base; - } - else { - bdp++; - } - info->rx_cur = (cbd_t *)bdp; - } - - c = *cp; - return((int)c); -} - static kdev_t serial_console_device(struct console *c) { return MKDEV(TTYAUX_MAJOR, 64 + c->index); @@ -2274,7 +2226,6 @@ name: "ttyS", write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: CONFIG_SERIAL_CONSOLE_PORT, diff -urN linux-2.4.19-pre5/arch/ppc/8xx_io/uart.c linux-2.4.19-pre6/arch/ppc/8xx_io/uart.c --- linux-2.4.19-pre5/arch/ppc/8xx_io/uart.c Mon Feb 25 11:37:54 2002 +++ linux-2.4.19-pre6/arch/ppc/8xx_io/uart.c Thu Apr 4 22:04:35 2002 @@ -97,7 +97,6 @@ static void serial_console_write(struct console *c, const char *s, unsigned count); static kdev_t serial_console_device(struct console *c); -static int serial_console_wait_key(struct console *co); #if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) static unsigned long break_pressed; /* break, really ... */ @@ -218,7 +217,6 @@ name: "ttyS", write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: CONFIG_SERIAL_CONSOLE_PORT, @@ -2402,11 +2400,6 @@ return((int)c); } -static int serial_console_wait_key(struct console *co) -{ - return(my_console_wait_key(co->index, 0, NULL)); -} - #ifdef CONFIG_XMON int xmon_8xx_read_poll(void) diff -urN linux-2.4.19-pre5/arch/ppc/amiga/config.c linux-2.4.19-pre6/arch/ppc/amiga/config.c --- linux-2.4.19-pre5/arch/ppc/amiga/config.c Thu Apr 4 22:04:20 2002 +++ linux-2.4.19-pre6/arch/ppc/amiga/config.c Thu Apr 4 22:04:35 2002 @@ -103,7 +103,6 @@ extern void amiga_floppy_setup(char *, int *); #endif static void amiga_reset (void); -static int amiga_wait_key (struct console *co); extern void amiga_init_sound(void); static void amiga_savekmsg_init(void); static void amiga_mem_console_write(struct console *co, const char *b, @@ -117,7 +116,6 @@ static struct console amiga_console_driver = { name: "debug", - wait_key: amiga_wait_key, flags: CON_PRINTBUFFER, index: -1, }; @@ -735,33 +733,6 @@ return 0; } -static int amiga_wait_key (struct console *co) -{ - int i; - - while (1) { - while (ciaa.pra & 0x40); - - /* debounce */ - for (i = 0; i < 1000; i++); - - if (!(ciaa.pra & 0x40)) - break; - } - - /* wait for button up */ - while (1) { - while (!(ciaa.pra & 0x40)); - - /* debounce */ - for (i = 0; i < 1000; i++); - - if (ciaa.pra & 0x40) - break; - } - return 0; -} - static NORET_TYPE void amiga_reset( void ) ATTRIB_NORET; diff -urN linux-2.4.19-pre5/arch/ppc/kernel/apus_setup.c linux-2.4.19-pre6/arch/ppc/kernel/apus_setup.c --- linux-2.4.19-pre5/arch/ppc/kernel/apus_setup.c Fri Nov 16 10:10:08 2001 +++ linux-2.4.19-pre6/arch/ppc/kernel/apus_setup.c Thu Apr 4 22:04:36 2002 @@ -106,7 +106,6 @@ long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ #if defined(CONFIG_AMIGA_FLOPPY) void (*mach_floppy_setup) (char *, int *) __initdata = NULL; -void (*mach_floppy_eject) (void) = NULL; #endif #ifdef CONFIG_HEARTBEAT void (*mach_heartbeat) (int) = NULL; @@ -404,12 +403,6 @@ if (mach_floppy_setup) mach_floppy_setup (str, ints); } - -void floppy_eject(void) -{ - if (mach_floppy_eject) - mach_floppy_eject(); -} #endif /*********************************************************** MEMORY */ diff -urN linux-2.4.19-pre5/arch/ppc/kernel/m8xx_setup.c linux-2.4.19-pre6/arch/ppc/kernel/m8xx_setup.c --- linux-2.4.19-pre5/arch/ppc/kernel/m8xx_setup.c Fri Nov 16 10:10:08 2001 +++ linux-2.4.19-pre6/arch/ppc/kernel/m8xx_setup.c Thu Apr 4 22:04:36 2002 @@ -55,12 +55,6 @@ extern void m8xx_ide_init(void); -#ifdef CONFIG_BLK_DEV_RAM -extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ -extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ -extern int rd_image_start; /* starting block # of image */ -#endif - extern unsigned long find_available_memory(void); extern void m8xx_cpm_reset(uint); diff -urN linux-2.4.19-pre5/arch/ppc/kernel/prep_setup.c linux-2.4.19-pre6/arch/ppc/kernel/prep_setup.c --- linux-2.4.19-pre5/arch/ppc/kernel/prep_setup.c Mon Feb 25 11:37:55 2002 +++ linux-2.4.19-pre6/arch/ppc/kernel/prep_setup.c Thu Apr 4 22:04:36 2002 @@ -111,12 +111,6 @@ extern int probingmem; extern unsigned long loops_per_jiffy; -#ifdef CONFIG_BLK_DEV_RAM -extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ -extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ -extern int rd_image_start; /* starting block # of image */ -#endif - #ifdef CONFIG_SOUND_MODULE EXPORT_SYMBOL(ppc_cs4232_dma); EXPORT_SYMBOL(ppc_cs4232_dma2); diff -urN linux-2.4.19-pre5/arch/ppc/kernel/time.c linux-2.4.19-pre6/arch/ppc/kernel/time.c --- linux-2.4.19-pre5/arch/ppc/kernel/time.c Mon Feb 25 11:37:55 2002 +++ linux-2.4.19-pre6/arch/ppc/kernel/time.c Thu Apr 4 22:04:36 2002 @@ -358,7 +358,7 @@ #define STARTOFTIME 1970 #define SECDAY 86400L #define SECYR (SECDAY * 365) -#define leapyear(year) ((year) % 4 == 0) +#define leapyear(y) ((!(y % 4) && (y % 100)) || !(y % 400)) #define days_in_year(a) (leapyear(a) ? 366 : 365) #define days_in_month(a) (month_days[(a) - 1]) diff -urN linux-2.4.19-pre5/arch/sh/kernel/setup.c linux-2.4.19-pre6/arch/sh/kernel/setup.c --- linux-2.4.19-pre5/arch/sh/kernel/setup.c Fri Nov 16 18:38:39 2001 +++ linux-2.4.19-pre6/arch/sh/kernel/setup.c Thu Apr 4 22:04:47 2002 @@ -140,15 +140,6 @@ sh_bios_console_write(s, count); } -/* - * Receive character from the serial port - */ -static int sh_console_wait_key(struct console *co) -{ - /* Not implemented yet */ - return 0; -} - static kdev_t sh_console_device(struct console *c) { /* TODO: this is totally bogus */ @@ -183,7 +174,6 @@ name: "bios", write: sh_console_write, device: sh_console_device, - wait_key: sh_console_wait_key, setup: sh_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/acorn/block/fd1772.c linux-2.4.19-pre6/drivers/acorn/block/fd1772.c --- linux-2.4.19-pre5/drivers/acorn/block/fd1772.c Sun Aug 12 10:38:48 2001 +++ linux-2.4.19-pre6/drivers/acorn/block/fd1772.c Thu Apr 4 22:04:54 2002 @@ -1620,7 +1620,3 @@ return 0; } - -void floppy_eject(void) -{ -} diff -urN linux-2.4.19-pre5/drivers/block/blkpg.c linux-2.4.19-pre6/drivers/block/blkpg.c --- linux-2.4.19-pre5/drivers/block/blkpg.c Mon Feb 25 11:37:57 2002 +++ linux-2.4.19-pre6/drivers/block/blkpg.c Thu Apr 4 22:04:55 2002 @@ -110,6 +110,7 @@ g->part[minor].nr_sects = plength; if (g->sizes) g->sizes[minor] = (plength >> (BLOCK_SIZE_BITS - 9)); + devfs_register_partitions (g, first_minor, 0); return 0; } @@ -157,6 +158,7 @@ g->part[minor].nr_sects = 0; if (g->sizes) g->sizes[minor] = 0; + devfs_register_partitions (g, first_minor, 0); return 0; } diff -urN linux-2.4.19-pre5/drivers/block/floppy.c linux-2.4.19-pre6/drivers/block/floppy.c --- linux-2.4.19-pre5/drivers/block/floppy.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/block/floppy.c Thu Apr 4 22:04:55 2002 @@ -4490,22 +4490,6 @@ __setup ("floppy=", floppy_setup); -/* eject the boot floppy (if we need the drive for a different root floppy) */ -/* This should only be called at boot time when we're sure that there's no - * resource contention. */ -void floppy_eject(void) -{ - int dummy; - if (have_no_fdc) - return; - if(floppy_grab_irq_and_dma()==0) - { - lock_fdc(MAXTIMEOUT,0); - dummy=fd_eject(0); - process_fd_request(); - floppy_release_irq_and_dma(); - } -} #endif EXPORT_NO_SYMBOLS; diff -urN linux-2.4.19-pre5/drivers/block/genhd.c linux-2.4.19-pre6/drivers/block/genhd.c --- linux-2.4.19-pre5/drivers/block/genhd.c Mon Feb 25 11:37:57 2002 +++ linux-2.4.19-pre6/drivers/block/genhd.c Thu Apr 4 22:04:55 2002 @@ -135,20 +135,39 @@ get_partition_list(char *page, char **start, off_t offset, int count) { struct gendisk *gp; + struct hd_struct *hd; char buf[64]; int len, n; - len = sprintf(page, "major minor #blocks name\n\n"); + len = sprintf(page, "major minor #blocks name " + "rio rmerge rsect ruse wio wmerge " + "wsect wuse running use aveq\n\n"); + + read_lock(&gendisk_lock); for (gp = gendisk_head; gp; gp = gp->next) { for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) { if (gp->part[n].nr_sects == 0) continue; - len += snprintf(page + len, 63, - "%4d %4d %10d %s\n", + hd = &gp->part[n]; disk_round_stats(hd); + len += sprintf(page + len, + "%4d %4d %10d %s " + "%d %d %d %d %d %d %d %d %d %d %d\n", gp->major, n, gp->sizes[n], - disk_name(gp, n, buf)); + disk_name(gp, n, buf), + hd->rd_ios, hd->rd_merges, + hd->rd_sectors, +#define MSEC(x) ((x) * 1000 / HZ) + MSEC(hd->rd_ticks), + hd->wr_ios, hd->wr_merges, + hd->wr_sectors, + MSEC(hd->wr_ticks), + hd->ios_in_flight, + MSEC(hd->io_ticks), + MSEC(hd->aveq)); +#undef MSEC + if (len < offset) offset -= len, len = 0; else if (len >= offset + count) diff -urN linux-2.4.19-pre5/drivers/block/ll_rw_blk.c linux-2.4.19-pre6/drivers/block/ll_rw_blk.c --- linux-2.4.19-pre5/drivers/block/ll_rw_blk.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/block/ll_rw_blk.c Thu Apr 4 22:04:55 2002 @@ -336,14 +336,17 @@ */ int blk_grow_request_list(request_queue_t *q, int nr_requests) { - spin_lock_irq(&io_request_lock); + unsigned long flags; + /* Several broken drivers assume that this function doesn't sleep, + * this causes system hangs during boot. + * As a temporary fix, make the the function non-blocking. + */ + spin_lock_irqsave(&io_request_lock, flags); while (q->nr_requests < nr_requests) { struct request *rq; int rw; - spin_unlock_irq(&io_request_lock); - rq = kmem_cache_alloc(request_cachep, SLAB_KERNEL); - spin_lock_irq(&io_request_lock); + rq = kmem_cache_alloc(request_cachep, SLAB_ATOMIC); if (rq == NULL) break; memset(rq, 0, sizeof(*rq)); @@ -356,7 +359,7 @@ q->batch_requests = q->nr_requests / 4; if (q->batch_requests > 32) q->batch_requests = 32; - spin_unlock_irq(&io_request_lock); + spin_unlock_irqrestore(&io_request_lock, flags); return q->nr_requests; } @@ -591,6 +594,121 @@ printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n"); } +/* Return up to two hd_structs on which to do IO accounting for a given + * request. On a partitioned device, we want to account both against + * the partition and against the whole disk. */ +static void locate_hd_struct(struct request *req, + struct hd_struct **hd1, + struct hd_struct **hd2) +{ + struct gendisk *gd; + + *hd1 = NULL; + *hd2 = NULL; + + gd = get_gendisk(req->rq_dev); + if (gd && gd->part) { + /* Mask out the partition bits: account for the entire disk */ + int devnr = MINOR(req->rq_dev) >> gd->minor_shift; + int whole_minor = devnr << gd->minor_shift; + *hd1 = &gd->part[whole_minor]; + if (whole_minor != MINOR(req->rq_dev)) + *hd2= &gd->part[MINOR(req->rq_dev)]; + } +} + +/* Round off the performance stats on an hd_struct. The average IO + * queue length and utilisation statistics are maintained by observing + * the current state of the queue length and the amount of time it has + * been in this state for. Normally, that accounting is done on IO + * completion, but that can result in more than a second's worth of IO + * being accounted for within any one second, leading to >100% + * utilisation. To deal with that, we do a round-off before returning + * the results when reading /proc/partitions, accounting immediately for + * all queue usage up to the current jiffies and restarting the counters + * again. */ +void disk_round_stats(struct hd_struct *hd) +{ + unsigned long now = jiffies; + + hd->aveq += (hd->ios_in_flight * (jiffies - hd->last_queue_change)); + hd->last_queue_change = now; + + if (hd->ios_in_flight) + hd->io_ticks += (now - hd->last_idle_time); + hd->last_idle_time = now; +} + + +static inline void down_ios(struct hd_struct *hd) +{ + disk_round_stats(hd); + --hd->ios_in_flight; +} + +static inline void up_ios(struct hd_struct *hd) +{ + disk_round_stats(hd); + ++hd->ios_in_flight; +} + +static void account_io_start(struct hd_struct *hd, struct request *req, + int merge, int sectors) +{ + switch (req->cmd) { + case READ: + if (merge) + hd->rd_merges++; + hd->rd_sectors += sectors; + break; + case WRITE: + if (merge) + hd->wr_merges++; + hd->wr_sectors += sectors; + break; + default: + } + if (!merge) + up_ios(hd); +} + +static void account_io_end(struct hd_struct *hd, struct request *req) +{ + unsigned long duration = jiffies - req->start_time; + switch (req->cmd) { + case READ: + hd->rd_ticks += duration; + hd->rd_ios++; + break; + case WRITE: + hd->wr_ticks += duration; + hd->wr_ios++; + break; + default: + } + down_ios(hd); +} + +void req_new_io(struct request *req, int merge, int sectors) +{ + struct hd_struct *hd1, *hd2; + locate_hd_struct(req, &hd1, &hd2); + if (hd1) + account_io_start(hd1, req, merge, sectors); + if (hd2) + account_io_start(hd2, req, merge, sectors); +} + +void req_finished_io(struct request *req) +{ + struct hd_struct *hd1, *hd2; + locate_hd_struct(req, &hd1, &hd2); + if (hd1) + account_io_end(hd1, req); + if (hd2) + account_io_end(hd2, req); +} + /* * add-request adds a request to the linked list. * io_request_lock is held and interrupts disabled, as we muck with the @@ -648,6 +766,7 @@ int max_segments) { struct request *next; + struct hd_struct *hd1, *hd2; next = blkdev_next_request(req); if (req->sector + req->nr_sectors != next->sector) @@ -671,6 +790,15 @@ req->bhtail = next->bhtail; req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors; list_del(&next->queue); + + /* One last thing: we have removed a request, so we now have one + less expected IO to complete for accounting purposes. */ + + locate_hd_struct(req, &hd1, &hd2); + if (hd1) + down_ios(hd1); + if (hd2) + down_ios(hd2); blkdev_release_request(next); } @@ -778,6 +906,7 @@ req->nr_sectors = req->hard_nr_sectors += count; blk_started_io(count); drive_stat_acct(req->rq_dev, req->cmd, count, 0); + req_new_io(req, 1, count); attempt_back_merge(q, req, max_sectors, max_segments); goto out; @@ -795,6 +924,7 @@ req->nr_sectors = req->hard_nr_sectors += count; blk_started_io(count); drive_stat_acct(req->rq_dev, req->cmd, count, 0); + req_new_io(req, 1, count); attempt_front_merge(q, head, req, max_sectors, max_segments); goto out; @@ -856,6 +986,8 @@ req->bh = bh; req->bhtail = bh; req->rq_dev = bh->b_rdev; + req->start_time = jiffies; + req_new_io(req, 0, count); blk_started_io(count); add_request(q, req, insert_here); out: @@ -1169,6 +1301,7 @@ { if (req->waiting != NULL) complete(req->waiting); + req_finished_io(req); blkdev_release_request(req); } @@ -1197,9 +1330,6 @@ #ifdef CONFIG_STRAM_SWAP stram_device_init(); #endif -#ifdef CONFIG_BLK_DEV_RAM - rd_init(); -#endif #ifdef CONFIG_ISP16_CDI isp16_init(); #endif @@ -1309,4 +1439,5 @@ EXPORT_SYMBOL(blk_queue_make_request); EXPORT_SYMBOL(generic_make_request); EXPORT_SYMBOL(blkdev_release_request); +EXPORT_SYMBOL(req_finished_io); EXPORT_SYMBOL(generic_unplug_device); diff -urN linux-2.4.19-pre5/drivers/block/rd.c linux-2.4.19-pre6/drivers/block/rd.c --- linux-2.4.19-pre5/drivers/block/rd.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/block/rd.c Thu Apr 4 22:04:55 2002 @@ -43,26 +43,13 @@ */ #include -#include -#include -#include -#include #include -#include -#include #include -#include -#include #include #include #include #include - -#include #include -#include - -extern void wait_for_keypress(void); /* * 35 has been officially registered as the RAMDISK major number, but @@ -78,6 +65,8 @@ #ifdef CONFIG_BLK_DEV_INITRD static int initrd_users; +unsigned long initrd_start, initrd_end; +int initrd_below_start_ok; #endif /* Various static variables go here. Most are used only in the RAM disk code. @@ -110,70 +99,6 @@ */ int rd_blocksize = BLOCK_SIZE; /* blocksize of the RAM disks */ -#ifndef MODULE - -int rd_doload; /* 1 = load RAM disk, 0 = don't load */ -int rd_prompt = 1; /* 1 = prompt for RAM disk, 0 = don't prompt */ -int rd_image_start; /* starting block # of image */ -#ifdef CONFIG_BLK_DEV_INITRD -unsigned long initrd_start, initrd_end; -int mount_initrd = 1; /* zero if initrd should not be mounted */ -int initrd_below_start_ok; - -static int __init no_initrd(char *str) -{ - mount_initrd = 0; - return 1; -} - -__setup("noinitrd", no_initrd); - -#endif - -static int __init ramdisk_start_setup(char *str) -{ - rd_image_start = simple_strtol(str,NULL,0); - return 1; -} - -static int __init load_ramdisk(char *str) -{ - rd_doload = simple_strtol(str,NULL,0) & 3; - return 1; -} - -static int __init prompt_ramdisk(char *str) -{ - rd_prompt = simple_strtol(str,NULL,0) & 1; - return 1; -} - -static int __init ramdisk_size(char *str) -{ - rd_size = simple_strtol(str,NULL,0); - return 1; -} - -static int __init ramdisk_size2(char *str) -{ - return ramdisk_size(str); -} - -static int __init ramdisk_blocksize(char *str) -{ - rd_blocksize = simple_strtol(str,NULL,0); - return 1; -} - -__setup("ramdisk_start=", ramdisk_start_setup); -__setup("load_ramdisk=", load_ramdisk); -__setup("prompt_ramdisk=", prompt_ramdisk); -__setup("ramdisk=", ramdisk_size); -__setup("ramdisk_size=", ramdisk_size2); -__setup("ramdisk_blocksize=", ramdisk_blocksize); - -#endif - /* * Copyright (C) 2000 Linus Torvalds. * 2000 Transmeta Corp. @@ -463,7 +388,6 @@ ioctl: rd_ioctl, }; -#ifdef MODULE /* Before freeing the module, invalidate all of the protected buffers! */ static void __exit rd_cleanup (void) { @@ -483,10 +407,9 @@ blksize_size[MAJOR_NR] = NULL; blk_size[MAJOR_NR] = NULL; } -#endif /* This is the registration and initialization section of the RAM disk driver */ -int __init rd_init (void) +static int __init rd_init (void) { int i; @@ -540,12 +463,31 @@ return 0; } -#ifdef MODULE module_init(rd_init); module_exit(rd_cleanup); + +/* options - nonmodular */ +#ifndef MODULE +static int __init ramdisk_size(char *str) +{ + rd_size = simple_strtol(str,NULL,0); + return 1; +} +static int __init ramdisk_size2(char *str) /* kludge */ +{ + return ramdisk_size(str); +} +static int __init ramdisk_blocksize(char *str) +{ + rd_blocksize = simple_strtol(str,NULL,0); + return 1; +} +__setup("ramdisk=", ramdisk_size); +__setup("ramdisk_size=", ramdisk_size2); +__setup("ramdisk_blocksize=", ramdisk_blocksize); #endif -/* loadable module support */ +/* options - modular */ MODULE_PARM (rd_size, "1i"); MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes."); MODULE_PARM (rd_blocksize, "i"); diff -urN linux-2.4.19-pre5/drivers/block/swim3.c linux-2.4.19-pre6/drivers/block/swim3.c --- linux-2.4.19-pre5/drivers/block/swim3.c Mon Feb 25 11:37:57 2002 +++ linux-2.4.19-pre6/drivers/block/swim3.c Thu Apr 4 22:04:55 2002 @@ -811,16 +811,6 @@ return err; } -int swim3_fd_eject(int devnum) -{ - if (devnum >= floppy_count) - return -ENODEV; - /* Do not check this - this function should ONLY be called early - * in the boot process! */ - /* if (floppy_states[devnum].ref_count != 1) return -EBUSY; */ - return fd_eject(&floppy_states[devnum]); -} - static struct floppy_struct floppy_type = { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */ diff -urN linux-2.4.19-pre5/drivers/char/Config.in linux-2.4.19-pre6/drivers/char/Config.in --- linux-2.4.19-pre5/drivers/char/Config.in Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/Config.in Thu Apr 4 22:04:55 2002 @@ -177,18 +177,11 @@ bool 'Watchdog Timer Support' CONFIG_WATCHDOG if [ "$CONFIG_WATCHDOG" != "n" ]; then bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT - tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG - tristate ' WDT Watchdog timer' CONFIG_WDT - tristate ' WDT PCI Watchdog timer' CONFIG_WDTPCI - if [ "$CONFIG_WDT" != "n" ]; then - bool ' WDT501 features' CONFIG_WDT_501 - if [ "$CONFIG_WDT_501" = "y" ]; then - bool ' Fan Tachometer' CONFIG_WDT_501_FAN - fi - fi - tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT tristate ' Advantech SBC Watchdog Timer' CONFIG_ADVANTECH_WDT + tristate ' ALi M7101 PMU Watchdog Timer' CONFIG_ALIM7101_WDT + tristate ' AMD "Elan" SC520 Watchdog Timer' CONFIG_SC520_WDT + tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then @@ -197,14 +190,25 @@ fi tristate ' Eurotech CPU-1220/1410 Watchdog Timer' CONFIG_EUROTECH_WDT tristate ' IB700 SBC Watchdog Timer' CONFIG_IB700_WDT + tristate ' ICP ELectronics Wafer 5823 Watchdog' CONFIG_WAFER_WDT + if [ "$CONFIG_SGI_IP22" = "y" ]; then + dep_tristate ' Indy/I2 Hardware Watchdog' CONFIG_INDYDOG $CONFIG_SGI_IP22 + fi tristate ' Intel i810 TCO timer / Watchdog' CONFIG_I810_TCO tristate ' Mixcom Watchdog' CONFIG_MIXCOMWD tristate ' SBC-60XX Watchdog Timer' CONFIG_60XX_WDT + dep_tristate ' SC1200 Watchdog Timer (EXPERIMENTAL)' CONFIG_SC1200_WDT $CONFIG_EXPERIMENTAL + tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG tristate ' W83877F (EMACS) Watchdog Timer' CONFIG_W83877F_WDT - tristate ' ZF MachZ Watchdog' CONFIG_MACHZ_WDT - if [ "$CONFIG_SGI_IP22" = "y" ]; then - tristate ' Indy/I2 Hardware Watchdog' CONFIG_INDYDOG + tristate ' WDT Watchdog timer' CONFIG_WDT + tristate ' WDT PCI Watchdog timer' CONFIG_WDTPCI + if [ "$CONFIG_WDT" != "n" ]; then + bool ' WDT501 features' CONFIG_WDT_501 + if [ "$CONFIG_WDT_501" = "y" ]; then + bool ' Fan Tachometer' CONFIG_WDT_501_FAN + fi fi + tristate ' ZF MachZ Watchdog' CONFIG_MACHZ_WDT fi endmenu @@ -217,8 +221,12 @@ tristate 'NetWinder flash support' CONFIG_NWFLASH fi -dep_tristate 'AMD 768 Random Number Generator support' CONFIG_AMD_RNG $CONFIG_PCI -dep_tristate 'Intel i8x0 Random Number Generator support' CONFIG_INTEL_RNG $CONFIG_PCI +if [ "$CONFIG_X86" = "y" -o "$CONFIG_X86_64" = "y" ]; then + dep_tristate 'AMD 768 Random Number Generator support' CONFIG_AMD_RNG $CONFIG_PCI +fi +if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" ]; then + dep_tristate 'Intel i8x0 Random Number Generator support' CONFIG_INTEL_RNG $CONFIG_PCI +fi tristate '/dev/nvram support' CONFIG_NVRAM tristate 'Enhanced Real Time Clock Support' CONFIG_RTC if [ "$CONFIG_IA64" = "y" ]; then @@ -277,4 +285,9 @@ if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then tristate ' ITE GPIO' CONFIG_ITE_GPIO fi + +if [ "$CONFIG_X86" = "y" ]; then + tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE +fi + endmenu diff -urN linux-2.4.19-pre5/drivers/char/agp/agp.h linux-2.4.19-pre6/drivers/char/agp/agp.h --- linux-2.4.19-pre5/drivers/char/agp/agp.h Mon Feb 25 11:37:57 2002 +++ linux-2.4.19-pre6/drivers/char/agp/agp.h Thu Apr 4 22:04:55 2002 @@ -248,6 +248,9 @@ #ifndef PCI_DEVICE_ID_AL_M1641_0 #define PCI_DEVICE_ID_AL_M1641_0 0x1641 #endif +#ifndef PCI_DEVICE_ID_AL_M1644_0 +#define PCI_DEVICE_ID_AL_M1644_0 0x1644 +#endif #ifndef PCI_DEVICE_ID_AL_M1647_0 #define PCI_DEVICE_ID_AL_M1647_0 0x1647 #endif diff -urN linux-2.4.19-pre5/drivers/char/agp/agpgart_be.c linux-2.4.19-pre6/drivers/char/agp/agpgart_be.c --- linux-2.4.19-pre5/drivers/char/agp/agpgart_be.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/agp/agpgart_be.c Thu Apr 4 22:04:55 2002 @@ -3484,6 +3484,12 @@ "Ali", "M1641", ali_generic_setup }, + { PCI_DEVICE_ID_AL_M1644_0, + PCI_VENDOR_ID_AL, + ALI_M1644, + "Ali", + "M1644", + ali_generic_setup }, { PCI_DEVICE_ID_AL_M1647_0, PCI_VENDOR_ID_AL, ALI_M1647, @@ -3515,7 +3521,7 @@ PCI_VENDOR_ID_AMD, AMD_IRONGATE, "AMD", - "AMD 760MP", + "760MP", amd_irongate_setup }, { PCI_DEVICE_ID_AMD_761_0, PCI_VENDOR_ID_AMD, @@ -3527,7 +3533,7 @@ PCI_VENDOR_ID_AMD, AMD_762, "AMD", - "AMD 760MP", + "760MP", amd_irongate_setup }, { 0, PCI_VENDOR_ID_AMD, diff -urN linux-2.4.19-pre5/drivers/char/console.c linux-2.4.19-pre6/drivers/char/console.c --- linux-2.4.19-pre5/drivers/char/console.c Fri Dec 21 09:41:53 2001 +++ linux-2.4.19-pre6/drivers/char/console.c Thu Apr 4 22:04:55 2002 @@ -2179,7 +2179,6 @@ name: "tty", write: vt_console_print, device: vt_console_device, - wait_key: keyboard_wait_for_keypress, unblank: unblank_screen, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/char/drm/drm_agpsupport.h linux-2.4.19-pre6/drivers/char/drm/drm_agpsupport.h --- linux-2.4.19-pre5/drivers/char/drm/drm_agpsupport.h Thu Nov 22 11:46:37 2001 +++ linux-2.4.19-pre6/drivers/char/drm/drm_agpsupport.h Thu Apr 4 22:04:55 2002 @@ -303,6 +303,7 @@ case ALI_M1631: head->chipset = "ALi M1631"; break; case ALI_M1632: head->chipset = "ALi M1632"; break; case ALI_M1641: head->chipset = "ALi M1641"; break; + case ALI_M1644: head->chipset = "ALi M1644"; break; case ALI_M1647: head->chipset = "ALi M1647"; break; case ALI_M1651: head->chipset = "ALi M1651"; break; #endif diff -urN linux-2.4.19-pre5/drivers/char/dz.c linux-2.4.19-pre6/drivers/char/dz.c --- linux-2.4.19-pre5/drivers/char/dz.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/dz.c Thu Apr 4 22:04:55 2002 @@ -63,7 +63,6 @@ DECLARE_TASK_QUEUE(tq_serial); -extern wait_queue_head_t keypress_wait; static struct dz_serial *lines[4]; static unsigned char tmp_buffer[256]; @@ -219,9 +218,6 @@ if (info->is_console) { if (ch == 0) return; /* it's a break ... */ - - /* It is a 'keyboard interrupt' ;-) */ - wake_up(&keypress_wait); } #endif @@ -1484,11 +1480,6 @@ } } -static int dz_console_wait_key(struct console *co) -{ - return 0; -} - static kdev_t dz_console_device(struct console *c) { return MKDEV(TTY_MAJOR, 64 + c->index); @@ -1587,7 +1578,6 @@ name: "ttyS", write: dz_console_print, device: dz_console_device, - wait_key: dz_console_wait_key, setup: dz_console_setup, flags: CON_CONSDEV | CON_PRINTBUFFER, index: CONSOLE_LINE, diff -urN linux-2.4.19-pre5/drivers/char/indydog.c linux-2.4.19-pre6/drivers/char/indydog.c --- linux-2.4.19-pre5/drivers/char/indydog.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/indydog.c Thu Apr 4 22:04:55 2002 @@ -24,7 +24,7 @@ #include #include -static int indydog_alive; +static unsigned long indydog_alive; static struct sgimc_misc_ctrl *mcmisc_regs; static void indydog_ping() @@ -41,7 +41,7 @@ { u32 mc_ctrl0; - if(indydog_alive) + if( test_and_set_bit(0,&indydog_alive) ) return -EBUSY; #ifdef CONFIG_WATCHDOG_NOWAYOUT MOD_INC_USE_COUNT; @@ -55,7 +55,6 @@ mcmisc_regs->cpuctrl0 = mc_ctrl0; indydog_ping(); - indydog_alive=1; printk("Started watchdog timer.\n"); return 0; } @@ -66,7 +65,6 @@ * Shut off the timer. * Lock it in if it's a module and we defined ...NOWAYOUT */ - lock_kernel(); #ifndef CONFIG_WATCHDOG_NOWAYOUT { u32 mc_ctrl0 = mcmisc_regs->cpuctrl0; @@ -75,8 +73,7 @@ printk("Stopped watchdog timer.\n"); } #endif - indydog_alive=0; - unlock_kernel(); + clear_bit(0,&indydog_alive); return 0; } diff -urN linux-2.4.19-pre5/drivers/char/joystick/a3d.c linux-2.4.19-pre6/drivers/char/joystick/a3d.c --- linux-2.4.19-pre5/drivers/char/joystick/a3d.c Wed Sep 12 15:34:06 2001 +++ linux-2.4.19-pre6/drivers/char/joystick/a3d.c Thu Apr 4 22:04:55 2002 @@ -190,7 +190,7 @@ int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons) { - struct a3d *a3d = gameport->private; + struct a3d *a3d = gameport->driver; int i; for (i = 0; i < 4; i++) axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1; @@ -205,7 +205,7 @@ int a3d_adc_open(struct gameport *gameport, int mode) { - struct a3d *a3d = gameport->private; + struct a3d *a3d = gameport->driver; if (mode != GAMEPORT_MODE_COOKED) return -1; if (!a3d->used++) @@ -219,7 +219,7 @@ static void a3d_adc_close(struct gameport *gameport) { - struct a3d *a3d = gameport->private; + struct a3d *a3d = gameport->driver; if (!--a3d->used) del_timer(&a3d->timer); } @@ -323,7 +323,7 @@ a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y); a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE); - a3d->adc.private = a3d; + a3d->adc.driver = a3d; a3d->adc.open = a3d_adc_open; a3d->adc.close = a3d_adc_close; a3d->adc.cooked_read = a3d_adc_cooked_read; diff -urN linux-2.4.19-pre5/drivers/char/joystick/lightning.c linux-2.4.19-pre6/drivers/char/joystick/lightning.c --- linux-2.4.19-pre5/drivers/char/joystick/lightning.c Wed Sep 12 15:34:06 2001 +++ linux-2.4.19-pre6/drivers/char/joystick/lightning.c Thu Apr 4 22:04:55 2002 @@ -77,7 +77,7 @@ static int l4_cooked_read(struct gameport *gameport, int *axes, int *buttons) { - struct l4 *l4 = gameport->private; + struct l4 *l4 = gameport->driver; unsigned char status; int i, result = -1; @@ -110,7 +110,7 @@ static int l4_open(struct gameport *gameport, int mode) { - struct l4 *l4 = gameport->private; + struct l4 *l4 = gameport->driver; if (l4->port != 0 && mode != GAMEPORT_MODE_COOKED) return -1; outb(L4_SELECT_ANALOG, L4_PORT); @@ -188,7 +188,7 @@ { int i, t; int cal[4]; - struct l4 *l4 = gameport->private; + struct l4 *l4 = gameport->driver; if (l4_getcal(l4->port, cal)) return -1; @@ -248,7 +248,7 @@ l4->port = i * 4 + j; gameport = &l4->gameport; - gameport->private = l4; + gameport->driver = l4; gameport->open = l4_open; gameport->cooked_read = l4_cooked_read; gameport->calibrate = l4_calibrate; diff -urN linux-2.4.19-pre5/drivers/char/joystick/pcigame.c linux-2.4.19-pre6/drivers/char/joystick/pcigame.c --- linux-2.4.19-pre5/drivers/char/joystick/pcigame.c Fri Dec 21 09:41:54 2001 +++ linux-2.4.19-pre6/drivers/char/joystick/pcigame.c Thu Apr 4 22:04:55 2002 @@ -76,19 +76,19 @@ static unsigned char pcigame_read(struct gameport *gameport) { - struct pcigame *pcigame = gameport->private; + struct pcigame *pcigame = gameport->driver; return readb(pcigame->base + pcigame->data->legacy); } static void pcigame_trigger(struct gameport *gameport) { - struct pcigame *pcigame = gameport->private; + struct pcigame *pcigame = gameport->driver; writeb(0xff, pcigame->base + pcigame->data->legacy); } static int pcigame_cooked_read(struct gameport *gameport, int *axes, int *buttons) { - struct pcigame *pcigame = gameport->private; + struct pcigame *pcigame = gameport->driver; int i; *buttons = (~readb(pcigame->base + pcigame->data->legacy) >> 4) & 0xf; @@ -103,7 +103,7 @@ static int pcigame_open(struct gameport *gameport, int mode) { - struct pcigame *pcigame = gameport->private; + struct pcigame *pcigame = gameport->driver; switch (mode) { case GAMEPORT_MODE_COOKED: @@ -135,7 +135,7 @@ pcigame->dev = dev; pci_set_drvdata(dev, pcigame); - pcigame->gameport.private = pcigame; + pcigame->gameport.driver = pcigame; pcigame->gameport.fuzz = 64; pcigame->gameport.read = pcigame_read; diff -urN linux-2.4.19-pre5/drivers/char/keyboard.c linux-2.4.19-pre6/drivers/char/keyboard.c --- linux-2.4.19-pre5/drivers/char/keyboard.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/keyboard.c Thu Apr 4 22:04:55 2002 @@ -67,15 +67,8 @@ extern void ctrl_alt_del(void); -DECLARE_WAIT_QUEUE_HEAD(keypress_wait); struct console; -int keyboard_wait_for_keypress(struct console *co) -{ - sleep_on(&keypress_wait); - return 0; -} - /* * global state includes the following, and various static variables * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next. @@ -339,7 +332,6 @@ if (forward_chars == fg_console+1){ kbd_forward_char (ch); } else { - wake_up(&keypress_wait); if (tty) { tty_insert_flip_char(tty, ch, 0); con_schedule_flip(tty); @@ -349,7 +341,6 @@ #else void put_queue(int ch) { - wake_up(&keypress_wait); if (tty) { tty_insert_flip_char(tty, ch, 0); con_schedule_flip(tty); @@ -359,7 +350,6 @@ static void puts_queue(char *cp) { - wake_up(&keypress_wait); if (!tty) return; diff -urN linux-2.4.19-pre5/drivers/char/sb1250_duart.c linux-2.4.19-pre6/drivers/char/sb1250_duart.c --- linux-2.4.19-pre5/drivers/char/sb1250_duart.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/sb1250_duart.c Thu Apr 4 22:04:55 2002 @@ -774,11 +774,6 @@ return MKDEV(TTY_MAJOR, 64 + c->index); } -static int ser_console_wait_key(struct console *cons) -{ - panic("ser_console_wait_key called"); -} - static int ser_console_setup(struct console *cons, char *str) { /* Initialize the transmitter */ @@ -791,7 +786,6 @@ name: "ttyS", write: ser_console_write, device: ser_console_device, - wait_key: ser_console_wait_key, setup: ser_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/char/serial.c linux-2.4.19-pre6/drivers/char/serial.c --- linux-2.4.19-pre5/drivers/char/serial.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/serial.c Thu Apr 4 22:04:55 2002 @@ -5833,35 +5833,6 @@ serial_out(info, UART_IER, ier); } -/* - * Receive character from the serial port - */ -static int serial_console_wait_key(struct console *co) -{ - static struct async_struct *info; - int ier, c; - - info = &async_sercons; - - /* - * First save the IER then disable the interrupts so - * that the real driver for the port does not get the - * character. - */ - ier = serial_in(info, UART_IER); - serial_out(info, UART_IER, 0x00); - - while ((serial_in(info, UART_LSR) & UART_LSR_DR) == 0); - c = serial_in(info, UART_RX); - - /* - * Restore the interrupts - */ - serial_out(info, UART_IER, ier); - - return c; -} - static kdev_t serial_console_device(struct console *c) { return MKDEV(TTY_MAJOR, 64 + c->index); @@ -6002,7 +5973,6 @@ name: "ttyS", write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/char/serial167.c linux-2.4.19-pre6/drivers/char/serial167.c --- linux-2.4.19-pre5/drivers/char/serial167.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/serial167.c Thu Apr 4 22:04:55 2002 @@ -2814,58 +2814,6 @@ restore_flags(flags); } -/* This is a hack; if there are multiple chars waiting in the chip we - * discard all but the last one, and return that. The cd2401 is not really - * designed to be driven in polled mode. - */ - -int serial167_console_wait_key(struct console *co) -{ - volatile unsigned char *base_addr = (u_char *)BASE_ADDR; - unsigned long flags; - volatile u_char sink; - u_char ier; - int port; - int keypress = 0; - - save_flags(flags); cli(); - - /* Ensure receiver is enabled! */ - - port = 0; - base_addr[CyCAR] = (u_char)port; - while (base_addr[CyCCR]) - ; - base_addr[CyCCR] = CyENB_RCVR; - ier = base_addr[CyIER]; - base_addr[CyIER] = CyRxData; - - while (!keypress) { - if (pcc2chip[PccSCCRICR] & 0x20) - { - /* We have an Rx int. Acknowledge it */ - sink = pcc2chip[PccRPIACKR]; - if ((base_addr[CyLICR] >> 2) == port) { - int cnt = base_addr[CyRFOC]; - while (cnt-- > 0) - { - keypress = base_addr[CyRDR]; - } - base_addr[CyREOIR] = 0; - } - else - base_addr[CyREOIR] = CyNOTRANS; - } - } - - base_addr[CyIER] = ier; - - restore_flags(flags); - - return keypress; -} - - static kdev_t serial167_console_device(struct console *c) { return MKDEV(TTY_MAJOR, 64 + c->index); @@ -2882,7 +2830,6 @@ name: "ttyS", write: serial167_console_write, device: serial167_console_device, - wait_key: serial167_console_wait_key, setup: serial167_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/char/serial_21285.c linux-2.4.19-pre6/drivers/char/serial_21285.c --- linux-2.4.19-pre5/drivers/char/serial_21285.c Thu Sep 13 15:21:32 2001 +++ linux-2.4.19-pre6/drivers/char/serial_21285.c Thu Apr 4 22:04:55 2002 @@ -389,17 +389,6 @@ enable_irq(IRQ_CONTX); } -static int rs285_console_wait_key(struct console *co) -{ - int c; - - disable_irq(IRQ_CONRX); - while (*CSR_UARTFLG & 0x10); - c = *CSR_UARTDR; - enable_irq(IRQ_CONRX); - return c; -} - static kdev_t rs285_console_device(struct console *c) { return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR); @@ -493,7 +482,6 @@ name: SERIAL_21285_NAME, write: rs285_console_write, device: rs285_console_device, - wait_key: rs285_console_wait_key, setup: rs285_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/char/serial_amba.c linux-2.4.19-pre6/drivers/char/serial_amba.c --- linux-2.4.19-pre5/drivers/char/serial_amba.c Sun Sep 16 21:23:14 2001 +++ linux-2.4.19-pre6/drivers/char/serial_amba.c Thu Apr 4 22:04:55 2002 @@ -1921,22 +1921,6 @@ UART_PUT_CR(port, old_cr); } -/* - * Receive character from the serial port - */ -static int ambauart_console_wait_key(struct console *co) -{ - struct amba_port *port = &amba_ports[co->index]; - unsigned int status; - int c; - - do { - status = UART_GET_FR(port); - } while (!UART_RX_DATA(status)); - c = UART_GET_CHAR(port); - return c; -} - static kdev_t ambauart_console_device(struct console *c) { return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index); @@ -2015,7 +1999,6 @@ read: ambauart_console_read, #endif device: ambauart_console_device, - wait_key: ambauart_console_wait_key, setup: ambauart_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/char/serial_tx3912.c linux-2.4.19-pre6/drivers/char/serial_tx3912.c --- linux-2.4.19-pre5/drivers/char/serial_tx3912.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/serial_tx3912.c Thu Apr 4 22:04:55 2002 @@ -752,21 +752,6 @@ outl(int2, TX3912_INT2_ENABLE); } -static int serial_console_wait_key(struct console *co) -{ - unsigned int int2, res; - - int2 = inl(TX3912_INT2_ENABLE); - outl(0, TX3912_INT2_ENABLE); - - while (!(inl(TX3912_UARTA_CTRL1) & TX3912_UART_CTRL1_RXHOLDFULL)); - res = inl(TX3912_UARTA_DATA); - udelay(10); - - outl(int2, TX3912_INT2_ENABLE); - return res; -} - static void serial_console_write(struct console *co, const char *s, unsigned count) { @@ -866,7 +851,6 @@ name: "ttyS", write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: -1 diff -urN linux-2.4.19-pre5/drivers/char/serial_txx927.c linux-2.4.19-pre6/drivers/char/serial_txx927.c --- linux-2.4.19-pre5/drivers/char/serial_txx927.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/serial_txx927.c Thu Apr 4 22:04:55 2002 @@ -2181,35 +2181,6 @@ sio_reg(info)->dicr = ier; } -/* - * Receive character from the serial port - */ -static int serial_console_wait_key(struct console *co) -{ - static struct async_struct *info = &async_sercons; - int ier; - int c; - - /* - * First save the IER then disable the interrupts so - * that the real driver for the port does not get the - * character. - */ - ier = sio_reg(info)->dicr; - sio_reg(info)->dicr = 0; - - while (sio_reg(info)->disr & TXx927_SIDISR_UVALID) - ; - c = sio_reg(info)->rfifo; - - /* - * Restore the interrupts - */ - sio_reg(info)->dicr = ier; - - return c; -} - static kdev_t serial_console_device(struct console *c) { return MKDEV(TXX927_TTY_MAJOR, TXX927_TTY_MINOR_START + c->index); @@ -2343,7 +2314,6 @@ name: TXX927_TTY_NAME, write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/char/sh-sci.c linux-2.4.19-pre6/drivers/char/sh-sci.c --- linux-2.4.19-pre5/drivers/char/sh-sci.c Mon Feb 25 11:37:57 2002 +++ linux-2.4.19-pre6/drivers/char/sh-sci.c Thu Apr 4 22:04:55 2002 @@ -1181,15 +1181,6 @@ put_string(sercons_port, s, count); } -/* - * Receive character from the serial port - */ -static int serial_console_wait_key(struct console *co) -{ - /* Not implemented yet */ - return 0; -} - static kdev_t serial_console_device(struct console *c) { return MKDEV(SCI_MAJOR, SCI_MINOR_START + c->index); @@ -1273,7 +1264,6 @@ name: "ttySC", write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/char/sonypi.c linux-2.4.19-pre6/drivers/char/sonypi.c --- linux-2.4.19-pre5/drivers/char/sonypi.c Mon Feb 25 11:37:57 2002 +++ linux-2.4.19-pre6/drivers/char/sonypi.c Thu Apr 4 22:04:55 2002 @@ -50,6 +50,7 @@ static int fnkeyinit; /* = 0 */ static int camera; /* = 0 */ static int compat; /* = 0 */ +static int nojogdial; /* = 0 */ /* Inits the queue */ static inline void sonypi_initq(void) { @@ -310,24 +311,28 @@ int i; u8 sonypi_jogger_ev, sonypi_fnkey_ev; u8 sonypi_capture_ev, sonypi_bluetooth_ev; + u8 sonypi_pkey_ev; if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) { sonypi_jogger_ev = SONYPI_TYPE2_JOGGER_EV; sonypi_fnkey_ev = SONYPI_TYPE2_FNKEY_EV; sonypi_capture_ev = SONYPI_TYPE2_CAPTURE_EV; sonypi_bluetooth_ev = SONYPI_TYPE2_BLUETOOTH_EV; + sonypi_pkey_ev = nojogdial ? SONYPI_TYPE2_PKEY_EV + : SONYPI_TYPE1_PKEY_EV; } else { sonypi_jogger_ev = SONYPI_TYPE1_JOGGER_EV; sonypi_fnkey_ev = SONYPI_TYPE1_FNKEY_EV; sonypi_capture_ev = SONYPI_TYPE1_CAPTURE_EV; sonypi_bluetooth_ev = SONYPI_TYPE1_BLUETOOTH_EV; + sonypi_pkey_ev = SONYPI_TYPE1_PKEY_EV; } v1 = inb_p(sonypi_device.ioport1); v2 = inb_p(sonypi_device.ioport2); - if ((v2 & SONYPI_TYPE1_PKEY_EV) == SONYPI_TYPE1_PKEY_EV) { + if ((v2 & sonypi_pkey_ev) == sonypi_pkey_ev) { for (i = 0; sonypi_pkeyev[i].event; i++) if (sonypi_pkeyev[i].data == v1) { event = sonypi_pkeyev[i].event; @@ -713,11 +718,12 @@ SONYPI_DRIVER_MAJORVERSION, SONYPI_DRIVER_MINORVERSION); printk(KERN_INFO "sonypi: detected %s model, " - "camera = %s, compat = %s\n", + "camera = %s, compat = %s, nojogdial = %s\n", (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ? "type1" : "type2", camera ? "on" : "off", - compat ? "on" : "off"); + compat ? "on" : "off", + nojogdial ? "on" : "off"); printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n", sonypi_device.irq, sonypi_device.ioport1, sonypi_device.ioport2); @@ -791,6 +797,9 @@ if (ints[0] == 4) goto out; compat = ints[5]; + if (ints[0] == 5) + goto out; + nojogdial = ints[6]; out: return 1; } @@ -817,5 +826,7 @@ MODULE_PARM_DESC(camera, "set this if you have a MotionEye camera (PictureBook series)"); MODULE_PARM(compat,"i"); MODULE_PARM_DESC(compat, "set this if you want to enable backward compatibility mode"); +MODULE_PARM(nojogdial, "i"); +MODULE_PARM_DESC(nojogdial, "set this if you have a Vaio without a jogdial (like the fx series)"); EXPORT_SYMBOL(sonypi_camera_command); diff -urN linux-2.4.19-pre5/drivers/char/sonypi.h linux-2.4.19-pre6/drivers/char/sonypi.h --- linux-2.4.19-pre5/drivers/char/sonypi.h Mon Feb 25 11:37:57 2002 +++ linux-2.4.19-pre6/drivers/char/sonypi.h Thu Apr 4 22:04:55 2002 @@ -35,7 +35,7 @@ #ifdef __KERNEL__ #define SONYPI_DRIVER_MAJORVERSION 1 -#define SONYPI_DRIVER_MINORVERSION 10 +#define SONYPI_DRIVER_MINORVERSION 11 #include #include @@ -141,6 +141,7 @@ #define SONYPI_TYPE1_BLUETOOTH_EV 0x30 #define SONYPI_TYPE2_BLUETOOTH_EV 0x08 #define SONYPI_TYPE1_PKEY_EV 0x40 +#define SONYPI_TYPE2_PKEY_EV 0x08 #define SONYPI_BACK_EV 0x08 #define SONYPI_LID_EV 0x38 diff -urN linux-2.4.19-pre5/drivers/char/tty_io.c linux-2.4.19-pre6/drivers/char/tty_io.c --- linux-2.4.19-pre5/drivers/char/tty_io.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/tty_io.c Thu Apr 4 22:04:55 2002 @@ -603,12 +603,6 @@ read_unlock(&tasklist_lock); } -void wait_for_keypress(void) -{ - struct console *c = console_drivers; - if (c) c->wait_key(c); -} - void stop_tty(struct tty_struct *tty) { if (tty->stopped) diff -urN linux-2.4.19-pre5/drivers/char/vme_scc.c linux-2.4.19-pre6/drivers/char/vme_scc.c --- linux-2.4.19-pre5/drivers/char/vme_scc.c Thu Apr 4 22:04:21 2002 +++ linux-2.4.19-pre6/drivers/char/vme_scc.c Thu Apr 4 22:04:55 2002 @@ -1082,41 +1082,6 @@ restore_flags(flags); } - -static int scc_console_wait_key(struct console *co) -{ - unsigned long flags; - volatile char *p = NULL; - int c; - -#ifdef CONFIG_MVME147_SCC - if (MACH_IS_MVME147) - p = (volatile char *)M147_SCC_A_ADDR; -#endif -#ifdef CONFIG_MVME162_SCC - if (MACH_IS_MVME16x) - p = (volatile char *)MVME_SCC_A_ADDR; -#endif -#ifdef CONFIG_BVME6000_SCC - if (MACH_IS_BVME6000) - p = (volatile char *)BVME_SCC_A_ADDR; -#endif - - save_flags(flags); - cli(); - - /* wait for rx buf filled */ - while ((*p & 0x01) == 0) - ; - - *p = 8; - scc_delay(); - c = *p; - restore_flags(flags); - return c; -} - - static kdev_t scc_console_device(struct console *c) { return MKDEV(TTY_MAJOR, SCC_MINOR_BASE + c->index); @@ -1133,7 +1098,6 @@ name: "ttyS", write: scc_console_write, device: scc_console_device, - wait_key: scc_console_wait_key, setup: scc_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/char/wdt285.c linux-2.4.19-pre6/drivers/char/wdt285.c --- linux-2.4.19-pre5/drivers/char/wdt285.c Mon Feb 25 11:37:57 2002 +++ linux-2.4.19-pre6/drivers/char/wdt285.c Thu Apr 4 22:04:55 2002 @@ -138,11 +138,9 @@ default: return -ENOTTY; case WDIOC_GETSUPPORT: - i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct watchdog_info)); - if (i) - return i; - else - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)); + if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + return -EFAULT; + return 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0,(int *)arg); diff -urN linux-2.4.19-pre5/drivers/ide/hptraid.c linux-2.4.19-pre6/drivers/ide/hptraid.c --- linux-2.4.19-pre5/drivers/ide/hptraid.c Mon Oct 15 13:27:42 2001 +++ linux-2.4.19-pre6/drivers/ide/hptraid.c Thu Apr 4 22:04:56 2002 @@ -123,13 +123,8 @@ return 0; } - case BLKROSET: - case BLKROGET: - case BLKSSZGET: - return blk_ioctl(inode->i_rdev, cmd, arg); - default: - return -EINVAL; + return blk_ioctl(inode->i_rdev, cmd, arg); }; return 0; @@ -366,7 +361,11 @@ probedisk(IDE2_MAJOR, 64, device); probedisk(IDE3_MAJOR, 0, device); probedisk(IDE3_MAJOR, 64, device); - + probedisk(IDE4_MAJOR, 0, device); + probedisk(IDE4_MAJOR, 64, device); + probedisk(IDE5_MAJOR, 0, device); + probedisk(IDE5_MAJOR, 64, device); + fill_cutoff(device); /* Initialize the gendisk structure */ diff -urN linux-2.4.19-pre5/drivers/ide/sis5513.c linux-2.4.19-pre6/drivers/ide/sis5513.c --- linux-2.4.19-pre5/drivers/ide/sis5513.c Thu Apr 4 22:04:22 2002 +++ linux-2.4.19-pre6/drivers/ide/sis5513.c Thu Apr 4 22:04:56 2002 @@ -1,12 +1,19 @@ /* - * linux/drivers/ide/sis5513.c Version 0.13 February 14, 2002 + * linux/drivers/ide/sis5513.c Version 0.13 March 6, 2002 * * Copyright (C) 1999-2000 Andre Hedrick * Copyright (C) 2002 Lionel Bouton , Maintainer * May be copied or modified under the terms of the GNU General Public License * - * Thanks to SIS Taiwan for direct support and hardware. - * Thanks to Daniela Engert for ATA100 support advice. + * + * Thanks : + * + * SiS Taiwan : for direct support and hardware. + * Daniela Engert : for initial ATA100 advices and numerous others. + * John Fremlin, Manfred Spraul : + * for checking code correctness, providing patches. + * + * * Original tests and design on the SiS620/5513 chipset. * ATA100 tests and design on the SiS735/5513 chipset. * ATA16/33 design from specs @@ -14,11 +21,11 @@ /* * TODO: - * - Are there pre-ATA_16 SiS chips ? -> tune init code for them - * or remove ATA_00 defines * - Get ridden of SisHostChipInfo[] completness dependancy. * - Get ATA-133 datasheets, implement ATA-133 init code. - * - Check latency timer init correctness. + * - Study drivers/ide/ide-timing.h. + * - Are there pre-ATA_16 SiS5513 chips ? -> tune init code for them + * or remove ATA_00 define * - More checks in the config registers (force values instead of * relying on the BIOS setting them correctly). * - Further optimisations ? @@ -45,62 +52,45 @@ #include "ide_modes.h" -#define DEBUG -/* if BROKEN_LEVEL is defined it limits the DMA mode +/* When DEBUG is defined it outputs initial PCI config register + values and changes made to them by the driver */ +// #define DEBUG +/* When BROKEN_LEVEL is defined it limits the DMA mode at boot time to its value */ // #define BROKEN_LEVEL XFER_SW_DMA_0 #define DISPLAY_SIS_TIMINGS /* Miscellaneaous flags */ #define SIS5513_LATENCY 0x01 -/* ATA transfer mode capabilities */ + +/* registers layout and init values are chipset family dependant */ +/* 1/ define families */ #define ATA_00 0x00 #define ATA_16 0x01 #define ATA_33 0x02 #define ATA_66 0x03 -#define ATA_100 0x04 -#define ATA_133 0x05 - -static unsigned char dma_capability = 0x00; +#define ATA_100a 0x04 // SiS730 is ATA100 with ATA66 layout +#define ATA_100 0x05 +#define ATA_133 0x06 +/* 2/ variable holding the controller chipset family value */ +static unsigned char chipset_family; /* * Debug code: following IDE config registers' changes */ #ifdef DEBUG -/* Copy of IDE Config registers 0x00 -> 0x58 +/* Copy of IDE Config registers 0x00 -> 0x57 Fewer might be used depending on the actual chipset */ -static unsigned char ide_regs_copy[] = { - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0 -}; +static unsigned char ide_regs_copy[0x58]; static byte sis5513_max_config_register(void) { - switch(dma_capability) { + switch(chipset_family) { case ATA_00: case ATA_16: return 0x4f; case ATA_33: return 0x52; case ATA_66: + case ATA_100a: case ATA_100: case ATA_133: default: return 0x57; @@ -145,7 +135,7 @@ printk(" %0#x:%0#x", reg, ide_regs_copy[reg]); } -/* Print valuable registers (for ATA100) */ +/* Print valuable registers */ static void sis5513_print_registers(struct pci_dev* dev, char* marker) { int i; byte max = sis5513_max_config_register(); @@ -176,14 +166,14 @@ static const struct { const char *name; unsigned short host_id; - unsigned char dma_capability; + unsigned char chipset_family; unsigned char flags; } SiSHostChipInfo[] = { { "SiS750", PCI_DEVICE_ID_SI_750, ATA_100, SIS5513_LATENCY }, { "SiS745", PCI_DEVICE_ID_SI_745, ATA_100, SIS5513_LATENCY }, { "SiS740", PCI_DEVICE_ID_SI_740, ATA_100, SIS5513_LATENCY }, { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100, SIS5513_LATENCY }, - { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100, SIS5513_LATENCY }, + { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a, SIS5513_LATENCY }, { "SiS650", PCI_DEVICE_ID_SI_650, ATA_100, SIS5513_LATENCY }, { "SiS645", PCI_DEVICE_ID_SI_645, ATA_100, SIS5513_LATENCY }, { "SiS635", PCI_DEVICE_ID_SI_635, ATA_100, SIS5513_LATENCY }, @@ -202,14 +192,15 @@ /* Cycle time bits and values vary accross chip dma capabilities These three arrays hold the register layout and the values to set. - Indexed by dma_capability and (dma_mode - XFER_UDMA_0) */ -static byte cycle_time_offset[] = {0,0,5,4,0,0}; -static byte cycle_time_range[] = {0,0,2,3,4,4}; + Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */ +static byte cycle_time_offset[] = {0,0,5,4,4,0,0}; +static byte cycle_time_range[] = {0,0,2,3,3,4,4}; static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = { {0,0,0,0,0,0}, /* no udma */ {0,0,0,0,0,0}, /* no udma */ {3,2,1,0,0,0}, {7,5,3,2,1,0}, + {7,5,3,2,1,0}, {11,7,5,4,2,1}, {0,0,0,0,0,0} /* not yet known, ask SiS */ }; @@ -283,23 +274,25 @@ pci_read_config_byte(bmide_dev, 0x45+2*pos, ®11); /* UDMA */ - if (dma_capability >= ATA_33) { + if (chipset_family >= ATA_33) { p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", (reg01 & 0x80) ? "Enabled" : "Disabled", (reg11 & 0x80) ? "Enabled" : "Disabled"); p += sprintf(p, " UDMA Cycle Time "); - switch(dma_capability) { + switch(chipset_family) { case ATA_33: p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break; - case ATA_66: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break; + case ATA_66: + case ATA_100a: p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break; case ATA_100: p += sprintf(p, cycle_time[reg01 & 0x0F]); break; case ATA_133: default: p += sprintf(p, "133+ ?"); break; } p += sprintf(p, " \t UDMA Cycle Time "); - switch(dma_capability) { + switch(chipset_family) { case ATA_33: p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break; - case ATA_66: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break; + case ATA_66: + case ATA_100a: p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break; case ATA_100: p += sprintf(p, cycle_time[reg11 & 0x0F]); break; case ATA_133: default: p += sprintf(p, "133+ ?"); break; @@ -309,21 +302,23 @@ /* Data Active */ p += sprintf(p, " Data Active Time "); - switch(dma_capability) { + switch(chipset_family) { case ATA_00: case ATA_16: /* confirmed */ case ATA_33: - case ATA_66: p += sprintf(p, active_time[reg01 & 0x07]); break; + case ATA_66: + case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break; case ATA_100: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break; case ATA_133: default: p += sprintf(p, "133+ ?"); break; } p += sprintf(p, " \t Data Active Time "); - switch(dma_capability) { + switch(chipset_family) { case ATA_00: case ATA_16: case ATA_33: - case ATA_66: p += sprintf(p, active_time[reg11 & 0x07]); break; + case ATA_66: + case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break; case ATA_100: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break; case ATA_133: default: p += sprintf(p, "133+ ?"); break; @@ -356,11 +351,12 @@ u16 reg2, reg3; p += sprintf(p, "\nSiS 5513 "); - switch(dma_capability) { + switch(chipset_family) { case ATA_00: p += sprintf(p, "Unknown???"); break; case ATA_16: p += sprintf(p, "DMA 16"); break; case ATA_33: p += sprintf(p, "Ultra 33"); break; case ATA_66: p += sprintf(p, "Ultra 66"); break; + case ATA_100a: case ATA_100: p += sprintf(p, "Ultra 100"); break; case ATA_133: default: p+= sprintf(p, "Ultra 133+"); break; @@ -371,7 +367,7 @@ /* Status */ pci_read_config_byte(bmide_dev, 0x4a, ®); p += sprintf(p, "Channel Status: "); - if (dma_capability < ATA_66) { + if (chipset_family < ATA_66) { p += sprintf(p, "%s \t \t \t \t %s\n", (reg & 0x04) ? "On" : "Off", (reg & 0x02) ? "On" : "Off"); @@ -388,7 +384,7 @@ (reg & 0x04) ? "Native" : "Compatible"); /* 80-pin cable ? */ - if (dma_capability > ATA_33) { + if (chipset_family > ATA_33) { pci_read_config_byte(bmide_dev, 0x48, ®); p += sprintf(p, "Cable Type: %s \t \t \t %s\n", (reg & 0x10) ? cable_type[1] : cable_type[0], @@ -489,8 +485,8 @@ default: return; } - /* register layout changed with ATA100 chips */ - if (dma_capability < ATA_100) { + /* register layout changed with newer ATA100 chips */ + if (chipset_family < ATA_100) { pci_read_config_byte(dev, drive_pci, &test1); pci_read_config_byte(dev, drive_pci+1, &test2); @@ -570,7 +566,7 @@ pci_read_config_byte(dev, drive_pci+1, ®); /* Disable UDMA bit for non UDMA modes on UDMA chips */ - if ((speed < XFER_UDMA_0) && (dma_capability > ATA_16)) { + if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) { reg &= 0x7F; pci_write_config_byte(dev, drive_pci+1, reg); } @@ -584,12 +580,14 @@ case XFER_UDMA_2: case XFER_UDMA_1: case XFER_UDMA_0: + /* Force the UDMA bit on if we want to use UDMA */ + reg |= 0x80; /* clean reg cycle time bits */ - reg &= ~((0xFF >> (8 - cycle_time_range[dma_capability])) - << cycle_time_offset[dma_capability]); + reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family])) + << cycle_time_offset[chipset_family]); /* set reg cycle time bits */ - reg |= cycle_time_value[dma_capability-ATA_00][speed-XFER_UDMA_0] - << cycle_time_offset[dma_capability]; + reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0] + << cycle_time_offset[chipset_family]; pci_write_config_byte(dev, drive_pci+1, reg); break; case XFER_MW_DMA_2: @@ -638,17 +636,17 @@ drive->dn, ultra); #endif - if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (dma_capability >= ATA_100)) + if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (chipset_family >= ATA_100a)) speed = XFER_UDMA_5; - else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (dma_capability >= ATA_66)) + else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (chipset_family >= ATA_66)) speed = XFER_UDMA_4; - else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (dma_capability >= ATA_66)) + else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (chipset_family >= ATA_66)) speed = XFER_UDMA_3; - else if ((id->dma_ultra & 0x0004) && ultra && (dma_capability >= ATA_33)) + else if ((id->dma_ultra & 0x0004) && ultra && (chipset_family >= ATA_33)) speed = XFER_UDMA_2; - else if ((id->dma_ultra & 0x0002) && ultra && (dma_capability >= ATA_33)) + else if ((id->dma_ultra & 0x0002) && ultra && (chipset_family >= ATA_33)) speed = XFER_UDMA_1; - else if ((id->dma_ultra & 0x0001) && ultra && (dma_capability >= ATA_33)) + else if ((id->dma_ultra & 0x0001) && ultra && (chipset_family >= ATA_33)) speed = XFER_UDMA_0; else if (id->dma_mword & 0x0004) speed = XFER_MW_DMA_2; @@ -681,6 +679,8 @@ struct hd_driveid *id = drive->id; ide_dma_action_t dma_func = ide_dma_off_quietly; + (void) config_chipset_for_pio(drive, 5); + if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { @@ -745,10 +745,6 @@ struct pci_dev *host; int i = 0; -#ifdef DEBUG - sis5513_print_registers(dev, "pci_init_sis5513 start"); -#endif - /* Find the chip */ for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !host_dev; i++) { host = pci_find_device (PCI_VENDOR_ID_SI, @@ -758,12 +754,16 @@ continue; host_dev = host; - dma_capability = SiSHostChipInfo[i].dma_capability; + chipset_family = SiSHostChipInfo[i].chipset_family; printk(SiSHostChipInfo[i].name); printk("\n"); +#ifdef DEBUG + sis5513_print_registers(dev, "pci_init_sis5513 start"); +#endif + if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) { - byte latency = (dma_capability == ATA_100)? 0x80 : 0x10; /* Lacking specs */ + byte latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */ pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency); } } @@ -773,7 +773,7 @@ 2/ tell old chips to allow per drive IDE timings */ if (host_dev) { byte reg; - switch(dma_capability) { + switch(chipset_family) { case ATA_133: case ATA_100: /* Set compatibility bit */ @@ -782,6 +782,7 @@ pci_write_config_byte(dev, 0x49, reg|0x01); } break; + case ATA_100a: case ATA_66: /* On ATA_66 chips the bit was elsewhere */ pci_read_config_byte(dev, 0x52, ®); @@ -827,7 +828,7 @@ byte mask = hwif->channel ? 0x20 : 0x10; pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); - if (dma_capability >= ATA_66) { + if (chipset_family >= ATA_66) { ata66 = (reg48h & mask) ? 0 : 1; } return ata66; @@ -846,7 +847,7 @@ if (host_dev) { #ifdef CONFIG_BLK_DEV_IDEDMA - if (dma_capability > ATA_16) { + if (chipset_family > ATA_16) { hwif->autodma = noautodma ? 0 : 1; hwif->dmaproc = &sis5513_dmaproc; } else { diff -urN linux-2.4.19-pre5/drivers/input/joydev.c linux-2.4.19-pre6/drivers/input/joydev.c --- linux-2.4.19-pre5/drivers/input/joydev.c Sun Sep 30 12:26:05 2001 +++ linux-2.4.19-pre6/drivers/input/joydev.c Thu Apr 4 22:04:57 2002 @@ -411,7 +411,7 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev) { struct joydev *joydev; - int i, j, minor; + int i, j, t, minor; if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) && (test_bit(ABS_X, dev->absbit) || test_bit(ABS_Y, dev->absbit)) && @@ -470,8 +470,10 @@ joydev->corr[i].prec = dev->absfuzz[j]; joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j]; joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j]; - joydev->corr[i].coef[2] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]); - joydev->corr[i].coef[3] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]); + if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]))) + continue; + joydev->corr[i].coef[2] = (1 << 29) / t; + joydev->corr[i].coef[3] = (1 << 29) / t; joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); } diff -urN linux-2.4.19-pre5/drivers/macintosh/mac_keyb.c linux-2.4.19-pre6/drivers/macintosh/mac_keyb.c --- linux-2.4.19-pre5/drivers/macintosh/mac_keyb.c Tue Sep 18 14:23:14 2001 +++ linux-2.4.19-pre6/drivers/macintosh/mac_keyb.c Thu Apr 4 22:04:57 2002 @@ -256,7 +256,6 @@ #endif extern struct kbd_struct kbd_table[]; -extern wait_queue_head_t keypress_wait; extern void handle_scancode(unsigned char, int); @@ -423,7 +422,6 @@ struct tty_struct *tty; tty = console_driver.table? console_driver.table[fg_console]: NULL; - wake_up(&keypress_wait); if (tty) { tty_insert_flip_char(tty, ch, 0); con_schedule_flip(tty); diff -urN linux-2.4.19-pre5/drivers/macintosh/macserial.c linux-2.4.19-pre6/drivers/macintosh/macserial.c --- linux-2.4.19-pre5/drivers/macintosh/macserial.c Mon Feb 25 11:37:58 2002 +++ linux-2.4.19-pre6/drivers/macintosh/macserial.c Thu Apr 4 22:04:57 2002 @@ -2866,30 +2866,6 @@ /* Don't disable the transmitter. */ } -/* - * Receive character from the serial port - */ -static int serial_console_wait_key(struct console *co) -{ - struct mac_serial *info = zs_soft + co->index; - int val; - - /* Turn of interrupts and enable the transmitter. */ - write_zsreg(info->zs_channel, R1, info->curregs[1] & ~INT_ALL_Rx); - write_zsreg(info->zs_channel, R3, info->curregs[3] | RxENABLE); - - /* Wait for something in the receive buffer. */ - while((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) - eieio(); - val = read_zsdata(info->zs_channel); - - /* Restore the values in the registers. */ - write_zsreg(info->zs_channel, R1, info->curregs[1]); - write_zsreg(info->zs_channel, R3, info->curregs[3]); - - return val; -} - static kdev_t serial_console_device(struct console *c) { return MKDEV(TTY_MAJOR, 64 + c->index); @@ -3080,7 +3056,6 @@ name: "ttyS", write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/md/md.c linux-2.4.19-pre6/drivers/md/md.c --- linux-2.4.19-pre5/drivers/md/md.c Mon Feb 25 11:37:58 2002 +++ linux-2.4.19-pre6/drivers/md/md.c Thu Apr 4 22:04:58 2002 @@ -3486,7 +3486,7 @@ * this also signals 'finished resyncing' to md_stop */ out: - wait_event(mddev->recovery_wait, atomic_read(&mddev->recovery_active)==0); + wait_disk_event(mddev->recovery_wait, atomic_read(&mddev->recovery_active)==0); up(&mddev->resync_sem); out_nolock: mddev->curr_resync = 0; diff -urN linux-2.4.19-pre5/drivers/md/raid1.c linux-2.4.19-pre6/drivers/md/raid1.c --- linux-2.4.19-pre5/drivers/md/raid1.c Mon Feb 25 11:37:58 2002 +++ linux-2.4.19-pre6/drivers/md/raid1.c Thu Apr 4 22:04:58 2002 @@ -269,8 +269,9 @@ static int raid1_grow_buffers (raid1_conf_t *conf, int cnt) { int i = 0; + struct raid1_bh *head = NULL, **tail; + tail = &head; - md_spin_lock_irq(&conf->device_lock); while (i < cnt) { struct raid1_bh *r1_bh; struct page *page; @@ -287,24 +288,36 @@ memset(r1_bh, 0, sizeof(*r1_bh)); r1_bh->bh_req.b_page = page; r1_bh->bh_req.b_data = page_address(page); - r1_bh->next_r1 = conf->freebuf; - conf->freebuf = r1_bh; + *tail = r1_bh; + r1_bh->next_r1 = NULL; + tail = & r1_bh->next_r1; i++; } + /* this lock probably isn't needed, as at the time when + * we are allocating buffers, nobody else will be touching the + * freebuf list. But it doesn't hurt.... + */ + md_spin_lock_irq(&conf->device_lock); + *tail = conf->freebuf; + conf->freebuf = head; md_spin_unlock_irq(&conf->device_lock); return i; } static void raid1_shrink_buffers (raid1_conf_t *conf) { + struct raid1_bh *head; md_spin_lock_irq(&conf->device_lock); - while (conf->freebuf) { - struct raid1_bh *r1_bh = conf->freebuf; - conf->freebuf = r1_bh->next_r1; + head = conf->freebuf; + conf->freebuf = NULL; + md_spin_unlock_irq(&conf->device_lock); + + while (head) { + struct raid1_bh *r1_bh = head; + head = r1_bh->next_r1; __free_page(r1_bh->bh_req.b_page); kfree(r1_bh); } - md_spin_unlock_irq(&conf->device_lock); } static int raid1_map (mddev_t *mddev, kdev_t *rdev) @@ -825,7 +838,7 @@ conf->start_ready = conf->start_pending; wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock); conf->start_active =conf->start_ready = conf->start_pending = conf->start_future; - conf->start_future = mddev->sb->size+1; + conf->start_future = (mddev->sb->size<<1)+1; conf->cnt_pending = conf->cnt_future; conf->cnt_future = 0; conf->phase = conf->phase ^1; @@ -849,6 +862,14 @@ mdk_rdev_t *spare_rdev, *failed_rdev; print_raid1_conf(conf); + + switch (state) { + case DISKOP_SPARE_ACTIVE: + case DISKOP_SPARE_INACTIVE: + /* need to wait for pending sync io before locking device */ + close_sync(conf); + } + md_spin_lock_irq(&conf->device_lock); /* * find the disk ... @@ -951,7 +972,11 @@ * Deactivate a spare disk: */ case DISKOP_SPARE_INACTIVE: - close_sync(conf); + if (conf->start_future > 0) { + MD_BUG(); + err = -EBUSY; + break; + } sdisk = conf->mirrors + spare_disk; sdisk->operational = 0; sdisk->write_only = 0; @@ -964,7 +989,11 @@ * property) */ case DISKOP_SPARE_ACTIVE: - close_sync(conf); + if (conf->start_future > 0) { + MD_BUG(); + err = -EBUSY; + break; + } sdisk = conf->mirrors + spare_disk; fdisk = conf->mirrors + failed_disk; @@ -1328,23 +1357,25 @@ int bsize; int disk; int block_nr; + int buffs; + if (!sector_nr) { + /* we want enough buffers to hold twice the window of 128*/ + buffs = 128 *2 / (PAGE_SIZE>>9); + buffs = raid1_grow_buffers(conf, buffs); + if (buffs < 2) + goto nomem; + conf->window = buffs*(PAGE_SIZE>>9)/2; + } spin_lock_irq(&conf->segment_lock); if (!sector_nr) { /* initialize ...*/ - int buffs; conf->start_active = 0; conf->start_ready = 0; conf->start_pending = 0; conf->start_future = 0; conf->phase = 0; - /* we want enough buffers to hold twice the window of 128*/ - buffs = 128 *2 / (PAGE_SIZE>>9); - buffs = raid1_grow_buffers(conf, buffs); - if (buffs < 2) - goto nomem; - conf->window = buffs*(PAGE_SIZE>>9)/2; conf->cnt_future += conf->cnt_done+conf->cnt_pending; conf->cnt_done = conf->cnt_pending = 0; if (conf->cnt_ready || conf->cnt_active) @@ -1429,7 +1460,6 @@ nomem: raid1_shrink_buffers(conf); - spin_unlock_irq(&conf->segment_lock); return -ENOMEM; } diff -urN linux-2.4.19-pre5/drivers/net/tlan.c linux-2.4.19-pre6/drivers/net/tlan.c --- linux-2.4.19-pre5/drivers/net/tlan.c Fri Dec 21 09:41:54 2001 +++ linux-2.4.19-pre6/drivers/net/tlan.c Thu Apr 4 22:04:59 2002 @@ -8,6 +8,7 @@ * (C) 1997-1998 Caldera, Inc. * (C) 1998 James Banks * (C) 1999-2001 Torben Mathiasen + * (C) 2002 Samuel Chessman * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -158,6 +159,11 @@ * * v1.14a Jan 6, 2001 - Minor adjustments (spinlocks, etc.) * + * Samuel Chessman New Maintainer! + * + * v1.15 Apr 4, 2002 - Correct operation when aui=1 to be + * 10T half duplex no loopback + * Thanks to Gunnar Eikman *******************************************************************************/ @@ -188,7 +194,7 @@ static int speed[MAX_TLAN_BOARDS]; static int boards_found; -MODULE_AUTHOR("Maintainer: Torben Mathiasen "); +MODULE_AUTHOR("Maintainer: Samuel Chessman "); MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters"); MODULE_LICENSE("GPL"); @@ -213,7 +219,7 @@ static int bbuf; static u8 *TLanPadBuffer; static char TLanSignature[] = "TLAN"; -static const char tlan_banner[] = "ThunderLAN driver v1.14a\n"; +static const char tlan_banner[] = "ThunderLAN driver v1.15\n"; static int tlan_have_pci; static int tlan_have_eisa; @@ -2603,12 +2609,12 @@ TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN ); return; } else if ( priv->phyNum == 0 ) { + control = 0; TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl ); if ( priv->aui ) { tctl |= TLAN_TC_AUISEL; } else { tctl &= ~TLAN_TC_AUISEL; - control = 0; if ( priv->duplex == TLAN_DUPLEX_FULL ) { control |= MII_GC_DUPLEX; priv->tlanFullDuplex = TRUE; @@ -2616,8 +2622,8 @@ if ( priv->speed == TLAN_SPEED_100 ) { control |= MII_GC_SPEEDSEL; } - TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, control ); } + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, control ); TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl ); } diff -urN linux-2.4.19-pre5/drivers/pci/pci.c linux-2.4.19-pre6/drivers/pci/pci.c --- linux-2.4.19-pre5/drivers/pci/pci.c Thu Apr 4 22:04:23 2002 +++ linux-2.4.19-pre6/drivers/pci/pci.c Thu Apr 4 22:05:00 2002 @@ -889,7 +889,7 @@ } /** - * pci_set_mwi - enables memory-write-validate PCI transaction + * pci_set_mwi - enables memory-write-invalidate PCI transaction * @dev: the PCI device for which MWI is enabled * * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND, diff -urN linux-2.4.19-pre5/drivers/pci/setup-bus.c linux-2.4.19-pre6/drivers/pci/setup-bus.c --- linux-2.4.19-pre5/drivers/pci/setup-bus.c Thu Oct 4 18:47:08 2001 +++ linux-2.4.19-pre6/drivers/pci/setup-bus.c Thu Apr 4 22:05:00 2002 @@ -201,6 +201,16 @@ b->resource[0]->end = ranges->io_end - 1; b->resource[1]->end = ranges->mem_end - 1; + /* Add bridge resources to the resource tree. */ + if (b->resource[0]->end > b->resource[0]->start && + request_resource(bus->resource[0], b->resource[0]) < 0) + printk(KERN_ERR "PCI: failed to reserve IO " + "for bus %d\n", b->number); + if (b->resource[1]->end > b->resource[1]->start && + request_resource(bus->resource[1], b->resource[1]) < 0) + printk(KERN_ERR "PCI: failed to reserve MEM " + "for bus %d\n", b->number); + pci_setup_bridge(b); } } diff -urN linux-2.4.19-pre5/drivers/s390/char/tuball.c linux-2.4.19-pre6/drivers/s390/char/tuball.c --- linux-2.4.19-pre5/drivers/s390/char/tuball.c Thu Oct 11 09:43:29 2001 +++ linux-2.4.19-pre6/drivers/s390/char/tuball.c Thu Apr 4 22:05:01 2002 @@ -84,7 +84,6 @@ tub3270_con_write, /* write */ NULL, /* read */ tub3270_con_device, /* device */ - NULL, /* wait_key */ tub3270_con_unblank, /* unblank */ NULL, /* setup */ CON_PRINTBUFFER, /* flags */ diff -urN linux-2.4.19-pre5/drivers/sbus/char/sab82532.c linux-2.4.19-pre6/drivers/sbus/char/sab82532.c --- linux-2.4.19-pre5/drivers/sbus/char/sab82532.c Wed Oct 17 14:16:39 2001 +++ linux-2.4.19-pre6/drivers/sbus/char/sab82532.c Thu Apr 4 22:05:03 2002 @@ -361,10 +361,6 @@ writeb(SAB82532_CMDR_RMC, &info->regs->w.cmdr); } -#ifdef CONFIG_SERIAL_CONSOLE - if (info->is_console) - wake_up(&keypress_wait); -#endif if (!tty) return; @@ -2541,13 +2537,6 @@ sab82532_tec_wait(info); } -static int -sab82532_console_wait_key(struct console *con) -{ - sleep_on(&keypress_wait); - return 0; -} - static kdev_t sab82532_console_device(struct console *con) { @@ -2622,7 +2611,6 @@ name: "ttyS", write: sab82532_console_write, device: sab82532_console_device, - wait_key: sab82532_console_wait_key, setup: sab82532_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/sbus/char/su.c linux-2.4.19-pre6/drivers/sbus/char/su.c --- linux-2.4.19-pre5/drivers/sbus/char/su.c Tue Nov 13 09:16:05 2001 +++ linux-2.4.19-pre6/drivers/sbus/char/su.c Thu Apr 4 22:05:03 2002 @@ -2854,40 +2854,6 @@ su_outb(info, UART_IER, ier); } -/* - * Receive character from the serial port - */ -static int -serial_console_wait_key(struct console *co) -{ - struct su_struct *info; - int ier; - int lsr; - int c; - - info = su_table + co->index; - - /* - * First save the IER then disable the interrupts so - * that the real driver for the port does not get the - * character. - */ - ier = su_inb(info, UART_IER); - su_outb(info, UART_IER, 0x00); - - do { - lsr = su_inb(info, UART_LSR); - } while (!(lsr & UART_LSR_DR)); - c = su_inb(info, UART_RX); - - /* - * Restore the interrupts - */ - su_outb(info, UART_IER, ier); - - return c; -} - static kdev_t serial_console_device(struct console *c) { @@ -3013,7 +2979,6 @@ name: "ttyS", write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/sbus/char/sunkbd.c linux-2.4.19-pre6/drivers/sbus/char/sunkbd.c --- linux-2.4.19-pre5/drivers/sbus/char/sunkbd.c Sun Sep 16 21:22:50 2001 +++ linux-2.4.19-pre6/drivers/sbus/char/sunkbd.c Thu Apr 4 22:05:03 2002 @@ -82,16 +82,6 @@ struct l1a_kbd_state l1a_state; -#ifndef CONFIG_PCI -DECLARE_WAIT_QUEUE_HEAD(keypress_wait); -#endif - -int keyboard_wait_for_keypress(struct console *co) -{ - sleep_on(&keypress_wait); - return 0; -} - static spinlock_t sunkbd_lock = SPIN_LOCK_UNLOCKED; /* @@ -629,7 +619,6 @@ static void put_queue(int ch) { - wake_up(&keypress_wait); if (tty) { tty_insert_flip_char(tty, ch, 0); con_schedule_flip(tty); @@ -638,7 +627,6 @@ static void puts_queue(char *cp) { - wake_up(&keypress_wait); if (!tty) return; diff -urN linux-2.4.19-pre5/drivers/sbus/char/zs.c linux-2.4.19-pre6/drivers/sbus/char/zs.c --- linux-2.4.19-pre5/drivers/sbus/char/zs.c Mon Feb 25 11:38:04 2002 +++ linux-2.4.19-pre6/drivers/sbus/char/zs.c Thu Apr 4 22:05:03 2002 @@ -543,8 +543,6 @@ /* Continue execution... */ return; } - /* It is a 'keyboard interrupt' ;-) */ - wake_up(&keypress_wait); } #ifndef __sparc_v9__ /* Look for kgdb 'stop' character, consult the gdb @@ -2797,13 +2795,6 @@ #endif } -static int -zs_console_wait_key(struct console *con) -{ - sleep_on(&keypress_wait); - return 0; -} - static kdev_t zs_console_device(struct console *con) { return MKDEV(TTY_MAJOR, 64 + con->index); @@ -2881,7 +2872,6 @@ name: "ttyS", write: zs_console_write, device: zs_console_device, - wait_key: zs_console_wait_key, setup: zs_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/scsi/scsi_lib.c linux-2.4.19-pre6/drivers/scsi/scsi_lib.c --- linux-2.4.19-pre5/drivers/scsi/scsi_lib.c Fri Oct 12 15:35:54 2001 +++ linux-2.4.19-pre6/drivers/scsi/scsi_lib.c Thu Apr 4 22:05:05 2002 @@ -426,6 +426,7 @@ if (req->waiting != NULL) { complete(req->waiting); } + req_finished_io(req); add_blkdev_randomness(MAJOR(req->rq_dev)); SDpnt = SCpnt->device; diff -urN linux-2.4.19-pre5/drivers/sgi/char/sgiserial.c linux-2.4.19-pre6/drivers/sgi/char/sgiserial.c --- linux-2.4.19-pre5/drivers/sgi/char/sgiserial.c Thu Apr 4 22:04:23 2002 +++ linux-2.4.19-pre6/drivers/sgi/char/sgiserial.c Thu Apr 4 22:05:05 2002 @@ -49,8 +49,6 @@ #define NUM_SERIAL 1 /* One chip on board. */ #define NUM_CHANNELS (NUM_SERIAL * 2) -extern wait_queue_head_t keypress_wait; - struct sgi_zslayout *zs_chips[NUM_SERIAL] = { 0, }; struct sgi_zschannel *zs_channels[NUM_CHANNELS] = { 0, 0, }; struct sgi_zschannel *zs_conschan; @@ -428,8 +426,6 @@ show_buffers(); return; } - /* It is a 'keyboard interrupt' ;-) */ - wake_up(&keypress_wait); } /* Look for kgdb 'stop' character, consult the gdb documentation * for remote target debugging and arch/sparc/kernel/sparc-stub.c @@ -2117,12 +2113,6 @@ rs_fair_output(); } -static int zs_console_wait_key(struct console *con) -{ - sleep_on(&keypress_wait); - return 0; -} - static kdev_t zs_console_device(struct console *con) { return MKDEV(TTY_MAJOR, 64 + con->index); @@ -2274,7 +2264,6 @@ name: "ttyS", write: zs_console_write, device: zs_console_device, - wait_key: zs_console_wait_key, setup: zs_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/sound/cmpci.c linux-2.4.19-pre6/drivers/sound/cmpci.c --- linux-2.4.19-pre5/drivers/sound/cmpci.c Fri Nov 9 14:07:41 2001 +++ linux-2.4.19-pre6/drivers/sound/cmpci.c Thu Apr 4 22:05:06 2002 @@ -2032,7 +2032,7 @@ if (s->dma_adc.mapped) s->dma_adc.count &= s->dma_adc.fragsize-1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) @@ -2049,7 +2049,7 @@ s->dma_adc.count &= s->dma_adc.fragsize-1; } spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { diff -urN linux-2.4.19-pre5/drivers/sound/cs4281/cs4281m.c linux-2.4.19-pre6/drivers/sound/cs4281/cs4281m.c --- linux-2.4.19-pre5/drivers/sound/cs4281/cs4281m.c Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/sound/cs4281/cs4281m.c Thu Apr 4 22:05:06 2002 @@ -3576,7 +3576,7 @@ if (s->dma_adc.mapped) s->dma_adc.count &= s->dma_adc.fragsize - 1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) @@ -3600,7 +3600,7 @@ if (s->dma_dac.mapped) s->dma_dac.count &= s->dma_dac.fragsize - 1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { diff -urN linux-2.4.19-pre5/drivers/sound/cs46xx.c linux-2.4.19-pre6/drivers/sound/cs46xx.c --- linux-2.4.19-pre5/drivers/sound/cs46xx.c Mon Feb 25 11:38:04 2002 +++ linux-2.4.19-pre6/drivers/sound/cs46xx.c Thu Apr 4 22:05:06 2002 @@ -2960,7 +2960,7 @@ cinfo.blocks = dmabuf->count/dmabuf->divisor >> dmabuf->fragshift; cinfo.ptr = dmabuf->hwptr/dmabuf->divisor; spin_unlock_irqrestore(&state->card->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; } return -ENODEV; @@ -2993,7 +2993,7 @@ "cs46xx: GETOPTR bytes=%d blocks=%d ptr=%d\n", cinfo.bytes,cinfo.blocks,cinfo.ptr) ); spin_unlock_irqrestore(&state->card->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; } return -ENODEV; diff -urN linux-2.4.19-pre5/drivers/sound/mad16.c linux-2.4.19-pre6/drivers/sound/mad16.c --- linux-2.4.19-pre5/drivers/sound/mad16.c Sun Sep 30 12:26:08 2001 +++ linux-2.4.19-pre6/drivers/sound/mad16.c Thu Apr 4 22:05:08 2002 @@ -42,6 +42,7 @@ #include #include #include +#include #include "sound_config.h" @@ -51,6 +52,7 @@ static int mad16_conf; static int mad16_cdsel; +static struct gameport gameport; static int already_initialized = 0; @@ -664,13 +666,13 @@ outb((bits | dma_bits[dma] | dma2_bit), config_port); /* Write IRQ+DMA setup */ - hw_config->slots[0] = ad1848_init("MAD16 WSS", hw_config->io_base + 4, + hw_config->slots[0] = ad1848_init("mad16 WSS", hw_config->io_base + 4, hw_config->irq, dma, dma2, 0, hw_config->osp, THIS_MODULE); - request_region(hw_config->io_base, 4, "MAD16 WSS config"); + request_region(hw_config->io_base, 4, "mad16 WSS config"); } static int __init probe_mad16_mpu(struct address_info *hw_config) @@ -1010,14 +1012,6 @@ } printk(".\n"); - printk(KERN_INFO "Joystick port "); - if (joystick == 1) - printk("enabled.\n"); - else - { - joystick = 0; - printk("disabled.\n"); - } cfg.io_base = io; cfg.irq = irq; @@ -1038,6 +1032,18 @@ attach_mad16(&cfg); found_mpu = probe_mad16_mpu(&cfg_mpu); + + if (joystick == 1) { + /* register gameport */ + if (!request_region(0x201, 1, "mad16 gameport")) + printk(KERN_ERR "mad16: gameport address 0x201 already in use\n"); + else { + printk(KERN_ERR "mad16: gameport enabled at 0x201\n"); + gameport.io = 0x201; + gameport_register_port(&gameport); + } + } + else printk(KERN_ERR "mad16: gameport disabled.\n"); return 0; } @@ -1055,16 +1061,17 @@ static int __init setup_mad16(char *str) { /* io, irq */ - int ints[7]; + int ints[8]; str = get_options(str, ARRAY_SIZE(ints), ints); - io = ints[1]; - irq = ints[2]; - dma = ints[3]; - dma16 = ints[4]; - mpu_io = ints[5]; - mpu_irq = ints[6]; + io = ints[1]; + irq = ints[2]; + dma = ints[3]; + dma16 = ints[4]; + mpu_io = ints[5]; + mpu_irq = ints[6]; + joystick = ints[7]; return 1; } diff -urN linux-2.4.19-pre5/drivers/sound/maestro.c linux-2.4.19-pre6/drivers/sound/maestro.c --- linux-2.4.19-pre5/drivers/sound/maestro.c Sun Sep 30 12:26:08 2001 +++ linux-2.4.19-pre6/drivers/sound/maestro.c Thu Apr 4 22:05:08 2002 @@ -2756,7 +2756,7 @@ if (s->dma_adc.mapped) s->dma_adc.count &= s->dma_adc.fragsize-1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) @@ -2771,7 +2771,7 @@ if (s->dma_dac.mapped) s->dma_dac.count &= s->dma_dac.fragsize-1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { diff -urN linux-2.4.19-pre5/drivers/sound/maestro3.c linux-2.4.19-pre6/drivers/sound/maestro3.c --- linux-2.4.19-pre5/drivers/sound/maestro3.c Fri Nov 9 13:41:42 2001 +++ linux-2.4.19-pre6/drivers/sound/maestro3.c Thu Apr 4 22:05:08 2002 @@ -1805,7 +1805,7 @@ if (s->dma_adc.mapped) s->dma_adc.count &= s->dma_adc.fragsize-1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) @@ -1818,7 +1818,7 @@ if (s->dma_dac.mapped) s->dma_dac.count &= s->dma_dac.fragsize-1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { diff -urN linux-2.4.19-pre5/drivers/sound/rme96xx.c linux-2.4.19-pre6/drivers/sound/rme96xx.c --- linux-2.4.19-pre5/drivers/sound/rme96xx.c Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/sound/rme96xx.c Thu Apr 4 22:05:09 2002 @@ -1348,7 +1348,7 @@ dma->readptr &= s->fragsize<<1; spin_unlock_irqrestore(&s->lock,flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_READ)) @@ -1365,7 +1365,7 @@ if (dma->mmapped) dma->writeptr &= s->fragsize<<1; spin_unlock_irqrestore(&s->lock,flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETBLKSIZE: return put_user(s->fragsize, (int *)arg); diff -urN linux-2.4.19-pre5/drivers/sound/sonicvibes.c linux-2.4.19-pre6/drivers/sound/sonicvibes.c --- linux-2.4.19-pre5/drivers/sound/sonicvibes.c Mon Feb 25 11:38:07 2002 +++ linux-2.4.19-pre6/drivers/sound/sonicvibes.c Thu Apr 4 22:05:09 2002 @@ -1802,7 +1802,7 @@ if (s->dma_adc.mapped) s->dma_adc.count &= s->dma_adc.fragsize-1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) @@ -1820,7 +1820,7 @@ if (s->dma_dac.mapped) s->dma_dac.count &= s->dma_dac.fragsize-1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { diff -urN linux-2.4.19-pre5/drivers/sound/vwsnd.c linux-2.4.19-pre6/drivers/sound/vwsnd.c --- linux-2.4.19-pre5/drivers/sound/vwsnd.c Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/sound/vwsnd.c Thu Apr 4 22:05:09 2002 @@ -2650,7 +2650,7 @@ DBGXV("SNDCTL_DSP_GETOSPACE returns { %d %d %d %d }\n", buf_info.fragments, buf_info.fragstotal, buf_info.fragsize, buf_info.bytes); - return copy_to_user((void *) arg, &buf_info, sizeof buf_info); + return copy_to_user((void *) arg, &buf_info, sizeof buf_info) ? -EFAULT : 0; case SNDCTL_DSP_GETISPACE: /* _SIOR ('P',13, audio_buf_info) */ DBGX("SNDCTL_DSP_GETISPACE\n"); @@ -2667,7 +2667,7 @@ DBGX("SNDCTL_DSP_GETISPACE returns { %d %d %d %d }\n", buf_info.fragments, buf_info.fragstotal, buf_info.fragsize, buf_info.bytes); - return copy_to_user((void *) arg, &buf_info, sizeof buf_info); + return copy_to_user((void *) arg, &buf_info, sizeof buf_info) ? -EFAULT : 0; case SNDCTL_DSP_NONBLOCK: /* _SIO ('P',14) */ DBGX("SNDCTL_DSP_NONBLOCK\n"); @@ -2725,7 +2725,7 @@ rport->frag_count = 0; } spin_unlock_irqrestore(&rport->lock, flags); - return copy_to_user((void *) arg, &info, sizeof info); + return copy_to_user((void *) arg, &info, sizeof info) ? -EFAULT : 0; case SNDCTL_DSP_GETOPTR: /* _SIOR ('P',18, count_info) */ DBGX("SNDCTL_DSP_GETOPTR\n"); @@ -2747,7 +2747,7 @@ wport->frag_count = 0; } spin_unlock_irqrestore(&wport->lock, flags); - return copy_to_user((void *) arg, &info, sizeof info); + return copy_to_user((void *) arg, &info, sizeof info) ? -EFAULT : 0; case SNDCTL_DSP_GETODELAY: /* _SIOR ('P', 23, int) */ DBGX("SNDCTL_DSP_GETODELAY\n"); diff -urN linux-2.4.19-pre5/drivers/tc/zs.c linux-2.4.19-pre6/drivers/tc/zs.c --- linux-2.4.19-pre5/drivers/tc/zs.c Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/tc/zs.c Thu Apr 4 22:05:09 2002 @@ -2125,18 +2125,6 @@ } } -/* - * Receive character from the serial port - */ -static int serial_console_wait_key(struct console *co) -{ - struct dec_serial *info; - - info = zs_soft + co->index; - - return zs_poll_rx_char(info); -} - static kdev_t serial_console_device(struct console *c) { return MKDEV(TTY_MAJOR, 64 + c->index); @@ -2271,7 +2259,6 @@ name: "ttyS", write: serial_console_write, device: serial_console_device, - wait_key: serial_console_wait_key, setup: serial_console_setup, flags: CON_PRINTBUFFER, index: -1, diff -urN linux-2.4.19-pre5/drivers/usb/CDCEther.c linux-2.4.19-pre6/drivers/usb/CDCEther.c --- linux-2.4.19-pre5/drivers/usb/CDCEther.c Fri Dec 21 09:41:55 2001 +++ linux-2.4.19-pre6/drivers/usb/CDCEther.c Thu Apr 4 22:05:09 2002 @@ -1,4 +1,4 @@ -// Portions of this file taken from +// Portions of this file taken from // Petko Manolov - Petkan (petkan@dce.bg) // from his driver pegasus.c @@ -25,20 +25,27 @@ #include #include #include -#include #include +#include +#include + +#define DEBUG +#include + #include "CDCEther.h" -static const char *version = __FILE__ ": v0.98.5 22 Sep 2001 Brad Hards and another"; +#define SHORT_DRIVER_DESC "CDC Ethernet Class" +#define DRIVER_VERSION "0.98.6" -/* Take any CDC device, and sort it out in probe() */ +static const char *version = __FILE__ ": " DRIVER_VERSION " 7 Jan 2002 Brad Hards and another"; +// We only try to claim CDC Ethernet model devices */ static struct usb_device_id CDCEther_ids[] = { - { USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) }, - { } /* Terminating null entry */ + { USB_INTERFACE_INFO(USB_CLASS_COMM, 6, 0) }, + { } }; -/* - * module parameter that provides an alternate upper limit on the +/* + * module parameter that provides an alternate upper limit on the * number of multicast filters we use, with a default to use all * the filters available to us. Note that the actual number used * is the lesser of this parameter and the number returned in the @@ -47,7 +54,6 @@ */ static int multicast_filter_limit = 32767; - ////////////////////////////////////////////////////////////////////////////// // Callback routines from USB device ///////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -59,7 +65,16 @@ int count = urb->actual_length, res; struct sk_buff *skb; - // Sanity check + switch ( urb->status ) { + case USB_ST_NOERROR: + break; + case USB_ST_URB_KILLED: + return; + default: + dbg("rx status %d", urb->status); + } + + // Sanity check if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) { dbg("BULK IN callback but driver is not active!"); return; @@ -133,7 +148,7 @@ // Give this to the USB subsystem so it can tell us // when more data arrives. if ( (res = usb_submit_urb(ðer_dev->rx_urb)) ) { - warn( __FUNCTION__ " failed submint rx_urb %d", res); + warn( __FUNCTION__ " failed submit rx_urb %d", res); } // We are no longer busy, show us the frames!!! @@ -160,47 +175,69 @@ // Hmm... What on Earth could have happened??? if ( urb->status ) { - info("%s: TX status %d", ether_dev->net->name, urb->status); + dbg("%s: TX status %d", ether_dev->net->name, urb->status); } // Update the network interface and tell it we are // ready for another frame ether_dev->net->trans_start = jiffies; netif_wake_queue( ether_dev->net ); + } -//static void intr_callback( struct urb *urb ) -//{ -// ether_dev_t *ether_dev = urb->context; -// struct net_device *net; -// __u8 *d; -// -// if ( !ether_dev ) -// return; -// -// switch ( urb->status ) { -// case USB_ST_NOERROR: -// break; -// case USB_ST_URB_KILLED: -// return; -// default: -// info("intr status %d", urb->status); -// } -// -// d = urb->transfer_buffer; -// net = ether_dev->net; -// if ( d[0] & 0xfc ) { -// ether_dev->stats.tx_errors++; -// if ( d[0] & TX_UNDERRUN ) -// ether_dev->stats.tx_fifo_errors++; -// if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) ) -// ether_dev->stats.tx_aborted_errors++; -// if ( d[0] & LATE_COL ) -// ether_dev->stats.tx_window_errors++; -// if ( d[0] & (NO_CARRIER | LOSS_CARRIER) ) -// ether_dev->stats.tx_carrier_errors++; -// } -//} +#if 0 +static void setpktfilter_done( struct urb *urb ) +{ + ether_dev_t *ether_dev = urb->context; + struct net_device *net; + + if ( !ether_dev ) + return; + dbg("got ctrl callback for setting packet filter"); + switch ( urb->status ) { + case USB_ST_NOERROR: + break; + case USB_ST_URB_KILLED: + return; + default: + dbg("intr status %d", urb->status); + } +} +#endif + +static void intr_callback( struct urb *urb ) +{ + ether_dev_t *ether_dev = urb->context; + struct net_device *net; + __u8 *d; + + if ( !ether_dev ) + return; + dbg("got intr callback"); + switch ( urb->status ) { + case USB_ST_NOERROR: + break; + case USB_ST_URB_KILLED: + return; + default: + dbg("intr status %d", urb->status); + } + + d = urb->transfer_buffer; + dbg("d: %x", d[0]); + net = ether_dev->net; + if ( d[0] & 0xfc ) { + ether_dev->stats.tx_errors++; + if ( d[0] & TX_UNDERRUN ) + ether_dev->stats.tx_fifo_errors++; + if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) ) + ether_dev->stats.tx_aborted_errors++; + if ( d[0] & LATE_COL ) + ether_dev->stats.tx_window_errors++; + if ( d[0] & (NO_CARRIER | LOSS_CARRIER) ) + netif_carrier_off(net); + } +} ////////////////////////////////////////////////////////////////////////////// // Routines for turning net traffic on and off on the USB side /////////////// @@ -213,8 +250,8 @@ // Here would be the time to set the data interface to the configuration where // it has two endpoints that use a protocol we can understand. - if (usb_set_interface( usb, - ether_dev->data_bInterfaceNumber, + if (usb_set_interface( usb, + ether_dev->data_bInterfaceNumber, ether_dev->data_bAlternateSetting_with_traffic ) ) { err("usb_set_interface() failed" ); err("Attempted to set interface %d", ether_dev->data_bInterfaceNumber); @@ -230,8 +267,8 @@ // no endpoints. This is what the spec suggests. if (ether_dev->data_interface_altset_num_without_traffic >= 0 ) { - if (usb_set_interface( ether_dev->usb, - ether_dev->data_bInterfaceNumber, + if (usb_set_interface( ether_dev->usb, + ether_dev->data_bInterfaceNumber, ether_dev->data_bAlternateSetting_without_traffic ) ) { err("usb_set_interface() failed"); } @@ -326,6 +363,9 @@ return 0; } +////////////////////////////////////////////////////////////////////////////// +// Standard routines for kernel Ethernet Device ////////////////////////////// +////////////////////////////////////////////////////////////////////////////// static struct net_device_stats *CDCEther_netdev_stats( struct net_device *net ) { // Easy enough! @@ -343,19 +383,33 @@ return -EIO; } - // Prep a receive URB + /* Prep a receive URB */ FILL_BULK_URB( ðer_dev->rx_urb, ether_dev->usb, usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in), - ether_dev->rx_buff, ether_dev->wMaxSegmentSize, + 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(ðer_dev->rx_urb)) ) - { - // Hmm... Okay... + /* Put it out there so the device can send us stuff */ + if ( (res = usb_submit_urb(ðer_dev->rx_urb)) ) { + /* Hmm... Okay... */ warn( __FUNCTION__ " failed rx_urb %d", res ); } + if (ether_dev->properties & HAVE_NOTIFICATION_ELEMENT) { + /* Arm and submit the interrupt URB */ + FILL_INT_URB( ðer_dev->intr_urb, + ether_dev->usb, + usb_rcvintpipe(ether_dev->usb, ether_dev->comm_ep_in), + ether_dev->intr_buff, + 8, /* Transfer buffer length */ + intr_callback, + ether_dev, + ether_dev->intr_interval); + if ( (res = usb_submit_urb(ðer_dev->intr_urb)) ) { + warn( __FUNCTION__ " failed intr_urb %d", res ); + } + } + // Tell the kernel we are ready to start receiving from it netif_start_queue( net ); @@ -386,92 +440,133 @@ usb_unlink_urb( ðer_dev->rx_urb ); usb_unlink_urb( ðer_dev->tx_urb ); usb_unlink_urb( ðer_dev->intr_urb ); - + usb_unlink_urb( ðer_dev->ctrl_urb ); + // That's it. I'm done. return 0; } -static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd ) +static int netdev_ethtool_ioctl(struct net_device *netdev, void *useraddr) { - //__u16 *data = (__u16 *)&rq->ifr_data; - //ether_dev_t *ether_dev = net->priv; + ether_dev_t *ether_dev = netdev->priv; + u32 cmd; + char tmp[40]; + + if (get_user(cmd, (u32 *)useraddr)) + return -EFAULT; + + switch (cmd) { + /* get driver info */ + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; + strncpy(info.driver, SHORT_DRIVER_DESC, ETHTOOL_BUSINFO_LEN); + strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); + sprintf(tmp, "usb%d:%d", ether_dev->usb->bus->busnum, ether_dev->usb->devnum); + strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN); + sprintf(tmp, "CDC %x.%x", ((ether_dev->bcdCDC & 0xff00)>>8), (ether_dev->bcdCDC & 0x00ff) ); + strncpy(info.fw_version, tmp, ETHTOOL_BUSINFO_LEN); + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + /* get link status */ + case ETHTOOL_GLINK: { + struct ethtool_value edata = {ETHTOOL_GLINK}; + edata.data = netif_carrier_ok(netdev); + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + } + dbg("Got unsupported ioctl: %x", cmd); + return -EOPNOTSUPP; /* the ethtool user space tool relies on this */ +} - // No support here yet. - // Do we need support??? +static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd ) +{ switch(cmd) { - case SIOCDEVPRIVATE: - return -EOPNOTSUPP; - case SIOCDEVPRIVATE+1: - return -EOPNOTSUPP; - case SIOCDEVPRIVATE+2: - //return 0; - return -EOPNOTSUPP; - default: - return -EOPNOTSUPP; + case SIOCETHTOOL: + return netdev_ethtool_ioctl(net, (void *) rq->ifr_data); + default: + return -ENOTTY; /* per ioctl man page */ } } +/* Multicast routines */ + static void CDC_SetEthernetPacketFilter (ether_dev_t *ether_dev) { - usb_control_msg(ether_dev->usb, +#if 0 + devrequest *dr = ðer_dev->ctrl_dr; + int res; + + dr->requesttype = USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE; + dr->request = SET_ETHERNET_PACKET_FILTER; + dr->value = cpu_to_le16(ether_dev->mode_flags); + dr->index = cpu_to_le16((u16)ether_dev->comm_interface); + dr->length = 0; + + FILL_CONTROL_URB(ðer_dev->ctrl_urb, + ether_dev->usb, usb_sndctrlpipe(ether_dev->usb, 0), - SET_ETHERNET_PACKET_FILTER, /* request */ - USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */ - cpu_to_le16(ether_dev->mode_flags), /* value */ - cpu_to_le16((u16)ether_dev->comm_interface), /* index */ + dr, + NULL, NULL, - 0, /* size */ - HZ); /* timeout */ -} + setpktfilter_done, + ether_dev); + if ( (res = usb_submit_urb(ðer_dev->ctrl_urb)) ) { + warn( __FUNCTION__ " failed submit ctrl_urb %d", res); + } +#endif +} static void CDCEther_set_multicast( struct net_device *net ) { ether_dev_t *ether_dev = net->priv; int i; __u8 *buff; - // Tell the kernel to stop sending us frames while we get this // all set up. netif_stop_queue(net); - /* Note: do not reorder, GCC is clever about common statements. */ - if (net->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - info( "%s: Promiscuous mode enabled", net->name); + /* Note: do not reorder, GCC is clever about common statements. */ + if (net->flags & IFF_PROMISC) { + /* Unconditionally log net taps. */ + dbg( "%s: Promiscuous mode enabled", net->name); ether_dev->mode_flags = MODE_FLAG_PROMISCUOUS | MODE_FLAG_ALL_MULTICAST | MODE_FLAG_DIRECTED | MODE_FLAG_BROADCAST | MODE_FLAG_MULTICAST; - } else if (net->mc_count > ether_dev->wNumberMCFilters) { - /* Too many to filter perfectly -- accept all multicasts. */ - info("%s: set too many MC filters, using allmulti", net->name); + } else if (net->mc_count > ether_dev->wNumberMCFilters) { + /* Too many to filter perfectly -- accept all multicasts. */ + dbg("%s: too many MC filters for hardware, using allmulti", net->name); ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST | MODE_FLAG_DIRECTED | MODE_FLAG_BROADCAST | MODE_FLAG_MULTICAST; } else if (net->flags & IFF_ALLMULTI) { - /* Filter in software */ - info("%s: using allmulti", net->name); + /* Filter in software */ + dbg("%s: using allmulti", net->name); ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST | MODE_FLAG_DIRECTED | MODE_FLAG_BROADCAST | MODE_FLAG_MULTICAST; - } else { + } else { /* do multicast filtering in hardware */ - struct dev_mc_list *mclist; - info("%s: set multicast filters", net->name); + struct dev_mc_list *mclist; + dbg("%s: set multicast filters", net->name); ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST | MODE_FLAG_DIRECTED | MODE_FLAG_BROADCAST | MODE_FLAG_MULTICAST; buff = kmalloc(6 * net->mc_count, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); - for (i = 0, mclist = net->mc_list; - mclist && i < net->mc_count; - i++, mclist = mclist->next) { - memcpy(&mclist->dmi_addr, &buff[i * 6], 6); + for (i = 0, mclist = net->mc_list; + mclist && i < net->mc_count; + i++, mclist = mclist->next) { + memcpy(&mclist->dmi_addr, &buff[i * 6], 6); } #if 0 usb_control_msg(ether_dev->usb, @@ -487,10 +582,9 @@ kfree(buff); } -#if 0 CDC_SetEthernetPacketFilter(ether_dev); -#endif - // Tell the kernel to start giving frames to us again. + + /* Tell the kernel to start giving frames to us again. */ netif_wake_queue(net); } @@ -498,40 +592,42 @@ // Routines used to parse out the Functional Descriptors ///////////////////// ////////////////////////////////////////////////////////////////////////////// -static int parse_header_functional_descriptor( int *bFunctionLength, - int bDescriptorType, +/* Header Descriptor - CDC Spec 5.2.3.1, Table 26 */ +static int parse_header_functional_descriptor( int *bFunctionLength, + int bDescriptorType, int bDescriptorSubtype, unsigned char *data, ether_dev_t *ether_dev, int *requirements ) { - // Check to make sure we haven't seen one of these already. + /* Check to make sure we haven't seen one of these already. */ if ( (~*requirements) & REQ_HDR_FUNC_DESCR ) { err( "Multiple Header Functional Descriptors found." ); return -1; } - - // Is it the right size??? - if (*bFunctionLength != 5) { - info( "Invalid length in Header Functional Descriptor" ); - // This is a hack to get around a particular device (NO NAMES) - // It has this function length set to the length of the - // whole class-specific descriptor - *bFunctionLength = 5; + + /* Check for appropriate length */ + if (*bFunctionLength != HEADER_FUNC_DESC_LEN) { + dbg( "Invalid length in Header Functional Descriptor, working around it." ); + /* This is a hack to get around a particular device (NO NAMES) + * It has this function length set to the length of the + * whole class-specific descriptor */ + *bFunctionLength = HEADER_FUNC_DESC_LEN; } - // Nothing extremely useful here. - // We'll keep it for posterity + /* Nothing extremely useful here */ + /* We'll keep it for posterity */ ether_dev->bcdCDC = data[0] + (data[1] << 8); - dbg( "Found Header descriptor, CDC version %x", ether_dev->bcdCDC); + dbg( "Found Header descriptor, CDC version %x.", ether_dev->bcdCDC); - // We've seen one of these + /* We've seen one of these */ *requirements &= ~REQ_HDR_FUNC_DESCR; - - // It's all good. + + /* Success */ return 0; } +/* Union Descriptor - CDC Spec 5.2.3.8, Table 33 */ static int parse_union_functional_descriptor( int *bFunctionLength, int bDescriptorType, int bDescriptorSubtype, @@ -539,77 +635,89 @@ ether_dev_t *ether_dev, int *requirements ) { - // Check to make sure we haven't seen one of these already. + /* Check to make sure we haven't seen one of these already. */ if ( (~*requirements) & REQ_UNION_FUNC_DESCR ) { err( "Multiple Union Functional Descriptors found." ); return -1; } - // Is it the right size? - if (*bFunctionLength != 5) { + /* Check for appropriate length */ + if (*bFunctionLength != UNION_FUNC_DESC_LEN) { // It is NOT the size we expected. - err( "Unsupported length in Union Functional Descriptor" ); + err( "Invalid length in Union Functional Descriptor." ); return -1; } - // Sanity check of sorts + /* Sanity check of sorts */ if (ether_dev->comm_interface != data[0]) { - // This tells us that we are chasing the wrong comm - // interface or we are crazy or something else weird. + /* This tells us that we are chasing the wrong comm + * interface or we are crazy or something else weird. */ if (ether_dev->comm_interface == data[1]) { - info( "Probably broken Union descriptor, fudging data interface" ); - // We'll need this in a few microseconds, - // so guess here, and hope for the best + dbg( "Probably broken Union descriptor, fudging data interface." ); + /* We'll need this in a few microseconds, + * so if the comm interface was the first slave, + * then probably the master interface is the data one + * Just hope for the best */ ether_dev->data_interface = data[0]; } else { - err( "Union Functional Descriptor is broken beyond repair" ); + err( "Union Functional Descriptor is broken beyond repair." ); return -1; } - } else{ // Descriptor is OK - // We'll need this in a few microseconds! + } else{ /* Descriptor is OK */ ether_dev->data_interface = data[1]; } - // We've seen one of these now. + /* We've seen one of these */ *requirements &= ~REQ_UNION_FUNC_DESCR; - - // Done + + /* Success */ return 0; } -static int parse_ethernet_functional_descriptor( int *bFunctionLength, +/* Ethernet Descriptor - CDC Spec 5.2.3.16, Table 41 */ +static int parse_ethernet_functional_descriptor( int *bFunctionLength, int bDescriptorType, int bDescriptorSubtype, unsigned char *data, ether_dev_t *ether_dev, int *requirements ) { - // Check to make sure we haven't seen one of these already. + //* Check to make sure we haven't seen one of these already. */ if ( (~*requirements) & REQ_ETH_FUNC_DESCR ) { err( "Multiple Ethernet Functional Descriptors found." ); return -1; } - // Is it the right size? - if (*bFunctionLength != 13) { - err( "Invalid length in Ethernet Networking Functional Descriptor" ); + /* Check for appropriate length */ + if (*bFunctionLength != ETHERNET_FUNC_DESC_LEN) { + err( "Invalid length in Ethernet Networking Functional Descriptor." ); return -1; } - - // Lots of goodies from this one. They are all important. + + /* Lots of goodies from this one. They are all important. */ ether_dev->iMACAddress = data[0]; ether_dev->bmEthernetStatistics = data[1] + (data[2] << 8) + (data[3] << 16) + (data[4] << 24); ether_dev->wMaxSegmentSize = data[5] + (data[6] << 8); - ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8)) & 0x00007FFF; + ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8)); + if (ether_dev->wNumberMCFilters & (1 << 15)) { + ether_dev->properties |= PERFECT_FILTERING; + dbg("Perfect filtering support"); + } else { + dbg("Imperfect filtering support - need sw hashing"); + } + if (0 == (ether_dev->wNumberMCFilters & (0x7f))) { + ether_dev->properties |= NO_SET_MULTICAST; + dbg("Can't use SetEthernetMulticastFilters request"); + } if (ether_dev->wNumberMCFilters > multicast_filter_limit) { ether_dev->wNumberMCFilters = multicast_filter_limit; - } + } ether_dev->bNumberPowerFilters = data[9]; - // We've seen one of these now. + /* We've seen one of these */ *requirements &= ~REQ_ETH_FUNC_DESCR; - - // That's all she wrote. + + /* Success */ return 0; } @@ -620,15 +728,15 @@ ether_dev_t *ether_dev, int *requirements ) { - // There should only be one type if we are sane + /* There should only be one type if we are sane */ if (bDescriptorType != CS_INTERFACE) { - info( "Invalid bDescriptorType found." ); + err( "Invalid bDescriptorType found." ); return -1; } - // The Subtype tells the tale. - switch (bDescriptorSubtype){ - case 0x00: // Header Functional Descriptor + /* The Subtype tells the tale - CDC spec Table 25 */ + switch (bDescriptorSubtype) { + case 0x00: /* Header Functional Descriptor */ return parse_header_functional_descriptor( bFunctionLength, bDescriptorType, bDescriptorSubtype, @@ -636,7 +744,7 @@ ether_dev, requirements ); break; - case 0x06: // Union Functional Descriptor + case 0x06: /* Union Functional Descriptor */ return parse_union_functional_descriptor( bFunctionLength, bDescriptorType, bDescriptorSubtype, @@ -644,7 +752,7 @@ ether_dev, requirements ); break; - case 0x0F: // Ethernet Networking Functional Descriptor + case 0x0F: /* Ethernet Networking Functional Descriptor */ return parse_ethernet_functional_descriptor( bFunctionLength, bDescriptorType, bDescriptorSubtype, @@ -652,12 +760,12 @@ ether_dev, requirements ); break; - default: // We don't support this at this time... - // However that doesn't necessarily indicate an error. - dbg( "Unexpected header type %x:", bDescriptorSubtype ); + default: /* We don't support this at this time... */ + /* However that doesn't necessarily indicate an error. */ + dbg( "Unexpected header type %x.", bDescriptorSubtype ); return 0; } - // How did we get here??? + /* How did we get here? */ return -1; } @@ -668,46 +776,49 @@ int bFunctionLength; int bDescriptorType; int bDescriptorSubtype; - int requirements = REQUIREMENTS_TOTAL; + int requirements = REQUIREMENTS_TOTAL; /* We init to our needs, and then clear + * bits as we find the descriptors */ - // As long as there is something here, we will try to parse it + /* As long as there is something here, we will try to parse it */ + /* All of the functional descriptors start with the same 3 byte pattern */ while (loc < length) { - // Length + /* Length */ bFunctionLength = data[loc]; loc++; - - // Type + + /* Type */ bDescriptorType = data[loc]; loc++; - - // Subtype + + /* Subtype */ bDescriptorSubtype = data[loc]; loc++; - // ship this off to be processed elsewhere. + /* ship this off to be processed */ rc = parse_protocol_unit_functional_descriptor( &bFunctionLength, bDescriptorType, bDescriptorSubtype, &data[loc], ether_dev, &requirements ); - // Did it process okay? + /* Did it process okay? */ if (rc) { - // Something was hosed somewhere. - // No need to continue; + /* Something was hosed somewhere. */ + /* No need to continue */ err("Bad descriptor parsing: %x", rc ); return -1; } - // We have already taken three bytes. + /* We move the loc pointer along, remembering + * that we have already taken three bytes */ loc += (bFunctionLength - 3); } - // Check to see if we got everything we need. + /* Check to see if we got everything we need. */ if (requirements) { // We missed some of the requirements... - err( "Not all required functional descriptors present 0x%08X", requirements ); + err( "Not all required functional descriptors present 0x%08X.", requirements ); return -1; } - // We got everything. + /* We got everything */ return 0; } @@ -721,28 +832,28 @@ struct usb_interface *comm_intf_group = NULL; struct usb_interface_descriptor *comm_intf = NULL; int rc = -1; - // The assumption here is that find_ethernet_comm_interface - // and find_valid_configuration - // have already filled in the information about where to find - // the a valid commication interface. + /* The assumption here is that find_ethernet_comm_interface + * and find_valid_configuration + * have already filled in the information about where to find + * the a valid commication interface. */ conf = &( device->config[ether_dev->configuration_num] ); comm_intf_group = &( conf->interface[ether_dev->comm_interface] ); comm_intf = &( comm_intf_group->altsetting[ether_dev->comm_interface_altset_num] ); - // Let's check and see if it has the extra information we need... + /* Let's check and see if it has the extra information we need */ if (comm_intf->extralen > 0) { - // This is where the information is SUPPOSED to be. + /* This is where the information is SUPPOSED to be */ rc = parse_ethernet_class_information( comm_intf->extra, comm_intf->extralen, ether_dev ); } else if (conf->extralen > 0) { - // This is a hack. The spec says it should be at the interface - // location checked above. However I have seen it here also. - // This is the same device that requires the functional descriptor hack above - warn( "Ethernet information found at device configuration. This is broken." ); + /* This is a hack. The spec says it should be at the interface + * location checked above. However I have seen it here also. + * This is the same device that requires the functional descriptor hack above */ + dbg( "Ethernet information found at device configuration. Trying to use it anyway." ); rc = parse_ethernet_class_information( conf->extra, conf->extralen, ether_dev ); } else { - // I don't know where else to look. - warn( "No ethernet information found." ); + /* I don't know where else to look */ + err( "No ethernet information found." ); rc = -1; } return rc; @@ -757,47 +868,43 @@ struct usb_config_descriptor *conf = NULL; struct usb_interface *data_intf_group = NULL; struct usb_interface_descriptor *data_intf = NULL; - - // Walk through and get to the data interface we are checking. + + /* Walk through and get to the data interface we are checking. */ conf = &( device->config[ether_dev->configuration_num] ); data_intf_group = &( conf->interface[ether_dev->data_interface] ); data_intf = &( data_intf_group->altsetting[ether_dev->data_interface_altset_num_with_traffic] ); - // Start out assuming we won't find anything we can use + /* Start out assuming we won't find anything we can use */ ether_dev->data_ep_in = 0; ether_dev->data_ep_out = 0; - - // If these are not BULK endpoints, we don't want them - if ( data_intf->endpoint[0].bmAttributes != 0x02 ) { + + /* If these are not BULK endpoints, we don't want them */ + if ( data_intf->endpoint[0].bmAttributes != USB_ENDPOINT_XFER_BULK ) { return -1; - } if ( data_intf->endpoint[1].bmAttributes != 0x02 ) { + } + if ( data_intf->endpoint[1].bmAttributes != USB_ENDPOINT_XFER_BULK ) { return -1; } - // Check the first endpoint to see if it is IN or OUT - if ( data_intf->endpoint[0].bEndpointAddress & 0x80 ) { - // This endpoint is IN + /* Check the first endpoint to see if it is IN or OUT */ + if ( data_intf->endpoint[0].bEndpointAddress & USB_DIR_IN ) { ether_dev->data_ep_in = data_intf->endpoint[0].bEndpointAddress & 0x7F; } else { - // This endpoint is OUT - ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress & 0x7F; + ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress; ether_dev->data_ep_out_size = data_intf->endpoint[0].wMaxPacketSize; } - // Check the second endpoint to see if it is IN or OUT - if ( data_intf->endpoint[1].bEndpointAddress & 0x80 ) { - // This endpoint is IN + /* Check the second endpoint to see if it is IN or OUT */ + if ( data_intf->endpoint[1].bEndpointAddress & USB_DIR_IN ) { ether_dev->data_ep_in = data_intf->endpoint[1].bEndpointAddress & 0x7F; } else { - // This endpoint is OUT - ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress & 0x7F; + ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress; ether_dev->data_ep_out_size = data_intf->endpoint[1].wMaxPacketSize; } - - // Now make sure we got both an IN and an OUT + + /* Now make sure we got both an IN and an OUT */ if (ether_dev->data_ep_in && ether_dev->data_ep_out) { - // We did get both, we are in good shape... - info( "detected BULK OUT packets of size %d", ether_dev->data_ep_out_size ); + dbg( "detected BULK OUT packets of size %d", ether_dev->data_ep_out_size ); return 0; } return -1; @@ -887,45 +994,45 @@ for ( altset_num = 0; altset_num < comm_intf_group->num_altsetting; altset_num++ ) { comm_intf = &( comm_intf_group->altsetting[altset_num] ); - // Is this a communication class of interface of the - // ethernet subclass variety. - if ( ( comm_intf->bInterfaceClass == 0x02 ) - && ( comm_intf->bInterfaceSubClass == 0x06 ) - && ( comm_intf->bInterfaceProtocol == 0x00 ) ) { - if ( comm_intf->bNumEndpoints == 1 ) { - // Good, we found one, we will try this one - // Fill in the structure... - ether_dev->comm_interface = intf_num; - ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber; - ether_dev->comm_interface_altset_num = altset_num; - ether_dev->comm_bAlternateSetting = comm_intf->bAlternateSetting; - - // Look for the Ethernet Functional Descriptors - rc = find_and_parse_ethernet_class_information( device, ether_dev ); - if (rc) { - // Nope this was no good after all. - continue; - } - - // Check that we really can talk to the data - // interface - // This includes # of endpoints, protocols, - // etc. - rc = verify_ethernet_data_interface( device, ether_dev ); - if (rc) { - // We got something we didn't like - continue; - } - // This communication interface seems to give us everything - // we require. We have all the ethernet info we need. - // Let's get out of here and go home right now. - return 0; - } else { - // bNumEndPoints != 1 - // We found an interface that had the wrong number of - // endpoints but would have otherwise been okay - } // end bNumEndpoints check. - } // end interface specifics check. + /* Good, we found one, we will try this one */ + /* Fill in the structure */ + ether_dev->comm_interface = intf_num; + ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber; + ether_dev->comm_interface_altset_num = altset_num; + ether_dev->comm_bAlternateSetting = comm_intf->bAlternateSetting; + + // Look for the Ethernet Functional Descriptors + rc = find_and_parse_ethernet_class_information( device, ether_dev ); + if (rc) { + // Nope this was no good after all. + continue; + } + + /* Check that we really can talk to the data interface + * This includes # of endpoints, protocols, etc. */ + rc = verify_ethernet_data_interface( device, ether_dev ); + if (rc) { + /* We got something we didn't like */ + continue; + } + /* It is a bit ambiguous whether the Ethernet model really requires + * the notification element (usually an interrupt endpoint) or not + * And some products (eg Sharp Zaurus) don't support it, so we + * only use the notification element if present */ + /* We check for a sane endpoint before using it */ + if ( (comm_intf->bNumEndpoints == 1) && + (comm_intf->endpoint[0].bEndpointAddress & USB_DIR_IN) && + (comm_intf->endpoint[0].bmAttributes == USB_ENDPOINT_XFER_INT)) { + ether_dev->properties |= HAVE_NOTIFICATION_ELEMENT; + ether_dev->comm_ep_in = (comm_intf->endpoint[0].bEndpointAddress & 0x7F); + dbg("interrupt address: %x",ether_dev->comm_ep_in); + ether_dev->intr_interval = (comm_intf->endpoint[0].bInterval); + dbg("interrupt interval: %d",ether_dev->intr_interval); + } + // This communication interface seems to give us everything + // we require. We have all the ethernet info we need. + + return 0; } // end for altset_num } // end for intf_num return -1; @@ -1005,8 +1112,8 @@ static inline unsigned char hex2dec( unsigned char digit ) { - // Is there a standard way to do this??? - // I have written this code TOO MANY times. + /* Is there a standard way to do this??? */ + /* I have written this code TOO MANY times. */ if ( (digit >= '0') && (digit <= '9') ) { return (digit - '0'); } @@ -1016,9 +1123,14 @@ if ( (digit >= 'A') && (digit <= 'F') ) { return (digit - 'A' + 10); } - return 0; + return 16; } +/* CDC Ethernet devices provide the MAC address as a string */ +/* We get an index to the string in the Ethernet functional header */ +/* This routine retrieves the string, sanity checks it, and sets the */ +/* MAC address in the network device */ +/* The encoding is a bit wacky - see CDC Spec Table 41 for details */ static void set_ethernet_addr( ether_dev_t *ether_dev ) { unsigned char mac_addr[6]; @@ -1026,7 +1138,7 @@ int len; unsigned char buffer[13]; - // Let's assume we don't get anything... + /* Let's assume we don't get anything */ mac_addr[0] = 0x00; mac_addr[1] = 0x00; mac_addr[2] = 0x00; @@ -1034,22 +1146,30 @@ mac_addr[4] = 0x00; mac_addr[5] = 0x00; - // Let's ask the device... - len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13); + /* Let's ask the device */ + if (0 > (len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13))) { + err("Attempting to get MAC address failed: %d", -1*len); + return; + } - // Sanity check! + /* Sanity check */ if (len != 12) { - // You gotta love failing sanity checks + /* You gotta love failing sanity checks */ err("Attempting to get MAC address returned %d bytes", len); return; } - // Fill in the mac_addr + /* Fill in the mac_addr */ for (i = 0; i < 6; i++) { - mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] ); + if ((16 == buffer[2 * i]) || (16 == buffer[2 * i + 1])) { + err("Bad value in MAC address"); + } + else { + mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] ); + } } - // Now copy it over to the kernel's network driver. + /* Now copy it over to our network device structure */ memcpy( ether_dev->net->dev_addr, mac_addr, sizeof(mac_addr) ); } @@ -1067,12 +1187,12 @@ unsigned char sern[256]; unsigned char *mac_addr; - // Default empty strings in case we don't find a real one + /* Default empty strings in case we don't find a real one */ manu[0] = 0x00; prod[0] = 0x00; sern[0] = 0x00; - // Try to get the device Manufacturer + /* Try to get the device Manufacturer */ string_num = ether_dev->usb->descriptor.iManufacturer; if (string_num) { // Put it into its buffer @@ -1081,7 +1201,7 @@ manu[len] = 0x00; } - // Try to get the device Product Name + /* Try to get the device Product Name */ string_num = ether_dev->usb->descriptor.iProduct; if (string_num) { // Put it into its buffer @@ -1090,7 +1210,7 @@ prod[len] = 0x00; } - // Try to get the device Serial Number + /* Try to get the device Serial Number */ string_num = ether_dev->usb->descriptor.iSerialNumber; if (string_num) { // Put it into its buffer @@ -1099,14 +1219,20 @@ sern[len] = 0x00; } - // This makes it easier for us to print + /* This makes it easier for us to print */ mac_addr = ether_dev->net->dev_addr; - // Now send everything we found to the syslog - info( "%s: %s %s %s %02X:%02X:%02X:%02X:%02X:%02X", - ether_dev->net->name, manu, prod, sern, mac_addr[0], - mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], - mac_addr[5] ); + /* Now send everything we found to the syslog */ + info( "%s: %s %s %s", ether_dev->net->name, manu, prod, sern); + dbg( "%s: %02X:%02X:%02X:%02X:%02X:%02X", + ether_dev->net->name, + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5] ); + } /* Forward declaration */ @@ -1227,11 +1353,7 @@ // Send a message to syslog about what we are handling log_device_info( ether_dev ); - // I claim this interface to be a CDC Ethernet Networking device - usb_driver_claim_interface( &CDCEther_driver, - &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]), - ether_dev ); - // I claim this interface to be a CDC Ethernet Networking device + /* We need to manually claim the data interface, while the comm interface gets claimed in the return */ usb_driver_claim_interface( &CDCEther_driver, &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]), ether_dev ); @@ -1239,11 +1361,8 @@ // Does this REALLY do anything??? usb_inc_dev_use( usb ); - // TODO - last minute HACK - ether_dev->comm_ep_in = 5; - // Okay, we are finally done... - return NULL; + return ether_dev; } @@ -1313,7 +1432,7 @@ int __init CDCEther_init(void) { - info( "%s", version ); + dbg( "%s", version ); return usb_register( &CDCEther_driver ); } @@ -1333,11 +1452,10 @@ MODULE_DESCRIPTION("USB CDC Ethernet driver"); MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE (usb, CDCEther_ids); MODULE_PARM (multicast_filter_limit, "i"); MODULE_PARM_DESC (multicast_filter_limit, "CDCEther maximum number of filtered multicast addresses"); -MODULE_DEVICE_TABLE (usb, CDCEther_ids); - ////////////////////////////////////////////////////////////////////////////// // End of file /////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// diff -urN linux-2.4.19-pre5/drivers/usb/CDCEther.h linux-2.4.19-pre6/drivers/usb/CDCEther.h --- linux-2.4.19-pre5/drivers/usb/CDCEther.h Sun Sep 23 09:49:00 2001 +++ linux-2.4.19-pre6/drivers/usb/CDCEther.h Thu Apr 4 22:05:09 2002 @@ -1,4 +1,4 @@ -// Portions of this file taken from +// Portions of this file taken from // Petko Manolov - Petkan (petkan@dce.bg) // from his driver pegasus.h @@ -18,11 +18,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - +/* From CDC Spec Table 24 */ #define CS_INTERFACE 0x24 #define CDC_ETHER_MAX_MTU 1536 +/* These definitions are used with the ether_dev_t flags element */ #define CDC_ETHER_PRESENT 0x00000001 #define CDC_ETHER_RUNNING 0x00000002 #define CDC_ETHER_TX_BUSY 0x00000004 @@ -31,10 +32,10 @@ #define CDC_ETHER_TX_TIMEOUT (HZ*10) -#define TX_UNDERRUN 0x80 +#define TX_UNDERRUN 0x80 #define EXCESSIVE_COL 0x40 -#define LATE_COL 0x20 -#define NO_CARRIER 0x10 +#define LATE_COL 0x20 +#define NO_CARRIER 0x10 #define LOSS_CARRIER 0x08 #define JABBER_TIMEOUT 0x04 @@ -43,22 +44,13 @@ #define CDC_ETHER_REQ_GET_REGS 0xf0 #define CDC_ETHER_REQ_SET_REGS 0xf1 #define CDC_ETHER_REQ_SET_REG PIPERIDER_REQ_SET_REGS -#define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES))) - -#define MODE_FLAG_PROMISCUOUS (1<<0) -#define MODE_FLAG_ALL_MULTICAST (1<<1) -#define MODE_FLAG_DIRECTED (1<<2) -#define MODE_FLAG_BROADCAST (1<<3) -#define MODE_FLAG_MULTICAST (1<<4) - -#define SET_ETHERNET_MULTICAST_FILTER 0x40 -#define SET_ETHERNET_PACKET_FILTER 0x43 typedef struct _ether_dev_t { struct usb_device *usb; struct net_device *net; struct net_device_stats stats; unsigned flags; + unsigned properties; int configuration_num; int bConfigurationValue; int comm_interface; @@ -79,20 +71,44 @@ __u8 iMACAddress; __u32 bmEthernetStatistics; __u16 wMaxSegmentSize; - __u16 mode_flags; __u16 wNumberMCFilters; __u8 bNumberPowerFilters; + __u16 mode_flags; int intr_interval; - 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]); + devrequest ctrl_dr; + struct urb rx_urb, tx_urb, intr_urb, ctrl_urb; + unsigned char rx_buff[CDC_ETHER_MAX_MTU] __attribute__((aligned(L1_CACHE_BYTES))); + unsigned char tx_buff[CDC_ETHER_MAX_MTU] __attribute__((aligned(L1_CACHE_BYTES))); + unsigned char intr_buff[8] __attribute__((aligned(L1_CACHE_BYTES))) ; } ether_dev_t; +/* These definitions used in the Ethernet Packet Filtering requests */ +/* See CDC Spec Table 62 */ +#define MODE_FLAG_PROMISCUOUS (1<<0) +#define MODE_FLAG_ALL_MULTICAST (1<<1) +#define MODE_FLAG_DIRECTED (1<<2) +#define MODE_FLAG_BROADCAST (1<<3) +#define MODE_FLAG_MULTICAST (1<<4) + +/* CDC Spec class requests - CDC Spec Table 46 */ +#define SET_ETHERNET_MULTICAST_FILTER 0x40 +#define SET_ETHERNET_PACKET_FILTER 0x43 + + +/* These definitions are used with the ether_dev_t properties field */ +#define HAVE_NOTIFICATION_ELEMENT 0x0001 +#define PERFECT_FILTERING 0x0002 +#define NO_SET_MULTICAST 0x0004 + +/* These definitions are used in the requirements parser */ #define REQ_HDR_FUNC_DESCR 0x0001 #define REQ_UNION_FUNC_DESCR 0x0002 #define REQ_ETH_FUNC_DESCR 0x0004 -#define REQUIREMENTS_TOTAL 0x0007 +#define REQUIREMENTS_TOTAL REQ_ETH_FUNC_DESCR | REQ_UNION_FUNC_DESCR | REQ_HDR_FUNC_DESCR +/* Some useful lengths */ +#define HEADER_FUNC_DESC_LEN 0x5 +#define UNION_FUNC_DESC_LEN 0x5 +#define ETHERNET_FUNC_DESC_LEN 0xD /* 13 for all you decimal weenies */ diff -urN linux-2.4.19-pre5/drivers/usb/Config.in linux-2.4.19-pre6/drivers/usb/Config.in --- linux-2.4.19-pre5/drivers/usb/Config.in Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/usb/Config.in Thu Apr 4 22:05:09 2002 @@ -49,17 +49,17 @@ dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB comment 'USB Human Interface Devices (HID)' + dep_tristate ' USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB if [ "$CONFIG_INPUT" = "n" ]; then - comment ' Input core support is needed for USB HID' - else - dep_tristate ' USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB $CONFIG_INPUT - dep_mbool ' /dev/hiddev raw HID device support (EXPERIMENTAL)' CONFIG_USB_HIDDEV $CONFIG_USB_HID - if [ "$CONFIG_USB_HID" != "y" ]; then - dep_tristate ' USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT - dep_tristate ' USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT - fi - dep_tristate ' Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT + comment ' Input core support is needed for USB HID input layer or HIDBP support' + fi + dep_mbool ' HID input layer support' CONFIG_USB_HIDINPUT $CONFIG_INPUT $CONFIG_USB_HID + dep_mbool ' /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID + if [ "$CONFIG_USB_HID" != "y" ]; then + dep_tristate ' USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT + dep_tristate ' USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT fi + dep_tristate ' Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT comment 'USB Imaging devices' dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB @@ -87,6 +87,7 @@ comment ' Networking support is needed for USB Networking device support' else dep_tristate ' USB Pegasus/Pegasus-II based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL + dep_tristate ' USB Realtek RTL8150 based ethernet device support (EXPERIMENTAL)' CONFIG_USB_RTL8150 $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL dep_tristate ' USB Communication Class Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL diff -urN linux-2.4.19-pre5/drivers/usb/Makefile linux-2.4.19-pre6/drivers/usb/Makefile --- linux-2.4.19-pre5/drivers/usb/Makefile Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/usb/Makefile Thu Apr 4 22:05:09 2002 @@ -16,7 +16,7 @@ list-multi := usbcore.o hid.o pwc.o usbcore-objs := usb.o usb-debug.o hub.o -hid-objs := hid-core.o hid-input.o +hid-objs := hid-core.o pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o @@ -30,6 +30,10 @@ hid-objs += hiddev.o endif +ifeq ($(CONFIG_USB_HIDINPUT),y) + hid-objs += hid-input.o +endif + # Object file lists. obj-y := @@ -77,6 +81,7 @@ obj-$(CONFIG_USB_SE401) += se401.o obj-$(CONFIG_USB_STV680) += stv680.o obj-$(CONFIG_USB_PEGASUS) += pegasus.o +obj-$(CONFIG_USB_RTL8150) += rtl8150.o obj-$(CONFIG_USB_CATC) += catc.o obj-$(CONFIG_USB_KAWETH) += kaweth.o obj-$(CONFIG_USB_CDCETHER) += CDCEther.o diff -urN linux-2.4.19-pre5/drivers/usb/audio.c linux-2.4.19-pre6/drivers/usb/audio.c --- linux-2.4.19-pre5/drivers/usb/audio.c Mon Feb 25 11:38:07 2002 +++ linux-2.4.19-pre6/drivers/usb/audio.c Thu Apr 4 22:05:09 2002 @@ -2536,7 +2536,7 @@ if (as->usbin.dma.mapped) as->usbin.dma.count &= as->usbin.dma.fragsize-1; spin_unlock_irqrestore(&as->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) @@ -2548,7 +2548,7 @@ if (as->usbout.dma.mapped) as->usbout.dma.count &= as->usbout.dma.fragsize-1; spin_unlock_irqrestore(&as->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { diff -urN linux-2.4.19-pre5/drivers/usb/catc.c linux-2.4.19-pre6/drivers/usb/catc.c --- linux-2.4.19-pre5/drivers/usb/catc.c Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/usb/catc.c Thu Apr 4 22:05:09 2002 @@ -409,7 +409,7 @@ { struct catc *catc = urb->context; struct ctrl_queue *q; - long flags; + unsigned long flags; if (urb->status) dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length); @@ -443,7 +443,7 @@ { struct ctrl_queue *q; int retval = 0; - long flags; + unsigned long flags; spin_lock_irqsave(&catc->ctrl_lock, flags); diff -urN linux-2.4.19-pre5/drivers/usb/hcd/ehci-hcd.c linux-2.4.19-pre6/drivers/usb/hcd/ehci-hcd.c --- linux-2.4.19-pre5/drivers/usb/hcd/ehci-hcd.c Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/usb/hcd/ehci-hcd.c Thu Apr 4 22:05:09 2002 @@ -747,8 +747,8 @@ { dbg (DRIVER_INFO); dbg ("block sizes: qh %d qtd %d itd %d sitd %d", - sizeof (struct ehci_qh), sizeof (struct ehci_qtd), - sizeof (struct ehci_itd), sizeof (struct ehci_sitd)); + (int) sizeof (struct ehci_qh), (int) sizeof (struct ehci_qtd), + (int) sizeof (struct ehci_itd), (int) sizeof (struct ehci_sitd)); return pci_module_init (&ehci_pci_driver); } diff -urN linux-2.4.19-pre5/drivers/usb/hcd.c linux-2.4.19-pre6/drivers/usb/hcd.c --- linux-2.4.19-pre5/drivers/usb/hcd.c Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/usb/hcd.c Thu Apr 4 22:05:09 2002 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001 by David Brownell + * Copyright (c) 2001-2002 by David Brownell * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -31,11 +31,9 @@ #include #include #include +#include #include /* for UTS_SYSNAME */ -#ifndef CONFIG_USB_DEBUG - #define CONFIG_USB_DEBUG /* this is experimental! */ -#endif #ifdef CONFIG_USB_DEBUG #define DEBUG @@ -104,6 +102,9 @@ /*-------------------------------------------------------------------------*/ +#define KERNEL_REL ((LINUX_VERSION_CODE >> 16) & 0x0ff) +#define KERNEL_VER ((LINUX_VERSION_CODE >> 8) & 0x0ff) + /* usb 2.0 root hub device descriptor */ static const u8 usb2_rh_dev_descriptor [18] = { 0x12, /* __u8 bLength; */ @@ -117,7 +118,7 @@ 0x00, 0x00, /* __u16 idVendor; */ 0x00, 0x00, /* __u16 idProduct; */ - 0x40, 0x02, /* __u16 bcdDevice; (v2.4) */ + KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */ 0x03, /* __u8 iManufacturer; */ 0x02, /* __u8 iProduct; */ @@ -140,7 +141,7 @@ 0x00, 0x00, /* __u16 idVendor; */ 0x00, 0x00, /* __u16 idProduct; */ - 0x40, 0x02, /* __u16 bcdDevice; (v2.4) */ + KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */ 0x03, /* __u8 iManufacturer; */ 0x02, /* __u8 iProduct; */ @@ -151,9 +152,56 @@ /*-------------------------------------------------------------------------*/ -/* Configuration descriptor for all our root hubs */ +/* Configuration descriptors for our root hubs */ + +static const u8 fs_rh_config_descriptor [] = { + + /* one configuration */ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, 0x00, /* __u16 wTotalLength; */ + 0x01, /* __u8 bNumInterfaces; (1) */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, + 6: Self-powered, + 5 Remote-wakwup, + 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* USB 1.1: + * USB 2.0, single TT organization (mandatory): + * one interface, protocol 0 + * + * USB 2.0, multiple TT organization (optional): + * two interfaces, protocols 1 (like single TT) + * and 2 (multiple TT mode) ... config is + * sometimes settable + * NOT IMPLEMENTED + */ + + /* one interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ + 0x00, /* __u8 if_iInterface; */ + + /* one endpoint (status change endpoint) */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x02, 0x00, /* __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ + 0xff /* __u8 ep_bInterval; (255ms -- usb 2.0 spec) */ +}; -static const u8 rh_config_descriptor [] = { +static const u8 hs_rh_config_descriptor [] = { /* one configuration */ 0x09, /* __u8 bLength; */ @@ -197,7 +245,7 @@ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x03, /* __u8 ep_bmAttributes; Interrupt */ 0x02, 0x00, /* __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ - 0x0c /* __u8 ep_bInterval; (12ms -- usb 2.0 spec) */ + 0x0c /* __u8 ep_bInterval; (256ms -- usb 2.0 spec) */ }; /*-------------------------------------------------------------------------*/ @@ -206,12 +254,12 @@ * helper routine for returning string descriptors in UTF-16LE * input can actually be ISO-8859-1; ASCII is its 7-bit subset */ -static int ascii2utf (char *ascii, u8 *utf, int utfmax) +static int ascii2utf (char *s, u8 *utf, int utfmax) { int retval; - for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) { - *utf++ = *ascii++ & 0x7f; + for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) { + *utf++ = *s++; *utf++ = 0; } return retval; @@ -230,8 +278,7 @@ */ static int rh_string ( int id, - struct pci_dev *pci_desc, - char *type, + struct usb_hcd *hcd, u8 *data, int len ) { @@ -245,15 +292,16 @@ // serial number } else if (id == 1) { - strcpy (buf, pci_desc->slot_name); + strcpy (buf, hcd->bus_name); // product description } else if (id == 2) { - strcpy (buf, pci_desc->name); + strcpy (buf, hcd->product_desc); // id 3 == vendor description } else if (id == 3) { - sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE, type); + sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE, + hcd->description); // unsupported IDs --> "protocol stall" } else @@ -315,14 +363,17 @@ len = 18; break; case USB_DT_CONFIG << 8: - bufp = rh_config_descriptor; - len = sizeof rh_config_descriptor; + if (hcd->driver->flags & HCD_USB2) { + bufp = hs_rh_config_descriptor; + len = sizeof hs_rh_config_descriptor; + } else { + bufp = fs_rh_config_descriptor; + len = sizeof fs_rh_config_descriptor; + } break; case USB_DT_STRING << 8: urb->actual_length = rh_string ( - wValue & 0xff, - hcd->pdev, - (char *) hcd->description, + wValue & 0xff, hcd, ubuf, wLength); break; default: @@ -412,10 +463,8 @@ init_timer (&hcd->rh_timer); hcd->rh_timer.function = rh_report_status; hcd->rh_timer.data = (unsigned long) urb; - hcd->rh_timer.expires = jiffies - + (HZ * (urb->interval < 30 - ? 30 - : urb->interval)) / 1000; + /* USB 2.0 spec says 256msec; this is close enough */ + hcd->rh_timer.expires = jiffies + HZ/4; add_timer (&hcd->rh_timer); return 0; } @@ -521,6 +570,7 @@ * usb_hcd_pci_probe - initialize PCI-based HCDs * @dev: USB Host Controller being probed * @id: pci hotplug id connecting controller to HCD framework + * Context: !in_interrupt() * * Allocates basic PCI resources for this USB host controller, and * then invokes the start() method for the HCD associated with it @@ -606,7 +656,7 @@ return retval; } } - dev->driver_data = hcd; + pci_set_drvdata(dev, hcd); hcd->driver = driver; hcd->description = driver->description; hcd->pdev = dev; @@ -652,6 +702,7 @@ } hcd->bus = bus; hcd->bus_name = dev->slot_name; + hcd->product_desc = dev->name; bus->hcpriv = (void *) hcd; INIT_LIST_HEAD (&hcd->dev_list); @@ -677,6 +728,7 @@ /** * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs * @dev: USB Host Controller being removed + * Context: !in_interrupt() * * Reverses the effect of usb_hcd_pci_probe(), first invoking * the HCD's stop() method. It is always called from a thread @@ -689,7 +741,7 @@ struct usb_hcd *hcd; struct usb_device *hub; - hcd = (struct usb_hcd *) dev->driver_data; + hcd = pci_get_drvdata(dev); if (!hcd) return; info ("remove: %s, state %x", hcd->bus_name, hcd->state); @@ -769,7 +821,7 @@ struct usb_hcd *hcd; int retval; - hcd = (struct usb_hcd *) dev->driver_data; + hcd = pci_get_drvdata(dev); info ("suspend %s to state %d", hcd->bus_name, state); pci_save_state (dev, hcd->pci_state); @@ -798,7 +850,7 @@ struct usb_hcd *hcd; int retval; - hcd = (struct usb_hcd *) dev->driver_data; + hcd = pci_get_drvdata(dev); info ("resume %s", hcd->bus_name); /* guard against multiple resumes (APM bug?) */ @@ -913,8 +965,29 @@ /*-------------------------------------------------------------------------*/ +static void urb_unlink (struct urb *urb) +{ + unsigned long flags; + struct usb_device *dev; + + /* Release any periodic transfer bandwidth */ + if (urb->bandwidth) + usb_release_bandwidth (urb->dev, urb, + usb_pipeisoc (urb->pipe)); + + /* clear all state linking urb to this dev (and hcd) */ + + spin_lock_irqsave (&hcd_data_lock, flags); + list_del_init (&urb->urb_list); + dev = urb->dev; + urb->dev = NULL; + usb_dec_dev_use (dev); + spin_unlock_irqrestore (&hcd_data_lock, flags); +} + + /* may be called in any context with a valid urb->dev usecount */ -/* caller surrenders "ownership" of urb (and chain at urb->next). */ +/* caller surrenders "ownership" of urb */ static int hcd_submit_urb (struct urb *urb) { @@ -922,7 +995,7 @@ struct usb_hcd *hcd; struct hcd_dev *dev; unsigned long flags; - int pipe; + int pipe, temp, max; int mem_flags; if (!urb || urb->hcpriv || !urb->complete) @@ -930,6 +1003,7 @@ urb->status = -EINPROGRESS; urb->actual_length = 0; + urb->bandwidth = 0; INIT_LIST_HEAD (&urb->urb_list); if (!urb->dev || !urb->dev->bus || urb->dev->devnum <= 0) @@ -943,16 +1017,70 @@ if (hcd->state == USB_STATE_QUIESCING || !HCD_IS_RUNNING (hcd->state)) return -ESHUTDOWN; pipe = urb->pipe; + temp = usb_pipetype (urb->pipe); if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) return -EPIPE; - // FIXME paging/swapping requests over USB should not use GFP_KERNEL - // and might even need to use GFP_NOIO ... that flag actually needs - // to be passed from the higher level. + /* NOTE: 2.5 passes this value explicitly in submit() */ mem_flags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL; + /* FIXME there should be a sharable lock protecting us against + * config/altsetting changes and disconnects, kicking in here. + */ + + /* Sanity check, so HCDs can rely on clean data */ + max = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); + if (max <= 0) { + err ("bogus endpoint (bad maxpacket)"); + return -EINVAL; + } + + /* "high bandwidth" mode, 1-3 packets/uframe? */ + if (urb->dev->speed == USB_SPEED_HIGH) { + int mult; + switch (temp) { + case PIPE_ISOCHRONOUS: + case PIPE_INTERRUPT: + mult = 1 + ((max >> 11) & 0x03); + max &= 0x03ff; + max *= mult; + } + } + + /* periodic transfers limit size per frame/uframe */ + switch (temp) { + case PIPE_ISOCHRONOUS: { + int n, len; + + if (urb->number_of_packets <= 0) + return -EINVAL; + for (n = 0; n < urb->number_of_packets; n++) { + len = urb->iso_frame_desc [n].length; + if (len < 0 || len > max) + return -EINVAL; + } + + } + break; + case PIPE_INTERRUPT: + if (urb->transfer_buffer_length > max) + return -EINVAL; + } + + /* the I/O buffer must usually be mapped/unmapped */ + if (urb->transfer_buffer_length < 0) + return -EINVAL; + + if (urb->next) { + warn ("use explicit queuing not urb->next"); + return -EINVAL; + } + #ifdef DEBUG + /* stuff that drivers shouldn't do, but which shouldn't + * cause problems in HCDs if they get it wrong. + */ { unsigned int orig_flags = urb->transfer_flags; unsigned int allowed; @@ -960,7 +1088,7 @@ /* enforce simple/standard policy */ allowed = USB_ASYNC_UNLINK; // affects later unlinks allowed |= USB_NO_FSBR; // only affects UHCI - switch (usb_pipetype (pipe)) { + switch (temp) { case PIPE_CONTROL: allowed |= USB_DISABLE_SPD; break; @@ -977,17 +1105,61 @@ } urb->transfer_flags &= allowed; - /* warn if submitter gave bogus flags */ - if (urb->transfer_flags != orig_flags) - warn ("BOGUS urb flags, %x --> %x", + /* fail if submitter gave bogus flags */ + if (urb->transfer_flags != orig_flags) { + err ("BOGUS urb flags, %x --> %x", orig_flags, urb->transfer_flags); + return -EINVAL; + } } #endif /* - * FIXME: alloc periodic bandwidth here, for interrupt and iso? - * Need to look at the ring submit mechanism for iso tds ... they - * aren't actually "periodic" in 2.4 kernels. + * Force periodic transfer intervals to be legal values that are + * a power of two (so HCDs don't need to). * + * FIXME want bus->{intr,iso}_sched_horizon values here. Each HC + * supports different values... this uses EHCI/UHCI defaults (and + * EHCI can use smaller non-default values). + */ + switch (temp) { + case PIPE_ISOCHRONOUS: + case PIPE_INTERRUPT: + /* too small? */ + if (urb->interval <= 0) + return -EINVAL; + /* too big? */ + switch (urb->dev->speed) { + case USB_SPEED_HIGH: /* units are microframes */ + // NOTE usb handles 2^15 + if (urb->interval > (1024 * 8)) + urb->interval = 1024 * 8; + temp = 1024 * 8; + break; + case USB_SPEED_FULL: /* units are frames/msec */ + case USB_SPEED_LOW: + if (temp == PIPE_INTERRUPT) { + if (urb->interval > 255) + return -EINVAL; + // NOTE ohci only handles up to 32 + temp = 128; + } else { + if (urb->interval > 1024) + urb->interval = 1024; + // NOTE usb and ohci handle up to 2^15 + temp = 1024; + } + break; + default: + return -EINVAL; + } + /* power of two? */ + while (temp > urb->interval) + temp >>= 1; + urb->interval = temp; + } + + + /* * FIXME: make urb timeouts be generic, keeping the HCD cores * as simple as possible. */ @@ -1014,20 +1186,20 @@ status = -ESHUTDOWN; } spin_unlock_irqrestore (&hcd_data_lock, flags); + if (status) + return status; - if (!status) { - if (urb->dev == hcd->bus->root_hub) - status = rh_urb_enqueue (hcd, urb); - else - status = hcd->driver->urb_enqueue (hcd, urb, mem_flags); - } - if (status) { - if (urb->dev) { - urb->status = status; - usb_hcd_giveback_urb (hcd, urb); - } - } - return 0; + if (urb->dev == hcd->bus->root_hub) + status = rh_urb_enqueue (hcd, urb); + else + status = hcd->driver->urb_enqueue (hcd, urb, mem_flags); + /* urb->dev got nulled if hcd called giveback for us + * NOTE: ref to urb->dev is a race without (2.5) refcounting, + * unless driver only returns status when it didn't giveback + */ + if (status && urb->dev) + urb_unlink (urb); + return status; } /*-------------------------------------------------------------------------*/ @@ -1043,7 +1215,7 @@ struct completion_splice { // modified urb context: /* did we complete? */ - int done; + struct completion done; /* original urb data */ void (*complete)(struct urb *); @@ -1061,7 +1233,8 @@ urb->context = splice->context; urb->complete (urb); - splice->done = 1; + /* then let the synchronous unlink call complete */ + complete (&splice->done); } /* @@ -1081,20 +1254,20 @@ if (!urb) return -EINVAL; - // FIXME: add some explicit records to flag the - // state where the URB is "in periodic completion". - // Workaround is for driver to set the urb status - // to "-EINPROGRESS", so it can get through here - // and unlink from the completion handler. - /* * we contend for urb->status with the hcd core, * which changes it while returning the urb. + * + * Caller guaranteed that the urb pointer hasn't been freed, and + * that it was submitted. But as a rule it can't know whether or + * not it's already been unlinked ... so we respect the reversed + * lock sequence needed for the usb_hcd_giveback_urb() code paths + * (urb lock, then hcd_data_lock) in case some other CPU is now + * unlinking it. */ spin_lock_irqsave (&urb->lock, flags); - if (!urb->hcpriv - || urb->status != -EINPROGRESS - || urb->transfer_flags & USB_TIMEOUT_KILLED) { + spin_lock (&hcd_data_lock); + if (!urb->hcpriv || urb->transfer_flags & USB_TIMEOUT_KILLED) { retval = -EINVAL; goto done; } @@ -1103,6 +1276,8 @@ retval = -ENODEV; goto done; } + + /* giveback clears dev; non-null means it's linked at this level */ dev = urb->dev->hcpriv; hcd = urb->dev->bus->hcpriv; if (!dev || !hcd) { @@ -1110,6 +1285,27 @@ goto done; } + /* For non-periodic transfers, any status except -EINPROGRESS means + * the HCD has already started to unlink this URB from the hardware. + * In that case, there's no more work to do. + * + * For periodic transfers, this is the only way to trigger unlinking + * from the hardware. Since we (currently) overload urb->status to + * tell the driver to unlink, error status might get clobbered ... + * unless that transfer hasn't yet restarted. One such case is when + * the URB gets unlinked from its completion handler. + * + * FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED + */ + switch (usb_pipetype (urb->pipe)) { + case PIPE_CONTROL: + case PIPE_BULK: + if (urb->status != -EINPROGRESS) { + retval = -EINVAL; + goto done; + } + } + /* maybe set up to block on completion notification */ if ((urb->transfer_flags & USB_TIMEOUT_KILLED)) urb->status = -ETIMEDOUT; @@ -1120,7 +1316,7 @@ goto done; } /* synchronous unlink: block till we see the completion */ - splice.done = 0; + init_completion (&splice.done); splice.complete = urb->complete; splice.context = urb->context; urb->complete = unlink_complete; @@ -1130,6 +1326,7 @@ /* asynchronous unlink */ urb->status = -ECONNRESET; } + spin_unlock (&hcd_data_lock); spin_unlock_irqrestore (&urb->lock, flags); if (urb == (struct urb *) hcd->rh_timer.data) { @@ -1145,17 +1342,15 @@ if (!(urb->transfer_flags & (USB_ASYNC_UNLINK|USB_TIMEOUT_KILLED)) && HCD_IS_RUNNING (hcd->state) && !retval) { - while (!splice.done) { - set_current_state (TASK_UNINTERRUPTIBLE); - schedule_timeout ((2/*msec*/ * HZ) / 1000); - dbg ("%s: wait for giveback urb %p", - hcd->bus_name, urb); - } + dbg ("%s: wait for giveback urb %p", + hcd->bus_name, urb); + wait_for_completion (&splice.done); } else if ((urb->transfer_flags & USB_ASYNC_UNLINK) && retval == 0) { return -EINPROGRESS; } goto bye; done: + spin_unlock (&hcd_data_lock); spin_unlock_irqrestore (&urb->lock, flags); bye: if (retval) @@ -1223,6 +1418,9 @@ struct usb_hcd *hcd = __hcd; int start = hcd->state; + if (unlikely (hcd->state == USB_STATE_HALT)) /* irq sharing? */ + return; + hcd->driver->irq (hcd); if (hcd->state != start && hcd->state == USB_STATE_HALT) hc_died (hcd); @@ -1234,6 +1432,7 @@ * usb_hcd_giveback_urb - return URB from HCD to device driver * @hcd: host controller returning the URB * @urb: urb being returned to the USB device driver. + * Context: in_interrupt() * * This hands the URB from HCD to its USB device driver, using its * completion function. The HCD has freed all per-urb resources @@ -1246,34 +1445,13 @@ * and will be reissued. They should just call their completion handlers * until the urb is returned to the device driver by unlinking. * - * In common cases, urb->next will be submitted before the completion - * function gets called. That's not done if the URB includes error - * status (including unlinking). + * NOTE that no urb->next processing is done, even for isochronous URBs. + * ISO streaming functionality can be achieved by having completion handlers + * re-queue URBs. Such explicit queuing doesn't discard error reports. */ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) { - unsigned long flags; - struct usb_device *dev; - - /* Release periodic transfer bandwidth */ - if (urb->bandwidth) { - switch (usb_pipetype (urb->pipe)) { - case PIPE_INTERRUPT: - usb_release_bandwidth (urb->dev, urb, 0); - break; - case PIPE_ISOCHRONOUS: - usb_release_bandwidth (urb->dev, urb, 1); - break; - } - } - - /* clear all state linking urb to this dev (and hcd) */ - - spin_lock_irqsave (&hcd_data_lock, flags); - list_del_init (&urb->urb_list); - dev = urb->dev; - urb->dev = NULL; - spin_unlock_irqrestore (&hcd_data_lock, flags); + urb_unlink (urb); // NOTE: a generic device/urb monitoring hook would go here. // hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev) @@ -1282,26 +1460,10 @@ // hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev) if (urb->status) - dbg ("giveback urb %p status %d", urb, urb->status); - - /* if no error, make sure urb->next progresses */ - else if (urb->next) { - int status; - - status = usb_submit_urb (urb->next); - if (status) { - dbg ("urb %p chain fail, %d", urb->next, status); - urb->next->status = -ENOTCONN; - } - - /* HCDs never modify the urb->next chain, and only use it here, - * so that if urb->complete sees an URB there with -ENOTCONN, - * it knows the driver chained it but it couldn't be submitted. - */ - } + dbg ("giveback urb %p status %d len %d", + urb, urb->status, urb->actual_length); /* pass ownership to the completion handler */ - usb_dec_dev_use (dev); urb->complete (urb); } EXPORT_SYMBOL (usb_hcd_giveback_urb); diff -urN linux-2.4.19-pre5/drivers/usb/hcd.h linux-2.4.19-pre6/drivers/usb/hcd.h --- linux-2.4.19-pre5/drivers/usb/hcd.h Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/usb/hcd.h Thu Apr 4 22:05:09 2002 @@ -37,7 +37,7 @@ struct list_head hcd_list; const char *bus_name; - + const char *product_desc; const char *description; /* "ehci-hcd" etc */ struct timer_list rh_timer; /* drives root hub */ diff -urN linux-2.4.19-pre5/drivers/usb/hid-core.c linux-2.4.19-pre6/drivers/usb/hid-core.c --- linux-2.4.19-pre5/drivers/usb/hid-core.c Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/usb/hid-core.c Thu Apr 4 22:05:09 2002 @@ -47,9 +47,7 @@ #include #include "hid.h" -#ifdef CONFIG_USB_HIDDEV #include -#endif /* * Version Information @@ -204,17 +202,13 @@ return -1; } - if (HID_MAIN_ITEM_VARIABLE & ~flags) { /* ARRAY */ - if (parser->global.logical_maximum <= parser->global.logical_minimum) { - dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum); - return -1; - } - usages = parser->local.usage_index; - /* Hint: we can assume usages < MAX_USAGE here */ - } else { /* VARIABLE */ - usages = parser->global.report_count; + if (parser->global.logical_maximum <= parser->global.logical_minimum) { + dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum); + return -1; } + usages = parser->local.usage_index; + offset = report->size; report->size += parser->global.report_size * parser->global.report_count; @@ -310,7 +304,10 @@ return 0; case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM: - parser->global.logical_maximum = item_sdata(item); + if (parser->global.logical_minimum < 0) + parser->global.logical_maximum = item_sdata(item); + else + parser->global.logical_maximum = item_udata(item); return 0; case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM: @@ -318,7 +315,10 @@ return 0; case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM: - parser->global.physical_maximum = item_sdata(item); + if (parser->global.physical_minimum < 0) + parser->global.physical_maximum = item_sdata(item); + else + parser->global.physical_maximum = item_udata(item); return 0; case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: @@ -735,10 +735,8 @@ hid_dump_input(usage, value); if (hid->claimed & HID_CLAIMED_INPUT) hidinput_hid_event(hid, field, usage, value); -#ifdef CONFIG_USB_HIDDEV if (hid->claimed & HID_CLAIMED_HIDDEV) hiddev_hid_event(hid, usage->hid, value); -#endif } @@ -1239,10 +1237,8 @@ if (!hidinput_connect(hid)) hid->claimed |= HID_CLAIMED_INPUT; -#ifdef CONFIG_USB_HIDDEV if (!hiddev_connect(hid)) hid->claimed |= HID_CLAIMED_HIDDEV; -#endif printk(KERN_INFO); if (hid->claimed & HID_CLAIMED_INPUT) @@ -1272,13 +1268,10 @@ dbg("cleanup called"); usb_unlink_urb(&hid->urb); - if (hid->claimed & HID_CLAIMED_INPUT) hidinput_disconnect(hid); -#ifdef CONFIG_USB_HIDDEV if (hid->claimed & HID_CLAIMED_HIDDEV) hiddev_disconnect(hid); -#endif hid_free_device(hid); } @@ -1299,9 +1292,7 @@ static int __init hid_init(void) { -#ifdef CONFIG_USB_HIDDEV hiddev_init(); -#endif usb_register(&hid_driver); info(DRIVER_VERSION " " DRIVER_AUTHOR); info(DRIVER_DESC); @@ -1311,9 +1302,7 @@ static void __exit hid_exit(void) { -#ifdef CONFIG_USB_HIDDEV hiddev_exit(); -#endif usb_deregister(&hid_driver); } diff -urN linux-2.4.19-pre5/drivers/usb/hid.h linux-2.4.19-pre6/drivers/usb/hid.h --- linux-2.4.19-pre5/drivers/usb/hid.h Thu Apr 4 22:04:24 2002 +++ linux-2.4.19-pre6/drivers/usb/hid.h Thu Apr 4 22:05:09 2002 @@ -352,9 +352,6 @@ struct hid_class_descriptor desc[1]; } __attribute__ ((packed)); -void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); -int hidinput_connect(struct hid_device *); -void hidinput_disconnect(struct hid_device *); #ifdef DEBUG #include "hid-debug.h" @@ -365,7 +362,17 @@ #endif +#ifdef CONFIG_USB_HIDINPUT #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || ( a == 0x000c0001)) +extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); +extern int hidinput_connect(struct hid_device *); +extern void hidinput_disconnect(struct hid_device *); +#else +#define IS_INPUT_APPLICATION(a) (0) +static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { } +static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; } +static inline void hidinput_disconnect(struct hid_device *hid) { } +#endif int hid_open(struct hid_device *); void hid_close(struct hid_device *); diff -urN linux-2.4.19-pre5/drivers/usb/pegasus.c linux-2.4.19-pre6/drivers/usb/pegasus.c --- linux-2.4.19-pre5/drivers/usb/pegasus.c Thu Apr 4 22:04:25 2002 +++ linux-2.4.19-pre6/drivers/usb/pegasus.c Thu Apr 4 22:05:10 2002 @@ -484,14 +484,12 @@ __u8 data[4]; pegasus_t *pegasus = dev->priv; - - if ( read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr) ) - return 1; -#if 0 - if ( !(bmsr & 0x20) && !loopback ) + /* read twice 'cos this is a latch bit */ + read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr); + read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr); + if ( !(bmsr & 4) && !loopback ) warn( "%s: link NOT established (0x%x) - check the cable.", dev->name, bmsr ); -#endif if ( read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart) ) return 2; if ( !(linkpart & 1) ) @@ -1021,11 +1019,11 @@ usb_free_urb (pegasus->rx_urb); usb_free_urb (pegasus->ctrl_urb); kfree( pegasus ); - pegasus = NULL; - goto exit; + return NULL; } init_MUTEX(&pegasus->sem); + down(&pegasus->sem); pegasus->usb = dev; pegasus->net = net; SET_MODULE_OWNER(net); @@ -1072,7 +1070,7 @@ } exit: - up(&gsem); + up(&pegasus->sem); return pegasus; } diff -urN linux-2.4.19-pre5/drivers/usb/rtl8150.c linux-2.4.19-pre6/drivers/usb/rtl8150.c --- linux-2.4.19-pre5/drivers/usb/rtl8150.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.19-pre6/drivers/usb/rtl8150.c Thu Apr 4 22:05:10 2002 @@ -0,0 +1,762 @@ +/* + * Copyright (c) 2002 Petko Manolov (petkan@users.sourceforge.net) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +/* Version Information */ +#define DRIVER_VERSION "v0.4.0 (2002/03/28)" +#define DRIVER_AUTHOR "Petko Manolov " +#define DRIVER_DESC "rtl8150 based usb-ethernet driver" + + +#define IRD 0x0120 +#define MAR 0x0126 +#define CR 0x012e +#define TCR 0x012f +#define RCR 0x0130 +#define TSR 0x0132 +#define RSR 0x0133 +#define CON0 0x0135 +#define CON1 0x0136 +#define MSR 0x0137 +#define PHYADD 0x0138 +#define PHYDAT 0x0139 +#define PHYCNT 0x013b +#define GPPC 0x013d +#define BMCR 0x0140 +#define BMSR 0x0142 +#define ANAR 0x0144 +#define ANLP 0x0146 +#define AER 0x0148 + +#define PHY_READ 0 +#define PHY_WRITE 0x20 +#define PHY_GO 0x40 + +#define RTL8150_REQT_READ 0xc0 +#define RTL8150_REQT_WRITE 0x40 +#define RTL8150_REQ_GET_REGS 0x05 +#define RTL8150_REQ_SET_REGS 0x05 + +#define RTL8150_MTU 1500 +#define RTL8150_MAX_MTU 1536 + +#define RTL8150_TX_TIMEOUT (HZ) + +/* rtl8150 flags */ +#define RTL8150_FLAG_HWCRC 0 +#define RX_REG_SET 1 +#define RTL8150_UNPLUG 2 + + +/* Define these values to match your device */ +#define VENDOR_ID_REALTEK 0x0bda +#define PRODUCT_ID_RTL8150 0x8150 + +/* table of devices that work with this driver */ +static struct usb_device_id rtl8150_table [] = { + { USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8150) }, + { } +}; + +MODULE_DEVICE_TABLE (usb, rtl8150_table); + + +struct rtl8150 { + unsigned int flags; + struct usb_device *udev; + struct usb_interface *interface; + struct semaphore sem; + struct net_device_stats stats; + struct net_device *netdev; + struct urb *rx_urb, *tx_urb, *intr_urb, *ctrl_urb; + devrequest dr; + int intr_interval; + u16 rx_creg; + u8 rx_buff[RTL8150_MAX_MTU]; + u8 tx_buff[RTL8150_MAX_MTU]; + u8 intr_buff[8]; + u8 phy; +}; + +typedef struct rtl8150 rtl8150_t; + + +/* the global usb devfs handle */ +extern devfs_handle_t usb_devfs_handle; +unsigned long multicast_filter_limit = 32; + + +static void rtl8150_disconnect(struct usb_device *dev, void *ptr); +static void * rtl8150_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id); + + +static struct usb_driver rtl8150_driver = { + name: "rtl8150", + probe: rtl8150_probe, + disconnect: rtl8150_disconnect, + id_table: rtl8150_table, +}; + + + +/* +** +** device related part of the code +** +*/ +static int get_registers(rtl8150_t *dev, u16 indx, u16 size, void *data) +{ + return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev,0), + RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, + indx, 0, data, size, HZ/2); +} + + +static int set_registers(rtl8150_t *dev, u16 indx, u16 size, void *data) +{ + return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev,0), + RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, + indx, 0, data, size, HZ/2); +} + + +static void ctrl_callback(struct urb *urb) +{ + rtl8150_t *dev; + + switch (urb->status) { + case 0: + break; + case -EINPROGRESS: + break; + case -ENOENT: + break; + default: + warn("ctrl urb status %d", urb->status); + } + dev = urb->context; + clear_bit(RX_REG_SET, &dev->flags); +} + + +static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, void *data) +{ + int ret; + + if (test_bit(RX_REG_SET, &dev->flags)) + return -EAGAIN; + + dev->dr.requesttype = RTL8150_REQT_WRITE; + dev->dr.request = RTL8150_REQ_SET_REGS; + dev->dr.value = cpu_to_le16(indx); + dev->dr.index = 0; + dev->dr.length = cpu_to_le16(2); + dev->ctrl_urb->transfer_buffer_length = 2; + FILL_CONTROL_URB(dev->ctrl_urb, dev->udev, usb_sndctrlpipe(dev->udev,0), + (char*)&dev->dr, &dev->rx_creg, 2, ctrl_callback, dev); + if ((ret = usb_submit_urb(dev->ctrl_urb))) + err("control request submission failed: %d", ret); + else + set_bit(RX_REG_SET, &dev->flags); + + return ret; +} + + +static int read_mii_word(rtl8150_t *dev, u8 phy, __u8 indx, u16 *reg) +{ + int i; + u8 data[3], tmp; + + data[0] = phy; + data[1] = data[2] = 0; + tmp = indx | PHY_READ | PHY_GO; + i = 0; + + set_registers(dev, PHYADD, sizeof(data), data); + set_registers(dev, PHYCNT, 1, &tmp); + do { + get_registers(dev, PHYCNT, 1, data); + } while ((data[0] & PHY_GO) && (i++ < HZ)); + + if (i < HZ) { + get_registers(dev, PHYDAT, 2, data); + *reg = le16_to_cpup(data); + return 0; + } else + return 1; +} + + +static int write_mii_word(rtl8150_t *dev, u8 phy, __u8 indx, u16 reg) +{ + int i; + u8 data[3], tmp; + + data[0] = phy; + *(data + 1) = cpu_to_le16p(®); + tmp = indx | PHY_WRITE | PHY_GO; + i = 0; + + set_registers(dev, PHYADD, sizeof(data), data); + set_registers(dev, PHYCNT, 1, &tmp); + do { + get_registers(dev, PHYCNT, 1, data); + } while((data[0] & PHY_GO) && (i++ < HZ)); + + if (i < HZ) + return 0; + else + return 1; +} + + +static inline void set_ethernet_addr(rtl8150_t *dev) +{ + u8 node_id[6]; + + get_registers(dev, IRD, sizeof(node_id), node_id); + memcpy(dev->netdev->dev_addr, node_id, sizeof(node_id)); +} + + +static int rtl8150_reset(rtl8150_t *dev) +{ + u8 data=0x10; + int i=HZ; + + set_registers(dev, CR, 1, &data); + do { + get_registers(dev, CR, 1, &data); + } while ((data & 0x10) && --i); + + return (i > 0) ? 0 : -1; +} + + +static int alloc_all_urbs(rtl8150_t *dev) +{ + dev->rx_urb = usb_alloc_urb(0); + if (!dev->rx_urb) + return 0; + dev->tx_urb = usb_alloc_urb(0); + if (!dev->tx_urb) { + usb_free_urb(dev->rx_urb); + return 0; + } + dev->intr_urb = usb_alloc_urb(0); + if (!dev->intr_urb) { + usb_free_urb(dev->rx_urb); + usb_free_urb(dev->tx_urb); + return 0; + } + dev->ctrl_urb = usb_alloc_urb(0); + if (!dev->ctrl_urb) { + usb_free_urb(dev->rx_urb); + usb_free_urb(dev->tx_urb); + usb_free_urb(dev->intr_urb); + return 0; + } + + return 1; +} + + +static void free_all_urbs(rtl8150_t *dev) +{ + usb_free_urb(dev->rx_urb); + usb_free_urb(dev->tx_urb); + usb_free_urb(dev->intr_urb); + usb_free_urb(dev->ctrl_urb); +} + + +static void unlink_all_urbs(rtl8150_t *dev) +{ + usb_unlink_urb(dev->rx_urb); + usb_unlink_urb(dev->tx_urb); + usb_unlink_urb(dev->intr_urb); + usb_unlink_urb(dev->ctrl_urb); +} + + +static void read_bulk_callback(struct urb *urb) +{ + rtl8150_t *dev; + int pkt_len, res; + struct sk_buff *skb; + struct net_device *netdev; + u16 rx_stat; + + dev = urb->context; + if (!dev) { + warn("!dev"); + return; + } + netdev = dev->netdev; + if (!netif_device_present(netdev)) { + warn("netdev is not present"); + return; + } + switch (urb->status) { + case 0: + break; + case -ENOENT: + return; + case -ETIMEDOUT: + warn("reset needed may be?.."); + goto goon; + default: + warn("Rx status %d", urb->status); + goto goon; + } + + pkt_len = urb->actual_length - 4; + rx_stat = le16_to_cpu(*(u16 *)(dev->rx_buff + pkt_len)); + + if (!(skb = dev_alloc_skb(pkt_len + 2))) + goto goon; + skb->dev = netdev; + skb_reserve(skb, 2); + eth_copy_and_sum(skb, dev->rx_buff, pkt_len, 0); + skb_put(skb, pkt_len); + skb->protocol = eth_type_trans(skb, netdev); + netif_rx(skb); + dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; +goon: + FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev,1), + dev->rx_buff, RTL8150_MAX_MTU, read_bulk_callback, dev); + if ((res=usb_submit_urb(dev->rx_urb))) + warn("%s: Rx urb submission failed %d", netdev->name, res); +} + + +static void write_bulk_callback(struct urb *urb) +{ + rtl8150_t *dev; + + dev = urb->context; + if (!dev) + return; + if (!netif_device_present(dev->netdev)) + return; + if (urb->status) + info("%s: Tx status %d", dev->netdev->name, urb->status); + dev->netdev->trans_start = jiffies; + netif_wake_queue(dev->netdev); +} + + +void intr_callback(struct urb *urb) +{ + rtl8150_t *dev; + + dev = urb->context; + if (!dev) + return; + switch (urb->status) { + case 0: + break; + case -ENOENT: + return; + default: + info("%s: intr status %d", dev->netdev->name, + urb->status); + } +} + + +/* +** +** network related part of the code +** +*/ + + +static int enable_net_traffic(rtl8150_t *dev) +{ + u8 cr, tcr, rcr, msr; + + if (rtl8150_reset(dev)) { + warn("%s - device reset failed", __FUNCTION__); + } + dev->rx_creg = rcr = 0x9e; /* bit7=1 attach Rx info at the end */ + tcr = 0xd8; + cr = 0x0c; + set_registers(dev, RCR, 1, &rcr); + set_registers(dev, TCR, 1, &tcr); + set_registers(dev, CR, 1, &cr); + get_registers(dev, MSR, 1, &msr); + + return 0; +} + + +static void disable_net_traffic(rtl8150_t *dev) +{ + u8 cr; + + get_registers(dev, CR, 1, &cr); + cr &= 0xf3; + set_registers(dev, CR, 1, &cr); +} + + +static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev) +{ + return &((rtl8150_t *)dev->priv)->stats; +} + + +static void rtl8150_tx_timeout(struct net_device *netdev) +{ + rtl8150_t *dev; + + dev = netdev->priv; + if (!dev) + return; + warn("%s: Tx timeout.", netdev->name); + dev->tx_urb->transfer_flags |= USB_ASYNC_UNLINK; + usb_unlink_urb(dev->tx_urb); + dev->stats.tx_errors++; +} + + +static void rtl8150_set_multicast(struct net_device *netdev) +{ + rtl8150_t *dev; + + dev = netdev->priv; + netif_stop_queue(netdev); + if (netdev->flags & IFF_PROMISC) { + dev->rx_creg |= 0x0001; + info("%s: promiscuous mode", netdev->name); + } else if ((netdev->mc_count > multicast_filter_limit) || + (netdev->flags & IFF_ALLMULTI)) { + dev->rx_creg &= 0xfffe; + dev->rx_creg |= 0x0002; + info("%s: allmulti set", netdev->name); + } else { + /* ~RX_MULTICAST, ~RX_PROMISCUOUS */ + dev->rx_creg &= 0x00fc; + } + async_set_registers(dev, RCR, 2, &dev->rx_creg); + netif_wake_queue(netdev); +} + + +static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + rtl8150_t *dev; + int count, res; + + netif_stop_queue(netdev); + dev = netdev->priv; + count = (skb->len < 60) ? 60 : skb->len; + count = (count & 0x3f) ? count : count + 1; + memcpy(dev->tx_buff, skb->data, skb->len); + FILL_BULK_URB(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev,2), + dev->tx_buff, RTL8150_MAX_MTU, write_bulk_callback, dev); + dev->tx_urb->transfer_buffer_length = count; + + if ((res = usb_submit_urb(dev->tx_urb))) { + warn("failed tx_urb %d\n", res); + dev->stats.tx_errors++; + netif_start_queue(netdev); + } else { + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + netdev->trans_start = jiffies; + } + dev_kfree_skb(skb); + + return 0; +} + + +static int rtl8150_open(struct net_device *netdev) +{ + rtl8150_t *dev; + int res; + + dev = netdev->priv; + if (dev == NULL) { + return -ENODEV; + } + + down(&dev->sem); + FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev,1), + dev->rx_buff, RTL8150_MAX_MTU, read_bulk_callback, dev); + if ((res=usb_submit_urb(dev->rx_urb))) + warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); + FILL_INT_URB(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev,3), + dev->intr_buff, sizeof(dev->intr_buff), intr_callback, + dev, dev->intr_interval); + if ((res=usb_submit_urb(dev->intr_urb))) + warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); + netif_start_queue(netdev); + enable_net_traffic(dev); + up(&dev->sem); + + return res; +} + + +static int rtl8150_close(struct net_device *netdev) +{ + rtl8150_t *dev; + int res = 0; + + dev = netdev->priv; + if (!dev) + return -ENODEV; + + down(&dev->sem); + if (!test_bit(RTL8150_UNPLUG, &dev->flags)) + disable_net_traffic(dev); + unlink_all_urbs(dev); + netif_stop_queue(netdev); + up(&dev->sem); + + return res; +} + + +static int rtl8150_ethtool_ioctl(struct net_device *netdev, void *uaddr) +{ + rtl8150_t *dev; + int cmd; + char tmp[128]; + + dev = netdev->priv; + if (get_user(cmd, (int *)uaddr)) + return -EFAULT; + + switch (cmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; + + strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN); + strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); + sprintf(tmp, "usb%d:%d", dev->udev->bus->busnum, + dev->udev->devnum); + strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN); + if (copy_to_user(uaddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + case ETHTOOL_GSET: { + struct ethtool_cmd ecmd; + short lpa, bmcr; + + if (copy_from_user(&ecmd, uaddr, sizeof(ecmd))) + return -EFAULT; + ecmd.supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP | + SUPPORTED_MII); + ecmd.port = PORT_TP; + ecmd.transceiver = XCVR_INTERNAL; + ecmd.phy_address = dev->phy; + get_registers(dev, BMCR, 2, &bmcr); + get_registers(dev, ANLP, 2, &lpa); + if (bmcr & BMCR_ANENABLE) { + ecmd.autoneg = AUTONEG_ENABLE; + ecmd.speed = (lpa & (LPA_100HALF | LPA_100FULL)) ? + SPEED_100 : SPEED_10; + if (ecmd.speed == SPEED_100) + ecmd.duplex = (lpa & LPA_100FULL) ? + DUPLEX_FULL : DUPLEX_HALF; + else + ecmd.duplex = (lpa & LPA_10FULL) ? + DUPLEX_FULL : DUPLEX_HALF; + } else { + ecmd.autoneg = AUTONEG_DISABLE; + ecmd.speed = (bmcr & BMCR_SPEED100) ? + SPEED_100 : SPEED_10; + ecmd.duplex = (bmcr & BMCR_FULLDPLX) ? + DUPLEX_FULL : DUPLEX_HALF; + } + if (copy_to_user(uaddr, &ecmd, sizeof(ecmd))) + return -EFAULT; + return 0; + } + case ETHTOOL_SSET: + return -ENOTSUPP; + case ETHTOOL_GLINK: { + struct ethtool_value edata = {ETHTOOL_GLINK}; + + edata.data = netif_carrier_ok(netdev); + if (copy_to_user(uaddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + default: + return -EOPNOTSUPP; + } +} + + +static int rtl8150_ioctl (struct net_device *netdev, struct ifreq *rq, int cmd) +{ + rtl8150_t *dev; + u16 *data; + int res; + + dev = netdev->priv; + data = (u16 *)&rq->ifr_data; + res = 0; + + down(&dev->sem); + switch (cmd) { + case SIOCETHTOOL: + res = rtl8150_ethtool_ioctl(netdev, rq->ifr_data); + break; + case SIOCDEVPRIVATE: + data[0] = dev->phy; + case SIOCDEVPRIVATE+1: + read_mii_word(dev, dev->phy, (data[1] & 0x1f), &data[3]); + break; + case SIOCDEVPRIVATE+2: + if (!capable(CAP_NET_ADMIN)) { + up(&dev->sem); + return -EPERM; + } + write_mii_word(dev, dev->phy, (data[1] & 0x1f), data[2]); + break; + default: + res = -EOPNOTSUPP; + } + up(&dev->sem); + + return res; +} + + +static void * rtl8150_probe(struct usb_device *udev, unsigned int ifnum, + const struct usb_device_id *id) +{ + rtl8150_t *dev; + struct net_device *netdev; + + udev->config[0].bConfigurationValue = 1; + if (usb_set_configuration(udev, udev->config[0].bConfigurationValue)) { + err("usb_set_configuration() failed"); + return NULL; + } + if ((udev->descriptor.idVendor != VENDOR_ID_REALTEK) || + (udev->descriptor.idProduct != PRODUCT_ID_RTL8150)) { + err("Not the one we are interested about"); + return NULL; + } + dev = kmalloc(sizeof(rtl8150_t), GFP_KERNEL); + if (!dev) { + err ("Out of memory"); + goto exit; + } else + memset(dev, 0, sizeof(rtl8150_t)); + + netdev = init_etherdev(NULL, 0); + if (!netdev) { + kfree(dev); + err("Oh boy, out of memory again?!?"); + dev = NULL; + goto exit; + } + + init_MUTEX(&dev->sem); + dev->udev = udev; + dev->netdev = netdev; + SET_MODULE_OWNER(netdev); + netdev->priv = dev; + netdev->open = rtl8150_open; + netdev->stop = rtl8150_close; + netdev->do_ioctl = rtl8150_ioctl; + netdev->watchdog_timeo = RTL8150_TX_TIMEOUT; + netdev->tx_timeout = rtl8150_tx_timeout; + netdev->hard_start_xmit = rtl8150_start_xmit; + netdev->set_multicast_list = rtl8150_set_multicast; + netdev->get_stats = rtl8150_netdev_stats; + netdev->mtu = RTL8150_MTU; + dev->intr_interval = 100; /* 100ms */ + + if (rtl8150_reset(dev) || !alloc_all_urbs(dev)) { + err("couldn't reset the device"); + free_all_urbs(dev); + unregister_netdev(dev->netdev); + kfree(netdev); + kfree(dev); + dev = NULL; + goto exit; + } + + set_ethernet_addr(dev); + /* let's not be very nasty :-) */ + info("%s: rtl8150 is detected", netdev->name); +exit: + return dev; +} + + +static void rtl8150_disconnect(struct usb_device *udev, void *ptr) +{ + rtl8150_t *dev; + + dev = ptr; + set_bit(RTL8150_UNPLUG, &dev->flags); + unregister_netdev(dev->netdev); + unlink_all_urbs(dev); + free_all_urbs(dev); + kfree(dev->netdev); + kfree(dev); + dev->netdev = NULL; + dev = NULL; +} + + + +static int __init usb_rtl8150_init(void) +{ + info(DRIVER_DESC " " DRIVER_VERSION); + return usb_register(&rtl8150_driver); +} + + +static void __exit usb_rtl8150_exit(void) +{ + usb_deregister(&rtl8150_driver); +} + + +module_init(usb_rtl8150_init); +module_exit(usb_rtl8150_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff -urN linux-2.4.19-pre5/drivers/usb/serial/visor.c linux-2.4.19-pre6/drivers/usb/serial/visor.c --- linux-2.4.19-pre5/drivers/usb/serial/visor.c Thu Apr 4 22:04:25 2002 +++ linux-2.4.19-pre6/drivers/usb/serial/visor.c Thu Apr 4 22:05:10 2002 @@ -11,7 +11,11 @@ * (at your option) any later version. * * See Documentation/usb/usb-serial.txt for more information on using this driver - * + * + * (03/23/2002) gkh + * Added support for the Palm i705 device, thanks to Thomas Riemer + * for the information. + * * (03/21/2002) gkh * Added support for the Palm m130 device, thanks to Udo Eisenbarth * for the information. @@ -173,6 +177,7 @@ { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) }, { } /* Terminating entry */ }; @@ -194,6 +199,7 @@ { USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) }, diff -urN linux-2.4.19-pre5/drivers/usb/serial/visor.h linux-2.4.19-pre6/drivers/usb/serial/visor.h --- linux-2.4.19-pre5/drivers/usb/serial/visor.h Thu Apr 4 22:04:25 2002 +++ linux-2.4.19-pre6/drivers/usb/serial/visor.h Thu Apr 4 22:05:10 2002 @@ -24,6 +24,7 @@ #define PALM_M500_ID 0x0001 #define PALM_M505_ID 0x0002 #define PALM_M515_ID 0x0003 +#define PALM_I705_ID 0x0020 #define PALM_M125_ID 0x0040 #define PALM_M130_ID 0x0050 diff -urN linux-2.4.19-pre5/drivers/usb/uhci.c linux-2.4.19-pre6/drivers/usb/uhci.c --- linux-2.4.19-pre5/drivers/usb/uhci.c Thu Apr 4 22:04:25 2002 +++ linux-2.4.19-pre6/drivers/usb/uhci.c Thu Apr 4 22:05:10 2002 @@ -336,6 +336,7 @@ qh->link = UHCI_PTR_TERM; qh->dev = dev; + qh->urbp = NULL; INIT_LIST_HEAD(&qh->list); INIT_LIST_HEAD(&qh->remove_list); @@ -410,20 +411,19 @@ spin_unlock_irqrestore(&uhci->frame_list_lock, flags); } -static void uhci_remove_qh(struct uhci *uhci, struct urb *urb) +static void uhci_remove_qh(struct uhci *uhci, struct uhci_qh *qh) { - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; unsigned long flags; - struct uhci_qh *qh = urbp->qh, *pqh; + struct uhci_qh *pqh; if (!qh) return; + qh->urbp = NULL; + /* Only go through the hoops if it's actually linked in */ spin_lock_irqsave(&uhci->frame_list_lock, flags); if (!list_empty(&qh->list)) { - qh->urbp = NULL; - pqh = list_entry(qh->list.prev, struct uhci_qh, list); if (pqh->urbp) { @@ -1040,7 +1040,7 @@ urbp->short_control_packet = 1; /* Create a new QH to avoid pointer overwriting problems */ - uhci_remove_qh(uhci, urb); + uhci_remove_qh(uhci, urbp->qh); /* Delete all of the TD's except for the status TD at the end */ head = &urbp->td_list; @@ -1259,20 +1259,29 @@ data); data += pktsze; - len -= pktsze; + len -= maxsze; usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); } while (len > 0); + /* + * USB_ZERO_PACKET means adding a 0-length packet, if + * direction is OUT and the transfer_length was an + * exact multiple of maxsze, hence + * (len = transfer_length - N * maxsze) == 0 + * however, if transfer_length == 0, the zero packet + * was already prepared above. + */ if (usb_pipeout(urb->pipe) && (urb->transfer_flags & USB_ZERO_PACKET) && - urb->transfer_buffer_length) { + !len && urb->transfer_buffer_length) { td = uhci_alloc_td(uhci, urb->dev); if (!td) return -ENOMEM; uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | UHCI_NULL_DATA_SIZE | + uhci_fill_td(td, status, destination | + (UHCI_NULL_DATA_SIZE << 21) | (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE), data); @@ -1728,7 +1737,8 @@ uhci_delete_queued_urb(uhci, urb); /* The interrupt loop will reclaim the QH's */ - uhci_remove_qh(uhci, urb); + uhci_remove_qh(uhci, urbp->qh); + urbp->qh = NULL; } static int uhci_unlink_urb(struct urb *urb) @@ -2351,15 +2361,15 @@ urb->dev = NULL; spin_unlock_irqrestore(&urb->lock, flags); - if (urb->complete) { + if (urb->complete) urb->complete(urb); + if (resubmit_interrupt) /* Recheck the status. The completion handler may have */ /* unlinked the resubmitting interrupt URB */ killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED || urb->status == -ECONNRESET); - } if (resubmit_interrupt && !killed) { urb->dev = dev; diff -urN linux-2.4.19-pre5/drivers/usb/usb-ohci.c linux-2.4.19-pre6/drivers/usb/usb-ohci.c --- linux-2.4.19-pre5/drivers/usb/usb-ohci.c Thu Apr 4 22:04:25 2002 +++ linux-2.4.19-pre6/drivers/usb/usb-ohci.c Thu Apr 4 22:05:10 2002 @@ -12,9 +12,10 @@ * * History: * + * 2002/03/08 interrupt unlink fix (Matt Hughes), better cleanup on + * load failure (Matthew Frederickson) * 2002/01/20 async unlink fixes: return -EINPROGRESS (per spec) and * make interrupt unlink-in-completion work (db) - * * 2001/09/19 USB_ZERO_PACKET support (Jean Tourrilhes) * 2001/07/17 power management and pmac cleanup (Benjamin Herrenschmidt) * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam); @@ -1076,6 +1077,28 @@ /*-------------------------------------------------------------------------*/ +/* scan the periodic table to find and unlink this ED */ +static void periodic_unlink ( + struct ohci *ohci, + struct ed *ed, + unsigned index, + unsigned period +) { + for (; index < NUM_INTS; index += period) { + __u32 *ed_p = &ohci->hcca->int_table [index]; + + /* ED might have been unlinked through another path */ + while (*ed_p != 0) { + if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) { + *ed_p = ed->hwNextED; + break; + } + ed_p = & ((dma_to_ed (ohci, + le32_to_cpup (ed_p)))->hwNextED); + } + } +} + /* unlink an ed from one of the HC chains. * just the link to the ed is unlinked. * the link from the ed still points to another operational ed or 0 @@ -1083,11 +1106,7 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed) { - int int_branch; int i; - int inter; - int interval; - __u32 * ed_p; ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); @@ -1127,21 +1146,8 @@ break; case PIPE_INTERRUPT: - int_branch = ed->int_branch; - interval = ed->int_interval; - - for (i = 0; i < ep_rev (6, interval); i += inter) { - for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]), inter = 1; - (*ed_p != 0) && (*ed_p != ed->hwNextED); - ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED), - inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval)) { - if((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) { - *ed_p = ed->hwNextED; - break; - } - } - } - for (i = int_branch; i < 32; i += interval) + periodic_unlink (ohci, ed, 0, 1); + for (i = ed->int_branch; i < 32; i += ed->int_interval) ohci->ohci_int_load[i] -= ed->int_load; #ifdef DEBUG ep_print_int_eds (ohci, "UNLINK_INT"); @@ -1152,23 +1158,13 @@ if (ohci->ed_isotail == ed) ohci->ed_isotail = ed->ed_prev; if (ed->hwNextED != 0) - (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; + (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED))) + ->ed_prev = ed->ed_prev; - if (ed->ed_prev != NULL) { + if (ed->ed_prev != NULL) ed->ed_prev->hwNextED = ed->hwNextED; - } else { - for (i = 0; i < 32; i++) { - for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i)]); - *ed_p != 0; - ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) { - // inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval); - if((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) { - *ed_p = ed->hwNextED; - break; - } - } - } - } + else + periodic_unlink (ohci, ed, 0, 1); #ifdef DEBUG ep_print_int_eds (ohci, "UNLINK_ISO"); #endif @@ -2354,7 +2350,6 @@ static ohci_t * __devinit hc_alloc_ohci (struct pci_dev *dev, void * mem_base) { ohci_t * ohci; - struct usb_bus * bus; ohci = (ohci_t *) kmalloc (sizeof *ohci, GFP_KERNEL); if (!ohci) @@ -2383,14 +2378,15 @@ INIT_LIST_HEAD (&ohci->timeout_list); - bus = usb_alloc_bus (&sohci_device_operations); - if (!bus) { + ohci->bus = usb_alloc_bus (&sohci_device_operations); + if (!ohci->bus) { + pci_set_drvdata (dev, NULL); + pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca, + ohci->hcca, ohci->hcca_dma); kfree (ohci); return NULL; } - - ohci->bus = bus; - bus->hcpriv = (void *) ohci; + ohci->bus->hcpriv = (void *) ohci; return ohci; } @@ -2416,9 +2412,11 @@ ohci->irq = -1; } pci_set_drvdata(ohci->ohci_dev, NULL); - - usb_deregister_bus (ohci->bus); - usb_free_bus (ohci->bus); + if (ohci->bus) { + if (ohci->bus->busnum) + usb_deregister_bus (ohci->bus); + usb_free_bus (ohci->bus); + } list_del (&ohci->ohci_hcd_list); INIT_LIST_HEAD (&ohci->ohci_hcd_list); @@ -2566,12 +2564,14 @@ { unsigned long mem_resource, mem_len; void *mem_base; + int status; if (pci_enable_device(dev) < 0) return -ENODEV; if (!dev->irq) { err("found OHCI device with no IRQ assigned. check BIOS settings!"); + pci_disable_device (dev); return -ENODEV; } @@ -2580,19 +2580,28 @@ mem_len = pci_resource_len(dev, 0); if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) { dbg ("controller already in use"); + pci_disable_device (dev); return -EBUSY; } mem_base = ioremap_nocache (mem_resource, mem_len); if (!mem_base) { err("Error mapping OHCI memory"); + release_mem_region (mem_resource, mem_len); + pci_disable_device (dev); return -EFAULT; } /* controller writes into our memory */ pci_set_master (dev); - return hc_found_ohci (dev, dev->irq, mem_base, id); + status = hc_found_ohci (dev, dev->irq, mem_base, id); + if (status < 0) { + iounmap (mem_base); + release_mem_region (mem_resource, mem_len); + pci_disable_device (dev); + } + return status; } /*-------------------------------------------------------------------------*/ @@ -2630,6 +2639,7 @@ hc_release_ohci (ohci); release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0)); + pci_disable_device (dev); } diff -urN linux-2.4.19-pre5/drivers/usb/usb-uhci.c linux-2.4.19-pre6/drivers/usb/usb-uhci.c --- linux-2.4.19-pre5/drivers/usb/usb-uhci.c Mon Feb 25 11:38:07 2002 +++ linux-2.4.19-pre6/drivers/usb/usb-uhci.c Thu Apr 4 22:05:10 2002 @@ -170,7 +170,7 @@ #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH _static void enable_desc_loop(uhci_t *s, urb_t *urb) { - int flags; + unsigned long flags; if (urb->transfer_flags & USB_NO_FSBR) return; @@ -185,7 +185,7 @@ /*-------------------------------------------------------------------*/ _static void disable_desc_loop(uhci_t *s, urb_t *urb) { - int flags; + unsigned long flags; if (urb->transfer_flags & USB_NO_FSBR) return; diff -urN linux-2.4.19-pre5/drivers/usb/usbnet.c linux-2.4.19-pre6/drivers/usb/usbnet.c --- linux-2.4.19-pre5/drivers/usb/usbnet.c Mon Feb 25 11:38:07 2002 +++ linux-2.4.19-pre6/drivers/usb/usbnet.c Thu Apr 4 22:05:10 2002 @@ -989,9 +989,8 @@ || skb->len > FRAMED_SIZE (dev->net.mtu)) { dev->stats.rx_frame_errors++; dbg ("rx framesize %d range %d..%d mtu %d", skb->len, - MIN_FRAMED, FRAMED_SIZE (dev->net.mtu), - dev->net.mtu - ); + (int)MIN_FRAMED, (int)FRAMED_SIZE (dev->net.mtu), + dev->net.mtu); return 0; } diff -urN linux-2.4.19-pre5/fs/Config.in linux-2.4.19-pre6/fs/Config.in --- linux-2.4.19-pre5/fs/Config.in Thu Apr 4 22:04:27 2002 +++ linux-2.4.19-pre6/fs/Config.in Thu Apr 4 22:05:12 2002 @@ -21,7 +21,7 @@ dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL -tristate 'Ext3 journalling file system support (EXPERIMENTAL)' CONFIG_EXT3_FS +tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS # CONFIG_JBD could be its own option (even modular), but until there are # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS @@ -45,7 +45,7 @@ fi tristate 'Compressed ROM file system support' CONFIG_CRAMFS bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS -tristate 'Simple RAM-based file system support' CONFIG_RAMFS +define_bool CONFIG_RAMFS y tristate 'ISO 9660 CDROM file system support' CONFIG_ISO9660_FS dep_mbool ' Microsoft Joliet CDROM extensions' CONFIG_JOLIET $CONFIG_ISO9660_FS diff -urN linux-2.4.19-pre5/fs/block_dev.c linux-2.4.19-pre6/fs/block_dev.c --- linux-2.4.19-pre5/fs/block_dev.c Mon Feb 25 11:38:08 2002 +++ linux-2.4.19-pre6/fs/block_dev.c Thu Apr 4 22:05:12 2002 @@ -616,7 +616,7 @@ down(&bdev->bd_sem); lock_kernel(); - if (kind == BDEV_FILE) + if (kind == BDEV_FILE && bdev->bd_openers == 1) __block_fsync(bd_inode); else if (kind == BDEV_FS) fsync_no_super(rdev); diff -urN linux-2.4.19-pre5/fs/coda/cache.c linux-2.4.19-pre6/fs/coda/cache.c --- linux-2.4.19-pre5/fs/coda/cache.c Fri Dec 21 09:41:55 2001 +++ linux-2.4.19-pre6/fs/coda/cache.c Thu Apr 4 22:05:12 2002 @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff -urN linux-2.4.19-pre5/fs/coda/cnode.c linux-2.4.19-pre6/fs/coda/cnode.c --- linux-2.4.19-pre5/fs/coda/cnode.c Fri Dec 21 09:41:55 2001 +++ linux-2.4.19-pre6/fs/coda/cnode.c Thu Apr 4 22:05:12 2002 @@ -12,7 +12,6 @@ #include extern int coda_debug; -extern int coda_print_entry; inline int coda_fideq(ViceFid *fid1, ViceFid *fid2) { @@ -58,7 +57,6 @@ } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &coda_symlink_inode_operations; inode->i_data.a_ops = &coda_symlink_aops; - inode->i_mapping = &inode->i_data; } else init_special_inode(inode, inode->i_mode, attr->va_rdev); } @@ -178,24 +176,24 @@ if ( !coda_fideq(fid, &cii->c_fid) ) BUG(); CDEBUG(D_INODE, "found %ld\n", inode->i_ino); - return inode; + return inode; } /* the CONTROL inode is made without asking attributes from Venus */ int coda_cnode_makectl(struct inode **inode, struct super_block *sb) { - int error = 0; + int error = 0; - *inode = iget(sb, CTL_INO); - if ( *inode ) { - (*inode)->i_op = &coda_ioctl_inode_operations; - (*inode)->i_fop = &coda_ioctl_operations; - (*inode)->i_mode = 0444; - error = 0; - } else { - error = -ENOMEM; - } + *inode = iget(sb, CTL_INO); + if ( *inode ) { + (*inode)->i_op = &coda_ioctl_inode_operations; + (*inode)->i_fop = &coda_ioctl_operations; + (*inode)->i_mode = 0444; + error = 0; + } else { + error = -ENOMEM; + } - return error; + return error; } diff -urN linux-2.4.19-pre5/fs/coda/coda_linux.c linux-2.4.19-pre6/fs/coda/coda_linux.c --- linux-2.4.19-pre5/fs/coda/coda_linux.c Thu Apr 4 22:04:27 2002 +++ linux-2.4.19-pre6/fs/coda/coda_linux.c Thu Apr 4 22:05:12 2002 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -26,7 +25,6 @@ /* initialize the debugging variables */ int coda_debug; -int coda_print_entry; int coda_access_cache = 1; int coda_fake_statfs; diff -urN linux-2.4.19-pre5/fs/coda/dir.c linux-2.4.19-pre6/fs/coda/dir.c --- linux-2.4.19-pre5/fs/coda/dir.c Thu Apr 4 22:04:27 2002 +++ linux-2.4.19-pre6/fs/coda/dir.c Thu Apr 4 22:05:12 2002 @@ -488,30 +488,41 @@ /* file operations for directories */ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir) { - int result = 0; struct dentry *coda_dentry = coda_file->f_dentry; - struct inode *coda_inode = coda_dentry->d_inode; - struct coda_inode_info *cii = ITOC(coda_inode); - struct file *host_file = cii->c_container; + struct coda_file_info *cfi; + struct file *host_file; - if (!host_file) BUG(); + cfi = CODA_FTOC(coda_file); + if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG(); + host_file = cfi->cfi_container; coda_vfs_stat.readdir++; - /* Access to both host and coda f_pos fields is serialized on the - * coda_file->f_dentry->d_inode->i_sem which has already been taken by - * vfs_readdir. Userspace shouldn't 'play' with the container file as - * long as the file is held open. */ - host_file->f_pos = coda_file->f_pos; - - if ( !host_file->f_op->readdir ) - result = coda_venus_readdir(host_file, filldir, dirent, - coda_dentry); - else - result = vfs_readdir(host_file, filldir, dirent); + if ( host_file->f_op->readdir ) + /* potemkin case: we were handed a directory inode */ + return vfs_readdir(host_file, filldir, dirent); - coda_file->f_pos = host_file->f_pos; - return result; + /* Venus: we must read Venus dirents from the file */ + return coda_venus_readdir(host_file, filldir, dirent, coda_dentry); +} + +static inline unsigned int CDT2DT(unsigned char cdt) +{ + unsigned int dt; + + switch(cdt) { + case CDT_UNKNOWN: dt = DT_UNKNOWN; break; + case CDT_FIFO: dt = DT_FIFO; break; + case CDT_CHR: dt = DT_CHR; break; + case CDT_DIR: dt = DT_DIR; break; + case CDT_BLK: dt = DT_BLK; break; + case CDT_REG: dt = DT_REG; break; + case CDT_LNK: dt = DT_LNK; break; + case CDT_SOCK: dt = DT_SOCK; break; + case CDT_WHT: dt = DT_WHT; break; + default: dt = DT_UNKNOWN; break; + } + return dt; } /* support routines */ @@ -522,6 +533,7 @@ struct venus_dirent *vdir; unsigned long vdir_size = (unsigned long)(&((struct venus_dirent *)0)->d_name); + unsigned int type; struct qstr name; ino_t ino; int ret, i; @@ -561,8 +573,7 @@ ret = -EBADF; break; } - - /* validate whether the directory entry makes sense */ + /* validate whether the directory file actually makes sense */ if (vdir->d_reclen < vdir_size + vdir->d_namlen || vdir->d_namlen > CODA_MAXNAMLEN) { printk("coda_venus_readdir: Invalid dir: %ld\n", @@ -581,15 +592,17 @@ /* skip null entries */ if (vdir->d_fileno && name.len) { - /* try to look for this entry in the dcache, that way - * userspace doesn't have to worry about breaking old - * getcwd implementation by having mismatched inode - * numbers for internal volume mountpoints. */ + /* try to look up this entry in the dcache, that way + * userspace doesn't have to worry about breaking + * getcwd by having mismatched inode numbers for + * internal volume mountpoints. */ ino = find_inode_number(dir, &name); if (!ino) ino = vdir->d_fileno; + type = CDT2DT(vdir->d_type); ret = filldir(dirent, name.name, name.len, filp->f_pos, - ino, DT_UNKNOWN); + ino, type); + /* failure means no space for filling in this round */ if (ret < 0) break; result++; } @@ -715,7 +728,6 @@ goto return_bad_inode; coda_flag_inode_children(inode, C_FLUSH); - cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); } @@ -724,11 +736,6 @@ return 0; return_bad_inode: - inode->i_mapping = &inode->i_data; - if (cii->c_container) { - fput(cii->c_container); - cii->c_container = NULL; - } make_bad_inode(inode); unlock_kernel(); return -EIO; diff -urN linux-2.4.19-pre5/fs/coda/file.c linux-2.4.19-pre6/fs/coda/file.c --- linux-2.4.19-pre5/fs/coda/file.c Thu Apr 4 22:04:27 2002 +++ linux-2.4.19-pre6/fs/coda/file.c Thu Apr 4 22:05:12 2002 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -31,250 +30,203 @@ int use_coda_close; static ssize_t -coda_file_read(struct file *file, char *buf, size_t count, loff_t *ppos) +coda_file_read(struct file *coda_file, char *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; - struct coda_inode_info *cii = ITOC(inode); - struct file *cfile; - ssize_t ret; + struct coda_file_info *cfi; + struct file *host_file; - cfile = cii->c_container; - if (!cfile) BUG(); + cfi = CODA_FTOC(coda_file); + if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG(); + host_file = cfi->cfi_container; - if (!cfile->f_op || !cfile->f_op->read) + if (!host_file->f_op || !host_file->f_op->read) return -EINVAL; - down(&inode->i_sem); - ret = cfile->f_op->read(cfile, buf, count, ppos); - UPDATE_ATIME(inode); - up(&inode->i_sem); - - return ret; + return host_file->f_op->read(host_file, buf, count, ppos); } static ssize_t -coda_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos) +coda_file_write(struct file *coda_file, const char *buf, size_t count, loff_t *ppos) { - struct inode *cinode, *inode = file->f_dentry->d_inode; - struct coda_inode_info *cii = ITOC(inode); - struct file *cfile; + struct inode *host_inode, *coda_inode = coda_file->f_dentry->d_inode; + struct coda_file_info *cfi; + struct file *host_file; ssize_t ret; - int flags; - cfile = cii->c_container; - if (!cfile) BUG(); + cfi = CODA_FTOC(coda_file); + if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG(); + host_file = cfi->cfi_container; - if (!cfile->f_op || !cfile->f_op->write) + if (!host_file->f_op || !host_file->f_op->write) return -EINVAL; - cinode = cfile->f_dentry->d_inode; - down(&inode->i_sem); - flags = cfile->f_flags; - cfile->f_flags |= file->f_flags & (O_APPEND | O_SYNC); - - ret = cfile->f_op->write(cfile, buf, count, ppos); - - cfile->f_flags = flags; - inode->i_size = cinode->i_size; - inode->i_blocks = (inode->i_size + 511) >> 9; - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - up(&inode->i_sem); + host_inode = host_file->f_dentry->d_inode; + down(&coda_inode->i_sem); + + ret = host_file->f_op->write(host_file, buf, count, ppos); + + coda_inode->i_size = host_inode->i_size; + coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9; + coda_inode->i_mtime = coda_inode->i_ctime = CURRENT_TIME; + up(&coda_inode->i_sem); return ret; } static int -coda_file_mmap(struct file *file, struct vm_area_struct *vma) +coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma) { - struct inode *inode = file->f_dentry->d_inode; - struct coda_inode_info *cii = ITOC(inode); - struct file *cfile; - int ret; - - cfile = cii->c_container; + struct coda_file_info *cfi; + struct file *host_file; - if (!cfile) BUG(); + cfi = CODA_FTOC(coda_file); + if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG(); + host_file = cfi->cfi_container; - if (!cfile->f_op || !cfile->f_op->mmap) + if (!host_file->f_op || !host_file->f_op->mmap) return -ENODEV; - down(&inode->i_sem); - ret = cfile->f_op->mmap(cfile, vma); - UPDATE_ATIME(inode); - up(&inode->i_sem); - - return ret; + return host_file->f_op->mmap(host_file, vma); } -int coda_open(struct inode *i, struct file *f) +int coda_open(struct inode *coda_inode, struct file *coda_file) { - struct file *fh = NULL; - int error = 0; - unsigned short flags = f->f_flags & (~O_EXCL); + struct file *host_file = NULL; + int error; + unsigned short flags = coda_file->f_flags & (~O_EXCL); unsigned short coda_flags = coda_flags_to_cflags(flags); - struct coda_cred *cred; - struct coda_inode_info *cii; + struct coda_file_info *cfi; lock_kernel(); coda_vfs_stat.open++; - CDEBUG(D_SPECIAL, "OPEN inode number: %ld, count %d, flags %o.\n", - f->f_dentry->d_inode->i_ino, atomic_read(&f->f_dentry->d_count), flags); + cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL); + if (!cfi) { + unlock_kernel(); + return -ENOMEM; + } - error = venus_open(i->i_sb, coda_i2f(i), coda_flags, &fh); - if (error || !fh) { - CDEBUG(D_FILE, "coda_open: venus_open result %d\n", error); + error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags, + &host_file); + if (error || !host_file) { + kfree(cfi); unlock_kernel(); return error; } - /* coda_upcall returns filehandle of container file object */ - cii = ITOC(i); - if (cii->c_container) - fput(cii->c_container); - - cii->c_contcount++; - cii->c_container = fh; - i->i_mapping = &cii->c_container->f_dentry->d_inode->i_data; - - cred = kmalloc(sizeof(struct coda_cred), GFP_KERNEL); - - /* If the allocation failed, we'll just muddle on. This actually works - * fine for normal cases. (i.e. when open credentials are the same as - * close credentials) */ - if (cred) { - coda_load_creds(cred); - f->private_data = cred; - } + host_file->f_flags |= coda_file->f_flags & (O_APPEND | O_SYNC); + + cfi->cfi_magic = CODA_MAGIC; + cfi->cfi_container = host_file; + coda_load_creds(&cfi->cfi_cred); + + if (coda_file->private_data != NULL) BUG(); + coda_file->private_data = cfi; - CDEBUG(D_FILE, "result %d, coda i->i_count is %d, cii->contcount is %d for ino %ld\n", - error, atomic_read(&i->i_count), cii->c_contcount, i->i_ino); - CDEBUG(D_FILE, "cache ino: %ld, count %d, ops %p\n", - fh->f_dentry->d_inode->i_ino, - atomic_read(&fh->f_dentry->d_inode->i_count), - fh->f_dentry->d_inode->i_op); unlock_kernel(); return 0; } - -int coda_flush(struct file *file) +int coda_flush(struct file *coda_file) { - unsigned short flags = (file->f_flags) & (~O_EXCL); - unsigned short cflags; - struct coda_inode_info *cii; - struct file *cfile; - struct inode *cinode, *inode; + unsigned short flags = coda_file->f_flags & ~O_EXCL; + unsigned short coda_flags = coda_flags_to_cflags(flags); + struct coda_file_info *cfi; + struct inode *coda_inode; int err = 0, fcnt; coda_vfs_stat.flush++; /* No need to make an upcall when we have not made any modifications * to the file */ - if ((file->f_flags & O_ACCMODE) == O_RDONLY) + if ((coda_file->f_flags & O_ACCMODE) == O_RDONLY) return 0; if (use_coda_close) return 0; - fcnt = file_count(file); + fcnt = file_count(coda_file); if (fcnt > 1) return 0; - cflags = coda_flags_to_cflags(flags); + coda_inode = coda_file->f_dentry->d_inode; - inode = file->f_dentry->d_inode; - cii = ITOC(inode); - cfile = cii->c_container; - if (!cfile) BUG(); + cfi = CODA_FTOC(coda_file); + if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG(); - cinode = cfile->f_dentry->d_inode; + err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags, + &cfi->cfi_cred); - CDEBUG(D_FILE, "FLUSH coda (file %p ct %d)\n", file, fcnt); - - err = venus_store(inode->i_sb, coda_i2f(inode), cflags, - (struct coda_cred *)file->private_data); if (err == -EOPNOTSUPP) { use_coda_close = 1; err = 0; } - CDEBUG(D_FILE, "coda_flush: result: %d\n", err); return err; } -int coda_release(struct inode *i, struct file *f) +int coda_release(struct inode *coda_inode, struct file *coda_file) { - unsigned short flags = (f->f_flags) & (~O_EXCL); - unsigned short cflags = coda_flags_to_cflags(flags); - struct coda_inode_info *cii; - struct file *cfile; + unsigned short flags = (coda_file->f_flags) & (~O_EXCL); + unsigned short coda_flags = coda_flags_to_cflags(flags); + struct coda_file_info *cfi; int err = 0; lock_kernel(); coda_vfs_stat.release++; if (!use_coda_close) { - err = venus_release(i->i_sb, coda_i2f(i), cflags); + err = venus_release(coda_inode->i_sb, coda_i2f(coda_inode), + coda_flags); if (err == -EOPNOTSUPP) { use_coda_close = 1; err = 0; } } - if (use_coda_close) - err = venus_close(i->i_sb, coda_i2f(i), cflags, - (struct coda_cred *)f->private_data); + cfi = CODA_FTOC(coda_file); + if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG(); - cii = ITOC(i); - cfile = cii->c_container; - if (!cfile) BUG(); - - if (--cii->c_contcount) { - unlock_kernel(); - return err; - } + if (use_coda_close) + err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode), + coda_flags, &cfi->cfi_cred); - i->i_mapping = &i->i_data; - fput(cfile); - cii->c_container = NULL; - - if (f->private_data) { - kfree(f->private_data); - f->private_data = NULL; - } + fput(cfi->cfi_container); + kfree(coda_file->private_data); + coda_file->private_data = NULL; unlock_kernel(); return err; } -int coda_fsync(struct file *file, struct dentry *dentry, int datasync) +int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync) { - struct file *cfile; - struct dentry *cdentry; - struct inode *cinode, *inode = dentry->d_inode; - struct coda_inode_info *cii = ITOC(inode); + struct file *host_file; + struct dentry *host_dentry; + struct inode *host_inode, *coda_inode = coda_dentry->d_inode; + struct coda_file_info *cfi; int err = 0; - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) + if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) || + S_ISLNK(coda_inode->i_mode))) return -EINVAL; - cfile = cii->c_container; - if (!cfile) BUG(); + cfi = CODA_FTOC(coda_file); + if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG(); + host_file = cfi->cfi_container; coda_vfs_stat.fsync++; - if (cfile->f_op && cfile->f_op->fsync) { - cdentry = cfile->f_dentry; - cinode = cdentry->d_inode; - down(&cinode->i_sem); - err = cfile->f_op->fsync(cfile, cdentry, datasync); - up(&cinode->i_sem); + if (host_file->f_op && host_file->f_op->fsync) { + host_dentry = host_file->f_dentry; + host_inode = host_dentry->d_inode; + down(&host_inode->i_sem); + err = host_file->f_op->fsync(host_file, host_dentry, datasync); + up(&host_inode->i_sem); } if ( !err && !datasync ) { lock_kernel(); - err = venus_fsync(inode->i_sb, coda_i2f(inode)); + err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode)); unlock_kernel(); } diff -urN linux-2.4.19-pre5/fs/coda/inode.c linux-2.4.19-pre6/fs/coda/inode.c --- linux-2.4.19-pre5/fs/coda/inode.c Mon Feb 25 11:38:08 2002 +++ linux-2.4.19-pre6/fs/coda/inode.c Thu Apr 4 22:05:12 2002 @@ -25,7 +25,6 @@ #include #include -#include #include #include @@ -189,22 +188,6 @@ if (!sbi) BUG(); -#if 0 - /* check if the inode is already initialized */ - if (inode->u.generic_ip) { - printk("coda_read_inode: initialized inode"); - return; - } - - inode->u.generic_ip = cii_alloc(); - if (!inode->u.generic_ip) { - CDEBUG(D_CNODE, "coda_read_inode: failed to allocate inode info\n"); - make_bad_inode(inode); - return; - } - memset(inode->u.generic_ip, 0, sizeof(struct coda_inode_info)); -#endif - cii = ITOC(inode); if (!coda_isnullfid(&cii->c_fid)) { printk("coda_read_inode: initialized inode"); @@ -222,30 +205,21 @@ inode->i_ino, atomic_read(&inode->i_count)); CDEBUG(D_DOWNCALL, "clearing inode: %ld, %x\n", inode->i_ino, cii->c_flags); - if (cii->c_container) BUG(); - list_del_init(&cii->c_cilist); - inode->i_mapping = &inode->i_data; coda_cache_clear_inode(inode); - -#if 0 - cii_free(inode->u.generic_ip); - inode->u.generic_ip = NULL; -#endif } int coda_notify_change(struct dentry *de, struct iattr *iattr) { struct inode *inode = de->d_inode; - struct coda_vattr vattr; - int error; - - inode->i_ctime = CURRENT_TIME; + struct coda_vattr vattr; + int error; - memset(&vattr, 0, sizeof(vattr)); - coda_iattr_to_vattr(iattr, &vattr); + memset(&vattr, 0, sizeof(vattr)); - vattr.va_type = C_VNON; /* cannot set type */ + inode->i_ctime = CURRENT_TIME; + coda_iattr_to_vattr(iattr, &vattr); + vattr.va_type = C_VNON; /* cannot set type */ CDEBUG(D_SUPER, "vattr.va_mode %o\n", vattr.va_mode); /* Venus is responsible for truncating the container-file!!! */ diff -urN linux-2.4.19-pre5/fs/coda/pioctl.c linux-2.4.19-pre6/fs/coda/pioctl.c --- linux-2.4.19-pre5/fs/coda/pioctl.c Fri Dec 21 09:41:55 2001 +++ linux-2.4.19-pre6/fs/coda/pioctl.c Thu Apr 4 22:05:12 2002 @@ -14,7 +14,6 @@ #include #include #include -#include #include #define __NO_VERSION__ #include diff -urN linux-2.4.19-pre5/fs/coda/psdev.c linux-2.4.19-pre6/fs/coda/psdev.c --- linux-2.4.19-pre5/fs/coda/psdev.c Mon Feb 25 11:38:08 2002 +++ linux-2.4.19-pre6/fs/coda/psdev.c Thu Apr 4 22:05:12 2002 @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff -urN linux-2.4.19-pre5/fs/coda/sysctl.c linux-2.4.19-pre6/fs/coda/sysctl.c --- linux-2.4.19-pre5/fs/coda/sysctl.c Fri Dec 21 09:41:55 2001 +++ linux-2.4.19-pre6/fs/coda/sysctl.c Thu Apr 4 22:05:12 2002 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #define __NO_VERSION__ @@ -51,7 +50,6 @@ static ctl_table coda_table[] = { {CODA_DEBUG, "debug", &coda_debug, sizeof(int), 0644, NULL, &proc_dointvec}, - {CODA_ENTRY, "printentry", &coda_print_entry, sizeof(int), 0644, NULL, &proc_dointvec}, {CODA_MC, "accesscache", &coda_access_cache, sizeof(int), 0644, NULL, &proc_dointvec}, {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec}, {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec}, diff -urN linux-2.4.19-pre5/fs/coda/upcall.c linux-2.4.19-pre6/fs/coda/upcall.c --- linux-2.4.19-pre5/fs/coda/upcall.c Fri Dec 21 09:41:55 2001 +++ linux-2.4.19-pre6/fs/coda/upcall.c Thu Apr 4 22:05:12 2002 @@ -15,7 +15,6 @@ */ #include -#include #include #include @@ -176,10 +175,7 @@ insize = SIZE(store); UPARG(CODA_STORE); - if ( cred ) { - memcpy(&(inp->ih.cred), cred, sizeof(*cred)); - } else - printk("CODA: store without valid file creds.\n"); + memcpy(&(inp->ih.cred), cred, sizeof(*cred)); inp->coda_store.VFid = *fid; inp->coda_store.flags = flags; @@ -218,10 +214,7 @@ insize = SIZE(release); UPARG(CODA_CLOSE); - if ( cred ) { - memcpy(&(inp->ih.cred), cred, sizeof(*cred)); - } else - printk("CODA: close without valid file creds.\n"); + memcpy(&(inp->ih.cred), cred, sizeof(*cred)); inp->coda_close.VFid = *fid; inp->coda_close.flags = flags; diff -urN linux-2.4.19-pre5/fs/devfs/base.c linux-2.4.19-pre6/fs/devfs/base.c --- linux-2.4.19-pre5/fs/devfs/base.c Mon Feb 25 11:38:08 2002 +++ linux-2.4.19-pre6/fs/devfs/base.c Thu Apr 4 22:05:12 2002 @@ -608,6 +608,13 @@ Fixed deadlock bug in . Tag VFS deletable in if handle ignored. v1.10 + 20020129 Richard Gooch + Added KERN_* to remaining messages. + Cleaned up declaration of . + v1.11 + 20020219 Richard Gooch + Changed to allow later additions if not yet empty. + v1.12 */ #include #include @@ -640,7 +647,7 @@ #include #include -#define DEVFS_VERSION "1.10 (20020120)" +#define DEVFS_VERSION "1.12 (20020219)" #define DEVFS_NAME "devfs" @@ -848,8 +855,8 @@ unsigned int cmd, unsigned long arg); static int devfsd_close (struct inode *inode, struct file *file); #ifdef CONFIG_DEVFS_DEBUG -static int stat_read (struct file *file, char *buf, size_t len, - loff_t *ppos); +static ssize_t stat_read (struct file *file, char *buf, size_t len, + loff_t *ppos); static struct file_operations stat_fops = { read: stat_read, @@ -2431,10 +2438,10 @@ if (bdops->check_media_change == NULL) goto out; if ( !bdops->check_media_change (dev) ) goto out; retval = 1; - printk ( KERN_DEBUG "VFS: Disk change detected on device %s\n", + printk (KERN_DEBUG "VFS: Disk change detected on device %s\n", kdevname (dev) ); - if (invalidate_device(dev, 0)) - printk("VFS: busy inodes on changed media..\n"); + if ( invalidate_device (dev, 0) ) + printk (KERN_WARNING "VFS: busy inodes on changed media..\n"); /* Ugly hack to disable messages about unable to read partition table */ tmp = warn_no_part; warn_no_part = 0; @@ -3112,10 +3119,10 @@ if (de == NULL) return -ENOENT; if ( !S_ISDIR (de->mode) ) return -ENOTDIR; if (!de->vfs_deletable) return -EPERM; - /* First ensure the directory is empty and will stay thay way */ + /* First ensure the directory is empty and will stay that way */ write_lock (&de->u.dir.lock); - de->u.dir.no_more_additions = TRUE; if (de->u.dir.first) err = -ENOTEMPTY; + else de->u.dir.no_more_additions = TRUE; write_unlock (&de->u.dir.lock); if (err) return err; /* Now unhook the directory from it's parent */ @@ -3237,7 +3244,7 @@ return sb; out_no_root: - printk ("devfs_read_super: get root inode failed\n"); + PRINTK ("(): get root inode failed\n"); if (root_inode) iput (root_inode); return NULL; } /* End Function devfs_read_super */ @@ -3464,7 +3471,7 @@ { int err; - printk ("%s: v%s Richard Gooch (rgooch@atnf.csiro.au)\n", + printk (KERN_INFO "%s: v%s Richard Gooch (rgooch@atnf.csiro.au)\n", DEVFS_NAME, DEVFS_VERSION); devfsd_buf_cache = kmem_cache_create ("devfsd_event", sizeof (struct devfsd_buf_entry), @@ -3472,9 +3479,9 @@ if (!devfsd_buf_cache) OOPS ("(): unable to allocate event slab\n"); #ifdef CONFIG_DEVFS_DEBUG devfs_debug = devfs_debug_init; - printk ("%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug); + printk (KERN_INFO "%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug); #endif - printk ("%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options); + printk (KERN_INFO "%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options); err = register_filesystem (&devfs_fs_type); if (!err) { @@ -3491,8 +3498,8 @@ if ( !(boot_options & OPTION_MOUNT) ) return; err = do_mount ("none", "/dev", "devfs", 0, ""); - if (err == 0) printk ("Mounted devfs on /dev\n"); - else printk ("Warning: unable to mount devfs, err: %d\n", err); + if (err == 0) printk (KERN_INFO "Mounted devfs on /dev\n"); + else PRINTK ("(): unable to mount devfs, err: %d\n", err); } /* End Function mount_devfs_fs */ module_init(init_devfs_fs) diff -urN linux-2.4.19-pre5/fs/devfs/util.c linux-2.4.19-pre6/fs/devfs/util.c --- linux-2.4.19-pre5/fs/devfs/util.c Thu Oct 11 09:43:30 2001 +++ linux-2.4.19-pre6/fs/devfs/util.c Thu Apr 4 22:05:12 2002 @@ -1,6 +1,6 @@ /* devfs (Device FileSystem) utilities. - Copyright (C) 1999-2001 Richard Gooch + Copyright (C) 1999-2002 Richard Gooch This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -48,6 +48,12 @@ 20010818 Richard Gooch Updated major masks up to Linus' "no new majors" proclamation. Block: were 126 now 122 free, char: were 26 now 19 free. + 20020324 Richard Gooch + Fixed bug in : was clearing beyond + bitfield. + 20020326 Richard Gooch + Fixed bitfield data type for . + Made major bitfield type and initialiser 64 bit safe. */ #include #include @@ -61,67 +67,6 @@ /* Private functions follow */ /** - * _devfs_convert_name - Convert from an old style location-based name to new style. - * @new: The new name will be written here. - * @old: The old name. - * @disc: If true, disc partitioning information should be processed. - */ - -static void __init _devfs_convert_name (char *new, const char *old, int disc) -{ - int host, bus, target, lun; - char *ptr; - char part[8]; - - /* Decode "c#b#t#u#" */ - if (old[0] != 'c') return; - host = simple_strtol (old + 1, &ptr, 10); - if (ptr[0] != 'b') return; - bus = simple_strtol (ptr + 1, &ptr, 10); - if (ptr[0] != 't') return; - target = simple_strtol (ptr + 1, &ptr, 10); - if (ptr[0] != 'u') return; - lun = simple_strtol (ptr + 1, &ptr, 10); - if (disc) - { - /* Decode "p#" */ - if (ptr[0] == 'p') sprintf (part, "part%s", ptr + 1); - else strcpy (part, "disc"); - } - else part[0] = '\0'; - sprintf (new, "/host%d/bus%d/target%d/lun%d/%s", - host, bus, target, lun, part); -} /* End Function _devfs_convert_name */ - - -/* Public functions follow */ - -/** - * devfs_make_root - Create the root FS device entry if required. - * @name: The name of the root FS device, as passed by "root=". - */ - -void __init devfs_make_root (const char *name) -{ - char dest[64]; - - if ( (strncmp (name, "sd/", 3) == 0) || (strncmp (name, "sr/", 3) == 0) ) - { - strcpy (dest, "../scsi"); - _devfs_convert_name (dest + 7, name + 3, (name[1] == 'd') ? 1 : 0); - } - else if ( (strncmp (name, "ide/hd/", 7) == 0) || - (strncmp (name, "ide/cd/", 7) == 0) ) - { - strcpy (dest, ".."); - _devfs_convert_name (dest + 2, name + 7, (name[4] == 'h') ? 1 : 0); - } - else return; - devfs_mk_symlink (NULL, name, DEVFS_FL_DEFAULT, dest, NULL, NULL); -} /* End Function devfs_make_root */ - - -/** * devfs_register_tape - Register a tape device in the "/dev/tapes" hierarchy. * @de: Any tape device entry in the device directory. */ @@ -186,8 +131,13 @@ struct major_list { spinlock_t lock; - __u32 bits[8]; + unsigned long bits[256 / BITS_PER_LONG]; }; +#if BITS_PER_LONG == 32 +# define INITIALISER64(low,high) (low), (high) +#else +# define INITIALISER64(low,high) ( (high) << 32 | (low) ) +#endif /* Block majors already assigned: 0-3, 7-9, 11-63, 65-99, 101-113, 120-127, 199, 201, 240-255 @@ -195,14 +145,11 @@ */ static struct major_list block_major_list = {SPIN_LOCK_UNLOCKED, - {0xfffffb8f, /* Majors 0 to 31 */ - 0xffffffff, /* Majors 32 to 63 */ - 0xfffffffe, /* Majors 64 to 95 */ - 0xff03ffef, /* Majors 96 to 127 */ - 0x00000000, /* Majors 128 to 159 */ - 0x00000000, /* Majors 160 to 191 */ - 0x00000280, /* Majors 192 to 223 */ - 0xffff0000} /* Majors 224 to 255 */ + {INITIALISER64 (0xfffffb8f, 0xffffffff), /* Majors 0-31, 32-63 */ + INITIALISER64 (0xfffffffe, 0xff03ffef), /* Majors 64-95, 96-127 */ + INITIALISER64 (0x00000000, 0x00000000), /* Majors 128-159, 160-191 */ + INITIALISER64 (0x00000280, 0xffff0000), /* Majors 192-223, 224-255 */ + } }; /* Char majors already assigned: @@ -211,14 +158,11 @@ */ static struct major_list char_major_list = {SPIN_LOCK_UNLOCKED, - {0xfffffeff, /* Majors 0 to 31 */ - 0xffffffff, /* Majors 32 to 63 */ - 0xffffffff, /* Majors 64 to 95 */ - 0xffffffff, /* Majors 96 to 127 */ - 0x7cffffff, /* Majors 128 to 159 */ - 0xffffffff, /* Majors 160 to 191 */ - 0x3f0fffff, /* Majors 192 to 223 */ - 0xffff007f} /* Majors 224 to 255 */ + {INITIALISER64 (0xfffffeff, 0xffffffff), /* Majors 0-31, 32-63 */ + INITIALISER64 (0xffffffff, 0xffffffff), /* Majors 64-95, 96-127 */ + INITIALISER64 (0x7cffffff, 0xffffffff), /* Majors 128-159, 160-191 */ + INITIALISER64 (0x3f0fffff, 0xffff007f), /* Majors 192-223, 224-255 */ + } }; @@ -273,7 +217,7 @@ struct minor_list { int major; - __u32 bits[8]; + unsigned long bits[256 / BITS_PER_LONG]; struct minor_list *next; }; @@ -416,7 +360,6 @@ { int number; unsigned int length; - __u32 *bits; /* Get around stupid lack of semaphore initialiser */ spin_lock (&space->init_lock); @@ -429,6 +372,8 @@ down (&space->semaphore); if (space->num_free < 1) { + void *bits; + if (space->length < 16) length = 16; else length = space->length << 1; if ( ( bits = vmalloc (length) ) == NULL ) diff -urN linux-2.4.19-pre5/fs/fat/inode.c linux-2.4.19-pre6/fs/fat/inode.c --- linux-2.4.19-pre5/fs/fat/inode.c Mon Feb 25 11:38:08 2002 +++ linux-2.4.19-pre6/fs/fat/inode.c Thu Apr 4 22:05:12 2002 @@ -434,12 +434,13 @@ struct dentry *result; if (fhtype != 3) - return NULL; + return ERR_PTR(-ESTALE); if (len < 5) - return NULL; + return ERR_PTR(-ESTALE); + /* We cannot find the parent, + It better just *be* there */ if (parent) - return NULL; /* We cannot find the parent, - It better just *be* there */ + return ERR_PTR(-ESTALE); inode = iget(sb, fh[0]); if (!inode || is_bad_inode(inode) || @@ -501,6 +502,7 @@ iput(inode); return ERR_PTR(-ENOMEM); } + result->d_op = sb->s_root->d_op; result->d_flags |= DCACHE_NFSD_DISCONNECTED; return result; diff -urN linux-2.4.19-pre5/fs/fcntl.c linux-2.4.19-pre6/fs/fcntl.c --- linux-2.4.19-pre5/fs/fcntl.c Mon Sep 17 13:16:30 2001 +++ linux-2.4.19-pre6/fs/fcntl.c Thu Apr 4 22:05:12 2002 @@ -66,6 +66,10 @@ write_lock(&files->file_lock); + error = -EINVAL; + if (orig_start >= current->rlim[RLIMIT_NOFILE].rlim_cur) + goto out; + repeat: /* * Someone might have closed fd's in the range diff -urN linux-2.4.19-pre5/fs/filesystems.c linux-2.4.19-pre6/fs/filesystems.c --- linux-2.4.19-pre5/fs/filesystems.c Tue Apr 17 23:23:12 2001 +++ linux-2.4.19-pre6/fs/filesystems.c Thu Apr 4 22:05:12 2002 @@ -3,7 +3,7 @@ * * Copyright (C) 1991, 1992 Linus Torvalds * - * table of configured filesystems + * nfsservctl system-call when nfsd is not compiled in. */ #include @@ -13,28 +13,28 @@ #include #include -#if defined(CONFIG_NFSD_MODULE) -struct nfsd_linkage *nfsd_linkage = NULL; +#if ! defined(CONFIG_NFSD) +struct nfsd_linkage *nfsd_linkage; long asmlinkage sys_nfsservctl(int cmd, void *argp, void *resp) { int ret = -ENOSYS; +#if defined(CONFIG_MODULES) lock_kernel(); if (nfsd_linkage || - (request_module ("nfsd") == 0 && nfsd_linkage)) + (request_module ("nfsd") == 0 && nfsd_linkage)) { + __MOD_INC_USE_COUNT(nfsd_linkage->owner); + unlock_kernel(); ret = nfsd_linkage->do_nfsservctl(cmd, argp, resp); - - unlock_kernel(); + __MOD_DEC_USE_COUNT(nfsd_linkage->owner); + } else + unlock_kernel(); +#endif return ret; } EXPORT_SYMBOL(nfsd_linkage); -#elif ! defined (CONFIG_NFSD) -asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp) -{ - return -ENOSYS; -} #endif /* CONFIG_NFSD */ diff -urN linux-2.4.19-pre5/fs/jbd/journal.c linux-2.4.19-pre6/fs/jbd/journal.c --- linux-2.4.19-pre5/fs/jbd/journal.c Mon Feb 25 11:38:08 2002 +++ linux-2.4.19-pre6/fs/jbd/journal.c Thu Apr 4 22:05:12 2002 @@ -204,6 +204,7 @@ lock_kernel(); daemonize(); + reparent_to_init(); spin_lock_irq(¤t->sigmask_lock); sigfillset(¤t->blocked); recalc_sigpending(current); @@ -267,6 +268,7 @@ journal->j_task = NULL; wake_up(&journal->j_wait_done_commit); + unlock_kernel(); jbd_debug(1, "Journal thread exiting.\n"); return 0; } diff -urN linux-2.4.19-pre5/fs/lockd/svc4proc.c linux-2.4.19-pre6/fs/lockd/svc4proc.c --- linux-2.4.19-pre5/fs/lockd/svc4proc.c Mon Oct 1 13:45:47 2001 +++ linux-2.4.19-pre6/fs/lockd/svc4proc.c Thu Apr 4 22:05:12 2002 @@ -447,11 +447,13 @@ if (nlmsvc_ops != NULL) { struct svc_client *clnt; saddr.sin_addr.s_addr = argp->addr; + nlmsvc_ops->exp_readlock(); if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL && (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) { nlmsvc_free_host_resources(host); } nlm_release_host(host); + nlmsvc_ops->exp_unlock(); } return rpc_success; diff -urN linux-2.4.19-pre5/fs/lockd/svcproc.c linux-2.4.19-pre6/fs/lockd/svcproc.c --- linux-2.4.19-pre5/fs/lockd/svcproc.c Thu Oct 11 07:52:18 2001 +++ linux-2.4.19-pre6/fs/lockd/svcproc.c Thu Apr 4 22:05:12 2002 @@ -474,12 +474,14 @@ /* If we run on an NFS server, delete all locks held by the client */ if (nlmsvc_ops != NULL) { struct svc_client *clnt; - saddr.sin_addr.s_addr = argp->addr; + saddr.sin_addr.s_addr = argp->addr; + nlmsvc_ops->exp_readlock(); if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL && (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) { nlmsvc_free_host_resources(host); } nlm_release_host(host); + nlmsvc_ops->exp_unlock(); } return rpc_success; diff -urN linux-2.4.19-pre5/fs/namei.c linux-2.4.19-pre6/fs/namei.c --- linux-2.4.19-pre5/fs/namei.c Thu Apr 4 22:04:27 2002 +++ linux-2.4.19-pre6/fs/namei.c Thu Apr 4 22:05:12 2002 @@ -903,6 +903,8 @@ return -EBUSY; } else if (S_ISDIR(victim->d_inode->i_mode)) return -EISDIR; + if (IS_DEADDIR(dir)) + return -ENOENT; return 0; } @@ -1395,9 +1397,7 @@ double_down(&dir->i_zombie, &dentry->d_inode->i_zombie); d_unhash(dentry); - if (IS_DEADDIR(dir)) - error = -ENOENT; - else if (d_mountpoint(dentry)) + if (d_mountpoint(dentry)) error = -EBUSY; else { lock_kernel(); @@ -1763,9 +1763,7 @@ } else double_down(&old_dir->i_zombie, &new_dir->i_zombie); - if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir)) - error = -ENOENT; - else if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) + if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) error = -EBUSY; else error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); diff -urN linux-2.4.19-pre5/fs/namespace.c linux-2.4.19-pre6/fs/namespace.c --- linux-2.4.19-pre5/fs/namespace.c Thu Apr 4 22:04:27 2002 +++ linux-2.4.19-pre6/fs/namespace.c Thu Apr 4 22:05:12 2002 @@ -19,8 +19,9 @@ #include #include +#include -struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data); +struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); int do_remount_sb(struct super_block *sb, int flags, void * data); void kill_super(struct super_block *sb); @@ -28,10 +29,6 @@ static int hash_mask, hash_bits; static kmem_cache_t *mnt_cache; -static LIST_HEAD(vfsmntlist); -static DECLARE_MUTEX(mount_sem); -static struct vfsmount *root_vfsmnt; - static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) { unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES); @@ -40,7 +37,7 @@ 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) { @@ -50,6 +47,14 @@ 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; } @@ -61,18 +66,6 @@ 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); @@ -97,7 +90,7 @@ while (mnt->mnt_parent != mnt) mnt = mnt->mnt_parent; spin_unlock(&dcache_lock); - return mnt == root_vfsmnt; + return mnt == current->namespace->root; } static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) @@ -140,11 +133,10 @@ 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); @@ -165,26 +157,29 @@ /* iterator */ static void *m_start(struct seq_file *m, loff_t *pos) { + struct namespace *n = m->private; struct list_head *p; - loff_t n = *pos; + loff_t l = *pos; - down(&mount_sem); - list_for_each(p, &vfsmntlist) - if (!n--) + down_read(&n->sem); + list_for_each(p, &n->list) + if (!l--) return list_entry(p, struct vfsmount, mnt_list); return NULL; } static void *m_next(struct seq_file *m, void *v, loff_t *pos) { + struct namespace *n = m->private; struct list_head *p = ((struct vfsmount *)v)->mnt_list.next; (*pos)++; - return p==&vfsmntlist ? NULL : list_entry(p, struct vfsmount, mnt_list); + return p==&n->list ? NULL : list_entry(p, struct vfsmount, mnt_list); } static void m_stop(struct seq_file *m, void *v) { - up(&mount_sem); + struct namespace *n = m->private; + up_read(&n->sem); } static inline void mangle(struct seq_file *m, const char *s) @@ -330,7 +325,7 @@ return retval; } - down(&mount_sem); + down_write(¤t->namespace->sem); spin_lock(&dcache_lock); if (atomic_read(&sb->s_active) == 1) { @@ -349,7 +344,7 @@ retval = 0; } spin_unlock(&dcache_lock); - up(&mount_sem); + up_write(¤t->namespace->sem); return retval; } @@ -479,7 +474,7 @@ struct list_head head; attach_mnt(mnt, nd); list_add_tail(&head, &mnt->mnt_list); - list_splice(&head, vfsmntlist.prev); + list_splice(&head, current->namespace->list.prev); mntget(mnt); err = 0; } @@ -506,7 +501,7 @@ if (err) return err; - down(&mount_sem); + down_write(¤t->namespace->sem); err = -EINVAL; if (check_mnt(nd->mnt) && (!recurse || check_mnt(old_nd.mnt))) { err = -ENOMEM; @@ -526,7 +521,7 @@ mntput(mnt); } - up(&mount_sem); + up_write(¤t->namespace->sem); path_release(&old_nd); return err; } @@ -573,7 +568,7 @@ if (err) return err; - down(&mount_sem); + down_write(¤t->namespace->sem); while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) ; err = -EINVAL; @@ -613,7 +608,7 @@ out1: up(&nd->dentry->d_inode->i_zombie); out: - up(&mount_sem); + up_write(¤t->namespace->sem); if (!err) path_release(&parent_nd); path_release(&old_nd); @@ -623,13 +618,22 @@ static int do_add_mount(struct nameidata *nd, char *type, int flags, int mnt_flags, char *name, void *data) { - struct vfsmount *mnt = do_kern_mount(type, flags, name, data); - int err = PTR_ERR(mnt); + struct vfsmount *mnt; + int err; + if (!type || !memchr(type, 0, PAGE_SIZE)) + return -EINVAL; + + /* we need capabilities... */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + mnt = do_kern_mount(type, flags, name, data); + err = PTR_ERR(mnt); if (IS_ERR(mnt)) goto out; - down(&mount_sem); + down_write(¤t->namespace->sem); /* Something was mounted here while we slept */ while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) ; @@ -645,7 +649,7 @@ mnt->mnt_flags = mnt_flags; err = graft_tree(mnt, nd); unlock: - up(&mount_sem); + up_write(¤t->namespace->sem); mntput(mnt); out: return err; @@ -745,6 +749,86 @@ return retval; } +int copy_namespace(int flags, struct task_struct *tsk) +{ + struct namespace *namespace = tsk->namespace; + struct namespace *new_ns; + struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL; + struct fs_struct *fs = tsk->fs; + + if (!namespace) + return 0; + + get_namespace(namespace); + + if (! (flags & CLONE_NEWNS)) + return 0; + + if (!capable(CAP_SYS_ADMIN)) { + put_namespace(namespace); + return -EPERM; + } + + new_ns = kmalloc(sizeof(struct namespace *), GFP_KERNEL); + if (!new_ns) + goto out; + + atomic_set(&new_ns->count, 1); + init_rwsem(&new_ns->sem); + new_ns->root = NULL; + INIT_LIST_HEAD(&new_ns->list); + + down_write(&tsk->namespace->sem); + /* First pass: copy the tree topology */ + new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root); + spin_lock(&dcache_lock); + list_add_tail(&new_ns->list, &new_ns->root->mnt_list); + spin_unlock(&dcache_lock); + + /* Second pass: switch the tsk->fs->* elements */ + if (fs) { + struct vfsmount *p, *q; + write_lock(&fs->lock); + + p = namespace->root; + q = new_ns->root; + while (p) { + if (p == fs->rootmnt) { + rootmnt = p; + fs->rootmnt = mntget(q); + } + if (p == fs->pwdmnt) { + pwdmnt = p; + fs->pwdmnt = mntget(q); + } + if (p == fs->altrootmnt) { + altrootmnt = p; + fs->altrootmnt = mntget(q); + } + p = next_mnt(p, namespace->root); + q = next_mnt(q, new_ns->root); + } + write_unlock(&fs->lock); + } + up_write(&tsk->namespace->sem); + + tsk->namespace = new_ns; + + if (rootmnt) + mntput(rootmnt); + if (pwdmnt) + mntput(pwdmnt); + if (altrootmnt) + mntput(altrootmnt); + + put_namespace(namespace); + return 0; + +out: + put_namespace(namespace); + return -ENOMEM; +} + asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, unsigned long flags, void * data) { @@ -863,7 +947,7 @@ user_nd.mnt = mntget(current->fs->rootmnt); user_nd.dentry = dget(current->fs->root); read_unlock(¤t->fs->lock); - down(&mount_sem); + down_write(¤t->namespace->sem); down(&old_nd.dentry->d_inode->i_zombie); error = -EINVAL; if (!check_mnt(user_nd.mnt)) @@ -908,7 +992,7 @@ path_release(&parent_nd); out2: up(&old_nd.dentry->d_inode->i_zombie); - up(&mount_sem); + up_write(¤t->namespace->sem); path_release(&user_nd); path_release(&old_nd); out1: @@ -921,95 +1005,34 @@ goto out2; } -/* - * Absolutely minimal fake fs - only empty root directory and nothing else. - * In 2.5 we'll use ramfs or tmpfs, but for now it's all we need - just - * something to go with root vfsmount. - */ -static struct inode_operations rootfs_dir_inode_operations; -static struct file_operations rootfs_dir_operations; -static int rootfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) -{ - struct inode * inode = new_inode(dir->i_sb); - int error = -ENOSPC; - if (inode) { - inode->i_mode = S_IFDIR|mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; - inode->i_op = &rootfs_dir_inode_operations; - inode->i_fop = &rootfs_dir_operations; - d_instantiate(dentry, inode); - dget(dentry); - error = 0; - } - return error; -} -static int rootfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev) -{ - struct inode * inode = new_inode(dir->i_sb); - int error = -ENOSPC; - if (inode) { - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; - init_special_inode(inode, mode, dev); - d_instantiate(dentry, inode); - dget(dentry); - error = 0; - } - return error; -} -static int rootfs_unlink(struct inode * dir, struct dentry *dentry) -{ - dentry->d_inode->i_nlink--; - dput(dentry); - return 0; -} -static struct dentry *rootfs_lookup(struct inode *dir, struct dentry *dentry) -{ - d_add(dentry, NULL); - return NULL; -} -static struct file_operations rootfs_dir_operations = { - read: generic_read_dir, - readdir: dcache_readdir, -}; -static struct inode_operations rootfs_dir_inode_operations = { - lookup: rootfs_lookup, - mkdir: rootfs_mkdir, - mknod: rootfs_mknod, - unlink: rootfs_unlink, -}; -static struct super_block *rootfs_read_super(struct super_block * sb, void * data, int silent) +static void __init init_mount_tree(void) { - struct inode * inode; - struct dentry * root; - static struct super_operations s_ops = {}; - sb->s_op = &s_ops; - inode = new_inode(sb); - if (!inode) - return NULL; - inode->i_mode = S_IFDIR|0555; - inode->i_uid = inode->i_gid = 0; - inode->i_op = &rootfs_dir_inode_operations; - inode->i_fop = &rootfs_dir_operations; - root = d_alloc_root(inode); - if (!root) { - iput(inode); - return NULL; + struct vfsmount *mnt; + struct namespace *namespace; + struct task_struct *p; + + mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); + if (IS_ERR(mnt)) + panic("Can't create rootfs"); + namespace = kmalloc(sizeof(*namespace), GFP_KERNEL); + if (!namespace) + panic("Can't allocate initial namespace"); + atomic_set(&namespace->count, 1); + INIT_LIST_HEAD(&namespace->list); + init_rwsem(&namespace->sem); + list_add(&mnt->mnt_list, &namespace->list); + namespace->root = mnt; + + init_task.namespace = namespace; + read_lock(&tasklist_lock); + for_each_task(p) { + get_namespace(namespace); + p->namespace = namespace; } - sb->s_root = root; - return sb; -} -static DECLARE_FSTYPE(root_fs_type, "rootfs", rootfs_read_super, FS_NOMOUNT); + read_unlock(&tasklist_lock); -static void __init init_mount_tree(void) -{ - register_filesystem(&root_fs_type); - root_vfsmnt = do_kern_mount("rootfs", 0, "rootfs", NULL); - if (IS_ERR(root_vfsmnt)) - panic("can't allocate root vfsmount"); - set_fs_pwd(current->fs, root_vfsmnt, root_vfsmnt->mnt_root); - set_fs_root(current->fs, root_vfsmnt, root_vfsmnt->mnt_root); + set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root); + set_fs_root(current->fs, namespace->root, namespace->root->mnt_root); } void __init mnt_init(unsigned long mempages) @@ -1067,5 +1090,6 @@ d++; i--; } while (i); + init_rootfs(); init_mount_tree(); } diff -urN linux-2.4.19-pre5/fs/nfs/nfsroot.c linux-2.4.19-pre6/fs/nfs/nfsroot.c --- linux-2.4.19-pre5/fs/nfs/nfsroot.c Thu Oct 25 00:02:26 2001 +++ linux-2.4.19-pre6/fs/nfs/nfsroot.c Thu Apr 4 22:05:12 2002 @@ -163,37 +163,6 @@ /* - * Extract IP address from the parameter string if needed. Note that we - * need to have root_server_addr set _before_ IPConfig gets called as it - * can override it. - */ -static void __init root_nfs_parse_addr(char *name) -{ - int octets = 0; - char *cp, *cq; - - cp = cq = name; - while (octets < 4) { - while (*cp >= '0' && *cp <= '9') - cp++; - if (cp == cq || cp - cq > 3) - break; - if (*cp == '.' || octets == 3) - octets++; - if (octets < 4) - cp++; - cq = cp; - } - if (octets == 4 && (*cp == ':' || *cp == '\0')) { - if (*cp == ':') - *cp++ = '\0'; - root_server_addr = in_aton(name); - strcpy(name, cp); - } -} - - -/* * Parse option string. */ static void __init root_nfs_parse(char *name, char *buf) @@ -344,7 +313,7 @@ line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0'; sprintf(nfs_root_name, NFS_ROOT, line); } - root_nfs_parse_addr(nfs_root_name); + root_server_addr = root_nfs_parse_addr(nfs_root_name); return 1; } diff -urN linux-2.4.19-pre5/fs/nfsd/export.c linux-2.4.19-pre6/fs/nfsd/export.c --- linux-2.4.19-pre5/fs/nfsd/export.c Wed Oct 3 22:57:36 2001 +++ linux-2.4.19-pre6/fs/nfsd/export.c Thu Apr 4 22:05:12 2002 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -31,7 +32,6 @@ typedef struct svc_client svc_client; typedef struct svc_export svc_export; -static svc_export * exp_find(svc_client *clp, kdev_t dev); static svc_export * exp_parent(svc_client *clp, kdev_t dev, struct dentry *dentry); static svc_export * exp_child(svc_client *clp, kdev_t dev, @@ -65,41 +65,25 @@ static int hash_count; static DECLARE_WAIT_QUEUE_HEAD( hash_wait ); - -/* - * Find a client's export for a device. - */ -static inline svc_export * -exp_find(svc_client *clp, kdev_t dev) -{ - svc_export * exp; - - exp = clp->cl_export[EXPORT_HASH(dev)]; - while (exp && exp->ex_dev != dev) - exp = exp->ex_next; - return exp; -} - /* * Find the client's export entry matching xdev/xino. */ svc_export * exp_get(svc_client *clp, kdev_t dev, ino_t ino) { - svc_export * exp; + struct list_head *head, *p; if (!clp) return NULL; - exp = clp->cl_export[EXPORT_HASH(dev)]; - if (exp) - do { - if (exp->ex_ino == ino && exp->ex_dev == dev) - goto out; - } while (NULL != (exp = exp->ex_next)); - exp = NULL; -out: - return exp; + head = &clp->cl_export[EXPORT_HASH(dev)]; + list_for_each(p, head) { + svc_export *exp = list_entry(p, svc_export, ex_hash); + if (exp->ex_ino == ino && exp->ex_dev == dev) + return exp; + } + + return NULL; } /* @@ -108,15 +92,15 @@ static svc_export * exp_parent(svc_client *clp, kdev_t dev, struct dentry *dentry) { - svc_export *exp; + struct list_head *head = &clp->cl_export[EXPORT_HASH(dev)]; + struct list_head *p; - if (clp == NULL) - return NULL; - - for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next) + list_for_each(p,head) { + svc_export *exp = list_entry(p, svc_export, ex_hash); if (is_subdir(dentry, exp->ex_dentry)) - break; - return exp; + return exp; + } + return NULL; } /* @@ -127,17 +111,31 @@ static svc_export * exp_child(svc_client *clp, kdev_t dev, struct dentry *dentry) { - svc_export *exp; + struct list_head *head = &clp->cl_export[EXPORT_HASH(dev)]; + struct list_head *p; - if (clp == NULL) - return NULL; - for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next) { - struct dentry *ndentry = exp->ex_dentry; + list_for_each(p, head) { + svc_export *exp = list_entry(p, svc_export, ex_hash); + struct dentry *ndentry = exp->ex_dentry; + if (ndentry && is_subdir(ndentry->d_parent, dentry)) - break; + return exp; + } + return NULL; +} + +/* Update parent pointers of all exports */ +static void exp_change_parents(svc_client *clp, svc_export *old, svc_export *new) +{ + struct list_head *head = &clp->cl_list; + struct list_head *p; + + list_for_each(p, head) { + svc_export *exp = list_entry(p, svc_export, ex_list); + if (exp->ex_parent == old) + exp->ex_parent = new; } - return exp; } /* @@ -148,10 +146,9 @@ { svc_client *clp; svc_export *exp, *parent; - svc_export **head; struct nameidata nd; struct inode *inode = NULL; - int i, err; + int err; kdev_t dev; ino_t ino; @@ -237,8 +234,8 @@ strcpy(exp->ex_path, nxp->ex_path); exp->ex_client = clp; exp->ex_parent = parent; - exp->ex_dentry = nd.dentry; - exp->ex_mnt = nd.mnt; + exp->ex_dentry = dget(nd.dentry); + exp->ex_mnt = mntget(nd.mnt); exp->ex_flags = nxp->ex_flags; exp->ex_dev = dev; exp->ex_ino = ino; @@ -246,34 +243,20 @@ exp->ex_anon_gid = nxp->ex_anon_gid; /* Update parent pointers of all exports */ - if (parent) { - for (i = 0; i < NFSCLNT_EXPMAX; i++) { - svc_export *temp = clp->cl_export[i]; - - while (temp) { - if (temp->ex_parent == parent) - temp->ex_parent = exp; - temp = temp->ex_next; - } - } - } + if (parent) + exp_change_parents(clp, parent, exp); - head = clp->cl_export + EXPORT_HASH(dev); - exp->ex_next = *head; - *head = exp; + list_add(&exp->ex_hash, clp->cl_export + EXPORT_HASH(dev)); + list_add_tail(&exp->ex_list, &clp->cl_list); err = 0; - /* Unlock hashtable */ +finish: + path_release(&nd); out_unlock: exp_unlock(); out: return err; - - /* Release the dentry */ -finish: - path_release(&nd); - goto out_unlock; } /* @@ -283,20 +266,14 @@ static void exp_do_unexport(svc_export *unexp) { - svc_export *exp; - svc_client *clp; struct dentry *dentry; struct vfsmount *mnt; struct inode *inode; - int i; - /* Update parent pointers. */ - clp = unexp->ex_client; - for (i = 0; i < NFSCLNT_EXPMAX; i++) { - for (exp = clp->cl_export[i]; exp; exp = exp->ex_next) - if (exp->ex_parent == unexp) - exp->ex_parent = unexp->ex_parent; - } + list_del(&unexp->ex_hash); + list_del(&unexp->ex_list); + + exp_change_parents(unexp->ex_client, unexp, unexp->ex_parent); dentry = unexp->ex_dentry; mnt = unexp->ex_mnt; @@ -317,18 +294,13 @@ static void exp_unexport_all(svc_client *clp) { - svc_export *exp; - int i; + struct list_head *p = &clp->cl_list; dprintk("unexporting all fs's for clnt %p\n", clp); - for (i = 0; i < NFSCLNT_EXPMAX; i++) { - exp = clp->cl_export[i]; - clp->cl_export[i] = NULL; - while (exp) { - svc_export *next = exp->ex_next; - exp_do_unexport(exp); - exp = next; - } + + while (!list_empty(p)) { + svc_export *exp = list_entry(p->next, svc_export, ex_list); + exp_do_unexport(exp); } } @@ -339,7 +311,6 @@ exp_unexport(struct nfsctl_export *nxp) { svc_client *clp; - svc_export **expp, *exp = NULL; int err; /* Consistency check */ @@ -352,17 +323,10 @@ err = -EINVAL; clp = exp_getclientbyname(nxp->ex_client); if (clp) { - expp = clp->cl_export + EXPORT_HASH(nxp->ex_dev); - while ((exp = *expp) != NULL) { - if (exp->ex_dev == nxp->ex_dev) { - if (exp->ex_ino == nxp->ex_ino) { - *expp = exp->ex_next; - exp_do_unexport(exp); - err = 0; - break; - } - } - expp = &(exp->ex_next); + svc_export *exp = exp_get(clp, nxp->ex_dev, nxp->ex_ino); + if (exp) { + exp_do_unexport(exp); + err = 0; } } @@ -542,6 +506,68 @@ return NULL; } +/* Iterator */ + +static void *e_start(struct seq_file *m, loff_t *pos) +{ + loff_t n = *pos; + unsigned client, export; + svc_client *clp; + struct list_head *p; + + exp_readlock(); + if (!n--) + return (void *)1; + client = n >> 32; + export = n & ((1LL<<32) - 1); + for (clp = clients; client && clp; clp = clp->cl_next, client--) + ; + if (!clp) + return NULL; + list_for_each(p, &clp->cl_list) + if (!export--) + return list_entry(p, svc_export, ex_list); + n &= ~((1LL<<32) - 1); + do { + clp = clp->cl_next; + n += 1LL<<32; + } while(clp && list_empty(&clp->cl_list)); + if (!clp) + return NULL; + *pos = n+1; + return list_entry(clp->cl_list.next, svc_export, ex_list); +} + +static void *e_next(struct seq_file *m, void *p, loff_t *pos) +{ + svc_export *exp = p; + svc_client *clp; + + if (p == (void *)1) + clp = clients; + else if (exp->ex_list.next == &exp->ex_client->cl_list) { + clp = exp->ex_client->cl_next; + *pos += 1LL<<32; + } else { + ++*pos; + return list_entry(exp->ex_list.next, svc_export, ex_list); + } + *pos &= ~((1LL<<32) - 1); + while (clp && list_empty(&clp->cl_list)) { + clp = clp->cl_next; + *pos += 1LL<<32; + } + if (!clp) + return NULL; + ++*pos; + return list_entry(clp->cl_list.next, svc_export, ex_list); +} + +static void e_stop(struct seq_file *m, void *p) +{ + exp_unlock(); +} + struct flags { int flag; char *name[2]; @@ -564,128 +590,77 @@ { 0, {"", ""}} }; -static int -exp_flags(char *buffer, int flag) +static void exp_flags(struct seq_file *m, int flag) { - int len = 0, first = 0; - struct flags *flg = expflags; + int first = 0; + struct flags *flg; - for (;flg->flag;flg++) { - int state = (flg->flag & flag)?0:1; - if (!flg->flag) - break; - if (*flg->name[state]) { - len += sprintf(buffer + len, "%s%s", - first++?",":"", flg->name[state]); - } - } - return len; + for (flg = expflags; flg->flag; flg++) { + int state = (flg->flag & flag)?0:1; + if (*flg->name[state]) + seq_printf(m, "%s%s", first++?",":"", flg->name[state]); + } } - - -/* mangling borrowed from fs/super.c */ -/* Use octal escapes, like mount does, for embedded spaces etc. */ -static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' }; - -static int -mangle(const unsigned char *s, char *buf, int len) { - char *sp; - int n; - - sp = buf; - while(*s && sp-buf < len-3) { - for (n = 0; n < sizeof(need_escaping); n++) { - if (*s == need_escaping[n]) { - *sp++ = '\\'; - *sp++ = '0' + ((*s & 0300) >> 6); - *sp++ = '0' + ((*s & 070) >> 3); - *sp++ = '0' + (*s & 07); - goto next; - } - } - *sp++ = *s; - next: - s++; - } - return sp - buf; /* no trailing NUL */ +static inline void mangle(struct seq_file *m, const char *s) +{ + seq_escape(m, s, " \t\n\\"); } -#define FREEROOM ((int)PAGE_SIZE-200-len) -#define MANGLE(s) len += mangle((s), buffer+len, FREEROOM); - -int -exp_procfs_exports(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) +static int e_show(struct seq_file *m, void *p) { - struct svc_clnthash **hp, **head, *tmp; - struct svc_client *clp; - svc_export *exp; - off_t pos = 0; - off_t begin = 0; - int len = 0; - int i,j; + struct svc_export *exp = p; + struct svc_client *clp; + int j, first = 0; - len += sprintf(buffer, "# Version 1.1\n"); - len += sprintf(buffer+len, "# Path Client(Flags) # IPs\n"); - - for (clp = clients; clp; clp = clp->cl_next) { - for (i = 0; i < NFSCLNT_EXPMAX; i++) { - exp = clp->cl_export[i]; - while (exp) { - int first = 0; - MANGLE(exp->ex_path); - buffer[len++]='\t'; - MANGLE(clp->cl_ident); - buffer[len++]='('; - - len += exp_flags(buffer+len, exp->ex_flags); - len += sprintf(buffer+len, ") # "); - for (j = 0; j < clp->cl_naddr; j++) { - struct in_addr addr = clp->cl_addr[j]; - - head = &clnt_hash[CLIENT_HASH(addr.s_addr)]; - for (hp = head; (tmp = *hp) != NULL; hp = &(tmp->h_next)) { - if (tmp->h_addr.s_addr == addr.s_addr) { - if (first++) len += sprintf(buffer+len, "%s", " "); - if (tmp->h_client != clp) - len += sprintf(buffer+len, "("); - len += sprintf(buffer+len, "%d.%d.%d.%d", - htonl(addr.s_addr) >> 24 & 0xff, - htonl(addr.s_addr) >> 16 & 0xff, - htonl(addr.s_addr) >> 8 & 0xff, - htonl(addr.s_addr) >> 0 & 0xff); - if (tmp->h_client != clp) - len += sprintf(buffer+len, ")"); - break; - } - } - } - exp = exp->ex_next; - - buffer[len++]='\n'; - - pos=begin+len; - if(pos offset + length) - goto done; - } - } + if (p == (void *)1) { + seq_puts(m, "# Version 1.1\n"); + seq_puts(m, "# Path Client(Flags) # IPs\n"); + return 0; } - *eof = 1; + clp = exp->ex_client; -done: - *start = buffer + (offset - begin); - len -= (offset - begin); - if ( len > length ) - len = length; - return len; + mangle(m, exp->ex_path); + seq_putc(m, '\t'); + mangle(m, clp->cl_ident); + seq_putc(m, '('); + exp_flags(m, exp->ex_flags); + seq_puts(m, ") # "); + for (j = 0; j < clp->cl_naddr; j++) { + struct svc_clnthash **hp, **head, *tmp; + struct in_addr addr = clp->cl_addr[j]; + + head = &clnt_hash[CLIENT_HASH(addr.s_addr)]; + for (hp = head; (tmp = *hp) != NULL; hp = &(tmp->h_next)) { + if (tmp->h_addr.s_addr == addr.s_addr) + break; + } + if (tmp) { + if (first++) + seq_putc(m, ' '); + if (tmp->h_client != clp) + seq_putc(m, '('); + seq_printf(m, "%d.%d.%d.%d", + htonl(addr.s_addr) >> 24 & 0xff, + htonl(addr.s_addr) >> 16 & 0xff, + htonl(addr.s_addr) >> 8 & 0xff, + htonl(addr.s_addr) >> 0 & 0xff); + if (tmp->h_client != clp) + seq_putc(m, ')'); + } + } + seq_putc(m, '\n'); + return 0; } +struct seq_operations nfs_exports_op = { + start: e_start, + next: e_next, + stop: e_stop, + show: e_show, +}; + /* * Add or modify a client. * Change requests may involve the list of host addresses. The list of @@ -721,6 +696,9 @@ if (!(clp = kmalloc(sizeof(*clp), GFP_KERNEL))) goto out_unlock; memset(clp, 0, sizeof(*clp)); + for (i = 0; i < NFSCLNT_EXPMAX; i++) + INIT_LIST_HEAD(&clp->cl_export[i]); + INIT_LIST_HEAD(&clp->cl_list); dprintk("created client %s (%p)\n", ncp->cl_ident, clp); diff -urN linux-2.4.19-pre5/fs/nfsd/nfs3proc.c linux-2.4.19-pre6/fs/nfsd/nfs3proc.c --- linux-2.4.19-pre5/fs/nfsd/nfs3proc.c Thu Sep 20 21:02:01 2001 +++ linux-2.4.19-pre6/fs/nfsd/nfs3proc.c Thu Apr 4 22:05:12 2002 @@ -339,7 +339,7 @@ || (argp->ftype == NF3BLK && argp->major >= MAX_BLKDEV) || argp->minor > 0xFF) RETURN_STATUS(nfserr_inval); - rdev = ((argp->major) << 8) | (argp->minor); + rdev = MKDEV(argp->major, argp->minor); } else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) RETURN_STATUS(nfserr_inval); diff -urN linux-2.4.19-pre5/fs/nfsd/nfsctl.c linux-2.4.19-pre6/fs/nfsd/nfsctl.c --- linux-2.4.19-pre5/fs/nfsd/nfsctl.c Sun Oct 21 10:32:33 2001 +++ linux-2.4.19-pre6/fs/nfsd/nfsctl.c Thu Apr 4 22:05:12 2002 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -44,31 +45,26 @@ static int nfsctl_ugidupdate(struct nfsctl_ugidmap *data); #endif -static int initialized; - -int exp_procfs_exports(char *buffer, char **start, off_t offset, - int length, int *eof, void *data); +extern struct seq_operations nfs_exports_op; +static int exports_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &nfs_exports_op); +} +static struct file_operations exports_operations = { + open: exports_open, + read: seq_read, + llseek: seq_lseek, + release: seq_release, +}; void proc_export_init(void) { + struct proc_dir_entry *entry; if (!proc_mkdir("fs/nfs", 0)) return; - create_proc_read_entry("fs/nfs/exports", 0, 0, exp_procfs_exports,NULL); -} - - -/* - * Initialize nfsd - */ -static void -nfsd_init(void) -{ - nfsd_stat_init(); /* Statistics */ - nfsd_cache_init(); /* RPC reply cache */ - nfsd_export_init(); /* Exports table */ - nfsd_lockd_init(); /* lockd->nfsd callbacks */ - proc_export_init(); - initialized = 1; + entry = create_proc_entry("fs/nfs/exports", 0, NULL); + if (entry) + entry->proc_fops = &exports_operations; } static inline int @@ -225,10 +221,8 @@ int err; int argsize, respsize; - MOD_INC_USE_COUNT; lock_kernel (); - if (!initialized) - nfsd_init(); + err = -EPERM; if (!capable(CAP_SYS_ADMIN)) { goto done; @@ -301,38 +295,47 @@ kfree(res); unlock_kernel (); - MOD_DEC_USE_COUNT; return err; } -#ifdef MODULE -/* New-style module support since 2.1.18 */ EXPORT_NO_SYMBOLS; MODULE_AUTHOR("Olaf Kirch "); MODULE_LICENSE("GPL"); +#ifdef MODULE struct nfsd_linkage nfsd_linkage_s = { do_nfsservctl: handle_sys_nfsservctl, + owner: THIS_MODULE, }; +#endif /* * Initialize the module */ -int -init_module(void) +static int __init +nfsd_init(void) { printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); +#ifdef MODULE nfsd_linkage = &nfsd_linkage_s; +#endif + nfsd_stat_init(); /* Statistics */ + nfsd_cache_init(); /* RPC reply cache */ + nfsd_export_init(); /* Exports table */ + nfsd_lockd_init(); /* lockd->nfsd callbacks */ + proc_export_init(); return 0; } /* * Clean up the mess before unloading the module */ -void -cleanup_module(void) +static void __exit +nfsd_exit(void) { +#ifdef MODULE nfsd_linkage = NULL; +#endif nfsd_export_shutdown(); nfsd_cache_shutdown(); remove_proc_entry("fs/nfs/exports", NULL); @@ -340,4 +343,6 @@ nfsd_stat_shutdown(); nfsd_lockd_shutdown(); } -#endif + +module_init(nfsd_init); +module_exit(nfsd_exit); diff -urN linux-2.4.19-pre5/fs/nfsd/nfsfh.c linux-2.4.19-pre6/fs/nfsd/nfsfh.c --- linux-2.4.19-pre5/fs/nfsd/nfsfh.c Wed Oct 3 22:59:22 2001 +++ linux-2.4.19-pre6/fs/nfsd/nfsfh.c Thu Apr 4 22:05:12 2002 @@ -576,11 +576,9 @@ error = nfserr_stale; exp = exp_get(rqstp->rq_client, xdev, xino); - if (!exp) { + if (!exp) /* export entry revoked */ - nfsdstats.fh_stale++; goto out; - } /* Check if the request originated from a secure port. */ error = nfserr_perm; @@ -657,7 +655,7 @@ * write call). */ - /* When is type ever negative? */ + /* Type can be negative to e.g. exclude directories from linking */ if (type > 0 && (inode->i_mode & S_IFMT) != type) { error = (type == S_IFDIR)? nfserr_notdir : nfserr_isdir; goto out; @@ -690,13 +688,11 @@ && !(tdentry->d_inode->i_mode & S_IXOTH) ) { error = nfserr_stale; - nfsdstats.fh_stale++; dprintk("fh_verify: no root_squashed access.\n"); } } while ((tdentry != tdentry->d_parent)); if (exp->ex_dentry != tdentry) { error = nfserr_stale; - nfsdstats.fh_stale++; printk("nfsd Security: %s/%s bad export.\n", dentry->d_parent->d_name.name, dentry->d_name.name); @@ -716,6 +712,8 @@ } #endif out: + if (error == nfserr_stale) + nfsdstats.fh_stale++; return error; } diff -urN linux-2.4.19-pre5/fs/nfsd/vfs.c linux-2.4.19-pre6/fs/nfsd/vfs.c --- linux-2.4.19-pre5/fs/nfsd/vfs.c Fri Dec 21 09:41:55 2001 +++ linux-2.4.19-pre6/fs/nfsd/vfs.c Thu Apr 4 22:05:12 2002 @@ -216,36 +216,37 @@ dentry = fhp->fh_dentry; inode = dentry->d_inode; - err = inode_change_ok(inode, iap); - /* could be a "touch" (utimes) request where the user is not the owner but does - * have write permission. In this case the user should be allowed to set - * both times to the current time. We could just assume any such SETATTR - * is intended to set the times to "now", but we do a couple of simple tests - * to increase our confidence. + /* NFSv2 does not differentiate between "set-[ac]time-to-now" + * which only requires access, and "set-[ac]time-to-X" which + * requires ownership. + * So if it looks like it might be "set both to the same time which + * is close to now", and if inode_change_ok fails, then we + * convert to "set to now" instead of "set to explicit time" + * + * We only call inode_change_ok as the last test as technically + * it is not an interface that we should be using. It is only + * valid if the filesystem does not define it's own i_op->setattr. */ #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET) #define MAX_TOUCH_TIME_ERROR (30*60) - if (err - && (iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET + if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET && iap->ia_mtime == iap->ia_atime ) { - /* looks good. now just make sure time is in the right ballpark. - * solaris, at least, doesn't seem to care what the time request is + /* Looks probable. Now just make sure time is in the right ballpark. + * Solaris, at least, doesn't seem to care what the time request is. + * We require it be within 30 minutes of now. */ time_t delta = iap->ia_atime - CURRENT_TIME; if (delta<0) delta = -delta; - if (delta < MAX_TOUCH_TIME_ERROR) { + if (delta < MAX_TOUCH_TIME_ERROR && + inode_change_ok(inode, iap) != 0) { /* turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME * this will cause notify_change to set these times to "now" */ iap->ia_valid &= ~BOTH_TIME_SET; - err = inode_change_ok(inode, iap); } } - if (err) - goto out_nfserr; - /* The size case is special. It changes the file as well as the attributes. */ if (iap->ia_valid & ATTR_SIZE) { if (iap->ia_size < inode->i_size) { @@ -518,24 +519,33 @@ * As this calls fsync (not fdatasync) there is no need for a write_inode * after it. */ +inline void nfsd_dosync(struct file *filp, struct dentry *dp, + struct file_operations *fop) +{ + struct inode *inode = dp->d_inode; + int (*fsync) (struct file *, struct dentry *, int); + + filemap_fdatasync(inode->i_mapping); + if (fop && (fsync = fop->fsync)) + fsync(filp, dp, 0); + filemap_fdatawait(inode->i_mapping); +} + + void nfsd_sync(struct file *filp) { + struct inode *inode = filp->f_dentry->d_inode; dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name); - down(&filp->f_dentry->d_inode->i_sem); - filp->f_op->fsync(filp, filp->f_dentry, 0); - up(&filp->f_dentry->d_inode->i_sem); + down(&inode->i_sem); + nfsd_dosync(filp, filp->f_dentry, filp->f_op); + up(&inode->i_sem); } void nfsd_sync_dir(struct dentry *dp) { - struct inode *inode = dp->d_inode; - int (*fsync) (struct file *, struct dentry *, int); - - if (inode->i_fop && (fsync = inode->i_fop->fsync)) { - fsync(NULL, dp, 0); - } + nfsd_dosync(NULL, dp, dp->d_inode->i_fop); } /* @@ -1380,7 +1390,6 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset, encode_dent_fn func, u32 *buffer, int *countp, u32 *verf) { - struct inode *inode; u32 *p; int oldlen, eof, err; struct file file; @@ -1392,9 +1401,6 @@ if (offset > ~(u32) 0) goto out_close; - err = nfserr_notdir; - if (!file.f_op->readdir) - goto out_close; file.f_pos = offset; /* Set up the readdir context */ @@ -1409,25 +1415,16 @@ * readdir() is not guaranteed to fill up the entire buffer, but * may choose to do less. */ - inode = file.f_dentry->d_inode; - down(&inode->i_sem); - while (1) { + + do { oldlen = cd.buflen; - /* - dprintk("nfsd: f_op->readdir(%x/%ld @ %d) buflen = %d (%d)\n", - file.f_inode->i_dev, file.f_inode->i_ino, - (int) file.f_pos, (int) oldlen, (int) cd.buflen); - */ - err = file.f_op->readdir(&file, &cd, (filldir_t) func); + err = vfs_readdir(&file, (filldir_t) func, &cd); + if (err < 0) goto out_nfserr; - if (oldlen == cd.buflen) - break; - if (cd.eob) - break; - } - up(&inode->i_sem); + + } while (oldlen != cd.buflen && !cd.eob); /* If we didn't fill the buffer completely, we're at EOF */ eof = !cd.eob; @@ -1454,7 +1451,6 @@ return err; out_nfserr: - up(&inode->i_sem); err = nfserrno(err); goto out_close; } diff -urN linux-2.4.19-pre5/fs/proc/base.c linux-2.4.19-pre6/fs/proc/base.c --- linux-2.4.19-pre5/fs/proc/base.c Mon Feb 25 11:38:09 2002 +++ linux-2.4.19-pre6/fs/proc/base.c Thu Apr 4 22:05:12 2002 @@ -23,6 +23,8 @@ #include #include #include +#include +#include /* * For hysterical raisins we keep the same inumbers as in the old procfs. @@ -246,6 +248,46 @@ read: pid_maps_read, }; +extern struct seq_operations mounts_op; +static int mounts_open(struct inode *inode, struct file *file) +{ + struct task_struct *task = inode->u.proc_i.task; + int ret = seq_open(file, &mounts_op); + + if (!ret) { + struct seq_file *m = file->private_data; + struct namespace *namespace; + task_lock(task); + namespace = task->namespace; + if (namespace) + get_namespace(namespace); + task_unlock(task); + + if (namespace) + m->private = namespace; + else { + seq_release(inode, file); + ret = -EINVAL; + } + } + return ret; +} + +static int mounts_release(struct inode *inode, struct file *file) +{ + struct seq_file *m = file->private_data; + struct namespace *namespace = m->private; + put_namespace(namespace); + return seq_release(inode, file); +} + +static struct file_operations proc_mounts_operations = { + open: mounts_open, + read: seq_read, + llseek: seq_lseek, + release: mounts_release, +}; + #define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ static ssize_t proc_info_read(struct file * file, char * buf, @@ -497,6 +539,7 @@ PROC_PID_STATM, PROC_PID_MAPS, PROC_PID_CPU, + PROC_PID_MOUNTS, PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */ }; @@ -516,6 +559,7 @@ E(PROC_PID_CWD, "cwd", S_IFLNK|S_IRWXUGO), E(PROC_PID_ROOT, "root", S_IFLNK|S_IRWXUGO), E(PROC_PID_EXE, "exe", S_IFLNK|S_IRWXUGO), + E(PROC_PID_MOUNTS, "mounts", S_IFREG|S_IRUGO), {0,0,NULL,0} }; #undef E @@ -881,6 +925,9 @@ inode->i_op = &proc_mem_inode_operations; inode->i_fop = &proc_mem_operations; break; + case PROC_PID_MOUNTS: + inode->i_fop = &proc_mounts_operations; + break; default: printk("procfs: impossible type (%d)",p->type); iput(inode); diff -urN linux-2.4.19-pre5/fs/proc/proc_misc.c linux-2.4.19-pre6/fs/proc/proc_misc.c --- linux-2.4.19-pre5/fs/proc/proc_misc.c Thu Apr 4 22:04:27 2002 +++ linux-2.4.19-pre6/fs/proc/proc_misc.c Thu Apr 4 22:05:12 2002 @@ -493,18 +493,6 @@ write: write_profile, }; -extern struct seq_operations mounts_op; -static int mounts_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &mounts_op); -} -static struct file_operations proc_mounts_operations = { - open: mounts_open, - read: seq_read, - llseek: seq_lseek, - release: seq_release, -}; - struct proc_dir_entry *proc_root_kcore; static void create_seq_entry(char *name, mode_t mode, struct file_operations *f) @@ -557,11 +545,12 @@ for (p = simple_ones; p->name; p++) create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL); + proc_symlink("mounts", NULL, "self/mounts"); + /* And now for trickier ones */ entry = create_proc_entry("kmsg", S_IRUSR, &proc_root); if (entry) entry->proc_fops = &proc_kmsg_operations; - create_seq_entry("mounts", 0, &proc_mounts_operations); create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); #ifdef CONFIG_MODULES create_seq_entry("ksyms", 0, &proc_ksyms_operations); diff -urN linux-2.4.19-pre5/fs/ramfs/inode.c linux-2.4.19-pre6/fs/ramfs/inode.c --- linux-2.4.19-pre5/fs/ramfs/inode.c Wed Oct 24 15:19:18 2001 +++ linux-2.4.19-pre6/fs/ramfs/inode.c Thu Apr 4 22:05:12 2002 @@ -325,6 +325,7 @@ } static DECLARE_FSTYPE(ramfs_fs_type, "ramfs", ramfs_read_super, FS_LITTER); +static DECLARE_FSTYPE(rootfs_fs_type, "rootfs", ramfs_read_super, FS_NOMOUNT|FS_LITTER); static int __init init_ramfs_fs(void) { @@ -338,5 +339,11 @@ module_init(init_ramfs_fs) module_exit(exit_ramfs_fs) + +int __init init_rootfs(void) +{ + return register_filesystem(&rootfs_fs_type); +} + MODULE_LICENSE("GPL"); diff -urN linux-2.4.19-pre5/fs/super.c linux-2.4.19-pre6/fs/super.c --- linux-2.4.19-pre5/fs/super.c Thu Apr 4 22:04:27 2002 +++ linux-2.4.19-pre6/fs/super.c Thu Apr 4 22:05:12 2002 @@ -34,8 +34,6 @@ #define __NO_VERSION__ #include -int do_remount_sb(struct super_block *sb, int flags, void * data); - LIST_HEAD(super_blocks); spinlock_t sb_lock = SPIN_LOCK_UNLOCKED; @@ -377,7 +375,7 @@ get_filesystem(type); } -void put_unnamed_dev(kdev_t dev); /* should become static */ +static void put_anon_dev(kdev_t dev); /** * remove_super - makes superblock unreachable @@ -407,12 +405,11 @@ if (bdev) blkdev_put(bdev, BDEV_FS); else - put_unnamed_dev(dev); + 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) { @@ -530,36 +527,122 @@ return err; } +/** + * do_remount_sb - asks filesystem to change mount options. + * @sb: superblock in question + * @flags: numeric part of options + * @data: the rest of options + * + * Alters the mount options of a mounted file system. + */ +int do_remount_sb(struct super_block *sb, int flags, void *data) +{ + int retval; + + if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev)) + return -EACCES; + /*flags |= MS_RDONLY;*/ + if (flags & MS_RDONLY) + acct_auto_close(sb->s_dev); + shrink_dcache_sb(sb); + fsync_super(sb); + /* If we are remounting RDONLY, make sure there are no rw files open */ + if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) + if (!fs_may_remount_ro(sb)) + return -EBUSY; + if (sb->s_op && sb->s_op->remount_fs) { + lock_super(sb); + retval = sb->s_op->remount_fs(sb, &flags, data); + unlock_super(sb); + if (retval) + return retval; + } + sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); + return 0; +} + /* * Unnamed block devices are dummy devices used by virtual * filesystems which don't use real block-devices. -- jrs */ -static unsigned long unnamed_dev_in_use[256/(8*sizeof(unsigned long))]; +enum {Max_anon = 256}; +static unsigned long unnamed_dev_in_use[Max_anon/(8*sizeof(unsigned long))]; +static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */ -kdev_t get_unnamed_dev(void) +/** + * put_anon_dev - release anonymous device number. + * @dev: device in question + */ +static void put_anon_dev(kdev_t dev) { - int i; - - for (i = 1; i < 256; i++) { - if (!test_and_set_bit(i,unnamed_dev_in_use)) - return MKDEV(UNNAMED_MAJOR, i); - } - return 0; + spin_lock(&unnamed_dev_lock); + clear_bit(MINOR(dev), unnamed_dev_in_use); + spin_unlock(&unnamed_dev_lock); } -void put_unnamed_dev(kdev_t dev) +/** + * get_anon_super - allocate a superblock for non-device fs + * @type: filesystem type + * @compare: check if existing superblock is what we want + * @data: argument for @compare. + * + * get_anon_super is a helper for non-blockdevice filesystems. + * It either finds and returns one of the superblocks of given type + * (if it can find one that would satisfy caller) or creates a new + * one. In the either case we return an active reference to superblock + * with ->s_umount locked. If superblock is new it gets a new + * anonymous device allocated for it and is inserted into lists - + * other initialization is left to caller. + * + * Rather than duplicating all that logics every time when + * we want something that doesn't fit "nodev" and "single" we pull + * the relevant code into common helper and let get_sb_...() call + * it. + * + * NB: get_sb_...() is going to become an fs type method, with + * current ->read_super() becoming a callback used by common instances. + */ +struct super_block *get_anon_super(struct file_system_type *type, + int (*compare)(struct super_block *,void *), void *data) { - if (!dev || MAJOR(dev) != UNNAMED_MAJOR) - return; - if (test_and_clear_bit(MINOR(dev), unnamed_dev_in_use)) - return; - printk("VFS: put_unnamed_dev: freeing unused device %s\n", - kdevname(dev)); + struct super_block *s = alloc_super(); + kdev_t dev; + struct list_head *p; + + if (!s) + return ERR_PTR(-ENOMEM); + + spin_lock(&unnamed_dev_lock); + dev = find_first_zero_bit(unnamed_dev_in_use, Max_anon); + if (dev == Max_anon) { + spin_unlock(&unnamed_dev_lock); + destroy_super(s); + return ERR_PTR(-EMFILE); + } + set_bit(dev, unnamed_dev_in_use); + spin_unlock(&unnamed_dev_lock); + +retry: + spin_lock(&sb_lock); + if (compare) list_for_each(p, &type->fs_supers) { + struct super_block *old; + old = list_entry(p, struct super_block, s_instances); + if (!compare(old, data)) + continue; + if (!grab_super(old)) + goto retry; + destroy_super(s); + return old; + } + + s->s_dev = dev; + insert_super(s, type); + return s; } static struct super_block *get_sb_bdev(struct file_system_type *fs_type, - char *dev_name, int flags, void * data) + int flags, char *dev_name, void * data) { struct inode *inode; struct block_device *bdev; @@ -601,17 +684,13 @@ goto out; check_disk_change(dev); error = -EACCES; - if (!(flags & MS_RDONLY) && is_read_only(dev)) { - blkdev_put(bdev, BDEV_FS); - goto out; - } + if (!(flags & MS_RDONLY) && is_read_only(dev)) + goto out1; error = -ENOMEM; s = alloc_super(); - if (!s) { - blkdev_put(bdev, BDEV_FS); - goto out; - } + if (!s) + goto out1; error = -EBUSY; restart: @@ -625,8 +704,7 @@ ((flags ^ old->s_flags) & MS_RDONLY)) { spin_unlock(&sb_lock); destroy_super(s); - blkdev_put(bdev, BDEV_FS); - goto out; + goto out1; } if (!grab_super(old)) goto restart; @@ -639,97 +717,102 @@ s->s_bdev = bdev; s->s_flags = flags; insert_super(s, fs_type); - - error = -EINVAL; - lock_super(s); if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) - goto out_fail; + goto Einval; s->s_flags |= MS_ACTIVE; - unlock_super(s); path_release(&nd); return s; -out_fail: - unlock_super(s); +Einval: deactivate_super(s); remove_super(s); + error = -EINVAL; + goto out; +out1: + blkdev_put(bdev, BDEV_FS); out: path_release(&nd); return ERR_PTR(error); } static struct super_block *get_sb_nodev(struct file_system_type *fs_type, - int flags, void * data) + int flags, char *dev_name, void *data) { - struct super_block *s = alloc_super(); + struct super_block *s = get_anon_super(fs_type, NULL, NULL); + + if (IS_ERR(s)) + return s; - if (!s) - return ERR_PTR(-ENOMEM); - s->s_dev = get_unnamed_dev(); - if (!s->s_dev) { - destroy_super(s); - return ERR_PTR(-EMFILE); - } s->s_flags = flags; - spin_lock(&sb_lock); - insert_super(s, fs_type); - lock_super(s); - if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) - goto out_fail; + if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) { + deactivate_super(s); + remove_super(s); + return ERR_PTR(-EINVAL); + } s->s_flags |= MS_ACTIVE; - unlock_super(s); return s; +} -out_fail: - unlock_super(s); - deactivate_super(s); - remove_super(s); - return ERR_PTR(-EINVAL); +static int compare_single(struct super_block *s, void *p) +{ + return 1; } static struct super_block *get_sb_single(struct file_system_type *fs_type, - int flags, void *data) + int flags, char *dev_name, void *data) { - struct super_block * s = alloc_super(); - if (!s) - return ERR_PTR(-ENOMEM); - /* - * Get the superblock of kernel-wide instance, but - * keep the reference to fs_type. - */ -retry: - spin_lock(&sb_lock); - if (!list_empty(&fs_type->fs_supers)) { - struct super_block *old; - old = list_entry(fs_type->fs_supers.next, struct super_block, - s_instances); - if (!grab_super(old)) - goto retry; - destroy_super(s); - do_remount_sb(old, flags, data); - return old; - } else { - s->s_dev = get_unnamed_dev(); - if (!s->s_dev) { - spin_unlock(&sb_lock); - destroy_super(s); - return ERR_PTR(-EMFILE); - } + struct super_block *s = get_anon_super(fs_type, compare_single, NULL); + + if (IS_ERR(s)) + return s; + if (!s->s_root) { s->s_flags = flags; - insert_super(s, fs_type); - lock_super(s); - if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) - goto out_fail; + if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) { + deactivate_super(s); + remove_super(s); + return ERR_PTR(-EINVAL); + } s->s_flags |= MS_ACTIVE; - unlock_super(s); - return s; - - out_fail: - unlock_super(s); - deactivate_super(s); - remove_super(s); - return ERR_PTR(-EINVAL); } + do_remount_sb(s, flags, data); + return s; +} + +struct vfsmount * +do_kern_mount(const char *fstype, int flags, char *name, void *data) +{ + struct file_system_type *type = get_fs_type(fstype); + struct super_block *sb = ERR_PTR(-ENOMEM); + struct vfsmount *mnt; + + if (!type) + return ERR_PTR(-ENODEV); + + mnt = alloc_vfsmnt(name); + if (!mnt) + goto out; + if (type->fs_flags & FS_REQUIRES_DEV) + sb = get_sb_bdev(type, flags, name, data); + else if (type->fs_flags & FS_SINGLE) + sb = get_sb_single(type, flags, name, data); + else + sb = get_sb_nodev(type, flags, name, data); + if (IS_ERR(sb)) + goto out_mnt; + if (type->fs_flags & FS_NOMOUNT) + sb->s_flags |= MS_NOUSER; + mnt->mnt_sb = sb; + mnt->mnt_root = dget(sb->s_root); + mnt->mnt_mountpoint = sb->s_root; + mnt->mnt_parent = mnt; + up_write(&sb->s_umount); + put_filesystem(type); + return mnt; +out_mnt: + free_vfsmnt(mnt); +out: + put_filesystem(type); + return (struct vfsmount *)sb; } void kill_super(struct super_block *sb) @@ -742,7 +825,6 @@ return; down_write(&sb->s_umount); - lock_kernel(); sb->s_root = NULL; /* Need to clean after the sucker */ if (fs->fs_flags & FS_LITTER) @@ -751,6 +833,7 @@ dput(root); fsync_super(sb); lock_super(sb); + lock_kernel(); sb->s_flags &= ~MS_ACTIVE; invalidate_inodes(sb); /* bad name - it should be evict_inodes() */ if (sop) { @@ -771,96 +854,7 @@ remove_super(sb); } -/* - * Alters the mount flags of a mounted file system. Only the mount point - * is used as a reference - file system type and the device are ignored. - */ - -int do_remount_sb(struct super_block *sb, int flags, void *data) -{ - int retval; - - if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev)) - return -EACCES; - /*flags |= MS_RDONLY;*/ - if (flags & MS_RDONLY) - acct_auto_close(sb->s_dev); - shrink_dcache_sb(sb); - fsync_super(sb); - /* If we are remounting RDONLY, make sure there are no rw files open */ - if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) - if (!fs_may_remount_ro(sb)) - return -EBUSY; - if (sb->s_op && sb->s_op->remount_fs) { - lock_super(sb); - retval = sb->s_op->remount_fs(sb, &flags, data); - unlock_super(sb); - if (retval) - return retval; - } - sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); - - /* - * We can't invalidate inodes as we can loose data when remounting - * (someone might manage to alter data while we are waiting in lock_super() - * or in foo_remount_fs())) - */ - - return 0; -} - -struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data) -{ - struct file_system_type * fstype; - struct vfsmount *mnt = NULL; - struct super_block *sb; - - if (!type || !memchr(type, 0, PAGE_SIZE)) - return ERR_PTR(-EINVAL); - - /* we need capabilities... */ - if (!capable(CAP_SYS_ADMIN)) - return ERR_PTR(-EPERM); - - /* ... filesystem driver... */ - fstype = get_fs_type(type); - if (!fstype) - return ERR_PTR(-ENODEV); - - /* ... allocated vfsmount... */ - mnt = alloc_vfsmnt(); - if (!mnt) { - mnt = ERR_PTR(-ENOMEM); - goto fs_out; - } - set_devname(mnt, name); - /* get locked superblock */ - if (fstype->fs_flags & FS_REQUIRES_DEV) - sb = get_sb_bdev(fstype, name, flags, data); - else if (fstype->fs_flags & FS_SINGLE) - sb = get_sb_single(fstype, flags, data); - else - sb = get_sb_nodev(fstype, flags, data); - - if (IS_ERR(sb)) { - free_vfsmnt(mnt); - mnt = (struct vfsmount *)sb; - goto fs_out; - } - if (fstype->fs_flags & FS_NOMOUNT) - sb->s_flags |= MS_NOUSER; - - mnt->mnt_sb = sb; - mnt->mnt_root = dget(sb->s_root); - mnt->mnt_mountpoint = mnt->mnt_root; - mnt->mnt_parent = mnt; - up_write(&sb->s_umount); -fs_out: - put_filesystem(fstype); - return mnt; -} - struct vfsmount *kern_mount(struct file_system_type *type) { - return do_kern_mount((char *)type->name, 0, (char *)type->name, NULL); + return do_kern_mount(type->name, 0, (char *)type->name, NULL); } diff -urN linux-2.4.19-pre5/include/asm-i386/types.h linux-2.4.19-pre6/include/asm-i386/types.h --- linux-2.4.19-pre5/include/asm-i386/types.h Fri Oct 12 15:35:54 2001 +++ linux-2.4.19-pre6/include/asm-i386/types.h Thu Apr 4 22:05:13 2002 @@ -45,7 +45,7 @@ /* DMA addresses come in generic and 64-bit flavours. */ -#ifdef CONFIG_HIGHMEM +#ifdef CONFIG_HIGHMEM64G typedef u64 dma_addr_t; #else typedef u32 dma_addr_t; diff -urN linux-2.4.19-pre5/include/asm-m68k/machdep.h linux-2.4.19-pre6/include/asm-m68k/machdep.h --- linux-2.4.19-pre5/include/asm-m68k/machdep.h Mon Nov 27 17:57:34 2000 +++ linux-2.4.19-pre6/include/asm-m68k/machdep.h Thu Apr 4 22:05:14 2002 @@ -37,7 +37,6 @@ extern void (*mach_hd_setup)(char *, int *); extern long mach_max_dma_address; extern void (*mach_floppy_setup)(char *, int *); -extern void (*mach_floppy_eject)(void); extern void (*mach_heartbeat) (int); extern void (*mach_l2_flush) (int); extern int mach_sysrq_key; diff -urN linux-2.4.19-pre5/include/asm-sparc/keyboard.h linux-2.4.19-pre6/include/asm-sparc/keyboard.h --- linux-2.4.19-pre5/include/asm-sparc/keyboard.h Tue Aug 28 07:09:44 2001 +++ linux-2.4.19-pre6/include/asm-sparc/keyboard.h Thu Apr 4 22:05:15 2002 @@ -40,7 +40,6 @@ #define kbd_init pcikbd_init #define compute_shiftstate pci_compute_shiftstate -#define keyboard_wait_for_keypress pci_wait_for_keypress #define getkeycode pci_getkeycode #define setkeycode pci_setkeycode #define getledstate pci_getledstate diff -urN linux-2.4.19-pre5/include/asm-sparc64/keyboard.h linux-2.4.19-pre6/include/asm-sparc64/keyboard.h --- linux-2.4.19-pre5/include/asm-sparc64/keyboard.h Tue Aug 28 07:09:44 2001 +++ linux-2.4.19-pre6/include/asm-sparc64/keyboard.h Thu Apr 4 22:05:15 2002 @@ -38,7 +38,6 @@ #define kbd_init pcikbd_init #define compute_shiftstate pci_compute_shiftstate -#define keyboard_wait_for_keypress pci_wait_for_keypress #define getkeycode pci_getkeycode #define setkeycode pci_setkeycode #define getledstate pci_getledstate diff -urN linux-2.4.19-pre5/include/linux/agp_backend.h linux-2.4.19-pre6/include/linux/agp_backend.h --- linux-2.4.19-pre5/include/linux/agp_backend.h Fri Nov 9 14:11:15 2001 +++ linux-2.4.19-pre6/include/linux/agp_backend.h Thu Apr 4 22:05:15 2002 @@ -69,6 +69,7 @@ ALI_M1631, ALI_M1632, ALI_M1641, + ALI_M1644, ALI_M1647, ALI_M1651, ALI_GENERIC, diff -urN linux-2.4.19-pre5/include/linux/blk.h linux-2.4.19-pre6/include/linux/blk.h --- linux-2.4.19-pre5/include/linux/blk.h Thu Nov 22 11:48:07 2001 +++ linux-2.4.19-pre6/include/linux/blk.h Thu Apr 4 22:05:15 2002 @@ -59,8 +59,6 @@ void add_blkdev_randomness(int major); extern int floppy_init(void); -extern void rd_load(void); -extern int rd_init(void); extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ extern int rd_image_start; /* starting block # of image */ @@ -70,7 +68,6 @@ #define INITRD_MINOR 250 /* shouldn't collide with /dev/ram* too soon ... */ extern unsigned long initrd_start,initrd_end; -extern int mount_initrd; /* zero if initrd should not be mounted */ extern int initrd_below_start_ok; /* 1 if it is not an error if initrd_start < memory_start */ void initrd_init(void); diff -urN linux-2.4.19-pre5/include/linux/blkdev.h linux-2.4.19-pre6/include/linux/blkdev.h --- linux-2.4.19-pre5/include/linux/blkdev.h Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/include/linux/blkdev.h Thu Apr 4 22:05:15 2002 @@ -30,6 +30,7 @@ kdev_t rq_dev; int cmd; /* READ or WRITE */ int errors; + unsigned long start_time; unsigned long sector; unsigned long nr_sectors; unsigned long hard_sector, hard_nr_sectors; diff -urN linux-2.4.19-pre5/include/linux/coda_fs_i.h linux-2.4.19-pre6/include/linux/coda_fs_i.h --- linux-2.4.19-pre5/include/linux/coda_fs_i.h Mon Feb 25 11:38:13 2002 +++ linux-2.4.19-pre6/include/linux/coda_fs_i.h Thu Apr 4 22:05:15 2002 @@ -20,12 +20,22 @@ struct ViceFid c_fid; /* Coda identifier */ u_short c_flags; /* flags (see below) */ struct list_head c_cilist; /* list of all coda inodes */ - struct file *c_container; /* container file for this cnode */ - unsigned int c_contcount; /* refcount for container file */ struct coda_cred c_cached_cred; /* credentials of cached perms */ unsigned int c_cached_perm; /* cached access permissions */ }; +/* + * coda fs file private data + */ +#define CODA_MAGIC 0xC0DAC0DA +struct coda_file_info { + int cfi_magic; /* magic number */ + struct file *cfi_container; /* container file for this cnode */ + struct coda_cred cfi_cred; /* credentials of opener */ +}; + +#define CODA_FTOC(file) ((struct coda_file_info *)((file)->private_data)) + /* flags */ #define C_VATTR 0x1 /* Validity of vattr in inode */ #define C_FLUSH 0x2 /* used after a flush */ diff -urN linux-2.4.19-pre5/include/linux/coda_linux.h linux-2.4.19-pre6/include/linux/coda_linux.h --- linux-2.4.19-pre5/include/linux/coda_linux.h Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/include/linux/coda_linux.h Thu Apr 4 22:05:15 2002 @@ -21,6 +21,7 @@ #include #include #include +#include /* operations */ extern struct inode_operations coda_dir_inode_operations; @@ -45,7 +46,6 @@ /* global variables */ extern int coda_debug; -extern int coda_print_entry; extern int coda_access_cache; extern int coda_fake_statfs; @@ -91,22 +91,19 @@ printk(format, ## a); } \ } while (0) -#define CODA_ALLOC(ptr, cast, size) \ -do { \ - if (size < PAGE_SIZE) { \ - ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL); \ - CDEBUG(D_MALLOC, "kmalloced: %lx at %p.\n", (long)size, ptr); \ - } else { \ - ptr = (cast)vmalloc((unsigned long) size); \ - CDEBUG(D_MALLOC, "vmalloced: %lx at %p .\n", (long)size, ptr);} \ - if (ptr == 0) { \ +#define CODA_ALLOC(ptr, cast, size) do { \ + if (size < PAGE_SIZE) \ + ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL); \ + else \ + ptr = (cast)vmalloc((unsigned long) size); \ + if (!ptr) \ printk("kernel malloc returns 0 at %s:%d\n", __FILE__, __LINE__); \ - } \ - else memset( ptr, 0, size ); \ + else memset( ptr, 0, size ); \ } while (0) -#define CODA_FREE(ptr,size) do {if (size < PAGE_SIZE) { kfree((ptr)); CDEBUG(D_MALLOC, "kfreed: %lx at %p.\n", (long) size, ptr); } else { vfree((ptr)); CDEBUG(D_MALLOC, "vfreed: %lx at %p.\n", (long) size, ptr);} } while (0) +#define CODA_FREE(ptr,size) \ + do { if (size < PAGE_SIZE) kfree((ptr)); else vfree((ptr)); } while (0) /* inode to cnode access functions */ diff -urN linux-2.4.19-pre5/include/linux/console.h linux-2.4.19-pre6/include/linux/console.h --- linux-2.4.19-pre5/include/linux/console.h Thu Nov 22 11:46:19 2001 +++ linux-2.4.19-pre6/include/linux/console.h Thu Apr 4 22:05:15 2002 @@ -97,7 +97,6 @@ void (*write)(struct console *, const char *, unsigned); int (*read)(struct console *, const char *, unsigned); kdev_t (*device)(struct console *); - int (*wait_key)(struct console *); void (*unblank)(void); int (*setup)(struct console *, char *); short flags; diff -urN linux-2.4.19-pre5/include/linux/devfs_fs_kernel.h linux-2.4.19-pre6/include/linux/devfs_fs_kernel.h --- linux-2.4.19-pre5/include/linux/devfs_fs_kernel.h Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/include/linux/devfs_fs_kernel.h Thu Apr 4 22:05:15 2002 @@ -54,7 +54,7 @@ unsigned char sem_initialised; unsigned int num_free; /* Num free in bits */ unsigned int length; /* Array length in bytes */ - __u32 *bits; + unsigned long *bits; struct semaphore semaphore; }; @@ -116,7 +116,6 @@ int number); extern void mount_devfs_fs (void); -extern void devfs_make_root (const char *name); #else /* CONFIG_DEVFS_FS */ @@ -312,10 +311,6 @@ { return; } -static inline void devfs_make_root (const char *name) -{ - return; -} #endif /* CONFIG_DEVFS_FS */ #endif /* _LINUX_DEVFS_FS_KERNEL_H */ diff -urN linux-2.4.19-pre5/include/linux/fb.h linux-2.4.19-pre6/include/linux/fb.h --- linux-2.4.19-pre5/include/linux/fb.h Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/include/linux/fb.h Thu Apr 4 22:05:15 2002 @@ -95,6 +95,18 @@ #define FB_ACCEL_SIS_GLAMOUR 36 /* SiS 300/630/540 */ #define FB_ACCEL_3DLABS_PERMEDIA3 37 /* 3Dlabs Permedia 3 */ + +#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 -urN linux-2.4.19-pre5/include/linux/fd.h linux-2.4.19-pre6/include/linux/fd.h --- linux-2.4.19-pre5/include/linux/fd.h Fri Aug 13 12:16:16 1999 +++ linux-2.4.19-pre6/include/linux/fd.h Thu Apr 4 22:05:15 2002 @@ -369,10 +369,4 @@ #define FDEJECT _IO(2, 0x5a) /* eject the disk */ - -#ifdef __KERNEL__ -/* eject the boot floppy (if we need the drive for a different root floppy) */ -void floppy_eject(void); -#endif - #endif diff -urN linux-2.4.19-pre5/include/linux/fs.h linux-2.4.19-pre6/include/linux/fs.h --- linux-2.4.19-pre5/include/linux/fs.h Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/include/linux/fs.h Thu Apr 4 22:05:15 2002 @@ -993,6 +993,7 @@ extern struct vfsmount *kern_mount(struct file_system_type *); extern int may_umount(struct vfsmount *); extern long do_mount(char *, char *, char *, unsigned long, void *); +extern void umount_tree(struct vfsmount *); #define kern_umount mntput diff -urN linux-2.4.19-pre5/include/linux/gameport.h linux-2.4.19-pre6/include/linux/gameport.h --- linux-2.4.19-pre5/include/linux/gameport.h Thu Nov 22 11:49:20 2001 +++ linux-2.4.19-pre6/include/linux/gameport.h Thu Apr 4 22:05:15 2002 @@ -38,6 +38,7 @@ struct gameport { void *private; + void *driver; int number; diff -urN linux-2.4.19-pre5/include/linux/genhd.h linux-2.4.19-pre6/include/linux/genhd.h --- linux-2.4.19-pre5/include/linux/genhd.h Mon Feb 25 11:38:13 2002 +++ linux-2.4.19-pre6/include/linux/genhd.h Thu Apr 4 22:05:15 2002 @@ -63,6 +63,22 @@ unsigned long nr_sects; devfs_handle_t de; /* primary (master) devfs entry */ int number; /* stupid old code wastes space */ + + /* Performance stats: */ + unsigned int ios_in_flight; + unsigned int io_ticks; + unsigned int last_idle_time; + unsigned int last_queue_change; + unsigned int aveq; + + unsigned int rd_ios; + unsigned int rd_merges; + unsigned int rd_ticks; + unsigned int rd_sectors; + unsigned int wr_ios; + unsigned int wr_merges; + unsigned int wr_ticks; + unsigned int wr_sectors; }; #define GENHD_FL_REMOVABLE 1 @@ -242,6 +258,19 @@ char *disk_name (struct gendisk *hd, int minor, char *buf); +/* + * disk_round_stats is used to round off the IO statistics for a disk + * for a complete clock tick. + */ +void disk_round_stats(struct hd_struct *hd); + +/* + * Account for the completion of an IO request (used by drivers which + * bypass the normal end_request processing) + */ +struct request; +void req_finished_io(struct request *); + extern void devfs_register_partitions (struct gendisk *dev, int minor, int unregister); diff -urN linux-2.4.19-pre5/include/linux/hiddev.h linux-2.4.19-pre6/include/linux/hiddev.h --- linux-2.4.19-pre5/include/linux/hiddev.h Wed Sep 12 15:34:06 2001 +++ linux-2.4.19-pre6/include/linux/hiddev.h Thu Apr 4 22:05:15 2002 @@ -185,7 +185,7 @@ #else static inline void *hiddev_connect(struct hid_device *hid) { return NULL; } static inline void hiddev_disconnect(struct hid_device *hid) { } -static inline void hiddev_event(struct hid_device *hid, unsigned int usage, int value) { } +static inline void hiddev_hid_event(struct hid_device *hid, unsigned int usage, int value) { } static inline int hiddev_init(void) { return 0; } static inline void hiddev_exit(void) { } #endif diff -urN linux-2.4.19-pre5/include/linux/kbd_kern.h linux-2.4.19-pre6/include/linux/kbd_kern.h --- linux-2.4.19-pre5/include/linux/kbd_kern.h Thu Nov 22 11:47:23 2001 +++ linux-2.4.19-pre6/include/linux/kbd_kern.h Thu Apr 4 22:05:15 2002 @@ -140,7 +140,6 @@ int getkeycode(unsigned int scancode); int setkeycode(unsigned int scancode, unsigned int keycode); void compute_shiftstate(void); -int keyboard_wait_for_keypress(struct console *); /* defkeymap.c */ diff -urN linux-2.4.19-pre5/include/linux/kernel.h linux-2.4.19-pre6/include/linux/kernel.h --- linux-2.4.19-pre5/include/linux/kernel.h Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/include/linux/kernel.h Thu Apr 4 22:05:15 2002 @@ -184,4 +184,6 @@ char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ }; -#endif +#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) + +#endif /* _LINUX_KERNEL_H */ diff -urN linux-2.4.19-pre5/include/linux/keyboard.h linux-2.4.19-pre6/include/linux/keyboard.h --- linux-2.4.19-pre5/include/linux/keyboard.h Thu Nov 22 11:47:07 2001 +++ linux-2.4.19-pre6/include/linux/keyboard.h Thu Apr 4 22:05:15 2002 @@ -26,7 +26,6 @@ extern const int max_vals[]; extern unsigned short *key_maps[MAX_NR_KEYMAPS]; extern unsigned short plain_map[NR_KEYS]; -extern wait_queue_head_t keypress_wait; extern unsigned char keyboard_type; #endif diff -urN linux-2.4.19-pre5/include/linux/namespace.h linux-2.4.19-pre6/include/linux/namespace.h --- linux-2.4.19-pre5/include/linux/namespace.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.19-pre6/include/linux/namespace.h Thu Apr 4 22:05:15 2002 @@ -0,0 +1,42 @@ +#ifndef _NAMESPACE_H_ +#define _NAMESPACE_H_ +#ifdef __KERNEL__ + +struct namespace { + atomic_t count; + struct vfsmount * root; + struct list_head list; + struct rw_semaphore sem; +}; + +static inline void put_namespace(struct namespace *namespace) +{ + if (atomic_dec_and_test(&namespace->count)) { + down_write(&namespace->sem); + spin_lock(&dcache_lock); + umount_tree(namespace->root); + spin_unlock(&dcache_lock); + up_write(&namespace->sem); + kfree(namespace); + } +} + +static inline void exit_namespace(struct task_struct *p) +{ + struct namespace *namespace = p->namespace; + if (namespace) { + task_lock(p); + p->namespace = NULL; + task_unlock(p); + put_namespace(namespace); + } +} +extern int copy_namespace(int, struct task_struct *); + +static inline void get_namespace(struct namespace *namespace) +{ + atomic_inc(&namespace->count); +} + +#endif +#endif diff -urN linux-2.4.19-pre5/include/linux/nfs_fs.h linux-2.4.19-pre6/include/linux/nfs_fs.h --- linux-2.4.19-pre5/include/linux/nfs_fs.h Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/include/linux/nfs_fs.h Thu Apr 4 22:05:15 2002 @@ -276,6 +276,9 @@ extern int nfs_mount(struct sockaddr_in *, char *, struct nfs_fh *); extern int nfs3_mount(struct sockaddr_in *, char *, struct nfs_fh *); +/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */ +extern u32 root_nfs_parse_addr(char *name); /*__init*/ + /* * inline functions */ diff -urN linux-2.4.19-pre5/include/linux/nfsd/export.h linux-2.4.19-pre6/include/linux/nfsd/export.h --- linux-2.4.19-pre5/include/linux/nfsd/export.h Thu Nov 22 11:47:20 2001 +++ linux-2.4.19-pre6/include/linux/nfsd/export.h Thu Apr 4 22:05:15 2002 @@ -54,11 +54,13 @@ int cl_naddr; struct in_addr cl_addr[NFSCLNT_ADDRMAX]; struct svc_uidmap * cl_umap; - struct svc_export * cl_export[NFSCLNT_EXPMAX]; + struct list_head cl_export[NFSCLNT_EXPMAX]; + struct list_head cl_list; }; struct svc_export { - struct svc_export * ex_next; + struct list_head ex_hash; + struct list_head ex_list; char ex_path[NFS_MAXPATHLEN+1]; struct svc_export * ex_parent; struct svc_client * ex_client; diff -urN linux-2.4.19-pre5/include/linux/nfsd/interface.h linux-2.4.19-pre6/include/linux/nfsd/interface.h --- linux-2.4.19-pre5/include/linux/nfsd/interface.h Wed Oct 3 22:57:36 2001 +++ linux-2.4.19-pre6/include/linux/nfsd/interface.h Thu Apr 4 22:05:15 2002 @@ -12,12 +12,15 @@ #include -#ifdef CONFIG_NFSD_MODULE +#ifndef CONFIG_NFSD +# ifdef CONFIG_MODULES extern struct nfsd_linkage { long (*do_nfsservctl)(int cmd, void *argp, void *resp); + struct module *owner; } * nfsd_linkage; +# endif #endif #endif /* LINUX_NFSD_INTERFACE_H */ diff -urN linux-2.4.19-pre5/include/linux/pci_ids.h linux-2.4.19-pre6/include/linux/pci_ids.h --- linux-2.4.19-pre5/include/linux/pci_ids.h Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/include/linux/pci_ids.h Thu Apr 4 22:05:15 2002 @@ -806,6 +806,7 @@ #define PCI_DEVICE_ID_AL_M1621 0x1621 #define PCI_DEVICE_ID_AL_M1631 0x1631 #define PCI_DEVICE_ID_AL_M1641 0x1641 +#define PCI_DEVICE_ID_AL_M1644 0x1644 #define PCI_DEVICE_ID_AL_M1647 0x1647 #define PCI_DEVICE_ID_AL_M1651 0x1651 #define PCI_DEVICE_ID_AL_M1543 0x1543 diff -urN linux-2.4.19-pre5/include/linux/sched.h linux-2.4.19-pre6/include/linux/sched.h --- linux-2.4.19-pre5/include/linux/sched.h Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/include/linux/sched.h Thu Apr 4 22:05:15 2002 @@ -42,6 +42,7 @@ #define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ #define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */ #define CLONE_THREAD 0x00010000 /* Same thread group? */ +#define CLONE_NEWNS 0x00020000 /* New namespace group? */ #define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD) @@ -166,6 +167,7 @@ */ #define NR_OPEN_DEFAULT BITS_PER_LONG +struct namespace; /* * Open file table structure */ @@ -391,6 +393,8 @@ struct fs_struct *fs; /* open file information */ struct files_struct *files; +/* namespace */ + struct namespace *namespace; /* signal handlers */ spinlock_t sigmask_lock; /* Protects signal and blocked */ struct signal_struct *sig; diff -urN linux-2.4.19-pre5/init/do_mounts.c linux-2.4.19-pre6/init/do_mounts.c --- linux-2.4.19-pre5/init/do_mounts.c Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/init/do_mounts.c Thu Apr 4 22:05:16 2002 @@ -3,13 +3,10 @@ #include #include #include -#include #include -#include -#include #include -#include #include +#include #include #include @@ -18,12 +15,9 @@ #include #include -#include - #define BUILD_CRAMDISK extern int get_filesystem_list(char * buf); -extern void wait_for_keypress(void); asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type, unsigned long flags, void *data); @@ -38,12 +32,21 @@ #ifdef CONFIG_BLK_DEV_INITRD unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ -#endif -#ifdef CONFIG_BLK_DEV_RAM -extern int rd_doload; +static int __initdata mount_initrd = 1; + +static int __init no_initrd(char *str) +{ + mount_initrd = 0; + return 1; +} + +__setup("noinitrd", no_initrd); #else -static int rd_doload = 0; +static int __initdata mount_initrd = 0; #endif + +int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */ + int root_mountflags = MS_RDONLY | MS_VERBOSE; static char root_device_name[64]; @@ -52,6 +55,13 @@ static int do_devfs = 0; +static int __init load_ramdisk(char *str) +{ + rd_doload = simple_strtol(str,NULL,0) & 3; + return 1; +} +__setup("load_ramdisk=", load_ramdisk); + static int __init readonly(char *str) { if (*str) @@ -351,29 +361,54 @@ return sys_symlink(path + n + 5, name); } -#ifdef CONFIG_MAC_FLOPPY -int swim3_fd_eject(int devnum); -#endif static void __init change_floppy(char *fmt, ...) { - extern void wait_for_keypress(void); + struct termios termios; char buf[80]; + char c; + int fd; va_list args; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); -#ifdef CONFIG_BLK_DEV_FD - floppy_eject(); -#endif -#ifdef CONFIG_MAC_FLOPPY - swim3_fd_eject(MINOR(ROOT_DEV)); -#endif + fd = open("/dev/root", O_RDWR, 0); + if (fd >= 0) { + sys_ioctl(fd, FDEJECT, 0); + close(fd); + } printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); - wait_for_keypress(); + fd = open("/dev/console", O_RDWR, 0); + if (fd >= 0) { + sys_ioctl(fd, TCGETS, (long)&termios); + termios.c_lflag &= ~ICANON; + sys_ioctl(fd, TCSETSF, (long)&termios); + read(fd, &c, 1); + termios.c_lflag |= ICANON; + sys_ioctl(fd, TCSETSF, (long)&termios); + close(fd); + } } #ifdef CONFIG_BLK_DEV_RAM +int __initdata rd_prompt = 1; /* 1 = prompt for RAM disk, 0 = don't prompt */ + +static int __init prompt_ramdisk(char *str) +{ + rd_prompt = simple_strtol(str,NULL,0) & 1; + return 1; +} +__setup("prompt_ramdisk=", prompt_ramdisk); + +int __initdata rd_image_start; /* starting block # of image */ + +static int __init ramdisk_start_setup(char *str) +{ + rd_image_start = simple_strtol(str,NULL,0); + return 1; +} +__setup("ramdisk_start=", ramdisk_start_setup); + static int __init crd_load(int in_fd, int out_fd); /* @@ -591,7 +626,6 @@ static int __init rd_load_disk(int n) { #ifdef CONFIG_BLK_DEV_RAM - extern int rd_prompt; if (rd_prompt) change_floppy("root floppy disk to be loaded into RAM disk"); create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL); @@ -599,6 +633,63 @@ return rd_load_image("/dev/root"); } +#ifdef CONFIG_DEVFS_FS + +static void __init convert_name(char *prefix, char *name, char *p, int part) +{ + int host, bus, target, lun; + char dest[64]; + char src[64]; + char *base = p - 1; + + /* Decode "c#b#t#u#" */ + if (*p++ != 'c') + return; + host = simple_strtol(p, &p, 10); + if (*p++ != 'b') + return; + bus = simple_strtol(p, &p, 10); + if (*p++ != 't') + return; + target = simple_strtol(p, &p, 10); + if (*p++ != 'u') + return; + lun = simple_strtol(p, &p, 10); + if (!part) + sprintf(dest, "%s/host%d/bus%d/target%d/lun%d", + prefix, host, bus, target, lun); + else if (*p++ == 'p') + sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/part%s", + prefix, host, bus, target, lun, p); + else + sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/disc", + prefix, host, bus, target, lun); + *base = '\0'; + sprintf(src, "/dev/%s", name); + sys_mkdir(src, 0755); + *base = '/'; + sprintf(src, "/dev/%s", name); + sys_symlink(dest, src); +} + +static void __init devfs_make_root(char *name) +{ + + if (!strncmp(name, "sd/", 3)) + convert_name("../scsi", name, name+3, 1); + else if (!strncmp(name, "sr/", 3)) + convert_name("../scsi", name, name+3, 0); + else if (!strncmp(name, "ide/hd/", 7)) + convert_name("..", name, name + 7, 1); + else if (!strncmp(name, "ide/cd/", 7)) + convert_name("..", name, name + 7, 0); +} +#else +static void __init devfs_make_root(char *name) +{ +} +#endif + static void __init mount_root(void) { #ifdef CONFIG_ROOT_NFS @@ -718,24 +809,22 @@ */ void prepare_namespace(void) { - int do_initrd = 0; int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; #ifdef CONFIG_BLK_DEV_INITRD if (!initrd_start) mount_initrd = 0; - if (mount_initrd) - do_initrd = 1; real_root_dev = ROOT_DEV; #endif sys_mkdir("/dev", 0700); sys_mkdir("/root", 0700); + sys_mknod("/dev/console", S_IFCHR|0600, MKDEV(TTYAUX_MAJOR, 1)); #ifdef CONFIG_DEVFS_FS sys_mount("devfs", "/dev", "devfs", 0, NULL); do_devfs = 1; #endif create_dev("/dev/root", ROOT_DEV, NULL); - if (do_initrd) { + if (mount_initrd) { if (initrd_load() && ROOT_DEV != MKDEV(RAMDISK_MAJOR, 0)) { handle_initrd(); goto out; diff -urN linux-2.4.19-pre5/kernel/exit.c linux-2.4.19-pre6/kernel/exit.c --- linux-2.4.19-pre5/kernel/exit.c Mon Feb 25 11:38:13 2002 +++ linux-2.4.19-pre6/kernel/exit.c Thu Apr 4 22:05:16 2002 @@ -12,6 +12,7 @@ #include #include #include +#include #ifdef CONFIG_BSD_PROCESS_ACCT #include #endif @@ -316,7 +317,7 @@ mm_release(); if (mm) { atomic_inc(&mm->mm_count); - if (mm != tsk->active_mm) BUG(); + BUG_ON(mm != tsk->active_mm); /* more a memory barrier than a real lock */ task_lock(tsk); tsk->mm = NULL; @@ -452,6 +453,7 @@ sem_exit(); __exit_files(tsk); __exit_fs(tsk); + exit_namespace(tsk); exit_sighand(tsk); exit_thread(); diff -urN linux-2.4.19-pre5/kernel/fork.c linux-2.4.19-pre6/kernel/fork.c --- linux-2.4.19-pre5/kernel/fork.c Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/kernel/fork.c Thu Apr 4 22:05:16 2002 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -251,7 +252,7 @@ */ inline void __mmdrop(struct mm_struct *mm) { - if (mm == &init_mm) BUG(); + BUG_ON(mm == &init_mm); pgd_free(mm->pgd); destroy_context(mm); free_mm(mm); @@ -569,6 +570,9 @@ struct task_struct *p; struct completion vfork; + if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) + return -EINVAL; + retval = -EPERM; /* @@ -671,9 +675,11 @@ goto bad_fork_cleanup_fs; if (copy_mm(clone_flags, p)) goto bad_fork_cleanup_sighand; + if (copy_namespace(clone_flags, p)) + goto bad_fork_cleanup_mm; retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); if (retval) - goto bad_fork_cleanup_mm; + goto bad_fork_cleanup_namespace; p->semundo = NULL; /* Our parent execution domain becomes current domain @@ -740,6 +746,8 @@ fork_out: return retval; +bad_fork_cleanup_namespace: + exit_namespace(p); bad_fork_cleanup_mm: exit_mm(p); bad_fork_cleanup_sighand: diff -urN linux-2.4.19-pre5/kernel/kmod.c linux-2.4.19-pre6/kernel/kmod.c --- linux-2.4.19-pre5/kernel/kmod.c Tue Jul 17 18:23:50 2001 +++ linux-2.4.19-pre6/kernel/kmod.c Thu Apr 4 22:05:16 2002 @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include @@ -36,6 +38,7 @@ struct fs_struct *our_fs, *init_fs; struct dentry *root, *pwd; struct vfsmount *rootmnt, *pwdmnt; + struct namespace *our_ns, *init_ns; /* * Make modprobe's fs context be a copy of init's. @@ -55,6 +58,11 @@ */ init_fs = init_task.fs; + init_ns = init_task.namespace; + get_namespace(init_ns); + our_ns = current->namespace; + current->namespace = init_ns; + put_namespace(our_ns); read_lock(&init_fs->lock); rootmnt = mntget(init_fs->rootmnt); root = dget(init_fs->root); diff -urN linux-2.4.19-pre5/kernel/sched.c linux-2.4.19-pre6/kernel/sched.c --- linux-2.4.19-pre5/kernel/sched.c Fri Dec 21 09:42:04 2001 +++ linux-2.4.19-pre6/kernel/sched.c Thu Apr 4 22:05:16 2002 @@ -556,7 +556,7 @@ spin_lock_prefetch(&runqueue_lock); - if (!current->active_mm) BUG(); + BUG_ON(!current->active_mm); need_resched_back: prev = current; this_cpu = prev->processor; @@ -675,12 +675,12 @@ struct mm_struct *mm = next->mm; struct mm_struct *oldmm = prev->active_mm; if (!mm) { - if (next->active_mm) BUG(); + BUG_ON(next->active_mm); next->active_mm = oldmm; atomic_inc(&oldmm->mm_count); enter_lazy_tlb(oldmm, next, this_cpu); } else { - if (next->active_mm != mm) BUG(); + BUG_ON(next->active_mm != mm); switch_mm(oldmm, mm, next, this_cpu); } diff -urN linux-2.4.19-pre5/mm/mmap.c linux-2.4.19-pre6/mm/mmap.c --- linux-2.4.19-pre5/mm/mmap.c Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/mm/mmap.c Thu Apr 4 22:05:16 2002 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -548,7 +549,30 @@ * Answer: Yes, several device drivers can do it in their * f_op->mmap method. -DaveM */ - addr = vma->vm_start; + if (addr != vma->vm_start) { + /* + * It is a bit too late to pretend changing the virtual + * area of the mapping, we just corrupted userspace + * in the do_munmap, so FIXME (not in 2.4 to avoid breaking + * the driver API). + */ + struct vm_area_struct * stale_vma; + /* Since addr changed, we rely on the mmap op to prevent + * collisions with existing vmas and just use find_vma_prepare + * to update the tree pointers. + */ + addr = vma->vm_start; + stale_vma = find_vma_prepare(mm, addr, &prev, + &rb_link, &rb_parent); + /* + * Make sure the lowlevel driver did its job right. + */ + if (unlikely(stale_vma && stale_vma->vm_start < vma->vm_end)) { + printk(KERN_ERR "buggy mmap operation: [<%p>]\n", + file ? file->f_op->mmap : NULL); + BUG(); + } + } vma_link(mm, vma, prev, rb_link, rb_parent); if (correct_wcount) diff -urN linux-2.4.19-pre5/mm/slab.c linux-2.4.19-pre6/mm/slab.c --- linux-2.4.19-pre5/mm/slab.c Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/mm/slab.c Thu Apr 4 22:05:16 2002 @@ -665,8 +665,7 @@ * Always checks flags, a caller might be expecting debug * support which isn't available. */ - if (flags & ~CREATE_MASK) - BUG(); + BUG_ON(flags & ~CREATE_MASK); /* Get cache's description obj. */ cachep = (kmem_cache_t *) kmem_cache_alloc(&cache_cache, SLAB_KERNEL); diff -urN linux-2.4.19-pre5/mm/vmscan.c linux-2.4.19-pre6/mm/vmscan.c --- linux-2.4.19-pre5/mm/vmscan.c Thu Apr 4 22:04:28 2002 +++ linux-2.4.19-pre6/mm/vmscan.c Thu Apr 4 22:05:16 2002 @@ -233,8 +233,7 @@ pgdir = pgd_offset(mm, address); end = vma->vm_end; - if (address >= end) - BUG(); + BUG_ON(address >= end); do { count = swap_out_pgd(mm, vma, pgdir, address, end, count, classzone); if (!count) @@ -353,10 +352,8 @@ page = list_entry(entry, struct page, lru); - if (unlikely(!PageLRU(page))) - BUG(); - if (unlikely(PageActive(page))) - BUG(); + BUG_ON(!PageLRU(page)); + BUG_ON(PageActive(page)); list_del(entry); list_add(entry, &inactive_list); diff -urN linux-2.4.19-pre5/net/ipv4/ipconfig.c linux-2.4.19-pre6/net/ipv4/ipconfig.c --- linux-2.4.19-pre5/net/ipv4/ipconfig.c Mon Feb 25 11:38:14 2002 +++ linux-2.4.19-pre6/net/ipv4/ipconfig.c Thu Apr 4 22:05:16 2002 @@ -1105,6 +1105,40 @@ #endif /* CONFIG_PROC_FS */ /* + * Extract IP address from the parameter string if needed. Note that we + * need to have root_server_addr set _before_ IPConfig gets called as it + * can override it. + */ +u32 __init root_nfs_parse_addr(char *name) +{ + u32 addr; + int octets = 0; + char *cp, *cq; + + cp = cq = name; + while (octets < 4) { + while (*cp >= '0' && *cp <= '9') + cp++; + if (cp == cq || cp - cq > 3) + break; + if (*cp == '.' || octets == 3) + octets++; + if (octets < 4) + cp++; + cq = cp; + } + if (octets == 4 && (*cp == ':' || *cp == '\0')) { + if (*cp == ':') + *cp++ = '\0'; + addr = in_aton(name); + strcpy(name, cp); + } else + addr = INADDR_NONE; + + return addr; +} + +/* * IP Autoconfig dispatcher. */ @@ -1112,6 +1146,7 @@ { int retries = CONF_OPEN_RETRIES; unsigned long jiff; + u32 addr; #ifdef CONFIG_PROC_FS proc_net_create("pnp", 0, pnp_get_info); @@ -1197,6 +1232,10 @@ ic_dev = ic_first_dev->dev; } + addr = root_nfs_parse_addr(root_server_path); + if (root_server_addr == INADDR_NONE) + root_server_addr = addr; + /* * Use defaults whereever applicable. */