diff options
139 files changed, 2425 insertions, 1234 deletions
diff --git a/Documentation/Changes b/Documentation/Changes index f8b055d21..9479dc463 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -231,25 +231,25 @@ o ftp://metalab.unc.edu/pub/gnu/gcc-2.7.2.3.tar.gz egcs 1.12 --------- -o ftp://ftp.varesearch.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-glibc.x86.tar.bz2 - <ftp://ftp.varesearch.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-glibc.x86.tar.bz2> -o ftp://ftp.varesearch.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-libc5.x86.tar.bz2 - <ftp://ftp.varesearch.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-libc5.x86.tar.bz2> -o ftp://ftp.varesearch.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-alpha.tar.bz2 - <ftp://ftp.varesearch.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-alpha.tar.bz2> +o ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-glibc.x86.tar.bz2 + <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-glibc.x86.tar.bz2> +o ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-libc5.x86.tar.bz2 + <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-libc5.x86.tar.bz2> +o ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-alpha.tar.bz2 + <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-alpha.tar.bz2> Binutils ******** 2.9.1 series ------------ -o ftp://ftp.varesearch.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.tar.gz - <ftp://ftp.varesearch.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.tar.gz> +o ftp://ftp.valinux.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.tar.gz + <ftp://ftp.valinux.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.tar.gz> 2.9.5 series ------------ -o ftp://ftp.varesearch.com/pub/support/hjl/binutils/binutils-2.9.5.0.46.tar.gz - <ftp://ftp.varesearch.com/pub/support/hjl/binutils/binutils-2.9.5.0.46.tar.bz2> +o ftp://ftp.valinux.com/pub/support/hjl/binutils/binutils-2.9.5.0.46.tar.gz + <ftp://ftp.valinux.com/pub/support/hjl/binutils/binutils-2.9.5.0.46.tar.bz2> System utilities **************** diff --git a/Documentation/Configure.help b/Documentation/Configure.help index e8430908a..fddcc41f9 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -6302,6 +6302,66 @@ CONFIG_SCSI_IZIP_SLOW_CTR Generally, saying N is fine. +Parallel port SCSI device support +CONFIG_PPSCSI + There are many external CD-ROM and disk devices that connect through + your computer's parallel port. Lots of them are actually SCSI + devices using a parallel port SCSI adapter. This option enables the + ppSCSI subsystem which contains drivers for many of these external + drives. You may also want to look at CONFIG_PARIDE (Parallel port + IDE device support). + + If you built ppSCSI support into your kernel, you may still build + the individual protocol modules and high-level drivers as loadable + modules. If you build this support as a module, it will be called + ppscsi.o. + + To use the ppSCSI support, you must say Y or M here and also to at + least one protocol driver (e.g. "Shuttle EPST adapter", "Iomega VPI0 + adapter", "Shining ScarSCI adapter" etc.). + +Adaptec APA-348 adapter +CONFIG_PPSCSI_T348 + This option enables support for the APA-348 adapter from Adaptec + (also known as Trantor T348). If you build this as a module it will + be called t348.o. + +Adaptec APA-358 adapter +CONFIG_PPSCSI_T358 + This option enables support for the APA-358 adapter from Adaptec + (also known as Trantor T358). If you build this as a module it will + be called t358.o. + +Iomega VPI0 adapter +CONFIG_PPSCSI_VPI0 + This option enables support for the Iomega VPI0 adapter found in the + original ZIP-100 drives and the Jaz Traveller. If you build this as + a module it will be called vpi0.o. + +OnSpec 90c26 adapter +CONFIG_PPSCSI_ONSCSI + This option enables support for the OnSpec 90c26 in its SCSI adapter + mode. If you build this as a module it will be called onscsi.o. + +Shining SparSCI adapter +CONFIG_PPSCSI_SPARCSI + This option enables support for the WBS-11A parallel port SCSI + adapter. This adapter has been marketed by LinkSys as the + "ParaSCSI+" and by Shining Technologies as the "SparCSI". If you + build this as a module it will be called sparcsi.o. + +Shuttle EPSA-2 adapter +CONFIG_PPSCSI_EPSA2 + This option enables support for the Shuttle Technologies EPSA2 + parallel port SCSI adapter. EPAS2 is a predecessor to the EPST. If + you build this as a module it will be called epsa2.o. + +Shuttle EPST adapter +CONFIG_PPSCSI_EPST + This option enables support for the Shuttle Technologies EPST + parallel port SCSI adapter. If you build this as a module is will + be called epst.o. + SCSI Debug host simulator. (EXPERIMENTAL) CONFIG_SCSI_DEBUG This is a host adapter simulator that can be programmed to simulate @@ -9999,7 +10059,7 @@ CONFIG_USB_SERIAL 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 usb-serial.o. If you want to compile it + The module will be called usbserial.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. USB Generic Serial Driver @@ -10015,12 +10075,22 @@ CONFIG_USB_SERIAL_WHITEHEAT Say Y here if you want to use a ConnectTech WhiteHEAT 4 port USB to serial converter device. + 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 whiteheat.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + USB Handspring Visor Driver CONFIG_USB_SERIAL_VISOR Say Y here if you want to connect to your HandSpring Visor through its USB docking station. See http://usbvisor.sourceforge.net for more information on using this driver. + 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 visor.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + USB FTDI Single Port Serial Driver CONFIG_USB_SERIAL_FTDI_SIO Say Y here if you want to use a FTDI SIO single port USB to serial @@ -10029,12 +10099,22 @@ CONFIG_USB_SERIAL_FTDI_SIO See http://reality.sgi.com/bryder_wellington/ftdi_sio for more information on this driver and the device. + 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 ftdi_sio.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + USB Keyspan PDA Single Port Serial Driver CONFIG_USB_SERIAL_KEYSPAN_PDA Say Y here if you want to use a Keyspan PDA single port USB to serial converter device. This driver makes use of firmware developed from scratch by Brian Warner. + 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 keyspan_pda.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. + USB Keyspan USA-xxx Serial Driver CONFIG_USB_SERIAL_KEYSPAN Say Y here if you want to use Keyspan USB to serial converter @@ -10045,6 +10125,11 @@ CONFIG_USB_SERIAL_KEYSPAN See http://www.linuxcare.com.au/hugh/keyspan.html for more information. + 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 keyspan.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + USB Keyspan USA-28 Firmware CONFIG_USB_SERIAL_KEYSPAN_USA28 Say Y here to include firmware for the USA-28 converter. @@ -10069,12 +10154,27 @@ USB ZyXEL omni.net LCD Plus Driver CONFIG_USB_SERIAL_OMNINET Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA. + 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 omninet.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + USB Digi International AccelePort USB Serial Driver CONFIG_USB_SERIAL_DIGI_ACCELEPORT Say Y here if you want to use a Digi AccelePort USB 4 device, a 4 port USB serial converter. The Digi Acceleport USB 2 and 8 are not yet supported by this driver. + 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 digi_acceleport.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + +USB Serial Converter verbose debug +CONFIG_USB_SERIAL_DEBUG + Say Y here if you want verbose debug messages from the USB Serial + Converter. + USB Printer support CONFIG_USB_PRINTER Say Y here if you want to connect a USB printer to your computer's @@ -10085,11 +10185,6 @@ CONFIG_USB_PRINTER The module will be called printer.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -USB Serial Converter verbose debug -CONFIG_USB_SERIAL_DEBUG - Say Y here if you want verbose debug messages from the USB Serial - Converter. - USB IBM (Xirlink) C-It Camera support CONFIG_USB_IBMCAM Say Y here if you want to connect a IBM "C-It" camera, also known as @@ -10309,6 +10404,18 @@ CONFIG_USB_MICROTEK http://fachschaft.cup.uni-muenchen.de/~neukum/scanner.html This driver can be compiled as a module. +USB Bluetooth support +CONFIG_USB_BLUETOOTH + Say Y here if you want to connect a USB Bluetooth device to your + computer's USB port. You will need the Bluetooth stack (available + at http://developer.axis.com/software/index.shtml) to fully use + the device. + + 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 bluetooth.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. + Minix fs support CONFIG_MINIX_FS Minix is a simple operating system used in many classes about OS's. @@ -12120,6 +12227,9 @@ CONFIG_I2C_PHILIPSPAR it as a module, say M here and read Documentation/modules.txt. The module will be called i2c-philips-par.o. + Note that if you want support for different parallel port devices, + life will be much easier if you compile them all as modules. + ELV adapter CONFIG_I2C_ELV This supports parallel-port I2C adapters called ELV. Say Y if you diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index b487825c7..06a613ed1 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -11,7 +11,7 @@ JPG-parportbook := $(patsubst %.fig, %.jpeg, $(IMG-parportbook)) $(BOOKS): $(TOPDIR)/scripts/docproc -.PHONY: books ps pdf html clean mrproper db2ps db2pdf db2html +.PHONY: books ps pdf html clean mrproper books: $(BOOKS) @@ -21,11 +21,6 @@ pdf: $(PDF) html: $(HTML) -db2ps db2pdf db2html: - @(which $@ > /dev/null 2>&1) || \ - (echo "*** You need to install DocBook stylesheets ***"; \ - exit 1) - %.eps: %.fig -fig2dev -Leps $< $@ @@ -88,8 +83,7 @@ kernel-api.sgml: kernel-api.tmpl $(APISOURCES) parportbook: $(JPG-parportbook) parportbook.ps: $(EPS-parportbook) parportbook.sgml: parportbook.tmpl $(TOPDIR)/drivers/parport/init.c - $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/parport/init.c \ - <parportbook.tmpl >parportbook.sgml + $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/parport/init.c <$< >$@ DVI := $(patsubst %.sgml, %.dvi, $(BOOKS)) AUX := $(patsubst %.sgml, %.aux, $(BOOKS)) @@ -106,17 +100,35 @@ clean: mrproper: clean -$(RM) $(PS) $(PDF) -$(RM) -r $(HTML) + -$(RM) .depend + -$(RM) $(TOPDIR)/scripts/mkdep-docbook -%.ps : %.sgml db2ps +%.ps : %.sgml + @(which db2ps > /dev/null 2>&1) || \ + (echo "*** You need to install DocBook stylesheets ***"; \ + exit 1) db2ps $< -%.pdf : %.sgml db2pdf +%.pdf : %.sgml + @(which db2pdf > /dev/null 2>&1) || \ + (echo "*** You need to install DocBook stylesheets ***"; \ + exit 1) db2pdf $< -%: %.sgml db2html +%: %.sgml + @(which db2html > /dev/null 2>&1) || \ + (echo "*** You need to install DocBook stylesheets ***"; \ + exit 1) -$(RM) -r $@ db2html $< if [ ! -z "$(JPG-$@)" ]; then cp $(JPG-$@) $@; fi +# +# we could have our own dependency generator +# +# +# .depend: $(TOPDIR)/scripts/mkdep-docbook +# $(TOPDIR)/scripts/mkdep-docbook $(wildcard *.tmpl) > .depend + include $(TOPDIR)/Rules.make diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index cbacdf8a7..a9328d869 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients @@ -395,7 +395,7 @@ For now, you can ignore the `flags' parameter. It is there for future use. /* Let's see whether this adapter can support what we need. Please substitute the things you need here! For `sensors' drivers, add `! is_isa &&' to the if statement */ - if (i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA | + if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_WRITE_BYTE)) goto ERROR0; diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 072508d51..86d716ed3 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -187,6 +187,8 @@ running once the system is up. ftape= [HW] Floppy Tape subsystem debugging options. + gamma= [HW,DRM] + gc= [HW,JOY] gc_2= [HW,JOY] @@ -208,6 +210,8 @@ running once the system is up. hisax= [HW,ISDN] + i810= [HW,DRM] + ibmmcascsi= [HW,MCA,SCSI] IBM MicroChannel SCSI adapter. icn= [HW,ISDN] @@ -234,6 +238,8 @@ running once the system is up. kbd-reset [VT] + keep_initrd [HW, ARM] + load_ramdisk= [RAM] List of ramdisks to load from floppy. logi_busmouse= [HW, MOUSE] @@ -291,6 +297,8 @@ running once the system is up. memfrac= [KNL] + mga= [HW,DRM] + mpu401= [HW,SOUND] msmouse= [HW,MOUSE] Microsoft Mouse. @@ -405,6 +413,10 @@ running once the system is up. quiet= [KNL] Disable log messages. + r128= [HW,DRM] + + raid= [HW,RAID] + ramdisk= [RAM] Sizes of RAM disks in kilobytes [deprecated]. ramdisk_blocksize= @@ -1,8 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 0 -#EXTRAVERSION = -test5 -EXTRAVERSION = -test5-pre4 +EXTRAVERSION = -test5-pre5 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -37,6 +36,7 @@ OBJDUMP = $(CROSS_COMPILE)objdump MAKEFILES = $(TOPDIR)/.config GENKSYMS = /sbin/genksyms MODFLAGS = -DMODULE +CFLAGS_KERNEL = PERL = perl export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \ @@ -191,7 +191,7 @@ Version: dummy @rm -f include/linux/compile.h boot: vmlinux - @$(MAKE) -C arch/$(ARCH)/boot + @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(ARCH)/boot vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \ @@ -232,7 +232,7 @@ include/config/MARKER: scripts/split-include include/linux/autoconf.h linuxsubdirs: $(patsubst %, _dir_%, $(SUBDIRS)) $(patsubst %, _dir_%, $(SUBDIRS)) : dummy include/linux/version.h include/config/MARKER - $(MAKE) -C $(patsubst _dir_%, %, $@) + $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C $(patsubst _dir_%, %, $@) $(TOPDIR)/include/linux/version.h: include/linux/version.h $(TOPDIR)/include/linux/compile.h: include/linux/compile.h @@ -269,13 +269,13 @@ include/linux/version.h: ./Makefile @mv -f .ver $@ init/version.o: init/version.c include/linux/compile.h include/config/MARKER - $(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c + $(CC) $(CFLAGS) $(CFLAGS_KERNEL) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c init/main.o: init/main.c include/config/MARKER - $(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $< + $(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $< fs lib mm ipc kernel drivers net: dummy - $(MAKE) $(subst $@, _dir_$@, $@) + $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@) TAGS: dummy etags `find include/asm-$(ARCH) -name '*.h'` diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 6f73ff9f9..d77c2efc6 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -33,8 +33,8 @@ #define TASK_ADDR_LIMIT 24 #define TASK_EXEC_DOMAIN 32 #define TASK_NEED_RESCHED 40 +#define TASK_PTRACE 48 #define TASK_PROCESSOR 100 -#define TASK_PTRACE 104 /* * task flags (must match include/linux/sched.h): diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 0600d91a9..a839790f8 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -569,43 +569,6 @@ int setup_profiling_timer(unsigned int multiplier) #undef APIC_DIVISOR -#ifdef CONFIG_SMP -static inline void handle_smp_time (int user, int cpu) -{ - int system = !user; - struct task_struct * p = current; - /* - * After doing the above, we need to make like - * a normal interrupt - otherwise timer interrupts - * ignore the global interrupt lock, which is the - * WrongThing (tm) to do. - */ - - irq_enter(cpu, 0); - update_one_process(p, 1, user, system, cpu); - if (p->pid) { - p->counter -= 1; - if (p->counter <= 0) { - p->counter = 0; - p->need_resched = 1; - } - if (p->nice > 0) { - kstat.cpu_nice += user; - kstat.per_cpu_nice[cpu] += user; - } else { - kstat.cpu_user += user; - kstat.per_cpu_user[cpu] += user; - } - kstat.cpu_system += system; - kstat.per_cpu_system[cpu] += system; - } else if (local_bh_count(cpu) || local_irq_count(cpu) > 1) { - kstat.cpu_system += system; - kstat.per_cpu_system[cpu] += system; - } - irq_exit(cpu, 0); -} -#endif - /* * Local timer interrupt handler. It does both profiling and * process statistics/rescheduling. @@ -646,7 +609,14 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs) } #ifdef CONFIG_SMP - handle_smp_time(user, cpu); + /* + * update_process_times() expects us to have done irq_enter(). + * Besides, if we don't timer interrupts ignore the global + * interrupt lock, which is the WrongThing (tm) to do. + */ + irq_enter(cpu, 0); + update_process_times(user); + irq_exit(cpu, 0); #endif } diff --git a/arch/i386/kernel/pci-i386.c b/arch/i386/kernel/pci-i386.c index 0e48d44d3..ab9cdfdf3 100644 --- a/arch/i386/kernel/pci-i386.c +++ b/arch/i386/kernel/pci-i386.c @@ -138,17 +138,9 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root, void pcibios_align_resource(void *data, struct resource *res, unsigned long size) { - struct pci_dev *dev = data; - if (res->flags & IORESOURCE_IO) { unsigned long start = res->start; - if (size > 0x100) { - printk(KERN_ERR "PCI: I/O Region %s/%d too large" - " (%ld bytes)\n", dev->slot_name, - dev->resource - res, size); - } - if (start & 0x300) { start = (start + 0x3ff) & ~0x3ff; res->start = start; diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index b11b629fe..4a118ab17 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -207,7 +207,7 @@ static inline void send_IPI_mask(int mask, int vector) * These mean you can really definitely utterly forget about * writing to user space from interrupts. (Its not allowed anyway). * - * Optimizations Manfred Spraul <manfreds@colorfullife.com> + * Optimizations Manfred Spraul <manfred@colorfullife.com> */ static volatile unsigned long flush_cpumask; @@ -216,23 +216,45 @@ static unsigned long flush_va; static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED; #define FLUSH_ALL 0xffffffff +/* + * We cannot call mmdrop() because we are in interrupt context, + * instead update mm->cpu_vm_mask. + */ static void inline leave_mm (unsigned long cpu) { if (cpu_tlbstate[cpu].state == TLBSTATE_OK) BUG(); clear_bit(cpu, &cpu_tlbstate[cpu].active_mm->cpu_vm_mask); - cpu_tlbstate[cpu].state = TLBSTATE_OLD; } /* * * The flush IPI assumes that a thread switch happens in this order: - * 1) set_bit(cpu, &new_mm->cpu_vm_mask); - * 2) update cpu_tlbstate - * [now the cpu can accept tlb flush request for the new mm] - * 3) change cr3 (if required, or flush local tlb,...) - * 4) clear_bit(cpu, &old_mm->cpu_vm_mask); - * 5) switch %%esp, ie current + * [cpu0: the cpu that switches] + * 1) switch_mm() either 1a) or 1b) + * 1a) thread switch to a different mm + * 1a1) clear_bit(cpu, &old_mm->cpu_vm_mask); + * Stop ipi delivery for the old mm. This is not synchronized with + * the other cpus, but smp_invalidate_interrupt ignore flush ipis + * for the wrong mm, and in the worst case we perform a superflous + * tlb flush. + * 1a2) set cpu_tlbstate to TLBSTATE_OK + * Now the smp_invalidate_interrupt won't call leave_mm if cpu0 + * was in lazy tlb mode. + * 1a3) update cpu_tlbstate[].active_mm + * Now cpu0 accepts tlb flushes for the new mm. + * 1a4) set_bit(cpu, &new_mm->cpu_vm_mask); + * Now the other cpus will send tlb flush ipis. + * 1a4) change cr3. + * 1b) thread switch without mm change + * cpu_tlbstate[].active_mm is correct, cpu0 already handles + * flush ipis. + * 1b1) set cpu_tlbstate to TLBSTATE_OK + * 1b2) test_and_set the cpu bit in cpu_vm_mask. + * Atomically set the bit [other cpus will start sending flush ipis], + * and test the bit. + * 1b3) if the bit was 0: leave_mm was called, flush the tlb. + * 2) switch %%esp, ie current * * The interrupt must handle 2 special cases: * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm. @@ -249,8 +271,6 @@ static void inline leave_mm (unsigned long cpu) * * 1) Flush the tlb entries if the cpu uses the mm that's being flushed. * 2) Leave the mm if we are in the lazy tlb mode. - * We cannot call mmdrop() because we are in interrupt context, - * instead update cpu_tlbstate. */ asmlinkage void smp_invalidate_interrupt (void) diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 50357e2f7..d542d1487 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -18,7 +18,8 @@ AFLAGS += -Wa,-x EXTRA = CFLAGS := $(CFLAGS) -pipe $(EXTRA) -Wa,-x -ffixed-r13 -mfixed-range=f10-f15,f32-f127 \ - -mconstant-gp -funwind-tables + -funwind-tables +CFLAGS_KERNEL := -mconstant-gp ifdef CONFIG_IA64_GENERIC CORE_FILES := arch/$(ARCH)/hp/hp.a \ diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 69988d873..be56f8570 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -38,7 +38,6 @@ #include <asm/io.h> #include <asm/smp.h> #ifdef CONFIG_SH_EARLY_PRINTK -#include <linux/console.h> #include <asm/sh_bios.h> #endif diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c index 9c6b107a6..a24b4a842 100644 --- a/arch/sh/kernel/sh_bios.c +++ b/arch/sh/kernel/sh_bios.c @@ -7,7 +7,7 @@ * */ -#include <config/sh/standard/bios.h> +#include <linux/config.h> #include <asm/sh_bios.h> #ifdef CONFIG_SH_STANDARD_BIOS diff --git a/drivers/block/Config.in b/drivers/block/Config.in index b04bd828e..4a92d53c2 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -44,7 +44,7 @@ if [ "$CONFIG_BLK_DEV_LVM" != "n" ]; then bool ' LVM information in proc filesystem' CONFIG_LVM_PROC_FS Y fi -bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD +tristate 'Multiple devices driver support' CONFIG_BLK_DEV_MD dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 30ebf11c2..af03cdf7b 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -42,13 +42,7 @@ obj-$(CONFIG_BLK_DEV_MD) += md.o obj-$(CONFIG_MD_LINEAR) += linear.o obj-$(CONFIG_MD_RAID0) += raid0.o obj-$(CONFIG_MD_RAID1) += raid1.o - -ifeq ($(CONFIG_MD_RAID5),m) - obj-y += xor.o -else - obj-$(CONFIG_MD_RAID5) += xor.o -endif -obj-$(CONFIG_MD_RAID5) += raid5.o +obj-$(CONFIG_MD_RAID5) += raid5.o xor.o obj-$(CONFIG_BLK_DEV_NBD) += nbd.o diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index ee9de09ec..3672e8976 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -1052,4 +1052,5 @@ EXPORT_SYMBOL(blk_queue_headactive); EXPORT_SYMBOL(blk_queue_pluggable); EXPORT_SYMBOL(blk_queue_make_request); EXPORT_SYMBOL(generic_make_request); +EXPORT_SYMBOL(generic_unplug_device); EXPORT_SYMBOL(blkdev_release_request); diff --git a/drivers/block/md.c b/drivers/block/md.c index 2eb6cea4b..afde399d4 100644 --- a/drivers/block/md.c +++ b/drivers/block/md.c @@ -28,6 +28,7 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/module.h> #include <linux/config.h> #include <linux/raid/md.h> #include <linux/raid/xor.h> @@ -265,6 +266,8 @@ static mddev_t * alloc_mddev (kdev_t dev) add_mddev_mapping(mddev, dev, 0); md_list_add(&mddev->all_mddevs, &all_mddevs); + MOD_INC_USE_COUNT; + return mddev; } @@ -807,6 +810,7 @@ static void free_mddev (mddev_t *mddev) MD_INIT_LIST_HEAD(&mddev->all_mddevs); blk_cleanup_queue(&mddev->queue); kfree(mddev); + MOD_DEC_USE_COUNT; } #undef BAD_CSUM @@ -2895,7 +2899,7 @@ int md_thread(void * arg) /* * Detach thread */ - sys_setsid(); + daemonize(); sprintf(current->comm, thread->name); md_init_signals(); md_flush_signals(); @@ -3582,7 +3586,7 @@ struct notifier_block md_notifier = { NULL, 0 }; - +#ifndef MODULE static int md__init raid_setup(char *str) { int len, pos; @@ -3605,7 +3609,7 @@ static int md__init raid_setup(char *str) return 1; } __setup("raid=", raid_setup); - +#endif static void md_geninit (void) { int i; @@ -3679,12 +3683,6 @@ int md__init md_init (void) #ifdef CONFIG_MD_RAID5 raid5_init (); #endif -#if defined(CONFIG_MD_RAID5) || defined(CONFIG_MD_RAID5_MODULE) - /* - * pick a XOR routine, runtime. - */ - calibrate_xor_block(); -#endif md_geninit(); return (0); } @@ -3855,6 +3853,54 @@ void md__init md_setup_drive(void) __setup("md=", md_setup); #endif +#ifdef MODULE +int init_module (void) +{ + return md_init(); +} + +static void free_device_names(void) +{ + while (device_names.next != &device_names) { + struct list_head *tmp = device_names.next; + list_del(tmp); + kfree(tmp); + } +} + + +void cleanup_module (void) +{ + struct gendisk **gendisk_ptr; + + md_unregister_thread(md_recovery_thread); + devfs_unregister(devfs_handle); + + devfs_unregister_blkdev(MAJOR_NR,"md"); + unregister_reboot_notifier(&md_notifier); + unregister_sysctl_table(raid_table_header); +#ifdef CONFIG_PROC_FS + remove_proc_entry("mdstat", NULL); +#endif + + gendisk_ptr = &gendisk_head; + while (*gendisk_ptr) { + if (*gendisk_ptr == &md_gendisk) { + *gendisk_ptr = md_gendisk.next; + break; + } + gendisk_ptr = & (*gendisk_ptr)->next; + } + blk_dev[MAJOR_NR].queue = NULL; + blksize_size[MAJOR_NR] = NULL; + blk_size[MAJOR_NR] = NULL; + max_readahead[MAJOR_NR] = NULL; + hardsect_size[MAJOR_NR] = NULL; + + free_device_names(); + +} +#endif MD_EXPORT_SYMBOL(md_size); MD_EXPORT_SYMBOL(register_md_personality); diff --git a/drivers/block/raid0.c b/drivers/block/raid0.c index f37d8e5fb..48055ecea 100644 --- a/drivers/block/raid0.c +++ b/drivers/block/raid0.c @@ -258,7 +258,7 @@ static int raid0_make_request (request_queue_t *q, mddev_t *mddev, sect_in_chunk = bh->b_rsector & ((chunk_size<<1) -1); chunk = (block - zone->zone_offset) / (zone->nb_dev << chunksize_bits); tmp_dev = zone->dev[(block >> chunksize_bits) % zone->nb_dev]; - rsect = ((chunk << chunksize_bits) + zone->dev_offset)<<1 + rsect = (((chunk << chunksize_bits) + zone->dev_offset)<<1) + sect_in_chunk; /* diff --git a/drivers/block/raid1.c b/drivers/block/raid1.c index 608bc4c43..c8b2ce456 100644 --- a/drivers/block/raid1.c +++ b/drivers/block/raid1.c @@ -379,7 +379,7 @@ static void raid1_end_bh_io (struct raid1_bh *r1_bh, int uptodate) } void raid1_end_request (struct buffer_head *bh, int uptodate) { - struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); + struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_private); /* * this branch is our 'one mirror IO has finished' event handler: @@ -626,7 +626,7 @@ static int raid1_make_request (request_queue_t *q, mddev_t *mddev, int rw, bh_req->b_rdev = mirror->dev; /* bh_req->b_rsector = bh->n_rsector; */ bh_req->b_end_io = raid1_end_request; - bh_req->b_dev_id = r1_bh; + bh_req->b_private = r1_bh; q = blk_get_queue(bh_req->b_rdev); generic_make_request (q, rw, bh_req); return 0; @@ -679,7 +679,7 @@ static int raid1_make_request (request_queue_t *q, mddev_t *mddev, int rw, mbh->b_data = bh->b_data; mbh->b_list = BUF_LOCKED; mbh->b_end_io = raid1_end_request; - mbh->b_dev_id = r1_bh; + mbh->b_private = r1_bh; mbh->b_next = r1_bh->mirror_bh_list; r1_bh->mirror_bh_list = mbh; @@ -1192,7 +1192,7 @@ static void raid1d (void *data) mbh->b_data = bh->b_data; mbh->b_list = BUF_LOCKED; mbh->b_end_io = end_sync_write; - mbh->b_dev_id = r1_bh; + mbh->b_private = r1_bh; mbh->b_next = r1_bh->mirror_bh_list; r1_bh->mirror_bh_list = mbh; @@ -1430,7 +1430,7 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr) if (bh->b_data != (char *) page_address(bh->b_page)) BUG(); bh->b_end_io = end_sync_read; - bh->b_dev_id = (void *) r1_bh; + bh->b_private = r1_bh; bh->b_rsector = block_nr<<1; init_waitqueue_head(&bh->b_wait); @@ -1448,7 +1448,7 @@ nomem: static void end_sync_read(struct buffer_head *bh, int uptodate) { - struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); + struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_private); /* we have read a block, now it needs to be re-written, * or re-read if the read failed. @@ -1463,7 +1463,7 @@ static void end_sync_read(struct buffer_head *bh, int uptodate) static void end_sync_write(struct buffer_head *bh, int uptodate) { - struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); + struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_private); if (!uptodate) md_error (mddev_to_kdev(r1_bh->mddev), bh->b_dev); diff --git a/drivers/block/raid5.c b/drivers/block/raid5.c index e7e73c689..4dc2d7d40 100644 --- a/drivers/block/raid5.c +++ b/drivers/block/raid5.c @@ -597,7 +597,7 @@ static inline void raid5_mark_buffer_uptodate (struct buffer_head *bh, int uptod static void raid5_end_request (struct buffer_head * bh, int uptodate) { - struct stripe_head *sh = bh->b_dev_id; + struct stripe_head *sh = bh->b_private; raid5_conf_t *conf = sh->raid_conf; int disks = conf->raid_disks, i; unsigned long flags; @@ -2391,6 +2391,12 @@ int raid5_init (void) err = register_md_personality (RAID5, &raid5_personality); if (err) return err; + + /* + * pick a XOR routine, runtime. + */ + calibrate_xor_block(); + return 0; } diff --git a/drivers/block/xor.c b/drivers/block/xor.c index 18abb6621..362ec6f8f 100644 --- a/drivers/block/xor.c +++ b/drivers/block/xor.c @@ -1827,6 +1827,8 @@ static struct buffer_head b1, b2; void calibrate_xor_block(void) { + if (xor_block) + return; memset(&b1,0,sizeof(b1)); b2 = b1; @@ -1885,6 +1887,8 @@ void calibrate_xor_block(void) void calibrate_xor_block(void) { + if (xor_block) + return; printk(KERN_INFO "raid5: using high-speed VIS checksum routine\n"); xor_block = xor_block_VIS; } @@ -1892,3 +1896,12 @@ void calibrate_xor_block(void) #endif /* __sparc_v9__ */ MD_EXPORT_SYMBOL(xor_block); +MD_EXPORT_SYMBOL(calibrate_xor_block); + +#ifdef MODULE +int init_module(void) +{ + calibrate_xor_block(); + return 0; +} +#endif diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index 901be5593..2882ca09c 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c @@ -35,6 +35,8 @@ #include "i810_drv.h" #include <linux/interrupt.h> /* For task queue support */ +#include <linux/sched.h> +#include <linux/smp_lock.h> /* in case we don't have a 2.3.99-pre6 kernel or later: */ #ifndef VM_DONTCOPY @@ -157,15 +159,22 @@ static struct file_operations i810_buffer_fops = { int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) { drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_i810_private_t *dev_priv = dev->dev_private; - drm_buf_t *buf = dev_priv->mmap_buffer; - drm_i810_buf_priv_t *buf_priv = buf->dev_private; + drm_device_t *dev; + drm_i810_private_t *dev_priv; + drm_buf_t *buf; + drm_i810_buf_priv_t *buf_priv; + + lock_kernel(); + dev = priv->dev; + dev_priv = dev->dev_private; + buf = dev_priv->mmap_buffer; + buf_priv = buf->dev_private; vma->vm_flags |= (VM_IO | VM_DONTCOPY); vma->vm_file = filp; buf_priv->currently_mapped = I810_BUF_MAPPED; + unlock_kernel(); if (remap_page_range(vma->vm_start, VM_OFFSET(vma), diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c index d8c49a57d..f212f2bf2 100644 --- a/drivers/char/drm/i810_drv.c +++ b/drivers/char/drm/i810_drv.c @@ -35,6 +35,8 @@ #endif #include "drmP.h" #include "i810_drv.h" +#include <linux/sched.h> +#include <linux/smp_lock.h> EXPORT_SYMBOL(i810_init); @@ -484,9 +486,11 @@ int i810_open(struct inode *inode, struct file *filp) int i810_release(struct inode *inode, struct file *filp) { drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; + drm_device_t *dev; int retcode = 0; + lock_kernel(); + dev = priv->dev; DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n", current->pid, dev->device, dev->open_count); @@ -557,12 +561,14 @@ int i810_release(struct inode *inode, struct file *filp) atomic_read(&dev->ioctl_count), dev->blocked); spin_unlock(&dev->count_lock); + unlock_kernel(); return -EBUSY; } spin_unlock(&dev->count_lock); - return i810_takedown(dev); - } - spin_unlock(&dev->count_lock); + retcode = i810_takedown(dev); + } else + spin_unlock(&dev->count_lock); + unlock_kernel(); return retcode; } diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index 30c8880fb..a3072c39e 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c @@ -36,6 +36,8 @@ #endif #include "drmP.h" #include "mga_drv.h" +#include <linux/sched.h> +#include <linux/smp_lock.h> EXPORT_SYMBOL(mga_init); EXPORT_SYMBOL(mga_cleanup); @@ -498,9 +500,11 @@ int mga_open(struct inode *inode, struct file *filp) int mga_release(struct inode *inode, struct file *filp) { drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; + drm_device_t *dev; int retcode = 0; + lock_kernel(); + dev = priv->dev; DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n", current->pid, dev->device, dev->open_count); @@ -571,12 +575,14 @@ int mga_release(struct inode *inode, struct file *filp) atomic_read(&dev->ioctl_count), dev->blocked); spin_unlock(&dev->count_lock); + unlock_kernel(); return -EBUSY; } spin_unlock(&dev->count_lock); - return mga_takedown(dev); - } - spin_unlock(&dev->count_lock); + retcode = mga_takedown(dev); + } else + spin_unlock(&dev->count_lock); + unlock_kernel(); return retcode; } diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c index e78d0231f..3e3ace345 100644 --- a/drivers/char/drm/r128_drv.c +++ b/drivers/char/drm/r128_drv.c @@ -35,6 +35,8 @@ #endif #include "drmP.h" #include "r128_drv.h" +#include <linux/sched.h> +#include <linux/smp_lock.h> EXPORT_SYMBOL(r128_init); EXPORT_SYMBOL(r128_cleanup); @@ -474,9 +476,11 @@ int r128_open(struct inode *inode, struct file *filp) int r128_release(struct inode *inode, struct file *filp) { drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; + drm_device_t *dev; int retcode = 0; + lock_kernel(); + dev = priv->dev; DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_release(inode, filp))) { MOD_DEC_USE_COUNT; @@ -488,13 +492,15 @@ int r128_release(struct inode *inode, struct file *filp) atomic_read(&dev->ioctl_count), dev->blocked); spin_unlock(&dev->count_lock); + unlock_kernel(); return -EBUSY; } spin_unlock(&dev->count_lock); - return r128_takedown(dev); - } - spin_unlock(&dev->count_lock); + retcode = r128_takedown(dev); + } else + spin_unlock(&dev->count_lock); } + unlock_kernel(); return retcode; } diff --git a/drivers/char/drm/vm.c b/drivers/char/drm/vm.c index 9dfd0d2b0..8469097a7 100644 --- a/drivers/char/drm/vm.c +++ b/drivers/char/drm/vm.c @@ -31,6 +31,8 @@ #define __NO_VERSION__ #include "drmP.h" +#include <linux/sched.h> +#include <linux/smp_lock.h> struct vm_operations_struct drm_vm_ops = { nopage: drm_vm_nopage, @@ -193,15 +195,22 @@ void drm_vm_close(struct vm_area_struct *vma) int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) { drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_device_dma_t *dma = dev->dma; + drm_device_t *dev; + drm_device_dma_t *dma; unsigned long length = vma->vm_end - vma->vm_start; + lock_kernel(); + dev = priv->dev; + dma = dev->dma; DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", vma->vm_start, vma->vm_end, VM_OFFSET(vma)); /* Length must match exact page count */ - if ((length >> PAGE_SHIFT) != dma->page_count) return -EINVAL; + if ((length >> PAGE_SHIFT) != dma->page_count) { + unlock_kernel(); + return -EINVAL; + } + unlock_kernel(); vma->vm_ops = &drm_vm_dma_ops; vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 274f3a726..aee35a3eb 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -112,7 +112,7 @@ static int misc_open(struct inode * inode, struct file * file) int minor = MINOR(inode->i_rdev); struct miscdevice *c; int err = -ENODEV; - struct file_operations *old_fops; + struct file_operations *old_fops, *new_fops = NULL; down(&misc_sem); @@ -120,7 +120,9 @@ static int misc_open(struct inode * inode, struct file * file) while ((c != &misc_list) && (c->minor != minor)) c = c->next; - if (c == &misc_list) { + if (c != &misc_list) + new_fops = fops_get(c->fops); + if (!new_fops) { char modname[20]; up(&misc_sem); sprintf(modname, "char-major-%d-%d", MISC_MAJOR, minor); @@ -129,20 +131,19 @@ static int misc_open(struct inode * inode, struct file * file) c = misc_list.next; while ((c != &misc_list) && (c->minor != minor)) c = c->next; - if (c == &misc_list) + if (c == &misc_list || (new_fops = fops_get(c->fops)) == NULL) goto fail; } + err = 0; old_fops = file->f_op; - file->f_op = fops_get(c->fops); - if (file->f_op) { - err = 0; - if (file->f_op->open) - err=file->f_op->open(inode,file); - } - if (err) { - fops_put(file->f_op); - file->f_op = fops_get(old_fops); + file->f_op = new_fops; + if (file->f_op->open) { + err=file->f_op->open(inode,file); + if (err) { + fops_put(file->f_op); + file->f_op = fops_get(old_fops); + } } fops_put(old_fops); fail: diff --git a/drivers/i2c/i2c-algo-bit.c b/drivers/i2c/i2c-algo-bit.c index 7d7a3bd4e..00f39d714 100644 --- a/drivers/i2c/i2c-algo-bit.c +++ b/drivers/i2c/i2c-algo-bit.c @@ -21,7 +21,7 @@ /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even Frodo Looijaard <frodol@dds.nl> */ -/* $Id: i2c-algo-bit.c,v 1.26 2000/01/24 02:06:33 mds Exp $ */ +/* $Id: i2c-algo-bit.c,v 1.27 2000/07/09 15:16:16 frodo Exp $ */ #include <linux/kernel.h> #include <linux/module.h> @@ -594,8 +594,10 @@ int i2c_bit_add_bus(struct i2c_adapter *adap) int i2c_bit_del_bus(struct i2c_adapter *adap) { + int res; - i2c_del_adapter(adap); + if ((res = i2c_del_adapter(adap)) < 0) + return res; DEB2(printk("i2c-algo-bit.o: adapter unregistered: %s\n",adap->name)); diff --git a/drivers/i2c/i2c-algo-pcf.c b/drivers/i2c/i2c-algo-pcf.c index 3f740784e..8a4f50f44 100644 --- a/drivers/i2c/i2c-algo-pcf.c +++ b/drivers/i2c/i2c-algo-pcf.c @@ -24,7 +24,7 @@ Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey <mbailey@littlefeet-inc.com> */ -/* $Id: i2c-algo-pcf.c,v 1.21 2000/03/16 13:07:34 frodo Exp $ */ +/* $Id: i2c-algo-pcf.c,v 1.24 2000/07/09 15:16:16 frodo Exp $ */ #include <linux/kernel.h> #include <linux/module.h> @@ -572,7 +572,9 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap) int i2c_pcf_del_bus(struct i2c_adapter *adap) { - i2c_del_adapter(adap); + int res; + if ((res = i2c_del_adapter(adap)) < 0) + return res; DEB2(printk("i2c-algo-pcf.o: adapter unregistered: %s\n",adap->name)); #ifdef MODULE diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0bcb9eddc..7deb12bcb 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -20,7 +20,7 @@ /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> */ -/* $Id: i2c-core.c,v 1.52 2000/02/27 10:43:29 frodo Exp $ */ +/* $Id: i2c-core.c,v 1.56 2000/07/09 15:13:05 frodo Exp $ */ #include <linux/module.h> #include <linux/kernel.h> @@ -73,8 +73,6 @@ static int driver_count; /**** debug level */ static int i2c_debug=1; -static void i2c_dummy_adapter(struct i2c_adapter *adapter); -static void i2c_dummy_client(struct i2c_client *client); /* --------------------------------------------------- * /proc entry declarations @@ -111,8 +109,8 @@ static int i2cproc_initialized = 0; #else /* undef CONFIG_PROC_FS */ -#define i2cproc_init() -#define i2cproc_cleanup() +#define i2cproc_init() 0 +#define i2cproc_cleanup() 0 #endif /* CONFIG_PROC_FS */ @@ -129,7 +127,7 @@ static int i2cproc_initialized = 0; */ int i2c_add_adapter(struct i2c_adapter *adap) { - int i,j; + int i,j,res; ADAP_LOCK(); for (i = 0; i < I2C_ADAP_MAX; i++) @@ -139,8 +137,8 @@ int i2c_add_adapter(struct i2c_adapter *adap) printk(KERN_WARNING " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n", adap->name); - ADAP_UNLOCK(); - return -ENOMEM; + res = -ENOMEM; + goto ERROR0; } adapters[i] = adap; @@ -150,7 +148,6 @@ int i2c_add_adapter(struct i2c_adapter *adap) /* init data types */ init_MUTEX(&adap->lock); - i2c_dummy_adapter(adap); /* actually i2c_dummy->add_adapter */ #ifdef CONFIG_PROC_FS if (i2cproc_initialized) { @@ -163,12 +160,12 @@ int i2c_add_adapter(struct i2c_adapter *adap) if (! proc_entry) { printk("i2c-core.o: Could not create /proc/bus/%s\n", name); - return -ENOENT; + res = -ENOENT; + goto ERROR1; } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,48)) proc_entry->proc_fops = &i2cproc_operations; - proc_entry->owner = THIS_MODULE; #else proc_entry->ops = &i2cproc_inode_operations; #endif @@ -185,7 +182,9 @@ int i2c_add_adapter(struct i2c_adapter *adap) /* inform drivers of new adapters */ DRV_LOCK(); for (j=0;j<I2C_DRIVER_MAX;j++) - if (drivers[j]!=NULL && drivers[j]->flags&I2C_DF_NOTIFY) + if (drivers[j]!=NULL && + (drivers[j]->flags&(I2C_DF_NOTIFY|I2C_DF_DUMMY))) + /* We ignore the return code; if it fails, too bad */ drivers[j]->attach_adapter(adap); DRV_UNLOCK(); @@ -193,24 +192,68 @@ int i2c_add_adapter(struct i2c_adapter *adap) adap->name,i)); return 0; + + +ERROR1: + ADAP_LOCK(); + adapters[i] = NULL; + adap_count--; +ERROR0: + ADAP_UNLOCK(); + return res; } int i2c_del_adapter(struct i2c_adapter *adap) { - int i,j; + int i,j,res; + ADAP_LOCK(); + for (i = 0; i < I2C_ADAP_MAX; i++) if (adap == adapters[i]) break; if (I2C_ADAP_MAX == i) { - printk( " i2c-core.o: unregister_adapter adap [%s] not found.\n", + printk( "i2c-core.o: unregister_adapter adap [%s] not found.\n", adap->name); - ADAP_UNLOCK(); - return -ENODEV; + res = -ENODEV; + goto ERROR0; + } + + /* DUMMY drivers do not register their clients, so we have to + * use a trick here: we call driver->attach_adapter to + * *detach* it! Of course, each dummy driver should know about + * this or hell will break loose... + */ + DRV_LOCK(); + for (j = 0; j < I2C_DRIVER_MAX; j++) + if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY)) + if ((res = drivers[j]->attach_adapter(adap))) { + printk("i2c-core.o: can't detach adapter %s " + "while detaching driver %s: driver not " + "detached!",adap->name,drivers[j]->name); + goto ERROR1; + } + DRV_UNLOCK(); + + + /* detach any active clients. This must be done first, because + * it can fail; in which case we give upp. */ + for (j=0;j<I2C_CLIENT_MAX;j++) { + struct i2c_client *client = adap->clients[j]; + if (client!=NULL) + /* detaching devices is unconditional of the set notify + * flag, as _all_ clients that reside on the adapter + * must be deleted, as this would cause invalid states. + */ + if ((res=client->driver->detach_client(client))) { + printk("i2c-core.o: adapter %s not " + "unregisted, because client at " + "address %02x can't be detached. ", + adap->name, client->addr); + goto ERROR0; + } } - - i2c_dummy_adapter(adap); /* actually i2c_dummy->del_adapter */ #ifdef CONFIG_PROC_FS if (i2cproc_initialized) { char name[8]; @@ -219,25 +262,19 @@ int i2c_del_adapter(struct i2c_adapter *adap) } #endif /* def CONFIG_PROC_FS */ - /* detach any active clients */ - for (j=0;j<I2C_CLIENT_MAX;j++) { - struct i2c_client *client = adap->clients[j]; - if ( (client!=NULL) - /* && (client->driver->flags & I2C_DF_NOTIFY) */ ) - /* detaching devices is unconditional of the set notify - * flag, as _all_ clients that reside on the adapter - * must be deleted, as this would cause invalid states. - */ - client->driver->detach_client(client); - /* i2c_detach_client(client); --- frodo */ - } - /* all done, now unregister */ adapters[i] = NULL; adap_count--; ADAP_UNLOCK(); DEB(printk("i2c-core.o: adapter unregistered: %s\n",adap->name)); return 0; + +ERROR0: + ADAP_UNLOCK(); + return res; +ERROR1: + DRV_UNLOCK(); + return res; } @@ -249,14 +286,15 @@ int i2c_del_adapter(struct i2c_adapter *adap) int i2c_add_driver(struct i2c_driver *driver) { - int i,j; + int i; DRV_LOCK(); for (i = 0; i < I2C_DRIVER_MAX; i++) if (NULL == drivers[i]) break; if (I2C_DRIVER_MAX == i) { printk(KERN_WARNING - " i2c-core.o: register_driver(%s) - enlarge I2C_DRIVER_MAX.\n", + " i2c-core.o: register_driver(%s) " + "- enlarge I2C_DRIVER_MAX.\n", driver->name); DRV_UNLOCK(); return -ENOMEM; @@ -269,27 +307,14 @@ int i2c_add_driver(struct i2c_driver *driver) DEB(printk("i2c-core.o: driver %s registered.\n",driver->name)); - /* Notify all existing adapters and clients to dummy driver */ ADAP_LOCK(); - if (driver->flags&I2C_DF_DUMMY) { - for (i=0; i<I2C_ADAP_MAX; i++) { - if (adapters[i]) { - driver->attach_adapter(adapters[i]); - for (j=0; j<I2C_CLIENT_MAX; j++) - if (adapters[i]->clients[j]) - driver->detach_client( - adapters[i]->clients[j]); - } - } - ADAP_UNLOCK(); - return 0; - } /* now look for instances of driver on our adapters */ - if ( driver->flags&I2C_DF_NOTIFY ) { + if (driver->flags& (I2C_DF_NOTIFY|I2C_DF_DUMMY)) { for (i=0;i<I2C_ADAP_MAX;i++) if (adapters[i]!=NULL) + /* Ignore errors */ driver->attach_adapter(adapters[i]); } ADAP_UNLOCK(); @@ -298,14 +323,15 @@ int i2c_add_driver(struct i2c_driver *driver) int i2c_del_driver(struct i2c_driver *driver) { - int i,j,k; + int i,j,k,res; DRV_LOCK(); for (i = 0; i < I2C_DRIVER_MAX; i++) if (driver == drivers[i]) break; if (I2C_DRIVER_MAX == i) { - printk(KERN_WARNING " i2c-core.o: unregister_driver: [%s] not found\n", + printk(KERN_WARNING " i2c-core.o: unregister_driver: " + "[%s] not found\n", driver->name); DRV_UNLOCK(); return -ENODEV; @@ -320,19 +346,52 @@ int i2c_del_driver(struct i2c_driver *driver) * pointers. */ ADAP_LOCK(); /* should be moved inside the if statement... */ - if ((driver->flags&I2C_DF_DUMMY)==0) for (k=0;k<I2C_ADAP_MAX;k++) { struct i2c_adapter *adap = adapters[k]; if (adap == NULL) /* skip empty entries. */ continue; - DEB2(printk("i2c-core.o: examining adapter %s:\n",adap->name)); - for (j=0;j<I2C_CLIENT_MAX;j++) { - struct i2c_client *client = adap->clients[j]; - if (client != NULL && client->driver == driver) { - DEB2(printk("i2c-core.o: detaching client %s:\n", - client->name)); - /*i2c_detach_client(client);*/ - driver->detach_client(client); + DEB2(printk("i2c-core.o: examining adapter %s:\n", + adap->name)); + if (driver->flags & I2C_DF_DUMMY) { + /* DUMMY drivers do not register their clients, so we have to + * use a trick here: we call driver->attach_adapter to + * *detach* it! Of course, each dummy driver should know about + * this or hell will break loose... + */ + if ((res = driver->attach_adapter(adap))) { + printk("i2c-core.o: while unregistering " + "dummy driver %s, adapter %s could " + "not be detached properly; driver " + "not unloaded!",driver->name, + adap->name); + ADAP_UNLOCK(); + return res; + } + } else { + for (j=0;j<I2C_CLIENT_MAX;j++) { + struct i2c_client *client = adap->clients[j]; + if (client != NULL && + client->driver == driver) { + DEB2(printk("i2c-core.o: " + "detaching client %s:\n", + client->name)); + if ((res = driver-> + detach_client(client))) + { + printk("i2c-core.o: while " + "unregistering driver " + "`%s', the client at " + "address %02x of + adapter `%s' could not + be detached; driver + not unloaded!", + driver->name, + client->addr, + adap->name); + ADAP_UNLOCK(); + return res; + } + } } } } @@ -374,12 +433,18 @@ int i2c_attach_client(struct i2c_client *client) adapter->clients[i] = client; adapter->client_count++; - i2c_dummy_client(client); - if (adapter->client_register != NULL) - adapter->client_register(client); + if (adapter->client_register) + if (adapter->client_register(client)) + printk("i2c-core.o: warning: client_register seems " + "to have failed for client %02x at adapter %s\n", + client->addr,adapter->name); DEB(printk("i2c-core.o: client [%s] registered to adapter [%s](pos. %d).\n", client->name, adapter->name,i)); + + if(client->flags & I2C_CLIENT_ALLOW_USE) + client->usage_count = 0; + return 0; } @@ -387,24 +452,31 @@ int i2c_attach_client(struct i2c_client *client) int i2c_detach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - int i; + int i,res; for (i = 0; i < I2C_CLIENT_MAX; i++) if (client == adapter->clients[i]) break; if (I2C_CLIENT_MAX == i) { - printk(KERN_WARNING " i2c-core.o: unregister_client [%s] not found\n", + printk(KERN_WARNING " i2c-core.o: unregister_client " + "[%s] not found\n", client->name); return -ENODEV; } - + + if( (client->flags & I2C_CLIENT_ALLOW_USE) && + (client->usage_count>0)) + return -EBUSY; + if (adapter->client_unregister != NULL) - adapter->client_unregister(client); - /* client->driver->detach_client(client);*/ + if ((res = adapter->client_unregister(client))) { + printk("i2c-core.o: client_unregister [%s] failed, " + "client not detached",client->name); + return res; + } adapter->clients[i] = NULL; adapter->client_count--; - i2c_dummy_client(client); DEB(printk("i2c-core.o: client [%s] unregistered.\n",client->name)); return 0; @@ -422,7 +494,7 @@ void i2c_inc_use_client(struct i2c_client *client) void i2c_dec_use_client(struct i2c_client *client) { - + if (client->driver->dec_use != NULL) client->driver->dec_use(client); @@ -430,6 +502,107 @@ void i2c_dec_use_client(struct i2c_client *client) client->adapter->dec_use(client->adapter); } +struct i2c_client *i2c_get_client(int driver_id, int adapter_id, + struct i2c_client *prev) +{ + int i,j; + + /* Will iterate through the list of clients in each adapter of adapters-list + in search for a client that matches the search criteria. driver_id or + adapter_id are ignored if set to 0. If both are ignored this returns + first client found. */ + + i = j = 0; + + /* set starting point */ + if(prev) + { + if(!(prev->adapter)) + return (struct i2c_client *) -EINVAL; + + for(j=0; j < I2C_ADAP_MAX; j++) + if(prev->adapter == adapters[j]) + break; + + /* invalid starting point? */ + if (I2C_ADAP_MAX == j) { + printk(KERN_WARNING " i2c-core.o: get_client adapter for client:[%s] not found\n", + prev->name); + return (struct i2c_client *) -ENODEV; + } + + for(i=0; i < I2C_CLIENT_MAX; i++) + if(prev == adapters[j]->clients[i]) + break; + + /* invalid starting point? */ + if (I2C_CLIENT_MAX == i) { + printk(KERN_WARNING " i2c-core.o: get_client client:[%s] not found\n", + prev->name); + return (struct i2c_client *) -ENODEV; + } + + i++; /* start from one after prev */ + } + + for(; j < I2C_ADAP_MAX; j++) + { + if(!adapters[j]) + continue; + + if(adapter_id && (adapters[j]->id != adapter_id)) + continue; + + for(; i < I2C_CLIENT_MAX; i++) + { + if(!adapters[j]->clients[i]) + continue; + + if(driver_id && (adapters[j]->clients[i]->driver->id != driver_id)) + continue; + if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE) + return adapters[j]->clients[i]; + } + } + + return 0; +} + +int i2c_use_client(struct i2c_client *client) +{ + if(client->flags & I2C_CLIENT_ALLOW_USE) { + if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE) + client->usage_count++; + else { + if(client->usage_count > 0) + return -EBUSY; + else + client->usage_count++; + } + } + + i2c_inc_use_client(client); + + return 0; +} + +int i2c_release_client(struct i2c_client *client) +{ + if(client->flags & I2C_CLIENT_ALLOW_USE) { + if(client->usage_count>0) + client->usage_count--; + else + { + printk(KERN_WARNING " i2c-core.o: dec_use_client used one too many times\n"); + return -EPERM; + } + } + + i2c_dec_use_client(client); + + return 0; +} + /* ---------------------------------------------------- * The /proc functions * ---------------------------------------------------- @@ -579,28 +752,6 @@ int i2cproc_cleanup(void) #endif /* def CONFIG_PROC_FS */ -/* --------------------------------------------------- - * dummy driver notification - * --------------------------------------------------- - */ - -static void i2c_dummy_adapter(struct i2c_adapter *adap) -{ - int i; - for (i=0; i<I2C_DRIVER_MAX; i++) - if (drivers[i] && (drivers[i]->flags & I2C_DF_DUMMY)) - drivers[i]->attach_adapter(adap); -} - -static void i2c_dummy_client(struct i2c_client *client) -{ - int i; - for (i=0; i<I2C_DRIVER_MAX; i++) - if (drivers[i] && (drivers[i]->flags & I2C_DF_DUMMY)) - drivers[i]->detach_client(client); -} - - /* ---------------------------------------------------- * the functional interface to the i2c busses. * ---------------------------------------------------- @@ -1187,6 +1338,9 @@ EXPORT_SYMBOL(i2c_attach_client); EXPORT_SYMBOL(i2c_detach_client); EXPORT_SYMBOL(i2c_inc_use_client); EXPORT_SYMBOL(i2c_dec_use_client); +EXPORT_SYMBOL(i2c_get_client); +EXPORT_SYMBOL(i2c_use_client); +EXPORT_SYMBOL(i2c_release_client); EXPORT_SYMBOL(i2c_check_addr); diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 47a6292d1..cec43ae51 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -25,7 +25,7 @@ /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */ -/* $Id: i2c-dev.c,v 1.30 2000/02/28 21:35:05 frodo Exp $ */ +/* $Id: i2c-dev.c,v 1.32 2000/07/25 23:52:17 frodo Exp $ */ #include <linux/kernel.h> #include <linux/module.h> @@ -415,6 +415,7 @@ int i2cdev_attach_adapter(struct i2c_adapter *adap) i2cdev_adaps[i] = adap; printk("i2c-dev.o: Registered '%s' as minor %d\n",adap->name,i); } else { + /* This is actually a detach_adapter call! */ i2cdev_adaps[i] = NULL; #ifdef DEBUG printk("i2c-dev.o: Adapter unregistered: %s\n",adap->name); diff --git a/drivers/i2c/i2c-elektor.c b/drivers/i2c/i2c-elektor.c index 86e79f22c..9e82fbdf4 100644 --- a/drivers/i2c/i2c-elektor.c +++ b/drivers/i2c/i2c-elektor.c @@ -22,7 +22,7 @@ /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even Frodo Looijaard <frodol@dds.nl> */ -/* $Id: i2c-elektor.c,v 1.17 2000/03/16 13:07:34 frodo Exp $ */ +/* $Id: i2c-elektor.c,v 1.19 2000/07/25 23:52:17 frodo Exp $ */ #include <linux/kernel.h> #include <linux/ioport.h> diff --git a/drivers/i2c/i2c-philips-par.c b/drivers/i2c/i2c-philips-par.c index ba72ddddb..ce9d7df27 100644 --- a/drivers/i2c/i2c-philips-par.c +++ b/drivers/i2c/i2c-philips-par.c @@ -21,30 +21,34 @@ /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even Frodo Looijaard <frodol@dds.nl> */ -/* $Id: i2c-philips-par.c,v 1.16 2000/01/18 23:54:07 frodo Exp $ */ +/* $Id: i2c-philips-par.c,v 1.18 2000/07/06 19:21:49 frodo Exp $ */ #include <linux/kernel.h> #include <linux/ioport.h> #include <linux/module.h> #include <linux/init.h> -#include <asm/io.h> #include <linux/stddef.h> +#include <linux/parport.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> -#define DEFAULT_BASE 0x378 -static int base=0; +#ifndef __exit +#define __exit __init +#endif -/* Note: all we need to know is the base address of the parallel port, so - * instead of having a dedicated struct to store this value, we store this - * int in the pointer field (=bit_lp_ops.data) itself. - */ +static int type; + +struct i2c_par +{ + struct pardevice *pdev; + struct i2c_adapter adapter; + struct i2c_algo_bit_data bit_lp_data; + struct i2c_par *next; +}; + +static struct i2c_par *adapter_list; -/* Note2: as the hw that implements the i2c bus on the parallel port is - * incompatible with other epp stuff etc., we access the port exclusively - * and don't cooperate with parport functions. - */ /* ----- global defines ----------------------------------------------- */ #define DEB(x) /* should be reasonable open, close &c. */ @@ -64,12 +68,6 @@ static int base=0; #define I2C_DMASK 0x7f #define I2C_CMASK 0xf7 -/* --- Convenience defines for the parallel port: */ -#define BASE (unsigned int)(data) -#define DATA BASE /* Centronics data port */ -#define STAT (BASE+1) /* Centronics status port */ -#define CTRL (BASE+2) /* Centronics control port */ - /* ----- local functions ---------------------------------------------- */ static void bit_lp_setscl(void *data, int state) @@ -77,48 +75,59 @@ static void bit_lp_setscl(void *data, int state) /*be cautious about state of the control register - touch only the one bit needed*/ if (state) { - outb(inb(CTRL)|I2C_SCL, CTRL); + parport_write_control((struct parport *) data, + parport_read_control((struct parport *) data)|I2C_SCL); } else { - outb(inb(CTRL)&I2C_CMASK, CTRL); + parport_write_control((struct parport *) data, + parport_read_control((struct parport *) data)&I2C_CMASK); } } static void bit_lp_setsda(void *data, int state) { if (state) { - outb(I2C_DMASK , DATA); + parport_write_data((struct parport *) data, I2C_DMASK); } else { - outb(I2C_SDA , DATA); + parport_write_data((struct parport *) data, I2C_SDA); } } static int bit_lp_getscl(void *data) { - return ( 0 != ( (inb(STAT)) & I2C_SCLIN ) ); + return parport_read_status((struct parport *) data) & I2C_SCLIN; } static int bit_lp_getsda(void *data) { - return ( 0 != ( (inb(STAT)) & I2C_SDAIN ) ); + return parport_read_status((struct parport *) data) & I2C_SDAIN; } -static int bit_lp_init(void) +static void bit_lp_setscl2(void *data, int state) { - if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) { - return -ENODEV; + if (state) { + parport_write_data((struct parport *) data, + parport_read_data((struct parport *) data)|0x1); } else { - request_region(base,(base == 0x3bc)? 3 : 8, - "i2c (parallel port adapter)"); - /* reset hardware to sane state */ - bit_lp_setsda((void*)base,1); - bit_lp_setscl((void*)base,1); + parport_write_data((struct parport *) data, + parport_read_data((struct parport *) data)&0xfe); } - return 0; } -static void bit_lp_exit(void) +static void bit_lp_setsda2(void *data, int state) { - release_region( base , (base == 0x3bc)? 3 : 8 ); + if (state) { + parport_write_data((struct parport *) data, + parport_read_data((struct parport *) data)|0x2); + } else { + parport_write_data((struct parport *) data, + parport_read_data((struct parport *) data)&0xfd); + } +} + +static int bit_lp_getsda2(void *data) +{ + return (parport_read_status((struct parport *) data) & + PARPORT_STATUS_BUSY) ? 0 : 1; } static int bit_lp_reg(struct i2c_client *client) @@ -155,64 +164,144 @@ static struct i2c_algo_bit_data bit_lp_data = { 80, 80, 100, /* waits, timeout */ }; +static struct i2c_algo_bit_data bit_lp_data2 = { + NULL, + bit_lp_setsda2, + bit_lp_setscl2, + bit_lp_getsda2, + NULL, + 80, 80, 100, /* waits, timeout */ +}; + static struct i2c_adapter bit_lp_ops = { "Philips Parallel port adapter", I2C_HW_B_LP, NULL, - &bit_lp_data, + NULL, bit_lp_inc_use, bit_lp_dec_use, bit_lp_reg, + bit_lp_unreg, }; +static void i2c_parport_attach (struct parport *port) +{ + struct i2c_par *adapter = kmalloc(sizeof(struct i2c_par), + GFP_KERNEL); + if (!adapter) { + printk("i2c-philips-par: Unable to malloc.\n"); + return; + } -int __init i2c_bitlp_init(void) + printk("i2c-philips-par.o: attaching to %s\n", port->name); + + adapter->pdev = parport_register_device(port, "i2c-philips-par", + NULL, NULL, NULL, + PARPORT_FLAG_EXCL, + NULL); + if (!adapter->pdev) { + printk("i2c-philips-par: Unable to register with parport.\n"); + return; + } + + adapter->adapter = bit_lp_ops; + adapter->adapter.algo_data = &adapter->bit_lp_data; + adapter->bit_lp_data = type ? bit_lp_data2 : bit_lp_data; + adapter->bit_lp_data.data = port; + + /* reset hardware to sane state */ + parport_claim_or_block(adapter->pdev); + bit_lp_setsda(port, 1); + bit_lp_setscl(port, 1); + parport_release(adapter->pdev); + + if (i2c_bit_add_bus(&adapter->adapter) < 0) + { + printk("i2c-philips-par: Unable to register with I2C.\n"); + parport_unregister_device(adapter->pdev); + kfree(adapter); + return; /* No good */ + } + + adapter->next = adapter_list; + adapter_list = adapter; +} + +static void i2c_parport_detach (struct parport *port) { - printk("i2c-philips-par.o: i2c Philips parallel port adapter module\n"); - if (base==0) { - /* probe some values */ - base=DEFAULT_BASE; - bit_lp_data.data=(void*)DEFAULT_BASE; - if (bit_lp_init()==0) { - if (i2c_bit_add_bus(&bit_lp_ops) < 0) - return -ENODEV; - } else { - return -ENODEV; - } - } else { - bit_lp_data.data=(void*)base; - if (bit_lp_init()==0) { - if (i2c_bit_add_bus(&bit_lp_ops) < 0) - return -ENODEV; - } else { - return -ENODEV; + struct i2c_par *adapter, *prev = NULL; + + for (adapter = adapter_list; adapter; adapter = adapter->next) + { + if (adapter->pdev->port == port) + { + parport_unregister_device(adapter->pdev); + i2c_bit_del_bus(&adapter->adapter); + if (prev) + prev->next = adapter->next; + else + adapter_list = adapter->next; + kfree(adapter); + return; } + prev = adapter; } - printk("i2c-philips-par.o: found device at %#x.\n",base); +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4) +static struct parport_driver i2c_driver = { + "i2c-philips-par", + i2c_parport_attach, + i2c_parport_detach, + NULL +}; +#endif + +int __init i2c_bitlp_init(void) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,4) + struct parport *port; +#endif + printk("i2c-philips-par.o: i2c Philips parallel port adapter module\n"); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4) + parport_register_driver(&i2c_driver); +#else + for (port = parport_enumerate(); port; port=port->next) + i2c_parport_attach(port); +#endif + return 0; } +void __exit i2c_bitlp_exit(void) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4) + parport_unregister_driver(&i2c_driver); +#else + struct parport *port; + for (port = parport_enumerate(); port; port=port->next) + i2c_parport_detach(port); +#endif +} + EXPORT_NO_SYMBOLS; -#ifdef MODULE MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); MODULE_DESCRIPTION("I2C-Bus adapter routines for Philips parallel port adapter"); -MODULE_PARM(base, "i"); +MODULE_PARM(type, "i"); -int init_module(void) +#ifdef MODULE +int init_module(void) { return i2c_bitlp_init(); } -void cleanup_module(void) +void cleanup_module(void) { - i2c_bit_del_bus(&bit_lp_ops); - bit_lp_exit(); + i2c_bitlp_exit(); } - #endif - - - diff --git a/drivers/isdn/avmb1/b1dma.c b/drivers/isdn/avmb1/b1dma.c index 168c7202f..42a77acf5 100644 --- a/drivers/isdn/avmb1/b1dma.c +++ b/drivers/isdn/avmb1/b1dma.c @@ -1,11 +1,14 @@ /* - * $Id: b1dma.c,v 1.5 2000/06/19 16:51:53 keil Exp $ + * $Id: b1dma.c,v 1.6 2000/06/29 13:59:06 calle Exp $ * * Common module for AVM B1 cards that support dma with AMCC * * (c) Copyright 2000 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1dma.c,v $ + * Revision 1.6 2000/06/29 13:59:06 calle + * Bugfix: reinit txdma without interrupt will confuse some AMCC chips. + * * Revision 1.5 2000/06/19 16:51:53 keil * don't free skb in irq context * @@ -41,7 +44,7 @@ #include "capicmd.h" #include "capiutil.h" -static char *revision = "$Revision: 1.5 $"; +static char *revision = "$Revision: 1.6 $"; /* ------------------------------------------------------------- */ diff --git a/drivers/isdn/avmb1/b1pci.c b/drivers/isdn/avmb1/b1pci.c index 9e230cb2e..fb7b5f755 100644 --- a/drivers/isdn/avmb1/b1pci.c +++ b/drivers/isdn/avmb1/b1pci.c @@ -1,11 +1,15 @@ /* - * $Id: b1pci.c,v 1.25 2000/05/29 12:29:18 keil Exp $ + * $Id: b1pci.c,v 1.26 2000/07/20 10:21:21 calle Exp $ * * Module for AVM B1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1pci.c,v $ + * Revision 1.26 2000/07/20 10:21:21 calle + * Bugfix: driver will not be unregistered, if not cards were detected. + * this result in an oops in kcapi.c + * * Revision 1.25 2000/05/29 12:29:18 keil * make pci_enable_dev compatible to 2.2 kernel versions * @@ -93,7 +97,7 @@ #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.25 $"; +static char *revision = "$Revision: 1.26 $"; /* ------------------------------------------------------------- */ @@ -338,10 +342,13 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p avmctrl_info *cinfo; int retval; + MOD_INC_USE_COUNT; + card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); if (!card) { printk(KERN_WARNING "%s: no memory.\n", driver->name); + MOD_DEC_USE_COUNT; return -ENOMEM; } memset(card, 0, sizeof(avmcard)); @@ -349,6 +356,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p if (!card->dma) { printk(KERN_WARNING "%s: no memory.\n", driver->name); kfree(card); + MOD_DEC_USE_COUNT; return -ENOMEM; } memset(card->dma, 0, sizeof(avmcard_dmainfo)); @@ -357,6 +365,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p printk(KERN_WARNING "%s: no memory.\n", driver->name); kfree(card->dma); kfree(card); + MOD_DEC_USE_COUNT; return -ENOMEM; } memset(cinfo, 0, sizeof(avmctrl_info)); @@ -375,6 +384,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p kfree(card->ctrlinfo); kfree(card->dma); kfree(card); + MOD_DEC_USE_COUNT; return -EBUSY; } @@ -389,6 +399,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p kfree(card->ctrlinfo); kfree(card->dma); kfree(card); + MOD_DEC_USE_COUNT; return -EIO; } @@ -401,6 +412,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p kfree(card->ctrlinfo); kfree(card->dma); kfree(card); + MOD_DEC_USE_COUNT; return -EIO; } b1dma_reset(card); @@ -417,6 +429,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p kfree(card->ctrlinfo); kfree(card->dma); kfree(card); + MOD_DEC_USE_COUNT; return -EBUSY; } @@ -429,6 +442,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p kfree(card->ctrlinfo); kfree(card->dma); kfree(card); + MOD_DEC_USE_COUNT; return -EBUSY; } card->cardnr = cinfo->capi_ctrl->cnr; @@ -440,8 +454,6 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p driver->name, card->port, card->irq, card->membase, card->revision); - MOD_INC_USE_COUNT; - return 0; } @@ -493,10 +505,6 @@ static int add_card(struct pci_dev *dev) printk(KERN_ERR "%s: failed to enable AVM-B1 V4 at i/o %#x, irq %d, mem %#x err=%d\n", driver->name, param.port, param.irq, param.membase, retval); -#ifdef MODULE - cleanup_module(); -#endif - MOD_DEC_USE_COUNT; return -EIO; } @@ -523,10 +531,6 @@ static int add_card(struct pci_dev *dev) printk(KERN_ERR "%s: failed to enable AVM-B1 at i/o %#x, irq %d, err=%d\n", driver->name, param.port, param.irq, retval); -#ifdef MODULE - cleanup_module(); -#endif - MOD_DEC_USE_COUNT; return -EIO; } printk(KERN_INFO @@ -605,8 +609,9 @@ int b1pci_init(void) while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) { retval = add_card(dev); if (retval != 0) { -#ifdef MODULE - cleanup_module(); + detach_capi_driver(driver); +#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 + detach_capi_driver(driverv4); #endif MOD_DEC_USE_COUNT; return retval; @@ -620,6 +625,10 @@ int b1pci_init(void) return 0; } printk(KERN_ERR "%s: NO B1-PCI card detected\n", driver->name); + detach_capi_driver(driver); +#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 + detach_capi_driver(driverv4); +#endif MOD_DEC_USE_COUNT; return -ESRCH; #else diff --git a/drivers/isdn/avmb1/b1pcmcia.c b/drivers/isdn/avmb1/b1pcmcia.c index 5774080fe..c3537c363 100644 --- a/drivers/isdn/avmb1/b1pcmcia.c +++ b/drivers/isdn/avmb1/b1pcmcia.c @@ -1,11 +1,15 @@ /* - * $Id: b1pcmcia.c,v 1.9 2000/04/03 13:29:24 calle Exp $ + * $Id: b1pcmcia.c,v 1.10 2000/05/06 00:52:36 kai Exp $ * * Module for AVM B1/M1/M2 PCMCIA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1pcmcia.c,v $ + * Revision 1.10 2000/05/06 00:52:36 kai + * merged changes from kernel tree + * fixed timer and net_device->name breakage + * * Revision 1.9 2000/04/03 13:29:24 calle * make Tim Waugh happy (module unload races in 2.3.99-pre3). * no real problem there, but now it is much cleaner ... @@ -79,7 +83,7 @@ #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.9 $"; +static char *revision = "$Revision: 1.10 $"; /* ------------------------------------------------------------- */ diff --git a/drivers/isdn/avmb1/c4.c b/drivers/isdn/avmb1/c4.c index 09c9bad99..64de830c2 100644 --- a/drivers/isdn/avmb1/c4.c +++ b/drivers/isdn/avmb1/c4.c @@ -1,11 +1,15 @@ /* - * $Id: c4.c,v 1.12 2000/06/19 16:51:53 keil Exp $ + * $Id: c4.c,v 1.13 2000/07/20 10:21:21 calle Exp $ * * Module for AVM C4 card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: c4.c,v $ + * Revision 1.13 2000/07/20 10:21:21 calle + * Bugfix: driver will not be unregistered, if not cards were detected. + * this result in an oops in kcapi.c + * * Revision 1.12 2000/06/19 16:51:53 keil * don't free skb in irq context * @@ -67,7 +71,7 @@ #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.12 $"; +static char *revision = "$Revision: 1.13 $"; #undef CONFIG_C4_DEBUG #undef CONFIG_C4_POLLDEBUG @@ -1357,9 +1361,7 @@ int c4_init(void) printk(KERN_ERR "%s: failed to enable AVM-C4 at i/o %#x, irq %d, mem %#x err=%d\n", driver->name, param.port, param.irq, param.membase, retval); -#ifdef MODULE - cleanup_module(); -#endif + detach_capi_driver(driver); MOD_DEC_USE_COUNT; return -EIO; } @@ -1372,9 +1374,7 @@ int c4_init(void) printk(KERN_ERR "%s: no AVM-C4 at i/o %#x, irq %d detected, mem %#x\n", driver->name, param.port, param.irq, param.membase); -#ifdef MODULE - cleanup_module(); -#endif + detach_capi_driver(driver); MOD_DEC_USE_COUNT; return retval; } @@ -1387,6 +1387,7 @@ int c4_init(void) return 0; } printk(KERN_ERR "%s: NO C4 card detected\n", driver->name); + detach_capi_driver(driver); MOD_DEC_USE_COUNT; return -ESRCH; #else diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c index 4c7e68266..a4223e878 100644 --- a/drivers/isdn/avmb1/capi.c +++ b/drivers/isdn/avmb1/capi.c @@ -1,11 +1,20 @@ /* - * $Id: capi.c,v 1.35 2000/06/19 15:11:24 keil Exp $ + * $Id: capi.c,v 1.38 2000/07/24 08:49:09 calle Exp $ * * CAPI 2.0 Interface for Linux * * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capi.c,v $ + * Revision 1.38 2000/07/24 08:49:09 calle + * - Bugfix: capiminor_del_all_ack completely wrong :-( + * + * Revision 1.37 2000/07/20 10:22:27 calle + * - Made procfs function cleaner and removed variable "begin". + * + * Revision 1.36 2000/06/29 13:59:35 calle + * - call to devfs_register was wrong + * * Revision 1.35 2000/06/19 15:11:24 keil * avoid use of freed structs * changes from 2.4.0-ac21 @@ -207,7 +216,7 @@ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ #include <linux/slab.h> -static char *revision = "$Revision: 1.35 $"; +static char *revision = "$Revision: 1.38 $"; MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)"); @@ -364,7 +373,8 @@ void capiminor_del_all_ack(struct capiminor *mp) { struct datahandle_queue **pp, *p; - for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) { + pp = &mp->ackqueue; + while (*pp) { p = *pp; *pp = (*pp)->next; kmem_cache_free(capidh_cachep, p); @@ -380,8 +390,10 @@ struct capiminor *capiminor_alloc(__u16 applid, __u32 ncci) struct capiminor *mp, **pp; unsigned int minor = 0; + MOD_INC_USE_COUNT; mp = (struct capiminor *)kmem_cache_alloc(capiminor_cachep, GFP_ATOMIC); if (!mp) { + MOD_DEC_USE_COUNT; printk(KERN_ERR "capi: can't alloc capiminor\n"); return 0; } @@ -433,6 +445,7 @@ void capiminor_free(struct capiminor *mp) kfree_skb(skb); capiminor_del_all_ack(mp); kmem_cache_free(capiminor_cachep, mp); + MOD_DEC_USE_COUNT; #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capiminor_free %d\n", GET_USE_COUNT(THIS_MODULE)); #endif @@ -1210,6 +1223,7 @@ capi_open(struct inode *inode, struct file *file) if ((file->private_data = capidev_alloc(file)) == 0) return -ENOMEM; + MOD_INC_USE_COUNT; #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capi_open %d\n", GET_USE_COUNT(THIS_MODULE)); #endif @@ -1226,6 +1240,7 @@ capi_release(struct inode *inode, struct file *file) capidev_free(cdev); file->private_data = NULL; + MOD_DEC_USE_COUNT; #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capi_release %d\n", GET_USE_COUNT(THIS_MODULE)); #endif @@ -1836,7 +1851,6 @@ static int proc_capidev_read_proc(char *page, char **start, off_t off, { struct capidev *cdev; int len = 0; - off_t begin = 0; for (cdev=capidev_openlist; cdev; cdev = cdev->next) { len += sprintf(page+len, "%d %d %lu %lu %lu %lu\n", @@ -1846,20 +1860,20 @@ static int proc_capidev_read_proc(char *page, char **start, off_t off, cdev->nrecvdatapkt, cdev->nsentctlpkt, cdev->nsentdatapkt); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; + if (len <= off) { + off -= len; len = 0; + } else { + if (len-off > count) + goto endloop; } } endloop: - if (cdev == 0) + if (len < count) *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); + if (len>count) len = count; + if (len<0) len = 0; + return len; } /* @@ -1872,7 +1886,6 @@ static int proc_capincci_read_proc(char *page, char **start, off_t off, struct capidev *cdev; struct capincci *np; int len = 0; - off_t begin = 0; for (cdev=capidev_openlist; cdev; cdev = cdev->next) { for (np=cdev->nccis; np; np = np->next) { @@ -1884,21 +1897,22 @@ static int proc_capincci_read_proc(char *page, char **start, off_t off, #else /* CONFIG_ISDN_CAPI_MIDDLEWARE */ np->minorp && np->minorp->file ? " open" : ""); #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; + if (len <= off) { + off -= len; len = 0; + } else { + if (len-off > count) + goto endloop; } } } endloop: - if (cdev == 0) + *start = page+off; + if (len < count) *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (begin-off); - return ((count < begin+len-off) ? count : begin+len-off); + if (len>count) len = count; + if (len<0) len = 0; + return len; } static struct procfsentries { @@ -2050,6 +2064,8 @@ int capi_init(void) { char *p; + MOD_INC_USE_COUNT; + if ((p = strchr(revision, ':'))) { strcpy(rev, p + 2); p = strchr(rev, '$'); @@ -2059,6 +2075,7 @@ int capi_init(void) if (devfs_register_chrdev(capi_major, "capi20", &capi_fops)) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); + MOD_DEC_USE_COUNT; return -EIO; } @@ -2066,6 +2083,7 @@ int capi_init(void) if (devfs_register_chrdev(capi_rawmajor, "capi/r%d", &capinc_raw_fops)) { devfs_unregister_chrdev(capi_major, "capi20"); printk(KERN_ERR "capi20: unable to get major %d\n", capi_rawmajor); + MOD_DEC_USE_COUNT; return -EIO; } devfs_register_series (NULL, "capi/r%u", CAPINC_NR_PORTS, @@ -2081,6 +2099,7 @@ int capi_init(void) if ((capifuncs = attach_capi_interface(&cuser)) == 0) { + MOD_DEC_USE_COUNT; devfs_unregister_chrdev(capi_major, "capi20"); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE devfs_unregister_chrdev(capi_rawmajor, "capi/r%d"); @@ -2096,6 +2115,7 @@ int capi_init(void) (void) detach_capi_interface(&cuser); devfs_unregister_chrdev(capi_major, "capi20"); devfs_unregister_chrdev(capi_rawmajor, "capi/r%d"); + MOD_DEC_USE_COUNT; return -ENOMEM; } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -2116,6 +2136,7 @@ int capi_init(void) devfs_unregister(devfs_find_handle(NULL, "capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0)); + MOD_DEC_USE_COUNT; return -ENOMEM; } @@ -2124,6 +2145,7 @@ int capi_init(void) printk(KERN_NOTICE "capi20: Rev%s: started up with major %d\n", rev, capi_major); + MOD_DEC_USE_COUNT; return 0; } diff --git a/drivers/isdn/avmb1/kcapi.c b/drivers/isdn/avmb1/kcapi.c index d8dd4f97b..fd18bf93c 100644 --- a/drivers/isdn/avmb1/kcapi.c +++ b/drivers/isdn/avmb1/kcapi.c @@ -1,11 +1,14 @@ /* - * $Id: kcapi.c,v 1.17 2000/04/21 13:00:56 calle Exp $ + * $Id: kcapi.c,v 1.18 2000/07/20 10:22:27 calle Exp $ * * Kernel CAPI 2.0 Module * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: kcapi.c,v $ + * Revision 1.18 2000/07/20 10:22:27 calle + * - Made procfs function cleaner and removed variable "begin". + * * Revision 1.17 2000/04/21 13:00:56 calle * Bugfix: driver_proc_info was also wrong. * @@ -115,7 +118,7 @@ #include <linux/b1lli.h> #endif -static char *revision = "$Revision: 1.17 $"; +static char *revision = "$Revision: 1.18 $"; /* ------------------------------------------------------------- */ @@ -263,7 +266,6 @@ static int proc_applications_read_proc(char *page, char **start, off_t off, struct capi_appl *ap; int i; int len = 0; - off_t begin = 0; for (i=0; i < CAPI_MAXAPPL; i++) { ap = &applications[i]; @@ -275,20 +277,21 @@ static int proc_applications_read_proc(char *page, char **start, off_t off, ap->rparam.datablklen, ap->nncci, skb_queue_len(&ap->recv_queue)); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; + if (len <= off) { + off -= len; len = 0; + } else { + if (len-off > count) + goto endloop; } } endloop: - if (i >= CAPI_MAXAPPL) + *start = page+off; + if (len < count) *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); + if (len>count) len = count; + if (len<0) len = 0; + return len; } /* @@ -302,7 +305,6 @@ static int proc_ncci_read_proc(char *page, char **start, off_t off, struct capi_ncci *np; int i; int len = 0; - off_t begin = 0; for (i=0; i < CAPI_MAXAPPL; i++) { ap = &applications[i]; @@ -313,21 +315,22 @@ static int proc_ncci_read_proc(char *page, char **start, off_t off, np->ncci, np->winsize, np->nmsg); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; + if (len <= off) { + off -= len; len = 0; + } else { + if (len-off > count) + goto endloop; } } } endloop: - if (i >= CAPI_MAXAPPL) + *start = page+off; + if (len < count) *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); + if (len>count) len = count; + if (len<0) len = 0; + return len; } /* @@ -339,7 +342,6 @@ static int proc_driver_read_proc(char *page, char **start, off_t off, { struct capi_driver *driver; int len = 0; - off_t begin = 0; spin_lock(&drivers_lock); for (driver = drivers; driver; driver = driver->next) { @@ -347,21 +349,22 @@ static int proc_driver_read_proc(char *page, char **start, off_t off, driver->name, driver->ncontroller, driver->revision); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; + if (len <= off) { + off -= len; len = 0; + } else { + if (len-off > count) + goto endloop; } } endloop: spin_unlock(&drivers_lock); - if (!driver) + *start = page+off; + if (len < count) *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); + if (len>count) len = count; + if (len<0) len = 0; + return len; } /* @@ -373,26 +376,26 @@ static int proc_users_read_proc(char *page, char **start, off_t off, { struct capi_interface_user *cp; int len = 0; - off_t begin = 0; spin_lock(&capi_users_lock); for (cp = capi_users; cp ; cp = cp->next) { len += sprintf(page+len, "%s\n", cp->name); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; + if (len <= off) { + off -= len; len = 0; + } else { + if (len-off > count) + goto endloop; } } endloop: spin_unlock(&capi_users_lock); - if (cp == 0) + *start = page+off; + if (len < count) *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); + if (len>count) len = count; + if (len<0) len = 0; + return len; } /* @@ -405,7 +408,6 @@ static int proc_controller_read_proc(char *page, char **start, off_t off, struct capi_ctr *cp; int i; int len = 0; - off_t begin = 0; for (i=0; i < CAPI_MAXCONTR; i++) { cp = &cards[i]; @@ -416,20 +418,21 @@ static int proc_controller_read_proc(char *page, char **start, off_t off, cp->name, cp->driver->procinfo ? cp->driver->procinfo(cp) : "" ); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; + if (len <= off) { + off -= len; len = 0; + } else { + if (len-off > count) + goto endloop; } } endloop: - if (i >= CAPI_MAXCONTR) + *start = page+off; + if (len < count) *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); + if (len>count) len = count; + if (len<0) len = 0; + return len; } /* @@ -442,7 +445,6 @@ static int proc_applstats_read_proc(char *page, char **start, off_t off, struct capi_appl *ap; int i; int len = 0; - off_t begin = 0; for (i=0; i < CAPI_MAXAPPL; i++) { ap = &applications[i]; @@ -453,20 +455,21 @@ static int proc_applstats_read_proc(char *page, char **start, off_t off, ap->nrecvdatapkt, ap->nsentctlpkt, ap->nsentdatapkt); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; + if (len <= off) { + off -= len; len = 0; + } else { + if (len-off > count) + goto endloop; } } endloop: - if (i >= CAPI_MAXAPPL) + *start = page+off; + if (len < count) *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); + if (len>count) len = count; + if (len<0) len = 0; + return len; } /* @@ -479,7 +482,6 @@ static int proc_contrstats_read_proc(char *page, char **start, off_t off, struct capi_ctr *cp; int i; int len = 0; - off_t begin = 0; for (i=0; i < CAPI_MAXCONTR; i++) { cp = &cards[i]; @@ -490,20 +492,21 @@ static int proc_contrstats_read_proc(char *page, char **start, off_t off, cp->nrecvdatapkt, cp->nsentctlpkt, cp->nsentdatapkt); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; + if (len <= off) { + off -= len; len = 0; + } else { + if (len-off > count) + goto endloop; } } endloop: - if (i >= CAPI_MAXCONTR) + *start = page+off; + if (len < count) *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); + if (len>count) len = count; + if (len<0) len = 0; + return len; } static struct procfsentries { diff --git a/drivers/isdn/avmb1/t1pci.c b/drivers/isdn/avmb1/t1pci.c index 07625bd0d..6248419be 100644 --- a/drivers/isdn/avmb1/t1pci.c +++ b/drivers/isdn/avmb1/t1pci.c @@ -1,11 +1,15 @@ /* - * $Id: t1pci.c,v 1.9 2000/05/19 15:43:22 calle Exp $ + * $Id: t1pci.c,v 1.10 2000/07/20 10:21:21 calle Exp $ * * Module for AVM T1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: t1pci.c,v $ + * Revision 1.10 2000/07/20 10:21:21 calle + * Bugfix: driver will not be unregistered, if not cards were detected. + * this result in an oops in kcapi.c + * * Revision 1.9 2000/05/19 15:43:22 calle * added calls to pci_device_start(). * @@ -62,7 +66,7 @@ #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.9 $"; +static char *revision = "$Revision: 1.10 $"; #undef CONFIG_T1PCI_DEBUG #undef CONFIG_T1PCI_POLLDEBUG @@ -322,9 +326,7 @@ int t1pci_init(void) printk(KERN_ERR "%s: failed to enable AVM-T1-PCI at i/o %#x, irq %d, mem %#x err=%d\n", driver->name, param.port, param.irq, param.membase, retval); -#ifdef MODULE - cleanup_module(); -#endif + detach_capi_driver(&t1pci_driver); MOD_DEC_USE_COUNT; return -EIO; } @@ -337,9 +339,7 @@ int t1pci_init(void) printk(KERN_ERR "%s: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n", driver->name, param.port, param.irq, param.membase); -#ifdef MODULE - cleanup_module(); -#endif + detach_capi_driver(&t1pci_driver); MOD_DEC_USE_COUNT; return retval; } @@ -352,6 +352,7 @@ int t1pci_init(void) return 0; } printk(KERN_ERR "%s: NO T1-PCI card detected\n", driver->name); + detach_capi_driver(&t1pci_driver); MOD_DEC_USE_COUNT; return -ESRCH; #else diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog index 34446db01..4c4fb9f9b 100644 --- a/drivers/parport/ChangeLog +++ b/drivers/parport/ChangeLog @@ -1,3 +1,12 @@ +2000-07-20 Eddie C. Dost <ecd@skynet.be> + + * share.c (attach_driver_chain): attach[i](port) needs to be + replaced by attach[count](port). + +2000-07-20 Eddie C. Dost <ecd@skynet.be> + + * daisy.c (add_dev): kmalloc args are in wrong order. + 2000-07-12 Tim Waugh <twaugh@redhat.com> * share.c: Documentation for parport_{get,port}_port, diff --git a/drivers/parport/share.c b/drivers/parport/share.c index c4c6a44b3..ec167ece1 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -125,7 +125,7 @@ static void attach_driver_chain(struct parport *port) spin_unlock (&driverlist_lock); for (count = 0; count < i; count++) - (*attach[i]) (port); + (*attach[count]) (port); kfree (attach); } diff --git a/drivers/pcmcia/Config.in b/drivers/pcmcia/Config.in index cc974944c..52f9a325b 100644 --- a/drivers/pcmcia/Config.in +++ b/drivers/pcmcia/Config.in @@ -8,7 +8,7 @@ mainmenu_option next_comment comment 'PCMCIA/CardBus support' dep_tristate 'CardBus support' CONFIG_PCMCIA $CONFIG_PCI -if [ "$CONFIG_CARDBUS" != "n" ]; then +if [ "$CONFIG_PCMCIA" != "n" ]; then define_bool CONFIG_CARDBUS y fi diff --git a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c index 36d0a5d6a..25d3ed11f 100644 --- a/drivers/pcmcia/yenta.c +++ b/drivers/pcmcia/yenta.c @@ -672,7 +672,7 @@ static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type) min = PCIBIOS_MIN_MEM; max = ~0U; if (type & IORESOURCE_IO) { align = 1024; - size = 256; + size = 1024; min = PCIBIOS_MIN_IO; max = 0xffff; } diff --git a/drivers/pnp/isapnp.c b/drivers/pnp/isapnp.c index 4b2aacce6..ffd440dc3 100644 --- a/drivers/pnp/isapnp.c +++ b/drivers/pnp/isapnp.c @@ -2067,10 +2067,12 @@ static void isapnp_free_card(struct pci_bus *card) static void isapnp_free_all_resources(void) { #ifdef ISAPNP_REGION_OK - release_resource(pidxr_res); + if (pidxr_res) + release_resource(pidxr_res); #endif - release_resource(pnpwrp_res); - if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) + if (pnpwrp_res) + release_resource(pnpwrp_res); + if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff && isapnp_rdp_res) release_resource(isapnp_rdp_res); #ifdef MODULE #ifdef CONFIG_PROC_FS diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index b8e134fa5..effaf3ec1 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -32,6 +32,7 @@ static int device_check(int host_no); typedef struct { struct pardevice *dev; /* Parport device entry */ int base; /* Actual port address */ + int base_hi; /* Hi Base address for ECP-ISA chipset */ int mode; /* Transfer mode */ int host; /* Host number (for proc) */ Scsi_Cmnd *cur_cmd; /* Current queued command */ @@ -46,6 +47,7 @@ typedef struct { #define IMM_EMPTY \ { dev: NULL, \ base: -1, \ + base_hi: 0, \ mode: IMM_AUTODETECT, \ host: -1, \ cur_cmd: NULL, \ @@ -63,6 +65,7 @@ static imm_struct imm_hosts[NO_HOSTS] = {IMM_EMPTY, IMM_EMPTY, IMM_EMPTY, IMM_EMPTY}; #define IMM_BASE(x) imm_hosts[(x)].base +#define IMM_BASE_HI(x) imm_hosts[(x)].base_hi int parbus_base[NO_HOSTS] = {0x03bc, 0x0378, 0x0278, 0x0000}; @@ -158,6 +161,7 @@ int imm_detect(Scsi_Host_Template * host) } } ppb = IMM_BASE(i) = imm_hosts[i].dev->port->base; + IMM_BASE_HI(i) = imm_hosts[i].dev->port->base_hi; w_ctr(ppb, 0x0c); modes = imm_hosts[i].dev->port->modes; @@ -374,6 +378,9 @@ static int imm_negotiate(imm_struct * tmp) return a; } +/* + * Clear EPP timeout bit. + */ static inline void epp_reset(unsigned short ppb) { int i; @@ -383,19 +390,23 @@ static inline void epp_reset(unsigned short ppb) w_str(ppb, i & 0xfe); } -static inline void ecp_sync(unsigned short ppb) +/* + * Wait for empty ECP fifo (if we are in ECP fifo mode only) + */ +static inline void ecp_sync(unsigned short hostno) { - int i; + int i, ppb_hi=IMM_BASE_HI(hostno); - if ((r_ecr(ppb) & 0xe0) != 0x80) - return; + if (ppb_hi == 0) return; - for (i = 0; i < 100; i++) { - if (r_ecr(ppb) & 0x01) - return; - udelay(5); + if ((r_ecr(ppb_hi) & 0xe0) == 0x60) { /* mode 011 == ECP fifo mode */ + for (i = 0; i < 100; i++) { + if (r_ecr(ppb_hi) & 0x01) + return; + udelay(5); + } + printk("imm: ECP sync failed as data still present in FIFO.\n"); } - printk("imm: ECP sync failed as data still present in FIFO.\n"); } static int imm_byte_out(unsigned short base, const char *buffer, int len) @@ -483,7 +494,7 @@ static int imm_out(int host_no, char *buffer, int len) w_ctr(ppb, 0xc); r = !(r_str(ppb) & 0x01); w_ctr(ppb, 0xc); - ecp_sync(ppb); + ecp_sync(host_no); break; case IMM_NIBBLE: @@ -545,7 +556,7 @@ static int imm_in(int host_no, char *buffer, int len) w_ctr(ppb, 0x2c); r = !(r_str(ppb) & 0x01); w_ctr(ppb, 0x2c); - ecp_sync(ppb); + ecp_sync(host_no); break; default: @@ -1235,7 +1246,7 @@ static int device_check(int host_no) return 1; } imm_disconnect(host_no); - printk("imm: Communication established with ID %i using %s\n", loop, + printk("imm: Communication established at 0x%x with ID %i using %s\n", ppb, loop, IMM_MODE_STRING[imm_hosts[host_no].mode]); imm_connect(host_no, CONNECT_EPP_MAYBE); imm_reset_pulse(IMM_BASE(host_no)); diff --git a/drivers/scsi/imm.h b/drivers/scsi/imm.h index 8221706db..0abe7a6cd 100644 --- a/drivers/scsi/imm.h +++ b/drivers/scsi/imm.h @@ -125,14 +125,15 @@ int imm_sg = SG_ALL; /* enable/disable scatter-gather. */ #define r_str(x) (unsigned char)inb((x)+1) #define r_ctr(x) (unsigned char)inb((x)+2) #define r_epp(x) (unsigned char)inb((x)+4) -#define r_fifo(x) (unsigned char)inb((x)+0x400) -#define r_ecr(x) (unsigned char)inb((x)+0x402) +#define r_fifo(x) (unsigned char)inb((x)) /* x must be base_hi */ + /* On PCI is: base+0x400 != base_hi */ +#define r_ecr(x) (unsigned char)inb((x)+2) /* x must be base_hi */ #define w_dtr(x,y) outb(y, (x)) #define w_str(x,y) outb(y, (x)+1) #define w_epp(x,y) outb(y, (x)+4) -#define w_fifo(x,y) outb(y, (x)+0x400) -#define w_ecr(x,y) outb(y, (x)+0x402) +#define w_fifo(x,y) outb(y, (x)) /* x must be base_hi */ +#define w_ecr(x,y) outb(y, (x)+0x2) /* x must be base_hi */ #ifdef CONFIG_SCSI_IZIP_SLOW_CTR #define w_ctr(x,y) outb_p(y, (x)+2) diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index d31a72d3d..54f7da01f 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -125,7 +125,7 @@ int ppa_detect(Scsi_Host_Template * host) } retry_entry: for (i = 0; pb; i++, pb = pb->next) { - int modes, ppb; + int modes, ppb, ppb_hi; ppa_hosts[i].dev = parport_register_device(pb, "ppa", NULL, ppa_wakeup, @@ -150,6 +150,7 @@ int ppa_detect(Scsi_Host_Template * host) } } ppb = PPA_BASE(i) = ppa_hosts[i].dev->port->base; + ppb_hi = ppa_hosts[i].dev->port->base_hi; w_ctr(ppb, 0x0c); modes = ppa_hosts[i].dev->port->modes; @@ -162,11 +163,11 @@ int ppa_detect(Scsi_Host_Template * host) ppa_hosts[i].mode = PPA_PS2; if (modes & PARPORT_MODE_ECP) { - w_ecr(ppb, 0x20); + w_ecr(ppb_hi, 0x20); ppa_hosts[i].mode = PPA_PS2; } if ((modes & PARPORT_MODE_EPP) && (modes & PARPORT_MODE_ECP)) - w_ecr(ppb, 0x80); + w_ecr(ppb_hi, 0x80); /* Done configuration */ ppa_pb_release(i); @@ -321,8 +322,7 @@ static unsigned char ppa_wait(int host_no) } /* - * output a string, in whatever mode is available, according to the - * PPA protocol. + * Clear EPP Timeout Bit */ static inline void epp_reset(unsigned short ppb) { @@ -333,19 +333,23 @@ static inline void epp_reset(unsigned short ppb) w_str(ppb, i & 0xfe); } -static inline void ecp_sync(unsigned short ppb) +/* + * Wait for empty ECP fifo (if we are in ECP fifo mode only) + */ +static inline void ecp_sync(unsigned short hostno) { - int i; + int i, ppb_hi=ppa_hosts[hostno].dev->port->base_hi; - if ((r_ecr(ppb) & 0xe0) != 0x80) - return; + if (ppb_hi == 0) return; - for (i = 0; i < 100; i++) { - if (r_ecr(ppb) & 0x01) - return; - udelay(5); + if ((r_ecr(ppb_hi) & 0xe0) == 0x60) { /* mode 011 == ECP fifo mode */ + for (i = 0; i < 100; i++) { + if (r_ecr(ppb_hi) & 0x01) + return; + udelay(5); + } + printk("ppa: ECP sync failed as data still present in FIFO.\n"); } - printk("ppa: ECP sync failed as data still present in FIFO.\n"); } static int ppa_byte_out(unsigned short base, const char *buffer, int len) @@ -420,7 +424,7 @@ static int ppa_out(int host_no, char *buffer, int len) w_ctr(ppb, 0xc); r = !(r_str(ppb) & 0x01); w_ctr(ppb, 0xc); - ecp_sync(ppb); + ecp_sync(host_no); break; default: @@ -473,7 +477,7 @@ static int ppa_in(int host_no, char *buffer, int len) w_ctr(ppb, 0x2c); r = !(r_str(ppb) & 0x01); w_ctr(ppb, 0x2c); - ecp_sync(ppb); + ecp_sync(host_no); break; default: diff --git a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h index 9f2ebcdb9..7ab442bbb 100644 --- a/drivers/scsi/ppa.h +++ b/drivers/scsi/ppa.h @@ -123,14 +123,15 @@ int ppa_sg = SG_ALL; /* enable/disable scatter-gather. */ #define r_str(x) (unsigned char)inb((x)+1) #define r_ctr(x) (unsigned char)inb((x)+2) #define r_epp(x) (unsigned char)inb((x)+4) -#define r_fifo(x) (unsigned char)inb((x)+0x400) -#define r_ecr(x) (unsigned char)inb((x)+0x402) +#define r_fifo(x) (unsigned char)inb((x)) /* x must be base_hi */ + /* On PCI is base+0x400 != base_hi */ +#define r_ecr(x) (unsigned char)inb((x)+0x2) /* x must be base_hi */ #define w_dtr(x,y) outb(y, (x)) #define w_str(x,y) outb(y, (x)+1) #define w_epp(x,y) outb(y, (x)+4) -#define w_fifo(x,y) outb(y, (x)+0x400) -#define w_ecr(x,y) outb(y, (x)+0x402) +#define w_fifo(x,y) outb(y, (x)) /* x must be base_hi */ +#define w_ecr(x,y) outb(y, (x)+0x2)/* x must be base_hi */ #ifdef CONFIG_SCSI_IZIP_SLOW_CTR #define w_ctr(x,y) outb_p(y, (x)+2) diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c index 938b77968..aa2890f05 100644 --- a/drivers/sound/sound_core.c +++ b/drivers/sound/sound_core.c @@ -479,6 +479,7 @@ int soundcore_open(struct inode *inode, struct file *file) int chain; int unit=MINOR(inode->i_rdev); struct sound_unit *s; + struct file_operations *new_fops = NULL; chain=unit&0x0F; if(chain==4 || chain==5) /* dsp/audio/dsp16 */ @@ -490,7 +491,9 @@ int soundcore_open(struct inode *inode, struct file *file) spin_lock(&sound_loader_lock); s = __look_for_unit(chain, unit); - if (s == NULL) { + if (s) + new_fops = fops_get(s->unit_fops); + if (!new_fops) { char mod[32]; spin_unlock(&sound_loader_lock); @@ -507,8 +510,10 @@ int soundcore_open(struct inode *inode, struct file *file) request_module(mod); spin_lock(&sound_loader_lock); s = __look_for_unit(chain, unit); + if (s) + new_fops = fops_get(s->unit_fops); } - if (s) { + if (new_fops) { /* * We rely upon the fact that we can't be unloaded while the * subdriver is there, so if ->open() is successful we can @@ -518,7 +523,7 @@ int soundcore_open(struct inode *inode, struct file *file) */ int err = 0; struct file_operations *old_fops = file->f_op; - file->f_op = fops_get(s->unit_fops); + file->f_op = new_fops; spin_unlock(&sound_loader_lock); if(file->f_op->open) err = file->f_op->open(inode,file); diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c index 3fde30bfa..74abe1bf9 100644 --- a/drivers/telephony/phonedev.c +++ b/drivers/telephony/phonedev.c @@ -49,14 +49,16 @@ static int phone_open(struct inode *inode, struct file *file) unsigned int minor = MINOR(inode->i_rdev); int err = 0; struct phone_device *p; - struct file_operations *old_fops; + struct file_operations *old_fops, *new_fops = NULL; if (minor >= PHONE_NUM_DEVICES) return -ENODEV; down(&phone_lock); p = phone_device[minor]; - if (p == NULL) { + if (p) + new_fops = fops_get(p->f_op); + if (!new_fops) { char modname[32]; up(&phone_lock); @@ -64,14 +66,14 @@ static int phone_open(struct inode *inode, struct file *file) request_module(modname); down(&phone_lock); p = phone_device[minor]; - if (p == NULL) + if (p == NULL || (new_fops = fops_get(p->f_op)) == NULL) { err=-ENODEV; goto end; } } old_fops = file->f_op; - file->f_op = fops_get(p->f_op); + file->f_op = new_fops; if (p->open) err = p->open(p, file); /* Tell the device it is open */ if (err) { diff --git a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c index 9b3bc24fa..7b19729a9 100644 --- a/drivers/usb/dabusb.c +++ b/drivers/usb/dabusb.c @@ -21,7 +21,7 @@ * * * - * $Id: dabusb.c,v 1.45 2000/01/31 10:23:44 fliegl Exp $ + * $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $ * */ @@ -272,16 +272,22 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) else pipe = usb_sndbulkpipe (s->usbdev, 2); - ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 1000); + ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100); if(ret<0) { err("dabusb: usb_bulk_msg failed(%d)",ret); + + if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { + err("set_interface failed"); + return -EINVAL; + } + } if( ret == -EPIPE ) { warn("CLEAR_FEATURE request to remove STALL condition."); if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) err("request failed"); - } + } pb->size = actual_length; return ret; @@ -667,8 +673,9 @@ static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cm break; } - dabusb_bulk (s, pbulk); - ret = copy_to_user ((void *) arg, pbulk, sizeof (bulk_transfer_t)); + ret=dabusb_bulk (s, pbulk); + if(ret==0) + ret = copy_to_user ((void *) arg, pbulk, sizeof (bulk_transfer_t)); kfree (pbulk); break; @@ -799,10 +806,6 @@ int __init dabusb_init (void) { unsigned u; - /* register misc device */ - if (usb_register(&dabusb_driver)) - return -1; - /* initialize struct */ for (u = 0; u < NRDABUSB; u++) { pdabusb_t s = &dabusb[u]; @@ -817,6 +820,10 @@ int __init dabusb_init (void) INIT_LIST_HEAD (&s->rec_buff_list); } + /* register misc device */ + if (usb_register(&dabusb_driver)) + return -1; + dbg("dabusb_init: driver registered"); return 0; } diff --git a/drivers/usb/devices.c b/drivers/usb/devices.c index 86b208d84..70e0150cb 100644 --- a/drivers/usb/devices.c +++ b/drivers/usb/devices.c @@ -136,7 +136,7 @@ static const struct class_info clas_info[] = {USB_CLASS_COMM, "comm."}, {USB_CLASS_HID, "HID"}, {USB_CLASS_HUB, "hub"}, - {USB_CLASS_PHYSICAL, "phys."}, + {USB_CLASS_PHYSICAL, "PID"}, {USB_CLASS_PRINTER, "print"}, {USB_CLASS_MASS_STORAGE, "stor."}, {USB_CLASS_DATA, "data"}, diff --git a/drivers/usb/ibmcam.c b/drivers/usb/ibmcam.c index 1001362e6..d70c99ddf 100644 --- a/drivers/usb/ibmcam.c +++ b/drivers/usb/ibmcam.c @@ -3055,6 +3055,7 @@ static void usb_ibmcam_release(struct usb_ibmcam *ibmcam) if (debug > 0) printk(KERN_DEBUG "usb_ibmcam_release: Video unregistered.\n"); ibmcam->ibmcam_used = 0; + ibmcam->initialized = 0; } /* diff --git a/drivers/usb/input.c b/drivers/usb/input.c index a21df12dc..98f1a1109 100644 --- a/drivers/usb/input.c +++ b/drivers/usb/input.c @@ -360,15 +360,24 @@ void input_unregister_handler(struct input_handler *handler) static int input_open_file(struct inode *inode, struct file *file) { struct input_handler *handler = input_table[MINOR(inode->i_rdev) >> 5]; - struct file_operations *old_fops; + struct file_operations *old_fops, *new_fops = NULL; int err; - if (!handler || !handler->fops || !handler->fops->open) + /* No load-on-demand here? */ + if (!handler || !(new_fops = fops_get(handler->fops))) return -ENODEV; + /* + * That's _really_ odd. Usually NULL ->open means "nothing special", + * not "no device". Oh, well... + */ + if (!new_fops->open) { + fops_put(new_fops); + return -ENODEV; + } old_fops = file->f_op; - file->f_op = fops_get(handler->fops); - err = handler->fops->open(inode, file); + file->f_op = new_fops; + err = new_fops->open(inode, file); if (err) { fops_put(file->f_op); file->f_op = fops_get(old_fops); diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index b0a0f2459..fe63007b8 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h @@ -11,6 +11,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (07/23/2000) gkh + * Added bulk_out_endpointAddress to port structure. + * * (07/19/2000) gkh, pberger, and borchers * Modifications to allow usb-serial drivers to be modules. * @@ -51,6 +54,7 @@ struct usb_serial_port { unsigned char * bulk_out_buffer; int bulk_out_size; struct urb * write_urb; + __u8 bulk_out_endpointAddress; wait_queue_head_t write_wait; diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c index 50b85c4f2..735aecaed 100644 --- a/drivers/usb/serial/usbserial.c +++ b/drivers/usb/serial/usbserial.c @@ -1,8 +1,9 @@ /* * USB Serial Converter driver * - * Copyright (C) 1999, 2000 - * Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 1999, 2000 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2000 Peter Berger (pberger@brimson.com) + * Copyright (c) 2000 Al Borchers (borchers@steinerpoint.com) * * 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 @@ -14,6 +15,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (07/23/2000) gkh + * Added bulk_out_endpointAddress to port structure. + * * (07/19/2000) gkh, pberger, and borchers * Modifications to allow usb-serial drivers to be modules. * @@ -1075,6 +1079,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) } buffer_size = endpoint->wMaxPacketSize; port->bulk_out_size = buffer_size; + port->bulk_out_endpointAddress = endpoint->bEndpointAddress; port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL); if (!port->bulk_out_buffer) { err("Couldn't allocate bulk_out_buffer"); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index f2502fbf6..f8145c37f 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -11,6 +11,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (07/23/2000) gkh + * Added pool of write urbs to speed up transfers to the visor. + * * (07/19/2000) gkh * Added module_init and module_exit functions to handle the fact that this * driver is a loadable module now. @@ -64,11 +67,13 @@ /* function prototypes for a handspring visor */ static int visor_open (struct usb_serial_port *port, struct file *filp); static void visor_close (struct usb_serial_port *port, struct file *filp); +static int visor_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); static void visor_throttle (struct usb_serial_port *port); static void visor_unthrottle (struct usb_serial_port *port); static int visor_startup (struct usb_serial *serial); static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void visor_write_bulk_callback (struct urb *urb); /* All of the device info needed for the Handspring Visor */ static __u16 handspring_vendor_id = HANDSPRING_VENDOR_ID; @@ -91,9 +96,15 @@ struct usb_serial_device_type handspring_device = { startup: visor_startup, ioctl: visor_ioctl, set_termios: visor_set_termios, + write: visor_write, + write_bulk_callback: visor_write_bulk_callback, }; +#define NUM_URBS 24 +static struct urb *write_urb_pool[NUM_URBS]; + + /****************************************************************************** * Handspring Visor specific driver functions ******************************************************************************/ @@ -139,6 +150,93 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) } +static int visor_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +{ + struct usb_serial *serial = port->serial; + struct urb *urb = NULL; + unsigned char *buffer = NULL; + int status; + int i; + + dbg(__FUNCTION__ " - port %d", port->number); + + if (count == 0) { + dbg(__FUNCTION__ " - write request of 0 bytes"); + return 0; + } + + /* try to find a free urb in our list of them */ + for (i = 0; i < NUM_URBS; ++i) { + if (write_urb_pool[i]->status != -EINPROGRESS) { + urb = write_urb_pool[i]; + break; + } + } + if (urb == NULL) { + dbg (__FUNCTION__ " - no free urbs"); + return 0; + } + + count = (count > port->bulk_out_size) ? port->bulk_out_size : count; + +#ifdef DEBUG + printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count); + for (i = 0; i < count; ++i) { + printk ("%.2x ", buf[i]); + } + printk ("\n"); +#endif + + if (urb->transfer_buffer != NULL) + kfree(urb->transfer_buffer); + buffer = kmalloc (count, GFP_KERNEL); + if (buffer == NULL) { + err(__FUNCTION__" no more kernel memory..."); + return 0; + } + + if (from_user) { + copy_from_user(buffer, buf, count); + } + else { + memcpy (buffer, buf, count); + } + + /* build up our urb */ + FILL_BULK_URB (urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), + buffer, count, visor_write_bulk_callback, port); + urb->transfer_flags |= USB_QUEUE_BULK; + + /* send it down the pipe */ + status = usb_submit_urb(urb); + if (status) + dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + + return (count); +} + + +static void visor_write_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + + if (port_paranoia_check (port, __FUNCTION__)) + return; + + dbg(__FUNCTION__ " - port %d", port->number); + + if (urb->status) { + dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status); + return; + } + + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + + return; +} + + static void visor_throttle (struct usb_serial_port *port) { dbg(__FUNCTION__ " - port %d", port->number); @@ -299,14 +397,37 @@ static void visor_set_termios (struct usb_serial_port *port, struct termios *old int visor_init (void) { + int i; + usb_serial_register (&handspring_device); + + /* create our write urb pool */ + for (i = 0; i < NUM_URBS; ++i) { + struct urb *urb = usb_alloc_urb(0); + if (urb == NULL) { + err("No more urbs???"); + continue; + } + urb->transfer_buffer = NULL; + write_urb_pool[i] = urb; + } + return 0; } void visor_exit (void) { + int i; + usb_serial_deregister (&handspring_device); + + for (i = 0; i < NUM_URBS; ++i) { + usb_unlink_urb(write_urb_pool[i]); + if (write_urb_pool[i]->transfer_buffer) + kfree(write_urb_pool[i]->transfer_buffer); + usb_free_urb (write_urb_pool[i]); + } } diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 7ede92c88..aaf1072db 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -4,7 +4,7 @@ O_TARGET := usb-storage.o M_OBJS := usb-storage.o -O_OBJS := scsiglue.o protocol.o transport.o debug.o usb.o +O_OBJS := scsiglue.o protocol.o transport.o usb.o MOD_LIST_NAME := USB_STORAGE_MODULES CFLAGS_scsiglue.o:= -I../../scsi/ @@ -22,6 +22,10 @@ ifeq ($(CONFIG_USB_STORAGE_HP8200e),y) O_OBJS += scm.o endif +ifeq ($(CONFIG_USB_STORAGE_SDDR09),y) + O_OBJS += scm.o +endif + ifeq ($(CONFIG_USB_STORAGE_FREECOM),y) O_OBJS += freecom.o endif diff --git a/drivers/usb/storage/scm.c b/drivers/usb/storage/scm.c index 2d3ca7051..7bae5e623 100644 --- a/drivers/usb/storage/scm.c +++ b/drivers/usb/storage/scm.c @@ -1,6 +1,18 @@ /* Driver for SCM Microsystems USB-ATAPI cable * - * SCM driver v0.1 + * $Id: scm.c,v 1.4 2000/07/24 19:19:52 mdharm Exp $ + * + * SCM driver v0.2: + * + * Removed any reference to maxlen for bulk transfers. + * Changed scm_bulk_transport to allow for transfers without commands. + * Changed hp8200e transport to use the request_bufflen field in the + * SCSI command for the length of the transfer, rather than calculating + * it ourselves based on the command. + * + * SCM driver v0.1: + * + * First release - hp8200e. * * Current development and maintainance by: * (c) 2000 Robert Baruch (autophile@dol.net) @@ -143,148 +155,118 @@ static int scm_send_control(struct us_data *us, } static int scm_raw_bulk(struct us_data *us, - int pipe, int maxlen, + int direction, unsigned char *data, unsigned short len) { - int transferred = 0; int result; int act_len; - int partial_len; - unsigned char status; - - maxlen = len; - - // while (transferred < len) { - - // We want to transfer up to maxlen bytes - - partial_len = len-transferred > maxlen ? - maxlen : - len-transferred; - - result = usb_stor_bulk_msg(us, - data+transferred, - pipe, - partial_len, - &act_len); + int pipe; - /* if we stall, we need to clear it before we go on */ - if (result == -EPIPE) { - US_DEBUGP("EPIPE: clearing endpoint halt for" - " pipe 0x%x, stalled at %d bytes\n", - pipe, act_len); - usb_clear_halt(us->pusb_dev, pipe); + if (direction == SCSI_DATA_READ) + pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); + else + pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); - // What the hey is goin' on? + result = usb_stor_bulk_msg(us, data, pipe, len, &act_len); - /* US_DEBUGP("EPIPE: Trying to retransmit bulk data...\n"); + /* if we stall, we need to clear it before we go on */ + if (result == -EPIPE) { + US_DEBUGP("EPIPE: clearing endpoint halt for" + " pipe 0x%x, stalled at %d bytes\n", + pipe, act_len); + usb_clear_halt(us->pusb_dev, pipe); + } - wait_ms(10); - - result = usb_stor_bulk_msg(us, data+act_len, - pipe, len-act_len, &act_len); + if (result) { - if (result==0) - US_DEBUGP("EPIPE: Retransmit successful\n"); */ + /* NAK - that means we've retried a few times already */ + if (result == -ETIMEDOUT) { + US_DEBUGP("scm_raw_bulk():" + " device NAKed\n"); + return US_BULK_TRANSFER_FAILED; + } - wait_ms(1000); - US_DEBUGP("Trying to get status\n"); - result = scm_read(us, SCM_ATA, 0x17, &status); - US_DEBUGP("SCM: Write ATA data status is %02X\n", - status); - - result = -EPIPE; - } - - if (result) { - - /* NAK - that means we've retried a few times already */ - if (result == -ETIMEDOUT) { - US_DEBUGP("scm_raw_bulk():" - " device NAKed\n"); - return US_BULK_TRANSFER_FAILED; - } - - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { - US_DEBUGP("scm_raw_bulk():" - " transfer aborted\n"); - return US_BULK_TRANSFER_ABORTED; - } - - if (result == -EPIPE) { - US_DEBUGP("scm_raw_bulk():" - " output pipe stalled\n"); - return USB_STOR_TRANSPORT_FAILED; - } + /* -ENOENT -- we canceled this transfer */ + if (result == -ENOENT) { + US_DEBUGP("scm_raw_bulk():" + " transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } - /* the catch-all case */ - US_DEBUGP("us_transfer_partial(): unknown error\n"); - return US_BULK_TRANSFER_FAILED; - } - - if (act_len != partial_len) { - US_DEBUGP("Warning: Transferred only %d bytes\n", - act_len); - return US_BULK_TRANSFER_SHORT; + if (result == -EPIPE) { + US_DEBUGP("scm_raw_bulk():" + " output pipe stalled\n"); + return USB_STOR_TRANSPORT_FAILED; } - US_DEBUGP("Transfered %d of %d bytes\n", act_len, partial_len); + /* the catch-all case */ + US_DEBUGP("us_transfer_partial(): unknown error\n"); + return US_BULK_TRANSFER_FAILED; + } + + if (act_len != len) { + US_DEBUGP("Warning: Transferred only %d bytes\n", + act_len); + return US_BULK_TRANSFER_SHORT; + } - transferred += act_len; - // } // while transferred < len + US_DEBUGP("Transfered %d of %d bytes\n", act_len, len); return US_BULK_TRANSFER_GOOD; } +/* + * Note: direction must be set if command_len == 0. + */ + static int scm_bulk_transport(struct us_data *us, unsigned char *command, unsigned short command_len, + int direction, unsigned char *data, unsigned short len, int use_sg) { - int result; + int result = USB_STOR_TRANSPORT_GOOD; int transferred = 0; - int maxlen; unsigned char execute[8] = { 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int i; - int pipe; struct scatterlist *sg; char string[64]; - maxlen = us->pusb_dev->actconfig-> - interface[0].altsetting[0].endpoint[ - ( (command[0]&0x80) ? us->ep_in : us->ep_out)-1]. - wMaxPacketSize; + if (command_len != 0) { - /* Fix up the command's data length */ + /* Fix up the command's data length */ - command[6] = len&0xFF; - command[7] = (len>>8)&0xFF; + command[6] = len&0xFF; + command[7] = (len>>8)&0xFF; - result = scm_send_control(us, - execute, - command, - command_len); + result = scm_send_control(us, + execute, + command, + command_len); - if (result != USB_STOR_TRANSPORT_GOOD) - return result; + if (result != USB_STOR_TRANSPORT_GOOD) + return result; + } if (len==0) - return result; + return USB_STOR_TRANSPORT_GOOD; + /* transfer the data payload for the command, if there is any */ - if (command[0]&0x80) - pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); - else { - pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); - /* Debug-print the first 48 bytes of the transfer */ + if (command_len != 0) + direction = (command[0]&0x80) ? SCSI_DATA_READ : + SCSI_DATA_WRITE; + + if (direction == SCSI_DATA_WRITE) { + + /* Debug-print the first 48 bytes of the write transfer */ if (!use_sg) { string[0] = 0; @@ -302,17 +284,16 @@ static int scm_bulk_transport(struct us_data *us, } - US_DEBUGP("HP 8200e data %s maxlen %d transfer %d sg buffers %d\n", - ( (command[0]&0x80) ? "in" : "out"), - maxlen, len, use_sg); + US_DEBUGP("SCM data %s transfer %d sg buffers %d\n", + ( direction==SCSI_DATA_READ ? "in" : "out"), + len, use_sg); if (!use_sg) - result = scm_raw_bulk(us, pipe, maxlen, - data, len); + result = scm_raw_bulk(us, direction, data, len); else { sg = (struct scatterlist *)data; for (i=0; i<use_sg && transferred<len; i++) { - result = scm_raw_bulk(us, pipe, maxlen, + result = scm_raw_bulk(us, direction, sg[i].address, len-transferred > sg[i].length ? sg[i].length : len-transferred); @@ -379,7 +360,7 @@ int scm_set_shuttle_features(struct us_data *us, test_pattern, mask_byte, subcountL, subcountH }; - result = scm_bulk_transport(us, command, 8, NULL, 0, 0); + result = scm_bulk_transport(us, command, 8, 0, NULL, 0, 0); if (result != USB_STOR_TRANSPORT_GOOD) return result; @@ -400,7 +381,7 @@ int scm_read_block(struct us_data *us, }; result = scm_bulk_transport(us, - command, 8, content, len, use_sg); + command, 8, 0, content, len, use_sg); if (result != USB_STOR_TRANSPORT_GOOD) return result; @@ -431,6 +412,8 @@ int scm_wait_not_busy(struct us_data *us) { return result; if (status&0x01) // check condition return USB_STOR_TRANSPORT_FAILED; + if (status&0x20) // device fault + return USB_STOR_TRANSPORT_FAILED; if ((status&0x80)!=0x80) // not busy break; if (i<5) @@ -460,11 +443,9 @@ int scm_write_block(struct us_data *us, unsigned char command[8] = { 0x40, access|0x03, reg, 0x00, 0x00, 0x00, 0x00, 0x00 }; - int i; - unsigned char status; result = scm_bulk_transport(us, - command, 8, content, len, use_sg); + command, 8, 0, content, len, use_sg); if (result!=USB_STOR_TRANSPORT_GOOD) return result; @@ -492,11 +473,8 @@ int scm_write_block_test(struct us_data *us, qualifier, timeout, 0x00, 0x00 }; int i; - unsigned char status; unsigned char data[num_registers*2]; - int maxlen; int transferred; - int pipe; struct scatterlist *sg; char string[64]; @@ -509,16 +487,11 @@ int scm_write_block_test(struct us_data *us, } result = scm_bulk_transport(us, - command, 16, data, num_registers*2, 0); + command, 16, 0, data, num_registers*2, 0); if (result!=USB_STOR_TRANSPORT_GOOD) return result; - maxlen = us->pusb_dev->actconfig-> - interface[0].altsetting[0].endpoint[us->ep_out-1]. - wMaxPacketSize; - - pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); transferred = 0; US_DEBUGP("Transfer out %d bytes, sg buffers %d\n", @@ -528,28 +501,25 @@ int scm_write_block_test(struct us_data *us, /* Debug-print the first 48 bytes of the transfer */ - if (!use_sg) { - string[0] = 0; - for (i=0; i<len && i<48; i++) { - sprintf(string+strlen(string), "%02X ", - content[i]); - if ((i%16)==15) { - US_DEBUGP("%s\n", string); - string[0] = 0; - } - } - if (string[0]!=0) + string[0] = 0; + for (i=0; i<len && i<48; i++) { + sprintf(string+strlen(string), "%02X ", + content[i]); + if ((i%16)==15) { US_DEBUGP("%s\n", string); + string[0] = 0; + } } + if (string[0]!=0) + US_DEBUGP("%s\n", string); - result = scm_raw_bulk(us, pipe, maxlen, - content, len); + result = scm_raw_bulk(us, SCSI_DATA_WRITE, content, len); } else { sg = (struct scatterlist *)content; for (i=0; i<use_sg && transferred<len; i++) { - result = scm_raw_bulk(us, pipe, maxlen, + result = scm_raw_bulk(us, SCSI_DATA_WRITE, sg[i].address, len-transferred > sg[i].length ? sg[i].length : len-transferred); @@ -577,14 +547,13 @@ int scm_multiple_write(struct us_data *us, unsigned char cmd[8] = { 0x40, access|0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - unsigned char status; for (i=0; i<num_registers; i++) { data[i<<1] = registers[i]; data[1+(i<<1)] = data_out[i]; } - result = scm_bulk_transport(us, cmd, 8, data, num_registers*2, 0); + result = scm_bulk_transport(us, cmd, 8, 0, data, num_registers*2, 0); if (result!=USB_STOR_TRANSPORT_GOOD) return result; @@ -679,6 +648,52 @@ int scm_write_user_io(struct us_data *us, return result; } +static int init_sddr09(struct us_data *us) { + + int result; + unsigned char data[14]; + unsigned char command[8] = { + 0xc1, 0x01, 0, 0, 0, 0, 0, 0 + }; + unsigned char command2[8] = { + 0x41, 0, 0, 0, 0, 0, 0, 0 + }; + unsigned char tur[12] = { + 0x03, 0x20, 0, 0, 0x0e, 0, 0, 0, 0, 0, 0, 0 + }; + + if ( (result = scm_send_control(us, command, data, 2)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]); + + command[1] = 0x08; + + if ( (result = scm_send_control(us, command, data, 2)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]); +/* + if ( (result = scm_send_control(us, command2, tur, 12)) != + USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("SDDR09: request sense failed\n"); + return result; + } + + if ( (result = scm_raw_bulk( + us, SCSI_DATA_READ, data, 14)) != + USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("SDDR09: request sense bulk in failed\n"); + return result; + } + + US_DEBUGP("SDDR09: request sense worked\n"); +*/ + return result; +} + static int init_8200e(struct us_data *us) { int result; @@ -810,18 +825,15 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */ "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */ - /* FIXME: B9 (READ CD MSF) has unknown length! */ - - /* US_DEBUGP("XXXXXXXX 8200e transport called, tid %08X\n", - current->pid); */ - if (us->flags & US_FL_NEED_INIT) { US_DEBUGP("8200e: initializing\n"); init_8200e(us); us->flags &= ~US_FL_NEED_INIT; } - if (srb->sc_data_direction == SCSI_DATA_WRITE) + len = srb->request_bufflen; + +/* if (srb->sc_data_direction == SCSI_DATA_WRITE) len = srb->request_bufflen; else { @@ -863,12 +875,17 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) case 'W': len = 24; break; + case 'B': + // Let's try using the command structure's + // request_bufflen here + len = srb->request_bufflen; + break; default: US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n", srb->cmnd[0]); return USB_STOR_TRANSPORT_ERROR; } - } + } */ if (len > 0xFFFF) { US_DEBUGP("Error: len = %08X... what do I do now?\n", @@ -977,3 +994,163 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) return result; } + + +/* + * Transport for the Sandisk SDDR-09 + */ +int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + int result; + unsigned int len; + unsigned char send_scsi_command[8] = { + 0x41, 0, 0, 0, 0, 0, 0, 0 + }; + int i; + char string[64]; + unsigned char *ptr; + unsigned char inquiry_response[36] = { + 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00, + 'S', 'a', 'n', 'D', 'i', 's', 'k', ' ', + 'I', 'm', 'a', 'g', 'e', 'M', 'a', 't', + 'e', ' ', 'S', 'D', 'D', 'R', '0', '9', + ' ', ' ', ' ', ' ' + }; + + /* This table tells us: + X = command not supported + L = return length in cmnd[4] (8 bits). + H = return length in cmnd[7] and cmnd[8] (16 bits). + D = return length in cmnd[6] to cmnd[9] (32 bits). + B = return length/blocksize in cmnd[6] to cmnd[8]. + T = return length in cmnd[6] to cmnd[8] (24 bits). + 0-9 = fixed return length + W = 24 bytes + h = return length/2048 in cmnd[7-8]. + */ + + static char *lengths = + + /* 0123456789ABCDEF 0123456789ABCDEF */ + + "0XXL0XXXXXXXXXXX" "XXLXXXXXXXX0XX0X" /* 00-1F */ + "XXXXX8XXhXH0XXX0" "XXXXX0XXXXXXXXXX" /* 20-3F */ + "XXHHL0X0XXH0XX0X" "XHH00HXX0TH0H0XX" /* 40-5F */ + "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */ + "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */ + "X0XXX0XXDXDXXXXX" "XXXXXXXXX000XHBX" /* A0-BF */ + "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */ + "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */ + + if (us->flags & US_FL_NEED_INIT) { + US_DEBUGP("SDDR-09: initializing\n"); + init_sddr09(us); + us->flags &= ~US_FL_NEED_INIT; + } + + /* if (srb->sc_data_direction == SCSI_DATA_WRITE) */ + len = srb->request_bufflen; + /* else { + + switch (lengths[srb->cmnd[0]]) { + + case 'L': + len = srb->cmnd[4]; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + len = lengths[srb->cmnd[0]]-'0'; + break; + case 'H': + len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8]; + break; + case 'h': + len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8]; + len <<= 11; // *2048 + break; + case 'T': + len = (((unsigned int)srb->cmnd[6])<<16) | + (((unsigned int)srb->cmnd[7])<<8) | + srb->cmnd[8]; + break; + case 'D': + len = (((unsigned int)srb->cmnd[6])<<24) | + (((unsigned int)srb->cmnd[7])<<16) | + (((unsigned int)srb->cmnd[8])<<8) | + srb->cmnd[9]; + break; + case 'W': + len = 24; + break; + case 'B': + // Let's try using the command structure's + // request_bufflen here + len = srb->request_bufflen; + break; + default: + US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n", + srb->cmnd[0]); + return USB_STOR_TRANSPORT_ERROR; + } + } */ + + if (srb->request_bufflen > 0xFFFF) { + US_DEBUGP("Error: len = %08X... what do I do now?\n", + len); + return USB_STOR_TRANSPORT_ERROR; + } + + /* Dummy up a response for INQUIRY since SDDR09 doesn't + respond to INQUIRY commands */ + + if (srb->cmnd[0] == INQUIRY) { + memcpy(srb->request_buffer, inquiry_response, 36); + return USB_STOR_TRANSPORT_GOOD; + } + + for (; srb->cmd_len<12; srb->cmd_len++) + srb->cmnd[srb->cmd_len] = 0; + + srb->cmnd[1] = 0x20; + + string[0] = 0; + for (i=0; i<12; i++) + sprintf(string+strlen(string), "%02X ", srb->cmnd[i]); + + US_DEBUGP("SDDR09: Send control for command %s\n", + string); + + if ( (result = scm_send_control(us, send_scsi_command, + srb->cmnd, 12)) != USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("SDDR09: Control for command OK\n"); + + if (srb->sc_data_direction == SCSI_DATA_WRITE || + srb->sc_data_direction == SCSI_DATA_READ) { + + US_DEBUGP("SDDR09: %s %d bytes\n", + srb->sc_data_direction==SCSI_DATA_WRITE ? + "sending" : "receiving", + len); + + result = scm_bulk_transport(us, + NULL, 0, srb->sc_data_direction, + srb->request_buffer, + len, srb->use_sg); + + return result; + + } + + return result; +} + diff --git a/drivers/usb/storage/scm.h b/drivers/usb/storage/scm.h index edc324a84..f57463a1e 100644 --- a/drivers/usb/storage/scm.h +++ b/drivers/usb/storage/scm.h @@ -1,6 +1,8 @@ /* Driver for SCM Microsystems USB-ATAPI cable * Header File * + * $Id: scm.h,v 1.3 2000/07/24 19:19:52 mdharm Exp $ + * * Current development and maintainance by: * (c) 2000 Robert Baruch (autophile@dol.net) * @@ -73,5 +75,8 @@ extern int scm_write_user_io(struct us_data *us, extern int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us); +/* Sandisk SDDR-09 stuff */ + +extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us); #endif diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index ad0df666b..21fe3ec97 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -1,7 +1,7 @@ /* Driver for USB Mass Storage compliant devices * SCSI layer glue code * - * $Id: scsiglue.c,v 1.4 2000/07/20 01:14:56 mdharm Exp $ + * $Id: scsiglue.c,v 1.5 2000/07/24 18:55:39 mdharm Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -192,7 +192,7 @@ static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) static int command_abort( Scsi_Cmnd *srb ) { struct us_data *us = (struct us_data *)srb->host->hostdata[0]; - api_wrapper_data *awd = (api_wrapper_data *)us->current_urb->context; + wait_queue_head_t *wqh = (wait_queue_head_t *)us->current_urb->context; US_DEBUGP("command_abort() called\n"); @@ -209,8 +209,8 @@ static int command_abort( Scsi_Cmnd *srb ) usb_unlink_urb(us->current_urb); /* wake the control thread up */ - if (waitqueue_active(awd->wakeup)) - wake_up(awd->wakeup); + if (waitqueue_active(wqh)) + wake_up(wqh); /* wait for us to be done */ down(&(us->notify)); diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index e5445f21b..55e12f79f 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h @@ -1,7 +1,7 @@ /* Driver for USB Mass Storage compliant devices * Transport Functions Header File * - * $Id: transport.h,v 1.3 2000/07/20 23:36:22 mdharm Exp $ + * $Id: transport.h,v 1.4 2000/07/23 18:40:38 groovyjava Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -41,6 +41,7 @@ #ifndef _TRANSPORT_H_ #define _TRANSPORT_H_ +#include <linux/config.h> #include <linux/blk.h> #include "usb.h" #include "scsi.h" @@ -57,6 +58,9 @@ extern unsigned char us_direction[256/8]; #ifdef CONFIG_USB_STORAGE_HP8200e #define US_PR_SCM_ATAPI 0x80 /* SCM-ATAPI bridge */ #endif +#ifdef CONFIG_USB_STORAGE_SDDR09 +#define US_PR_SCM_SCSI 0x81 /* SCM-SCSI bridge */ +#endif /* * Bulk only data structures diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 060c8f4c0..99986371f 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -1,6 +1,6 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: usb.c,v 1.6 2000/07/20 23:36:22 mdharm Exp $ + * $Id: usb.c,v 1.11 2000/07/24 20:37:24 mdharm Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -43,12 +43,14 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/config.h> + #include "usb.h" #include "scsiglue.h" #include "transport.h" #include "protocol.h" #include "debug.h" -#ifdef CONFIG_USB_STORAGE_HP8200e +#if defined(CONFIG_USB_STORAGE_HP8200e) || defined(CONFIG_USB_STORAGE_SDDR09) #include "scm.h" #endif @@ -98,6 +100,9 @@ static int usb_stor_control_thread(void * __us) * This thread doesn't need any user-level access, * so get rid of all our resources.. */ + exit_files(current); + current->files = init_task.files; + atomic_inc(¤t->files->count); daemonize(); /* set our name for identification purposes */ @@ -250,6 +255,11 @@ static struct us_unusual_dev us_unusual_dev_list[] = { US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, { 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk ImageMate (SDDR-01)", US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP}, +#ifdef CONFIG_USB_STORAGE_SDDR09 + { 0x0781, 0x0200, 0x0100, 0x0100, "Sandisk ImageMate (SDDR-09)", + US_SC_SCSI, US_PR_SCM_SCSI, + US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_NEED_INIT}, +#endif { 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk Imagemate (SDDR-31)", US_SC_SCSI, US_PR_BULK, US_FL_IGNORE_SER}, { 0x07af, 0x0004, 0x0100, 0x0100, "Microtech USB-SCSI-DB25", @@ -436,7 +446,15 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) ep_in, ep_out, ep_int, ep_int ? ep_int->bInterval : 0); /* set the interface -- STALL is an acceptable response here */ +#ifdef CONFIG_USB_STORAGE_SDDR09 + if (protocol != US_PR_SCM_SCSI) + result = usb_set_interface(dev, + altsetting->bInterfaceNumber, 0); + else + result = usb_set_configuration(dev, 1); +#else result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0); +#endif US_DEBUGP("Result from usb_set_interface is %d\n", result); if (result == -EPIPE) { US_DEBUGP("-- clearing stall on control interface\n"); @@ -509,6 +527,12 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) USB_ENDPOINT_NUMBER_MASK; ss->ep_int = ep_int; + /* Reset the device's NEED_INIT flag if it needs to be + initialized with a magic sequence */ + + if (flags & US_FL_NEED_INIT) + ss->flags |= US_FL_NEED_INIT; + /* allocate an IRQ callback if one is needed */ if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) return NULL; @@ -603,8 +627,17 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) ss->transport = hp8200e_transport; ss->transport_reset = usb_stor_CB_reset; ss->max_lun = 1; + break; #endif + +#ifdef CONFIG_USB_STORAGE_SDDR09 + case US_PR_SCM_SCSI: + ss->transport_name = "SCM/SCSI"; + ss->transport = sddr09_transport; + ss->transport_reset = usb_stor_CB_reset; + ss->max_lun = 1; break; +#endif default: ss->transport_name = "Unknown"; @@ -691,8 +724,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) /* start up our control thread */ ss->pid = kernel_thread(usb_stor_control_thread, ss, - CLONE_FS | CLONE_FILES | - CLONE_SIGHAND); + CLONE_VM); if (ss->pid < 0) { printk(KERN_WARNING USB_STORAGE "Unable to start control thread\n"); diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c index de3b0dd9c..25026b174 100644 --- a/drivers/usb/usb.c +++ b/drivers/usb/usb.c @@ -607,6 +607,10 @@ static void call_policy (char *verb, struct usb_device *dev) dbg ("In_interrupt"); return; } + if (dev->devnum < 0) { + dbg ("device already deleted ??"); + return; + } if (!(envp = (char **) kmalloc (20 * sizeof (char *), GFP_KERNEL))) { dbg ("enomem"); return; @@ -1948,12 +1952,17 @@ static int usb_open(struct inode * inode, struct file * file) int minor = MINOR(inode->i_rdev); struct usb_driver *c = usb_minors[minor/16]; int err = -ENODEV; - struct file_operations *old_fops; + struct file_operations *old_fops, *new_fops = NULL; - if (!c || !c->fops) + /* + * No load-on-demand? Randy, could you ACK that it's really not + * supposed to be done? -- AV + */ + if (!c || !(new_fops = fops_get(c->fops))) return err; old_fops = file->f_op; - file->f_op = fops_get(c->fops); + file->f_op = new_fops; + /* Curiouser and curiouser... NULL ->open() as "no device" ? */ if (file->f_op->open) err = file->f_op->open(inode,file); if (err) { diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c index 19539318a..dacf0e317 100644 --- a/drivers/video/S3triofb.c +++ b/drivers/video/S3triofb.c @@ -861,8 +861,13 @@ static void fbcon_trio8_revc(struct display *p, int xx, int yy) } static struct display_switch fbcon_trio8 = { - fbcon_cfb8_setup, fbcon_trio8_bmove, fbcon_trio8_clear, fbcon_trio8_putc, - fbcon_trio8_putcs, fbcon_trio8_revc, NULL, NULL, fbcon_cfb8_clear_margins, - FONTWIDTH(8) + setup: fbcon_cfb8_setup, + bmove: fbcon_trio8_bmove, + clear: fbcon_trio8_clear, + putc: fbcon_trio8_putc, + putcs: fbcon_trio8_putcs, + revc: fbcon_trio8_revc, + clear_margins: fbcon_cfb8_clear_margins, + fontwidthmask: FONTWIDTH(8) }; #endif diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c index 3af8ee798..192cb278b 100644 --- a/drivers/video/aty128fb.c +++ b/drivers/video/aty128fb.c @@ -2400,10 +2400,14 @@ static void fbcon_aty8_clear_margins(struct vc_data *conp, } static struct display_switch fbcon_aty128_8 = { - fbcon_cfb8_setup, fbcon_aty128_bmove, fbcon_cfb8_clear, - fbcon_aty8_putc, fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL, - fbcon_aty8_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb8_setup, + bmove: fbcon_aty128_bmove, + clear: fbcon_cfb8_clear, + putc: fbcon_aty8_putc, + putcs: fbcon_aty8_putcs, + revc: fbcon_cfb8_revc, + clear_margins: fbcon_aty8_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif #ifdef FBCON_HAS_CFB16 @@ -2444,10 +2448,14 @@ static void fbcon_aty16_clear_margins(struct vc_data *conp, } static struct display_switch fbcon_aty128_16 = { - fbcon_cfb16_setup, fbcon_aty128_bmove, fbcon_cfb16_clear, - fbcon_aty16_putc, fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, NULL, - fbcon_aty16_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb16_setup, + bmove: fbcon_aty128_bmove, + clear: fbcon_cfb16_clear, + putc: fbcon_aty16_putc, + putcs: fbcon_aty16_putcs, + revc: fbcon_cfb16_revc, + clear_margins: fbcon_aty16_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif #ifdef FBCON_HAS_CFB24 @@ -2488,10 +2496,14 @@ static void fbcon_aty24_clear_margins(struct vc_data *conp, } static struct display_switch fbcon_aty128_24 = { - fbcon_cfb24_setup, fbcon_aty128_bmove, fbcon_cfb24_clear, - fbcon_aty24_putc, fbcon_aty24_putcs, fbcon_cfb24_revc, NULL, NULL, - fbcon_aty24_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb24_setup, + bmove: fbcon_aty128_bmove, + clear: fbcon_cfb24_clear, + putc: fbcon_aty24_putc, + putcs: fbcon_aty24_putcs, + revc: fbcon_cfb24_revc, + clear_margins: fbcon_aty24_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif #ifdef FBCON_HAS_CFB32 @@ -2532,10 +2544,14 @@ static void fbcon_aty32_clear_margins(struct vc_data *conp, } static struct display_switch fbcon_aty128_32 = { - fbcon_cfb32_setup, fbcon_aty128_bmove, fbcon_cfb32_clear, - fbcon_aty32_putc, fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL, - fbcon_aty32_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb32_setup, + bmove: fbcon_aty128_bmove, + clear: fbcon_cfb32_clear, + putc: fbcon_aty32_putc, + putcs: fbcon_aty32_putcs, + revc: fbcon_cfb32_revc, + clear_margins: fbcon_aty32_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c index d32a621b7..868a2485a 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -4562,9 +4562,14 @@ static void fbcon_aty8_clear_margins(struct vc_data *conp, struct display *p, } static struct display_switch fbcon_aty8 = { - fbcon_cfb8_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty8_putc, - fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_aty8_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb8_setup, + bmove: fbcon_aty_bmove, + clear: fbcon_aty_clear, + putc: fbcon_aty8_putc, + putcs: fbcon_aty8_putcs, + revc: fbcon_cfb8_revc, + clear_margins: fbcon_aty8_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif @@ -4619,9 +4624,14 @@ static void fbcon_aty16_clear_margins(struct vc_data *conp, struct display *p, } static struct display_switch fbcon_aty16 = { - fbcon_cfb16_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty16_putc, - fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_aty16_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb16_setup, + bmove: fbcon_aty_bmove, + clear: fbcon_aty_clear, + putc: fbcon_aty16_putc, + putcs: fbcon_aty16_putcs, + revc: fbcon_cfb16_revc, + clear_margins: fbcon_aty16_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif @@ -4676,9 +4686,14 @@ static void fbcon_aty24_clear_margins(struct vc_data *conp, struct display *p, } static struct display_switch fbcon_aty24 = { - fbcon_cfb24_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty24_putc, - fbcon_aty24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_aty24_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb24_setup, + bmove: fbcon_aty_bmove, + clear: fbcon_aty_clear, + putc: fbcon_aty24_putc, + putcs: fbcon_aty24_putcs, + revc: fbcon_cfb24_revc, + clear_margins: fbcon_aty24_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif @@ -4733,9 +4748,14 @@ static void fbcon_aty32_clear_margins(struct vc_data *conp, struct display *p, } static struct display_switch fbcon_aty32 = { - fbcon_cfb32_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty32_putc, - fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_aty32_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb32_setup, + bmove: fbcon_aty_bmove, + clear: fbcon_aty_clear, + putc: fbcon_aty32_putc, + putcs: fbcon_aty32_putcs, + revc: fbcon_cfb32_revc, + clear_margins: fbcon_aty32_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c index 2fd457eb6..1b4ae093a 100644 --- a/drivers/video/cgsixfb.c +++ b/drivers/video/cgsixfb.c @@ -517,8 +517,13 @@ static void cg6_restore_palette (struct fb_info_sbusfb *fb) } static struct display_switch cg6_dispsw __initdata = { - cg6_setup, fbcon_redraw_bmove, cg6_clear, cg6_putc, cg6_putcs, cg6_revc, - NULL, NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */ + setup: cg6_setup, + bmove: fbcon_redraw_bmove, + clear: cg6_clear, + putc: cg6_putc, + putcs: cg6_putcs, + revc: cg6_revc, + fontwidthmask: FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */ }; static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c index bdabd1e45..a0999093f 100644 --- a/drivers/video/clgenfb.c +++ b/drivers/video/clgenfb.c @@ -540,18 +540,15 @@ static void fbcon_clgen8_bmove (struct display *p, int sy, int sx, static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width); -static struct display_switch fbcon_clgen_8 = -{ - fbcon_cfb8_setup, - fbcon_clgen8_bmove, - fbcon_clgen8_clear, - fbcon_cfb8_putc, - fbcon_cfb8_putcs, - fbcon_cfb8_revc, - NULL, - NULL, - fbcon_cfb8_clear_margins, - FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) +static struct display_switch fbcon_clgen_8 = { + setup: fbcon_cfb8_setup, + bmove: fbcon_clgen8_bmove, + clear: fbcon_clgen8_clear, + putc: fbcon_cfb8_putc, + putcs: fbcon_cfb8_putcs, + revc: fbcon_cfb8_revc, + clear_margins: fbcon_cfb8_clear_margins, + fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) }; #endif #ifdef FBCON_HAS_CFB16 @@ -559,18 +556,15 @@ static void fbcon_clgen16_bmove (struct display *p, int sy, int sx, int dy, int dx, int height, int width); static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width); -static struct display_switch fbcon_clgen_16 = -{ - fbcon_cfb16_setup, - fbcon_clgen16_bmove, - fbcon_clgen16_clear, - fbcon_cfb16_putc, - fbcon_cfb16_putcs, - fbcon_cfb16_revc, - NULL, - NULL, - fbcon_cfb16_clear_margins, - FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) +static struct display_switch fbcon_clgen_16 = { + setup: fbcon_cfb16_setup, + bmove: fbcon_clgen16_bmove, + clear: fbcon_clgen16_clear, + putc: fbcon_cfb16_putc, + putcs: fbcon_cfb16_putcs, + revc: fbcon_cfb16_revc, + clear_margins: fbcon_cfb16_clear_margins, + fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) }; #endif #ifdef FBCON_HAS_CFB32 @@ -578,18 +572,15 @@ static void fbcon_clgen32_bmove (struct display *p, int sy, int sx, int dy, int dx, int height, int width); static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width); -static struct display_switch fbcon_clgen_32 = -{ - fbcon_cfb32_setup, - fbcon_clgen32_bmove, - fbcon_clgen32_clear, - fbcon_cfb32_putc, - fbcon_cfb32_putcs, - fbcon_cfb32_revc, - NULL, - NULL, - fbcon_cfb32_clear_margins, - FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) +static struct display_switch fbcon_clgen_32 = { + setup: fbcon_cfb32_setup, + bmove: fbcon_clgen32_bmove, + clear: fbcon_clgen32_clear, + putc: fbcon_cfb32_putc, + putcs: fbcon_cfb32_putcs, + revc: fbcon_cfb32_revc, + clear_margins: fbcon_cfb32_clear_margins, + fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) }; #endif diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 00080376f..f6a70e3a4 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -1106,15 +1106,25 @@ static void control_cfb32_revc(struct display *p, int xx, int yy) } static struct display_switch control_cfb16 = { - fbcon_cfb16_setup, fbcon_cfb16_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc, - fbcon_cfb16_putcs, control_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb16_setup, + bmove: fbcon_cfb16_bmove, + clear: fbcon_cfb16_clear, + putc: fbcon_cfb16_putc, + putcs: fbcon_cfb16_putcs, + revc: control_cfb16_revc, + clear_margins: fbcon_cfb16_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; static struct display_switch control_cfb32 = { - fbcon_cfb32_setup, fbcon_cfb32_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc, - fbcon_cfb32_putcs, control_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb32_setup, + bmove: fbcon_cfb32_bmove, + clear: fbcon_cfb32_clear, + putc: fbcon_cfb32_putc, + putcs: fbcon_cfb32_putcs, + revc: control_cfb32_revc, + clear_margins: fbcon_cfb32_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c index d01a4c9fc..5ee5295c1 100644 --- a/drivers/video/creatorfb.c +++ b/drivers/video/creatorfb.c @@ -626,8 +626,13 @@ out: } static struct display_switch ffb_dispsw __initdata = { - ffb_setup, fbcon_redraw_bmove, ffb_clear, ffb_putc, ffb_putcs, ffb_revc, - NULL, NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */ + setup: ffb_setup, + bmove: fbcon_redraw_bmove, + clear: ffb_clear, + putc: ffb_putc, + putcs: ffb_putcs, + revc: ffb_revc, + fontwidthmask: FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */ }; static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 55fb8728b..7f9cac9a1 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -246,16 +246,14 @@ cyber2000_accel_clear_margins(struct vc_data *conp, struct display *p, } static struct display_switch fbcon_cyber_accel = { - cyber2000_accel_setup, - cyber2000_accel_bmove, - cyber2000_accel_clear, - cyber2000_accel_putc, - cyber2000_accel_putcs, - cyber2000_accel_revc, - NULL, - NULL, - cyber2000_accel_clear_margins, - FONTWIDTH(8)|FONTWIDTH(16) + setup: cyber2000_accel_setup, + bmove: cyber2000_accel_bmove, + clear: cyber2000_accel_clear, + putc: cyber2000_accel_putc, + putcs: cyber2000_accel_putcs, + revc: cyber2000_accel_revc, + clear_margins: cyber2000_accel_clear_margins, + fontwidthmask: FONTWIDTH(8)|FONTWIDTH(16) }; /* diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c index b8246ceac..396a7befc 100644 --- a/drivers/video/cyberfb.c +++ b/drivers/video/cyberfb.c @@ -1270,9 +1270,14 @@ static void fbcon_cyber8_revc(struct display *p, int xx, int yy) } static struct display_switch fbcon_cyber8 = { - fbcon_cfb8_setup, fbcon_cyber8_bmove, fbcon_cyber8_clear, fbcon_cyber8_putc, - fbcon_cyber8_putcs, fbcon_cyber8_revc, NULL, NULL, fbcon_cfb8_clear_margins, - FONTWIDTH(8) + setup: fbcon_cfb8_setup, + bmove: fbcon_cyber8_bmove, + clear: fbcon_cyber8_clear, + putc: fbcon_cyber8_putc, + putcs: fbcon_cyber8_putcs, + revc: fbcon_cyber8_revc, + clear_margins: fbcon_cfb8_clear_margins, + fontwidthmask: FONTWIDTH(8) }; #endif diff --git a/drivers/video/dn_cfb4.c b/drivers/video/dn_cfb4.c index bee60647a..18ec1b79b 100644 --- a/drivers/video/dn_cfb4.c +++ b/drivers/video/dn_cfb4.c @@ -529,6 +529,11 @@ static void rev_char_apollofb(struct display *p, int xx, int yy) } static struct display_switch dispsw_apollofb = { - fbcon_mfb_setup, bmove_apollofb, clear_apollofb, - putc_apollofb, putcs_apollofb, rev_char_apollofb + setup: fbcon_mfb_setup, + bmove: bmove_apollofb, + clear: clear_apollofb, + putc: putc_apollofb, + putcs: putcs_apollofb, + revc: rev_char_apollofb, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/dn_cfb8.c b/drivers/video/dn_cfb8.c index a0b4cdb67..5452f1534 100644 --- a/drivers/video/dn_cfb8.c +++ b/drivers/video/dn_cfb8.c @@ -577,6 +577,11 @@ static void rev_char_apollofb(struct display *p, int xx, int yy) } static struct display_switch dispsw_apollofb = { - fbcon_mfb_setup, bmove_apollofb, clear_apollofb, - putc_apollofb, putcs_apollofb, rev_char_apollofb + setup: fbcon_mfb_setup, + bmove: bmove_apollofb, + clear: clear_apollofb, + putc: putc_apollofb, + putcs: putcs_apollofb, + revc: rev_char_apollofb, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c index 6029341a2..238f29555 100644 --- a/drivers/video/dnfb.c +++ b/drivers/video/dnfb.c @@ -533,6 +533,11 @@ static void rev_char_apollofb(struct display *p, int xx, int yy) } static struct display_switch dispsw_apollofb = { - fbcon_mfb_setup, bmove_apollofb, clear_apollofb, - putc_apollofb, putcs_apollofb, rev_char_apollofb + setup: fbcon_mfb_setup, + bmove: bmove_apollofb, + clear: clear_apollofb, + putc: putc_apollofb, + putcs: putcs_apollofb, + revc: rev_char_apollofb, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/dummycon.c b/drivers/video/dummycon.c index 9b54b6a76..ee14ed409 100644 --- a/drivers/video/dummycon.c +++ b/drivers/video/dummycon.c @@ -45,6 +45,8 @@ static int dummycon_dummy(void) return 0; } +#define DUMMY (void *)dummycon_dummy + /* * The console `switch' structure for the dummy console * @@ -52,19 +54,18 @@ static int dummycon_dummy(void) */ struct consw dummy_con = { - dummycon_startup, dummycon_init, - (void *)dummycon_dummy, /* con_deinit */ - (void *)dummycon_dummy, /* con_clear */ - (void *)dummycon_dummy, /* con_putc */ - (void *)dummycon_dummy, /* con_putcs */ - (void *)dummycon_dummy, /* con_cursor */ - (void *)dummycon_dummy, /* con_scroll */ - (void *)dummycon_dummy, /* con_bmove */ - (void *)dummycon_dummy, /* con_switch */ - (void *)dummycon_dummy, /* con_blank */ - (void *)dummycon_dummy, /* con_font_op */ - (void *)dummycon_dummy, /* con_set_palette */ - (void *)dummycon_dummy, /* con_scrolldelta */ - NULL, /* con_set_origin */ - NULL, /* con_save_screen */ + con_startup: dummycon_startup, + con_init: dummycon_init, + con_deinit: DUMMY, + con_clear: DUMMY, + con_putc: DUMMY, + con_putcs: DUMMY, + con_cursor: DUMMY, + con_scroll: DUMMY, + con_bmove: DUMMY, + con_switch: DUMMY, + con_blank: DUMMY, + con_font_op: DUMMY, + con_set_palette: DUMMY, + con_scrolldelta: DUMMY, }; diff --git a/drivers/video/fbcon-afb.c b/drivers/video/fbcon-afb.c index 5bc95651b..960925bc7 100644 --- a/drivers/video/fbcon-afb.c +++ b/drivers/video/fbcon-afb.c @@ -411,8 +411,13 @@ void fbcon_afb_revc(struct display *p, int xx, int yy) */ struct display_switch fbcon_afb = { - fbcon_afb_setup, fbcon_afb_bmove, fbcon_afb_clear, fbcon_afb_putc, - fbcon_afb_putcs, fbcon_afb_revc, NULL, NULL, NULL, FONTWIDTH(8) + setup: fbcon_afb_setup, + bmove: fbcon_afb_bmove, + clear: fbcon_afb_clear, + putc: fbcon_afb_putc, + putcs: fbcon_afb_putcs, + revc: fbcon_afb_revc, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/fbcon-cfb16.c b/drivers/video/fbcon-cfb16.c index 0c3c79ab7..f9dc80d14 100644 --- a/drivers/video/fbcon-cfb16.c +++ b/drivers/video/fbcon-cfb16.c @@ -280,9 +280,14 @@ void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p, */ struct display_switch fbcon_cfb16 = { - fbcon_cfb16_setup, fbcon_cfb16_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc, - fbcon_cfb16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb16_setup, + bmove: fbcon_cfb16_bmove, + clear: fbcon_cfb16_clear, + putc: fbcon_cfb16_putc, + putcs: fbcon_cfb16_putcs, + revc: fbcon_cfb16_revc, + clear_margins: fbcon_cfb16_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; diff --git a/drivers/video/fbcon-cfb2.c b/drivers/video/fbcon-cfb2.c index 4326b87f8..959b3e124 100644 --- a/drivers/video/fbcon-cfb2.c +++ b/drivers/video/fbcon-cfb2.c @@ -190,8 +190,13 @@ void fbcon_cfb2_revc(struct display *p, int xx, int yy) */ struct display_switch fbcon_cfb2 = { - fbcon_cfb2_setup, fbcon_cfb2_bmove, fbcon_cfb2_clear, fbcon_cfb2_putc, - fbcon_cfb2_putcs, fbcon_cfb2_revc, NULL, NULL, NULL, FONTWIDTH(8) + setup: fbcon_cfb2_setup, + bmove: fbcon_cfb2_bmove, + clear: fbcon_cfb2_clear, + putc: fbcon_cfb2_putc, + putcs: fbcon_cfb2_putcs, + revc: fbcon_cfb2_revc, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/fbcon-cfb24.c b/drivers/video/fbcon-cfb24.c index 74ace660f..ad66ee8bc 100644 --- a/drivers/video/fbcon-cfb24.c +++ b/drivers/video/fbcon-cfb24.c @@ -292,9 +292,14 @@ void fbcon_cfb24_clear_margins(struct vc_data *conp, struct display *p, */ struct display_switch fbcon_cfb24 = { - fbcon_cfb24_setup, fbcon_cfb24_bmove, fbcon_cfb24_clear, fbcon_cfb24_putc, - fbcon_cfb24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_cfb24_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb24_setup, + bmove: fbcon_cfb24_bmove, + clear: fbcon_cfb24_clear, + putc: fbcon_cfb24_putc, + putcs: fbcon_cfb24_putcs, + revc: fbcon_cfb24_revc, + clear_margins: fbcon_cfb24_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; diff --git a/drivers/video/fbcon-cfb32.c b/drivers/video/fbcon-cfb32.c index bedd81c96..dd88a4af2 100644 --- a/drivers/video/fbcon-cfb32.c +++ b/drivers/video/fbcon-cfb32.c @@ -266,9 +266,14 @@ void fbcon_cfb32_clear_margins(struct vc_data *conp, struct display *p, */ struct display_switch fbcon_cfb32 = { - fbcon_cfb32_setup, fbcon_cfb32_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc, - fbcon_cfb32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb32_setup, + bmove: fbcon_cfb32_bmove, + clear: fbcon_cfb32_clear, + putc: fbcon_cfb32_putc, + putcs: fbcon_cfb32_putcs, + revc: fbcon_cfb32_revc, + clear_margins: fbcon_cfb32_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; diff --git a/drivers/video/fbcon-cfb4.c b/drivers/video/fbcon-cfb4.c index a885fddfa..98b3fd119 100644 --- a/drivers/video/fbcon-cfb4.c +++ b/drivers/video/fbcon-cfb4.c @@ -194,8 +194,13 @@ void fbcon_cfb4_revc(struct display *p, int xx, int yy) */ struct display_switch fbcon_cfb4 = { - fbcon_cfb4_setup, fbcon_cfb4_bmove, fbcon_cfb4_clear, fbcon_cfb4_putc, - fbcon_cfb4_putcs, fbcon_cfb4_revc, NULL, NULL, NULL, FONTWIDTH(8) + setup: fbcon_cfb4_setup, + bmove: fbcon_cfb4_bmove, + clear: fbcon_cfb4_clear, + putc: fbcon_cfb4_putc, + putcs: fbcon_cfb4_putcs, + revc: fbcon_cfb4_revc, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/fbcon-cfb8.c b/drivers/video/fbcon-cfb8.c index 78e3d462f..7b91137e6 100644 --- a/drivers/video/fbcon-cfb8.c +++ b/drivers/video/fbcon-cfb8.c @@ -256,9 +256,14 @@ void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p, */ struct display_switch fbcon_cfb8 = { - fbcon_cfb8_setup, fbcon_cfb8_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc, - fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb8_setup, + bmove: fbcon_cfb8_bmove, + clear: fbcon_cfb8_clear, + putc: fbcon_cfb8_putc, + putcs: fbcon_cfb8_putcs, + revc: fbcon_cfb8_revc, + clear_margins: fbcon_cfb8_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; diff --git a/drivers/video/fbcon-hga.c b/drivers/video/fbcon-hga.c index 384e0a917..7d6767dee 100644 --- a/drivers/video/fbcon-hga.c +++ b/drivers/video/fbcon-hga.c @@ -213,9 +213,14 @@ void fbcon_hga_clear_margins(struct vc_data *conp, struct display *p, */ struct display_switch fbcon_hga = { - fbcon_hga_setup, fbcon_hga_bmove, fbcon_hga_clear, fbcon_hga_putc, - fbcon_hga_putcs, fbcon_hga_revc, NULL, NULL, fbcon_hga_clear_margins, - FONTWIDTH(8) + setup: fbcon_hga_setup, + bmove: fbcon_hga_bmove, + clear: fbcon_hga_clear, + putc: fbcon_hga_putc, + putcs: fbcon_hga_putcs, + revc: fbcon_hga_revc, + clear_margins: fbcon_hga_clear_margins, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/fbcon-ilbm.c b/drivers/video/fbcon-ilbm.c index d23c7e4b1..fd7f7459c 100644 --- a/drivers/video/fbcon-ilbm.c +++ b/drivers/video/fbcon-ilbm.c @@ -259,8 +259,13 @@ void fbcon_ilbm_revc(struct display *p, int xx, int yy) */ struct display_switch fbcon_ilbm = { - fbcon_ilbm_setup, fbcon_ilbm_bmove, fbcon_ilbm_clear, fbcon_ilbm_putc, - fbcon_ilbm_putcs, fbcon_ilbm_revc, NULL, NULL, NULL, FONTWIDTH(8) + setup: fbcon_ilbm_setup, + bmove: fbcon_ilbm_bmove, + clear: fbcon_ilbm_clear, + putc: fbcon_ilbm_putc, + putcs: fbcon_ilbm_putcs, + revc: fbcon_ilbm_revc, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/fbcon-iplan2p2.c b/drivers/video/fbcon-iplan2p2.c index 1a7e21cfe..0e9837b70 100644 --- a/drivers/video/fbcon-iplan2p2.c +++ b/drivers/video/fbcon-iplan2p2.c @@ -438,9 +438,14 @@ void fbcon_iplan2p2_clear_margins(struct vc_data *conp, struct display *p, */ struct display_switch fbcon_iplan2p2 = { - fbcon_iplan2p2_setup, fbcon_iplan2p2_bmove, fbcon_iplan2p2_clear, - fbcon_iplan2p2_putc, fbcon_iplan2p2_putcs, fbcon_iplan2p2_revc, NULL, - NULL, fbcon_iplan2p2_clear_margins, FONTWIDTH(8) + setup: fbcon_iplan2p2_setup, + bmove: fbcon_iplan2p2_bmove, + clear: fbcon_iplan2p2_clear, + putc: fbcon_iplan2p2_putc, + putcs: fbcon_iplan2p2_putcs, + revc: fbcon_iplan2p2_revc, + clear_margins: fbcon_iplan2p2_clear_margins, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/fbcon-iplan2p4.c b/drivers/video/fbcon-iplan2p4.c index 069c7d406..771d71893 100644 --- a/drivers/video/fbcon-iplan2p4.c +++ b/drivers/video/fbcon-iplan2p4.c @@ -458,9 +458,14 @@ void fbcon_iplan2p4_clear_margins(struct vc_data *conp, struct display *p, */ struct display_switch fbcon_iplan2p4 = { - fbcon_iplan2p4_setup, fbcon_iplan2p4_bmove, fbcon_iplan2p4_clear, - fbcon_iplan2p4_putc, fbcon_iplan2p4_putcs, fbcon_iplan2p4_revc, NULL, - NULL, fbcon_iplan2p4_clear_margins, FONTWIDTH(8) + setup: fbcon_iplan2p4_setup, + bmove: fbcon_iplan2p4_bmove, + clear: fbcon_iplan2p4_clear, + putc: fbcon_iplan2p4_putc, + putcs: fbcon_iplan2p4_putcs, + revc: fbcon_iplan2p4_revc, + clear_margins: fbcon_iplan2p4_clear_margins, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/fbcon-iplan2p8.c b/drivers/video/fbcon-iplan2p8.c index bc3730a1f..95c5680dd 100644 --- a/drivers/video/fbcon-iplan2p8.c +++ b/drivers/video/fbcon-iplan2p8.c @@ -495,9 +495,14 @@ void fbcon_iplan2p8_clear_margins(struct vc_data *conp, struct display *p, */ struct display_switch fbcon_iplan2p8 = { - fbcon_iplan2p8_setup, fbcon_iplan2p8_bmove, fbcon_iplan2p8_clear, - fbcon_iplan2p8_putc, fbcon_iplan2p8_putcs, fbcon_iplan2p8_revc, NULL, - NULL, fbcon_iplan2p8_clear_margins, FONTWIDTH(8) + setup: fbcon_iplan2p8_setup, + bmove: fbcon_iplan2p8_bmove, + clear: fbcon_iplan2p8_clear, + putc: fbcon_iplan2p8_putc, + putcs: fbcon_iplan2p8_putcs, + revc: fbcon_iplan2p8_revc, + clear_margins: fbcon_iplan2p8_clear_margins, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/fbcon-mac.c b/drivers/video/fbcon-mac.c index 2d021dd87..2a82bca4a 100644 --- a/drivers/video/fbcon-mac.c +++ b/drivers/video/fbcon-mac.c @@ -447,8 +447,13 @@ static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y) */ struct display_switch fbcon_mac = { - fbcon_mac_setup, fbcon_redraw_bmove, fbcon_redraw_clear, fbcon_mac_putc, - fbcon_mac_putcs, fbcon_mac_revc, NULL, NULL, NULL, FONTWIDTHRANGE(1,8) + setup: fbcon_mac_setup, + bmove: fbcon_redraw_bmove, + clear: fbcon_redraw_clear, + putc: fbcon_mac_putc, + putcs: fbcon_mac_putcs, + revc: fbcon_mac_revc, + fontwidthmask: FONTWIDTHRANGE(1,8) }; diff --git a/drivers/video/fbcon-mfb.c b/drivers/video/fbcon-mfb.c index 9aa3528dd..6185d8f3f 100644 --- a/drivers/video/fbcon-mfb.c +++ b/drivers/video/fbcon-mfb.c @@ -178,9 +178,14 @@ void fbcon_mfb_clear_margins(struct vc_data *conp, struct display *p, */ struct display_switch fbcon_mfb = { - fbcon_mfb_setup, fbcon_mfb_bmove, fbcon_mfb_clear, fbcon_mfb_putc, - fbcon_mfb_putcs, fbcon_mfb_revc, NULL, NULL, fbcon_mfb_clear_margins, - FONTWIDTH(8) + setup: fbcon_mfb_setup, + bmove: fbcon_mfb_bmove, + clear: fbcon_mfb_clear, + putc: fbcon_mfb_putc, + putcs: fbcon_mfb_putcs, + revc: fbcon_mfb_revc, + clear_margins: fbcon_mfb_clear_margins, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/fbcon-vga-planes.c b/drivers/video/fbcon-vga-planes.c index 3f500e694..2e1f5297e 100644 --- a/drivers/video/fbcon-vga-planes.c +++ b/drivers/video/fbcon-vga-planes.c @@ -327,15 +327,23 @@ void fbcon_vga_planes_revc(struct display *p, int xx, int yy) } struct display_switch fbcon_vga_planes = { - fbcon_vga_planes_setup, fbcon_vga_planes_bmove, fbcon_vga_planes_clear, - fbcon_vga_planes_putc, fbcon_vga_planes_putcs, fbcon_vga_planes_revc, - NULL, NULL, NULL, FONTWIDTH(8) + setup: fbcon_vga_planes_setup, + bmove: fbcon_vga_planes_bmove, + clear: fbcon_vga_planes_clear, + putc: fbcon_vga_planes_putc, + putcs: fbcon_vga_planes_putcs, + revc: fbcon_vga_planes_revc, + fontwidthmask: FONTWIDTH(8) }; struct display_switch fbcon_ega_planes = { - fbcon_vga_planes_setup, fbcon_vga_planes_bmove, fbcon_vga_planes_clear, - fbcon_ega_planes_putc, fbcon_ega_planes_putcs, fbcon_vga_planes_revc, - NULL, NULL, NULL, FONTWIDTH(8) + setup: fbcon_vga_planes_setup, + bmove: fbcon_vga_planes_bmove, + clear: fbcon_vga_planes_clear, + putc: fbcon_ega_planes_putc, + putcs: fbcon_ega_planes_putcs, + revc: fbcon_vga_planes_revc, + fontwidthmask: FONTWIDTH(8) }; #ifdef MODULE diff --git a/drivers/video/fbcon-vga.c b/drivers/video/fbcon-vga.c index 05f843d25..be890e53f 100644 --- a/drivers/video/fbcon-vga.c +++ b/drivers/video/fbcon-vga.c @@ -177,8 +177,13 @@ void fbcon_vga_revc(struct display *p, int x, int y) */ struct display_switch fbcon_vga = { - fbcon_vga_setup, fbcon_vga_bmove, fbcon_vga_clear, fbcon_vga_putc, - fbcon_vga_putcs, fbcon_vga_revc, NULL, NULL, NULL, FONTWIDTH(8) + setup: fbcon_vga_setup, + bmove: fbcon_vga_bmove, + clear: fbcon_vga_clear, + putc: fbcon_vga_putc, + putcs: fbcon_vga_putcs, + revc: fbcon_vga_revc, + fontwidthmask: FONTWIDTH(8) }; diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c index bf74fa162..37cb2f734 100644 --- a/drivers/video/fbcon.c +++ b/drivers/video/fbcon.c @@ -2400,8 +2400,6 @@ struct consw fb_con = { con_set_palette: fbcon_set_palette, con_scrolldelta: fbcon_scrolldelta, con_set_origin: fbcon_set_origin, - con_save_screen: NULL, - con_build_attr: NULL, con_invert_region: fbcon_invert_region, con_screen_pos: fbcon_screen_pos, con_getxy: fbcon_getxy, @@ -2414,14 +2412,15 @@ struct consw fb_con = { static void fbcon_dummy_op(void) {} +#define DUMMY (void *)fbcon_dummy_op + struct display_switch fbcon_dummy = { - (void *)fbcon_dummy_op, /* fbcon_dummy_setup */ - (void *)fbcon_dummy_op, /* fbcon_dummy_bmove */ - (void *)fbcon_dummy_op, /* fbcon_dummy_clear */ - (void *)fbcon_dummy_op, /* fbcon_dummy_putc */ - (void *)fbcon_dummy_op, /* fbcon_dummy_putcs */ - (void *)fbcon_dummy_op, /* fbcon_dummy_revc */ - NULL, /* fbcon_dummy_cursor */ + setup: DUMMY, + bmove: DUMMY, + clear: DUMMY, + putc: DUMMY, + putcs: DUMMY, + revc: DUMMY, }; diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c index 6eb6e0514..447b1b613 100644 --- a/drivers/video/g364fb.c +++ b/drivers/video/g364fb.c @@ -155,9 +155,15 @@ void fbcon_g364fb_cursor(struct display *p, int mode, int x, int y) static struct display_switch fbcon_g364cfb8 = { - fbcon_cfb8_setup, fbcon_cfb8_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc, - fbcon_cfb8_putcs, fbcon_cfb8_revc, fbcon_g364fb_cursor, NULL, - fbcon_cfb8_clear_margins, FONTWIDTH(8) + setup: fbcon_cfb8_setup, + bmove: fbcon_cfb8_bmove, + clear: fbcon_cfb8_clear, + putc: fbcon_cfb8_putc, + putcs: fbcon_cfb8_putcs, + revc: fbcon_cfb8_revc, + cursor: fbcon_g364fb_cursor, + clear_margins: fbcon_cfb8_clear_margins, + fontwidthmask: FONTWIDTH(8) }; /* diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index 2fbca3ef4..d3b3e5a38 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -1115,30 +1115,58 @@ imsttfbcon_revc (struct display *disp, int sx, int sy) #ifdef FBCON_HAS_CFB8 static struct display_switch fbcon_imstt8 = { - fbcon_cfb8_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb8_putc, - fbcon_cfb8_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb8_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb8_setup, + bmove: imsttfbcon_bmove, + clear: imsttfbcon_clear, + putc: fbcon_cfb8_putc, + putcs: fbcon_cfb8_putcs, + revc: imsttfbcon_revc, + cursor: imsttfbcon_cursor, + set_font: imsttfbcon_set_font, + clear_margins: fbcon_cfb8_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif #ifdef FBCON_HAS_CFB16 static struct display_switch fbcon_imstt16 = { - fbcon_cfb16_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb16_putc, - fbcon_cfb16_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb16_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb16_setup, + bmove: imsttfbcon_bmove, + clear: imsttfbcon_clear, + putc: fbcon_cfb16_putc, + putcs: fbcon_cfb16_putcs, + revc: imsttfbcon_revc, + cursor: imsttfbcon_cursor, + set_font: imsttfbcon_set_font, + clear_margins: fbcon_cfb16_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif #ifdef FBCON_HAS_CFB24 static struct display_switch fbcon_imstt24 = { - fbcon_cfb24_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb24_putc, - fbcon_cfb24_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb24_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb24_setup, + bmove: imsttfbcon_bmove, + clear: imsttfbcon_clear, + putc: fbcon_cfb24_putc, + putcs: fbcon_cfb24_putcs, + revc: imsttfbcon_revc, + cursor: imsttfbcon_cursor, + set_font: imsttfbcon_set_font, + clear_margins: fbcon_cfb24_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif #ifdef FBCON_HAS_CFB32 static struct display_switch fbcon_imstt32 = { - fbcon_cfb32_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb32_putc, - fbcon_cfb32_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb32_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb32_setup, + bmove: imsttfbcon_bmove, + clear: imsttfbcon_clear, + putc: fbcon_cfb32_putc, + putcs: fbcon_cfb32_putcs, + revc: imsttfbcon_revc, + cursor: imsttfbcon_cursor, + set_font: imsttfbcon_set_font, + clear_margins: fbcon_cfb32_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif diff --git a/drivers/video/leofb.c b/drivers/video/leofb.c index 8eeab5bb1..1ff9987f9 100644 --- a/drivers/video/leofb.c +++ b/drivers/video/leofb.c @@ -449,8 +449,13 @@ static void leo_restore_palette (struct fb_info_sbusfb *fb) } static struct display_switch leo_dispsw __initdata = { - leo_setup, fbcon_redraw_bmove, leo_clear, leo_putc, leo_putcs, leo_revc, - NULL, NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */ + setup: leo_setup, + bmove: fbcon_redraw_bmove, + clear: leo_clear, + putc: leo_putc, + putcs: leo_putcs, + revc: leo_revc, + fontwidthmask: FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */ }; static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c index 2eb2cfd85..a28388e1e 100644 --- a/drivers/video/matrox/matroxfb_accel.c +++ b/drivers/video/matrox/matroxfb_accel.c @@ -1042,56 +1042,79 @@ static int matrox_text_setfont(struct display* p, int width, int height) { #ifdef FBCON_HAS_VGATEXT static struct display_switch matroxfb_text = { - matrox_text_setup, matrox_text_bmove, matrox_text_clear, - matrox_text_putc, matrox_text_putcs, matrox_text_revc, - matrox_text_cursor, matrox_text_setfont, NULL, - FONTWIDTH(8)|FONTWIDTH(9) + setup: matrox_text_setup, + bmove: matrox_text_bmove, + clear: matrox_text_clear, + putc: matrox_text_putc, + putcs: matrox_text_putcs, + revc: matrox_text_revc, + cursor: matrox_text_cursor, + set_font: matrox_text_setfont, + fontwidthmask: FONTWIDTH(8)|FONTWIDTH(9) }; #endif #ifdef FBCON_HAS_CFB4 static struct display_switch matroxfb_cfb4 = { - fbcon_cfb4_setup, matrox_cfb4_bmove, matrox_cfb4_clear, - fbcon_cfb4_putc, fbcon_cfb4_putcs, matrox_cfb4_revc, - NULL, NULL, NULL, - /* cursor... */ /* set_font... */ - FONTWIDTH(8) /* fix, fix, fix it */ + setup: fbcon_cfb4_setup, + bmove: matrox_cfb4_bmove, + clear: matrox_cfb4_clear, + putc: fbcon_cfb4_putc, + putcs: fbcon_cfb4_putcs, + revc: matrox_cfb4_revc, + fontwidthmask: FONTWIDTH(8) /* fix, fix, fix it */ }; #endif #ifdef FBCON_HAS_CFB8 static struct display_switch matroxfb_cfb8 = { - fbcon_cfb8_setup, matrox_cfbX_bmove, matrox_cfb8_clear, - matrox_cfb8_putc, matrox_cfb8_putcs, matrox_cfb8_revc, - NULL, NULL, matrox_cfbX_clear_margins, - ~1 /* FONTWIDTHS */ + setup: fbcon_cfb8_setup, + bmove: matrox_cfbX_bmove, + clear: matrox_cfb8_clear, + putc: matrox_cfb8_putc, + putcs: matrox_cfb8_putcs, + revc: matrox_cfb8_revc, + clear_margins: matrox_cfbX_clear_margins, + fontwidthmask: ~1 /* FONTWIDTHS */ }; #endif #ifdef FBCON_HAS_CFB16 static struct display_switch matroxfb_cfb16 = { - fbcon_cfb16_setup, matrox_cfbX_bmove, matrox_cfb16_clear, - matrox_cfb16_putc, matrox_cfb16_putcs, matrox_cfb16_revc, - NULL, NULL, matrox_cfbX_clear_margins, - ~1 /* FONTWIDTHS */ + setup: fbcon_cfb16_setup, + bmove: matrox_cfbX_bmove, + clear: matrox_cfb16_clear, + putc: matrox_cfb16_putc, + putcs: matrox_cfb16_putcs, + revc: matrox_cfb16_revc, + clear_margins: matrox_cfbX_clear_margins, + fontwidthmask: ~1 /* FONTWIDTHS */ }; #endif #ifdef FBCON_HAS_CFB24 static struct display_switch matroxfb_cfb24 = { - fbcon_cfb24_setup, matrox_cfbX_bmove, matrox_cfb24_clear, - matrox_cfb24_putc, matrox_cfb24_putcs, matrox_cfb24_revc, - NULL, NULL, matrox_cfbX_clear_margins, - ~1 /* FONTWIDTHS */ /* TODO: and what about non-aligned access on BE? I think that there are no in my code */ + setup: fbcon_cfb24_setup, + bmove: matrox_cfbX_bmove, + clear: matrox_cfb24_clear, + putc: matrox_cfb24_putc, + putcs: matrox_cfb24_putcs, + revc: matrox_cfb24_revc, + clear_margins: matrox_cfbX_clear_margins, + fontwidthmask: ~1 /* FONTWIDTHS */ /* TODO: and what about non-aligned access on BE? I think that there are no in my code */ }; #endif #ifdef FBCON_HAS_CFB32 static struct display_switch matroxfb_cfb32 = { - fbcon_cfb32_setup, matrox_cfbX_bmove, matrox_cfb32_clear, - matrox_cfb32_putc, matrox_cfb32_putcs, matrox_cfb32_revc, - NULL, NULL, matrox_cfbX_clear_margins, - ~1 /* FONTWIDTHS */ + setup: fbcon_cfb32_setup, + bmove: matrox_cfbX_bmove, + clear: matrox_cfb32_clear, + putc: matrox_cfb32_putc, + putcs: matrox_cfb32_putcs, + revc: matrox_cfb32_revc, + clear_margins: matrox_cfbX_clear_margins, + fontwidthmask: ~1 /* FONTWIDTHS */ }; #endif diff --git a/drivers/video/mdacon.c b/drivers/video/mdacon.c index f249071f2..aac8c4ab9 100644 --- a/drivers/video/mdacon.c +++ b/drivers/video/mdacon.c @@ -586,24 +586,22 @@ static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines) */ struct consw mda_con = { - mdacon_startup, /* con_startup */ - mdacon_init, /* con_init */ - mdacon_deinit, /* con_deinit */ - mdacon_clear, /* con_clear */ - mdacon_putc, /* con_putc */ - mdacon_putcs, /* con_putcs */ - mdacon_cursor, /* con_cursor */ - mdacon_scroll, /* con_scroll */ - mdacon_bmove, /* con_bmove */ - mdacon_switch, /* con_switch */ - mdacon_blank, /* con_blank */ - mdacon_font_op, /* con_font_op */ - mdacon_set_palette, /* con_set_palette */ - mdacon_scrolldelta, /* con_scrolldelta */ - NULL, /* con_set_origin */ - NULL, /* con_save_screen */ - mdacon_build_attr, /* con_build_attr */ - mdacon_invert_region, /* con_invert_region */ + con_startup: mdacon_startup, + con_init: mdacon_init, + con_deinit: mdacon_deinit, + con_clear: mdacon_clear, + con_putc: mdacon_putc, + con_putcs: mdacon_putcs, + con_cursor: mdacon_cursor, + con_scroll: mdacon_scroll, + con_bmove: mdacon_bmove, + con_switch: mdacon_switch, + con_blank: mdacon_blank, + con_font_op: mdacon_font_op, + con_set_palette: mdacon_set_palette, + con_scrolldelta: mdacon_scrolldelta, + con_build_attr: mdacon_build_attr, + con_invert_region: mdacon_invert_region, }; #ifdef MODULE diff --git a/drivers/video/newport_con.c b/drivers/video/newport_con.c index eae607efb..da99d78a1 100644 --- a/drivers/video/newport_con.c +++ b/drivers/video/newport_con.c @@ -575,24 +575,22 @@ static int newport_dummy(struct vc_data *c) #define DUMMY (void *) newport_dummy struct consw newport_con = { - newport_startup, - newport_init, - DUMMY, /* con_deinit */ - newport_clear, - newport_putc, - newport_putcs, - newport_cursor, - newport_scroll, - newport_bmove, - newport_switch, - newport_blank, - newport_font_op, - newport_set_palette, - newport_scrolldelta, - DUMMY, /* newport_set_origin, */ - DUMMY, /* newport_save_screen */ - NULL, /* newport_build_attr */ - NULL /* newport_invert_region */ + con_startup: newport_startup, + con_init: newport_init, + con_deinit: DUMMY, + con_clear: newport_clear, + con_putc: newport_putc, + con_putcs: newport_putcs, + con_cursor: newport_cursor, + con_scroll: newport_scroll, + con_bmove: newport_bmove, + con_switch: newport_switch, + con_blank: newport_blank, + con_font_op: newport_font_op, + con_set_palette: newport_set_palette, + con_scrolldelta: newport_scrolldelta, + con_set_origin: DUMMY, + con_save_screen: DUMMY, }; #ifdef MODULE diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index d9789a75e..a3ee01ea1 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -1281,20 +1281,24 @@ static void pm2fb_clear_margins8(struct vc_data* conp, struct display* p, } static struct display_switch pm2_cfb8 = { - fbcon_cfb8_setup, pm2fb_pp_bmove, + setup: fbcon_cfb8_setup, + bmove: pm2fb_pp_bmove, #ifdef __alpha__ /* Not sure why, but this works and the other does not. */ /* Also, perhaps we need a separate routine to wait for the blitter to stop before doing this? */ /* In addition, maybe we need to do this for 16 and 32 bit depths? */ - fbcon_cfb8_clear, + clear: fbcon_cfb8_clear, #else - pm2fb_clear8, + clear: pm2fb_clear8, #endif - fbcon_cfb8_putc, fbcon_cfb8_putcs, fbcon_cfb8_revc, - pm2fb_cursor, pm2fb_set_font, - pm2fb_clear_margins8, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; + putc: fbcon_cfb8_putc, + putcs: fbcon_cfb8_putcs, + revc: fbcon_cfb8_revc, + cursor: pm2fb_cursor, + set_font: pm2fb_set_font, + clear_margins: pm2fb_clear_margins8, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif /* FBCON_HAS_CFB8 */ #ifdef FBCON_HAS_CFB16 @@ -1330,11 +1334,17 @@ static void pm2fb_clear_margins16(struct vc_data* conp, struct display* p, } static struct display_switch pm2_cfb16 = { - fbcon_cfb16_setup, pm2fb_pp_bmove, pm2fb_clear16, - fbcon_cfb16_putc, fbcon_cfb16_putcs, fbcon_cfb16_revc, - pm2fb_cursor, pm2fb_set_font, - pm2fb_clear_margins16, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; + setup: fbcon_cfb16_setup, + bmove: pm2fb_pp_bmove, + clear: pm2fb_clear16, + putc: fbcon_cfb16_putc, + putcs: fbcon_cfb16_putcs, + revc: fbcon_cfb16_revc, + cursor: pm2fb_cursor, + set_font: pm2fb_set_font, + clear_margins: pm2fb_clear_margins16, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; #endif /* FBCON_HAS_CFB16 */ #ifdef FBCON_HAS_CFB24 @@ -1388,11 +1398,17 @@ static void pm2fb_clear_margins24(struct vc_data* conp, struct display* p, } static struct display_switch pm2_cfb24 = { - fbcon_cfb24_setup, pm2fb_bmove, pm2fb_clear24, - fbcon_cfb24_putc, fbcon_cfb24_putcs, fbcon_cfb24_revc, - pm2fb_cursor, pm2fb_set_font, - pm2fb_clear_margins24, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; + setup: fbcon_cfb24_setup, + bmove: pm2fb_bmove, + clear: pm2fb_clear24, + putc: fbcon_cfb24_putc, + putcs: fbcon_cfb24_putcs, + revc: fbcon_cfb24_revc, + cursor: pm2fb_cursor, + set_font: pm2fb_set_font, + clear_margins: pm2fb_clear_margins24, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; #endif /* FBCON_HAS_CFB24 */ #ifdef FBCON_HAS_CFB32 @@ -1426,11 +1442,17 @@ static void pm2fb_clear_margins32(struct vc_data* conp, struct display* p, } static struct display_switch pm2_cfb32 = { - fbcon_cfb32_setup, pm2fb_bmove, pm2fb_clear32, - fbcon_cfb32_putc, fbcon_cfb32_putcs, fbcon_cfb32_revc, - pm2fb_cursor, pm2fb_set_font, - pm2fb_clear_margins32, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; + setup: fbcon_cfb32_setup, + bmove: pm2fb_bmove, + clear: pm2fb_clear32, + putc: fbcon_cfb32_putc, + putcs: fbcon_cfb32_putcs, + revc: fbcon_cfb32_revc, + cursor: pm2fb_cursor, + set_font: pm2fb_set_font, + clear_margins: pm2fb_clear_margins32, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; #endif /* FBCON_HAS_CFB32 */ /*************************************************************************** diff --git a/drivers/video/promcon.c b/drivers/video/promcon.c index e58d32ed1..d1090613e 100644 --- a/drivers/video/promcon.c +++ b/drivers/video/promcon.c @@ -581,14 +581,9 @@ struct consw prom_con = { con_font_op: promcon_font_op, con_set_palette: DUMMY, con_scrolldelta: DUMMY, - con_set_origin: NULL, - con_save_screen: NULL, -#if PROMCON_COLOR - con_build_attr: NULL, -#else +#if !(PROMCON_COLOR) con_build_attr: promcon_build_attr, #endif - con_invert_region: NULL, }; void __init prom_con_init(void) diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c index ccbdee763..5dda9d19c 100644 --- a/drivers/video/retz3fb.c +++ b/drivers/video/retz3fb.c @@ -1669,8 +1669,13 @@ static void retz3_clear_margins(struct vc_data* conp, struct display* p, static struct display_switch fbcon_retz3_8 = { - fbcon_cfb8_setup, retz3_8_bmove, retz3_8_clear, - retz3_putc, retz3_putcs, retz3_revc, NULL, NULL, - retz3_clear_margins, FONTWIDTH(8) + setup: fbcon_cfb8_setup, + bmove: retz3_8_bmove, + clear: retz3_8_clear, + putc: retz3_putc, + putcs: retz3_putcs, + revc: retz3_revc, + clear_margins: retz3_clear_margins, + fontwidthmask: FONTWIDTH(8) }; #endif diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index bbd547454..4128c313e 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -1183,58 +1183,54 @@ static void tdfx_cfbX_cursor(struct display *p, int mode, int x, int y) } #ifdef FBCON_HAS_CFB8 static struct display_switch fbcon_banshee8 = { - fbcon_cfb8_setup, - tdfx_cfbX_bmove, - tdfx_cfb8_clear, - tdfx_cfb8_putc, - tdfx_cfb8_putcs, - tdfx_cfbX_revc, - tdfx_cfbX_cursor, - NULL, - tdfx_cfbX_clear_margins, - FONTWIDTH(8) + setup: fbcon_cfb8_setup, + bmove: tdfx_cfbX_bmove, + clear: tdfx_cfb8_clear, + putc: tdfx_cfb8_putc, + putcs: tdfx_cfb8_putcs, + revc: tdfx_cfbX_revc, + cursor: tdfx_cfbX_cursor, + clear_margins: tdfx_cfbX_clear_margins, + fontwidthmask: FONTWIDTH(8) }; #endif #ifdef FBCON_HAS_CFB16 static struct display_switch fbcon_banshee16 = { - fbcon_cfb16_setup, - tdfx_cfbX_bmove, - tdfx_cfb16_clear, - tdfx_cfb16_putc, - tdfx_cfb16_putcs, - tdfx_cfbX_revc, - tdfx_cfbX_cursor, - NULL, - tdfx_cfbX_clear_margins, - FONTWIDTH(8) + setup: fbcon_cfb16_setup, + bmove: tdfx_cfbX_bmove, + clear: tdfx_cfb16_clear, + putc: tdfx_cfb16_putc, + putcs: tdfx_cfb16_putcs, + revc: tdfx_cfbX_revc, + cursor: tdfx_cfbX_cursor, + clear_margins: tdfx_cfbX_clear_margins, + fontwidthmask: FONTWIDTH(8) }; #endif #ifdef FBCON_HAS_CFB24 static struct display_switch fbcon_banshee24 = { - fbcon_cfb24_setup, - tdfx_cfbX_bmove, - tdfx_cfb24_clear, - tdfx_cfb24_putc, - tdfx_cfb24_putcs, - tdfx_cfbX_revc, - tdfx_cfbX_cursor, - NULL, - tdfx_cfbX_clear_margins, - FONTWIDTH(8) + setup: fbcon_cfb24_setup, + bmove: tdfx_cfbX_bmove, + clear: tdfx_cfb24_clear, + putc: tdfx_cfb24_putc, + putcs: tdfx_cfb24_putcs, + revc: tdfx_cfbX_revc, + cursor: tdfx_cfbX_cursor, + clear_margins: tdfx_cfbX_clear_margins, + fontwidthmask: FONTWIDTH(8) }; #endif #ifdef FBCON_HAS_CFB32 static struct display_switch fbcon_banshee32 = { - fbcon_cfb32_setup, - tdfx_cfbX_bmove, - tdfx_cfb32_clear, - tdfx_cfb32_putc, - tdfx_cfb32_putcs, - tdfx_cfbX_revc, - tdfx_cfbX_cursor, - NULL, - tdfx_cfbX_clear_margins, - FONTWIDTH(8) + setup: fbcon_cfb32_setup, + bmove: tdfx_cfbX_bmove, + clear: tdfx_cfb32_clear, + putc: tdfx_cfb32_putc, + putcs: tdfx_cfb32_putcs, + revc: tdfx_cfbX_revc, + cursor: tdfx_cfbX_cursor, + clear_margins: tdfx_cfbX_clear_margins, + fontwidthmask: FONTWIDTH(8) }; #endif diff --git a/drivers/video/vgacon.c b/drivers/video/vgacon.c index 1180d3ee0..5ebfec7b0 100644 --- a/drivers/video/vgacon.c +++ b/drivers/video/vgacon.c @@ -1038,22 +1038,22 @@ static int vgacon_dummy(struct vc_data *c) #define DUMMY (void *) vgacon_dummy struct consw vga_con = { - vgacon_startup, - vgacon_init, - vgacon_deinit, - DUMMY, /* con_clear */ - DUMMY, /* con_putc */ - DUMMY, /* con_putcs */ - vgacon_cursor, - vgacon_scroll, /* con_scroll */ - DUMMY, /* con_bmove */ - vgacon_switch, - vgacon_blank, - vgacon_font_op, - vgacon_set_palette, - vgacon_scrolldelta, - vgacon_set_origin, - vgacon_save_screen, - vgacon_build_attr, - vgacon_invert_region + con_startup: vgacon_startup, + con_init: vgacon_init, + con_deinit: vgacon_deinit, + con_clear: DUMMY, + con_putc: DUMMY, + con_putcs: DUMMY, + con_cursor: vgacon_cursor, + con_scroll: vgacon_scroll, + con_bmove: DUMMY, + con_switch: vgacon_switch, + con_blank: vgacon_blank, + con_font_op: vgacon_font_op, + con_set_palette: vgacon_set_palette, + con_scrolldelta: vgacon_scrolldelta, + con_set_origin: vgacon_set_origin, + con_save_screen: vgacon_save_screen, + con_build_attr: vgacon_build_attr, + con_invert_region: vgacon_invert_region, }; diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c index 41f2c4610..7441b7fdc 100644 --- a/drivers/video/virgefb.c +++ b/drivers/video/virgefb.c @@ -1348,9 +1348,14 @@ static void fbcon_virge8_clear_margins(struct vc_data *conp, struct display *p, } static struct display_switch fbcon_virge8 = { - fbcon_cfb8_setup, fbcon_virge8_bmove, fbcon_virge8_clear, fbcon_virge8_putc, - fbcon_virge8_putcs, fbcon_virge8_revc, NULL, NULL, fbcon_virge8_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb8_setup, + bmove: fbcon_virge8_bmove, + clear: fbcon_virge8_clear, + putc: fbcon_virge8_putc, + putcs: fbcon_virge8_putcs, + revc: fbcon_virge8_revc, + clear_margins: fbcon_virge8_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif @@ -1408,9 +1413,14 @@ static void fbcon_virge16_clear_margins(struct vc_data *conp, struct display *p, } static struct display_switch fbcon_virge16 = { - fbcon_cfb16_setup, fbcon_virge16_bmove, fbcon_virge16_clear, fbcon_virge16_putc, - fbcon_virge16_putcs, fbcon_virge16_revc, NULL, NULL, fbcon_virge16_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) + setup: fbcon_cfb16_setup, + bmove: fbcon_virge16_bmove, + clear: fbcon_virge16_clear, + putc: fbcon_virge16_putc, + putcs: fbcon_virge16_putcs, + revc: fbcon_virge16_revc, + clear_margins: fbcon_virge16_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif diff --git a/fs/buffer.c b/fs/buffer.c index 20790847f..8b5d19bda 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -708,11 +708,11 @@ static void refill_freelist(int size) } } -void init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *dev_id) +void init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private) { bh->b_list = BUF_CLEAN; bh->b_end_io = handler; - bh->b_dev_id = dev_id; + bh->b_private = private; } static void end_buffer_io_sync(struct buffer_head *bh, int uptodate) @@ -1742,7 +1742,7 @@ static void end_buffer_io_kiobuf(struct buffer_head *bh, int uptodate) mark_buffer_uptodate(bh, uptodate); - kiobuf = bh->b_kiobuf; + kiobuf = bh->b_private; unlock_buffer(bh); end_kio_request(kiobuf, uptodate); } @@ -1862,11 +1862,10 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], set_bh_page(tmp, map, offset); tmp->b_this_page = tmp; - init_buffer(tmp, end_buffer_io_kiobuf, NULL); + init_buffer(tmp, end_buffer_io_kiobuf, iobuf); tmp->b_dev = dev; tmp->b_blocknr = blocknr; tmp->b_state = 1 << BH_Mapped; - tmp->b_kiobuf = iobuf; if (rw == WRITE) { set_bit(BH_Uptodate, &tmp->b_state); diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 38a773d72..ad28db63a 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -1246,8 +1246,7 @@ devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, } if (ops == NULL) { - if ( S_ISCHR (mode) ) ops = get_chrfops (major, 0); - else if ( S_ISBLK (mode) ) ops = (void *) get_blkfops (major); + if ( S_ISBLK (mode) ) ops = (void *) get_blkfops (major); if (ops == NULL) { printk ("%s: devfs_register(%s): NULL ops pointer\n", @@ -2506,6 +2505,19 @@ static int devfs_open (struct inode *inode, struct file *file) else { /* Fallback to legacy scheme */ + /* + * Do we need it? Richard, could you verify it? + * It can legitimately happen if + * it is a character device and + * df->ops == NULL and + * de->registered is true, + * but AFAICS it can't happen - in devfs_register() we never set + * ->ops to NULL, in unregister() we set ->registered to false, + * in devfs_mknod() we set it to NULL only if ->register is false. + * + * Looks like this fallback is not needed at all. + * AV + */ if ( S_ISCHR (inode->i_mode) ) err = chrdev_open (inode, file); else err = -ENODEV; } diff --git a/fs/devices.c b/fs/devices.c index 3023747da..dd7db7730 100644 --- a/fs/devices.c +++ b/fs/devices.c @@ -35,6 +35,7 @@ struct device_struct { struct file_operations * fops; }; +static rwlock_t chrdevs_lock = RW_LOCK_UNLOCKED; static struct device_struct chrdevs[MAX_CHRDEV] = { { NULL, NULL }, }; @@ -47,11 +48,13 @@ int get_device_list(char * page) int len; len = sprintf(page, "Character devices:\n"); + read_lock(&chrdevs_lock); for (i = 0; i < MAX_CHRDEV ; i++) { if (chrdevs[i].fops) { len += sprintf(page+len, "%3d %s\n", i, chrdevs[i].name); } } + read_unlock(&chrdevs_lock); len += get_blkdev_list(page+len); return len; } @@ -59,68 +62,66 @@ int get_device_list(char * page) /* Return the function table of a device. Load the driver if needed. + Increment the reference count of module in question. */ -static struct file_operations * get_fops( - unsigned int major, - unsigned int minor, - unsigned int maxdev, - const char *mangle, /* String to use to build the module name */ - struct device_struct tb[]) +static struct file_operations * get_chrfops(unsigned int major, unsigned int minor) { struct file_operations *ret = NULL; - if (major < maxdev){ + if (!major || major >= MAX_CHRDEV) + return NULL; + + read_lock(&chrdevs_lock); + ret = fops_get(chrdevs[major].fops); + read_unlock(&chrdevs_lock); #ifdef CONFIG_KMOD - /* - * I do get request for device 0. I have no idea why. It happen - * at shutdown time for one. Without the following test, the - * kernel will happily trigger a request_module() which will - * trigger kmod and modprobe for nothing (since there - * is no device with major number == 0. And furthermore - * it locks the reboot process :-( - * - * Jacques Gelinas (jacques@solucorp.qc.ca) - * - * A. Haritsis <ah@doc.ic.ac.uk>: fix for serial module - * though we need the minor here to check if serial dev, - * we pass only the normal major char dev to kmod - * as there is no other loadable dev on these majors - */ - if ((isa_tty_dev(major) && need_serial(major,minor)) || - (major != 0 && !tb[major].fops)) { - char name[20]; - sprintf(name, mangle, major); - request_module(name); + if (ret && isa_tty_dev(major)) { + lock_kernel(); + if (need_serial(major,minor)) { + /* Force request_module anyway, but what for? */ + fops_put(ret); + ret = NULL; } -#endif - ret = tb[major].fops; + unlock_kernel(); } - return ret; -} + if (!ret) { + char name[20]; + sprintf(name, "char-major-%d", major); + request_module(name); + } + read_lock(&chrdevs_lock); + ret = fops_get(chrdevs[major].fops); + read_unlock(&chrdevs_lock); -struct file_operations * get_chrfops(unsigned int major, unsigned int minor) -{ - return get_fops (major,minor,MAX_CHRDEV,"char-major-%d",chrdevs); +#endif + return ret; } int register_chrdev(unsigned int major, const char * name, struct file_operations *fops) { if (major == 0) { + write_lock(&chrdevs_lock); for (major = MAX_CHRDEV-1; major > 0; major--) { if (chrdevs[major].fops == NULL) { chrdevs[major].name = name; chrdevs[major].fops = fops; + write_unlock(&chrdevs_lock); return major; } } + write_unlock(&chrdevs_lock); return -EBUSY; } if (major >= MAX_CHRDEV) return -EINVAL; - if (chrdevs[major].fops && chrdevs[major].fops != fops) + write_lock(&chrdevs_lock); + if (chrdevs[major].fops && chrdevs[major].fops != fops) { + write_unlock(&chrdevs_lock); return -EBUSY; + } chrdevs[major].name = name; chrdevs[major].fops = fops; + write_unlock(&chrdevs_lock); return 0; } @@ -128,12 +129,14 @@ int unregister_chrdev(unsigned int major, const char * name) { if (major >= MAX_CHRDEV) return -EINVAL; - if (!chrdevs[major].fops) - return -EINVAL; - if (strcmp(chrdevs[major].name, name)) + write_lock(&chrdevs_lock); + if (!chrdevs[major].fops || strcmp(chrdevs[major].name, name)) { + write_unlock(&chrdevs_lock); return -EINVAL; + } chrdevs[major].name = NULL; chrdevs[major].fops = NULL; + write_unlock(&chrdevs_lock); return 0; } @@ -144,15 +147,15 @@ int chrdev_open(struct inode * inode, struct file * filp) { int ret = -ENODEV; - lock_kernel(); - filp->f_op = fops_get(get_chrfops(MAJOR(inode->i_rdev), - MINOR(inode->i_rdev))); + filp->f_op = get_chrfops(MAJOR(inode->i_rdev), MINOR(inode->i_rdev)); if (filp->f_op) { ret = 0; - if (filp->f_op->open != NULL) + if (filp->f_op->open != NULL) { + lock_kernel(); ret = filp->f_op->open(inode,filp); + unlock_kernel(); + } } - unlock_kernel(); return ret; } diff --git a/fs/dquot.c b/fs/dquot.c index 022dd3423..42d91c35f 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -732,7 +732,7 @@ put_it: /* Free list of dquots - called from inode.c */ void put_dquot_list(struct list_head *tofree_head) { - struct list_head *act_head = tofree_head; + struct list_head *act_head = tofree_head.next; struct dquot *dquot; /* So now we have dquots on the list... Just free them */ diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 5792d7b95..70e806b02 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -259,10 +259,9 @@ repeat: ext2_debug ("goal = %d.\n", goal); tmp = ext2_alloc_block (inode, goal, err); - if (!tmp) { - *err = -ENOSPC; + if (!tmp) return NULL; - } + if (metadata) { result = getblk (inode->i_dev, tmp, blocksize); if (!buffer_uptodate(result)) diff --git a/fs/fcntl.c b/fs/fcntl.c index 37e32a012..659821873 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -15,45 +15,80 @@ extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg); +/* Expand files. Return <0 on error; 0 nothing done; 1 files expanded, + * we may have blocked. + * + * Should be called with the files->file_lock spinlock held for write. + */ +static int expand_files(struct files_struct *files, int nr) +{ + int err, expand = 0; +#ifdef FDSET_DEBUG + printk (KERN_ERR __FUNCTION__ " %d: nr = %d\n", current->pid, nr); +#endif + + if (nr >= files->max_fdset) { + expand = 1; + if ((err = expand_fdset(files, nr))) + goto out; + } + if (nr >= files->max_fds) { + expand = 1; + if ((err = expand_fd_array(files, nr))) + goto out; + } + err = expand; + out: +#ifdef FDSET_DEBUG + if (err) + printk (KERN_ERR __FUNCTION__ " %d: return %d\n", current->pid, err); +#endif + return err; +} + /* * locate_fd finds a free file descriptor in the open_fds fdset, * expanding the fd arrays if necessary. The files write lock will be * held on exit to ensure that the fd can be entered atomically. */ -static inline int locate_fd(struct files_struct *files, - struct file *file, int start) +static int locate_fd(struct files_struct *files, + struct file *file, int orig_start) { unsigned int newfd; int error; + int start; write_lock(&files->file_lock); repeat: - error = -EMFILE; + /* + * Someone might have closed fd's in the range + * orig_start..files->next_fd + */ + start = orig_start; if (start < files->next_fd) start = files->next_fd; - if (start >= files->max_fdset) { - expand: - error = expand_files(files, start); - if (error < 0) - goto out; - goto repeat; + + newfd = start; + if (start < files->max_fdset) { + newfd = find_next_zero_bit(files->open_fds->fds_bits, + files->max_fdset, start); } - newfd = find_next_zero_bit(files->open_fds->fds_bits, - files->max_fdset, start); - error = -EMFILE; if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur) goto out; - if (newfd >= files->max_fdset) - goto expand; error = expand_files(files, newfd); if (error < 0) goto out; - if (error) /* If we might have blocked, try again. */ + + /* + * If we needed to expand the fs array we + * might have blocked - try again. + */ + if (error) goto repeat; if (start <= files->next_fd) @@ -104,8 +139,8 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) if (newfd == oldfd) goto out_unlock; err = -EBADF; - if (newfd >= NR_OPEN) - goto out_unlock; /* following POSIX.1 6.2.1 */ + if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur) + goto out_unlock; get_file(file); /* We are now finished with oldfd */ err = expand_files(files, newfd); diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c index 74f174d63..12fa97fe1 100644 --- a/fs/nfsd/auth.c +++ b/fs/nfsd/auth.c @@ -10,6 +10,7 @@ #include <linux/sunrpc/svcauth.h> #include <linux/nfsd/nfsd.h> +#define CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE)) void nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) { @@ -50,10 +51,10 @@ nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) current->ngroups = i; if ((cred->cr_uid)) { - cap_t(current->cap_effective) &= ~CAP_FS_MASK; + cap_t(current->cap_effective) &= ~CAP_NFSD_MASK; } else { - cap_t(current->cap_effective) |= (CAP_FS_MASK & - current->cap_permitted); + cap_t(current->cap_effective) |= (CAP_NFSD_MASK & + current->cap_permitted); } rqstp->rq_userset = 1; diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index d3bb67b53..20e82fa7a 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -331,10 +331,6 @@ init_module(void) void cleanup_module(void) { - if (MOD_IN_USE) { - printk("nfsd: nfsd busy, remove delayed\n"); - return; - } do_nfsservctl = NULL; nfsd_export_shutdown(); nfsd_cache_shutdown(); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 2cdec3ec8..20fa7fafe 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -196,7 +196,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap) int ftype = 0; int imode; int err; - kernel_cap_t saved_cap = 0; int size_change = 0; if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) @@ -283,10 +282,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap) iap->ia_valid |= ATTR_CTIME; - if (current->fsuid != 0) { - saved_cap = current->cap_effective; - cap_clear(current->cap_effective); - } #ifdef CONFIG_QUOTA /* DQUOT_TRANSFER needs both ia_uid and ia_gid defined */ if (iap->ia_valid & (ATTR_UID|ATTR_GID)) { @@ -312,8 +307,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap) fh_unlock(fhp); put_write_access(inode); } - if (current->fsuid != 0) - current->cap_effective = saved_cap; if (err) goto out_nfserr; if (EX_ISSYNC(fhp->fh_export)) @@ -640,9 +633,6 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset, mm_segment_t oldfs; int err = 0; int stable = *stablep; -#ifdef CONFIG_QUOTA - uid_t saved_euid; -#endif err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file); if (err) @@ -680,15 +670,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset, /* Write the data. */ oldfs = get_fs(); set_fs(KERNEL_DS); -#ifdef CONFIG_QUOTA - /* This is for disk quota. */ - saved_euid = current->euid; - current->euid = current->fsuid; - err = file.f_op->write(&file, buf, cnt, &file.f_pos); - current->euid = saved_euid; -#else err = file.f_op->write(&file, buf, cnt, &file.f_pos); -#endif if (err >= 0) nfsdstats.io_write += cnt; set_fs(oldfs); @@ -696,17 +678,10 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset, /* clear setuid/setgid flag after write */ if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) { struct iattr ia; - kernel_cap_t saved_cap = 0; ia.ia_valid = ATTR_MODE; ia.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID); - if (current->fsuid != 0) { - saved_cap = current->cap_effective; - cap_clear(current->cap_effective); - } notify_change(dentry, &ia); - if (current->fsuid != 0) - current->cap_effective = saved_cap; } if (err >= 0 && stable) { @@ -1463,7 +1438,6 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc) { struct inode *inode = dentry->d_inode; int err; - kernel_cap_t saved_cap = 0; if (acc == MAY_NOP) return 0; @@ -1522,10 +1496,6 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc) inode->i_uid == current->fsuid) return 0; - if (current->fsuid != 0) { - saved_cap = current->cap_effective; - cap_clear(current->cap_effective); - } err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC)); @@ -1533,9 +1503,6 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc) if (err == -EACCES && S_ISREG(inode->i_mode) && acc == MAY_READ) err = permission(inode, MAY_EXEC); - if (current->fsuid != 0) - current->cap_effective = saved_cap; - return err? nfserrno(err) : 0; } diff --git a/fs/partitions/check.c b/fs/partitions/check.c index a72e2ccbc..29b93e5a5 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -34,7 +34,6 @@ #include "ultrix.h" extern void device_init(void); -extern void md_run_setup(void); extern int *blk_size[]; extern void rd_load(void); extern void initrd_load(void); diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 9f574e278..d7aabc334 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -287,18 +287,21 @@ static int kstat_read_proc(char *page, char **start, off_t off, int i, len; extern unsigned long total_forks; unsigned long jif = hz_to_std(jiffies); - unsigned sum = 0; + unsigned int sum = 0, user = 0, nice = 0, system = 0; int major, disk; - for (i = 0 ; i < NR_IRQS ; i++) - sum += kstat_irqs(i); - - len = sprintf(page, - "cpu %u %u %u %lu\n", - hz_to_std(kstat.cpu_user), - hz_to_std(kstat.cpu_nice), - hz_to_std(kstat.cpu_system), - jif*smp_num_cpus - hz_to_std(kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system)); + for (i = 0 ; i < smp_num_cpus; i++) { + int cpu = cpu_logical_map(i), j; + + user += hz_to_std(kstat.per_cpu_user[cpu]); + nice += hz_to_std(kstat.per_cpu_nice[cpu]); + system += hz_to_std(kstat.per_cpu_system[cpu]); + for (j = 0 ; j < NR_IRQS ; j++) + sum += kstat.irqs[cpu][j]; + } + + len = sprintf(page, "cpu %u %u %u %lu\n", user, nice, system, + jif * smp_num_cpus - (user + nice + system)); for (i = 0 ; i < smp_num_cpus; i++) len += sprintf(page + len, "cpu%d %u %u %u %lu\n", i, diff --git a/fs/select.c b/fs/select.c index 0b3718309..a49213ecb 100644 --- a/fs/select.c +++ b/fs/select.c @@ -37,7 +37,7 @@ struct poll_table_page { }; #define POLL_TABLE_FULL(table) \ - ((unsigned long)(table->entry+1) > PAGE_SIZE + (unsigned long)(table)) + ((unsigned long)((table)->entry+1) > PAGE_SIZE + (unsigned long)(table)) /* * Ok, Peter made a complicated, but straightforward multiple_wait() function. diff --git a/fs/super.c b/fs/super.c index 3303789f6..91e17f2b6 100644 --- a/fs/super.c +++ b/fs/super.c @@ -285,7 +285,7 @@ static LIST_HEAD(vfsmntlist); * add_vfsmnt - add a new mount node * @nd: location of mountpoint or %NULL if we want a root node * @root: root of (sub)tree to be mounted - * @dev_name: device name to show in /proc/mounts + * @dev_name: device name to show in /proc/mounts or %NULL (for "none"). * * This is VFS idea of mount. New node is allocated, bound to a tree * we are mounting and optionally (OK, usually) registered as mounted @@ -295,6 +295,13 @@ static LIST_HEAD(vfsmntlist); * Potential reason for failure (aside of trivial lack of memory) is a * deleted mountpoint. Caller must hold ->i_zombie on mountpoint * dentry (if any). + * + * Node is marked as MNT_VISIBLE (visible in /proc/mounts) unless both + * @nd and @devname are %NULL. It works since we pass non-%NULL @devname + * when we are mounting root and kern_mount() filesystems are deviceless. + * If we will get a kern_mount() filesystem with nontrivial @devname we + * will have to pass the visibility flag explicitly, so if we will add + * support for such beasts we'll have to change prototype. */ static struct vfsmount *add_vfsmnt(struct nameidata *nd, @@ -310,6 +317,9 @@ static struct vfsmount *add_vfsmnt(struct nameidata *nd, goto out; memset(mnt, 0, sizeof(struct vfsmount)); + if (nd || dev_name) + mnt->mnt_flags = MNT_VISIBLE; + /* It may be NULL, but who cares? */ if (dev_name) { name = kmalloc(strlen(dev_name)+1, GFP_KERNEL); @@ -344,7 +354,8 @@ out: return mnt; fail: spin_unlock(&dcache_lock); - kfree(mnt->mnt_devname); + if (mnt->mnt_devname) + kfree(mnt->mnt_devname); kfree(mnt); return NULL; } @@ -370,7 +381,8 @@ static void move_vfsmnt(struct vfsmount *mnt, /* flip names */ if (new_devname) { - kfree(mnt->mnt_devname); + if (mnt->mnt_devname) + kfree(mnt->mnt_devname); mnt->mnt_devname = new_devname; } @@ -411,7 +423,8 @@ static void remove_vfsmnt(struct vfsmount *mnt) dput(mnt->mnt_mountpoint); dput(mnt->mnt_root); - kfree(mnt->mnt_devname); + if (mnt->mnt_devname) + kfree(mnt->mnt_devname); kfree(mnt); } @@ -460,11 +473,13 @@ int get_filesystem_info( char *buf ) for (p = vfsmntlist.next; p!=&vfsmntlist && len < PAGE_SIZE - 160; p = p->next) { struct vfsmount *tmp = list_entry(p, struct vfsmount, mnt_list); + if (!(tmp->mnt_flags & MNT_VISIBLE)) + continue; path = d_path(tmp->mnt_root, tmp, buffer, PAGE_SIZE); if (!path) continue; len += sprintf( buf + len, "%s %s %s %s", - tmp->mnt_devname, path, + tmp->mnt_devname ? tmp->mnt_devname : "none", path, tmp->mnt_sb->s_type->name, tmp->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw" ); for (fs_infop = fs_info; fs_infop->flag; fs_infop++) { @@ -922,7 +937,7 @@ struct vfsmount *kern_mount(struct file_system_type *type) put_unnamed_dev(dev); return ERR_PTR(-EINVAL); } - mnt = add_vfsmnt(NULL, sb->s_root, "none"); + mnt = add_vfsmnt(NULL, sb->s_root, NULL); if (!mnt) { kill_super(sb, 0); return ERR_PTR(-ENOMEM); diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index 9c38896a3..3895b0774 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -453,10 +453,11 @@ static int vfat_valid_shortname(struct nls_table *nls, wchar_t *name, int len) if (charbuf[chi] != vfat_tolower(nls, c)) return -EINVAL; if (strchr(replace_chars,c)) return -EINVAL; if (c < ' '|| c==':') return -EINVAL; - if (c == '.') break; + if (c == '.') goto dot; space = c == ' '; } } +dot:; if (space) return -EINVAL; if (len && c != '.') { len--; @@ -464,6 +465,7 @@ static int vfat_valid_shortname(struct nls_table *nls, wchar_t *name, int len) if (charbuf[0] != '.') return -EINVAL; } else return -EINVAL; + c = '.'; } if (c == '.') { if (len >= 4) return -EINVAL; @@ -522,7 +524,7 @@ static int vfat_format_name(struct nls_table *nls, wchar_t *name, if (chl == 0) return -EINVAL; for (chi = 0; chi < chl; chi++){ - if (charbuf[chi] == '.') break; + if (charbuf[chi] == '.') goto dot; if (!charbuf[chi]) return -EINVAL; if (walk-res == 8) return -EINVAL; if (strchr(replace_chars,charbuf[chi])) return -EINVAL; @@ -532,6 +534,7 @@ static int vfat_format_name(struct nls_table *nls, wchar_t *name, walk++; } } +dot:; if (space) return -EINVAL; if (len >= 0) { while (walk-res < 8) *walk++ = ' '; diff --git a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h index e02aff08d..75b33ae5c 100644 --- a/include/asm-i386/mmu_context.h +++ b/include/asm-i386/mmu_context.h @@ -27,8 +27,9 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu) { - set_bit(cpu, &next->cpu_vm_mask); if (prev != next) { + /* stop flush ipis for the previous mm */ + clear_bit(cpu, &prev->cpu_vm_mask); /* * Re-load LDT if necessary */ @@ -38,20 +39,22 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str cpu_tlbstate[cpu].state = TLBSTATE_OK; cpu_tlbstate[cpu].active_mm = next; #endif + set_bit(cpu, &next->cpu_vm_mask); /* Re-load page tables */ asm volatile("movl %0,%%cr3": :"r" (__pa(next->pgd))); - clear_bit(cpu, &prev->cpu_vm_mask); } #ifdef CONFIG_SMP else { - int old_state = cpu_tlbstate[cpu].state; cpu_tlbstate[cpu].state = TLBSTATE_OK; if(cpu_tlbstate[cpu].active_mm != next) BUG(); - if(old_state == TLBSTATE_OLD) + if(!test_and_set_bit(cpu, &next->cpu_vm_mask)) { + /* We were in lazy tlb mode and leave_mm disabled + * tlb flush IPI delivery. We must flush our tlb. + */ local_flush_tlb(); + } } - #endif } diff --git a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h index 78a229362..74c9b3798 100644 --- a/include/asm-i386/pgalloc.h +++ b/include/asm-i386/pgalloc.h @@ -240,7 +240,6 @@ static inline void flush_tlb_range(struct mm_struct * mm, unsigned long start, u #define TLBSTATE_OK 1 #define TLBSTATE_LAZY 2 -#define TLBSTATE_OLD 3 struct tlb_state { diff --git a/include/asm-sh/checksum.h b/include/asm-sh/checksum.h index f19fc9067..05a556fc7 100644 --- a/include/asm-sh/checksum.h +++ b/include/asm-sh/checksum.h @@ -9,6 +9,8 @@ * Copyright (C) 1999 by Kaz Kojima & Niibe Yutaka */ +#include <linux/config.h> + /* * computes the checksum of a memory block at buff, length len, * and adds in "sum" (32-bit) diff --git a/include/asm-sh/serial.h b/include/asm-sh/serial.h index 3156c8a5f..8e39b4e90 100644 --- a/include/asm-sh/serial.h +++ b/include/asm-sh/serial.h @@ -7,8 +7,6 @@ #ifndef _ASM_SERIAL_H #define _ASM_SERIAL_H -#include <linux/config.h> - /* * This assumes you have a 1.8432 MHz clock for your UART. * diff --git a/include/linux/fs.h b/include/linux/fs.h index 821abdf30..050318926 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -238,11 +238,10 @@ struct buffer_head { char * b_data; /* pointer to data block (512 byte) */ struct page *b_page; /* the page this bh is mapped to */ void (*b_end_io)(struct buffer_head *bh, int uptodate); /* I/O completion */ - void *b_dev_id; + void *b_private; /* reserved for b_end_io */ unsigned long b_rsector; /* Real buffer location on disk */ wait_queue_head_t b_wait; - struct kiobuf * b_kiobuf; /* kiobuf which owns this IO */ }; typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate); @@ -803,7 +802,7 @@ struct file_system_type var = { \ /* Alas, no aliases. Too much hassle with bringing module.h everywhere */ #define fops_get(fops) \ (((fops) && (fops)->owner) \ - ? __MOD_INC_USE_COUNT((fops)->owner), (fops) \ + ? ( try_inc_mod_count((fops)->owner) ? (fops) : NULL ) \ : (fops)) #define fops_put(fops) \ @@ -900,7 +899,6 @@ extern int blkdev_put(struct block_device *, int); /* fs/devices.c */ extern const struct block_device_operations *get_blkfops(unsigned int); -extern struct file_operations *get_chrfops(unsigned int, unsigned int); extern int register_chrdev(unsigned int, const char *, struct file_operations *); extern int unregister_chrdev(unsigned int, const char *); extern int chrdev_open(struct inode *, struct file *); diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index ae788ce52..9c123fa48 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ------------------------------------------------------------------------- */ -/* $Id: i2c-id.h,v 1.15 2000/03/16 14:01:57 frodo Exp $ */ +/* $Id: i2c-id.h,v 1.16 2000/04/03 18:57:42 frodo Exp $ */ #ifndef I2C_ID_H #define I2C_ID_H @@ -70,6 +70,7 @@ #define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */ #define I2C_DRIVERID_PCF8583 25 /* real time clock */ #define I2C_DRIVERID_SAB3036 26 /* SAB3036 tuner */ +#define I2C_DRIVERID_TDA7432 27 /* Stereo sound processor */ #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ #define I2C_DRIVERID_EXP1 0xF1 diff --git a/include/linux/i2c.h b/include/linux/i2c.h index f1f82a1c8..62066f8b0 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -23,13 +23,17 @@ /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and Frodo Looijaard <frodol@dds.nl> */ -/* $Id: i2c.h,v 1.37 2000/02/15 17:57:27 frodo Exp $ */ +/* $Id: i2c.h,v 1.40 2000/07/19 19:55:45 frodo Exp $ */ #ifndef I2C_H #define I2C_H #include <linux/i2c-id.h> /* id values of adapters et. al. */ + +struct i2c_msg; + + #ifdef __KERNEL__ /* --- Includes and compatibility declarations ------------------------ */ @@ -56,7 +60,6 @@ #define I2C_CLIENT_MAX 32 #define I2C_DUMMY_MAX 4 -struct i2c_msg; struct i2c_algorithm; struct i2c_adapter; struct i2c_client; @@ -86,23 +89,6 @@ extern int i2c_slave_send(struct i2c_client *,char*,int); extern int i2c_slave_recv(struct i2c_client *,char*,int); -/* - * I2C Message - could be used in the current interface to - */ -struct i2c_msg { - u16 addr; /* slave address */ - unsigned short flags; -#define I2C_M_TEN 0x10 /* we have a ten bit chip address */ -#define I2C_M_RD 0x01 -#define I2C_M_NOSTART 0x4000 -#define I2C_M_REV_DIR_ADDR 0x2000 -#if 0 -#define I2C_M_PROBE 0x20 -#endif - short len; /* msg length */ - char *buf; /* pointer to msg data */ -}; - /* This is the very generalized SMBus access routine. You probably do not want to use this, though; one of the functions below may be much easier, @@ -198,6 +184,8 @@ struct i2c_client { struct i2c_adapter *adapter; /* the adapter we sit on */ struct i2c_driver *driver; /* and our access routines */ void *data; /* for the clients */ + int usage_count; /* How many accesses currently */ + /* to the client */ }; @@ -283,6 +271,11 @@ struct i2c_adapter { #define I2C_DF_NOTIFY 0x01 /* notify on bus (de/a)ttaches */ #define I2C_DF_DUMMY 0x02 /* do not connect any clients */ +/*flags for the client struct: */ +#define I2C_CLIENT_ALLOW_USE 0x01 /* Client allows access */ +#define I2C_CLIENT_ALLOW_MULTIPLE_USE 0x02 /* Allow multiple access-locks */ + /* on an i2c_client */ + /* i2c_client_address_data is the struct for holding default client * addresses for a driver and for the parameters supplied on the * command line @@ -326,6 +319,23 @@ extern int i2c_detach_client(struct i2c_client *); extern void i2c_inc_use_client(struct i2c_client *); extern void i2c_dec_use_client(struct i2c_client *); +/* New function: This is to get an i2c_client-struct for controlling the + client either by using i2c_control-function or having the + client-module export functions that can be used with the i2c_client + -struct. */ +extern struct i2c_client *i2c_get_client(int driver_id, int adapter_id, + struct i2c_client *prev); + +/* Should be used with new function + extern struct i2c_client *i2c_get_client(int,int,struct i2c_client *); + to make sure that client-struct is valid and that it is okay to access + the i2c-client. + returns -EACCES if client doesn't allow use (default) + returns -EBUSY if client doesn't allow multiple use (default) and + usage_count >0 */ +extern int i2c_use_client(struct i2c_client *); +extern int i2c_release_client(struct i2c_client *); + /* returns -EBUSY if address has been taken, 0 if not. Note that the only other place at which this is called is within i2c_attach_client; so you can cheat by simply not registering. Not recommended, of course! */ @@ -361,6 +371,21 @@ extern int i2c_check_functionality (struct i2c_adapter *adap, u32 func); #endif /* __KERNEL__ */ +#include <linux/types.h> +/* + * I2C Message - used for pure i2c transaction, also from /dev interface + */ +struct i2c_msg { + __u16 addr; /* slave address */ + unsigned short flags; +#define I2C_M_TEN 0x10 /* we have a ten bit chip address */ +#define I2C_M_RD 0x01 +#define I2C_M_NOSTART 0x4000 +#define I2C_M_REV_DIR_ADDR 0x2000 + short len; /* msg length */ + char *buf; /* pointer to msg data */ +}; + /* To determine what functionality is present */ #define I2C_FUNC_I2C 0x00000001 @@ -395,7 +420,7 @@ extern int i2c_check_functionality (struct i2c_adapter *adap, u32 func); I2C_FUNC_SMBUS_BYTE_DATA | \ I2C_FUNC_SMBUS_WORD_DATA | \ I2C_FUNC_SMBUS_PROC_CALL | \ - I2C_FUNC_SMBUS_READ_BLOCK_DATA + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA /* * Data for SMBus Messages diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index c9f194be4..179963c77 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h @@ -16,7 +16,6 @@ #define DK_MAX_DISK 16 struct kernel_stat { - unsigned int cpu_user, cpu_nice, cpu_system; unsigned int per_cpu_user[NR_CPUS], per_cpu_nice[NR_CPUS], per_cpu_system[NR_CPUS]; diff --git a/include/linux/mount.h b/include/linux/mount.h index adb571de2..8eff1ecc9 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -12,6 +12,8 @@ #define _LINUX_MOUNT_H #ifdef __KERNEL__ +#define MNT_VISIBLE 1 + struct vfsmount { struct dentry *mnt_mountpoint; /* dentry of mountpoint */ @@ -24,6 +26,7 @@ struct vfsmount struct list_head mnt_mounts; /* list of children, anchored here */ struct list_head mnt_child; /* and going through their mnt_child */ atomic_t mnt_count; + int mnt_flags; char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; diff --git a/include/linux/parport.h b/include/linux/parport.h index 27d813e9d..71fc1398b 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -1,10 +1,9 @@ /* $Id: parport.h,v 1.1 1998/05/17 10:57:52 andrea Exp andrea $ */ /* - * The block comments above the functions in this file are - * licensed as part of the generated file - * Documentation/DocBook/parportbook.sgml under the GNU Free - * Documentation License. + * Any part of this program may be used in documents licensed under + * the GNU Free Documentation License, Version 1.1 or any later version + * published by the Free Software Foundation. */ #ifndef _PARPORT_H_ diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index 7aef27bca..6cc9767a3 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h @@ -82,6 +82,7 @@ extern struct gendisk * find_gendisk (kdev_t dev); extern int md_notify_reboot(struct notifier_block *this, unsigned long code, void *x); extern int md_error (kdev_t mddev, kdev_t rdev); +extern void md_run_setup(void); extern void md_print_devices (void); diff --git a/include/linux/sched.h b/include/linux/sched.h index 2d7161676..6b82d6977 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -139,8 +139,9 @@ extern void init_idle(void); extern void show_state(void); extern void cpu_init (void); extern void trap_init(void); -extern void update_one_process( struct task_struct *p, - unsigned long ticks, unsigned long user, unsigned long system, int cpu); +extern void update_process_times(int user); +extern void update_one_process(struct task_struct *p, unsigned long user, + unsigned long system, int cpu); #define MAX_SCHEDULE_TIMEOUT LONG_MAX extern signed long FASTCALL(schedule_timeout(signed long timeout)); @@ -683,37 +684,6 @@ extern fd_set *alloc_fdset(int); extern int expand_fdset(struct files_struct *, int nr); extern void free_fdset(fd_set *, int); -/* Expand files. Return <0 on error; 0 nothing done; 1 files expanded, - * we may have blocked. - * - * Should be called with the files->file_lock spinlock held for write. - */ -static inline int expand_files(struct files_struct *files, int nr) -{ - int err, expand = 0; -#ifdef FDSET_DEBUG - printk (KERN_ERR __FUNCTION__ " %d: nr = %d\n", current->pid, nr); -#endif - - if (nr >= files->max_fdset) { - expand = 1; - if ((err = expand_fdset(files, nr))) - goto out; - } - if (nr >= files->max_fds) { - expand = 1; - if ((err = expand_fd_array(files, nr))) - goto out; - } - err = expand; - out: -#ifdef FDSET_DEBUG - if (err) - printk (KERN_ERR __FUNCTION__ " %d: return %d\n", current->pid, err); -#endif - return err; -} - extern int copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *); extern void flush_thread(void); extern void exit_thread(void); diff --git a/kernel/kmod.c b/kernel/kmod.c index 5f9c3b7df..3f59386e5 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -15,6 +15,7 @@ #define __KERNEL_SYSCALLS__ +#include <linux/config.h> #include <linux/sched.h> #include <linux/unistd.h> #include <linux/smp_lock.h> diff --git a/kernel/ksyms.c b/kernel/ksyms.c index eae4ef1b7..241855d8e 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -141,6 +141,7 @@ EXPORT_SYMBOL(get_empty_super); EXPORT_SYMBOL(getname); EXPORT_SYMBOL(names_cachep); EXPORT_SYMBOL(fput); +EXPORT_SYMBOL(fget); EXPORT_SYMBOL(igrab); EXPORT_SYMBOL(iunique); EXPORT_SYMBOL(iget4); @@ -353,6 +354,11 @@ EXPORT_SYMBOL(del_timer); EXPORT_SYMBOL(request_irq); EXPORT_SYMBOL(free_irq); +/* waitqueue handling */ +EXPORT_SYMBOL(add_wait_queue); +EXPORT_SYMBOL(add_wait_queue_exclusive); +EXPORT_SYMBOL(remove_wait_queue); + /* The notion of irq probe/assignment is foreign to S/390 */ #if !defined(CONFIG_ARCH_S390) @@ -503,9 +509,7 @@ EXPORT_SYMBOL(fs_overflowgid); EXPORT_SYMBOL(fasync_helper); EXPORT_SYMBOL(kill_fasync); -#ifdef CONFIG_BLK_DEV_MD EXPORT_SYMBOL(disk_name); /* for md.c */ -#endif /* binfmt_aout */ EXPORT_SYMBOL(get_write_access); diff --git a/kernel/sched.c b/kernel/sched.c index 1cfa76d3b..68d786e89 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -106,7 +106,7 @@ static union { #define cpu_curr(cpu) aligned_data[(cpu)].schedule_data.curr #define last_schedule(cpu) aligned_data[(cpu)].schedule_data.last_schedule -struct kernel_stat kstat = { 0 }; +struct kernel_stat kstat; #ifdef CONFIG_SMP diff --git a/kernel/timer.c b/kernel/timer.c index 7688a56a4..108ca240f 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -545,64 +545,60 @@ static inline void do_it_virt(struct task_struct * p, unsigned long ticks) unsigned long it_virt = p->it_virt_value; if (it_virt) { - if (it_virt <= ticks) { - it_virt = ticks + p->it_virt_incr; + it_virt -= ticks; + if (!it_virt) { + it_virt = p->it_virt_incr; send_sig(SIGVTALRM, p, 1); } - p->it_virt_value = it_virt - ticks; + p->it_virt_value = it_virt; } } -static inline void do_it_prof(struct task_struct * p, unsigned long ticks) +static inline void do_it_prof(struct task_struct *p) { unsigned long it_prof = p->it_prof_value; if (it_prof) { - if (it_prof <= ticks) { - it_prof = ticks + p->it_prof_incr; + if (--it_prof == 0) { + it_prof = p->it_prof_incr; send_sig(SIGPROF, p, 1); } - p->it_prof_value = it_prof - ticks; + p->it_prof_value = it_prof; } } -void update_one_process(struct task_struct *p, - unsigned long ticks, unsigned long user, unsigned long system, int cpu) +void update_one_process(struct task_struct *p, unsigned long user, + unsigned long system, int cpu) { p->per_cpu_utime[cpu] += user; p->per_cpu_stime[cpu] += system; do_process_times(p, user, system); do_it_virt(p, user); - do_it_prof(p, ticks); + do_it_prof(p); } /* * Called from the timer interrupt handler to charge one tick to the current * process. user_tick is 1 if the tick is user time, 0 for system. */ -static void update_process_times(int user_tick) +void update_process_times(int user_tick) { -/* - * SMP does this on a per-CPU basis elsewhere - */ -#ifndef CONFIG_SMP struct task_struct *p = current; - int system = !user_tick; + int cpu = smp_processor_id(), system = user_tick ^ 1; + update_one_process(p, user_tick, system, cpu); if (p->pid) { if (--p->counter <= 0) { p->counter = 0; p->need_resched = 1; } if (p->nice > 0) - kstat.cpu_nice += user_tick; + kstat.per_cpu_nice[cpu] += user_tick; else - kstat.cpu_user += user_tick; - kstat.cpu_system += system; - } else if (local_bh_count(0) || local_irq_count(0) > 1) - kstat.cpu_system += system; - update_one_process(p, 1, user_tick, system, 0); -#endif + kstat.per_cpu_user[cpu] += user_tick; + kstat.per_cpu_system[cpu] += system; + } else if (local_bh_count(cpu) || local_irq_count(cpu) > 1) + kstat.per_cpu_system[cpu] += system; } /* @@ -683,7 +679,11 @@ void timer_bh(void) void do_timer(struct pt_regs *regs) { (*(unsigned long *)&jiffies)++; +#ifndef CONFIG_SMP + /* SMP process accounting uses the local APIC timer */ + update_process_times(user_mode(regs)); +#endif mark_bh(TIMER_BH); if (tq_timer) mark_bh(TQUEUE_BH); diff --git a/mm/highmem.c b/mm/highmem.c index 7c9dbc695..6c7485327 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -281,7 +281,7 @@ static inline void copy_to_high_bh_irq (struct buffer_head *to, static inline void bounce_end_io (struct buffer_head *bh, int uptodate) { - struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_dev_id); + struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_private); bh_orig->b_end_io(bh_orig, uptodate); __free_page(bh->b_page); @@ -295,7 +295,7 @@ static void bounce_end_io_write (struct buffer_head *bh, int uptodate) static void bounce_end_io_read (struct buffer_head *bh, int uptodate) { - struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_dev_id); + struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_private); if (uptodate) copy_to_high_bh_irq(bh_orig, bh); @@ -354,10 +354,9 @@ repeat_page: copy_from_high_bh(bh, bh_orig); } else bh->b_end_io = bounce_end_io_read; - bh->b_dev_id = (void *)bh_orig; + bh->b_private = (void *)bh_orig; bh->b_rsector = bh_orig->b_rsector; memset(&bh->b_wait, -1, sizeof(bh->b_wait)); - bh->b_kiobuf = NULL; return bh; } @@ -864,6 +864,7 @@ void exit_mmap(struct mm_struct * mm) } mm->map_count--; remove_shared_vm_struct(mpnt); + flush_cache_range(mm, start, end); zap_page_range(mm, start, size); if (mpnt->vm_file) fput(mpnt->vm_file); |