summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/Changes20
-rw-r--r--Documentation/Configure.help122
-rw-r--r--Documentation/DocBook/Makefile34
-rw-r--r--Documentation/i2c/writing-clients2
-rw-r--r--Documentation/kernel-parameters.txt12
-rw-r--r--Makefile14
-rw-r--r--arch/alpha/kernel/entry.S2
-rw-r--r--arch/i386/kernel/apic.c46
-rw-r--r--arch/i386/kernel/pci-i386.c8
-rw-r--r--arch/i386/kernel/smp.c40
-rw-r--r--arch/ia64/Makefile3
-rw-r--r--arch/sh/kernel/setup.c1
-rw-r--r--arch/sh/kernel/sh_bios.c2
-rw-r--r--drivers/block/Config.in2
-rw-r--r--drivers/block/Makefile8
-rw-r--r--drivers/block/ll_rw_blk.c1
-rw-r--r--drivers/block/md.c64
-rw-r--r--drivers/block/raid0.c2
-rw-r--r--drivers/block/raid1.c14
-rw-r--r--drivers/block/raid5.c8
-rw-r--r--drivers/block/xor.c13
-rw-r--r--drivers/char/drm/i810_dma.c17
-rw-r--r--drivers/char/drm/i810_drv.c14
-rw-r--r--drivers/char/drm/mga_drv.c14
-rw-r--r--drivers/char/drm/r128_drv.c14
-rw-r--r--drivers/char/drm/vm.c15
-rw-r--r--drivers/char/misc.c25
-rw-r--r--drivers/i2c/i2c-algo-bit.c6
-rw-r--r--drivers/i2c/i2c-algo-pcf.c6
-rw-r--r--drivers/i2c/i2c-core.c336
-rw-r--r--drivers/i2c/i2c-dev.c3
-rw-r--r--drivers/i2c/i2c-elektor.c2
-rw-r--r--drivers/i2c/i2c-philips-par.c221
-rw-r--r--drivers/isdn/avmb1/b1dma.c7
-rw-r--r--drivers/isdn/avmb1/b1pci.c37
-rw-r--r--drivers/isdn/avmb1/b1pcmcia.c8
-rw-r--r--drivers/isdn/avmb1/c4.c17
-rw-r--r--drivers/isdn/avmb1/capi.c68
-rw-r--r--drivers/isdn/avmb1/kcapi.c147
-rw-r--r--drivers/isdn/avmb1/t1pci.c17
-rw-r--r--drivers/parport/ChangeLog9
-rw-r--r--drivers/parport/share.c2
-rw-r--r--drivers/pcmcia/Config.in2
-rw-r--r--drivers/pcmcia/yenta.c2
-rw-r--r--drivers/pnp/isapnp.c8
-rw-r--r--drivers/scsi/imm.c35
-rw-r--r--drivers/scsi/imm.h9
-rw-r--r--drivers/scsi/ppa.c36
-rw-r--r--drivers/scsi/ppa.h9
-rw-r--r--drivers/sound/sound_core.c11
-rw-r--r--drivers/telephony/phonedev.c10
-rw-r--r--drivers/usb/dabusb.c25
-rw-r--r--drivers/usb/devices.c2
-rw-r--r--drivers/usb/ibmcam.c1
-rw-r--r--drivers/usb/input.c17
-rw-r--r--drivers/usb/serial/usb-serial.h4
-rw-r--r--drivers/usb/serial/usbserial.c9
-rw-r--r--drivers/usb/serial/visor.c121
-rw-r--r--drivers/usb/storage/Makefile6
-rw-r--r--drivers/usb/storage/scm.c461
-rw-r--r--drivers/usb/storage/scm.h5
-rw-r--r--drivers/usb/storage/scsiglue.c8
-rw-r--r--drivers/usb/storage/transport.h6
-rw-r--r--drivers/usb/storage/usb.c40
-rw-r--r--drivers/usb/usb.c15
-rw-r--r--drivers/video/S3triofb.c11
-rw-r--r--drivers/video/aty128fb.c48
-rw-r--r--drivers/video/atyfb.c44
-rw-r--r--drivers/video/cgsixfb.c9
-rw-r--r--drivers/video/clgenfb.c63
-rw-r--r--drivers/video/controlfb.c22
-rw-r--r--drivers/video/creatorfb.c9
-rw-r--r--drivers/video/cyber2000fb.c18
-rw-r--r--drivers/video/cyberfb.c11
-rw-r--r--drivers/video/dn_cfb4.c9
-rw-r--r--drivers/video/dn_cfb8.c9
-rw-r--r--drivers/video/dnfb.c9
-rw-r--r--drivers/video/dummycon.c31
-rw-r--r--drivers/video/fbcon-afb.c9
-rw-r--r--drivers/video/fbcon-cfb16.c11
-rw-r--r--drivers/video/fbcon-cfb2.c9
-rw-r--r--drivers/video/fbcon-cfb24.c11
-rw-r--r--drivers/video/fbcon-cfb32.c11
-rw-r--r--drivers/video/fbcon-cfb4.c9
-rw-r--r--drivers/video/fbcon-cfb8.c11
-rw-r--r--drivers/video/fbcon-hga.c11
-rw-r--r--drivers/video/fbcon-ilbm.c9
-rw-r--r--drivers/video/fbcon-iplan2p2.c11
-rw-r--r--drivers/video/fbcon-iplan2p4.c11
-rw-r--r--drivers/video/fbcon-iplan2p8.c11
-rw-r--r--drivers/video/fbcon-mac.c9
-rw-r--r--drivers/video/fbcon-mfb.c11
-rw-r--r--drivers/video/fbcon-vga-planes.c20
-rw-r--r--drivers/video/fbcon-vga.c9
-rw-r--r--drivers/video/fbcon.c17
-rw-r--r--drivers/video/g364fb.c12
-rw-r--r--drivers/video/imsttfb.c52
-rw-r--r--drivers/video/leofb.c9
-rw-r--r--drivers/video/matrox/matroxfb_accel.c73
-rw-r--r--drivers/video/mdacon.c34
-rw-r--r--drivers/video/newport_con.c34
-rw-r--r--drivers/video/pm2fb.c66
-rw-r--r--drivers/video/promcon.c7
-rw-r--r--drivers/video/retz3fb.c11
-rw-r--r--drivers/video/tdfxfb.c76
-rw-r--r--drivers/video/vgacon.c36
-rw-r--r--drivers/video/virgefb.c22
-rw-r--r--fs/buffer.c9
-rw-r--r--fs/devfs/base.c16
-rw-r--r--fs/devices.c89
-rw-r--r--fs/dquot.c2
-rw-r--r--fs/ext2/inode.c5
-rw-r--r--fs/fcntl.c69
-rw-r--r--fs/nfsd/auth.c7
-rw-r--r--fs/nfsd/nfsctl.c4
-rw-r--r--fs/nfsd/vfs.c33
-rw-r--r--fs/partitions/check.c1
-rw-r--r--fs/proc/proc_misc.c23
-rw-r--r--fs/select.c2
-rw-r--r--fs/super.c27
-rw-r--r--fs/vfat/namei.c7
-rw-r--r--include/asm-i386/mmu_context.h13
-rw-r--r--include/asm-i386/pgalloc.h1
-rw-r--r--include/asm-sh/checksum.h2
-rw-r--r--include/asm-sh/serial.h2
-rw-r--r--include/linux/fs.h6
-rw-r--r--include/linux/i2c-id.h3
-rw-r--r--include/linux/i2c.h65
-rw-r--r--include/linux/kernel_stat.h1
-rw-r--r--include/linux/mount.h3
-rw-r--r--include/linux/parport.h7
-rw-r--r--include/linux/raid/md.h1
-rw-r--r--include/linux/sched.h36
-rw-r--r--kernel/kmod.c1
-rw-r--r--kernel/ksyms.c8
-rw-r--r--kernel/sched.c2
-rw-r--r--kernel/timer.c46
-rw-r--r--mm/highmem.c7
-rw-r--r--mm/mmap.c1
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=
diff --git a/Makefile b/Makefile
index 9a760d5f4..8473151cb 100644
--- a/Makefile
+++ b/Makefile
@@ -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(&current->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;
}
diff --git a/mm/mmap.c b/mm/mmap.c
index ea8eba783..d3e596d25 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -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);